Annotation of sys/scsi/ses.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: ses.c,v 1.45 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/ses.h>
39:
40: #ifdef SES_DEBUG
41: #define DPRINTF(x...) do { if (sesdebug) printf(x); } while (0)
42: #define DPRINTFN(n, x...) do { if (sesdebug > (n)) printf(x); } while (0)
43: int sesdebug = 2;
44: #else
45: #define DPRINTF(x...) /* x */
46: #define DPRINTFN(n,x...) /* n: x */
47: #endif
48:
49: int ses_match(struct device *, void *, void *);
50: void ses_attach(struct device *, struct device *, void *);
51: int ses_detach(struct device *, int);
52:
53: struct ses_sensor {
54: struct ksensor se_sensor;
55: u_int8_t se_type;
56: struct ses_status *se_stat;
57:
58: TAILQ_ENTRY(ses_sensor) se_entry;
59: };
60:
61: #if NBIO > 0
62: struct ses_slot {
63: struct ses_status *sl_stat;
64:
65: TAILQ_ENTRY(ses_slot) sl_entry;
66: };
67: #endif
68:
69: struct ses_softc {
70: struct device sc_dev;
71: struct scsi_link *sc_link;
72: struct rwlock sc_lock;
73:
74: enum {
75: SES_ENC_STD,
76: SES_ENC_DELL
77: } sc_enctype;
78:
79: u_char *sc_buf;
80: ssize_t sc_buflen;
81:
82: #if NBIO > 0
83: TAILQ_HEAD(, ses_slot) sc_slots;
84: #endif
85: TAILQ_HEAD(, ses_sensor) sc_sensors;
86: struct ksensordev sc_sensordev;
87: struct sensor_task *sc_sensortask;
88: };
89:
90: struct cfattach ses_ca = {
91: sizeof(struct ses_softc), ses_match, ses_attach, ses_detach
92: };
93:
94: struct cfdriver ses_cd = {
95: NULL, "ses", DV_DULL
96: };
97:
98: #define DEVNAME(s) ((s)->sc_dev.dv_xname)
99:
100: #define SES_BUFLEN 2048 /* XXX is this enough? */
101:
102: int ses_read_config(struct ses_softc *);
103: int ses_read_status(struct ses_softc *);
104: int ses_make_sensors(struct ses_softc *, struct ses_type_desc *, int);
105: void ses_refresh_sensors(void *);
106:
107: #if NBIO > 0
108: int ses_ioctl(struct device *, u_long, caddr_t);
109: int ses_write_config(struct ses_softc *);
110: int ses_bio_blink(struct ses_softc *, struct bioc_blink *);
111: #endif
112:
113: void ses_psu2sensor(struct ses_softc *, struct ses_sensor *);
114: void ses_cool2sensor(struct ses_softc *, struct ses_sensor *);
115: void ses_temp2sensor(struct ses_softc *, struct ses_sensor *);
116:
117: #ifdef SES_DEBUG
118: void ses_dump_enc_desc(struct ses_enc_desc *);
119: char *ses_dump_enc_string(u_char *, ssize_t);
120: #endif
121:
122: int
123: ses_match(struct device *parent, void *match, void *aux)
124: {
125: struct scsi_attach_args *sa = aux;
126: struct scsi_inquiry_data *inq = sa->sa_inqbuf;
127:
128: if (inq == NULL)
129: return (0);
130:
131: if ((inq->device & SID_TYPE) == T_ENCLOSURE &&
132: SCSISPC(inq->version) >= 2)
133: return (2);
134:
135: /* match on dell enclosures */
136: if ((inq->device & SID_TYPE) == T_PROCESSOR &&
137: SCSISPC(inq->version) == 3)
138: return (3);
139:
140: return (0);
141: }
142:
143: void
144: ses_attach(struct device *parent, struct device *self, void *aux)
145: {
146: struct ses_softc *sc = (struct ses_softc *)self;
147: struct scsi_attach_args *sa = aux;
148: char vendor[33];
149: struct ses_sensor *sensor;
150: #if NBIO > 0
151: struct ses_slot *slot;
152: #endif
153:
154: sc->sc_link = sa->sa_sc_link;
155: sa->sa_sc_link->device_softc = sc;
156: rw_init(&sc->sc_lock, DEVNAME(sc));
157:
158: scsi_strvis(vendor, sc->sc_link->inqdata.vendor,
159: sizeof(sc->sc_link->inqdata.vendor));
160: if (strncasecmp(vendor, "Dell", sizeof(vendor)) == 0)
161: sc->sc_enctype = SES_ENC_DELL;
162: else
163: sc->sc_enctype = SES_ENC_STD;
164:
165: printf("\n");
166:
167: if (ses_read_config(sc) != 0) {
168: printf("%s: unable to read enclosure configuration\n",
169: DEVNAME(sc));
170: return;
171: }
172:
173: if (!TAILQ_EMPTY(&sc->sc_sensors)) {
174: sc->sc_sensortask = sensor_task_register(sc,
175: ses_refresh_sensors, 10);
176: if (sc->sc_sensortask == NULL) {
177: printf("%s: unable to register update task\n",
178: DEVNAME(sc));
179: while (!TAILQ_EMPTY(&sc->sc_sensors)) {
180: sensor = TAILQ_FIRST(&sc->sc_sensors);
181: TAILQ_REMOVE(&sc->sc_sensors, sensor,
182: se_entry);
183: free(sensor, M_DEVBUF);
184: }
185: } else {
186: TAILQ_FOREACH(sensor, &sc->sc_sensors, se_entry)
187: sensor_attach(&sc->sc_sensordev,
188: &sensor->se_sensor);
189: sensordev_install(&sc->sc_sensordev);
190: }
191: }
192:
193: #if NBIO > 0
194: if (!TAILQ_EMPTY(&sc->sc_slots) &&
195: bio_register(self, ses_ioctl) != 0) {
196: printf("%s: unable to register ioctl\n", DEVNAME(sc));
197: while (!TAILQ_EMPTY(&sc->sc_slots)) {
198: slot = TAILQ_FIRST(&sc->sc_slots);
199: TAILQ_REMOVE(&sc->sc_slots, slot, sl_entry);
200: free(slot, M_DEVBUF);
201: }
202: }
203: #endif
204:
205: if (TAILQ_EMPTY(&sc->sc_sensors)
206: #if NBIO > 0
207: && TAILQ_EMPTY(&sc->sc_slots)
208: #endif
209: ) {
210: free(sc->sc_buf, M_DEVBUF);
211: sc->sc_buf = NULL;
212: }
213: }
214:
215: int
216: ses_detach(struct device *self, int flags)
217: {
218: struct ses_softc *sc = (struct ses_softc *)self;
219: struct ses_sensor *sensor;
220: #if NBIO > 0
221: struct ses_slot *slot;
222: #endif
223:
224: rw_enter_write(&sc->sc_lock);
225:
226: #if NBIO > 0
227: if (!TAILQ_EMPTY(&sc->sc_slots)) {
228: bio_unregister(self);
229: while (!TAILQ_EMPTY(&sc->sc_slots)) {
230: slot = TAILQ_FIRST(&sc->sc_slots);
231: TAILQ_REMOVE(&sc->sc_slots, slot, sl_entry);
232: free(slot, M_DEVBUF);
233: }
234: }
235: #endif
236:
237: if (!TAILQ_EMPTY(&sc->sc_sensors)) {
238: sensordev_deinstall(&sc->sc_sensordev);
239: sensor_task_unregister(sc->sc_sensortask);
240:
241: while (!TAILQ_EMPTY(&sc->sc_sensors)) {
242: sensor = TAILQ_FIRST(&sc->sc_sensors);
243: sensor_detach(&sc->sc_sensordev, &sensor->se_sensor);
244: TAILQ_REMOVE(&sc->sc_sensors, sensor, se_entry);
245: free(sensor, M_DEVBUF);
246: }
247: }
248:
249: if (sc->sc_buf != NULL)
250: free(sc->sc_buf, M_DEVBUF);
251:
252: rw_exit_write(&sc->sc_lock);
253:
254: return (0);
255: }
256:
257: int
258: ses_read_config(struct ses_softc *sc)
259: {
260: struct ses_scsi_diag cmd;
261: int flags;
262:
263: u_char *buf, *p;
264:
265: struct ses_config_hdr *cfg;
266: struct ses_enc_hdr *enc;
267: #ifdef SES_DEBUG
268: struct ses_enc_desc *desc;
269: #endif
270: struct ses_type_desc *tdh, *tdlist;
271:
272: int i, ntypes = 0, nelems = 0;
273:
274: buf = malloc(SES_BUFLEN, M_DEVBUF, M_NOWAIT);
275: if (buf == NULL)
276: return (1);
277:
278: memset(buf, 0, SES_BUFLEN);
279: memset(&cmd, 0, sizeof(cmd));
280: cmd.opcode = RECEIVE_DIAGNOSTIC;
281: cmd.flags |= SES_DIAG_PCV;
282: cmd.pgcode = SES_PAGE_CONFIG;
283: cmd.length = htobe16(SES_BUFLEN);
284: flags = SCSI_DATA_IN;
285: #ifndef SCSIDEBUG
286: flags |= SCSI_SILENT;
287: #endif
288:
289: if (cold)
290: flags |= SCSI_AUTOCONF;
291:
292: if (scsi_scsi_cmd(sc->sc_link, (struct scsi_generic *)&cmd,
293: sizeof(cmd), buf, SES_BUFLEN, 2, 3000, NULL, flags) != 0) {
294: free(buf, M_DEVBUF);
295: return (1);
296: }
297:
298: cfg = (struct ses_config_hdr *)buf;
299: if (cfg->pgcode != cmd.pgcode || betoh16(cfg->length) > SES_BUFLEN) {
300: free(buf, M_DEVBUF);
301: return (1);
302: }
303:
304: DPRINTF("%s: config: n_subenc: %d length: %d\n", DEVNAME(sc),
305: cfg->n_subenc, betoh16(cfg->length));
306:
307: p = buf + SES_CFG_HDRLEN;
308: for (i = 0; i <= cfg->n_subenc; i++) {
309: enc = (struct ses_enc_hdr *)p;
310: #ifdef SES_DEBUG
311: DPRINTF("%s: enclosure %d enc_id: 0x%02x n_types: %d\n",
312: DEVNAME(sc), i, enc->enc_id, enc->n_types);
313: desc = (struct ses_enc_desc *)(p + SES_ENC_HDRLEN);
314: ses_dump_enc_desc(desc);
315: #endif /* SES_DEBUG */
316:
317: ntypes += enc->n_types;
318:
319: p += SES_ENC_HDRLEN + enc->vendor_len;
320: }
321:
322: tdlist = (struct ses_type_desc *)p; /* stash this for later */
323:
324: for (i = 0; i < ntypes; i++) {
325: tdh = (struct ses_type_desc *)p;
326: DPRINTF("%s: td %d subenc_id: %d type 0x%02x n_elem: %d\n",
327: DEVNAME(sc), i, tdh->subenc_id, tdh->type, tdh->n_elem);
328:
329: nelems += tdh->n_elem;
330:
331: p += SES_TYPE_DESCLEN;
332: }
333:
334: #ifdef SES_DEBUG
335: for (i = 0; i < ntypes; i++) {
336: DPRINTF("%s: td %d '%s'\n", DEVNAME(sc), i,
337: ses_dump_enc_string(p, tdlist[i].desc_len));
338:
339: p += tdlist[i].desc_len;
340: }
341: #endif /* SES_DEBUG */
342:
343: sc->sc_buflen = SES_STAT_LEN(ntypes, nelems);
344: sc->sc_buf = malloc(sc->sc_buflen, M_DEVBUF, M_NOWAIT);
345: if (sc->sc_buf == NULL) {
346: free(buf, M_DEVBUF);
347: return (1);
348: }
349:
350: /* get the status page and then use it to generate a list of sensors */
351: if (ses_make_sensors(sc, tdlist, ntypes) != 0) {
352: free(buf, M_DEVBUF);
353: free(sc->sc_buf, M_DEVBUF);
354: return (1);
355: }
356:
357: free(buf, M_DEVBUF);
358: return (0);
359: }
360:
361: int
362: ses_read_status(struct ses_softc *sc)
363: {
364: struct ses_scsi_diag cmd;
365: int flags;
366:
367: memset(&cmd, 0, sizeof(cmd));
368: cmd.opcode = RECEIVE_DIAGNOSTIC;
369: cmd.flags |= SES_DIAG_PCV;
370: cmd.pgcode = SES_PAGE_STATUS;
371: cmd.length = htobe16(sc->sc_buflen);
372: flags = SCSI_DATA_IN;
373: #ifndef SCSIDEBUG
374: flags |= SCSI_SILENT;
375: #endif
376: if (cold)
377: flags |= SCSI_AUTOCONF;
378:
379: if (scsi_scsi_cmd(sc->sc_link, (struct scsi_generic *)&cmd,
380: sizeof(cmd), sc->sc_buf, sc->sc_buflen, 2, 3000, NULL, flags) != 0)
381: return (1);
382:
383: return (0);
384: }
385:
386: int
387: ses_make_sensors(struct ses_softc *sc, struct ses_type_desc *types, int ntypes)
388: {
389: struct ses_status *status;
390: struct ses_sensor *sensor;
391: #if NBIO > 0
392: struct ses_slot *slot;
393: #endif
394: enum sensor_type stype;
395: char *fmt;
396: int i, j;
397:
398: if (ses_read_status(sc) != 0)
399: return (1);
400:
401: strlcpy(sc->sc_sensordev.xname, DEVNAME(sc),
402: sizeof(sc->sc_sensordev.xname));
403:
404: TAILQ_INIT(&sc->sc_sensors);
405: #if NBIO > 0
406: TAILQ_INIT(&sc->sc_slots);
407: #endif
408:
409: status = (struct ses_status *)(sc->sc_buf + SES_STAT_HDRLEN);
410: for (i = 0; i < ntypes; i++) {
411: /* ignore the overall status element for this type */
412: DPRINTFN(1, "%s: %3d:- 0x%02x 0x%02x%02x%02x type: 0x%02x\n",
413: DEVNAME(sc), i, status->com, status->f1, status->f2,
414: status->f3, types[i].type);
415:
416: for (j = 0; j < types[i].n_elem; j++) {
417: /* move to the current status element */
418: status++;
419:
420: DPRINTFN(1, "%s: %3d:%-3d 0x%02x 0x%02x%02x%02x\n",
421: DEVNAME(sc), i, j, status->com, status->f1,
422: status->f2, status->f3);
423:
424: if (SES_STAT_CODE(status->com) == SES_STAT_CODE_NOTINST)
425: continue;
426:
427: switch (types[i].type) {
428: #if NBIO > 0
429: case SES_T_DEVICE:
430: slot = malloc(sizeof(struct ses_slot),
431: M_DEVBUF, M_NOWAIT);
432: if (slot == NULL)
433: goto error;
434:
435: memset(slot, 0, sizeof(struct ses_slot));
436: slot->sl_stat = status;
437:
438: TAILQ_INSERT_TAIL(&sc->sc_slots, slot,
439: sl_entry);
440:
441: continue;
442: #endif
443:
444: case SES_T_POWERSUPPLY:
445: stype = SENSOR_INDICATOR;
446: fmt = "PSU";
447: break;
448:
449: case SES_T_COOLING:
450: stype = SENSOR_PERCENT;
451: fmt = "Fan";
452: break;
453:
454: case SES_T_TEMP:
455: stype = SENSOR_TEMP;
456: fmt = "";
457: break;
458:
459: default:
460: continue;
461: }
462:
463: sensor = malloc(sizeof(struct ses_sensor), M_DEVBUF,
464: M_NOWAIT);
465: if (sensor == NULL)
466: goto error;
467:
468: memset(sensor, 0, sizeof(struct ses_sensor));
469: sensor->se_type = types[i].type;
470: sensor->se_stat = status;
471: sensor->se_sensor.type = stype;
472: strlcpy(sensor->se_sensor.desc, fmt,
473: sizeof(sensor->se_sensor.desc));
474:
475: TAILQ_INSERT_TAIL(&sc->sc_sensors, sensor, se_entry);
476: }
477:
478: /* move to the overall status element of the next type */
479: status++;
480: }
481:
482: return (0);
483: error:
484: #if NBIO > 0
485: while (!TAILQ_EMPTY(&sc->sc_slots)) {
486: slot = TAILQ_FIRST(&sc->sc_slots);
487: TAILQ_REMOVE(&sc->sc_slots, slot, sl_entry);
488: free(slot, M_DEVBUF);
489: }
490: #endif
491: while (!TAILQ_EMPTY(&sc->sc_sensors)) {
492: sensor = TAILQ_FIRST(&sc->sc_sensors);
493: TAILQ_REMOVE(&sc->sc_sensors, sensor, se_entry);
494: free(sensor, M_DEVBUF);
495: }
496: return (1);
497: }
498:
499: void
500: ses_refresh_sensors(void *arg)
501: {
502: struct ses_softc *sc = (struct ses_softc *)arg;
503: struct ses_sensor *sensor;
504: int ret = 0;
505:
506: rw_enter_write(&sc->sc_lock);
507:
508: if (ses_read_status(sc) != 0) {
509: rw_exit_write(&sc->sc_lock);
510: return;
511: }
512:
513: TAILQ_FOREACH(sensor, &sc->sc_sensors, se_entry) {
514: DPRINTFN(10, "%s: %s 0x%02x 0x%02x%02x%02x\n", DEVNAME(sc),
515: sensor->se_sensor.desc, sensor->se_stat->com,
516: sensor->se_stat->f1, sensor->se_stat->f2,
517: sensor->se_stat->f3);
518:
519: switch (SES_STAT_CODE(sensor->se_stat->com)) {
520: case SES_STAT_CODE_OK:
521: sensor->se_sensor.status = SENSOR_S_OK;
522: break;
523:
524: case SES_STAT_CODE_CRIT:
525: case SES_STAT_CODE_UNREC:
526: sensor->se_sensor.status = SENSOR_S_CRIT;
527: break;
528:
529: case SES_STAT_CODE_NONCRIT:
530: sensor->se_sensor.status = SENSOR_S_WARN;
531: break;
532:
533: case SES_STAT_CODE_NOTINST:
534: case SES_STAT_CODE_UNKNOWN:
535: case SES_STAT_CODE_NOTAVAIL:
536: sensor->se_sensor.status = SENSOR_S_UNKNOWN;
537: break;
538: }
539:
540: switch (sensor->se_type) {
541: case SES_T_POWERSUPPLY:
542: ses_psu2sensor(sc, sensor);
543: break;
544:
545: case SES_T_COOLING:
546: ses_cool2sensor(sc, sensor);
547: break;
548:
549: case SES_T_TEMP:
550: ses_temp2sensor(sc, sensor);
551: break;
552:
553: default:
554: ret = 1;
555: break;
556: }
557: }
558:
559: rw_exit_write(&sc->sc_lock);
560:
561: if (ret)
562: printf("%s: error in sensor data\n", DEVNAME(sc));
563: }
564:
565: #if NBIO > 0
566: int
567: ses_ioctl(struct device *dev, u_long cmd, caddr_t addr)
568: {
569: struct ses_softc *sc = (struct ses_softc *)dev;
570: int error = 0;
571:
572: switch (cmd) {
573: case BIOCBLINK:
574: error = ses_bio_blink(sc, (struct bioc_blink *)addr);
575: break;
576:
577: default:
578: error = EINVAL;
579: break;
580: }
581:
582: return (error);
583: }
584:
585: int
586: ses_write_config(struct ses_softc *sc)
587: {
588: struct ses_scsi_diag cmd;
589: int flags;
590:
591: memset(&cmd, 0, sizeof(cmd));
592: cmd.opcode = SEND_DIAGNOSTIC;
593: cmd.flags |= SES_DIAG_PF;
594: cmd.length = htobe16(sc->sc_buflen);
595: flags = SCSI_DATA_OUT;
596: #ifndef SCSIDEBUG
597: flags |= SCSI_SILENT;
598: #endif
599:
600: if (cold)
601: flags |= SCSI_AUTOCONF;
602:
603: if (scsi_scsi_cmd(sc->sc_link, (struct scsi_generic *)&cmd,
604: sizeof(cmd), sc->sc_buf, sc->sc_buflen, 2, 3000, NULL, flags) != 0)
605: return (1);
606:
607: return (0);
608: }
609:
610: int
611: ses_bio_blink(struct ses_softc *sc, struct bioc_blink *blink)
612: {
613: struct ses_slot *slot;
614:
615: rw_enter_write(&sc->sc_lock);
616:
617: if (ses_read_status(sc) != 0) {
618: rw_exit_write(&sc->sc_lock);
619: return (EIO);
620: }
621:
622: TAILQ_FOREACH(slot, &sc->sc_slots, sl_entry) {
623: if (slot->sl_stat->f1 == blink->bb_target)
624: break;
625: }
626:
627: if (slot == TAILQ_END(&sc->sc_slots)) {
628: rw_exit_write(&sc->sc_lock);
629: return (EINVAL);
630: }
631:
632: DPRINTFN(3, "%s: 0x%02x 0x%02x 0x%02x 0x%02x\n", DEVNAME(sc),
633: slot->sl_stat->com, slot->sl_stat->f1, slot->sl_stat->f2,
634: slot->sl_stat->f3);
635:
636: slot->sl_stat->com = SES_STAT_SELECT;
637: slot->sl_stat->f2 &= SES_C_DEV_F2MASK;
638: slot->sl_stat->f3 &= SES_C_DEV_F3MASK;
639:
640: switch (blink->bb_status) {
641: case BIOC_SBUNBLINK:
642: slot->sl_stat->f2 &= ~SES_C_DEV_IDENT;
643: break;
644:
645: case BIOC_SBBLINK:
646: slot->sl_stat->f2 |= SES_C_DEV_IDENT;
647: break;
648:
649: default:
650: rw_exit_write(&sc->sc_lock);
651: return (EINVAL);
652: }
653:
654: DPRINTFN(3, "%s: 0x%02x 0x%02x 0x%02x 0x%02x\n", DEVNAME(sc),
655: slot->sl_stat->com, slot->sl_stat->f1, slot->sl_stat->f2,
656: slot->sl_stat->f3);
657:
658: if (ses_write_config(sc) != 0) {
659: rw_exit_write(&sc->sc_lock);
660: return (EIO);
661: }
662:
663: rw_exit_write(&sc->sc_lock);
664:
665: return (0);
666: }
667: #endif
668:
669: void
670: ses_psu2sensor(struct ses_softc *sc, struct ses_sensor *s)
671: {
672: s->se_sensor.value = SES_S_PSU_OFF(s->se_stat) ? 0 : 1;
673: }
674:
675: void
676: ses_cool2sensor(struct ses_softc *sc, struct ses_sensor *s)
677: {
678: switch (sc->sc_enctype) {
679: case SES_ENC_STD:
680: switch (SES_S_COOL_CODE(s->se_stat)) {
681: case SES_S_COOL_C_STOPPED:
682: s->se_sensor.value = 0;
683: break;
684: case SES_S_COOL_C_LOW1:
685: case SES_S_COOL_C_LOW2:
686: case SES_S_COOL_C_LOW3:
687: s->se_sensor.value = 33333;
688: break;
689: case SES_S_COOL_C_INTER:
690: case SES_S_COOL_C_HI3:
691: case SES_S_COOL_C_HI2:
692: s->se_sensor.value = 66666;
693: break;
694: case SES_S_COOL_C_HI1:
695: s->se_sensor.value = 100000;
696: break;
697: }
698: break;
699:
700: /* Dell only use the first three codes to represent speed */
701: case SES_ENC_DELL:
702: switch (SES_S_COOL_CODE(s->se_stat)) {
703: case SES_S_COOL_C_STOPPED:
704: s->se_sensor.value = 0;
705: break;
706: case SES_S_COOL_C_LOW1:
707: s->se_sensor.value = 33333;
708: break;
709: case SES_S_COOL_C_LOW2:
710: s->se_sensor.value = 66666;
711: break;
712: case SES_S_COOL_C_LOW3:
713: case SES_S_COOL_C_INTER:
714: case SES_S_COOL_C_HI3:
715: case SES_S_COOL_C_HI2:
716: case SES_S_COOL_C_HI1:
717: s->se_sensor.value = 100000;
718: break;
719: }
720: break;
721: }
722: }
723:
724: void
725: ses_temp2sensor(struct ses_softc *sc, struct ses_sensor *s)
726: {
727: s->se_sensor.value = (int64_t)SES_S_TEMP(s->se_stat);
728: s->se_sensor.value += SES_S_TEMP_OFFSET;
729: s->se_sensor.value *= 1000000; /* convert to micro (mu) degrees */
730: s->se_sensor.value += 273150000; /* convert to kelvin */
731: }
732:
733: #ifdef SES_DEBUG
734: void
735: ses_dump_enc_desc(struct ses_enc_desc *desc)
736: {
737: char str[32];
738:
739: #if 0
740: /* XXX not a string. wwn? */
741: memset(str, 0, sizeof(str));
742: memcpy(str, desc->logical_id, sizeof(desc->logical_id));
743: DPRINTF("logical_id: %s", str);
744: #endif
745:
746: memset(str, 0, sizeof(str));
747: memcpy(str, desc->vendor_id, sizeof(desc->vendor_id));
748: DPRINTF(" vendor_id: %s", str);
749:
750: memset(str, 0, sizeof(str));
751: memcpy(str, desc->prod_id, sizeof(desc->prod_id));
752: DPRINTF(" prod_id: %s", str);
753:
754: memset(str, 0, sizeof(str));
755: memcpy(str, desc->prod_rev, sizeof(desc->prod_rev));
756: DPRINTF(" prod_rev: %s\n", str);
757: }
758:
759: char *
760: ses_dump_enc_string(u_char *buf, ssize_t len)
761: {
762: static char str[256];
763:
764: memset(str, 0, sizeof(str));
765: if (len > 0)
766: memcpy(str, buf, len);
767:
768: return (str);
769: }
770: #endif /* SES_DEBUG */
CVSweb