This source file includes following definitions.
- esm_probe
- esm_match
- esm_attach
- esm_watchdog
- esm_refresh
- esm_get_devmap
- esm_devmap
- esm_make_sensors
- esm_thresholds
- esm_bmc_ready
- esm_cmd
- esm_smb_cmd
- esm_val2temp
- esm_val2volts
- esm_val2amps
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <sys/param.h>
21 #include <sys/systm.h>
22 #include <sys/device.h>
23 #include <sys/kernel.h>
24 #include <sys/malloc.h>
25 #include <sys/timeout.h>
26 #include <sys/proc.h>
27 #include <sys/queue.h>
28 #include <sys/sensors.h>
29
30 #include <dev/isa/isareg.h>
31 #include <machine/bus.h>
32 #include <machine/intr.h>
33
34 #include <arch/i386/i386/esmvar.h>
35 #include <arch/i386/i386/esmreg.h>
36 #include <arch/i386/isa/isa_machdep.h>
37
38 #ifdef ESM_DEBUG
39 #define DPRINTF(x...) do { if (esmdebug) printf(x); } while (0)
40 #define DPRINTFN(n,x...) do { if (esmdebug > (n)) printf(x); } while (0)
41 int esmdebug = 3;
42 #else
43 #define DPRINTF(x...)
44 #define DPRINTFN(n,x...)
45 #endif
46
47 int esm_match(struct device *, void *, void *);
48 void esm_attach(struct device *, struct device *, void *);
49
50 enum esm_sensor_type {
51 ESM_S_UNKNOWN,
52 ESM_S_INTRUSION,
53 ESM_S_TEMP,
54 ESM_S_FANRPM,
55 ESM_S_VOLTS,
56 ESM_S_VOLTSx10,
57 ESM_S_AMPS,
58 ESM_S_PWRSUP,
59 ESM_S_PCISLOT,
60 ESM_S_SCSICONN,
61 ESM_S_DRIVES,
62 ESM_S_DRIVE,
63 ESM_S_HPSLOT,
64 ESM_S_ACSWITCH
65 };
66
67
68
69
70
71 enum sensor_type esm_typemap[] = {
72 SENSOR_INTEGER,
73 SENSOR_INDICATOR,
74 SENSOR_TEMP,
75 SENSOR_FANRPM,
76 SENSOR_VOLTS_DC,
77 SENSOR_VOLTS_DC,
78 SENSOR_AMPS,
79 SENSOR_INDICATOR,
80 SENSOR_INTEGER,
81 SENSOR_INDICATOR,
82 SENSOR_DRIVE,
83 SENSOR_DRIVE,
84 SENSOR_INTEGER,
85 SENSOR_INDICATOR
86 };
87
88 struct esm_sensor_map {
89 enum esm_sensor_type type;
90 long arg;
91 const char *name;
92 };
93
94 struct esm_sensor {
95 u_int8_t es_dev;
96 u_int8_t es_id;
97
98 enum esm_sensor_type es_type;
99
100 struct {
101 u_int16_t th_lo_crit;
102 u_int16_t th_lo_warn;
103 u_int16_t th_hi_warn;
104 u_int16_t th_hi_crit;
105 } es_thresholds;
106
107 struct ksensor *es_sensor;
108 TAILQ_ENTRY(esm_sensor) es_entry;
109 };
110
111 struct esm_softc {
112 struct device sc_dev;
113 bus_space_tag_t sc_iot;
114 bus_space_handle_t sc_ioh;
115
116 TAILQ_HEAD(, esm_sensor) sc_sensors;
117 struct esm_sensor *sc_nextsensor;
118 struct ksensordev sc_sensordev;
119 int sc_retries;
120 volatile int sc_step;
121 struct timeout sc_timeout;
122
123 int sc_wdog_period;
124 volatile int sc_wdog_tickle;
125 };
126
127 struct cfattach esm_ca = {
128 sizeof(struct esm_softc), esm_match, esm_attach
129 };
130
131 struct cfdriver esm_cd = {
132 NULL, "esm", DV_DULL
133 };
134
135 #define DEVNAME(s) ((s)->sc_dev.dv_xname)
136
137 #define EREAD(s, r) bus_space_read_1((s)->sc_iot, (s)->sc_ioh, (r))
138 #define EWRITE(s, r, v) bus_space_write_1((s)->sc_iot, (s)->sc_ioh, (r), (v))
139
140 #define ECTRLWR(s, v) EWRITE((s), ESM2_CTRL_REG, (v))
141 #define EDATARD(s) EREAD((s), ESM2_DATA_REG)
142 #define EDATAWR(s, v) EWRITE((s), ESM2_DATA_REG, (v))
143
144 int esm_watchdog(void *, int);
145
146 void esm_refresh(void *);
147
148 int esm_get_devmap(struct esm_softc *, int, struct esm_devmap *);
149 void esm_devmap(struct esm_softc *, struct esm_devmap *);
150 void esm_make_sensors(struct esm_softc *, struct esm_devmap *,
151 struct esm_sensor_map *, int);
152 int esm_thresholds(struct esm_softc *, struct esm_devmap *,
153 struct esm_sensor *);
154
155 int esm_bmc_ready(struct esm_softc *, int, u_int8_t, u_int8_t, int);
156 int esm_cmd(struct esm_softc *, void *, size_t, void *, size_t,
157 int, int);
158 int esm_smb_cmd(struct esm_softc *, struct esm_smb_req *,
159 struct esm_smb_resp *, int, int);
160
161 int64_t esm_val2temp(u_int16_t);
162 int64_t esm_val2volts(u_int16_t);
163 int64_t esm_val2amps(u_int16_t);
164
165
166 int
167 esm_probe(void *aux)
168 {
169 const char *pdellstr;
170 struct dell_sysid *pdellid;
171 uint16_t sysid;
172
173 pdellstr = (const char *)ISA_HOLE_VADDR(DELL_SYSSTR_ADDR);
174 DPRINTF("Dell String: %s\n", pdellstr);
175 if (strncmp(pdellstr, "Dell System", 11))
176 return (0);
177
178 pdellid = (struct dell_sysid *)ISA_HOLE_VADDR(DELL_SYSID_ADDR);
179 if ((sysid = pdellid->sys_id) == DELL_SYSID_EXT)
180 sysid = pdellid->ext_id;
181 DPRINTF("SysId: %x\n", sysid);
182
183 switch (sysid) {
184 case DELL_SYSID_2300:
185 case DELL_SYSID_4300:
186 case DELL_SYSID_4350:
187 case DELL_SYSID_6300:
188 case DELL_SYSID_6350:
189 case DELL_SYSID_2400:
190 case DELL_SYSID_2450:
191 case DELL_SYSID_4400:
192 case DELL_SYSID_6400:
193 case DELL_SYSID_6450:
194 case DELL_SYSID_2500:
195 case DELL_SYSID_2550:
196 case DELL_SYSID_PV530F:
197 case DELL_SYSID_PV735N:
198 case DELL_SYSID_PV750N:
199 case DELL_SYSID_PV755N:
200 case DELL_SYSID_PA200:
201 return (1);
202 }
203
204 return (0);
205 }
206
207 int
208 esm_match(struct device *parent, void *match, void *aux)
209 {
210 struct esm_attach_args *eaa = aux;
211
212 if (strncmp(eaa->eaa_name, esm_cd.cd_name, sizeof(esm_cd.cd_name)) == 0 &&
213 esm_probe(eaa))
214 return (1);
215
216 return (0);
217 }
218
219 void
220 esm_attach(struct device *parent, struct device *self, void *aux)
221 {
222 struct esm_softc *sc = (struct esm_softc *)self;
223 struct esm_attach_args *eaa = aux;
224 u_int8_t x;
225
226 struct esm_devmap devmap;
227 int i;
228
229 sc->sc_iot = eaa->eaa_iot;
230 TAILQ_INIT(&sc->sc_sensors);
231
232 if (bus_space_map(sc->sc_iot, ESM2_BASE_PORT, 8, 0, &sc->sc_ioh) != 0) {
233 printf(": unable to map memory\n");
234 return;
235 }
236
237
238 x = EREAD(sc, ESM2_INTMASK_REG);
239 x &= ~(ESM2_TIM_SCI_EN|ESM2_TIM_SMI_EN|ESM2_TIM_NMI2SMI);
240 x |= ESM2_TIM_POWER_UP_BITS;
241 EWRITE(sc, ESM2_INTMASK_REG, x);
242
243
244 x = EREAD(sc, ESM2_CTRL_REG);
245 x &= ~ESM2_TC_HOSTBUSY;
246 x |= ESM2_TC_POWER_UP_BITS;
247 EWRITE(sc, ESM2_CTRL_REG, x);
248
249
250 if (esm_bmc_ready(sc, ESM2_CTRL_REG, ESM2_TC_ECBUSY, 0, 1) != 0) {
251 printf(": card is not alive\n");
252 bus_space_unmap(sc->sc_iot, sc->sc_ioh, 8);
253 return;
254 }
255
256 sc->sc_wdog_period = 0;
257 wdog_register(sc, esm_watchdog);
258 printf("\n");
259
260 strlcpy(sc->sc_sensordev.xname, DEVNAME(sc),
261 sizeof(sc->sc_sensordev.xname));
262 for (i = 0; i <= 0xff; i++) {
263 if (esm_get_devmap(sc, i, &devmap) != 0)
264 break;
265 esm_devmap(sc, &devmap);
266 }
267
268 if (!TAILQ_EMPTY(&sc->sc_sensors)) {
269 sensordev_install(&sc->sc_sensordev);
270 DPRINTF("%s: starting refresh\n", DEVNAME(sc));
271 sc->sc_nextsensor = TAILQ_FIRST(&sc->sc_sensors);
272 sc->sc_retries = 0;
273 timeout_set(&sc->sc_timeout, esm_refresh, sc);
274 timeout_add(&sc->sc_timeout, hz);
275 }
276 }
277
278 int
279 esm_watchdog(void *arg, int period)
280 {
281 struct esm_softc *sc = arg;
282 struct esm_wdog_prop prop;
283 struct esm_wdog_state state;
284 int s;
285
286 if (sc->sc_wdog_period == period) {
287 if (period != 0) {
288 s = splclock();
289 if (sc->sc_step != 0) {
290
291 sc->sc_wdog_tickle = 1;
292 } else {
293
294 EWRITE(sc, ESM2_CTRL_REG, ESM2_TC_HBDB);
295 }
296 splx(s);
297 }
298 return (period);
299 }
300
301
302
303 memset(&prop, 0, sizeof(prop));
304 memset(&state, 0, sizeof(state));
305
306 if (period < 10 && period > 0)
307 period = 10;
308
309 s = splclock();
310
311 prop.cmd = ESM2_CMD_HWDC;
312 prop.subcmd = ESM2_HWDC_WRITE_PROPERTY;
313 prop.action = (period == 0) ? ESM_WDOG_DISABLE : ESM_WDOG_RESET;
314 prop.time = period;
315
316
317
318
319
320
321 while (sc->sc_step != 0) {
322 if (tsleep(sc, PUSER | PCATCH, "esm", 0) == EINTR) {
323 splx(s);
324 return (sc->sc_wdog_period);
325 }
326 }
327
328 if (esm_cmd(sc, &prop, sizeof(prop), NULL, 0, 1, 0) != 0) {
329 splx(s);
330 return (sc->sc_wdog_period);
331 }
332
333 state.cmd = ESM2_CMD_HWDC;
334 state.subcmd = ESM2_HWDC_WRITE_STATE;
335 state.state = (period == 0) ? 0 : 1;
336
337
338 esm_cmd(sc, &state, sizeof(state), NULL, 0, 1, 0);
339
340 splx(s);
341
342 sc->sc_wdog_period = period;
343 return (period);
344 }
345
346 void
347 esm_refresh(void *arg)
348 {
349 struct esm_softc *sc = arg;
350 struct esm_sensor *es = sc->sc_nextsensor;
351 struct esm_smb_req req;
352 struct esm_smb_resp resp;
353 struct esm_smb_resp_val *val = &resp.resp_val;
354 int nsensors, i, step;
355
356 memset(&req, 0, sizeof(req));
357 req.h_cmd = ESM2_CMD_SMB_XMIT_RECV;
358 req.h_dev = es->es_dev;
359 req.h_txlen = sizeof(req.req_val);
360 req.h_rxlen = sizeof(resp.resp_val);
361 req.req_val.v_cmd = ESM2_SMB_SENSOR_VALUE;
362 req.req_val.v_sensor = es->es_id;
363
364 switch (es->es_type) {
365 case ESM_S_DRIVES:
366 nsensors = 4;
367 break;
368 case ESM_S_PWRSUP:
369 nsensors = 6;
370 break;
371 default:
372 nsensors = 1;
373 break;
374 }
375
376 if ((step = esm_smb_cmd(sc, &req, &resp, 0, sc->sc_step)) != 0) {
377 sc->sc_step = step;
378 if (++sc->sc_retries < 10)
379 goto tick;
380
381 for (i = 0; i < nsensors; i++)
382 es->es_sensor[i].flags |= SENSOR_FINVALID;
383 } else {
384 switch (es->es_type) {
385 case ESM_S_TEMP:
386 es->es_sensor->value = esm_val2temp(val->v_reading);
387 break;
388 case ESM_S_VOLTS:
389 es->es_sensor->value = esm_val2volts(val->v_reading);
390 break;
391 case ESM_S_VOLTSx10:
392 es->es_sensor->value =
393 esm_val2volts(val->v_reading) * 10;
394 break;
395 case ESM_S_AMPS:
396 es->es_sensor->value = esm_val2amps(val->v_reading);
397 break;
398 case ESM_S_DRIVES:
399 for (i = 0; i < nsensors; i++) {
400 es->es_sensor[i].value =
401 (val->v_reading >> i * 8) & 0xf;
402 }
403 break;
404 case ESM_S_PWRSUP:
405 for (i = 0; i < nsensors; i++) {
406 es->es_sensor[i].value =
407 (val->v_reading >> i) & 0x1;
408 }
409 break;
410 default:
411 es->es_sensor->value = val->v_reading;
412 break;
413 }
414
415 switch (es->es_type) {
416 case ESM_S_TEMP:
417 case ESM_S_FANRPM:
418 case ESM_S_VOLTS:
419 case ESM_S_AMPS:
420 if (val->v_reading >= es->es_thresholds.th_hi_crit ||
421 val->v_reading <= es->es_thresholds.th_lo_crit) {
422 es->es_sensor->status = SENSOR_S_CRIT;
423 break;
424 }
425
426 if (val->v_reading >= es->es_thresholds.th_hi_warn ||
427 val->v_reading <= es->es_thresholds.th_lo_warn) {
428 es->es_sensor->status = SENSOR_S_WARN;
429 break;
430 }
431
432 es->es_sensor->status = SENSOR_S_OK;
433 break;
434
435 case ESM_S_PWRSUP:
436 if (val->v_status & ESM2_VS_PSU_FAIL) {
437 es->es_sensor[3].status = SENSOR_S_CRIT;
438 break;
439 }
440
441 es->es_sensor[3].status = SENSOR_S_OK;
442 break;
443
444 default:
445 break;
446 }
447
448 for (i = 0; i < nsensors; i++)
449 es->es_sensor->flags &= ~SENSOR_FINVALID;
450 }
451
452 sc->sc_nextsensor = TAILQ_NEXT(es, es_entry);
453 sc->sc_retries = 0;
454 sc->sc_step = 0;
455
456 if (sc->sc_wdog_tickle) {
457
458
459
460
461 EWRITE(sc, ESM2_CTRL_REG, ESM2_TC_HBDB);
462 sc->sc_wdog_tickle = 0;
463 }
464 wakeup(sc);
465
466 if (sc->sc_nextsensor == NULL) {
467 sc->sc_nextsensor = TAILQ_FIRST(&sc->sc_sensors);
468 timeout_add(&sc->sc_timeout, hz * 10);
469 return;
470 }
471 tick:
472 timeout_add(&sc->sc_timeout, hz / 20);
473 }
474
475 int
476 esm_get_devmap(struct esm_softc *sc, int dev, struct esm_devmap *devmap)
477 {
478 struct esm_devmap_req req;
479 struct esm_devmap_resp resp;
480 #ifdef ESM_DEBUG
481 int i;
482 #endif
483
484 memset(&req, 0, sizeof(req));
485 memset(&resp, 0, sizeof(resp));
486
487 req.cmd = ESM2_CMD_DEVICEMAP;
488 req.action = ESM2_DEVICEMAP_READ;
489 req.index = dev;
490 req.ndev = 1;
491
492 if (esm_cmd(sc, &req, sizeof(req), &resp, sizeof(resp), 1, 0) != 0)
493 return (1);
494
495 if (resp.status != 0)
496 return (1);
497
498 memcpy(devmap, &resp.devmap[0], sizeof(struct esm_devmap));
499
500 #ifdef ESM_DEBUG
501 if (esmdebug > 5) {
502 printf("\n");
503 printf("Device Map(%d) returns:\n", dev);
504 printf(" status: %.2x\n", resp.status);
505 printf(" #devs : %.2x\n", resp.ndev);
506 printf(" index: %.2x\n", resp.devmap[0].index);
507 printf(" Type : %.2x.%.2x\n", resp.devmap[0].dev_major,
508 resp.devmap[0].dev_minor);
509 printf(" Rev : %.2x.%.2x\n", resp.devmap[0].rev_major,
510 resp.devmap[0].rev_minor);
511 printf(" ROM : %.2x\n", resp.devmap[0].rev_rom);
512 printf(" SMB : %.2x\n", resp.devmap[0].smb_addr);
513 printf(" Stat : %.2x\n", resp.devmap[0].status);
514 printf(" MonTy: %.2x\n", resp.devmap[0].monitor_type);
515 printf(" Poll : %.2x\n", resp.devmap[0].pollcycle);
516 printf(" UUID : ");
517 for (i = 0; i < ESM2_UUID_LEN; i++) {
518 printf("%02x", resp.devmap[0].uniqueid[i]);
519 }
520 printf("\n");
521 }
522 #endif
523
524 return (0);
525 }
526
527 struct esm_sensor_map esm_sensors_esm2[] = {
528 { ESM_S_UNKNOWN, 0, "Motherboard" },
529 { ESM_S_TEMP, 0, "CPU 1" },
530 { ESM_S_TEMP, 0, "CPU 2" },
531 { ESM_S_TEMP, 0, "CPU 3" },
532 { ESM_S_TEMP, 0, "CPU 4" },
533
534 { ESM_S_TEMP, 0, "Mainboard" },
535 { ESM_S_TEMP, 0, "Ambient" },
536 { ESM_S_VOLTS, 0, "CPU 1 Core" },
537 { ESM_S_VOLTS, 0, "CPU 2 Core" },
538 { ESM_S_VOLTS, 0, "CPU 3 Core" },
539
540 { ESM_S_VOLTS, 0, "CPU 4 Core" },
541 { ESM_S_VOLTS, 0, "Motherboard +5V" },
542 { ESM_S_VOLTS, 0, "Motherboard +12V" },
543 { ESM_S_VOLTS, 0, "Motherboard +3.3V" },
544 { ESM_S_VOLTS, 0, "Motherboard +2.5V" },
545
546 { ESM_S_VOLTS, 0, "Motherboard GTL Term" },
547 { ESM_S_VOLTS, 0, "Motherboard Battery" },
548 { ESM_S_INTRUSION, 0, "Chassis Intrusion", },
549 { ESM_S_UNKNOWN, 0, "Chassis Fan Ctrl", },
550 { ESM_S_FANRPM, 0, "Fan 1" },
551
552 { ESM_S_FANRPM, 0, "Fan 2" },
553 { ESM_S_FANRPM, 0, "Fan 3" },
554 { ESM_S_FANRPM, 0, "Power Supply Fan" },
555 { ESM_S_VOLTS, 0, "CPU 1 cache" },
556 { ESM_S_VOLTS, 0, "CPU 2 cache" },
557
558 { ESM_S_VOLTS, 0, "CPU 3 cache" },
559 { ESM_S_VOLTS, 0, "CPU 4 cache" },
560 { ESM_S_UNKNOWN, 0, "Power Ctrl" },
561 { ESM_S_PWRSUP, 0, "Power Supply 1" },
562 { ESM_S_PWRSUP, 0, "Power Supply 2" },
563
564 { ESM_S_VOLTS, 0, "Mainboard +1.5V" },
565 { ESM_S_VOLTS, 0, "Motherboard +2.8V" },
566 { ESM_S_UNKNOWN, 0, "HotPlug Status" },
567 { ESM_S_PCISLOT, 0, "PCI Slot 1" },
568 { ESM_S_PCISLOT, 0, "PCI Slot 2" },
569
570 { ESM_S_PCISLOT, 0, "PCI Slot 3" },
571 { ESM_S_PCISLOT, 0, "PCI Slot 4" },
572 { ESM_S_PCISLOT, 0, "PCI Slot 5" },
573 { ESM_S_PCISLOT, 0, "PCI Slot 6" },
574 { ESM_S_PCISLOT, 0, "PCI Slot 7" },
575
576 { ESM_S_VOLTS, 0, "CPU 1 Cartridge" },
577 { ESM_S_VOLTS, 0, "CPU 2 Cartridge" },
578 { ESM_S_VOLTS, 0, "CPU 3 Cartridge" },
579 { ESM_S_VOLTS, 0, "CPU 4 Cartridge" },
580 { ESM_S_VOLTS, 0, "Gigabit NIC +1.8V" },
581
582 { ESM_S_VOLTS, 0, "Gigabit NIC +2.5V" },
583 { ESM_S_VOLTS, 0, "Memory +3.3V" },
584 { ESM_S_VOLTS, 0, "Video +2.5V" },
585 { ESM_S_PWRSUP, 0, "Power Supply 3" },
586 { ESM_S_FANRPM, 0, "Fan 4" },
587
588 { ESM_S_FANRPM, 0, "Power Supply Fan" },
589 { ESM_S_FANRPM, 0, "Power Supply Fan" },
590 { ESM_S_FANRPM, 0, "Power Supply Fan" },
591 { ESM_S_ACSWITCH, 0, "A/C Power Switch" },
592 { ESM_S_UNKNOWN, 0, "PS Over Temp" }
593 };
594
595 struct esm_sensor_map esm_sensors_backplane[] = {
596 { ESM_S_UNKNOWN, 0, "Backplane" },
597 { ESM_S_UNKNOWN, 0, "Backplane Control" },
598 { ESM_S_TEMP, 0, "Backplane Top" },
599 { ESM_S_TEMP, 0, "Backplane Bottom" },
600 { ESM_S_TEMP, 0, "Backplane Control Panel" },
601 { ESM_S_VOLTS, 0, "Backplane Battery" },
602 { ESM_S_VOLTS, 0, "Backplane +5V" },
603 { ESM_S_VOLTS, 0, "Backplane +12V" },
604 { ESM_S_VOLTS, 0, "Backplane Board" },
605 { ESM_S_INTRUSION, 0, "Backplane Intrusion" },
606 { ESM_S_UNKNOWN, 0, "Backplane Fan Control" },
607 { ESM_S_FANRPM, 0, "Backplane Fan 1" },
608 { ESM_S_FANRPM, 0, "Backplane Fan 2" },
609 { ESM_S_FANRPM, 0, "Backplane Fan 3" },
610 { ESM_S_SCSICONN, 0, "Backplane SCSI A Connected" },
611 { ESM_S_VOLTS, 0, "Backplane SCSI A External" },
612 { ESM_S_VOLTS, 0, "Backplane SCSI A Internal" },
613 { ESM_S_SCSICONN, 0, "Backplane SCSI B Connected" },
614 { ESM_S_VOLTS, 0, "Backplane SCSI B External" },
615 { ESM_S_VOLTS, 0, "Backplane SCSI B Internal" },
616 { ESM_S_DRIVES, 0, "Drive" },
617 { ESM_S_DRIVES, 4, "Drive" },
618 { ESM_S_DRIVE, 0, "Drive 0" },
619 { ESM_S_DRIVE, 0, "Drive 1" },
620 { ESM_S_DRIVE, 0, "Drive 2" },
621 { ESM_S_DRIVE, 0, "Drive 3" },
622 { ESM_S_DRIVE, 0, "Drive 4" },
623 { ESM_S_DRIVE, 0, "Drive 5" },
624 { ESM_S_DRIVE, 0, "Drive 6" },
625 { ESM_S_DRIVE, 0, "Drive 7" },
626 { ESM_S_UNKNOWN, 0, "Backplane Control 2" },
627 { ESM_S_VOLTS, 0, "Backplane +3.3V" },
628 };
629
630 struct esm_sensor_map esm_sensors_powerunit[] = {
631 { ESM_S_UNKNOWN, 0, "Power Unit" },
632 { ESM_S_VOLTSx10, 0, "Power Supply 1 +5V" },
633 { ESM_S_VOLTSx10, 0, "Power Supply 1 +12V" },
634 { ESM_S_VOLTSx10, 0, "Power Supply 1 +3.3V" },
635 { ESM_S_VOLTSx10, 0, "Power Supply 1 -5V" },
636
637 { ESM_S_VOLTSx10, 0, "Power Supply 1 -12V" },
638 { ESM_S_VOLTSx10, 0, "Power Supply 2 +5V" },
639 { ESM_S_VOLTSx10, 0, "Power Supply 2 +12V" },
640 { ESM_S_VOLTSx10, 0, "Power Supply 2 +3.3V" },
641 { ESM_S_VOLTSx10, 0, "Power Supply 2 -5V" },
642
643 { ESM_S_VOLTSx10, 0, "Power Supply 2 -12V" },
644 { ESM_S_VOLTSx10, 0, "Power Supply 3 +5V" },
645 { ESM_S_VOLTSx10, 0, "Power Supply 3 +12V" },
646 { ESM_S_VOLTSx10, 0, "Power Supply 3 +3.3V" },
647 { ESM_S_VOLTSx10, 0, "Power Supply 3 -5V" },
648
649 { ESM_S_VOLTSx10, 0, "Power Supply 3 -12V" },
650 { ESM_S_VOLTSx10, 0, "System Power Supply +5V" },
651 { ESM_S_VOLTSx10, 0, "System Power Supply +12V" },
652 { ESM_S_VOLTSx10, 0, "System Power Supply +3.3V" },
653 { ESM_S_VOLTSx10, 0, "System Power Supply -5V" },
654
655 { ESM_S_VOLTSx10, 0, "System Power Supply -12V" },
656 { ESM_S_VOLTSx10, 0, "System Power Supply +5V aux" },
657 { ESM_S_AMPS, 0, "Power Supply 1 +5V" },
658 { ESM_S_AMPS, 0, "Power Supply 1 +12V" },
659 { ESM_S_AMPS, 0, "Power Supply 1 +3.3V" },
660
661 { ESM_S_AMPS, 0, "Power Supply 2 +5V" },
662 { ESM_S_AMPS, 0, "Power Supply 2 +12V" },
663 { ESM_S_AMPS, 0, "Power Supply 2 +3.3V" },
664 { ESM_S_AMPS, 0, "Power Supply 3 +5V" },
665 { ESM_S_AMPS, 0, "Power Supply 3 +12V" },
666
667 { ESM_S_AMPS, 0, "Power Supply 3 +3.3V" },
668 { ESM_S_FANRPM, 0, "Power Supply 1 Fan" },
669 { ESM_S_FANRPM, 0, "Power Supply 2 Fan" },
670 { ESM_S_FANRPM, 0, "Power Supply 3 Fan" },
671 { ESM_S_PWRSUP, 0, "Power Supply 1" },
672
673 { ESM_S_PWRSUP, 0, "Power Supply 2" },
674 { ESM_S_PWRSUP, 0, "Power Supply 3" },
675 { ESM_S_UNKNOWN, 0, "PSPB Fan Control" },
676 { ESM_S_FANRPM, 0, "Fan 1" },
677 { ESM_S_FANRPM, 0, "Fan 2" },
678
679 { ESM_S_FANRPM, 0, "Fan 3" },
680 { ESM_S_FANRPM, 0, "Fan 4" },
681 { ESM_S_FANRPM, 0, "Fan 5" },
682 { ESM_S_FANRPM, 0, "Fan 6" },
683 { ESM_S_UNKNOWN, 0, "Fan Enclosure" },
684 };
685
686 void
687 esm_devmap(struct esm_softc *sc, struct esm_devmap *devmap)
688 {
689 struct esm_sensor_map *sensor_map;
690 const char *name = NULL, *fname = NULL;
691 int mapsize;
692
693 switch (devmap->dev_major) {
694 case ESM2_DEV_ESM2:
695 sensor_map = esm_sensors_esm2;
696
697 switch (devmap->dev_minor) {
698 case ESM2_DEV_ESM2_2300:
699 name = "PowerEdge 2300";
700 mapsize = 23;
701 break;
702 case ESM2_DEV_ESM2_4300:
703 name = "PowerEdge 4300";
704 mapsize = 27;
705 break;
706 case ESM2_DEV_ESM2_6300:
707 name = "PowerEdge 6300";
708 mapsize = 27;
709 break;
710 case ESM2_DEV_ESM2_6400:
711 name = "PowerEdge 6400";
712 mapsize = 44;
713 break;
714 case ESM2_DEV_ESM2_2550:
715 name = "PowerEdge 2550";
716 mapsize = 48;
717 break;
718 case ESM2_DEV_ESM2_4350:
719 name = "PowerEdge 4350";
720 mapsize = 27;
721 break;
722 case ESM2_DEV_ESM2_6350:
723 name = "PowerEdge 6350";
724 mapsize = 27;
725 break;
726 case ESM2_DEV_ESM2_6450:
727 name = "PowerEdge 6450";
728 mapsize = 44;
729 break;
730 case ESM2_DEV_ESM2_2400:
731 name = "PowerEdge 2400";
732 mapsize = 30;
733 break;
734 case ESM2_DEV_ESM2_4400:
735 name = "PowerEdge 4400";
736 mapsize = 44;
737 break;
738 case ESM2_DEV_ESM2_2500:
739 name = "PowerEdge 2500";
740 mapsize = 55;
741 break;
742 case ESM2_DEV_ESM2_2450:
743 name = "PowerEdge 2450";
744 mapsize = 27;
745 break;
746 case ESM2_DEV_ESM2_2400EX:
747 name = "PowerEdge 2400";
748 mapsize = 27;
749 break;
750 case ESM2_DEV_ESM2_2450EX:
751 name = "PowerEdge 2450";
752 mapsize = 44;
753 break;
754 default:
755 return;
756 }
757
758 fname = "Embedded Server Management";
759 break;
760
761 case ESM2_DEV_DRACII:
762 fname = "Dell Remote Assistance Card II";
763 break;
764
765 case ESM2_DEV_FRONT_PANEL:
766 fname = "Front Panel";
767 break;
768
769 case ESM2_DEV_BACKPLANE2:
770 sensor_map = esm_sensors_backplane;
771 mapsize = 22;
772
773 fname = "Primary System Backplane";
774 break;
775
776 case ESM2_DEV_POWERUNIT2:
777 sensor_map = esm_sensors_powerunit;
778 mapsize = sizeof(esm_sensors_powerunit) /
779 sizeof(esm_sensors_powerunit[0]);
780
781 fname = "Power Unit";
782 break;
783
784 case ESM2_DEV_ENCL2_BACKPLANE:
785 case ESM2_DEV_ENCL1_BACKPLANE:
786 fname = "Enclosure Backplane";
787 break;
788
789 case ESM2_DEV_ENCL2_POWERUNIT:
790 case ESM2_DEV_ENCL1_POWERUNIT:
791 fname = "Enclosure Powerunit";
792 break;
793
794 case ESM2_DEV_HPPCI:
795 fname = "HPPCI";
796 break;
797
798 case ESM2_DEV_BACKPLANE3:
799 sensor_map = esm_sensors_backplane;
800 mapsize = sizeof(esm_sensors_backplane) /
801 sizeof(esm_sensors_backplane[0]);
802
803 fname = "Primary System Backplane";
804 break;
805
806 default:
807 return;
808 }
809
810 printf("%s: %s%s%s %d.%d\n", DEVNAME(sc),
811 name ? name : "", name ? " " : "", fname,
812 devmap->rev_major, devmap->rev_minor);
813
814 esm_make_sensors(sc, devmap, sensor_map, mapsize);
815 }
816
817 void
818 esm_make_sensors(struct esm_softc *sc, struct esm_devmap *devmap,
819 struct esm_sensor_map *sensor_map, int mapsize)
820 {
821 struct esm_smb_req req;
822 struct esm_smb_resp resp;
823 struct esm_smb_resp_val *val = &resp.resp_val;
824 struct esm_sensor *es;
825 struct ksensor *s;
826 int nsensors, i, j;
827 const char *psulabels[] = {
828 "AC", "SW", "OK", "ON", "FFAN", "OTMP"
829 };
830
831 memset(&req, 0, sizeof(req));
832 req.h_cmd = ESM2_CMD_SMB_XMIT_RECV;
833 req.h_dev = devmap->index;
834 req.h_txlen = sizeof(req.req_val);
835 req.h_rxlen = sizeof(resp.resp_val);
836
837 req.req_val.v_cmd = ESM2_SMB_SENSOR_VALUE;
838
839 for (i = 0; i < mapsize; i++) {
840 req.req_val.v_sensor = i;
841 if (esm_smb_cmd(sc, &req, &resp, 1, 0) != 0)
842 continue;
843
844 DPRINTFN(1, "%s: dev: 0x%02x sensor: %d (%s) "
845 "reading: 0x%04x status: 0x%02x cksum: 0x%02x\n",
846 DEVNAME(sc), devmap->index, i, sensor_map[i].name,
847 val->v_reading, val->v_status, val->v_checksum);
848
849 switch (sensor_map[i].type) {
850 case ESM_S_PWRSUP:
851 if (val->v_status == 0x00)
852 continue;
853 break;
854 default:
855 if (!(val->v_status & ESM2_VS_VALID))
856 continue;
857 break;
858 }
859
860 es = malloc(sizeof(struct esm_sensor), M_DEVBUF, M_NOWAIT);
861 if (es == NULL)
862 return;
863
864 memset(es, 0, sizeof(struct esm_sensor));
865 es->es_dev = devmap->index;
866 es->es_id = i;
867 es->es_type = sensor_map[i].type;
868
869 switch (es->es_type) {
870 case ESM_S_DRIVES:
871
872
873
874
875 nsensors = 4;
876 s = malloc(sizeof(struct ksensor) * nsensors, M_DEVBUF,
877 M_NOWAIT);
878 if (s == NULL) {
879 free(es, M_DEVBUF);
880 return;
881 }
882 memset(s, 0, sizeof(struct ksensor) * nsensors);
883
884 for (j = 0; j < nsensors; j++) {
885 snprintf(s[j].desc, sizeof(s[j].desc), "%s %d",
886 sensor_map[i].name, sensor_map[i].arg + j);
887 }
888 break;
889 case ESM_S_PWRSUP:
890
891
892
893
894 nsensors = 6;
895 s = malloc(sizeof(struct ksensor) * nsensors, M_DEVBUF,
896 M_NOWAIT);
897 if (s == NULL) {
898 free(es, M_DEVBUF);
899 return;
900 }
901 memset(s, 0, sizeof(struct ksensor) * nsensors);
902
903 for (j = 0; j < nsensors; j++) {
904 snprintf(s[j].desc, sizeof(s[j].desc), "%s %s",
905 sensor_map[i].name, psulabels[j]);
906 }
907 break;
908
909 case ESM_S_TEMP:
910 case ESM_S_FANRPM:
911 case ESM_S_AMPS:
912 case ESM_S_VOLTS:
913 case ESM_S_VOLTSx10:
914 if (esm_thresholds(sc, devmap, es) != 0) {
915 free(es, M_DEVBUF);
916 continue;
917 }
918
919
920 default:
921 nsensors = 1;
922 s = malloc(sizeof(struct ksensor), M_DEVBUF, M_NOWAIT);
923 if (s == NULL) {
924 free(es, M_DEVBUF);
925 return;
926 }
927 memset(s, 0, sizeof(struct ksensor));
928
929 strlcpy(s->desc, sensor_map[i].name, sizeof(s->desc));
930 break;
931 }
932
933 for (j = 0; j < nsensors; j++) {
934 s[j].type = esm_typemap[es->es_type];
935 sensor_attach(&sc->sc_sensordev, &s[j]);
936 }
937
938 es->es_sensor = s;
939 TAILQ_INSERT_TAIL(&sc->sc_sensors, es, es_entry);
940 }
941 }
942
943 int
944 esm_thresholds(struct esm_softc *sc, struct esm_devmap *devmap,
945 struct esm_sensor *es)
946 {
947 struct esm_smb_req req;
948 struct esm_smb_resp resp;
949 struct esm_smb_resp_thr *thr = &resp.resp_thr;
950
951 memset(&req, 0, sizeof(req));
952 req.h_cmd = ESM2_CMD_SMB_XMIT_RECV;
953 req.h_dev = devmap->index;
954 req.h_txlen = sizeof(req.req_thr);
955 req.h_rxlen = sizeof(resp.resp_thr);
956
957 req.req_thr.t_cmd = ESM2_SMB_SENSOR_THRESHOLDS;
958 req.req_thr.t_sensor = es->es_id;
959
960 if (esm_smb_cmd(sc, &req, &resp, 1, 0) != 0)
961 return (1);
962
963 DPRINTFN(2, "%s: dev: %d sensor: %d lo fail: %d hi fail: %d "
964 "lo warn: %d hi warn: %d hysterisis: %d checksum: 0x%02x\n",
965 DEVNAME(sc), devmap->index, es->es_id, thr->t_lo_fail,
966 thr->t_hi_fail, thr->t_lo_warn, thr->t_hi_warn, thr->t_hysterisis,
967 thr->t_checksum);
968
969 es->es_thresholds.th_lo_crit = thr->t_lo_fail;
970 es->es_thresholds.th_lo_warn = thr->t_lo_warn;
971 es->es_thresholds.th_hi_warn = thr->t_hi_warn;
972 es->es_thresholds.th_hi_crit = thr->t_hi_fail;
973
974 return (0);
975 }
976
977 int
978 esm_bmc_ready(struct esm_softc *sc, int port, u_int8_t mask, u_int8_t val,
979 int wait)
980 {
981 unsigned int count = wait ? 0 : 0xfffff;
982
983 do {
984 if ((EREAD(sc, port) & mask) == val)
985 return (0);
986 } while (count++ < 0xfffff);
987
988 return (1);
989 }
990
991 int
992 esm_cmd(struct esm_softc *sc, void *cmd, size_t cmdlen, void *resp,
993 size_t resplen, int wait, int step)
994 {
995 u_int8_t *tx = (u_int8_t *)cmd;
996 u_int8_t *rx = (u_int8_t *)resp;
997 int i;
998
999 switch (step) {
1000 case 0:
1001 case 1:
1002
1003 if (esm_bmc_ready(sc, ESM2_CTRL_REG, ESM2_TC_READY,
1004 0, wait) != 0)
1005 return (1);
1006
1007
1008 ECTRLWR(sc, ESM2_TC_CLR_WPTR);
1009 for (i = 0; i < cmdlen; i++) {
1010 DPRINTFN(2, "write: %.2x\n", *tx);
1011 EDATAWR(sc, *tx);
1012 tx++;
1013 }
1014
1015
1016 ECTRLWR(sc, ESM2_TC_H2ECDB);
1017
1018 case 2:
1019
1020 if (esm_bmc_ready(sc, ESM2_CTRL_REG, ESM2_TC_EC2HDB,
1021 ESM2_TC_EC2HDB, wait) != 0)
1022 return (2);
1023
1024
1025 ECTRLWR(sc, ESM2_TC_HOSTBUSY);
1026 ECTRLWR(sc, ESM2_TC_EC2HDB);
1027
1028
1029 ECTRLWR(sc, ESM2_TC_CLR_RPTR);
1030 for (i = 0; i < resplen; i++) {
1031 *rx = EDATARD(sc);
1032 DPRINTFN(2, "read = %.2x\n", *rx);
1033 rx++;
1034 }
1035
1036
1037 ECTRLWR(sc, ESM2_TC_HOSTBUSY);
1038 break;
1039 }
1040
1041 return (0);
1042 }
1043
1044 int
1045 esm_smb_cmd(struct esm_softc *sc, struct esm_smb_req *req,
1046 struct esm_smb_resp *resp, int wait, int step)
1047 {
1048 int err;
1049
1050 memset(resp, 0, sizeof(struct esm_smb_resp));
1051
1052 err = esm_cmd(sc, req, sizeof(req->hdr) + req->h_txlen, resp,
1053 sizeof(resp->hdr) + req->h_rxlen, wait, step);
1054 if (err)
1055 return (err);
1056
1057 if (resp->h_status != 0 || resp->h_i2csts != 0) {
1058 DPRINTFN(3, "%s: dev: 0x%02x error status: 0x%02x "
1059 "i2csts: 0x%02x procsts: 0x%02x tx: 0x%02x rx: 0x%02x\n",
1060 __func__, req->h_dev, resp->h_status, resp->h_i2csts,
1061 resp->h_procsts, resp->h_rx, resp->h_tx);
1062 return (1);
1063 }
1064
1065 return (0);
1066 }
1067
1068 int64_t
1069 esm_val2temp(u_int16_t value)
1070 {
1071 return (((int64_t)value * 100000) + 273150000);
1072 }
1073
1074 int64_t
1075 esm_val2volts(u_int16_t value)
1076 {
1077 return ((int64_t)value * 1000);
1078 }
1079
1080 int64_t
1081 esm_val2amps(u_int16_t value)
1082 {
1083 return ((int64_t)value * 100000);
1084 }