xref: /openbsd/sys/scsi/safte.c (revision 9593dc34)
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