[BACK]Return to owtemp.c CVS log [TXT][DIR] Up to [local] / sys / dev / onewire

Annotation of sys/dev/onewire/owtemp.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: owtemp.c,v 1.8 2007/06/24 05:34:35 dlg Exp $  */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2006 Alexander Yurchenko <grange@openbsd.org>
        !             5:  *
        !             6:  * Permission to use, copy, modify, and distribute this software for any
        !             7:  * purpose with or without fee is hereby granted, provided that the above
        !             8:  * copyright notice and this permission notice appear in all copies.
        !             9:  *
        !            10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            17:  */
        !            18:
        !            19: /*
        !            20:  * 1-Wire temperature family type device driver.
        !            21:  */
        !            22:
        !            23: #include <sys/param.h>
        !            24: #include <sys/systm.h>
        !            25: #include <sys/device.h>
        !            26: #include <sys/kernel.h>
        !            27: #include <sys/proc.h>
        !            28: #include <sys/rwlock.h>
        !            29: #include <sys/sensors.h>
        !            30:
        !            31: #include <dev/onewire/onewiredevs.h>
        !            32: #include <dev/onewire/onewirereg.h>
        !            33: #include <dev/onewire/onewirevar.h>
        !            34:
        !            35: /* Commands */
        !            36: #define DS1920_CMD_CONVERT             0x44
        !            37: #define DS1920_CMD_READ_SCRATCHPAD     0xbe
        !            38:
        !            39: /* Scratchpad layout */
        !            40: #define DS1920_SP_TEMP_LSB             0
        !            41: #define DS1920_SP_TEMP_MSB             1
        !            42: #define DS1920_SP_TH                   2
        !            43: #define DS1920_SP_TL                   3
        !            44: #define DS1920_SP_COUNT_REMAIN         6
        !            45: #define DS1920_SP_COUNT_PERC           7
        !            46: #define DS1920_SP_CRC                  8
        !            47:
        !            48: struct owtemp_softc {
        !            49:        struct device           sc_dev;
        !            50:
        !            51:        void *                  sc_onewire;
        !            52:        u_int64_t               sc_rom;
        !            53:
        !            54:        struct ksensor          sc_sensor;
        !            55:        struct ksensordev       sc_sensordev;
        !            56:        struct sensor_task      *sc_sensortask;
        !            57:        struct rwlock           sc_lock;
        !            58: };
        !            59:
        !            60: int    owtemp_match(struct device *, void *, void *);
        !            61: void   owtemp_attach(struct device *, struct device *, void *);
        !            62: int    owtemp_detach(struct device *, int);
        !            63: int    owtemp_activate(struct device *, enum devact);
        !            64:
        !            65: void   owtemp_update(void *);
        !            66:
        !            67: struct cfattach owtemp_ca = {
        !            68:        sizeof(struct owtemp_softc),
        !            69:        owtemp_match,
        !            70:        owtemp_attach,
        !            71:        owtemp_detach,
        !            72:        owtemp_activate
        !            73: };
        !            74:
        !            75: struct cfdriver owtemp_cd = {
        !            76:        NULL, "owtemp", DV_DULL
        !            77: };
        !            78:
        !            79: static const struct onewire_matchfam owtemp_fams[] = {
        !            80:        { ONEWIRE_FAMILY_DS1920 }
        !            81: };
        !            82:
        !            83: int
        !            84: owtemp_match(struct device *parent, void *match, void *aux)
        !            85: {
        !            86:        return (onewire_matchbyfam(aux, owtemp_fams,
        !            87:            sizeof(owtemp_fams) /sizeof(owtemp_fams[0])));
        !            88: }
        !            89:
        !            90: void
        !            91: owtemp_attach(struct device *parent, struct device *self, void *aux)
        !            92: {
        !            93:        struct owtemp_softc *sc = (struct owtemp_softc *)self;
        !            94:        struct onewire_attach_args *oa = aux;
        !            95:
        !            96:        sc->sc_onewire = oa->oa_onewire;
        !            97:        sc->sc_rom = oa->oa_rom;
        !            98:
        !            99:        /* Initialize sensor */
        !           100:        strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
        !           101:            sizeof(sc->sc_sensordev.xname));
        !           102:        sc->sc_sensor.type = SENSOR_TEMP;
        !           103:
        !           104:        sc->sc_sensortask = sensor_task_register(sc, owtemp_update, 5);
        !           105:        if (sc->sc_sensortask == NULL) {
        !           106:                printf(": unable to register update task\n");
        !           107:                return;
        !           108:        }
        !           109:        sensor_attach(&sc->sc_sensordev, &sc->sc_sensor);
        !           110:        sensordev_install(&sc->sc_sensordev);
        !           111:
        !           112:        rw_init(&sc->sc_lock, sc->sc_dev.dv_xname);
        !           113:        printf("\n");
        !           114: }
        !           115:
        !           116: int
        !           117: owtemp_detach(struct device *self, int flags)
        !           118: {
        !           119:        struct owtemp_softc *sc = (struct owtemp_softc *)self;
        !           120:
        !           121:        rw_enter_write(&sc->sc_lock);
        !           122:        sensordev_deinstall(&sc->sc_sensordev);
        !           123:        if (sc->sc_sensortask != NULL)
        !           124:                sensor_task_unregister(sc->sc_sensortask);
        !           125:        rw_exit_write(&sc->sc_lock);
        !           126:
        !           127:        return (0);
        !           128: }
        !           129:
        !           130: int
        !           131: owtemp_activate(struct device *self, enum devact act)
        !           132: {
        !           133:        return (0);
        !           134: }
        !           135:
        !           136: void
        !           137: owtemp_update(void *arg)
        !           138: {
        !           139:        struct owtemp_softc *sc = arg;
        !           140:        u_int8_t data[9];
        !           141:        u_int16_t temp;
        !           142:        int count_perc, count_remain, val;
        !           143:
        !           144:        rw_enter_write(&sc->sc_lock);
        !           145:        onewire_lock(sc->sc_onewire, 0);
        !           146:        if (onewire_reset(sc->sc_onewire) != 0)
        !           147:                goto done;
        !           148:        onewire_matchrom(sc->sc_onewire, sc->sc_rom);
        !           149:
        !           150:        /*
        !           151:         * Start temperature conversion. The conversion takes up to 750ms.
        !           152:         * After sending the command, the data line must be held high for
        !           153:         * at least 750ms to provide power during the conversion process.
        !           154:         * As such, no other activity may take place on the 1-Wire bus for
        !           155:         * at least this period.
        !           156:         */
        !           157:        onewire_write_byte(sc->sc_onewire, DS1920_CMD_CONVERT);
        !           158:        tsleep(sc, PRIBIO, "owtemp", hz);
        !           159:
        !           160:        if (onewire_reset(sc->sc_onewire) != 0)
        !           161:                goto done;
        !           162:        onewire_matchrom(sc->sc_onewire, sc->sc_rom);
        !           163:
        !           164:        /*
        !           165:         * The result of the temperature measurement is placed in the
        !           166:         * first two bytes of the scratchpad.
        !           167:         */
        !           168:        onewire_write_byte(sc->sc_onewire, DS1920_CMD_READ_SCRATCHPAD);
        !           169:        onewire_read_block(sc->sc_onewire, data, 9);
        !           170:        if (onewire_crc(data, 8) == data[DS1920_SP_CRC]) {
        !           171:                temp = data[DS1920_SP_TEMP_MSB] << 8 |
        !           172:                    data[DS1920_SP_TEMP_LSB];
        !           173:                count_perc = data[DS1920_SP_COUNT_PERC];
        !           174:                count_remain = data[DS1920_SP_COUNT_REMAIN];
        !           175:
        !           176:                if (count_perc != 0) {
        !           177:                        /* High resolution algorithm */
        !           178:                        temp &= ~0x0001;
        !           179:                        val = temp * 500000 - 250000 +
        !           180:                            ((count_perc - count_remain) * 1000000) /
        !           181:                            count_perc;
        !           182:                } else {
        !           183:                        val = temp * 500000;
        !           184:                }
        !           185:                sc->sc_sensor.value = 273150000 + val;
        !           186:        }
        !           187:
        !           188: done:
        !           189:        onewire_unlock(sc->sc_onewire);
        !           190:        rw_exit_write(&sc->sc_lock);
        !           191: }

CVSweb