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