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

Annotation of sys/dev/ic/lm78.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: lm78.c,v 1.20 2007/06/25 22:50:18 cnst Exp $  */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2005, 2006 Mark Kettenis
        !             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: #include <sys/param.h>
        !            20: #include <sys/systm.h>
        !            21: #include <sys/device.h>
        !            22: #include <sys/kernel.h>
        !            23: #include <sys/queue.h>
        !            24: #include <sys/sensors.h>
        !            25: #include <machine/bus.h>
        !            26:
        !            27: #include <dev/ic/lm78var.h>
        !            28:
        !            29: #if defined(LMDEBUG)
        !            30: #define DPRINTF(x)             do { printf x; } while (0)
        !            31: #else
        !            32: #define DPRINTF(x)
        !            33: #endif
        !            34:
        !            35: /*
        !            36:  * LM78-compatible chips can typically measure voltages up to 4.096 V.
        !            37:  * To measure higher voltages the input is attenuated with (external)
        !            38:  * resistors.  Negative voltages are measured using inverting op amps
        !            39:  * and resistors.  So we have to convert the sensor values back to
        !            40:  * real voltages by applying the appropriate resistor factor.
        !            41:  */
        !            42: #define RFACT_NONE     10000
        !            43: #define RFACT(x, y)    (RFACT_NONE * ((x) + (y)) / (y))
        !            44: #define NRFACT(x, y)   (-RFACT_NONE * (x) / (y))
        !            45:
        !            46: struct cfdriver lm_cd = {
        !            47:        NULL, "lm", DV_DULL
        !            48: };
        !            49:
        !            50: int  lm_match(struct lm_softc *);
        !            51: int  wb_match(struct lm_softc *);
        !            52: int  def_match(struct lm_softc *);
        !            53:
        !            54: void lm_setup_sensors(struct lm_softc *, struct lm_sensor *);
        !            55: void lm_refresh(void *);
        !            56:
        !            57: void lm_refresh_sensor_data(struct lm_softc *);
        !            58: void lm_refresh_volt(struct lm_softc *, int);
        !            59: void lm_refresh_temp(struct lm_softc *, int);
        !            60: void lm_refresh_fanrpm(struct lm_softc *, int);
        !            61:
        !            62: void wb_refresh_sensor_data(struct lm_softc *);
        !            63: void wb_w83637hf_refresh_vcore(struct lm_softc *, int);
        !            64: void wb_refresh_nvolt(struct lm_softc *, int);
        !            65: void wb_w83627ehf_refresh_nvolt(struct lm_softc *, int);
        !            66: void wb_refresh_temp(struct lm_softc *, int);
        !            67: void wb_refresh_fanrpm(struct lm_softc *, int);
        !            68: void wb_w83792d_refresh_fanrpm(struct lm_softc *, int);
        !            69:
        !            70: void as_refresh_temp(struct lm_softc *, int);
        !            71:
        !            72: struct lm_chip {
        !            73:        int (*chip_match)(struct lm_softc *);
        !            74: };
        !            75:
        !            76: struct lm_chip lm_chips[] = {
        !            77:        { wb_match },
        !            78:        { lm_match },
        !            79:        { def_match } /* Must be last */
        !            80: };
        !            81:
        !            82: struct lm_sensor lm78_sensors[] = {
        !            83:        /* Voltage */
        !            84:        { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
        !            85:        { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
        !            86:        { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
        !            87:        { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(68, 100) },
        !            88:        { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(30, 10) },
        !            89:        { "-12V", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, NRFACT(240, 60) },
        !            90:        { "-5V", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, NRFACT(100, 60) },
        !            91:
        !            92:        /* Temperature */
        !            93:        { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
        !            94:
        !            95:        /* Fans */
        !            96:        { "", SENSOR_FANRPM, 0, 0x28, lm_refresh_fanrpm },
        !            97:        { "", SENSOR_FANRPM, 0, 0x29, lm_refresh_fanrpm },
        !            98:        { "", SENSOR_FANRPM, 0, 0x2a, lm_refresh_fanrpm },
        !            99:
        !           100:        { NULL }
        !           101: };
        !           102:
        !           103: struct lm_sensor w83627hf_sensors[] = {
        !           104:        /* Voltage */
        !           105:        { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
        !           106:        { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
        !           107:        { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
        !           108:        { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
        !           109:        { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
        !           110:        { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
        !           111:        { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
        !           112:        { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(17, 33) },
        !           113:        { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
        !           114:
        !           115:        /* Temperature */
        !           116:        { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
        !           117:        { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
        !           118:        { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
        !           119:
        !           120:        /* Fans */
        !           121:        { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
        !           122:        { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
        !           123:        { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
        !           124:
        !           125:        { NULL }
        !           126: };
        !           127:
        !           128: /*
        !           129:  * The W83627EHF can measure voltages up to 2.048 V instead of the
        !           130:  * traditional 4.096 V.  For measuring positive voltages, this can be
        !           131:  * accounted for by halving the resistor factor.  Negative voltages
        !           132:  * need special treatment, also because the reference voltage is 2.048 V
        !           133:  * instead of the traditional 3.6 V.
        !           134:  */
        !           135: struct lm_sensor w83627ehf_sensors[] = {
        !           136:        /* Voltage */
        !           137:        { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE / 2},
        !           138:        { "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(56, 10) / 2 },
        !           139:        { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT(34, 34) / 2 },
        !           140:        { "+3.3V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 34) / 2 },
        !           141:        { "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_w83627ehf_refresh_nvolt },
        !           142:        { "", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, RFACT_NONE / 2 },
        !           143:        { "", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, RFACT_NONE / 2 },
        !           144:        { "3.3VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 34) / 2 },
        !           145:        { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE / 2 },
        !           146:        { "", SENSOR_VOLTS_DC, 5, 0x52, lm_refresh_volt, RFACT_NONE / 2 },
        !           147:
        !           148:        /* Temperature */
        !           149:        { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
        !           150:        { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
        !           151:        { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
        !           152:
        !           153:        /* Fans */
        !           154:        { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
        !           155:        { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
        !           156:        { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
        !           157:
        !           158:        { NULL }
        !           159: };
        !           160:
        !           161: /*
        !           162:  * w83627dhg is almost identical to w83627ehf, except that
        !           163:  * it has 9 instead of 10 voltage sensors
        !           164:  */
        !           165: struct lm_sensor w83627dhg_sensors[] = {
        !           166:        /* Voltage */
        !           167:        { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE / 2},
        !           168:        { "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(56, 10) / 2 },
        !           169:        { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT(34, 34) / 2 },
        !           170:        { "+3.3V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 34) / 2 },
        !           171:        { "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_w83627ehf_refresh_nvolt },
        !           172:        { "", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, RFACT_NONE / 2 },
        !           173:        { "", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, RFACT_NONE / 2 },
        !           174:        { "3.3VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 34) / 2 },
        !           175:        { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE / 2 },
        !           176:
        !           177:        /* Temperature */
        !           178:        { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
        !           179:        { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
        !           180:        { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
        !           181:
        !           182:        /* Fans */
        !           183:        { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
        !           184:        { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
        !           185:        { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
        !           186:
        !           187:        { NULL }
        !           188: };
        !           189:
        !           190: struct lm_sensor w83637hf_sensors[] = {
        !           191:        /* Voltage */
        !           192:        { "VCore", SENSOR_VOLTS_DC, 0, 0x20, wb_w83637hf_refresh_vcore },
        !           193:        { "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(28, 10) },
        !           194:        { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
        !           195:        { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 51) },
        !           196:        { "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_refresh_nvolt, RFACT(232, 56) },
        !           197:        { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 51) },
        !           198:        { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
        !           199:
        !           200:        /* Temperature */
        !           201:        { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
        !           202:        { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
        !           203:        { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
        !           204:
        !           205:        /* Fans */
        !           206:        { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
        !           207:        { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
        !           208:        { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
        !           209:
        !           210:        { NULL }
        !           211: };
        !           212:
        !           213: struct lm_sensor w83697hf_sensors[] = {
        !           214:        /* Voltage */
        !           215:        { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
        !           216:        { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
        !           217:        { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
        !           218:        { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
        !           219:        { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
        !           220:        { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
        !           221:        { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(17, 33) },
        !           222:        { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
        !           223:
        !           224:        /* Temperature */
        !           225:        { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
        !           226:        { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
        !           227:
        !           228:        /* Fans */
        !           229:        { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
        !           230:        { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
        !           231:
        !           232:        { NULL }
        !           233: };
        !           234:
        !           235: /*
        !           236:  * The datasheet doesn't mention the (internal) resistors used for the
        !           237:  * +5V, but using the values from the W83782D datasheets seems to
        !           238:  * provide sensible results.
        !           239:  */
        !           240: struct lm_sensor w83781d_sensors[] = {
        !           241:        /* Voltage */
        !           242:        { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
        !           243:        { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
        !           244:        { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
        !           245:        { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
        !           246:        { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
        !           247:        { "-12V", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, NRFACT(2100, 604) },
        !           248:        { "-5V", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, NRFACT(909, 604) },
        !           249:
        !           250:        /* Temperature */
        !           251:        { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
        !           252:        { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
        !           253:        { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
        !           254:
        !           255:        /* Fans */
        !           256:        { "", SENSOR_FANRPM, 0, 0x28, lm_refresh_fanrpm },
        !           257:        { "", SENSOR_FANRPM, 0, 0x29, lm_refresh_fanrpm },
        !           258:        { "", SENSOR_FANRPM, 0, 0x2a, lm_refresh_fanrpm },
        !           259:
        !           260:        { NULL }
        !           261: };
        !           262:
        !           263: struct lm_sensor w83782d_sensors[] = {
        !           264:        /* Voltage */
        !           265:        { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
        !           266:        { "VINR0", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
        !           267:        { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
        !           268:        { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
        !           269:        { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
        !           270:        { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
        !           271:        { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
        !           272:        { "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(17, 33) },
        !           273:        { "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
        !           274:
        !           275:        /* Temperature */
        !           276:        { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
        !           277:        { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
        !           278:        { "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
        !           279:
        !           280:        /* Fans */
        !           281:        { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
        !           282:        { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
        !           283:        { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
        !           284:
        !           285:        { NULL }
        !           286: };
        !           287:
        !           288: struct lm_sensor w83783s_sensors[] = {
        !           289:        /* Voltage */
        !           290:        { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
        !           291:        { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
        !           292:        { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
        !           293:        { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
        !           294:        { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
        !           295:        { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
        !           296:
        !           297:        /* Temperature */
        !           298:        { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
        !           299:        { "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
        !           300:
        !           301:        /* Fans */
        !           302:        { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
        !           303:        { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
        !           304:        { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
        !           305:
        !           306:        { NULL }
        !           307: };
        !           308:
        !           309: struct lm_sensor w83791d_sensors[] = {
        !           310:        /* Voltage */
        !           311:        { "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, 10000 },
        !           312:        { "VINR0", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, 10000 },
        !           313:        { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, 10000 },
        !           314:        { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
        !           315:        { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
        !           316:        { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
        !           317:        { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
        !           318:        { "5VSB", SENSOR_VOLTS_DC, 0, 0xb0, lm_refresh_volt, RFACT(17, 33) },
        !           319:        { "VBAT", SENSOR_VOLTS_DC, 0, 0xb1, lm_refresh_volt, RFACT_NONE },
        !           320:        { "VINR1", SENSOR_VOLTS_DC, 0, 0xb2, lm_refresh_volt, RFACT_NONE },
        !           321:
        !           322:        /* Temperature */
        !           323:        { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
        !           324:        { "", SENSOR_TEMP, 0, 0xc0, wb_refresh_temp },
        !           325:        { "", SENSOR_TEMP, 0, 0xc8, wb_refresh_temp },
        !           326:
        !           327:        /* Fans */
        !           328:        { "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
        !           329:        { "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
        !           330:        { "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
        !           331:        { "", SENSOR_FANRPM, 0, 0xba, wb_refresh_fanrpm },
        !           332:        { "", SENSOR_FANRPM, 0, 0xbb, wb_refresh_fanrpm },
        !           333:
        !           334:        { NULL }
        !           335: };
        !           336:
        !           337: struct lm_sensor w83792d_sensors[] = {
        !           338:        /* Voltage */
        !           339:        { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
        !           340:        { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
        !           341:        { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
        !           342:        { "-5V", SENSOR_VOLTS_DC, 0, 0x23, wb_refresh_nvolt, RFACT(120, 56) },
        !           343:        { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
        !           344:        { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
        !           345:        { "+5V", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, RFACT(34, 50) },
        !           346:        { "5VSB", SENSOR_VOLTS_DC, 0, 0xb0, lm_refresh_volt, RFACT(17, 33) },
        !           347:        { "VBAT", SENSOR_VOLTS_DC, 0, 0xb1, lm_refresh_volt, RFACT_NONE },
        !           348:
        !           349:        /* Temperature */
        !           350:        { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
        !           351:        { "", SENSOR_TEMP, 0, 0xc0, wb_refresh_temp },
        !           352:        { "", SENSOR_TEMP, 0, 0xc8, wb_refresh_temp },
        !           353:
        !           354:        /* Fans */
        !           355:        { "", SENSOR_FANRPM, 0, 0x28, wb_w83792d_refresh_fanrpm },
        !           356:        { "", SENSOR_FANRPM, 0, 0x29, wb_w83792d_refresh_fanrpm },
        !           357:        { "", SENSOR_FANRPM, 0, 0x2a, wb_w83792d_refresh_fanrpm },
        !           358:        { "", SENSOR_FANRPM, 0, 0xb8, wb_w83792d_refresh_fanrpm },
        !           359:        { "", SENSOR_FANRPM, 0, 0xb9, wb_w83792d_refresh_fanrpm },
        !           360:        { "", SENSOR_FANRPM, 0, 0xba, wb_w83792d_refresh_fanrpm },
        !           361:        { "", SENSOR_FANRPM, 0, 0xbe, wb_w83792d_refresh_fanrpm },
        !           362:
        !           363:        { NULL }
        !           364: };
        !           365:
        !           366: struct lm_sensor as99127f_sensors[] = {
        !           367:        /* Voltage */
        !           368:        { "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
        !           369:        { "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
        !           370:        { "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
        !           371:        { "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
        !           372:        { "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
        !           373:        { "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
        !           374:        { "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
        !           375:
        !           376:        /* Temperature */
        !           377:        { "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
        !           378:        { "", SENSOR_TEMP, 1, 0x50, as_refresh_temp },
        !           379:        { "", SENSOR_TEMP, 2, 0x50, as_refresh_temp },
        !           380:
        !           381:        /* Fans */
        !           382:        { "", SENSOR_FANRPM, 0, 0x28, lm_refresh_fanrpm },
        !           383:        { "", SENSOR_FANRPM, 0, 0x29, lm_refresh_fanrpm },
        !           384:        { "", SENSOR_FANRPM, 0, 0x2a, lm_refresh_fanrpm },
        !           385:
        !           386:        { NULL }
        !           387: };
        !           388:
        !           389: void
        !           390: lm_attach(struct lm_softc *sc)
        !           391: {
        !           392:        u_int i, config;
        !           393:
        !           394:        for (i = 0; i < sizeof(lm_chips) / sizeof(lm_chips[0]); i++)
        !           395:                if (lm_chips[i].chip_match(sc))
        !           396:                        break;
        !           397:
        !           398:        /* No point in doing anything if we don't have any sensors. */
        !           399:        if (sc->numsensors == 0)
        !           400:                return;
        !           401:
        !           402:        sc->sensortask = sensor_task_register(sc, lm_refresh, 5);
        !           403:        if (sc->sensortask == NULL) {
        !           404:                printf("%s: unable to register update task\n",
        !           405:                    sc->sc_dev.dv_xname);
        !           406:                return;
        !           407:        }
        !           408:
        !           409:        /* Start the monitoring loop */
        !           410:        config = sc->lm_readreg(sc, LM_CONFIG);
        !           411:        sc->lm_writereg(sc, LM_CONFIG, config | 0x01);
        !           412:
        !           413:        /* Add sensors */
        !           414:        for (i = 0; i < sc->numsensors; ++i)
        !           415:                sensor_attach(&sc->sensordev, &sc->sensors[i]);
        !           416:        sensordev_install(&sc->sensordev);
        !           417: }
        !           418:
        !           419: int
        !           420: lm_detach(struct lm_softc *sc)
        !           421: {
        !           422:        int i;
        !           423:
        !           424:        /* Remove sensors */
        !           425:        sensordev_deinstall(&sc->sensordev);
        !           426:        for (i = 0; i < sc->numsensors; i++)
        !           427:                sensor_detach(&sc->sensordev, &sc->sensors[i]);
        !           428:
        !           429:        if (sc->sensortask != NULL)
        !           430:                sensor_task_unregister(sc->sensortask);
        !           431:
        !           432:        return 0;
        !           433: }
        !           434:
        !           435: int
        !           436: lm_match(struct lm_softc *sc)
        !           437: {
        !           438:        int chipid;
        !           439:
        !           440:        /* See if we have an LM78 or LM79. */
        !           441:        chipid = sc->lm_readreg(sc, LM_CHIPID) & LM_CHIPID_MASK;
        !           442:        switch(chipid) {
        !           443:        case LM_CHIPID_LM78:
        !           444:                printf(": LM78\n");
        !           445:                break;
        !           446:        case LM_CHIPID_LM78J:
        !           447:                printf(": LM78J\n");
        !           448:                break;
        !           449:        case LM_CHIPID_LM79:
        !           450:                printf(": LM79\n");
        !           451:                break;
        !           452:        case LM_CHIPID_LM81:
        !           453:                printf(": LM81\n");
        !           454:                break;
        !           455:        default:
        !           456:                return 0;
        !           457:        }
        !           458:
        !           459:        lm_setup_sensors(sc, lm78_sensors);
        !           460:        sc->refresh_sensor_data = lm_refresh_sensor_data;
        !           461:        return 1;
        !           462: }
        !           463:
        !           464: int
        !           465: def_match(struct lm_softc *sc)
        !           466: {
        !           467:        int chipid;
        !           468:
        !           469:        chipid = sc->lm_readreg(sc, LM_CHIPID) & LM_CHIPID_MASK;
        !           470:        printf(": unknown chip (ID %d)\n", chipid);
        !           471:
        !           472:        lm_setup_sensors(sc, lm78_sensors);
        !           473:        sc->refresh_sensor_data = lm_refresh_sensor_data;
        !           474:        return 1;
        !           475: }
        !           476:
        !           477: int
        !           478: wb_match(struct lm_softc *sc)
        !           479: {
        !           480:        int banksel, vendid, devid;
        !           481:
        !           482:        /* Read vendor ID */
        !           483:        banksel = sc->lm_readreg(sc, WB_BANKSEL);
        !           484:        sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_HBAC);
        !           485:        vendid = sc->lm_readreg(sc, WB_VENDID) << 8;
        !           486:        sc->lm_writereg(sc, WB_BANKSEL, 0);
        !           487:        vendid |= sc->lm_readreg(sc, WB_VENDID);
        !           488:        sc->lm_writereg(sc, WB_BANKSEL, banksel);
        !           489:        DPRINTF((" winbond vend id 0x%x\n", vendid));
        !           490:        if (vendid != WB_VENDID_WINBOND && vendid != WB_VENDID_ASUS)
        !           491:                return 0;
        !           492:
        !           493:        /* Read device/chip ID */
        !           494:        sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_B0);
        !           495:        devid = sc->lm_readreg(sc, LM_CHIPID);
        !           496:        sc->chipid = sc->lm_readreg(sc, WB_BANK0_CHIPID);
        !           497:        sc->lm_writereg(sc, WB_BANKSEL, banksel);
        !           498:        DPRINTF((" winbond chip id 0x%x\n", sc->chipid));
        !           499:        switch(sc->chipid) {
        !           500:        case WB_CHIPID_W83627HF:
        !           501:                printf(": W83627HF\n");
        !           502:                lm_setup_sensors(sc, w83627hf_sensors);
        !           503:                break;
        !           504:        case WB_CHIPID_W83627THF:
        !           505:                printf(": W83627THF\n");
        !           506:                lm_setup_sensors(sc, w83637hf_sensors);
        !           507:                break;
        !           508:        case WB_CHIPID_W83627EHF_A:
        !           509:                printf(": W83627EHF-A\n");
        !           510:                lm_setup_sensors(sc, w83627ehf_sensors);
        !           511:                break;
        !           512:        case WB_CHIPID_W83627EHF:
        !           513:                printf(": W83627EHF\n");
        !           514:                lm_setup_sensors(sc, w83627ehf_sensors);
        !           515:                break;
        !           516:        case WB_CHIPID_W83627DHG:
        !           517:                printf(": W83627DHG\n");
        !           518:                lm_setup_sensors(sc, w83627dhg_sensors);
        !           519:                break;
        !           520:        case WB_CHIPID_W83637HF:
        !           521:                printf(": W83637HF\n");
        !           522:                sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_B0);
        !           523:                if (sc->lm_readreg(sc, WB_BANK0_CONFIG) & WB_CONFIG_VMR9)
        !           524:                        sc->vrm9 = 1;
        !           525:                sc->lm_writereg(sc, WB_BANKSEL, banksel);
        !           526:                lm_setup_sensors(sc, w83637hf_sensors);
        !           527:                break;
        !           528:        case WB_CHIPID_W83697HF:
        !           529:                printf(": W83697HF\n");
        !           530:                lm_setup_sensors(sc, w83697hf_sensors);
        !           531:                break;
        !           532:        case WB_CHIPID_W83781D:
        !           533:        case WB_CHIPID_W83781D_2:
        !           534:                printf(": W83781D\n");
        !           535:                lm_setup_sensors(sc, w83781d_sensors);
        !           536:                break;
        !           537:        case WB_CHIPID_W83782D:
        !           538:                printf(": W83782D\n");
        !           539:                lm_setup_sensors(sc, w83782d_sensors);
        !           540:                break;
        !           541:        case WB_CHIPID_W83783S:
        !           542:                printf(": W83783S\n");
        !           543:                lm_setup_sensors(sc, w83783s_sensors);
        !           544:                break;
        !           545:        case WB_CHIPID_W83791D:
        !           546:                printf(": W83791D\n");
        !           547:                lm_setup_sensors(sc, w83791d_sensors);
        !           548:                break;
        !           549:        case WB_CHIPID_W83791SD:
        !           550:                printf(": W83791SD\n");
        !           551:                break;
        !           552:        case WB_CHIPID_W83792D:
        !           553:                if (devid >= 0x10 && devid <= 0x29)
        !           554:                        printf(": W83792D rev %c\n", 'A' + devid - 0x10);
        !           555:                else
        !           556:                        printf(": W83792D rev 0x%x\n", devid);
        !           557:                lm_setup_sensors(sc, w83792d_sensors);
        !           558:                break;
        !           559:        case WB_CHIPID_AS99127F:
        !           560:                if (vendid == WB_VENDID_ASUS) {
        !           561:                        printf(": AS99127F\n");
        !           562:                        lm_setup_sensors(sc, w83781d_sensors);
        !           563:                } else {
        !           564:                        printf(": AS99127F rev 2\n");
        !           565:                        lm_setup_sensors(sc, as99127f_sensors);
        !           566:                }
        !           567:                break;
        !           568:        default:
        !           569:                printf(": unknown Winbond chip (ID 0x%x)\n", sc->chipid);
        !           570:                /* Handle as a standard LM78. */
        !           571:                lm_setup_sensors(sc, lm78_sensors);
        !           572:                sc->refresh_sensor_data = lm_refresh_sensor_data;
        !           573:                return 1;
        !           574:        }
        !           575:
        !           576:        sc->refresh_sensor_data = wb_refresh_sensor_data;
        !           577:        return 1;
        !           578: }
        !           579:
        !           580: void
        !           581: lm_setup_sensors(struct lm_softc *sc, struct lm_sensor *sensors)
        !           582: {
        !           583:        int i;
        !           584:
        !           585:        strlcpy(sc->sensordev.xname, sc->sc_dev.dv_xname,
        !           586:            sizeof(sc->sensordev.xname));
        !           587:
        !           588:        for (i = 0; sensors[i].desc; i++) {
        !           589:                sc->sensors[i].type = sensors[i].type;
        !           590:                strlcpy(sc->sensors[i].desc, sensors[i].desc,
        !           591:                    sizeof(sc->sensors[i].desc));
        !           592:                sc->numsensors++;
        !           593:        }
        !           594:        sc->lm_sensors = sensors;
        !           595: }
        !           596:
        !           597: void
        !           598: lm_refresh(void *arg)
        !           599: {
        !           600:        struct lm_softc *sc = arg;
        !           601:
        !           602:        sc->refresh_sensor_data(sc);
        !           603: }
        !           604:
        !           605: void
        !           606: lm_refresh_sensor_data(struct lm_softc *sc)
        !           607: {
        !           608:        int i;
        !           609:
        !           610:        for (i = 0; i < sc->numsensors; i++)
        !           611:                sc->lm_sensors[i].refresh(sc, i);
        !           612: }
        !           613:
        !           614: void
        !           615: lm_refresh_volt(struct lm_softc *sc, int n)
        !           616: {
        !           617:        struct ksensor *sensor = &sc->sensors[n];
        !           618:        int data;
        !           619:
        !           620:        data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
        !           621:        sensor->value = (data << 4);
        !           622:        sensor->value *= sc->lm_sensors[n].rfact;
        !           623:        sensor->value /= 10;
        !           624: }
        !           625:
        !           626: void
        !           627: lm_refresh_temp(struct lm_softc *sc, int n)
        !           628: {
        !           629:        struct ksensor *sensor = &sc->sensors[n];
        !           630:        int sdata;
        !           631:
        !           632:        /*
        !           633:         * The data sheet suggests that the range of the temperature
        !           634:         * sensor is between -55 degC and +125 degC.
        !           635:         */
        !           636:        sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
        !           637:        if (sdata > 0x7d && sdata < 0xc9) {
        !           638:                sensor->flags |= SENSOR_FINVALID;
        !           639:                sensor->value = 0;
        !           640:        } else {
        !           641:                if (sdata & 0x80)
        !           642:                        sdata -= 0x100;
        !           643:                sensor->flags &= ~SENSOR_FINVALID;
        !           644:                sensor->value = sdata * 1000000 + 273150000;
        !           645:        }
        !           646: }
        !           647:
        !           648: void
        !           649: lm_refresh_fanrpm(struct lm_softc *sc, int n)
        !           650: {
        !           651:        struct ksensor *sensor = &sc->sensors[n];
        !           652:        int data, divisor = 1;
        !           653:
        !           654:        /*
        !           655:         * We might get more accurate fan readings by adjusting the
        !           656:         * divisor, but that might interfere with APM or other SMM
        !           657:         * BIOS code reading the fan speeds.
        !           658:         */
        !           659:
        !           660:        /* FAN3 has a fixed fan divisor. */
        !           661:        if (sc->lm_sensors[n].reg == LM_FAN1 ||
        !           662:            sc->lm_sensors[n].reg == LM_FAN2) {
        !           663:                data = sc->lm_readreg(sc, LM_VIDFAN);
        !           664:                if (sc->lm_sensors[n].reg == LM_FAN1)
        !           665:                        divisor = (data >> 4) & 0x03;
        !           666:                else
        !           667:                        divisor = (data >> 6) & 0x03;
        !           668:        }
        !           669:
        !           670:        data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
        !           671:        if (data == 0xff || data == 0x00) {
        !           672:                sensor->flags |= SENSOR_FINVALID;
        !           673:                sensor->value = 0;
        !           674:        } else {
        !           675:                sensor->flags &= ~SENSOR_FINVALID;
        !           676:                sensor->value = 1350000 / (data << divisor);
        !           677:        }
        !           678: }
        !           679:
        !           680: void
        !           681: wb_refresh_sensor_data(struct lm_softc *sc)
        !           682: {
        !           683:        int banksel, bank, i;
        !           684:
        !           685:        /*
        !           686:         * Properly save and restore bank selection register.
        !           687:         */
        !           688:
        !           689:        banksel = bank = sc->lm_readreg(sc, WB_BANKSEL);
        !           690:        for (i = 0; i < sc->numsensors; i++) {
        !           691:                if (bank != sc->lm_sensors[i].bank) {
        !           692:                        bank = sc->lm_sensors[i].bank;
        !           693:                        sc->lm_writereg(sc, WB_BANKSEL, bank);
        !           694:                }
        !           695:                sc->lm_sensors[i].refresh(sc, i);
        !           696:        }
        !           697:        sc->lm_writereg(sc, WB_BANKSEL, banksel);
        !           698: }
        !           699:
        !           700: void
        !           701: wb_w83637hf_refresh_vcore(struct lm_softc *sc, int n)
        !           702: {
        !           703:        struct ksensor *sensor = &sc->sensors[n];
        !           704:        int data;
        !           705:
        !           706:        data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
        !           707:
        !           708:        /*
        !           709:         * Depending on the voltage detection method,
        !           710:         * one of the following formulas is used:
        !           711:         *      VRM8 method: value = raw * 0.016V
        !           712:         *      VRM9 method: value = raw * 0.00488V + 0.70V
        !           713:         */
        !           714:        if (sc->vrm9)
        !           715:                sensor->value = (data * 4880) + 700000;
        !           716:        else
        !           717:                sensor->value = (data * 16000);
        !           718: }
        !           719:
        !           720: void
        !           721: wb_refresh_nvolt(struct lm_softc *sc, int n)
        !           722: {
        !           723:        struct ksensor *sensor = &sc->sensors[n];
        !           724:        int data;
        !           725:
        !           726:        data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
        !           727:        sensor->value = ((data << 4) - WB_VREF);
        !           728:        sensor->value *= sc->lm_sensors[n].rfact;
        !           729:        sensor->value /= 10;
        !           730:        sensor->value += WB_VREF * 1000;
        !           731: }
        !           732:
        !           733: void
        !           734: wb_w83627ehf_refresh_nvolt(struct lm_softc *sc, int n)
        !           735: {
        !           736:        struct ksensor *sensor = &sc->sensors[n];
        !           737:        int data;
        !           738:
        !           739:        data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
        !           740:        sensor->value = ((data << 3) - WB_W83627EHF_VREF);
        !           741:        sensor->value *= RFACT(232, 10);
        !           742:        sensor->value /= 10;
        !           743:        sensor->value += WB_W83627EHF_VREF * 1000;
        !           744: }
        !           745:
        !           746: void
        !           747: wb_refresh_temp(struct lm_softc *sc, int n)
        !           748: {
        !           749:        struct ksensor *sensor = &sc->sensors[n];
        !           750:        int sdata;
        !           751:
        !           752:        /*
        !           753:         * The data sheet suggests that the range of the temperature
        !           754:         * sensor is between -55 degC and +125 degC.  However, values
        !           755:         * around -48 degC seem to be a very common bogus values.
        !           756:         * Since such values are unreasonably low, we use -45 degC for
        !           757:         * the lower limit instead.
        !           758:         */
        !           759:        sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg) << 1;
        !           760:        sdata += sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1) >> 7;
        !           761:        if (sdata > 0x0fa && sdata < 0x1a6) {
        !           762:                sensor->flags |= SENSOR_FINVALID;
        !           763:                sensor->value = 0;
        !           764:        } else {
        !           765:                if (sdata & 0x100)
        !           766:                        sdata -= 0x200;
        !           767:                sensor->flags &= ~SENSOR_FINVALID;
        !           768:                sensor->value = sdata * 500000 + 273150000;
        !           769:        }
        !           770: }
        !           771:
        !           772: void
        !           773: wb_refresh_fanrpm(struct lm_softc *sc, int n)
        !           774: {
        !           775:        struct ksensor *sensor = &sc->sensors[n];
        !           776:        int fan, data, divisor = 0;
        !           777:
        !           778:        /*
        !           779:         * This is madness; the fan divisor bits are scattered all
        !           780:         * over the place.
        !           781:         */
        !           782:
        !           783:        if (sc->lm_sensors[n].reg == LM_FAN1 ||
        !           784:            sc->lm_sensors[n].reg == LM_FAN2 ||
        !           785:            sc->lm_sensors[n].reg == LM_FAN3) {
        !           786:                data = sc->lm_readreg(sc, WB_BANK0_VBAT);
        !           787:                fan = (sc->lm_sensors[n].reg - LM_FAN1);
        !           788:                if ((data >> 5) & (1 << fan))
        !           789:                        divisor |= 0x04;
        !           790:        }
        !           791:
        !           792:        if (sc->lm_sensors[n].reg == LM_FAN1 ||
        !           793:            sc->lm_sensors[n].reg == LM_FAN2) {
        !           794:                data = sc->lm_readreg(sc, LM_VIDFAN);
        !           795:                if (sc->lm_sensors[n].reg == LM_FAN1)
        !           796:                        divisor |= (data >> 4) & 0x03;
        !           797:                else
        !           798:                        divisor |= (data >> 6) & 0x03;
        !           799:        } else if (sc->lm_sensors[n].reg == LM_FAN3) {
        !           800:                data = sc->lm_readreg(sc, WB_PIN);
        !           801:                divisor |= (data >> 6) & 0x03;
        !           802:        } else if (sc->lm_sensors[n].reg == WB_BANK0_FAN4 ||
        !           803:                   sc->lm_sensors[n].reg == WB_BANK0_FAN5) {
        !           804:                data = sc->lm_readreg(sc, WB_BANK0_FAN45);
        !           805:                if (sc->lm_sensors[n].reg == WB_BANK0_FAN4)
        !           806:                        divisor |= (data >> 0) & 0x07;
        !           807:                else
        !           808:                        divisor |= (data >> 4) & 0x07;
        !           809:        }
        !           810:
        !           811:        data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
        !           812:        if (data == 0xff || data == 0x00) {
        !           813:                sensor->flags |= SENSOR_FINVALID;
        !           814:                sensor->value = 0;
        !           815:        } else {
        !           816:                sensor->flags &= ~SENSOR_FINVALID;
        !           817:                sensor->value = 1350000 / (data << divisor);
        !           818:        }
        !           819: }
        !           820:
        !           821: void
        !           822: wb_w83792d_refresh_fanrpm(struct lm_softc *sc, int n)
        !           823: {
        !           824:        struct ksensor *sensor = &sc->sensors[n];
        !           825:        int reg, shift, data, divisor = 1;
        !           826:
        !           827:        switch (sc->lm_sensors[n].reg) {
        !           828:        case 0x28:
        !           829:                reg = 0x47; shift = 0;
        !           830:                break;
        !           831:        case 0x29:
        !           832:                reg = 0x47; shift = 4;
        !           833:                break;
        !           834:        case 0x2a:
        !           835:                reg = 0x5b; shift = 0;
        !           836:                break;
        !           837:        case 0xb8:
        !           838:                reg = 0x5b; shift = 4;
        !           839:                break;
        !           840:        case 0xb9:
        !           841:                reg = 0x5c; shift = 0;
        !           842:                break;
        !           843:        case 0xba:
        !           844:                reg = 0x5c; shift = 4;
        !           845:                break;
        !           846:        case 0xbe:
        !           847:                reg = 0x9e; shift = 0;
        !           848:                break;
        !           849:        default:
        !           850:                reg = 0;
        !           851:                break;
        !           852:        }
        !           853:
        !           854:        data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
        !           855:        if (data == 0xff || data == 0x00) {
        !           856:                sensor->flags |= SENSOR_FINVALID;
        !           857:                sensor->value = 0;
        !           858:        } else {
        !           859:                if (reg != 0)
        !           860:                        divisor = (sc->lm_readreg(sc, reg) >> shift) & 0x7;
        !           861:                sensor->flags &= ~SENSOR_FINVALID;
        !           862:                sensor->value = 1350000 / (data << divisor);
        !           863:        }
        !           864: }
        !           865:
        !           866: void
        !           867: as_refresh_temp(struct lm_softc *sc, int n)
        !           868: {
        !           869:        struct ksensor *sensor = &sc->sensors[n];
        !           870:        int sdata;
        !           871:
        !           872:        /*
        !           873:         * It seems a shorted temperature diode produces an all-ones
        !           874:         * bit pattern.
        !           875:         */
        !           876:        sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg) << 1;
        !           877:        sdata += sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1) >> 7;
        !           878:        if (sdata == 0x1ff) {
        !           879:                sensor->flags |= SENSOR_FINVALID;
        !           880:                sensor->value = 0;
        !           881:        } else {
        !           882:                if (sdata & 0x100)
        !           883:                        sdata -= 0x200;
        !           884:                sensor->flags &= ~SENSOR_FINVALID;
        !           885:                sensor->value = sdata * 500000 + 273150000;
        !           886:        }
        !           887: }

CVSweb