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