Line data Source code
1 : /* $OpenBSD: safte.c,v 1.53 2015/08/23 01:55:39 tedu 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
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_int8_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 0 : safte_match(struct device *parent, void *match, void *aux)
110 : {
111 : struct scsi_inquiry_data *inqbuf;
112 0 : struct scsi_attach_args *sa = aux;
113 0 : struct scsi_inquiry_data *inq = sa->sa_inqbuf;
114 : struct scsi_xfer *xs;
115 : struct safte_inq *si;
116 : int error, flags = 0, length;
117 :
118 0 : if (inq == NULL)
119 0 : return (0);
120 :
121 : /* match on dell enclosures */
122 0 : if ((inq->device & SID_TYPE) == T_PROCESSOR &&
123 0 : SCSISPC(inq->version) == 3)
124 0 : return (2);
125 :
126 0 : if ((inq->device & SID_TYPE) != T_PROCESSOR ||
127 0 : SCSISPC(inq->version) != 2 ||
128 0 : (inq->response_format & SID_ANSII) != 2)
129 0 : return (0);
130 :
131 0 : length = inq->additional_length + SAFTE_EXTRA_OFFSET;
132 0 : if (length < SAFTE_INQ_LEN)
133 0 : return (0);
134 0 : if (length > sizeof(*inqbuf))
135 0 : length = sizeof(*inqbuf);
136 :
137 0 : inqbuf = dma_alloc(sizeof(*inqbuf), PR_NOWAIT | PR_ZERO);
138 0 : if (inqbuf == NULL)
139 0 : return (0);
140 :
141 0 : memset(inqbuf->extra, ' ', sizeof(inqbuf->extra));
142 :
143 0 : if (cold)
144 0 : flags |= SCSI_AUTOCONF;
145 0 : xs = scsi_xs_get(sa->sa_sc_link, flags | SCSI_DATA_IN);
146 0 : if (xs == NULL)
147 : goto fail;
148 :
149 0 : xs->retries = 2;
150 0 : xs->timeout = 10000;
151 :
152 0 : scsi_init_inquiry(xs, 0, 0, inqbuf, length);
153 :
154 0 : error = scsi_xs_sync(xs);
155 0 : scsi_xs_put(xs);
156 :
157 0 : if (error)
158 : goto fail;
159 :
160 0 : si = (struct safte_inq *)&inqbuf->extra;
161 0 : if (memcmp(si->ident, SAFTE_IDENT, sizeof(si->ident)) == 0) {
162 0 : dma_free(inqbuf, sizeof(*inqbuf));
163 0 : return (2);
164 : }
165 :
166 : fail:
167 0 : dma_free(inqbuf, sizeof(*inqbuf));
168 0 : return (0);
169 0 : }
170 :
171 : void
172 0 : safte_attach(struct device *parent, struct device *self, void *aux)
173 : {
174 0 : struct safte_softc *sc = (struct safte_softc *)self;
175 0 : struct scsi_attach_args *sa = aux;
176 : int i = 0;
177 :
178 0 : sc->sc_link = sa->sa_sc_link;
179 0 : sa->sa_sc_link->device_softc = sc;
180 0 : rw_init(&sc->sc_lock, DEVNAME(sc));
181 :
182 0 : printf("\n");
183 :
184 0 : sc->sc_encbuf = NULL;
185 0 : sc->sc_nsensors = 0;
186 : #if NBIO > 0
187 0 : sc->sc_nslots = 0;
188 : #endif
189 :
190 0 : if (safte_read_config(sc) != 0) {
191 0 : printf("%s: unable to read enclosure configuration\n",
192 : DEVNAME(sc));
193 0 : return;
194 : }
195 :
196 0 : if (sc->sc_nsensors > 0) {
197 0 : sc->sc_sensortask = sensor_task_register(sc,
198 : safte_read_encstat, 10);
199 0 : if (sc->sc_sensortask == NULL) {
200 0 : printf("%s: unable to register update task\n",
201 : DEVNAME(sc));
202 0 : free(sc->sc_sensors, M_DEVBUF,
203 0 : sc->sc_nsensors * sizeof(struct safte_sensor));
204 0 : sc->sc_nsensors = sc->sc_ntemps = 0;
205 0 : } else {
206 0 : for (i = 0; i < sc->sc_nsensors; i++)
207 0 : sensor_attach(&sc->sc_sensordev,
208 0 : &sc->sc_sensors[i].se_sensor);
209 0 : sensordev_install(&sc->sc_sensordev);
210 : }
211 : }
212 :
213 : #if NBIO > 0
214 0 : if (sc->sc_nslots > 0 &&
215 0 : bio_register(self, safte_ioctl) != 0) {
216 0 : printf("%s: unable to register ioctl with bio\n", DEVNAME(sc));
217 0 : sc->sc_nslots = 0;
218 0 : } else
219 0 : i++;
220 : #endif
221 :
222 0 : if (i) /* if we're doing something, then preinit encbuf and sensors */
223 0 : safte_read_encstat(sc);
224 : else {
225 0 : dma_free(sc->sc_encbuf, sc->sc_encbuflen);
226 0 : sc->sc_encbuf = NULL;
227 : }
228 0 : }
229 :
230 : int
231 0 : safte_detach(struct device *self, int flags)
232 : {
233 0 : struct safte_softc *sc = (struct safte_softc *)self;
234 : int i;
235 :
236 0 : rw_enter_write(&sc->sc_lock);
237 :
238 : #if NBIO > 0
239 0 : if (sc->sc_nslots > 0)
240 0 : bio_unregister(self);
241 : #endif
242 :
243 0 : if (sc->sc_nsensors > 0) {
244 0 : sensordev_deinstall(&sc->sc_sensordev);
245 0 : sensor_task_unregister(sc->sc_sensortask);
246 :
247 0 : for (i = 0; i < sc->sc_nsensors; i++)
248 0 : sensor_detach(&sc->sc_sensordev,
249 0 : &sc->sc_sensors[i].se_sensor);
250 0 : free(sc->sc_sensors, M_DEVBUF,
251 0 : sc->sc_nsensors * sizeof(struct safte_sensor));
252 0 : }
253 :
254 0 : if (sc->sc_encbuf != NULL)
255 0 : dma_free(sc->sc_encbuf, sc->sc_encbuflen);
256 :
257 0 : rw_exit_write(&sc->sc_lock);
258 :
259 0 : return (0);
260 : }
261 :
262 : int
263 0 : safte_read_config(struct safte_softc *sc)
264 : {
265 : struct safte_config *config = NULL;
266 : struct safte_readbuf_cmd *cmd;
267 : struct safte_sensor *s;
268 : struct scsi_xfer *xs;
269 : int error = 0, flags = 0, i, j;
270 :
271 0 : config = dma_alloc(sizeof(*config), PR_NOWAIT);
272 0 : if (config == NULL)
273 0 : return (1);
274 :
275 0 : if (cold)
276 0 : flags |= SCSI_AUTOCONF;
277 0 : xs = scsi_xs_get(sc->sc_link, flags | SCSI_DATA_IN | SCSI_SILENT);
278 0 : if (xs == NULL) {
279 : error = 1;
280 0 : goto done;
281 : }
282 0 : xs->cmdlen = sizeof(*cmd);
283 0 : xs->data = (void *)config;
284 0 : xs->datalen = sizeof(*config);
285 0 : xs->retries = 2;
286 0 : xs->timeout = 30000;
287 :
288 0 : cmd = (struct safte_readbuf_cmd *)xs->cmd;
289 0 : cmd->opcode = READ_BUFFER;
290 0 : cmd->flags |= SAFTE_RD_MODE;
291 0 : cmd->bufferid = SAFTE_RD_CONFIG;
292 0 : cmd->length = htobe16(sizeof(*config));
293 :
294 0 : error = scsi_xs_sync(xs);
295 0 : scsi_xs_put(xs);
296 :
297 0 : if (error != 0) {
298 : error = 1;
299 0 : goto done;
300 : }
301 :
302 : DPRINTF(("%s: nfans: %d npwrsup: %d nslots: %d doorlock: %d ntemps: %d"
303 : " alarm: %d celsius: %d ntherm: %d\n", DEVNAME(sc), config->nfans,
304 : config->npwrsup, config->nslots, config->doorlock, config->ntemps,
305 : config->alarm, SAFTE_CFG_CELSIUS(config->therm),
306 : SAFTE_CFG_NTHERM(config->therm)));
307 :
308 0 : sc->sc_encbuflen = config->nfans * sizeof(u_int8_t) + /* fan status */
309 0 : config->npwrsup * sizeof(u_int8_t) + /* power supply status */
310 0 : config->nslots * sizeof(u_int8_t) + /* device scsi id (lun) */
311 0 : sizeof(u_int8_t) + /* door lock status */
312 0 : sizeof(u_int8_t) + /* speaker status */
313 0 : config->ntemps * sizeof(u_int8_t) + /* temp sensors */
314 : sizeof(u_int16_t); /* temp out of range sensors */
315 :
316 0 : sc->sc_encbuf = dma_alloc(sc->sc_encbuflen, PR_NOWAIT);
317 0 : if (sc->sc_encbuf == NULL) {
318 : error = 1;
319 0 : goto done;
320 : }
321 :
322 0 : sc->sc_nsensors = config->nfans + config->npwrsup + config->ntemps +
323 0 : (config->doorlock ? 1 : 0) + (config->alarm ? 1 : 0);
324 :
325 0 : sc->sc_sensors = mallocarray(sc->sc_nsensors, sizeof(struct safte_sensor),
326 : M_DEVBUF, M_NOWAIT | M_ZERO);
327 0 : if (sc->sc_sensors == NULL) {
328 0 : dma_free(sc->sc_encbuf, sc->sc_encbuflen);
329 0 : sc->sc_encbuf = NULL;
330 0 : sc->sc_nsensors = 0;
331 : error = 1;
332 0 : goto done;
333 : }
334 :
335 0 : strlcpy(sc->sc_sensordev.xname, DEVNAME(sc),
336 : sizeof(sc->sc_sensordev.xname));
337 :
338 0 : s = sc->sc_sensors;
339 :
340 0 : for (i = 0; i < config->nfans; i++) {
341 0 : s->se_type = SAFTE_T_FAN;
342 0 : s->se_field = (u_int8_t *)(sc->sc_encbuf + i);
343 0 : s->se_sensor.type = SENSOR_INDICATOR;
344 0 : snprintf(s->se_sensor.desc, sizeof(s->se_sensor.desc),
345 : "Fan%d", i);
346 :
347 0 : s++;
348 : }
349 : j = config->nfans;
350 :
351 0 : for (i = 0; i < config->npwrsup; i++) {
352 0 : s->se_type = SAFTE_T_PWRSUP;
353 0 : s->se_field = (u_int8_t *)(sc->sc_encbuf + j + i);
354 0 : s->se_sensor.type = SENSOR_INDICATOR;
355 0 : snprintf(s->se_sensor.desc, sizeof(s->se_sensor.desc),
356 : "PSU%d", i);
357 :
358 0 : s++;
359 : }
360 0 : j += config->npwrsup;
361 :
362 : #if NBIO > 0
363 0 : sc->sc_nslots = config->nslots;
364 0 : sc->sc_slots = (u_int8_t *)(sc->sc_encbuf + j);
365 : #endif
366 0 : j += config->nslots;
367 :
368 0 : if (config->doorlock) {
369 0 : s->se_type = SAFTE_T_DOORLOCK;
370 0 : s->se_field = (u_int8_t *)(sc->sc_encbuf + j);
371 0 : s->se_sensor.type = SENSOR_INDICATOR;
372 0 : strlcpy(s->se_sensor.desc, "doorlock",
373 : sizeof(s->se_sensor.desc));
374 :
375 0 : s++;
376 0 : }
377 0 : j++;
378 :
379 0 : if (config->alarm) {
380 0 : s->se_type = SAFTE_T_ALARM;
381 0 : s->se_field = (u_int8_t *)(sc->sc_encbuf + j);
382 0 : s->se_sensor.type = SENSOR_INDICATOR;
383 0 : strlcpy(s->se_sensor.desc, "alarm", sizeof(s->se_sensor.desc));
384 :
385 0 : s++;
386 0 : }
387 0 : j++;
388 :
389 : /*
390 : * stash the temp info so we can get out of range status. limit the
391 : * number so the out of temp checks cant go into memory it doesnt own
392 : */
393 0 : sc->sc_ntemps = (config->ntemps > 15) ? 15 : config->ntemps;
394 0 : sc->sc_temps = s;
395 0 : sc->sc_celsius = SAFTE_CFG_CELSIUS(config->therm);
396 0 : for (i = 0; i < config->ntemps; i++) {
397 0 : s->se_type = SAFTE_T_TEMP;
398 0 : s->se_field = (u_int8_t *)(sc->sc_encbuf + j + i);
399 0 : s->se_sensor.type = SENSOR_TEMP;
400 :
401 0 : s++;
402 : }
403 0 : j += config->ntemps;
404 :
405 0 : sc->sc_temperrs = (u_int8_t *)(sc->sc_encbuf + j);
406 : done:
407 0 : dma_free(config, sizeof(*config));
408 0 : return (error);
409 0 : }
410 :
411 : void
412 0 : safte_read_encstat(void *arg)
413 : {
414 : struct safte_readbuf_cmd *cmd;
415 : struct safte_sensor *s;
416 0 : struct safte_softc *sc = (struct safte_softc *)arg;
417 : struct scsi_xfer *xs;
418 : int error, i, flags = 0;
419 : u_int16_t oot;
420 :
421 0 : rw_enter_write(&sc->sc_lock);
422 :
423 0 : if (cold)
424 0 : flags |= SCSI_AUTOCONF;
425 0 : xs = scsi_xs_get(sc->sc_link, flags | SCSI_DATA_IN | SCSI_SILENT);
426 0 : if (xs == NULL) {
427 0 : rw_exit_write(&sc->sc_lock);
428 0 : return;
429 : }
430 0 : xs->cmdlen = sizeof(*cmd);
431 0 : xs->data = sc->sc_encbuf;
432 0 : xs->datalen = sc->sc_encbuflen;
433 0 : xs->retries = 2;
434 0 : xs->timeout = 30000;
435 :
436 0 : cmd = (struct safte_readbuf_cmd *)xs->cmd;
437 0 : cmd->opcode = READ_BUFFER;
438 0 : cmd->flags |= SAFTE_RD_MODE;
439 0 : cmd->bufferid = SAFTE_RD_ENCSTAT;
440 0 : cmd->length = htobe16(sc->sc_encbuflen);
441 :
442 0 : error = scsi_xs_sync(xs);
443 0 : scsi_xs_put(xs);
444 :
445 0 : if (error != 0) {
446 0 : rw_exit_write(&sc->sc_lock);
447 0 : return;
448 : }
449 :
450 0 : for (i = 0; i < sc->sc_nsensors; i++) {
451 0 : s = &sc->sc_sensors[i];
452 0 : s->se_sensor.flags &= ~SENSOR_FUNKNOWN;
453 :
454 : DPRINTF(("%s: %d type: %d field: 0x%02x\n", DEVNAME(sc), i,
455 : s->se_type, *s->se_field));
456 :
457 0 : switch (s->se_type) {
458 : case SAFTE_T_FAN:
459 0 : switch (*s->se_field) {
460 : case SAFTE_FAN_OP:
461 0 : s->se_sensor.value = 1;
462 0 : s->se_sensor.status = SENSOR_S_OK;
463 0 : break;
464 : case SAFTE_FAN_MF:
465 0 : s->se_sensor.value = 0;
466 0 : s->se_sensor.status = SENSOR_S_CRIT;
467 0 : break;
468 : case SAFTE_FAN_NOTINST:
469 : case SAFTE_FAN_UNKNOWN:
470 : default:
471 0 : s->se_sensor.value = 0;
472 0 : s->se_sensor.status = SENSOR_S_UNKNOWN;
473 0 : s->se_sensor.flags |= SENSOR_FUNKNOWN;
474 0 : break;
475 : }
476 : break;
477 :
478 : case SAFTE_T_PWRSUP:
479 0 : switch (*s->se_field) {
480 : case SAFTE_PWR_OP_ON:
481 0 : s->se_sensor.value = 1;
482 0 : s->se_sensor.status = SENSOR_S_OK;
483 0 : break;
484 : case SAFTE_PWR_OP_OFF:
485 0 : s->se_sensor.value = 0;
486 0 : s->se_sensor.status = SENSOR_S_OK;
487 0 : break;
488 : case SAFTE_PWR_MF_ON:
489 0 : s->se_sensor.value = 1;
490 0 : s->se_sensor.status = SENSOR_S_CRIT;
491 0 : break;
492 : case SAFTE_PWR_MF_OFF:
493 0 : s->se_sensor.value = 0;
494 0 : s->se_sensor.status = SENSOR_S_CRIT;
495 0 : break;
496 : case SAFTE_PWR_NOTINST:
497 : case SAFTE_PWR_PRESENT:
498 : case SAFTE_PWR_UNKNOWN:
499 0 : s->se_sensor.value = 0;
500 0 : s->se_sensor.status = SENSOR_S_UNKNOWN;
501 0 : s->se_sensor.flags |= SENSOR_FUNKNOWN;
502 0 : break;
503 : }
504 : break;
505 :
506 : case SAFTE_T_DOORLOCK:
507 0 : switch (*s->se_field) {
508 : case SAFTE_DOOR_LOCKED:
509 0 : s->se_sensor.value = 1;
510 0 : s->se_sensor.status = SENSOR_S_OK;
511 0 : break;
512 : case SAFTE_DOOR_UNLOCKED:
513 0 : s->se_sensor.value = 0;
514 0 : s->se_sensor.status = SENSOR_S_CRIT;
515 0 : break;
516 : case SAFTE_DOOR_UNKNOWN:
517 0 : s->se_sensor.value = 0;
518 0 : s->se_sensor.status = SENSOR_S_CRIT;
519 0 : s->se_sensor.flags |= SENSOR_FUNKNOWN;
520 0 : break;
521 : }
522 : break;
523 :
524 : case SAFTE_T_ALARM:
525 0 : switch (*s->se_field) {
526 : case SAFTE_SPKR_OFF:
527 0 : s->se_sensor.value = 0;
528 0 : s->se_sensor.status = SENSOR_S_OK;
529 0 : break;
530 : case SAFTE_SPKR_ON:
531 0 : s->se_sensor.value = 1;
532 0 : s->se_sensor.status = SENSOR_S_CRIT;
533 0 : break;
534 : }
535 : break;
536 :
537 : case SAFTE_T_TEMP:
538 0 : s->se_sensor.value = safte_temp2uK(*s->se_field,
539 0 : sc->sc_celsius);
540 0 : break;
541 : }
542 : }
543 :
544 0 : oot = _2btol(sc->sc_temperrs);
545 0 : for (i = 0; i < sc->sc_ntemps; i++)
546 0 : sc->sc_temps[i].se_sensor.status =
547 0 : (oot & (1 << i)) ? SENSOR_S_CRIT : SENSOR_S_OK;
548 :
549 0 : rw_exit_write(&sc->sc_lock);
550 0 : }
551 :
552 : #if NBIO > 0
553 : int
554 0 : safte_ioctl(struct device *dev, u_long cmd, caddr_t addr)
555 : {
556 0 : struct safte_softc *sc = (struct safte_softc *)dev;
557 : int error = 0;
558 :
559 0 : switch (cmd) {
560 : case BIOCBLINK:
561 0 : error = safte_bio_blink(sc, (struct bioc_blink *)addr);
562 0 : break;
563 :
564 : default:
565 : error = EINVAL;
566 0 : break;
567 : }
568 :
569 0 : return (error);
570 : }
571 :
572 : int
573 0 : safte_bio_blink(struct safte_softc *sc, struct bioc_blink *blink)
574 : {
575 : struct safte_writebuf_cmd *cmd;
576 : struct safte_slotop *op;
577 : struct scsi_xfer *xs;
578 : int error, slot, flags = 0, wantblink;
579 :
580 0 : switch (blink->bb_status) {
581 : case BIOC_SBBLINK:
582 : wantblink = 1;
583 0 : break;
584 : case BIOC_SBUNBLINK:
585 : wantblink = 0;
586 0 : break;
587 : default:
588 0 : return (EINVAL);
589 : }
590 :
591 0 : rw_enter_read(&sc->sc_lock);
592 0 : for (slot = 0; slot < sc->sc_nslots; slot++) {
593 0 : if (sc->sc_slots[slot] == blink->bb_target)
594 : break;
595 : }
596 0 : rw_exit_read(&sc->sc_lock);
597 :
598 0 : if (slot >= sc->sc_nslots)
599 0 : return (ENODEV);
600 :
601 0 : op = dma_alloc(sizeof(*op), PR_WAITOK | PR_ZERO);
602 :
603 0 : op->opcode = SAFTE_WRITE_SLOTOP;
604 0 : op->slot = slot;
605 0 : op->flags |= wantblink ? SAFTE_SLOTOP_IDENTIFY : 0;
606 :
607 0 : if (cold)
608 0 : flags |= SCSI_AUTOCONF;
609 0 : xs = scsi_xs_get(sc->sc_link, flags | SCSI_DATA_OUT | SCSI_SILENT);
610 0 : if (xs == NULL) {
611 0 : dma_free(op, sizeof(*op));
612 0 : return (ENOMEM);
613 : }
614 0 : xs->cmdlen = sizeof(*cmd);
615 0 : xs->data = (void *)op;
616 0 : xs->datalen = sizeof(*op);
617 0 : xs->retries = 2;
618 0 : xs->timeout = 30000;
619 :
620 0 : cmd = (struct safte_writebuf_cmd *)xs->cmd;
621 0 : cmd->opcode = WRITE_BUFFER;
622 0 : cmd->flags |= SAFTE_WR_MODE;
623 0 : cmd->length = htobe16(sizeof(struct safte_slotop));
624 :
625 0 : error = scsi_xs_sync(xs);
626 0 : scsi_xs_put(xs);
627 :
628 0 : if (error != 0) {
629 : error = EIO;
630 0 : }
631 0 : dma_free(op, sizeof(*op));
632 :
633 0 : return (error);
634 0 : }
635 : #endif /* NBIO > 0 */
636 :
637 : int64_t
638 0 : safte_temp2uK(u_int8_t measured, int celsius)
639 : {
640 : int64_t temp;
641 :
642 0 : temp = (int64_t)measured;
643 0 : temp += SAFTE_TEMP_OFFSET;
644 0 : temp *= 1000000; /* convert to micro (mu) degrees */
645 0 : if (!celsius)
646 0 : temp = ((temp - 32000000) * 5) / 9; /* convert to Celsius */
647 :
648 0 : temp += 273150000; /* convert to kelvin */
649 :
650 0 : return (temp);
651 : }
|