This source file includes following definitions.
- safte_match
- safte_attach
- safte_detach
- safte_read_config
- safte_read_encstat
- safte_ioctl
- safte_bio_blink
- safte_temp2uK
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include "bio.h"
20
21 #include <sys/param.h>
22 #include <sys/systm.h>
23 #include <sys/device.h>
24 #include <sys/scsiio.h>
25 #include <sys/malloc.h>
26 #include <sys/proc.h>
27 #include <sys/rwlock.h>
28 #include <sys/queue.h>
29 #include <sys/sensors.h>
30
31 #if NBIO > 0
32 #include <dev/biovar.h>
33 #endif
34
35 #include <scsi/scsi_all.h>
36 #include <scsi/scsiconf.h>
37
38 #include <scsi/safte.h>
39
40 #ifdef SAFTE_DEBUG
41 #define DPRINTF(x) do { if (safte_debug) printf x ; } while (0)
42 int safte_debug = 1;
43 #else
44 #define DPRINTF(x)
45 #endif
46
47
48 int safte_match(struct device *, void *, void *);
49 void safte_attach(struct device *, struct device *, void *);
50 int safte_detach(struct device *, int);
51
52 struct safte_sensor {
53 struct ksensor se_sensor;
54 enum {
55 SAFTE_T_FAN,
56 SAFTE_T_PWRSUP,
57 SAFTE_T_DOORLOCK,
58 SAFTE_T_ALARM,
59 SAFTE_T_TEMP
60 } se_type;
61 u_int8_t *se_field;
62 };
63
64 struct safte_softc {
65 struct device sc_dev;
66 struct scsi_link *sc_link;
67 struct rwlock sc_lock;
68
69 u_int sc_encbuflen;
70 u_char *sc_encbuf;
71
72 int sc_nsensors;
73 struct safte_sensor *sc_sensors;
74 struct ksensordev sc_sensordev;
75 struct sensor_task *sc_sensortask;
76
77 int sc_celsius;
78 int sc_ntemps;
79 struct safte_sensor *sc_temps;
80 u_int16_t *sc_temperrs;
81
82 #if NBIO > 0
83 int sc_nslots;
84 u_int8_t *sc_slots;
85 #endif
86 };
87
88 struct cfattach safte_ca = {
89 sizeof(struct safte_softc), safte_match, safte_attach, safte_detach
90 };
91
92 struct cfdriver safte_cd = {
93 NULL, "safte", DV_DULL
94 };
95
96 #define DEVNAME(s) ((s)->sc_dev.dv_xname)
97
98 int safte_read_config(struct safte_softc *);
99 void safte_read_encstat(void *);
100
101 #if NBIO > 0
102 int safte_ioctl(struct device *, u_long, caddr_t);
103 int safte_bio_blink(struct safte_softc *, struct bioc_blink *);
104 #endif
105
106 int64_t safte_temp2uK(u_int8_t, int);
107
108 int
109 safte_match(struct device *parent, void *match, void *aux)
110 {
111 struct scsi_attach_args *sa = aux;
112 struct scsi_inquiry_data *inq = sa->sa_inqbuf;
113 struct scsi_inquiry_data inqbuf;
114 struct scsi_inquiry cmd;
115 struct safte_inq *si = (struct safte_inq *)&inqbuf.extra;
116 int length, flags;
117
118 if (inq == NULL)
119 return (0);
120
121
122 if ((inq->device & SID_TYPE) == T_PROCESSOR &&
123 SCSISPC(inq->version) == 3)
124 return (2);
125
126 if ((inq->device & SID_TYPE) != T_PROCESSOR ||
127 SCSISPC(inq->version) != 2 ||
128 (inq->response_format & SID_ANSII) != 2)
129 return (0);
130
131 length = inq->additional_length + SAFTE_EXTRA_OFFSET;
132 if (length < SAFTE_INQ_LEN)
133 return (0);
134 if (length > sizeof(inqbuf))
135 length = sizeof(inqbuf);
136
137 memset(&cmd, 0, sizeof(cmd));
138 cmd.opcode = INQUIRY;
139 _lto2b(length, cmd.length);
140
141 memset(&inqbuf, 0, sizeof(inqbuf));
142 memset(&inqbuf.extra, ' ', sizeof(inqbuf.extra));
143
144 flags = SCSI_DATA_IN;
145 if (cold)
146 flags |= SCSI_AUTOCONF;
147
148 if (scsi_scsi_cmd(sa->sa_sc_link, (struct scsi_generic *)&cmd,
149 sizeof(cmd), (u_char *)&inqbuf, length, 2, 10000, NULL,
150 flags) != 0)
151 return (0);
152
153 if (memcmp(si->ident, SAFTE_IDENT, sizeof(si->ident)) == 0)
154 return (2);
155
156 return (0);
157 }
158
159 void
160 safte_attach(struct device *parent, struct device *self, void *aux)
161 {
162 struct safte_softc *sc = (struct safte_softc *)self;
163 struct scsi_attach_args *sa = aux;
164 int i = 0;
165
166 sc->sc_link = sa->sa_sc_link;
167 sa->sa_sc_link->device_softc = sc;
168 rw_init(&sc->sc_lock, DEVNAME(sc));
169
170 printf("\n");
171
172 sc->sc_encbuf = NULL;
173 sc->sc_nsensors = 0;
174 #if NBIO > 0
175 sc->sc_nslots = 0;
176 #endif
177
178 if (safte_read_config(sc) != 0) {
179 printf("%s: unable to read enclosure configuration\n",
180 DEVNAME(sc));
181 return;
182 }
183
184 if (sc->sc_nsensors > 0) {
185 sc->sc_sensortask = sensor_task_register(sc,
186 safte_read_encstat, 10);
187 if (sc->sc_sensortask == NULL) {
188 printf("%s: unable to register update task\n",
189 DEVNAME(sc));
190 sc->sc_nsensors = sc->sc_ntemps = 0;
191 free(sc->sc_sensors, M_DEVBUF);
192 } else {
193 for (i = 0; i < sc->sc_nsensors; i++)
194 sensor_attach(&sc->sc_sensordev,
195 &sc->sc_sensors[i].se_sensor);
196 sensordev_install(&sc->sc_sensordev);
197 }
198 }
199
200 #if NBIO > 0
201 if (sc->sc_nslots > 0 &&
202 bio_register(self, safte_ioctl) != 0) {
203 printf("%s: unable to register ioctl with bio\n", DEVNAME(sc));
204 sc->sc_nslots = 0;
205 } else
206 i++;
207 #endif
208
209 if (i)
210 safte_read_encstat(sc);
211 else {
212 free(sc->sc_encbuf, M_DEVBUF);
213 sc->sc_encbuf = NULL;
214 }
215 }
216
217 int
218 safte_detach(struct device *self, int flags)
219 {
220 struct safte_softc *sc = (struct safte_softc *)self;
221 int i;
222
223 rw_enter_write(&sc->sc_lock);
224
225 #if NBIO > 0
226 if (sc->sc_nslots > 0)
227 bio_unregister(self);
228 #endif
229
230 if (sc->sc_nsensors > 0) {
231 sensordev_deinstall(&sc->sc_sensordev);
232 sensor_task_unregister(sc->sc_sensortask);
233
234 for (i = 0; i < sc->sc_nsensors; i++)
235 sensor_detach(&sc->sc_sensordev,
236 &sc->sc_sensors[i].se_sensor);
237 free(sc->sc_sensors, M_DEVBUF);
238 }
239
240 if (sc->sc_encbuf != NULL)
241 free(sc->sc_encbuf, M_DEVBUF);
242
243 rw_exit_write(&sc->sc_lock);
244
245 return (0);
246 }
247
248 int
249 safte_read_config(struct safte_softc *sc)
250 {
251 struct safte_readbuf_cmd cmd;
252 struct safte_config config;
253 struct safte_sensor *s;
254 int flags, i, j;
255
256 memset(&cmd, 0, sizeof(cmd));
257 cmd.opcode = READ_BUFFER;
258 cmd.flags |= SAFTE_RD_MODE;
259 cmd.bufferid = SAFTE_RD_CONFIG;
260 cmd.length = htobe16(sizeof(config));
261 flags = SCSI_DATA_IN;
262 #ifndef SCSIDEBUG
263 flags |= SCSI_SILENT;
264 #endif
265
266 if (cold)
267 flags |= SCSI_AUTOCONF;
268
269 if (scsi_scsi_cmd(sc->sc_link, (struct scsi_generic *)&cmd,
270 sizeof(cmd), (u_char *)&config, sizeof(config), 2, 30000, NULL,
271 flags) != 0)
272 return (1);
273
274 DPRINTF(("%s: nfans: %d npwrsup: %d nslots: %d doorlock: %d ntemps: %d"
275 " alarm: %d celsius: %d ntherm: %d\n", DEVNAME(sc), config.nfans,
276 config.npwrsup, config.nslots, config.doorlock, config.ntemps,
277 config.alarm, SAFTE_CFG_CELSIUS(config.therm),
278 SAFTE_CFG_NTHERM(config.therm)));
279
280 sc->sc_encbuflen = config.nfans * sizeof(u_int8_t) +
281 config.npwrsup * sizeof(u_int8_t) +
282 config.nslots * sizeof(u_int8_t) +
283 sizeof(u_int8_t) +
284 sizeof(u_int8_t) +
285 config.ntemps * sizeof(u_int8_t) +
286 sizeof(u_int16_t);
287
288 sc->sc_encbuf = malloc(sc->sc_encbuflen, M_DEVBUF, M_NOWAIT);
289 if (sc->sc_encbuf == NULL)
290 return (1);
291
292 sc->sc_nsensors = config.nfans + config.npwrsup + config.ntemps +
293 (config.doorlock ? 1 : 0) + (config.alarm ? 1 : 0);
294
295 sc->sc_sensors = malloc(sc->sc_nsensors * sizeof(struct safte_sensor),
296 M_DEVBUF, M_NOWAIT);
297 if (sc->sc_sensors == NULL) {
298 free(sc->sc_encbuf, M_DEVBUF);
299 sc->sc_encbuf = NULL;
300 sc->sc_nsensors = 0;
301 return (1);
302 }
303
304 strlcpy(sc->sc_sensordev.xname, DEVNAME(sc),
305 sizeof(sc->sc_sensordev.xname));
306
307 memset(sc->sc_sensors, 0,
308 sc->sc_nsensors * sizeof(struct safte_sensor));
309 s = sc->sc_sensors;
310
311 for (i = 0; i < config.nfans; i++) {
312 s->se_type = SAFTE_T_FAN;
313 s->se_field = (u_int8_t *)(sc->sc_encbuf + i);
314 s->se_sensor.type = SENSOR_INDICATOR;
315 snprintf(s->se_sensor.desc, sizeof(s->se_sensor.desc),
316 "Fan%d", i);
317
318 s++;
319 }
320 j = config.nfans;
321
322 for (i = 0; i < config.npwrsup; i++) {
323 s->se_type = SAFTE_T_PWRSUP;
324 s->se_field = (u_int8_t *)(sc->sc_encbuf + j + i);
325 s->se_sensor.type = SENSOR_INDICATOR;
326 snprintf(s->se_sensor.desc, sizeof(s->se_sensor.desc),
327 "PSU%d", i);
328
329 s++;
330 }
331 j += config.npwrsup;
332
333 #if NBIO > 0
334 sc->sc_nslots = config.nslots;
335 sc->sc_slots = (u_int8_t *)(sc->sc_encbuf + j);
336 #endif
337 j += config.nslots;
338
339 if (config.doorlock) {
340 s->se_type = SAFTE_T_DOORLOCK;
341 s->se_field = (u_int8_t *)(sc->sc_encbuf + j);
342 s->se_sensor.type = SENSOR_INDICATOR;
343 strlcpy(s->se_sensor.desc, "doorlock",
344 sizeof(s->se_sensor.desc));
345
346 s++;
347 }
348 j++;
349
350 if (config.alarm) {
351 s->se_type = SAFTE_T_ALARM;
352 s->se_field = (u_int8_t *)(sc->sc_encbuf + j);
353 s->se_sensor.type = SENSOR_INDICATOR;
354 strlcpy(s->se_sensor.desc, "alarm", sizeof(s->se_sensor.desc));
355
356 s++;
357 }
358 j++;
359
360
361
362
363
364 sc->sc_ntemps = (config.ntemps > 15) ? 15 : config.ntemps;
365 sc->sc_temps = s;
366 sc->sc_celsius = SAFTE_CFG_CELSIUS(config.therm);
367 for (i = 0; i < config.ntemps; i++) {
368 s->se_type = SAFTE_T_TEMP;
369 s->se_field = (u_int8_t *)(sc->sc_encbuf + j + i);
370 s->se_sensor.type = SENSOR_TEMP;
371
372 s++;
373 }
374 j += config.ntemps;
375
376 sc->sc_temperrs = (u_int16_t *)(sc->sc_encbuf + j);
377
378 return (0);
379 }
380
381 void
382 safte_read_encstat(void *arg)
383 {
384 struct safte_softc *sc = (struct safte_softc *)arg;
385 struct safte_readbuf_cmd cmd;
386 int flags, i;
387 struct safte_sensor *s;
388 u_int16_t oot;
389
390 rw_enter_write(&sc->sc_lock);
391
392 memset(&cmd, 0, sizeof(cmd));
393 cmd.opcode = READ_BUFFER;
394 cmd.flags |= SAFTE_RD_MODE;
395 cmd.bufferid = SAFTE_RD_ENCSTAT;
396 cmd.length = htobe16(sc->sc_encbuflen);
397 flags = SCSI_DATA_IN;
398 #ifndef SCSIDEBUG
399 flags |= SCSI_SILENT;
400 #endif
401
402 if (cold)
403 flags |= SCSI_AUTOCONF;
404
405 if (scsi_scsi_cmd(sc->sc_link, (struct scsi_generic *)&cmd,
406 sizeof(cmd), sc->sc_encbuf, sc->sc_encbuflen, 2, 30000, NULL,
407 flags) != 0) {
408 rw_exit_write(&sc->sc_lock);
409 return;
410 }
411
412 for (i = 0; i < sc->sc_nsensors; i++) {
413 s = &sc->sc_sensors[i];
414 s->se_sensor.flags &= ~SENSOR_FUNKNOWN;
415
416 DPRINTF(("%s: %d type: %d field: 0x%02x\n", DEVNAME(sc), i,
417 s->se_type, *s->se_field));
418
419 switch (s->se_type) {
420 case SAFTE_T_FAN:
421 switch (*s->se_field) {
422 case SAFTE_FAN_OP:
423 s->se_sensor.value = 1;
424 s->se_sensor.status = SENSOR_S_OK;
425 break;
426 case SAFTE_FAN_MF:
427 s->se_sensor.value = 0;
428 s->se_sensor.status = SENSOR_S_CRIT;
429 break;
430 case SAFTE_FAN_NOTINST:
431 case SAFTE_FAN_UNKNOWN:
432 default:
433 s->se_sensor.value = 0;
434 s->se_sensor.status = SENSOR_S_UNKNOWN;
435 s->se_sensor.flags |= SENSOR_FUNKNOWN;
436 break;
437 }
438 break;
439
440 case SAFTE_T_PWRSUP:
441 switch (*s->se_field) {
442 case SAFTE_PWR_OP_ON:
443 s->se_sensor.value = 1;
444 s->se_sensor.status = SENSOR_S_OK;
445 break;
446 case SAFTE_PWR_OP_OFF:
447 s->se_sensor.value = 0;
448 s->se_sensor.status = SENSOR_S_OK;
449 break;
450 case SAFTE_PWR_MF_ON:
451 s->se_sensor.value = 1;
452 s->se_sensor.status = SENSOR_S_CRIT;
453 break;
454 case SAFTE_PWR_MF_OFF:
455 s->se_sensor.value = 0;
456 s->se_sensor.status = SENSOR_S_CRIT;
457 break;
458 case SAFTE_PWR_NOTINST:
459 case SAFTE_PWR_PRESENT:
460 case SAFTE_PWR_UNKNOWN:
461 s->se_sensor.value = 0;
462 s->se_sensor.status = SENSOR_S_UNKNOWN;
463 s->se_sensor.flags |= SENSOR_FUNKNOWN;
464 break;
465 }
466 break;
467
468 case SAFTE_T_DOORLOCK:
469 switch (*s->se_field) {
470 case SAFTE_DOOR_LOCKED:
471 s->se_sensor.value = 1;
472 s->se_sensor.status = SENSOR_S_OK;
473 break;
474 case SAFTE_DOOR_UNLOCKED:
475 s->se_sensor.value = 0;
476 s->se_sensor.status = SENSOR_S_CRIT;
477 break;
478 case SAFTE_DOOR_UNKNOWN:
479 s->se_sensor.value = 0;
480 s->se_sensor.status = SENSOR_S_CRIT;
481 s->se_sensor.flags |= SENSOR_FUNKNOWN;
482 break;
483 }
484 break;
485
486 case SAFTE_T_ALARM:
487 switch (*s->se_field) {
488 case SAFTE_SPKR_OFF:
489 s->se_sensor.value = 0;
490 s->se_sensor.status = SENSOR_S_OK;
491 break;
492 case SAFTE_SPKR_ON:
493 s->se_sensor.value = 1;
494 s->se_sensor.status = SENSOR_S_CRIT;
495 break;
496 }
497 break;
498
499 case SAFTE_T_TEMP:
500 s->se_sensor.value = safte_temp2uK(*s->se_field,
501 sc->sc_celsius);
502 break;
503 }
504 }
505
506 oot = betoh16(*sc->sc_temperrs);
507 for (i = 0; i < sc->sc_ntemps; i++)
508 sc->sc_temps[i].se_sensor.status =
509 (oot & (1 << i)) ? SENSOR_S_CRIT : SENSOR_S_OK;
510
511 rw_exit_write(&sc->sc_lock);
512 }
513
514 #if NBIO > 0
515 int
516 safte_ioctl(struct device *dev, u_long cmd, caddr_t addr)
517 {
518 struct safte_softc *sc = (struct safte_softc *)dev;
519 int error = 0;
520
521 switch (cmd) {
522 case BIOCBLINK:
523 error = safte_bio_blink(sc, (struct bioc_blink *)addr);
524 break;
525
526 default:
527 error = EINVAL;
528 break;
529 }
530
531 return (error);
532 }
533
534 int
535 safte_bio_blink(struct safte_softc *sc, struct bioc_blink *blink)
536 {
537 struct safte_writebuf_cmd cmd;
538 struct safte_slotop *op;
539 int slot;
540 int flags;
541 int wantblink;
542
543 switch (blink->bb_status) {
544 case BIOC_SBBLINK:
545 wantblink = 1;
546 break;
547 case BIOC_SBUNBLINK:
548 wantblink = 0;
549 break;
550 default:
551 return (EINVAL);
552 }
553
554 rw_enter_read(&sc->sc_lock);
555 for (slot = 0; slot < sc->sc_nslots; slot++) {
556 if (sc->sc_slots[slot] == blink->bb_target)
557 break;
558 }
559 rw_exit_read(&sc->sc_lock);
560
561 if (slot >= sc->sc_nslots)
562 return (ENODEV);
563
564 op = malloc(sizeof(struct safte_slotop), M_TEMP, 0);
565
566 memset(op, 0, sizeof(struct safte_slotop));
567 op->opcode = SAFTE_WRITE_SLOTOP;
568 op->slot = slot;
569 op->flags |= wantblink ? SAFTE_SLOTOP_IDENTIFY : 0;
570
571 memset(&cmd, 0, sizeof(cmd));
572 cmd.opcode = WRITE_BUFFER;
573 cmd.flags |= SAFTE_WR_MODE;
574 cmd.length = htobe16(sizeof(struct safte_slotop));
575 flags = SCSI_DATA_OUT;
576 #ifndef SCSIDEBUG
577 flags |= SCSI_SILENT;
578 #endif
579 if (cold)
580 flags |= SCSI_AUTOCONF;
581
582 if (scsi_scsi_cmd(sc->sc_link, (struct scsi_generic *)&cmd,
583 sizeof(cmd), (u_char *)op, sizeof(struct safte_slotop),
584 2, 30000, NULL, flags) != 0) {
585 free(op, M_TEMP);
586 return (EIO);
587 }
588
589 free(op, M_TEMP);
590
591 return (0);
592 }
593 #endif
594
595 int64_t
596 safte_temp2uK(u_int8_t measured, int celsius)
597 {
598 int64_t temp;
599
600 temp = (int64_t)measured;
601 temp += SAFTE_TEMP_OFFSET;
602 temp *= 1000000;
603 if (!celsius)
604 temp = ((temp - 32000000) * 5) / 9;
605
606 temp += 273150000;
607
608 return (temp);
609 }