1*9593dc34Smglocker /* $OpenBSD: safte.c,v 1.68 2024/09/04 07:54:53 mglocker Exp $ */ 2d596fd10Sdlg 3d596fd10Sdlg /* 4d596fd10Sdlg * Copyright (c) 2005 David Gwynne <dlg@openbsd.org> 5d596fd10Sdlg * 6d596fd10Sdlg * Permission to use, copy, modify, and distribute this software for any 7d596fd10Sdlg * purpose with or without fee is hereby granted, provided that the above 8d596fd10Sdlg * copyright notice and this permission notice appear in all copies. 9d596fd10Sdlg * 10d596fd10Sdlg * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11d596fd10Sdlg * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12d596fd10Sdlg * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13d596fd10Sdlg * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14d596fd10Sdlg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15d596fd10Sdlg * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16d596fd10Sdlg * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17d596fd10Sdlg */ 18d596fd10Sdlg 197579196dSdlg #include "bio.h" 207579196dSdlg 21d596fd10Sdlg #include <sys/param.h> 22d596fd10Sdlg #include <sys/systm.h> 231122f506Sfgsch #include <sys/device.h> 24d596fd10Sdlg #include <sys/scsiio.h> 25d596fd10Sdlg #include <sys/malloc.h> 265c0b007dSderaadt #include <sys/pool.h> 2760eafd6fSdlg #include <sys/rwlock.h> 28d596fd10Sdlg #include <sys/queue.h> 29d596fd10Sdlg #include <sys/sensors.h> 30d596fd10Sdlg 317579196dSdlg #if NBIO > 0 327579196dSdlg #include <dev/biovar.h> 33364ebb70Skrw #endif /* NBIO > 0 */ 347579196dSdlg 35d596fd10Sdlg #include <scsi/scsi_all.h> 36d596fd10Sdlg #include <scsi/scsiconf.h> 37d596fd10Sdlg 38d596fd10Sdlg #include <scsi/safte.h> 39d596fd10Sdlg 40d596fd10Sdlg #ifdef SAFTE_DEBUG 41d596fd10Sdlg #define DPRINTF(x) do { if (safte_debug) printf x ; } while (0) 42d596fd10Sdlg int safte_debug = 1; 43d596fd10Sdlg #else 44d596fd10Sdlg #define DPRINTF(x) /* x */ 45364ebb70Skrw #endif /* SAFTE_DEBUG */ 46d596fd10Sdlg 47d596fd10Sdlg 48d596fd10Sdlg int safte_match(struct device *, void *, void *); 49d596fd10Sdlg void safte_attach(struct device *, struct device *, void *); 50d596fd10Sdlg int safte_detach(struct device *, int); 51d596fd10Sdlg 52816e8e59Sdlg struct safte_sensor { 53275cbf62Sderaadt struct ksensor se_sensor; 54816e8e59Sdlg enum { 55816e8e59Sdlg SAFTE_T_FAN, 56816e8e59Sdlg SAFTE_T_PWRSUP, 57816e8e59Sdlg SAFTE_T_DOORLOCK, 58816e8e59Sdlg SAFTE_T_ALARM, 59816e8e59Sdlg SAFTE_T_TEMP 60816e8e59Sdlg } se_type; 61816e8e59Sdlg u_int8_t *se_field; 62816e8e59Sdlg }; 63816e8e59Sdlg 64d596fd10Sdlg struct safte_softc { 65d596fd10Sdlg struct device sc_dev; 66d596fd10Sdlg struct scsi_link *sc_link; 6760eafd6fSdlg struct rwlock sc_lock; 68d596fd10Sdlg 69816e8e59Sdlg u_int sc_encbuflen; 70d596fd10Sdlg u_char *sc_encbuf; 71d596fd10Sdlg 72d596fd10Sdlg int sc_nsensors; 73816e8e59Sdlg struct safte_sensor *sc_sensors; 74275cbf62Sderaadt struct ksensordev sc_sensordev; 75abd9fc28Sdlg struct sensor_task *sc_sensortask; 76816e8e59Sdlg 77816e8e59Sdlg int sc_celsius; 78816e8e59Sdlg int sc_ntemps; 79816e8e59Sdlg struct safte_sensor *sc_temps; 80a104ef5fSkettenis u_int8_t *sc_temperrs; 81816e8e59Sdlg 827579196dSdlg #if NBIO > 0 837579196dSdlg int sc_nslots; 847579196dSdlg u_int8_t *sc_slots; 85364ebb70Skrw #endif /* NBIO > 0 */ 86d596fd10Sdlg }; 87d596fd10Sdlg 889eaf72d1Smpi const struct cfattach safte_ca = { 89d596fd10Sdlg sizeof(struct safte_softc), safte_match, safte_attach, safte_detach 90d596fd10Sdlg }; 91d596fd10Sdlg 92d596fd10Sdlg struct cfdriver safte_cd = { 93d596fd10Sdlg NULL, "safte", DV_DULL 94d596fd10Sdlg }; 95d596fd10Sdlg 96d596fd10Sdlg #define DEVNAME(s) ((s)->sc_dev.dv_xname) 97d596fd10Sdlg 98d596fd10Sdlg int safte_read_config(struct safte_softc *); 99b054292eSdlg void safte_read_encstat(void *); 100d596fd10Sdlg 1017579196dSdlg #if NBIO > 0 1027579196dSdlg int safte_ioctl(struct device *, u_long, caddr_t); 1037579196dSdlg int safte_bio_blink(struct safte_softc *, struct bioc_blink *); 104364ebb70Skrw #endif /* NBIO > 0 */ 1057579196dSdlg 106d596fd10Sdlg int64_t safte_temp2uK(u_int8_t, int); 107d596fd10Sdlg 108d596fd10Sdlg int 109d596fd10Sdlg safte_match(struct device *parent, void *match, void *aux) 110d596fd10Sdlg { 111a0837789Sdlg struct scsi_attach_args *sa = aux; 1120fbd355cSkrw struct scsi_inquiry_data *inq = &sa->sa_sc_link->inqdata; 113f8bbb75aSkrw struct safte_inq *si; 114f8bbb75aSkrw 11557343048Skrw /* Match on Dell enclosures. */ 116bf821d43Sdlg if ((inq->device & SID_TYPE) == T_PROCESSOR && 1177b732f28Skrw SID_ANSII_REV(inq) == SCSI_REV_SPC) 11857343048Skrw return 2; 119bf821d43Sdlg 120d596fd10Sdlg if ((inq->device & SID_TYPE) != T_PROCESSOR || 1217b732f28Skrw SID_ANSII_REV(inq) != SCSI_REV_2 || 1223da569d0Skrw SID_RESPONSE_FORMAT(inq) != SID_SCSI2_RESPONSE) 12357343048Skrw return 0; 124d596fd10Sdlg 12596a16d09Skrw if (inq->additional_length < SID_SCSI2_ALEN + sizeof(*si)) 12657343048Skrw return 0; 1275c0b007dSderaadt 12896a16d09Skrw si = (struct safte_inq *)&inq->extra; 12996a16d09Skrw if (memcmp(si->ident, SAFTE_IDENT, sizeof(si->ident)) == 0) 13057343048Skrw return 2; 131d596fd10Sdlg 13257343048Skrw return 0; 133d596fd10Sdlg } 134d596fd10Sdlg 135d596fd10Sdlg void 136d596fd10Sdlg safte_attach(struct device *parent, struct device *self, void *aux) 137d596fd10Sdlg { 138d596fd10Sdlg struct safte_softc *sc = (struct safte_softc *)self; 139a0837789Sdlg struct scsi_attach_args *sa = aux; 1401e5a5352Sdlg int i = 0; 141d596fd10Sdlg 142d596fd10Sdlg sc->sc_link = sa->sa_sc_link; 143ba35ccc6Smarco sa->sa_sc_link->device_softc = sc; 14460eafd6fSdlg rw_init(&sc->sc_lock, DEVNAME(sc)); 145d596fd10Sdlg 14652c6b24cSdlg printf("\n"); 147d596fd10Sdlg 148b054292eSdlg sc->sc_encbuf = NULL; 149b054292eSdlg sc->sc_nsensors = 0; 1503974dfb4Sdlg #if NBIO > 0 151b054292eSdlg sc->sc_nslots = 0; 152364ebb70Skrw #endif /* NBIO > 0 */ 1537579196dSdlg 154d596fd10Sdlg if (safte_read_config(sc) != 0) { 155d596fd10Sdlg printf("%s: unable to read enclosure configuration\n", 156d596fd10Sdlg DEVNAME(sc)); 157d596fd10Sdlg return; 158d596fd10Sdlg } 159d596fd10Sdlg 160abd9fc28Sdlg if (sc->sc_nsensors > 0) { 161abd9fc28Sdlg sc->sc_sensortask = sensor_task_register(sc, 162abd9fc28Sdlg safte_read_encstat, 10); 163abd9fc28Sdlg if (sc->sc_sensortask == NULL) { 164abd9fc28Sdlg printf("%s: unable to register update task\n", 165abd9fc28Sdlg DEVNAME(sc)); 166a67129dbStedu free(sc->sc_sensors, M_DEVBUF, 167a67129dbStedu sc->sc_nsensors * sizeof(struct safte_sensor)); 1681e5a5352Sdlg sc->sc_nsensors = sc->sc_ntemps = 0; 169b054292eSdlg } else { 170b054292eSdlg for (i = 0; i < sc->sc_nsensors; i++) 17127515a6bSderaadt sensor_attach(&sc->sc_sensordev, 17227515a6bSderaadt &sc->sc_sensors[i].se_sensor); 17327515a6bSderaadt sensordev_install(&sc->sc_sensordev); 174b054292eSdlg } 175abd9fc28Sdlg } 176b054292eSdlg 177b054292eSdlg #if NBIO > 0 178b054292eSdlg if (sc->sc_nslots > 0 && 179b054292eSdlg bio_register(self, safte_ioctl) != 0) { 180b054292eSdlg printf("%s: unable to register ioctl with bio\n", DEVNAME(sc)); 181b054292eSdlg sc->sc_nslots = 0; 1821e5a5352Sdlg } else 1831e5a5352Sdlg i++; 184364ebb70Skrw #endif /* NBIO > 0 */ 1851e5a5352Sdlg 1861e5a5352Sdlg if (i) /* if we're doing something, then preinit encbuf and sensors */ 1871e5a5352Sdlg safte_read_encstat(sc); 1881e5a5352Sdlg else { 1895c0b007dSderaadt dma_free(sc->sc_encbuf, sc->sc_encbuflen); 1901e5a5352Sdlg sc->sc_encbuf = NULL; 1911e5a5352Sdlg } 192d596fd10Sdlg } 193d596fd10Sdlg 194d596fd10Sdlg int 195d596fd10Sdlg safte_detach(struct device *self, int flags) 196d596fd10Sdlg { 197d596fd10Sdlg struct safte_softc *sc = (struct safte_softc *)self; 198d596fd10Sdlg int i; 199d596fd10Sdlg 20060eafd6fSdlg rw_enter_write(&sc->sc_lock); 2019c336412Sdlg 2027579196dSdlg #if NBIO > 0 203b054292eSdlg if (sc->sc_nslots > 0) 2047579196dSdlg bio_unregister(self); 205364ebb70Skrw #endif /* NBIO > 0 */ 2067579196dSdlg 207b054292eSdlg if (sc->sc_nsensors > 0) { 20827515a6bSderaadt sensordev_deinstall(&sc->sc_sensordev); 209abd9fc28Sdlg sensor_task_unregister(sc->sc_sensortask); 210b054292eSdlg 211d596fd10Sdlg for (i = 0; i < sc->sc_nsensors; i++) 21227515a6bSderaadt sensor_detach(&sc->sc_sensordev, 21327515a6bSderaadt &sc->sc_sensors[i].se_sensor); 214a67129dbStedu free(sc->sc_sensors, M_DEVBUF, 215a67129dbStedu sc->sc_nsensors * sizeof(struct safte_sensor)); 216d596fd10Sdlg } 217d596fd10Sdlg 218b054292eSdlg if (sc->sc_encbuf != NULL) 2195c0b007dSderaadt dma_free(sc->sc_encbuf, sc->sc_encbuflen); 220b054292eSdlg 22160eafd6fSdlg rw_exit_write(&sc->sc_lock); 2229c336412Sdlg 22357343048Skrw return 0; 224d596fd10Sdlg } 225d596fd10Sdlg 226d596fd10Sdlg int 227d596fd10Sdlg safte_read_config(struct safte_softc *sc) 228d596fd10Sdlg { 2295c0b007dSderaadt struct safte_config *config = NULL; 230f8bbb75aSkrw struct safte_readbuf_cmd *cmd; 231816e8e59Sdlg struct safte_sensor *s; 232f8bbb75aSkrw struct scsi_xfer *xs; 2335c0b007dSderaadt int error = 0, flags = 0, i, j; 2345c0b007dSderaadt 2355c0b007dSderaadt config = dma_alloc(sizeof(*config), PR_NOWAIT); 2365c0b007dSderaadt if (config == NULL) 23757343048Skrw return 1; 238d596fd10Sdlg 2397351cb62Smarco if (cold) 240dacf4336Skrw SET(flags, SCSI_AUTOCONF); 241f8bbb75aSkrw xs = scsi_xs_get(sc->sc_link, flags | SCSI_DATA_IN | SCSI_SILENT); 2425c0b007dSderaadt if (xs == NULL) { 2435c0b007dSderaadt error = 1; 2445c0b007dSderaadt goto done; 2455c0b007dSderaadt } 246f8bbb75aSkrw xs->cmdlen = sizeof(*cmd); 2475c0b007dSderaadt xs->data = (void *)config; 2485c0b007dSderaadt xs->datalen = sizeof(*config); 249f8bbb75aSkrw xs->retries = 2; 250f8bbb75aSkrw xs->timeout = 30000; 251cc96c0e3Sderaadt 252664c6166Skrw cmd = (struct safte_readbuf_cmd *)&xs->cmd; 25349227f1aSmatthew cmd->opcode = READ_BUFFER; 254dacf4336Skrw SET(cmd->flags, SAFTE_RD_MODE); 255f8bbb75aSkrw cmd->bufferid = SAFTE_RD_CONFIG; 2565c0b007dSderaadt cmd->length = htobe16(sizeof(*config)); 257f8bbb75aSkrw 258f8bbb75aSkrw error = scsi_xs_sync(xs); 259f8bbb75aSkrw scsi_xs_put(xs); 260f8bbb75aSkrw 2615c0b007dSderaadt if (error != 0) { 2625c0b007dSderaadt error = 1; 2635c0b007dSderaadt goto done; 2645c0b007dSderaadt } 265d596fd10Sdlg 266d596fd10Sdlg DPRINTF(("%s: nfans: %d npwrsup: %d nslots: %d doorlock: %d ntemps: %d" 2675c0b007dSderaadt " alarm: %d celsius: %d ntherm: %d\n", DEVNAME(sc), config->nfans, 2685c0b007dSderaadt config->npwrsup, config->nslots, config->doorlock, config->ntemps, 2695c0b007dSderaadt config->alarm, SAFTE_CFG_CELSIUS(config->therm), 2705c0b007dSderaadt SAFTE_CFG_NTHERM(config->therm))); 271d596fd10Sdlg 2725c0b007dSderaadt sc->sc_encbuflen = config->nfans * sizeof(u_int8_t) + /* fan status */ 2735c0b007dSderaadt config->npwrsup * sizeof(u_int8_t) + /* power supply status */ 2745c0b007dSderaadt config->nslots * sizeof(u_int8_t) + /* device scsi id (lun) */ 275816e8e59Sdlg sizeof(u_int8_t) + /* door lock status */ 276816e8e59Sdlg sizeof(u_int8_t) + /* speaker status */ 2775c0b007dSderaadt config->ntemps * sizeof(u_int8_t) + /* temp sensors */ 278816e8e59Sdlg sizeof(u_int16_t); /* temp out of range sensors */ 279816e8e59Sdlg 2805c0b007dSderaadt sc->sc_encbuf = dma_alloc(sc->sc_encbuflen, PR_NOWAIT); 2815c0b007dSderaadt if (sc->sc_encbuf == NULL) { 2825c0b007dSderaadt error = 1; 2835c0b007dSderaadt goto done; 2845c0b007dSderaadt } 285816e8e59Sdlg 2865c0b007dSderaadt sc->sc_nsensors = config->nfans + config->npwrsup + config->ntemps + 2875c0b007dSderaadt (config->doorlock ? 1 : 0) + (config->alarm ? 1 : 0); 288816e8e59Sdlg 28957343048Skrw sc->sc_sensors = mallocarray(sc->sc_nsensors, 29057343048Skrw sizeof(struct safte_sensor), M_DEVBUF, M_NOWAIT | M_ZERO); 291816e8e59Sdlg if (sc->sc_sensors == NULL) { 2925c0b007dSderaadt dma_free(sc->sc_encbuf, sc->sc_encbuflen); 293b054292eSdlg sc->sc_encbuf = NULL; 294b054292eSdlg sc->sc_nsensors = 0; 2955c0b007dSderaadt error = 1; 2965c0b007dSderaadt goto done; 297816e8e59Sdlg } 298816e8e59Sdlg 29927515a6bSderaadt strlcpy(sc->sc_sensordev.xname, DEVNAME(sc), 30027515a6bSderaadt sizeof(sc->sc_sensordev.xname)); 30127515a6bSderaadt 302816e8e59Sdlg s = sc->sc_sensors; 303816e8e59Sdlg 3045c0b007dSderaadt for (i = 0; i < config->nfans; i++) { 305816e8e59Sdlg s->se_type = SAFTE_T_FAN; 306816e8e59Sdlg s->se_field = (u_int8_t *)(sc->sc_encbuf + i); 307816e8e59Sdlg s->se_sensor.type = SENSOR_INDICATOR; 308816e8e59Sdlg snprintf(s->se_sensor.desc, sizeof(s->se_sensor.desc), 3097447b807Sderaadt "Fan%d", i); 310816e8e59Sdlg 311816e8e59Sdlg s++; 312816e8e59Sdlg } 3135c0b007dSderaadt j = config->nfans; 314816e8e59Sdlg 3155c0b007dSderaadt for (i = 0; i < config->npwrsup; i++) { 316816e8e59Sdlg s->se_type = SAFTE_T_PWRSUP; 31753668107Sdlg s->se_field = (u_int8_t *)(sc->sc_encbuf + j + i); 318816e8e59Sdlg s->se_sensor.type = SENSOR_INDICATOR; 319816e8e59Sdlg snprintf(s->se_sensor.desc, sizeof(s->se_sensor.desc), 3207447b807Sderaadt "PSU%d", i); 321816e8e59Sdlg 322816e8e59Sdlg s++; 323816e8e59Sdlg } 3245c0b007dSderaadt j += config->npwrsup; 3257579196dSdlg 3267579196dSdlg #if NBIO > 0 3275c0b007dSderaadt sc->sc_nslots = config->nslots; 3287579196dSdlg sc->sc_slots = (u_int8_t *)(sc->sc_encbuf + j); 329364ebb70Skrw #endif /* NBIO > 0 */ 3305c0b007dSderaadt j += config->nslots; 331816e8e59Sdlg 3325c0b007dSderaadt if (config->doorlock) { 333816e8e59Sdlg s->se_type = SAFTE_T_DOORLOCK; 334816e8e59Sdlg s->se_field = (u_int8_t *)(sc->sc_encbuf + j); 335816e8e59Sdlg s->se_sensor.type = SENSOR_INDICATOR; 336816e8e59Sdlg strlcpy(s->se_sensor.desc, "doorlock", 337816e8e59Sdlg sizeof(s->se_sensor.desc)); 338816e8e59Sdlg 339816e8e59Sdlg s++; 340816e8e59Sdlg } 341816e8e59Sdlg j++; 342816e8e59Sdlg 3435c0b007dSderaadt if (config->alarm) { 344816e8e59Sdlg s->se_type = SAFTE_T_ALARM; 345816e8e59Sdlg s->se_field = (u_int8_t *)(sc->sc_encbuf + j); 346816e8e59Sdlg s->se_sensor.type = SENSOR_INDICATOR; 347816e8e59Sdlg strlcpy(s->se_sensor.desc, "alarm", sizeof(s->se_sensor.desc)); 348816e8e59Sdlg 349816e8e59Sdlg s++; 350816e8e59Sdlg } 351816e8e59Sdlg j++; 352816e8e59Sdlg 353816e8e59Sdlg /* 35457343048Skrw * Stash the temp info so we can get out of range status. Limit the 355*9593dc34Smglocker * number so the out of temp checks can't go into memory it doesn't own. 356816e8e59Sdlg */ 3575c0b007dSderaadt sc->sc_ntemps = (config->ntemps > 15) ? 15 : config->ntemps; 358816e8e59Sdlg sc->sc_temps = s; 3595c0b007dSderaadt sc->sc_celsius = SAFTE_CFG_CELSIUS(config->therm); 3605c0b007dSderaadt for (i = 0; i < config->ntemps; i++) { 361816e8e59Sdlg s->se_type = SAFTE_T_TEMP; 362816e8e59Sdlg s->se_field = (u_int8_t *)(sc->sc_encbuf + j + i); 363816e8e59Sdlg s->se_sensor.type = SENSOR_TEMP; 364816e8e59Sdlg 365816e8e59Sdlg s++; 366816e8e59Sdlg } 3675c0b007dSderaadt j += config->ntemps; 368816e8e59Sdlg 369a104ef5fSkettenis sc->sc_temperrs = (u_int8_t *)(sc->sc_encbuf + j); 3705c0b007dSderaadt done: 3715c0b007dSderaadt dma_free(config, sizeof(*config)); 37257343048Skrw return error; 373d596fd10Sdlg } 374d596fd10Sdlg 375b054292eSdlg void 376b054292eSdlg safte_read_encstat(void *arg) 377d596fd10Sdlg { 378f8bbb75aSkrw struct safte_readbuf_cmd *cmd; 379816e8e59Sdlg struct safte_sensor *s; 380f8bbb75aSkrw struct safte_softc *sc = (struct safte_softc *)arg; 381f8bbb75aSkrw struct scsi_xfer *xs; 382f8bbb75aSkrw int error, i, flags = 0; 383816e8e59Sdlg u_int16_t oot; 384d596fd10Sdlg 38560eafd6fSdlg rw_enter_write(&sc->sc_lock); 3869c336412Sdlg 3877351cb62Smarco if (cold) 388dacf4336Skrw SET(flags, SCSI_AUTOCONF); 389f8bbb75aSkrw xs = scsi_xs_get(sc->sc_link, flags | SCSI_DATA_IN | SCSI_SILENT); 3904daa7709Smatthew if (xs == NULL) { 3914daa7709Smatthew rw_exit_write(&sc->sc_lock); 392f8bbb75aSkrw return; 3934daa7709Smatthew } 394f8bbb75aSkrw xs->cmdlen = sizeof(*cmd); 395f8bbb75aSkrw xs->data = sc->sc_encbuf; 396f8bbb75aSkrw xs->datalen = sc->sc_encbuflen; 397f8bbb75aSkrw xs->retries = 2; 398f8bbb75aSkrw xs->timeout = 30000; 3997351cb62Smarco 400664c6166Skrw cmd = (struct safte_readbuf_cmd *)&xs->cmd; 40149227f1aSmatthew cmd->opcode = READ_BUFFER; 402dacf4336Skrw SET(cmd->flags, SAFTE_RD_MODE); 403f8bbb75aSkrw cmd->bufferid = SAFTE_RD_ENCSTAT; 404f8bbb75aSkrw cmd->length = htobe16(sc->sc_encbuflen); 405f8bbb75aSkrw 406f8bbb75aSkrw error = scsi_xs_sync(xs); 407f8bbb75aSkrw scsi_xs_put(xs); 408f8bbb75aSkrw 409f8bbb75aSkrw if (error != 0) { 41060eafd6fSdlg rw_exit_write(&sc->sc_lock); 411b054292eSdlg return; 412b054292eSdlg } 413d596fd10Sdlg 414816e8e59Sdlg for (i = 0; i < sc->sc_nsensors; i++) { 415816e8e59Sdlg s = &sc->sc_sensors[i]; 41664e2b1d6Skrw CLR(s->se_sensor.flags, SENSOR_FUNKNOWN); 417816e8e59Sdlg 418816e8e59Sdlg DPRINTF(("%s: %d type: %d field: 0x%02x\n", DEVNAME(sc), i, 419816e8e59Sdlg s->se_type, *s->se_field)); 420816e8e59Sdlg 421816e8e59Sdlg switch (s->se_type) { 422816e8e59Sdlg case SAFTE_T_FAN: 423816e8e59Sdlg switch (*s->se_field) { 424816e8e59Sdlg case SAFTE_FAN_OP: 425816e8e59Sdlg s->se_sensor.value = 1; 426816e8e59Sdlg s->se_sensor.status = SENSOR_S_OK; 427816e8e59Sdlg break; 428816e8e59Sdlg case SAFTE_FAN_MF: 429816e8e59Sdlg s->se_sensor.value = 0; 430816e8e59Sdlg s->se_sensor.status = SENSOR_S_CRIT; 431816e8e59Sdlg break; 432816e8e59Sdlg case SAFTE_FAN_NOTINST: 433816e8e59Sdlg case SAFTE_FAN_UNKNOWN: 434816e8e59Sdlg default: 435816e8e59Sdlg s->se_sensor.value = 0; 436816e8e59Sdlg s->se_sensor.status = SENSOR_S_UNKNOWN; 437dacf4336Skrw SET(s->se_sensor.flags, SENSOR_FUNKNOWN); 438816e8e59Sdlg break; 439816e8e59Sdlg } 440816e8e59Sdlg break; 441816e8e59Sdlg 442816e8e59Sdlg case SAFTE_T_PWRSUP: 443816e8e59Sdlg switch (*s->se_field) { 444816e8e59Sdlg case SAFTE_PWR_OP_ON: 445816e8e59Sdlg s->se_sensor.value = 1; 446816e8e59Sdlg s->se_sensor.status = SENSOR_S_OK; 447816e8e59Sdlg break; 448816e8e59Sdlg case SAFTE_PWR_OP_OFF: 449816e8e59Sdlg s->se_sensor.value = 0; 450816e8e59Sdlg s->se_sensor.status = SENSOR_S_OK; 451816e8e59Sdlg break; 452816e8e59Sdlg case SAFTE_PWR_MF_ON: 453816e8e59Sdlg s->se_sensor.value = 1; 454816e8e59Sdlg s->se_sensor.status = SENSOR_S_CRIT; 455816e8e59Sdlg break; 456816e8e59Sdlg case SAFTE_PWR_MF_OFF: 457816e8e59Sdlg s->se_sensor.value = 0; 458816e8e59Sdlg s->se_sensor.status = SENSOR_S_CRIT; 459816e8e59Sdlg break; 460816e8e59Sdlg case SAFTE_PWR_NOTINST: 461816e8e59Sdlg case SAFTE_PWR_PRESENT: 462816e8e59Sdlg case SAFTE_PWR_UNKNOWN: 463816e8e59Sdlg s->se_sensor.value = 0; 464816e8e59Sdlg s->se_sensor.status = SENSOR_S_UNKNOWN; 465dacf4336Skrw SET(s->se_sensor.flags, SENSOR_FUNKNOWN); 466816e8e59Sdlg break; 467816e8e59Sdlg } 468816e8e59Sdlg break; 469816e8e59Sdlg 470816e8e59Sdlg case SAFTE_T_DOORLOCK: 471816e8e59Sdlg switch (*s->se_field) { 472816e8e59Sdlg case SAFTE_DOOR_LOCKED: 473816e8e59Sdlg s->se_sensor.value = 1; 474816e8e59Sdlg s->se_sensor.status = SENSOR_S_OK; 475816e8e59Sdlg break; 476816e8e59Sdlg case SAFTE_DOOR_UNLOCKED: 477816e8e59Sdlg s->se_sensor.value = 0; 478816e8e59Sdlg s->se_sensor.status = SENSOR_S_CRIT; 479816e8e59Sdlg break; 480816e8e59Sdlg case SAFTE_DOOR_UNKNOWN: 481816e8e59Sdlg s->se_sensor.value = 0; 482816e8e59Sdlg s->se_sensor.status = SENSOR_S_CRIT; 483dacf4336Skrw SET(s->se_sensor.flags, SENSOR_FUNKNOWN); 484816e8e59Sdlg break; 485816e8e59Sdlg } 486816e8e59Sdlg break; 487816e8e59Sdlg 488816e8e59Sdlg case SAFTE_T_ALARM: 489816e8e59Sdlg switch (*s->se_field) { 490816e8e59Sdlg case SAFTE_SPKR_OFF: 491816e8e59Sdlg s->se_sensor.value = 0; 492816e8e59Sdlg s->se_sensor.status = SENSOR_S_OK; 493816e8e59Sdlg break; 494816e8e59Sdlg case SAFTE_SPKR_ON: 495816e8e59Sdlg s->se_sensor.value = 1; 496816e8e59Sdlg s->se_sensor.status = SENSOR_S_CRIT; 497816e8e59Sdlg break; 498d596fd10Sdlg } 49927899c6aSkrw break; 500d596fd10Sdlg 501816e8e59Sdlg case SAFTE_T_TEMP: 502816e8e59Sdlg s->se_sensor.value = safte_temp2uK(*s->se_field, 503816e8e59Sdlg sc->sc_celsius); 504816e8e59Sdlg break; 505816e8e59Sdlg } 506d596fd10Sdlg } 507d596fd10Sdlg 508a104ef5fSkettenis oot = _2btol(sc->sc_temperrs); 509816e8e59Sdlg for (i = 0; i < sc->sc_ntemps; i++) 510816e8e59Sdlg sc->sc_temps[i].se_sensor.status = 511816e8e59Sdlg (oot & (1 << i)) ? SENSOR_S_CRIT : SENSOR_S_OK; 5129c336412Sdlg 51360eafd6fSdlg rw_exit_write(&sc->sc_lock); 514d596fd10Sdlg } 515d596fd10Sdlg 5167579196dSdlg #if NBIO > 0 5177579196dSdlg int 5187579196dSdlg safte_ioctl(struct device *dev, u_long cmd, caddr_t addr) 5197579196dSdlg { 5207579196dSdlg struct safte_softc *sc = (struct safte_softc *)dev; 5217579196dSdlg int error = 0; 5227579196dSdlg 5237579196dSdlg switch (cmd) { 5247579196dSdlg case BIOCBLINK: 5257579196dSdlg error = safte_bio_blink(sc, (struct bioc_blink *)addr); 5267579196dSdlg break; 5277579196dSdlg 5287579196dSdlg default: 5297579196dSdlg error = EINVAL; 5307579196dSdlg break; 5317579196dSdlg } 5327579196dSdlg 53357343048Skrw return error; 5347579196dSdlg } 5357579196dSdlg 5367579196dSdlg int 5377579196dSdlg safte_bio_blink(struct safte_softc *sc, struct bioc_blink *blink) 5387579196dSdlg { 539f8bbb75aSkrw struct safte_writebuf_cmd *cmd; 5407579196dSdlg struct safte_slotop *op; 541f8bbb75aSkrw struct scsi_xfer *xs; 542f8bbb75aSkrw int error, slot, flags = 0, wantblink; 5437579196dSdlg 5445ae89792Sderaadt switch (blink->bb_status) { 5455ae89792Sderaadt case BIOC_SBBLINK: 5465ae89792Sderaadt wantblink = 1; 5475ae89792Sderaadt break; 5485ae89792Sderaadt case BIOC_SBUNBLINK: 5495ae89792Sderaadt wantblink = 0; 5505ae89792Sderaadt break; 5515ae89792Sderaadt default: 55257343048Skrw return EINVAL; 5535ae89792Sderaadt } 5547579196dSdlg 55560eafd6fSdlg rw_enter_read(&sc->sc_lock); 5567579196dSdlg for (slot = 0; slot < sc->sc_nslots; slot++) { 5577579196dSdlg if (sc->sc_slots[slot] == blink->bb_target) 5587579196dSdlg break; 5597579196dSdlg } 56060eafd6fSdlg rw_exit_read(&sc->sc_lock); 5617579196dSdlg 5627579196dSdlg if (slot >= sc->sc_nslots) 56357343048Skrw return ENODEV; 5647579196dSdlg 5655c0b007dSderaadt op = dma_alloc(sizeof(*op), PR_WAITOK | PR_ZERO); 5667579196dSdlg 5677579196dSdlg op->opcode = SAFTE_WRITE_SLOTOP; 5687579196dSdlg op->slot = slot; 5695ae89792Sderaadt op->flags |= wantblink ? SAFTE_SLOTOP_IDENTIFY : 0; 5707579196dSdlg 5717351cb62Smarco if (cold) 572dacf4336Skrw SET(flags, SCSI_AUTOCONF); 573f8bbb75aSkrw xs = scsi_xs_get(sc->sc_link, flags | SCSI_DATA_OUT | SCSI_SILENT); 574f8bbb75aSkrw if (xs == NULL) { 5755c0b007dSderaadt dma_free(op, sizeof(*op)); 57657343048Skrw return ENOMEM; 5777579196dSdlg } 578f8bbb75aSkrw xs->cmdlen = sizeof(*cmd); 579f8bbb75aSkrw xs->data = (void *)op; 580f8bbb75aSkrw xs->datalen = sizeof(*op); 581f8bbb75aSkrw xs->retries = 2; 582f8bbb75aSkrw xs->timeout = 30000; 5837579196dSdlg 584664c6166Skrw cmd = (struct safte_writebuf_cmd *)&xs->cmd; 58549227f1aSmatthew cmd->opcode = WRITE_BUFFER; 586dacf4336Skrw SET(cmd->flags, SAFTE_WR_MODE); 587f8bbb75aSkrw cmd->length = htobe16(sizeof(struct safte_slotop)); 588f8bbb75aSkrw 589f8bbb75aSkrw error = scsi_xs_sync(xs); 590f8bbb75aSkrw scsi_xs_put(xs); 591f8bbb75aSkrw 592f8bbb75aSkrw if (error != 0) { 593f8bbb75aSkrw error = EIO; 594f8bbb75aSkrw } 5955c0b007dSderaadt dma_free(op, sizeof(*op)); 5967579196dSdlg 59757343048Skrw return error; 5987579196dSdlg } 5997579196dSdlg #endif /* NBIO > 0 */ 6007579196dSdlg 601d596fd10Sdlg int64_t 602d596fd10Sdlg safte_temp2uK(u_int8_t measured, int celsius) 603d596fd10Sdlg { 604d596fd10Sdlg int64_t temp; 605d596fd10Sdlg 606d596fd10Sdlg temp = (int64_t)measured; 607d596fd10Sdlg temp += SAFTE_TEMP_OFFSET; 60857343048Skrw temp *= 1000000; /* Convert to micro (mu) degrees. */ 609d596fd10Sdlg if (!celsius) 61057343048Skrw temp = ((temp - 32000000) * 5) / 9; /* Convert to Celsius. */ 611d596fd10Sdlg 61257343048Skrw temp += 273150000; /* Convert to kelvin. */ 613d596fd10Sdlg 61457343048Skrw return temp; 615d596fd10Sdlg } 616