safte.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. /* $OpenBSD: safte.c,v 1.52 2015/06/07 19:13:27 krw Exp $ */
  2. /*
  3. * Copyright (c) 2005 David Gwynne <dlg@openbsd.org>
  4. *
  5. * Permission to use, copy, modify, and distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. #include "bio.h"
  18. #include <sys/param.h>
  19. #include <sys/systm.h>
  20. #include <sys/device.h>
  21. #include <sys/scsiio.h>
  22. #include <sys/malloc.h>
  23. #include <sys/pool.h>
  24. #include <sys/rwlock.h>
  25. #include <sys/queue.h>
  26. #include <sys/sensors.h>
  27. #if NBIO > 0
  28. #include <dev/biovar.h>
  29. #endif
  30. #include <scsi/scsi_all.h>
  31. #include <scsi/scsiconf.h>
  32. #include <scsi/safte.h>
  33. #ifdef SAFTE_DEBUG
  34. #define DPRINTF(x) do { if (safte_debug) printf x ; } while (0)
  35. int safte_debug = 1;
  36. #else
  37. #define DPRINTF(x) /* x */
  38. #endif
  39. int safte_match(struct device *, void *, void *);
  40. void safte_attach(struct device *, struct device *, void *);
  41. int safte_detach(struct device *, int);
  42. struct safte_sensor {
  43. struct ksensor se_sensor;
  44. enum {
  45. SAFTE_T_FAN,
  46. SAFTE_T_PWRSUP,
  47. SAFTE_T_DOORLOCK,
  48. SAFTE_T_ALARM,
  49. SAFTE_T_TEMP
  50. } se_type;
  51. u_int8_t *se_field;
  52. };
  53. struct safte_softc {
  54. struct device sc_dev;
  55. struct scsi_link *sc_link;
  56. struct rwlock sc_lock;
  57. u_int sc_encbuflen;
  58. u_char *sc_encbuf;
  59. int sc_nsensors;
  60. struct safte_sensor *sc_sensors;
  61. struct ksensordev sc_sensordev;
  62. struct sensor_task *sc_sensortask;
  63. int sc_celsius;
  64. int sc_ntemps;
  65. struct safte_sensor *sc_temps;
  66. u_int8_t *sc_temperrs;
  67. #if NBIO > 0
  68. int sc_nslots;
  69. u_int8_t *sc_slots;
  70. #endif
  71. };
  72. struct cfattach safte_ca = {
  73. sizeof(struct safte_softc), safte_match, safte_attach, safte_detach
  74. };
  75. struct cfdriver safte_cd = {
  76. NULL, "safte", DV_DULL
  77. };
  78. #define DEVNAME(s) ((s)->sc_dev.dv_xname)
  79. int safte_read_config(struct safte_softc *);
  80. void safte_read_encstat(void *);
  81. #if NBIO > 0
  82. int safte_ioctl(struct device *, u_long, caddr_t);
  83. int safte_bio_blink(struct safte_softc *, struct bioc_blink *);
  84. #endif
  85. int64_t safte_temp2uK(u_int8_t, int);
  86. int
  87. safte_match(struct device *parent, void *match, void *aux)
  88. {
  89. struct scsi_inquiry_data *inqbuf;
  90. struct scsi_attach_args *sa = aux;
  91. struct scsi_inquiry_data *inq = sa->sa_inqbuf;
  92. struct scsi_xfer *xs;
  93. struct safte_inq *si;
  94. int error, flags = 0, length;
  95. if (inq == NULL)
  96. return (0);
  97. /* match on dell enclosures */
  98. if ((inq->device & SID_TYPE) == T_PROCESSOR &&
  99. SCSISPC(inq->version) == 3)
  100. return (2);
  101. if ((inq->device & SID_TYPE) != T_PROCESSOR ||
  102. SCSISPC(inq->version) != 2 ||
  103. (inq->response_format & SID_ANSII) != 2)
  104. return (0);
  105. length = inq->additional_length + SAFTE_EXTRA_OFFSET;
  106. if (length < SAFTE_INQ_LEN)
  107. return (0);
  108. if (length > sizeof(*inqbuf))
  109. length = sizeof(*inqbuf);
  110. inqbuf = dma_alloc(sizeof(*inqbuf), PR_NOWAIT | PR_ZERO);
  111. if (inqbuf == NULL)
  112. return (0);
  113. memset(inqbuf->extra, ' ', sizeof(inqbuf->extra));
  114. if (cold)
  115. flags |= SCSI_AUTOCONF;
  116. xs = scsi_xs_get(sa->sa_sc_link, flags | SCSI_DATA_IN);
  117. if (xs == NULL)
  118. goto fail;
  119. xs->retries = 2;
  120. xs->timeout = 10000;
  121. scsi_init_inquiry(xs, 0, 0, inqbuf, length);
  122. error = scsi_xs_sync(xs);
  123. scsi_xs_put(xs);
  124. if (error)
  125. goto fail;
  126. si = (struct safte_inq *)&inqbuf->extra;
  127. if (memcmp(si->ident, SAFTE_IDENT, sizeof(si->ident)) == 0) {
  128. dma_free(inqbuf, sizeof(*inqbuf));
  129. return (2);
  130. }
  131. fail:
  132. dma_free(inqbuf, sizeof(*inqbuf));
  133. return (0);
  134. }
  135. void
  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. sc->sc_link = sa->sa_sc_link;
  142. sa->sa_sc_link->device_softc = sc;
  143. rw_init(&sc->sc_lock, DEVNAME(sc));
  144. printf("\n");
  145. sc->sc_encbuf = NULL;
  146. sc->sc_nsensors = 0;
  147. #if NBIO > 0
  148. sc->sc_nslots = 0;
  149. #endif
  150. if (safte_read_config(sc) != 0) {
  151. printf("%s: unable to read enclosure configuration\n",
  152. DEVNAME(sc));
  153. return;
  154. }
  155. if (sc->sc_nsensors > 0) {
  156. sc->sc_sensortask = sensor_task_register(sc,
  157. safte_read_encstat, 10);
  158. if (sc->sc_sensortask == NULL) {
  159. printf("%s: unable to register update task\n",
  160. DEVNAME(sc));
  161. sc->sc_nsensors = sc->sc_ntemps = 0;
  162. free(sc->sc_sensors, M_DEVBUF, 0);
  163. } else {
  164. for (i = 0; i < sc->sc_nsensors; i++)
  165. sensor_attach(&sc->sc_sensordev,
  166. &sc->sc_sensors[i].se_sensor);
  167. sensordev_install(&sc->sc_sensordev);
  168. }
  169. }
  170. #if NBIO > 0
  171. if (sc->sc_nslots > 0 &&
  172. bio_register(self, safte_ioctl) != 0) {
  173. printf("%s: unable to register ioctl with bio\n", DEVNAME(sc));
  174. sc->sc_nslots = 0;
  175. } else
  176. i++;
  177. #endif
  178. if (i) /* if we're doing something, then preinit encbuf and sensors */
  179. safte_read_encstat(sc);
  180. else {
  181. dma_free(sc->sc_encbuf, sc->sc_encbuflen);
  182. sc->sc_encbuf = NULL;
  183. }
  184. }
  185. int
  186. safte_detach(struct device *self, int flags)
  187. {
  188. struct safte_softc *sc = (struct safte_softc *)self;
  189. int i;
  190. rw_enter_write(&sc->sc_lock);
  191. #if NBIO > 0
  192. if (sc->sc_nslots > 0)
  193. bio_unregister(self);
  194. #endif
  195. if (sc->sc_nsensors > 0) {
  196. sensordev_deinstall(&sc->sc_sensordev);
  197. sensor_task_unregister(sc->sc_sensortask);
  198. for (i = 0; i < sc->sc_nsensors; i++)
  199. sensor_detach(&sc->sc_sensordev,
  200. &sc->sc_sensors[i].se_sensor);
  201. free(sc->sc_sensors, M_DEVBUF, 0);
  202. }
  203. if (sc->sc_encbuf != NULL)
  204. dma_free(sc->sc_encbuf, sc->sc_encbuflen);
  205. rw_exit_write(&sc->sc_lock);
  206. return (0);
  207. }
  208. int
  209. safte_read_config(struct safte_softc *sc)
  210. {
  211. struct safte_config *config = NULL;
  212. struct safte_readbuf_cmd *cmd;
  213. struct safte_sensor *s;
  214. struct scsi_xfer *xs;
  215. int error = 0, flags = 0, i, j;
  216. config = dma_alloc(sizeof(*config), PR_NOWAIT);
  217. if (config == NULL)
  218. return (1);
  219. if (cold)
  220. flags |= SCSI_AUTOCONF;
  221. xs = scsi_xs_get(sc->sc_link, flags | SCSI_DATA_IN | SCSI_SILENT);
  222. if (xs == NULL) {
  223. error = 1;
  224. goto done;
  225. }
  226. xs->cmdlen = sizeof(*cmd);
  227. xs->data = (void *)config;
  228. xs->datalen = sizeof(*config);
  229. xs->retries = 2;
  230. xs->timeout = 30000;
  231. cmd = (struct safte_readbuf_cmd *)xs->cmd;
  232. cmd->opcode = READ_BUFFER;
  233. cmd->flags |= SAFTE_RD_MODE;
  234. cmd->bufferid = SAFTE_RD_CONFIG;
  235. cmd->length = htobe16(sizeof(*config));
  236. error = scsi_xs_sync(xs);
  237. scsi_xs_put(xs);
  238. if (error != 0) {
  239. error = 1;
  240. goto done;
  241. }
  242. DPRINTF(("%s: nfans: %d npwrsup: %d nslots: %d doorlock: %d ntemps: %d"
  243. " alarm: %d celsius: %d ntherm: %d\n", DEVNAME(sc), config->nfans,
  244. config->npwrsup, config->nslots, config->doorlock, config->ntemps,
  245. config->alarm, SAFTE_CFG_CELSIUS(config->therm),
  246. SAFTE_CFG_NTHERM(config->therm)));
  247. sc->sc_encbuflen = config->nfans * sizeof(u_int8_t) + /* fan status */
  248. config->npwrsup * sizeof(u_int8_t) + /* power supply status */
  249. config->nslots * sizeof(u_int8_t) + /* device scsi id (lun) */
  250. sizeof(u_int8_t) + /* door lock status */
  251. sizeof(u_int8_t) + /* speaker status */
  252. config->ntemps * sizeof(u_int8_t) + /* temp sensors */
  253. sizeof(u_int16_t); /* temp out of range sensors */
  254. sc->sc_encbuf = dma_alloc(sc->sc_encbuflen, PR_NOWAIT);
  255. if (sc->sc_encbuf == NULL) {
  256. error = 1;
  257. goto done;
  258. }
  259. sc->sc_nsensors = config->nfans + config->npwrsup + config->ntemps +
  260. (config->doorlock ? 1 : 0) + (config->alarm ? 1 : 0);
  261. sc->sc_sensors = mallocarray(sc->sc_nsensors, sizeof(struct safte_sensor),
  262. M_DEVBUF, M_NOWAIT | M_ZERO);
  263. if (sc->sc_sensors == NULL) {
  264. dma_free(sc->sc_encbuf, sc->sc_encbuflen);
  265. sc->sc_encbuf = NULL;
  266. sc->sc_nsensors = 0;
  267. error = 1;
  268. goto done;
  269. }
  270. strlcpy(sc->sc_sensordev.xname, DEVNAME(sc),
  271. sizeof(sc->sc_sensordev.xname));
  272. s = sc->sc_sensors;
  273. for (i = 0; i < config->nfans; i++) {
  274. s->se_type = SAFTE_T_FAN;
  275. s->se_field = (u_int8_t *)(sc->sc_encbuf + i);
  276. s->se_sensor.type = SENSOR_INDICATOR;
  277. snprintf(s->se_sensor.desc, sizeof(s->se_sensor.desc),
  278. "Fan%d", i);
  279. s++;
  280. }
  281. j = config->nfans;
  282. for (i = 0; i < config->npwrsup; i++) {
  283. s->se_type = SAFTE_T_PWRSUP;
  284. s->se_field = (u_int8_t *)(sc->sc_encbuf + j + i);
  285. s->se_sensor.type = SENSOR_INDICATOR;
  286. snprintf(s->se_sensor.desc, sizeof(s->se_sensor.desc),
  287. "PSU%d", i);
  288. s++;
  289. }
  290. j += config->npwrsup;
  291. #if NBIO > 0
  292. sc->sc_nslots = config->nslots;
  293. sc->sc_slots = (u_int8_t *)(sc->sc_encbuf + j);
  294. #endif
  295. j += config->nslots;
  296. if (config->doorlock) {
  297. s->se_type = SAFTE_T_DOORLOCK;
  298. s->se_field = (u_int8_t *)(sc->sc_encbuf + j);
  299. s->se_sensor.type = SENSOR_INDICATOR;
  300. strlcpy(s->se_sensor.desc, "doorlock",
  301. sizeof(s->se_sensor.desc));
  302. s++;
  303. }
  304. j++;
  305. if (config->alarm) {
  306. s->se_type = SAFTE_T_ALARM;
  307. s->se_field = (u_int8_t *)(sc->sc_encbuf + j);
  308. s->se_sensor.type = SENSOR_INDICATOR;
  309. strlcpy(s->se_sensor.desc, "alarm", sizeof(s->se_sensor.desc));
  310. s++;
  311. }
  312. j++;
  313. /*
  314. * stash the temp info so we can get out of range status. limit the
  315. * number so the out of temp checks cant go into memory it doesnt own
  316. */
  317. sc->sc_ntemps = (config->ntemps > 15) ? 15 : config->ntemps;
  318. sc->sc_temps = s;
  319. sc->sc_celsius = SAFTE_CFG_CELSIUS(config->therm);
  320. for (i = 0; i < config->ntemps; i++) {
  321. s->se_type = SAFTE_T_TEMP;
  322. s->se_field = (u_int8_t *)(sc->sc_encbuf + j + i);
  323. s->se_sensor.type = SENSOR_TEMP;
  324. s++;
  325. }
  326. j += config->ntemps;
  327. sc->sc_temperrs = (u_int8_t *)(sc->sc_encbuf + j);
  328. done:
  329. dma_free(config, sizeof(*config));
  330. return (error);
  331. }
  332. void
  333. safte_read_encstat(void *arg)
  334. {
  335. struct safte_readbuf_cmd *cmd;
  336. struct safte_sensor *s;
  337. struct safte_softc *sc = (struct safte_softc *)arg;
  338. struct scsi_xfer *xs;
  339. int error, i, flags = 0;
  340. u_int16_t oot;
  341. rw_enter_write(&sc->sc_lock);
  342. if (cold)
  343. flags |= SCSI_AUTOCONF;
  344. xs = scsi_xs_get(sc->sc_link, flags | SCSI_DATA_IN | SCSI_SILENT);
  345. if (xs == NULL) {
  346. rw_exit_write(&sc->sc_lock);
  347. return;
  348. }
  349. xs->cmdlen = sizeof(*cmd);
  350. xs->data = sc->sc_encbuf;
  351. xs->datalen = sc->sc_encbuflen;
  352. xs->retries = 2;
  353. xs->timeout = 30000;
  354. cmd = (struct safte_readbuf_cmd *)xs->cmd;
  355. cmd->opcode = READ_BUFFER;
  356. cmd->flags |= SAFTE_RD_MODE;
  357. cmd->bufferid = SAFTE_RD_ENCSTAT;
  358. cmd->length = htobe16(sc->sc_encbuflen);
  359. error = scsi_xs_sync(xs);
  360. scsi_xs_put(xs);
  361. if (error != 0) {
  362. rw_exit_write(&sc->sc_lock);
  363. return;
  364. }
  365. for (i = 0; i < sc->sc_nsensors; i++) {
  366. s = &sc->sc_sensors[i];
  367. s->se_sensor.flags &= ~SENSOR_FUNKNOWN;
  368. DPRINTF(("%s: %d type: %d field: 0x%02x\n", DEVNAME(sc), i,
  369. s->se_type, *s->se_field));
  370. switch (s->se_type) {
  371. case SAFTE_T_FAN:
  372. switch (*s->se_field) {
  373. case SAFTE_FAN_OP:
  374. s->se_sensor.value = 1;
  375. s->se_sensor.status = SENSOR_S_OK;
  376. break;
  377. case SAFTE_FAN_MF:
  378. s->se_sensor.value = 0;
  379. s->se_sensor.status = SENSOR_S_CRIT;
  380. break;
  381. case SAFTE_FAN_NOTINST:
  382. case SAFTE_FAN_UNKNOWN:
  383. default:
  384. s->se_sensor.value = 0;
  385. s->se_sensor.status = SENSOR_S_UNKNOWN;
  386. s->se_sensor.flags |= SENSOR_FUNKNOWN;
  387. break;
  388. }
  389. break;
  390. case SAFTE_T_PWRSUP:
  391. switch (*s->se_field) {
  392. case SAFTE_PWR_OP_ON:
  393. s->se_sensor.value = 1;
  394. s->se_sensor.status = SENSOR_S_OK;
  395. break;
  396. case SAFTE_PWR_OP_OFF:
  397. s->se_sensor.value = 0;
  398. s->se_sensor.status = SENSOR_S_OK;
  399. break;
  400. case SAFTE_PWR_MF_ON:
  401. s->se_sensor.value = 1;
  402. s->se_sensor.status = SENSOR_S_CRIT;
  403. break;
  404. case SAFTE_PWR_MF_OFF:
  405. s->se_sensor.value = 0;
  406. s->se_sensor.status = SENSOR_S_CRIT;
  407. break;
  408. case SAFTE_PWR_NOTINST:
  409. case SAFTE_PWR_PRESENT:
  410. case SAFTE_PWR_UNKNOWN:
  411. s->se_sensor.value = 0;
  412. s->se_sensor.status = SENSOR_S_UNKNOWN;
  413. s->se_sensor.flags |= SENSOR_FUNKNOWN;
  414. break;
  415. }
  416. break;
  417. case SAFTE_T_DOORLOCK:
  418. switch (*s->se_field) {
  419. case SAFTE_DOOR_LOCKED:
  420. s->se_sensor.value = 1;
  421. s->se_sensor.status = SENSOR_S_OK;
  422. break;
  423. case SAFTE_DOOR_UNLOCKED:
  424. s->se_sensor.value = 0;
  425. s->se_sensor.status = SENSOR_S_CRIT;
  426. break;
  427. case SAFTE_DOOR_UNKNOWN:
  428. s->se_sensor.value = 0;
  429. s->se_sensor.status = SENSOR_S_CRIT;
  430. s->se_sensor.flags |= SENSOR_FUNKNOWN;
  431. break;
  432. }
  433. break;
  434. case SAFTE_T_ALARM:
  435. switch (*s->se_field) {
  436. case SAFTE_SPKR_OFF:
  437. s->se_sensor.value = 0;
  438. s->se_sensor.status = SENSOR_S_OK;
  439. break;
  440. case SAFTE_SPKR_ON:
  441. s->se_sensor.value = 1;
  442. s->se_sensor.status = SENSOR_S_CRIT;
  443. break;
  444. }
  445. break;
  446. case SAFTE_T_TEMP:
  447. s->se_sensor.value = safte_temp2uK(*s->se_field,
  448. sc->sc_celsius);
  449. break;
  450. }
  451. }
  452. oot = _2btol(sc->sc_temperrs);
  453. for (i = 0; i < sc->sc_ntemps; i++)
  454. sc->sc_temps[i].se_sensor.status =
  455. (oot & (1 << i)) ? SENSOR_S_CRIT : SENSOR_S_OK;
  456. rw_exit_write(&sc->sc_lock);
  457. }
  458. #if NBIO > 0
  459. int
  460. safte_ioctl(struct device *dev, u_long cmd, caddr_t addr)
  461. {
  462. struct safte_softc *sc = (struct safte_softc *)dev;
  463. int error = 0;
  464. switch (cmd) {
  465. case BIOCBLINK:
  466. error = safte_bio_blink(sc, (struct bioc_blink *)addr);
  467. break;
  468. default:
  469. error = EINVAL;
  470. break;
  471. }
  472. return (error);
  473. }
  474. int
  475. safte_bio_blink(struct safte_softc *sc, struct bioc_blink *blink)
  476. {
  477. struct safte_writebuf_cmd *cmd;
  478. struct safte_slotop *op;
  479. struct scsi_xfer *xs;
  480. int error, slot, flags = 0, wantblink;
  481. switch (blink->bb_status) {
  482. case BIOC_SBBLINK:
  483. wantblink = 1;
  484. break;
  485. case BIOC_SBUNBLINK:
  486. wantblink = 0;
  487. break;
  488. default:
  489. return (EINVAL);
  490. }
  491. rw_enter_read(&sc->sc_lock);
  492. for (slot = 0; slot < sc->sc_nslots; slot++) {
  493. if (sc->sc_slots[slot] == blink->bb_target)
  494. break;
  495. }
  496. rw_exit_read(&sc->sc_lock);
  497. if (slot >= sc->sc_nslots)
  498. return (ENODEV);
  499. op = dma_alloc(sizeof(*op), PR_WAITOK | PR_ZERO);
  500. op->opcode = SAFTE_WRITE_SLOTOP;
  501. op->slot = slot;
  502. op->flags |= wantblink ? SAFTE_SLOTOP_IDENTIFY : 0;
  503. if (cold)
  504. flags |= SCSI_AUTOCONF;
  505. xs = scsi_xs_get(sc->sc_link, flags | SCSI_DATA_OUT | SCSI_SILENT);
  506. if (xs == NULL) {
  507. dma_free(op, sizeof(*op));
  508. return (ENOMEM);
  509. }
  510. xs->cmdlen = sizeof(*cmd);
  511. xs->data = (void *)op;
  512. xs->datalen = sizeof(*op);
  513. xs->retries = 2;
  514. xs->timeout = 30000;
  515. cmd = (struct safte_writebuf_cmd *)xs->cmd;
  516. cmd->opcode = WRITE_BUFFER;
  517. cmd->flags |= SAFTE_WR_MODE;
  518. cmd->length = htobe16(sizeof(struct safte_slotop));
  519. error = scsi_xs_sync(xs);
  520. scsi_xs_put(xs);
  521. if (error != 0) {
  522. error = EIO;
  523. }
  524. dma_free(op, sizeof(*op));
  525. return (error);
  526. }
  527. #endif /* NBIO > 0 */
  528. int64_t
  529. safte_temp2uK(u_int8_t measured, int celsius)
  530. {
  531. int64_t temp;
  532. temp = (int64_t)measured;
  533. temp += SAFTE_TEMP_OFFSET;
  534. temp *= 1000000; /* convert to micro (mu) degrees */
  535. if (!celsius)
  536. temp = ((temp - 32000000) * 5) / 9; /* convert to Celsius */
  537. temp += 273150000; /* convert to kelvin */
  538. return (temp);
  539. }