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

Annotation of sys/dev/isa/it.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: it.c,v 1.23 2007/06/24 05:34:35 dlg Exp $     */
                      2:
                      3: /*
                      4:  * Copyright (c) 2003 Julien Bordet <zejames@greyhats.org>
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     18:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     19:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     20:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     21:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     22:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     23:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     24:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     25:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     26:  */
                     27:
                     28: #include <sys/param.h>
                     29: #include <sys/systm.h>
                     30: #include <sys/device.h>
                     31: #include <sys/kernel.h>
                     32: #include <sys/sensors.h>
                     33: #include <machine/bus.h>
                     34:
                     35: #include <dev/isa/isareg.h>
                     36: #include <dev/isa/isavar.h>
                     37:
                     38: #include <dev/isa/itvar.h>
                     39:
                     40: #if defined(ITDEBUG)
                     41: #define DPRINTF(x)             do { printf x; } while (0)
                     42: #else
                     43: #define DPRINTF(x)
                     44: #endif
                     45:
                     46: /*
                     47:  * IT87-compatible chips can typically measure voltages up to 4.096 V.
                     48:  * To measure higher voltages the input is attenuated with (external)
                     49:  * resistors.  Negative voltages are measured using a reference
                     50:  * voltage.  So we have to convert the sensor values back to real
                     51:  * voltages by applying the appropriate resistor factor.
                     52:  */
                     53: #define RFACT_NONE     10000
                     54: #define RFACT(x, y)    (RFACT_NONE * ((x) + (y)) / (y))
                     55:
                     56: int  it_match(struct device *, void *, void *);
                     57: void it_attach(struct device *, struct device *, void *);
                     58: u_int8_t it_readreg(struct it_softc *, int);
                     59: void it_writereg(struct it_softc *, int, int);
                     60: void it_setup_volt(struct it_softc *, int, int);
                     61: void it_setup_temp(struct it_softc *, int, int);
                     62: void it_setup_fan(struct it_softc *, int, int);
                     63:
                     64: void it_generic_stemp(struct it_softc *, struct ksensor *);
                     65: void it_generic_svolt(struct it_softc *, struct ksensor *);
                     66: void it_generic_fanrpm(struct it_softc *, struct ksensor *);
                     67:
                     68: void it_refresh_sensor_data(struct it_softc *);
                     69: void it_refresh(void *);
                     70:
                     71: struct cfattach it_ca = {
                     72:        sizeof(struct it_softc),
                     73:        it_match,
                     74:        it_attach
                     75: };
                     76:
                     77: struct cfdriver it_cd = {
                     78:        NULL, "it", DV_DULL
                     79: };
                     80:
                     81: const int it_vrfact[] = {
                     82:        RFACT_NONE,
                     83:        RFACT_NONE,
                     84:        RFACT_NONE,
                     85:        RFACT(68, 100),
                     86:        RFACT(30, 10),
                     87:        RFACT(21, 10),
                     88:        RFACT(83, 20),
                     89:        RFACT(68, 100),
                     90:        RFACT_NONE
                     91: };
                     92:
                     93: int
                     94: it_match(struct device *parent, void *match, void *aux)
                     95: {
                     96:        bus_space_tag_t iot;
                     97:        bus_space_handle_t ioh;
                     98:        struct isa_attach_args *ia = aux;
                     99:        int iobase;
                    100:        u_int8_t cr;
                    101:
                    102:        iot = ia->ia_iot;
                    103:        iobase = ia->ipa_io[0].base;
                    104:
                    105:        if (bus_space_map(iot, iobase, 8, 0, &ioh)) {
                    106:                DPRINTF(("it: can't map i/o space\n"));
                    107:                return (0);
                    108:        }
                    109:
                    110:        /* Check Vendor ID */
                    111:        bus_space_write_1(iot, ioh, ITC_ADDR, ITD_CHIPID);
                    112:        cr = bus_space_read_1(iot, ioh, ITC_DATA);
                    113:        bus_space_unmap(iot, ioh, 8);
                    114:        DPRINTF(("it: vendor id 0x%x\n", cr));
                    115:        if (cr != IT_ID_IT87)
                    116:                return (0);
                    117:
                    118:        ia->ipa_nio = 1;
                    119:        ia->ipa_io[0].length = 8;
                    120:        ia->ipa_nmem = 0;
                    121:        ia->ipa_nirq = 0;
                    122:        ia->ipa_ndrq = 0;
                    123:
                    124:        return (1);
                    125: }
                    126:
                    127: void
                    128: it_attach(struct device *parent, struct device *self, void *aux)
                    129: {
                    130:        struct it_softc *sc = (void *)self;
                    131:        int iobase;
                    132:        bus_space_tag_t iot;
                    133:        struct isa_attach_args *ia = aux;
                    134:        int i;
                    135:        u_int8_t cr;
                    136:
                    137:        iobase = ia->ipa_io[0].base;
                    138:        iot = sc->it_iot = ia->ia_iot;
                    139:
                    140:        if (bus_space_map(iot, iobase, 8, 0, &sc->it_ioh)) {
                    141:                printf(": can't map i/o space\n");
                    142:                return;
                    143:        }
                    144:
                    145:        i = it_readreg(sc, ITD_CHIPID);
                    146:        switch (i) {
                    147:                case IT_ID_IT87:
                    148:                        printf(": IT87\n");
                    149:                        break;
                    150:        }
                    151:
                    152:        sc->numsensors = IT_NUM_SENSORS;
                    153:
                    154:        it_setup_fan(sc, 0, 3);
                    155:        it_setup_volt(sc, 3, 9);
                    156:        it_setup_temp(sc, 12, 3);
                    157:
                    158:        if (sensor_task_register(sc, it_refresh, 5) == NULL) {
                    159:                printf("%s: unable to register update task\n",
                    160:                    sc->sc_dev.dv_xname);
                    161:                return;
                    162:        }
                    163:
                    164:        /* Activate monitoring */
                    165:        cr = it_readreg(sc, ITD_CONFIG);
                    166:        cr |= 0x01 | 0x08;
                    167:        it_writereg(sc, ITD_CONFIG, cr);
                    168:
                    169:        /* Initialize sensors */
                    170:        strlcpy(sc->sensordev.xname, sc->sc_dev.dv_xname,
                    171:            sizeof(sc->sensordev.xname));
                    172:        for (i = 0; i < sc->numsensors; ++i)
                    173:                sensor_attach(&sc->sensordev, &sc->sensors[i]);
                    174:        sensordev_install(&sc->sensordev);
                    175: }
                    176:
                    177: u_int8_t
                    178: it_readreg(struct it_softc *sc, int reg)
                    179: {
                    180:        bus_space_write_1(sc->it_iot, sc->it_ioh, ITC_ADDR, reg);
                    181:        return (bus_space_read_1(sc->it_iot, sc->it_ioh, ITC_DATA));
                    182: }
                    183:
                    184: void
                    185: it_writereg(struct it_softc *sc, int reg, int val)
                    186: {
                    187:        bus_space_write_1(sc->it_iot, sc->it_ioh, ITC_ADDR, reg);
                    188:        bus_space_write_1(sc->it_iot, sc->it_ioh, ITC_DATA, val);
                    189: }
                    190:
                    191: void
                    192: it_setup_volt(struct it_softc *sc, int start, int n)
                    193: {
                    194:        int i;
                    195:
                    196:        for (i = 0; i < n; ++i) {
                    197:                sc->sensors[start + i].type = SENSOR_VOLTS_DC;
                    198:        }
                    199:
                    200:        snprintf(sc->sensors[start + 0].desc, sizeof(sc->sensors[0].desc),
                    201:            "VCORE_A");
                    202:        snprintf(sc->sensors[start + 1].desc, sizeof(sc->sensors[1].desc),
                    203:            "VCORE_B");
                    204:        snprintf(sc->sensors[start + 2].desc, sizeof(sc->sensors[2].desc),
                    205:            "+3.3V");
                    206:        snprintf(sc->sensors[start + 3].desc, sizeof(sc->sensors[3].desc),
                    207:            "+5V");
                    208:        snprintf(sc->sensors[start + 4].desc, sizeof(sc->sensors[4].desc),
                    209:            "+12V");
                    210:        snprintf(sc->sensors[start + 5].desc, sizeof(sc->sensors[5].desc),
                    211:            "Unused");
                    212:        snprintf(sc->sensors[start + 6].desc, sizeof(sc->sensors[6].desc),
                    213:            "-12V");
                    214:        snprintf(sc->sensors[start + 7].desc, sizeof(sc->sensors[7].desc),
                    215:            "+5VSB");
                    216:        snprintf(sc->sensors[start + 8].desc, sizeof(sc->sensors[8].desc),
                    217:            "VBAT");
                    218: }
                    219:
                    220: void
                    221: it_setup_temp(struct it_softc *sc, int start, int n)
                    222: {
                    223:        int i;
                    224:
                    225:        for (i = 0; i < n; ++i)
                    226:                sc->sensors[start + i].type = SENSOR_TEMP;
                    227: }
                    228:
                    229: void
                    230: it_setup_fan(struct it_softc *sc, int start, int n)
                    231: {
                    232:        int i;
                    233:
                    234:        for (i = 0; i < n; ++i)
                    235:                sc->sensors[start + i].type = SENSOR_FANRPM;
                    236: }
                    237:
                    238: void
                    239: it_generic_stemp(struct it_softc *sc, struct ksensor *sensors)
                    240: {
                    241:        int i, sdata;
                    242:
                    243:        for (i = 0; i < 3; i++) {
                    244:                sdata = it_readreg(sc, ITD_SENSORTEMPBASE + i);
                    245:                /* Convert temperature to Fahrenheit degres */
                    246:                sensors[i].value = sdata * 1000000 + 273150000;
                    247:        }
                    248: }
                    249:
                    250: void
                    251: it_generic_svolt(struct it_softc *sc, struct ksensor *sensors)
                    252: {
                    253:        int i, sdata;
                    254:
                    255:        for (i = 0; i < 9; i++) {
                    256:                sdata = it_readreg(sc, ITD_SENSORVOLTBASE + i);
                    257:                DPRINTF(("sdata[volt%d] 0x%x\n", i, sdata));
                    258:                /* voltage returned as (mV >> 4) */
                    259:                sensors[i].value = (sdata << 4);
                    260:                /* these two values are negative and formula is different */
                    261:                if (i == 5 || i == 6)
                    262:                        sensors[i].value = ((sdata << 4) - IT_VREF);
                    263:                /* rfact is (factor * 10^4) */
                    264:                sensors[i].value *= it_vrfact[i];
                    265:                /* division by 10 gets us back to uVDC */
                    266:                sensors[i].value /= 10;
                    267:                if (i == 5 || i == 6)
                    268:                        sensors[i].value += IT_VREF * 1000;
                    269:        }
                    270: }
                    271:
                    272: void
                    273: it_generic_fanrpm(struct it_softc *sc, struct ksensor *sensors)
                    274: {
                    275:        int i, sdata, divisor, odivisor, ndivisor;
                    276:
                    277:        odivisor = ndivisor = divisor = it_readreg(sc, ITD_FAN);
                    278:        for (i = 0; i < 3; i++, divisor >>= 3) {
                    279:                sensors[i].flags &= ~SENSOR_FINVALID;
                    280:                if ((sdata = it_readreg(sc, ITD_SENSORFANBASE + i)) == 0xff) {
                    281:                        sensors[i].flags |= SENSOR_FINVALID;
                    282:                        if (i == 2)
                    283:                                ndivisor ^= 0x40;
                    284:                        else {
                    285:                                ndivisor &= ~(7 << (i * 3));
                    286:                                ndivisor |= ((divisor + 1) & 7) << (i * 3);
                    287:                        }
                    288:                } else if (sdata == 0) {
                    289:                        sensors[i].value = 0;
                    290:                } else {
                    291:                        if (i == 2)
                    292:                                divisor = divisor & 1 ? 3 : 1;
                    293:                        sensors[i].value = 1350000 / (sdata << (divisor & 7));
                    294:                }
                    295:        }
                    296:        if (ndivisor != odivisor)
                    297:                it_writereg(sc, ITD_FAN, ndivisor);
                    298: }
                    299:
                    300: /*
                    301:  * pre:  last read occurred >= 1.5 seconds ago
                    302:  * post: sensors[] current data are the latest from the chip
                    303:  */
                    304: void
                    305: it_refresh_sensor_data(struct it_softc *sc)
                    306: {
                    307:        /* Refresh our stored data for every sensor */
                    308:        it_generic_stemp(sc, &sc->sensors[12]);
                    309:        it_generic_svolt(sc, &sc->sensors[3]);
                    310:        it_generic_fanrpm(sc, &sc->sensors[0]);
                    311: }
                    312:
                    313: void
                    314: it_refresh(void *arg)
                    315: {
                    316:        struct it_softc *sc = (struct it_softc *)arg;
                    317:
                    318:        it_refresh_sensor_data(sc);
                    319: }

CVSweb