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