1 /* $OpenBSD: safte.c,v 1.68 2024/09/04 07:54:53 mglocker Exp $ */
2
3 /*
4 * Copyright (c) 2005 David Gwynne <dlg@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
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/pool.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 /* NBIO > 0 */
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) /* x */
45 #endif /* SAFTE_DEBUG */
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_int8_t *sc_temperrs;
81
82 #if NBIO > 0
83 int sc_nslots;
84 u_int8_t *sc_slots;
85 #endif /* NBIO > 0 */
86 };
87
88 const 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 /* NBIO > 0 */
105
106 int64_t safte_temp2uK(u_int8_t, int);
107
108 int
safte_match(struct device * parent,void * match,void * aux)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_sc_link->inqdata;
113 struct safte_inq *si;
114
115 /* Match on Dell enclosures. */
116 if ((inq->device & SID_TYPE) == T_PROCESSOR &&
117 SID_ANSII_REV(inq) == SCSI_REV_SPC)
118 return 2;
119
120 if ((inq->device & SID_TYPE) != T_PROCESSOR ||
121 SID_ANSII_REV(inq) != SCSI_REV_2 ||
122 SID_RESPONSE_FORMAT(inq) != SID_SCSI2_RESPONSE)
123 return 0;
124
125 if (inq->additional_length < SID_SCSI2_ALEN + sizeof(*si))
126 return 0;
127
128 si = (struct safte_inq *)&inq->extra;
129 if (memcmp(si->ident, SAFTE_IDENT, sizeof(si->ident)) == 0)
130 return 2;
131
132 return 0;
133 }
134
135 void
safte_attach(struct device * parent,struct device * self,void * aux)136 safte_attach(struct device *parent, struct device *self, void *aux)
137 {
138 struct safte_softc *sc = (struct safte_softc *)self;
139 struct scsi_attach_args *sa = aux;
140 int i = 0;
141
142 sc->sc_link = sa->sa_sc_link;
143 sa->sa_sc_link->device_softc = sc;
144 rw_init(&sc->sc_lock, DEVNAME(sc));
145
146 printf("\n");
147
148 sc->sc_encbuf = NULL;
149 sc->sc_nsensors = 0;
150 #if NBIO > 0
151 sc->sc_nslots = 0;
152 #endif /* NBIO > 0 */
153
154 if (safte_read_config(sc) != 0) {
155 printf("%s: unable to read enclosure configuration\n",
156 DEVNAME(sc));
157 return;
158 }
159
160 if (sc->sc_nsensors > 0) {
161 sc->sc_sensortask = sensor_task_register(sc,
162 safte_read_encstat, 10);
163 if (sc->sc_sensortask == NULL) {
164 printf("%s: unable to register update task\n",
165 DEVNAME(sc));
166 free(sc->sc_sensors, M_DEVBUF,
167 sc->sc_nsensors * sizeof(struct safte_sensor));
168 sc->sc_nsensors = sc->sc_ntemps = 0;
169 } else {
170 for (i = 0; i < sc->sc_nsensors; i++)
171 sensor_attach(&sc->sc_sensordev,
172 &sc->sc_sensors[i].se_sensor);
173 sensordev_install(&sc->sc_sensordev);
174 }
175 }
176
177 #if NBIO > 0
178 if (sc->sc_nslots > 0 &&
179 bio_register(self, safte_ioctl) != 0) {
180 printf("%s: unable to register ioctl with bio\n", DEVNAME(sc));
181 sc->sc_nslots = 0;
182 } else
183 i++;
184 #endif /* NBIO > 0 */
185
186 if (i) /* if we're doing something, then preinit encbuf and sensors */
187 safte_read_encstat(sc);
188 else {
189 dma_free(sc->sc_encbuf, sc->sc_encbuflen);
190 sc->sc_encbuf = NULL;
191 }
192 }
193
194 int
safte_detach(struct device * self,int flags)195 safte_detach(struct device *self, int flags)
196 {
197 struct safte_softc *sc = (struct safte_softc *)self;
198 int i;
199
200 rw_enter_write(&sc->sc_lock);
201
202 #if NBIO > 0
203 if (sc->sc_nslots > 0)
204 bio_unregister(self);
205 #endif /* NBIO > 0 */
206
207 if (sc->sc_nsensors > 0) {
208 sensordev_deinstall(&sc->sc_sensordev);
209 sensor_task_unregister(sc->sc_sensortask);
210
211 for (i = 0; i < sc->sc_nsensors; i++)
212 sensor_detach(&sc->sc_sensordev,
213 &sc->sc_sensors[i].se_sensor);
214 free(sc->sc_sensors, M_DEVBUF,
215 sc->sc_nsensors * sizeof(struct safte_sensor));
216 }
217
218 if (sc->sc_encbuf != NULL)
219 dma_free(sc->sc_encbuf, sc->sc_encbuflen);
220
221 rw_exit_write(&sc->sc_lock);
222
223 return 0;
224 }
225
226 int
safte_read_config(struct safte_softc * sc)227 safte_read_config(struct safte_softc *sc)
228 {
229 struct safte_config *config = NULL;
230 struct safte_readbuf_cmd *cmd;
231 struct safte_sensor *s;
232 struct scsi_xfer *xs;
233 int error = 0, flags = 0, i, j;
234
235 config = dma_alloc(sizeof(*config), PR_NOWAIT);
236 if (config == NULL)
237 return 1;
238
239 if (cold)
240 SET(flags, SCSI_AUTOCONF);
241 xs = scsi_xs_get(sc->sc_link, flags | SCSI_DATA_IN | SCSI_SILENT);
242 if (xs == NULL) {
243 error = 1;
244 goto done;
245 }
246 xs->cmdlen = sizeof(*cmd);
247 xs->data = (void *)config;
248 xs->datalen = sizeof(*config);
249 xs->retries = 2;
250 xs->timeout = 30000;
251
252 cmd = (struct safte_readbuf_cmd *)&xs->cmd;
253 cmd->opcode = READ_BUFFER;
254 SET(cmd->flags, SAFTE_RD_MODE);
255 cmd->bufferid = SAFTE_RD_CONFIG;
256 cmd->length = htobe16(sizeof(*config));
257
258 error = scsi_xs_sync(xs);
259 scsi_xs_put(xs);
260
261 if (error != 0) {
262 error = 1;
263 goto done;
264 }
265
266 DPRINTF(("%s: nfans: %d npwrsup: %d nslots: %d doorlock: %d ntemps: %d"
267 " alarm: %d celsius: %d ntherm: %d\n", DEVNAME(sc), config->nfans,
268 config->npwrsup, config->nslots, config->doorlock, config->ntemps,
269 config->alarm, SAFTE_CFG_CELSIUS(config->therm),
270 SAFTE_CFG_NTHERM(config->therm)));
271
272 sc->sc_encbuflen = config->nfans * sizeof(u_int8_t) + /* fan status */
273 config->npwrsup * sizeof(u_int8_t) + /* power supply status */
274 config->nslots * sizeof(u_int8_t) + /* device scsi id (lun) */
275 sizeof(u_int8_t) + /* door lock status */
276 sizeof(u_int8_t) + /* speaker status */
277 config->ntemps * sizeof(u_int8_t) + /* temp sensors */
278 sizeof(u_int16_t); /* temp out of range sensors */
279
280 sc->sc_encbuf = dma_alloc(sc->sc_encbuflen, PR_NOWAIT);
281 if (sc->sc_encbuf == NULL) {
282 error = 1;
283 goto done;
284 }
285
286 sc->sc_nsensors = config->nfans + config->npwrsup + config->ntemps +
287 (config->doorlock ? 1 : 0) + (config->alarm ? 1 : 0);
288
289 sc->sc_sensors = mallocarray(sc->sc_nsensors,
290 sizeof(struct safte_sensor), M_DEVBUF, M_NOWAIT | M_ZERO);
291 if (sc->sc_sensors == NULL) {
292 dma_free(sc->sc_encbuf, sc->sc_encbuflen);
293 sc->sc_encbuf = NULL;
294 sc->sc_nsensors = 0;
295 error = 1;
296 goto done;
297 }
298
299 strlcpy(sc->sc_sensordev.xname, DEVNAME(sc),
300 sizeof(sc->sc_sensordev.xname));
301
302 s = sc->sc_sensors;
303
304 for (i = 0; i < config->nfans; i++) {
305 s->se_type = SAFTE_T_FAN;
306 s->se_field = (u_int8_t *)(sc->sc_encbuf + i);
307 s->se_sensor.type = SENSOR_INDICATOR;
308 snprintf(s->se_sensor.desc, sizeof(s->se_sensor.desc),
309 "Fan%d", i);
310
311 s++;
312 }
313 j = config->nfans;
314
315 for (i = 0; i < config->npwrsup; i++) {
316 s->se_type = SAFTE_T_PWRSUP;
317 s->se_field = (u_int8_t *)(sc->sc_encbuf + j + i);
318 s->se_sensor.type = SENSOR_INDICATOR;
319 snprintf(s->se_sensor.desc, sizeof(s->se_sensor.desc),
320 "PSU%d", i);
321
322 s++;
323 }
324 j += config->npwrsup;
325
326 #if NBIO > 0
327 sc->sc_nslots = config->nslots;
328 sc->sc_slots = (u_int8_t *)(sc->sc_encbuf + j);
329 #endif /* NBIO > 0 */
330 j += config->nslots;
331
332 if (config->doorlock) {
333 s->se_type = SAFTE_T_DOORLOCK;
334 s->se_field = (u_int8_t *)(sc->sc_encbuf + j);
335 s->se_sensor.type = SENSOR_INDICATOR;
336 strlcpy(s->se_sensor.desc, "doorlock",
337 sizeof(s->se_sensor.desc));
338
339 s++;
340 }
341 j++;
342
343 if (config->alarm) {
344 s->se_type = SAFTE_T_ALARM;
345 s->se_field = (u_int8_t *)(sc->sc_encbuf + j);
346 s->se_sensor.type = SENSOR_INDICATOR;
347 strlcpy(s->se_sensor.desc, "alarm", sizeof(s->se_sensor.desc));
348
349 s++;
350 }
351 j++;
352
353 /*
354 * Stash the temp info so we can get out of range status. Limit the
355 * number so the out of temp checks can't go into memory it doesn't own.
356 */
357 sc->sc_ntemps = (config->ntemps > 15) ? 15 : config->ntemps;
358 sc->sc_temps = s;
359 sc->sc_celsius = SAFTE_CFG_CELSIUS(config->therm);
360 for (i = 0; i < config->ntemps; i++) {
361 s->se_type = SAFTE_T_TEMP;
362 s->se_field = (u_int8_t *)(sc->sc_encbuf + j + i);
363 s->se_sensor.type = SENSOR_TEMP;
364
365 s++;
366 }
367 j += config->ntemps;
368
369 sc->sc_temperrs = (u_int8_t *)(sc->sc_encbuf + j);
370 done:
371 dma_free(config, sizeof(*config));
372 return error;
373 }
374
375 void
safte_read_encstat(void * arg)376 safte_read_encstat(void *arg)
377 {
378 struct safte_readbuf_cmd *cmd;
379 struct safte_sensor *s;
380 struct safte_softc *sc = (struct safte_softc *)arg;
381 struct scsi_xfer *xs;
382 int error, i, flags = 0;
383 u_int16_t oot;
384
385 rw_enter_write(&sc->sc_lock);
386
387 if (cold)
388 SET(flags, SCSI_AUTOCONF);
389 xs = scsi_xs_get(sc->sc_link, flags | SCSI_DATA_IN | SCSI_SILENT);
390 if (xs == NULL) {
391 rw_exit_write(&sc->sc_lock);
392 return;
393 }
394 xs->cmdlen = sizeof(*cmd);
395 xs->data = sc->sc_encbuf;
396 xs->datalen = sc->sc_encbuflen;
397 xs->retries = 2;
398 xs->timeout = 30000;
399
400 cmd = (struct safte_readbuf_cmd *)&xs->cmd;
401 cmd->opcode = READ_BUFFER;
402 SET(cmd->flags, SAFTE_RD_MODE);
403 cmd->bufferid = SAFTE_RD_ENCSTAT;
404 cmd->length = htobe16(sc->sc_encbuflen);
405
406 error = scsi_xs_sync(xs);
407 scsi_xs_put(xs);
408
409 if (error != 0) {
410 rw_exit_write(&sc->sc_lock);
411 return;
412 }
413
414 for (i = 0; i < sc->sc_nsensors; i++) {
415 s = &sc->sc_sensors[i];
416 CLR(s->se_sensor.flags, SENSOR_FUNKNOWN);
417
418 DPRINTF(("%s: %d type: %d field: 0x%02x\n", DEVNAME(sc), i,
419 s->se_type, *s->se_field));
420
421 switch (s->se_type) {
422 case SAFTE_T_FAN:
423 switch (*s->se_field) {
424 case SAFTE_FAN_OP:
425 s->se_sensor.value = 1;
426 s->se_sensor.status = SENSOR_S_OK;
427 break;
428 case SAFTE_FAN_MF:
429 s->se_sensor.value = 0;
430 s->se_sensor.status = SENSOR_S_CRIT;
431 break;
432 case SAFTE_FAN_NOTINST:
433 case SAFTE_FAN_UNKNOWN:
434 default:
435 s->se_sensor.value = 0;
436 s->se_sensor.status = SENSOR_S_UNKNOWN;
437 SET(s->se_sensor.flags, SENSOR_FUNKNOWN);
438 break;
439 }
440 break;
441
442 case SAFTE_T_PWRSUP:
443 switch (*s->se_field) {
444 case SAFTE_PWR_OP_ON:
445 s->se_sensor.value = 1;
446 s->se_sensor.status = SENSOR_S_OK;
447 break;
448 case SAFTE_PWR_OP_OFF:
449 s->se_sensor.value = 0;
450 s->se_sensor.status = SENSOR_S_OK;
451 break;
452 case SAFTE_PWR_MF_ON:
453 s->se_sensor.value = 1;
454 s->se_sensor.status = SENSOR_S_CRIT;
455 break;
456 case SAFTE_PWR_MF_OFF:
457 s->se_sensor.value = 0;
458 s->se_sensor.status = SENSOR_S_CRIT;
459 break;
460 case SAFTE_PWR_NOTINST:
461 case SAFTE_PWR_PRESENT:
462 case SAFTE_PWR_UNKNOWN:
463 s->se_sensor.value = 0;
464 s->se_sensor.status = SENSOR_S_UNKNOWN;
465 SET(s->se_sensor.flags, SENSOR_FUNKNOWN);
466 break;
467 }
468 break;
469
470 case SAFTE_T_DOORLOCK:
471 switch (*s->se_field) {
472 case SAFTE_DOOR_LOCKED:
473 s->se_sensor.value = 1;
474 s->se_sensor.status = SENSOR_S_OK;
475 break;
476 case SAFTE_DOOR_UNLOCKED:
477 s->se_sensor.value = 0;
478 s->se_sensor.status = SENSOR_S_CRIT;
479 break;
480 case SAFTE_DOOR_UNKNOWN:
481 s->se_sensor.value = 0;
482 s->se_sensor.status = SENSOR_S_CRIT;
483 SET(s->se_sensor.flags, SENSOR_FUNKNOWN);
484 break;
485 }
486 break;
487
488 case SAFTE_T_ALARM:
489 switch (*s->se_field) {
490 case SAFTE_SPKR_OFF:
491 s->se_sensor.value = 0;
492 s->se_sensor.status = SENSOR_S_OK;
493 break;
494 case SAFTE_SPKR_ON:
495 s->se_sensor.value = 1;
496 s->se_sensor.status = SENSOR_S_CRIT;
497 break;
498 }
499 break;
500
501 case SAFTE_T_TEMP:
502 s->se_sensor.value = safte_temp2uK(*s->se_field,
503 sc->sc_celsius);
504 break;
505 }
506 }
507
508 oot = _2btol(sc->sc_temperrs);
509 for (i = 0; i < sc->sc_ntemps; i++)
510 sc->sc_temps[i].se_sensor.status =
511 (oot & (1 << i)) ? SENSOR_S_CRIT : SENSOR_S_OK;
512
513 rw_exit_write(&sc->sc_lock);
514 }
515
516 #if NBIO > 0
517 int
safte_ioctl(struct device * dev,u_long cmd,caddr_t addr)518 safte_ioctl(struct device *dev, u_long cmd, caddr_t addr)
519 {
520 struct safte_softc *sc = (struct safte_softc *)dev;
521 int error = 0;
522
523 switch (cmd) {
524 case BIOCBLINK:
525 error = safte_bio_blink(sc, (struct bioc_blink *)addr);
526 break;
527
528 default:
529 error = EINVAL;
530 break;
531 }
532
533 return error;
534 }
535
536 int
safte_bio_blink(struct safte_softc * sc,struct bioc_blink * blink)537 safte_bio_blink(struct safte_softc *sc, struct bioc_blink *blink)
538 {
539 struct safte_writebuf_cmd *cmd;
540 struct safte_slotop *op;
541 struct scsi_xfer *xs;
542 int error, slot, flags = 0, wantblink;
543
544 switch (blink->bb_status) {
545 case BIOC_SBBLINK:
546 wantblink = 1;
547 break;
548 case BIOC_SBUNBLINK:
549 wantblink = 0;
550 break;
551 default:
552 return EINVAL;
553 }
554
555 rw_enter_read(&sc->sc_lock);
556 for (slot = 0; slot < sc->sc_nslots; slot++) {
557 if (sc->sc_slots[slot] == blink->bb_target)
558 break;
559 }
560 rw_exit_read(&sc->sc_lock);
561
562 if (slot >= sc->sc_nslots)
563 return ENODEV;
564
565 op = dma_alloc(sizeof(*op), PR_WAITOK | PR_ZERO);
566
567 op->opcode = SAFTE_WRITE_SLOTOP;
568 op->slot = slot;
569 op->flags |= wantblink ? SAFTE_SLOTOP_IDENTIFY : 0;
570
571 if (cold)
572 SET(flags, SCSI_AUTOCONF);
573 xs = scsi_xs_get(sc->sc_link, flags | SCSI_DATA_OUT | SCSI_SILENT);
574 if (xs == NULL) {
575 dma_free(op, sizeof(*op));
576 return ENOMEM;
577 }
578 xs->cmdlen = sizeof(*cmd);
579 xs->data = (void *)op;
580 xs->datalen = sizeof(*op);
581 xs->retries = 2;
582 xs->timeout = 30000;
583
584 cmd = (struct safte_writebuf_cmd *)&xs->cmd;
585 cmd->opcode = WRITE_BUFFER;
586 SET(cmd->flags, SAFTE_WR_MODE);
587 cmd->length = htobe16(sizeof(struct safte_slotop));
588
589 error = scsi_xs_sync(xs);
590 scsi_xs_put(xs);
591
592 if (error != 0) {
593 error = EIO;
594 }
595 dma_free(op, sizeof(*op));
596
597 return error;
598 }
599 #endif /* NBIO > 0 */
600
601 int64_t
safte_temp2uK(u_int8_t measured,int celsius)602 safte_temp2uK(u_int8_t measured, int celsius)
603 {
604 int64_t temp;
605
606 temp = (int64_t)measured;
607 temp += SAFTE_TEMP_OFFSET;
608 temp *= 1000000; /* Convert to micro (mu) degrees. */
609 if (!celsius)
610 temp = ((temp - 32000000) * 5) / 9; /* Convert to Celsius. */
611
612 temp += 273150000; /* Convert to kelvin. */
613
614 return temp;
615 }
616