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