[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     ! 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