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