Annotation of sys/scsi/safte.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: safte.c,v 1.37 2007/06/24 05:34:35 dlg 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/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) /* 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: /* match on dell enclosures */
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) /* if we're doing something, then preinit encbuf and sensors */
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) + /* fan status */
281: config.npwrsup * sizeof(u_int8_t) + /* power supply status */
282: config.nslots * sizeof(u_int8_t) + /* device scsi id (lun) */
283: sizeof(u_int8_t) + /* door lock status */
284: sizeof(u_int8_t) + /* speaker status */
285: config.ntemps * sizeof(u_int8_t) + /* temp sensors */
286: sizeof(u_int16_t); /* temp out of range sensors */
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: * stash the temp info so we can get out of range status. limit the
362: * number so the out of temp checks cant go into memory it doesnt own
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 /* NBIO > 0 */
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; /* convert to micro (mu) degrees */
603: if (!celsius)
604: temp = ((temp - 32000000) * 5) / 9; /* convert to Celsius */
605:
606: temp += 273150000; /* convert to kelvin */
607:
608: return (temp);
609: }
CVSweb