This source file includes following definitions.
- viaenv_match
- val_to_uK
- val_to_rpm
- val_to_uV
- viaenv_refresh_sensor_data
- viaenv_attach
- viaenv_refresh
- viaenv_get_timecount
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/device.h>
41 #include <sys/kernel.h>
42 #include <sys/queue.h>
43 #include <sys/sensors.h>
44 #include <sys/timeout.h>
45 #ifdef __HAVE_TIMECOUNTER
46 #include <sys/timetc.h>
47 #endif
48
49 #include <machine/bus.h>
50
51 #include <dev/pci/pcivar.h>
52 #include <dev/pci/pcireg.h>
53 #include <dev/pci/pcidevs.h>
54
55 #ifdef VIAENV_DEBUG
56 unsigned int viaenv_debug = 0;
57 #define DPRINTF(X) do { if(viaenv_debug) printf X ; } while(0)
58 #else
59 #define DPRINTF(X)
60 #endif
61
62 #define VIANUMSENSORS 10
63
64 struct viaenv_softc {
65 struct device sc_dev;
66 bus_space_tag_t sc_iot;
67 bus_space_handle_t sc_ioh;
68 bus_space_handle_t sc_pm_ioh;
69
70 int sc_fan_div[2];
71
72 struct ksensor sc_data[VIANUMSENSORS];
73 struct ksensordev sc_sensordev;
74 };
75
76 int viaenv_match(struct device *, void *, void *);
77 void viaenv_attach(struct device *, struct device *, void *);
78
79 int val_to_uK(unsigned int);
80 int val_to_rpm(unsigned int, int);
81 long val_to_uV(unsigned int, int);
82 void viaenv_refresh_sensor_data(struct viaenv_softc *);
83 void viaenv_refresh(void *);
84
85 #ifdef __HAVE_TIMECOUNTER
86 u_int viaenv_get_timecount(struct timecounter *tc);
87
88 struct timecounter viaenv_timecounter = {
89 viaenv_get_timecount,
90 0,
91 0xffffff,
92 3579545,
93 "VIAPM",
94 1000
95 };
96 #endif
97
98 struct cfattach viaenv_ca = {
99 sizeof(struct viaenv_softc),
100 viaenv_match,
101 viaenv_attach
102 };
103
104 struct cfdriver viaenv_cd = {
105 NULL, "viaenv", DV_DULL
106 };
107
108 struct timeout viaenv_timeout;
109
110 const struct pci_matchid viaenv_devices[] = {
111 { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT82C686A_SMB },
112 { PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT8231_PWR }
113 };
114
115 int
116 viaenv_match(struct device *parent, void *match, void *aux)
117 {
118 return (pci_matchbyid((struct pci_attach_args *)aux, viaenv_devices,
119 sizeof(viaenv_devices) / sizeof(viaenv_devices[0])));
120 }
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135 static const long val_to_temp[] = {
136 20225, 20435, 20645, 20855, 21045, 21245, 21425, 21615, 21785, 21955,
137 22125, 22285, 22445, 22605, 22755, 22895, 23035, 23175, 23315, 23445,
138 23565, 23695, 23815, 23925, 24045, 24155, 24265, 24365, 24465, 24565,
139 24665, 24765, 24855, 24945, 25025, 25115, 25195, 25275, 25355, 25435,
140 25515, 25585, 25655, 25725, 25795, 25865, 25925, 25995, 26055, 26115,
141 26175, 26235, 26295, 26355, 26405, 26465, 26515, 26575, 26625, 26675,
142 26725, 26775, 26825, 26875, 26925, 26975, 27025, 27065, 27115, 27165,
143 27205, 27255, 27295, 27345, 27385, 27435, 27475, 27515, 27565, 27605,
144 27645, 27685, 27735, 27775, 27815, 27855, 27905, 27945, 27985, 28025,
145 28065, 28105, 28155, 28195, 28235, 28275, 28315, 28355, 28405, 28445,
146 28485, 28525, 28565, 28615, 28655, 28695, 28735, 28775, 28825, 28865,
147 28905, 28945, 28995, 29035, 29075, 29125, 29165, 29205, 29245, 29295,
148 29335, 29375, 29425, 29465, 29505, 29555, 29595, 29635, 29685, 29725,
149 29765, 29815, 29855, 29905, 29945, 29985, 30035, 30075, 30125, 30165,
150 30215, 30255, 30305, 30345, 30385, 30435, 30475, 30525, 30565, 30615,
151 30655, 30705, 30755, 30795, 30845, 30885, 30935, 30975, 31025, 31075,
152 31115, 31165, 31215, 31265, 31305, 31355, 31405, 31455, 31505, 31545,
153 31595, 31645, 31695, 31745, 31805, 31855, 31905, 31955, 32005, 32065,
154 32115, 32175, 32225, 32285, 32335, 32395, 32455, 32515, 32575, 32635,
155 32695, 32755, 32825, 32885, 32955, 33025, 33095, 33155, 33235, 33305,
156 33375, 33455, 33525, 33605, 33685, 33765, 33855, 33935, 34025, 34115,
157 34205, 34295, 34395, 34495, 34595, 34695, 34805, 34905, 35015, 35135,
158 35245, 35365, 35495, 35615, 35745, 35875, 36015, 36145, 36295, 36435,
159 36585, 36745, 36895, 37065, 37225, 37395, 37575, 37755, 37935, 38125,
160 38325, 38525, 38725, 38935, 39155, 39375, 39605, 39835, 40075, 40325,
161 40575, 40835, 41095, 41375, 41655, 41935,
162 };
163
164
165 int
166 val_to_uK(unsigned int val)
167 {
168 int i = val / 4;
169 int j = val % 4;
170
171 assert(i >= 0 && i <= 255);
172
173 if (j == 0 || i == 255)
174 return val_to_temp[i] * 10000;
175
176
177 return (val_to_temp[i] * (4 - j) +
178 val_to_temp[i + 1] * j) * 2500 ;
179 }
180
181 int
182 val_to_rpm(unsigned int val, int div)
183 {
184
185 if (val == 0)
186 return 0;
187
188 return 1350000 / val / div;
189 }
190
191 long
192 val_to_uV(unsigned int val, int index)
193 {
194 static const long mult[] =
195 {1250000, 1250000, 1670000, 2600000, 6300000};
196
197 assert(index >= 0 && index <= 4);
198
199 return (25LL * val + 133) * mult[index] / 2628;
200 }
201
202 #define VIAENV_TSENS3 0x1f
203 #define VIAENV_TSENS1 0x20
204 #define VIAENV_TSENS2 0x21
205 #define VIAENV_VSENS1 0x22
206 #define VIAENV_VSENS2 0x23
207 #define VIAENV_VCORE 0x24
208 #define VIAENV_VSENS3 0x25
209 #define VIAENV_VSENS4 0x26
210 #define VIAENV_FAN1 0x29
211 #define VIAENV_FAN2 0x2a
212 #define VIAENV_FANCONF 0x47
213 #define VIAENV_TLOW 0x49
214 #define VIAENV_TIRQ 0x4b
215
216 #define VIAENV_GENCFG 0x40
217 #define VIAENV_GENCFG_TMR32 (1 << 11)
218 #define VIAENV_GENCFG_PMEN (1 << 15)
219 #define VIAENV_PMBASE 0x48
220 #define VIAENV_PMSIZE 128
221 #define VIAENV_PM_TMR 0x08
222
223 void
224 viaenv_refresh_sensor_data(struct viaenv_softc *sc)
225 {
226 int i;
227 u_int8_t v, v2;
228
229
230 v = bus_space_read_1(sc->sc_iot, sc->sc_ioh, VIAENV_TIRQ);
231 v2 = bus_space_read_1(sc->sc_iot, sc->sc_ioh, VIAENV_TSENS1);
232 DPRINTF(("TSENS1 = %d\n", (v2 << 2) | (v >> 6)));
233 sc->sc_data[0].value = val_to_uK((v2 << 2) | (v >> 6));
234
235 v = bus_space_read_1(sc->sc_iot, sc->sc_ioh, VIAENV_TLOW);
236 v2 = bus_space_read_1(sc->sc_iot, sc->sc_ioh, VIAENV_TSENS2);
237 DPRINTF(("TSENS2 = %d\n", (v2 << 2) | ((v >> 4) & 0x3)));
238 sc->sc_data[1].value = val_to_uK((v2 << 2) | ((v >> 4) & 0x3));
239
240 v2 = bus_space_read_1(sc->sc_iot, sc->sc_ioh, VIAENV_TSENS3);
241 DPRINTF(("TSENS3 = %d\n", (v2 << 2) | (v >> 6)));
242 sc->sc_data[2].value = val_to_uK((v2 << 2) | (v >> 6));
243
244 v = bus_space_read_1(sc->sc_iot, sc->sc_ioh, VIAENV_FANCONF);
245
246 sc->sc_fan_div[0] = 1 << ((v >> 4) & 0x3);
247 sc->sc_fan_div[1] = 1 << ((v >> 6) & 0x3);
248
249
250 for (i = 3; i <= 4; i++) {
251 v = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
252 VIAENV_FAN1 + i - 3);
253 DPRINTF(("FAN%d = %d / %d\n", i - 3, v,
254 sc->sc_fan_div[i - 3]));
255 sc->sc_data[i].value = val_to_rpm(v, sc->sc_fan_div[i - 3]);
256 }
257
258
259 for (i = 5; i <= 9; i++) {
260 v = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
261 VIAENV_VSENS1 + i - 5);
262 DPRINTF(("V%d = %d\n", i - 5, v));
263 sc->sc_data[i].value = val_to_uV(v, i - 5);
264 }
265 }
266
267 void
268 viaenv_attach(struct device * parent, struct device * self, void *aux)
269 {
270 struct viaenv_softc *sc = (struct viaenv_softc *) self;
271 struct pci_attach_args *pa = aux;
272 pcireg_t iobase, control;
273 int i;
274
275 iobase = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x70);
276 control = pci_conf_read(pa->pa_pc, pa->pa_tag, 0x74);
277 if ((iobase & 0xff80) == 0 || (control & 1) == 0) {
278 printf(": HWM disabled");
279 goto nohwm;
280 }
281 sc->sc_iot = pa->pa_iot;
282 if (bus_space_map(sc->sc_iot, iobase & 0xff80, 128, 0, &sc->sc_ioh)) {
283 printf(": failed to map HWM I/O space");
284 goto nohwm;
285 }
286
287 for (i = 0; i <= 2; i++) {
288 sc->sc_data[i].type = SENSOR_TEMP;
289 }
290
291 for (i = 3; i <= 4; i++) {
292 sc->sc_data[i].type = SENSOR_FANRPM;
293 }
294
295 for (i = 5; i <= 9; ++i) {
296 sc->sc_data[i].type = SENSOR_VOLTS_DC;
297 }
298 strlcpy(sc->sc_data[5].desc, "VSENS1",
299 sizeof(sc->sc_data[5].desc));
300 strlcpy(sc->sc_data[6].desc, "VSENS2",
301 sizeof(sc->sc_data[6].desc));
302 strlcpy(sc->sc_data[7].desc, "Vcore",
303 sizeof(sc->sc_data[7].desc));
304 strlcpy(sc->sc_data[8].desc, "VSENS3",
305 sizeof(sc->sc_data[8].desc));
306 strlcpy(sc->sc_data[9].desc, "VSENS4",
307 sizeof(sc->sc_data[9].desc));
308
309
310 viaenv_refresh_sensor_data(sc);
311
312
313 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
314 sizeof(sc->sc_sensordev.xname));
315 for (i = 0; i < VIANUMSENSORS; ++i)
316 sensor_attach(&sc->sc_sensordev, &sc->sc_data[i]);
317 sensordev_install(&sc->sc_sensordev);
318
319
320 timeout_set(&viaenv_timeout, viaenv_refresh, sc);
321 timeout_add(&viaenv_timeout, (15 * hz) / 10);
322
323 nohwm:
324 #ifdef __HAVE_TIMECOUNTER
325
326 control = pci_conf_read(pa->pa_pc, pa->pa_tag, VIAENV_GENCFG);
327 if ((control & VIAENV_GENCFG_PMEN) == 0) {
328 printf(": PM disabled");
329 goto nopm;
330 }
331
332
333 iobase = pci_conf_read(pa->pa_pc, pa->pa_tag, VIAENV_PMBASE);
334 if (bus_space_map(sc->sc_iot, PCI_MAPREG_IO_ADDR(iobase),
335 VIAENV_PMSIZE, 0, &sc->sc_pm_ioh)) {
336 printf(": failed to map PM I/O space");
337 goto nopm;
338 }
339
340
341 if (control & VIAENV_GENCFG_TMR32)
342 viaenv_timecounter.tc_counter_mask = 0xffffffff;
343
344
345 viaenv_timecounter.tc_priv = sc;
346 tc_init(&viaenv_timecounter);
347
348 printf(": %s-bit timer at %lluHz",
349 (viaenv_timecounter.tc_counter_mask == 0xffffffff ? "32" : "24"),
350 (unsigned long long)viaenv_timecounter.tc_frequency);
351
352 nopm:
353 #endif
354 printf("\n");
355 }
356
357 void
358 viaenv_refresh(void *arg)
359 {
360 struct viaenv_softc *sc = (struct viaenv_softc *)arg;
361
362 viaenv_refresh_sensor_data(sc);
363 timeout_add(&viaenv_timeout, (15 * hz) / 10);
364 }
365
366 #ifdef __HAVE_TIMECOUNTER
367 u_int
368 viaenv_get_timecount(struct timecounter *tc)
369 {
370 struct viaenv_softc *sc = tc->tc_priv;
371 u_int u1, u2, u3;
372
373 u2 = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, VIAENV_PM_TMR);
374 u3 = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh, VIAENV_PM_TMR);
375 do {
376 u1 = u2;
377 u2 = u3;
378 u3 = bus_space_read_4(sc->sc_iot, sc->sc_pm_ioh,
379 VIAENV_PM_TMR);
380 } while (u1 > u2 || u2 > u3);
381
382 return (u2);
383 }
384 #endif