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