1 /* $OpenBSD: lom.c,v 1.27 2019/10/12 15:55:31 cheloha Exp $ */ 2 /* 3 * Copyright (c) 2009 Mark Kettenis 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/device.h> 20 #include <sys/kernel.h> 21 #include <sys/proc.h> 22 #include <sys/sensors.h> 23 #include <sys/systm.h> 24 #include <sys/timeout.h> 25 26 #include <machine/autoconf.h> 27 #include <machine/openfirm.h> 28 29 #include <sparc64/dev/ebusreg.h> 30 #include <sparc64/dev/ebusvar.h> 31 32 /* 33 * LOMlite is a so far unidentified microcontroller. 34 */ 35 #define LOM1_STATUS 0x00 /* R */ 36 #define LOM1_STATUS_BUSY 0x80 37 #define LOM1_CMD 0x00 /* W */ 38 #define LOM1_DATA 0x01 /* R/W */ 39 40 /* 41 * LOMlite2 is implemented as a H8/3437 microcontroller which has its 42 * on-chip host interface hooked up to EBus. 43 */ 44 #define LOM2_DATA 0x00 /* R/W */ 45 #define LOM2_CMD 0x01 /* W */ 46 #define LOM2_STATUS 0x01 /* R */ 47 #define LOM2_STATUS_OBF 0x01 /* Output Buffer Full */ 48 #define LOM2_STATUS_IBF 0x02 /* Input Buffer Full */ 49 50 #define LOM_IDX_CMD 0x00 51 #define LOM_IDX_CMD_GENERIC 0x00 52 #define LOM_IDX_CMD_TEMP 0x04 53 #define LOM_IDX_CMD_FAN 0x05 54 55 #define LOM_IDX_FW_REV 0x01 /* Firmware revision */ 56 57 #define LOM_IDX_FAN1 0x04 /* Fan speed */ 58 #define LOM_IDX_FAN2 0x05 59 #define LOM_IDX_FAN3 0x06 60 #define LOM_IDX_FAN4 0x07 61 #define LOM_IDX_PSU1 0x08 /* PSU status */ 62 #define LOM_IDX_PSU2 0x09 63 #define LOM_IDX_PSU3 0x0a 64 #define LOM_PSU_INPUTA 0x01 65 #define LOM_PSU_INPUTB 0x02 66 #define LOM_PSU_OUTPUT 0x04 67 #define LOM_PSU_PRESENT 0x08 68 #define LOM_PSU_STANDBY 0x10 69 70 #define LOM_IDX_TEMP1 0x18 /* Temperature */ 71 #define LOM_IDX_TEMP2 0x19 72 #define LOM_IDX_TEMP3 0x1a 73 #define LOM_IDX_TEMP4 0x1b 74 #define LOM_IDX_TEMP5 0x1c 75 #define LOM_IDX_TEMP6 0x1d 76 #define LOM_IDX_TEMP7 0x1e 77 #define LOM_IDX_TEMP8 0x1f 78 79 #define LOM_IDX_LED1 0x25 80 81 #define LOM_IDX_ALARM 0x30 82 #define LOM_IDX_WDOG_CTL 0x31 83 #define LOM_WDOG_ENABLE 0x01 84 #define LOM_WDOG_RESET 0x02 85 #define LOM_WDOG_AL3_WDOG 0x04 86 #define LOM_WDOG_AL3_FANPSU 0x08 87 #define LOM_IDX_WDOG_TIME 0x32 88 #define LOM_WDOG_TIME_MAX 126 89 90 #define LOM1_IDX_HOSTNAME1 0x33 91 #define LOM1_IDX_HOSTNAME2 0x34 92 #define LOM1_IDX_HOSTNAME3 0x35 93 #define LOM1_IDX_HOSTNAME4 0x36 94 #define LOM1_IDX_HOSTNAME5 0x37 95 #define LOM1_IDX_HOSTNAME6 0x38 96 #define LOM1_IDX_HOSTNAME7 0x39 97 #define LOM1_IDX_HOSTNAME8 0x3a 98 #define LOM1_IDX_HOSTNAME9 0x3b 99 #define LOM1_IDX_HOSTNAME10 0x3c 100 #define LOM1_IDX_HOSTNAME11 0x3d 101 #define LOM1_IDX_HOSTNAME12 0x3e 102 103 #define LOM2_IDX_HOSTNAMELEN 0x38 104 #define LOM2_IDX_HOSTNAME 0x39 105 106 #define LOM_IDX_CONFIG 0x5d 107 #define LOM_IDX_FAN1_CAL 0x5e 108 #define LOM_IDX_FAN2_CAL 0x5f 109 #define LOM_IDX_FAN3_CAL 0x60 110 #define LOM_IDX_FAN4_CAL 0x61 111 #define LOM_IDX_FAN1_LOW 0x62 112 #define LOM_IDX_FAN2_LOW 0x63 113 #define LOM_IDX_FAN3_LOW 0x64 114 #define LOM_IDX_FAN4_LOW 0x65 115 116 #define LOM_IDX_CONFIG2 0x66 117 #define LOM_IDX_CONFIG3 0x67 118 119 #define LOM_IDX_PROBE55 0x7e /* Always returns 0x55 */ 120 #define LOM_IDX_PROBEAA 0x7f /* Always returns 0xaa */ 121 122 #define LOM_IDX_WRITE 0x80 123 124 #define LOM_IDX4_TEMP_NAME_START 0x40 125 #define LOM_IDX4_TEMP_NAME_END 0xff 126 127 #define LOM_IDX5_FAN_NAME_START 0x40 128 #define LOM_IDX5_FAN_NAME_END 0xff 129 130 #define LOM_MAX_FAN 4 131 #define LOM_MAX_PSU 3 132 #define LOM_MAX_TEMP 8 133 134 struct lom_cmd { 135 uint8_t lc_cmd; 136 uint8_t lc_data; 137 138 TAILQ_ENTRY(lom_cmd) lc_next; 139 }; 140 141 struct lom_softc { 142 struct device sc_dev; 143 bus_space_tag_t sc_iot; 144 bus_space_handle_t sc_ioh; 145 146 int sc_type; 147 #define LOM_LOMLITE 0 148 #define LOM_LOMLITE2 2 149 int sc_space; 150 151 struct ksensor sc_fan[LOM_MAX_FAN]; 152 struct ksensor sc_psu[LOM_MAX_PSU]; 153 struct ksensor sc_temp[LOM_MAX_TEMP]; 154 struct ksensordev sc_sensordev; 155 156 int sc_num_fan; 157 int sc_num_psu; 158 int sc_num_temp; 159 160 uint8_t sc_fan_cal[LOM_MAX_FAN]; 161 uint8_t sc_fan_low[LOM_MAX_FAN]; 162 163 char sc_hostname[MAXHOSTNAMELEN]; 164 165 struct timeout sc_wdog_to; 166 int sc_wdog_period; 167 uint8_t sc_wdog_ctl; 168 struct lom_cmd sc_wdog_pat; 169 170 TAILQ_HEAD(, lom_cmd) sc_queue; 171 struct mutex sc_queue_mtx; 172 struct timeout sc_state_to; 173 int sc_state; 174 #define LOM_STATE_IDLE 0 175 #define LOM_STATE_CMD 1 176 #define LOM_STATE_DATA 2 177 int sc_retry; 178 }; 179 180 int lom_match(struct device *, void *, void *); 181 void lom_attach(struct device *, struct device *, void *); 182 int lom_activate(struct device *, int); 183 184 struct cfattach lom_ca = { 185 sizeof(struct lom_softc), lom_match, lom_attach, 186 NULL, lom_activate 187 }; 188 189 struct cfdriver lom_cd = { 190 NULL, "lom", DV_DULL 191 }; 192 193 int lom_read(struct lom_softc *, uint8_t, uint8_t *); 194 int lom_write(struct lom_softc *, uint8_t, uint8_t); 195 void lom_queue_cmd(struct lom_softc *, struct lom_cmd *); 196 void lom_dequeue_cmd(struct lom_softc *, struct lom_cmd *); 197 int lom1_read(struct lom_softc *, uint8_t, uint8_t *); 198 int lom1_write(struct lom_softc *, uint8_t, uint8_t); 199 int lom1_read_polled(struct lom_softc *, uint8_t, uint8_t *); 200 int lom1_write_polled(struct lom_softc *, uint8_t, uint8_t); 201 void lom1_queue_cmd(struct lom_softc *, struct lom_cmd *); 202 void lom1_process_queue(void *); 203 void lom1_process_queue_locked(struct lom_softc *); 204 int lom2_read(struct lom_softc *, uint8_t, uint8_t *); 205 int lom2_write(struct lom_softc *, uint8_t, uint8_t); 206 int lom2_read_polled(struct lom_softc *, uint8_t, uint8_t *); 207 int lom2_write_polled(struct lom_softc *, uint8_t, uint8_t); 208 void lom2_queue_cmd(struct lom_softc *, struct lom_cmd *); 209 int lom2_intr(void *); 210 211 int lom_init_desc(struct lom_softc *sc); 212 void lom_refresh(void *); 213 void lom1_write_hostname(struct lom_softc *); 214 void lom2_write_hostname(struct lom_softc *); 215 216 void lom_wdog_pat(void *); 217 int lom_wdog_cb(void *, int); 218 219 void lom_shutdown(void *); 220 221 int 222 lom_match(struct device *parent, void *match, void *aux) 223 { 224 struct ebus_attach_args *ea = aux; 225 226 if (strcmp(ea->ea_name, "SUNW,lom") == 0 || 227 strcmp(ea->ea_name, "SUNW,lomh") == 0) 228 return (1); 229 230 return (0); 231 } 232 233 void 234 lom_attach(struct device *parent, struct device *self, void *aux) 235 { 236 struct lom_softc *sc = (void *)self; 237 struct ebus_attach_args *ea = aux; 238 uint8_t reg, fw_rev, config, config2, config3; 239 uint8_t cal, low; 240 int i; 241 242 if (strcmp(ea->ea_name, "SUNW,lomh") == 0) { 243 if (ea->ea_nintrs < 1) { 244 printf(": no interrupt\n"); 245 return; 246 } 247 sc->sc_type = LOM_LOMLITE2; 248 } 249 250 if (ebus_bus_map(ea->ea_iotag, 0, 251 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), 252 ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) { 253 sc->sc_iot = ea->ea_iotag; 254 } else if (ebus_bus_map(ea->ea_memtag, 0, 255 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), 256 ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) { 257 sc->sc_iot = ea->ea_memtag; 258 } else { 259 printf(": can't map register space\n"); 260 return; 261 } 262 263 if (sc->sc_type < LOM_LOMLITE2) { 264 /* XXX Magic */ 265 bus_space_read_1(sc->sc_iot, sc->sc_ioh, 0); 266 bus_space_write_1(sc->sc_iot, sc->sc_ioh, 3, 0xca); 267 } 268 269 if (lom_read(sc, LOM_IDX_PROBE55, ®) || reg != 0x55 || 270 lom_read(sc, LOM_IDX_PROBEAA, ®) || reg != 0xaa || 271 lom_read(sc, LOM_IDX_FW_REV, &fw_rev) || 272 lom_read(sc, LOM_IDX_CONFIG, &config)) 273 { 274 printf(": not responding\n"); 275 return; 276 } 277 278 TAILQ_INIT(&sc->sc_queue); 279 mtx_init(&sc->sc_queue_mtx, IPL_BIO); 280 281 config2 = config3 = 0; 282 if (sc->sc_type < LOM_LOMLITE2) { 283 /* 284 * LOMlite doesn't do interrupts so we limp along on 285 * timeouts. 286 */ 287 timeout_set(&sc->sc_state_to, lom1_process_queue, sc); 288 } else { 289 lom_read(sc, LOM_IDX_CONFIG2, &config2); 290 lom_read(sc, LOM_IDX_CONFIG3, &config3); 291 292 bus_intr_establish(sc->sc_iot, ea->ea_intrs[0], 293 IPL_BIO, 0, lom2_intr, sc, self->dv_xname); 294 } 295 296 sc->sc_num_fan = min((config >> 5) & 0x7, LOM_MAX_FAN); 297 sc->sc_num_psu = min((config >> 3) & 0x3, LOM_MAX_PSU); 298 sc->sc_num_temp = min((config2 >> 4) & 0xf, LOM_MAX_TEMP); 299 300 for (i = 0; i < sc->sc_num_fan; i++) { 301 if (lom_read(sc, LOM_IDX_FAN1_CAL + i, &cal) || 302 lom_read(sc, LOM_IDX_FAN1_LOW + i, &low)) { 303 printf(": can't read fan information\n"); 304 return; 305 } 306 sc->sc_fan_cal[i] = cal; 307 sc->sc_fan_low[i] = low; 308 } 309 310 /* Initialize sensor data. */ 311 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, 312 sizeof(sc->sc_sensordev.xname)); 313 for (i = 0; i < sc->sc_num_fan; i++) { 314 sc->sc_fan[i].type = SENSOR_FANRPM; 315 sensor_attach(&sc->sc_sensordev, &sc->sc_fan[i]); 316 snprintf(sc->sc_fan[i].desc, sizeof(sc->sc_fan[i].desc), 317 "fan%d", i + 1); 318 } 319 for (i = 0; i < sc->sc_num_psu; i++) { 320 sc->sc_psu[i].type = SENSOR_INDICATOR; 321 sensor_attach(&sc->sc_sensordev, &sc->sc_psu[i]); 322 snprintf(sc->sc_psu[i].desc, sizeof(sc->sc_psu[i].desc), 323 "PSU%d", i + 1); 324 } 325 for (i = 0; i < sc->sc_num_temp; i++) { 326 sc->sc_temp[i].type = SENSOR_TEMP; 327 sensor_attach(&sc->sc_sensordev, &sc->sc_temp[i]); 328 } 329 if (lom_init_desc(sc)) { 330 printf(": can't read sensor names\n"); 331 return; 332 } 333 334 if (sensor_task_register(sc, lom_refresh, 5) == NULL) { 335 printf(": unable to register update task\n"); 336 return; 337 } 338 339 sensordev_install(&sc->sc_sensordev); 340 341 /* 342 * We configure the watchdog to turn on the fault LED when the 343 * watchdog timer expires. We run our own timeout to pat it 344 * such that this won't happen unless the kernel hangs. When 345 * the watchdog is explicitly configured using sysctl(8), we 346 * reconfigure it to reset the machine and let the standard 347 * watchdog(4) machinery take over. 348 */ 349 lom_write(sc, LOM_IDX_WDOG_TIME, LOM_WDOG_TIME_MAX); 350 lom_read(sc, LOM_IDX_WDOG_CTL, &sc->sc_wdog_ctl); 351 sc->sc_wdog_ctl &= ~LOM_WDOG_RESET; 352 sc->sc_wdog_ctl |= LOM_WDOG_ENABLE; 353 lom_write(sc, LOM_IDX_WDOG_CTL, sc->sc_wdog_ctl); 354 timeout_set(&sc->sc_wdog_to, lom_wdog_pat, sc); 355 timeout_add_sec(&sc->sc_wdog_to, LOM_WDOG_TIME_MAX / 2); 356 357 wdog_register(lom_wdog_cb, sc); 358 359 printf(": %s rev %d.%d\n", 360 sc->sc_type < LOM_LOMLITE2 ? "LOMlite" : "LOMlite2", 361 fw_rev >> 4, fw_rev & 0x0f); 362 } 363 364 int 365 lom_activate(struct device *self, int act) 366 { 367 int ret = 0; 368 369 switch (act) { 370 case DVACT_POWERDOWN: 371 wdog_shutdown(self); 372 lom_shutdown(self); 373 break; 374 } 375 376 return (ret); 377 } 378 379 int 380 lom_read(struct lom_softc *sc, uint8_t reg, uint8_t *val) 381 { 382 if (sc->sc_type < LOM_LOMLITE2) 383 return lom1_read(sc, reg, val); 384 else 385 return lom2_read(sc, reg, val); 386 } 387 388 int 389 lom_write(struct lom_softc *sc, uint8_t reg, uint8_t val) 390 { 391 if (sc->sc_type < LOM_LOMLITE2) 392 return lom1_write(sc, reg, val); 393 else 394 return lom2_write(sc, reg, val); 395 } 396 397 void 398 lom_queue_cmd(struct lom_softc *sc, struct lom_cmd *lc) 399 { 400 if (sc->sc_type < LOM_LOMLITE2) 401 return lom1_queue_cmd(sc, lc); 402 else 403 return lom2_queue_cmd(sc, lc); 404 } 405 406 void 407 lom_dequeue_cmd(struct lom_softc *sc, struct lom_cmd *lc) 408 { 409 struct lom_cmd *lcp; 410 411 mtx_enter(&sc->sc_queue_mtx); 412 TAILQ_FOREACH(lcp, &sc->sc_queue, lc_next) { 413 if (lcp == lc) { 414 TAILQ_REMOVE(&sc->sc_queue, lc, lc_next); 415 break; 416 } 417 } 418 mtx_leave(&sc->sc_queue_mtx); 419 } 420 421 int 422 lom1_read(struct lom_softc *sc, uint8_t reg, uint8_t *val) 423 { 424 struct lom_cmd lc; 425 int error; 426 427 if (cold) 428 return lom1_read_polled(sc, reg, val); 429 430 lc.lc_cmd = reg; 431 lc.lc_data = 0xff; 432 lom1_queue_cmd(sc, &lc); 433 434 error = tsleep_nsec(&lc, PZERO, "lomrd", SEC_TO_NSEC(1)); 435 if (error) 436 lom_dequeue_cmd(sc, &lc); 437 438 *val = lc.lc_data; 439 440 return (error); 441 } 442 443 int 444 lom1_write(struct lom_softc *sc, uint8_t reg, uint8_t val) 445 { 446 struct lom_cmd lc; 447 int error; 448 449 if (cold) 450 return lom1_write_polled(sc, reg, val); 451 452 lc.lc_cmd = reg | LOM_IDX_WRITE; 453 lc.lc_data = val; 454 lom1_queue_cmd(sc, &lc); 455 456 error = tsleep_nsec(&lc, PZERO, "lomwr", SEC_TO_NSEC(2)); 457 if (error) 458 lom_dequeue_cmd(sc, &lc); 459 460 return (error); 461 } 462 463 int 464 lom1_read_polled(struct lom_softc *sc, uint8_t reg, uint8_t *val) 465 { 466 uint8_t str; 467 int i; 468 469 /* Wait for input buffer to become available. */ 470 for (i = 30; i > 0; i--) { 471 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS); 472 delay(1000); 473 if ((str & LOM1_STATUS_BUSY) == 0) 474 break; 475 } 476 if (i == 0) 477 return (ETIMEDOUT); 478 479 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_CMD, reg); 480 481 /* Wait until the microcontroller fills output buffer. */ 482 for (i = 30; i > 0; i--) { 483 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS); 484 delay(1000); 485 if ((str & LOM1_STATUS_BUSY) == 0) 486 break; 487 } 488 if (i == 0) 489 return (ETIMEDOUT); 490 491 *val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA); 492 return (0); 493 } 494 495 int 496 lom1_write_polled(struct lom_softc *sc, uint8_t reg, uint8_t val) 497 { 498 uint8_t str; 499 int i; 500 501 /* Wait for input buffer to become available. */ 502 for (i = 30; i > 0; i--) { 503 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS); 504 delay(1000); 505 if ((str & LOM1_STATUS_BUSY) == 0) 506 break; 507 } 508 if (i == 0) 509 return (ETIMEDOUT); 510 511 reg |= LOM_IDX_WRITE; 512 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_CMD, reg); 513 514 /* Wait until the microcontroller fills output buffer. */ 515 for (i = 30; i > 0; i--) { 516 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS); 517 delay(1000); 518 if ((str & LOM1_STATUS_BUSY) == 0) 519 break; 520 } 521 if (i == 0) 522 return (ETIMEDOUT); 523 524 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA, val); 525 526 return (0); 527 } 528 529 void 530 lom1_queue_cmd(struct lom_softc *sc, struct lom_cmd *lc) 531 { 532 mtx_enter(&sc->sc_queue_mtx); 533 TAILQ_INSERT_TAIL(&sc->sc_queue, lc, lc_next); 534 if (sc->sc_state == LOM_STATE_IDLE) { 535 sc->sc_state = LOM_STATE_CMD; 536 lom1_process_queue_locked(sc); 537 } 538 mtx_leave(&sc->sc_queue_mtx); 539 } 540 541 void 542 lom1_process_queue(void *arg) 543 { 544 struct lom_softc *sc = arg; 545 546 mtx_enter(&sc->sc_queue_mtx); 547 lom1_process_queue_locked(sc); 548 mtx_leave(&sc->sc_queue_mtx); 549 } 550 551 void 552 lom1_process_queue_locked(struct lom_softc *sc) 553 { 554 struct lom_cmd *lc; 555 uint8_t str; 556 557 lc = TAILQ_FIRST(&sc->sc_queue); 558 if (lc == NULL) { 559 sc->sc_state = LOM_STATE_IDLE; 560 return; 561 } 562 563 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS); 564 if (str & LOM1_STATUS_BUSY) { 565 if (sc->sc_retry++ < 30) { 566 timeout_add_msec(&sc->sc_state_to, 1); 567 return; 568 } 569 570 /* 571 * Looks like the microcontroller got wedged. Unwedge 572 * it by writing this magic value. Give it some time 573 * to recover. 574 */ 575 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA, 0xac); 576 timeout_add_msec(&sc->sc_state_to, 1000); 577 sc->sc_state = LOM_STATE_CMD; 578 return; 579 } 580 581 sc->sc_retry = 0; 582 583 if (sc->sc_state == LOM_STATE_CMD) { 584 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_CMD, lc->lc_cmd); 585 sc->sc_state = LOM_STATE_DATA; 586 timeout_add_msec(&sc->sc_state_to, 250); 587 return; 588 } 589 590 KASSERT(sc->sc_state == LOM_STATE_DATA); 591 if ((lc->lc_cmd & LOM_IDX_WRITE) == 0) 592 lc->lc_data = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA); 593 else 594 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA, lc->lc_data); 595 596 TAILQ_REMOVE(&sc->sc_queue, lc, lc_next); 597 598 wakeup(lc); 599 600 if (!TAILQ_EMPTY(&sc->sc_queue)) { 601 sc->sc_state = LOM_STATE_CMD; 602 timeout_add_msec(&sc->sc_state_to, 1); 603 return; 604 } 605 606 sc->sc_state = LOM_STATE_IDLE; 607 } 608 609 int 610 lom2_read(struct lom_softc *sc, uint8_t reg, uint8_t *val) 611 { 612 struct lom_cmd lc; 613 int error; 614 615 if (cold) 616 return lom2_read_polled(sc, reg, val); 617 618 lc.lc_cmd = reg; 619 lc.lc_data = 0xff; 620 lom2_queue_cmd(sc, &lc); 621 622 error = tsleep_nsec(&lc, PZERO, "lom2rd", SEC_TO_NSEC(1)); 623 if (error) 624 lom_dequeue_cmd(sc, &lc); 625 626 *val = lc.lc_data; 627 628 return (error); 629 } 630 631 int 632 lom2_read_polled(struct lom_softc *sc, uint8_t reg, uint8_t *val) 633 { 634 uint8_t str; 635 int i; 636 637 /* Wait for input buffer to become available. */ 638 for (i = 1000; i > 0; i--) { 639 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); 640 delay(10); 641 if ((str & LOM2_STATUS_IBF) == 0) 642 break; 643 } 644 if (i == 0) 645 return (ETIMEDOUT); 646 647 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM2_CMD, reg); 648 649 /* Wait until the microcontroller fills output buffer. */ 650 for (i = 1000; i > 0; i--) { 651 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); 652 delay(10); 653 if (str & LOM2_STATUS_OBF) 654 break; 655 } 656 if (i == 0) 657 return (ETIMEDOUT); 658 659 *val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA); 660 return (0); 661 } 662 663 int 664 lom2_write(struct lom_softc *sc, uint8_t reg, uint8_t val) 665 { 666 struct lom_cmd lc; 667 int error; 668 669 if (cold) 670 return lom2_write_polled(sc, reg, val); 671 672 lc.lc_cmd = reg | LOM_IDX_WRITE; 673 lc.lc_data = val; 674 lom2_queue_cmd(sc, &lc); 675 676 error = tsleep_nsec(&lc, PZERO, "lom2wr", SEC_TO_NSEC(1)); 677 if (error) 678 lom_dequeue_cmd(sc, &lc); 679 680 return (error); 681 } 682 683 int 684 lom2_write_polled(struct lom_softc *sc, uint8_t reg, uint8_t val) 685 { 686 uint8_t str; 687 int i; 688 689 /* Wait for input buffer to become available. */ 690 for (i = 1000; i > 0; i--) { 691 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); 692 delay(10); 693 if ((str & LOM2_STATUS_IBF) == 0) 694 break; 695 } 696 if (i == 0) 697 return (ETIMEDOUT); 698 699 if (sc->sc_space == LOM_IDX_CMD_GENERIC && reg != LOM_IDX_CMD) 700 reg |= LOM_IDX_WRITE; 701 702 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM2_CMD, reg); 703 704 /* Wait until the microcontroller fills output buffer. */ 705 for (i = 1000; i > 0; i--) { 706 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); 707 delay(10); 708 if (str & LOM2_STATUS_OBF) 709 break; 710 } 711 if (i == 0) 712 return (ETIMEDOUT); 713 714 bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA); 715 716 /* Wait for input buffer to become available. */ 717 for (i = 1000; i > 0; i--) { 718 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); 719 delay(10); 720 if ((str & LOM2_STATUS_IBF) == 0) 721 break; 722 } 723 if (i == 0) 724 return (ETIMEDOUT); 725 726 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA, val); 727 728 /* Wait until the microcontroller fills output buffer. */ 729 for (i = 1000; i > 0; i--) { 730 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); 731 delay(10); 732 if (str & LOM2_STATUS_OBF) 733 break; 734 } 735 if (i == 0) 736 return (ETIMEDOUT); 737 738 bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA); 739 740 /* If we switched spaces, remember the one we're in now. */ 741 if (reg == LOM_IDX_CMD) 742 sc->sc_space = val; 743 744 return (0); 745 } 746 747 void 748 lom2_queue_cmd(struct lom_softc *sc, struct lom_cmd *lc) 749 { 750 uint8_t str; 751 752 mtx_enter(&sc->sc_queue_mtx); 753 TAILQ_INSERT_TAIL(&sc->sc_queue, lc, lc_next); 754 if (sc->sc_state == LOM_STATE_IDLE) { 755 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); 756 if ((str & LOM2_STATUS_IBF) == 0) { 757 bus_space_write_1(sc->sc_iot, sc->sc_ioh, 758 LOM2_CMD, lc->lc_cmd); 759 sc->sc_state = LOM_STATE_DATA; 760 } 761 } 762 mtx_leave(&sc->sc_queue_mtx); 763 } 764 765 int 766 lom2_intr(void *arg) 767 { 768 struct lom_softc *sc = arg; 769 struct lom_cmd *lc; 770 uint8_t str, obr; 771 772 mtx_enter(&sc->sc_queue_mtx); 773 774 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); 775 obr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA); 776 777 lc = TAILQ_FIRST(&sc->sc_queue); 778 if (lc == NULL) { 779 mtx_leave(&sc->sc_queue_mtx); 780 return (0); 781 } 782 783 if (lc->lc_cmd & LOM_IDX_WRITE) { 784 bus_space_write_1(sc->sc_iot, sc->sc_ioh, 785 LOM2_DATA, lc->lc_data); 786 lc->lc_cmd &= ~LOM_IDX_WRITE; 787 mtx_leave(&sc->sc_queue_mtx); 788 return (1); 789 } 790 791 KASSERT(sc->sc_state == LOM_STATE_DATA); 792 lc->lc_data = obr; 793 794 TAILQ_REMOVE(&sc->sc_queue, lc, lc_next); 795 796 wakeup(lc); 797 798 sc->sc_state = LOM_STATE_IDLE; 799 800 if (!TAILQ_EMPTY(&sc->sc_queue)) { 801 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); 802 if ((str & LOM2_STATUS_IBF) == 0) { 803 bus_space_write_1(sc->sc_iot, sc->sc_ioh, 804 LOM2_CMD, lc->lc_cmd); 805 sc->sc_state = LOM_STATE_DATA; 806 } 807 } 808 809 mtx_leave(&sc->sc_queue_mtx); 810 811 return (1); 812 } 813 814 int 815 lom_init_desc(struct lom_softc *sc) 816 { 817 uint8_t val; 818 int i, j, k; 819 int error; 820 821 /* LOMlite doesn't provide sensor descriptions. */ 822 if (sc->sc_type < LOM_LOMLITE2) 823 return (0); 824 825 /* 826 * Read temperature sensor names. 827 */ 828 error = lom_write(sc, LOM_IDX_CMD, LOM_IDX_CMD_TEMP); 829 if (error) 830 return (error); 831 832 i = 0; 833 j = 0; 834 k = LOM_IDX4_TEMP_NAME_START; 835 while (k <= LOM_IDX4_TEMP_NAME_END) { 836 error = lom_read(sc, k++, &val); 837 if (error) 838 goto fail; 839 840 if (val == 0xff) 841 break; 842 843 if (j < sizeof (sc->sc_temp[i].desc) - 1) 844 sc->sc_temp[i].desc[j++] = val; 845 846 if (val == '\0') { 847 i++; 848 j = 0; 849 if (i < sc->sc_num_temp) 850 continue; 851 852 break; 853 } 854 } 855 856 /* 857 * Read fan names. 858 */ 859 error = lom_write(sc, LOM_IDX_CMD, LOM_IDX_CMD_FAN); 860 if (error) 861 return (error); 862 863 i = 0; 864 j = 0; 865 k = LOM_IDX5_FAN_NAME_START; 866 while (k <= LOM_IDX5_FAN_NAME_END) { 867 error = lom_read(sc, k++, &val); 868 if (error) 869 goto fail; 870 871 if (val == 0xff) 872 break; 873 874 if (j < sizeof (sc->sc_fan[i].desc) - 1) 875 sc->sc_fan[i].desc[j++] = val; 876 877 if (val == '\0') { 878 i++; 879 j = 0; 880 if (i < sc->sc_num_fan) 881 continue; 882 883 break; 884 } 885 } 886 887 fail: 888 lom_write(sc, LOM_IDX_CMD, LOM_IDX_CMD_GENERIC); 889 return (error); 890 } 891 892 void 893 lom_refresh(void *arg) 894 { 895 struct lom_softc *sc = arg; 896 uint8_t val; 897 int i; 898 899 for (i = 0; i < sc->sc_num_fan; i++) { 900 if (lom_read(sc, LOM_IDX_FAN1 + i, &val)) { 901 sc->sc_fan[i].flags |= SENSOR_FINVALID; 902 continue; 903 } 904 905 sc->sc_fan[i].value = (60 * sc->sc_fan_cal[i] * val) / 100; 906 if (val < sc->sc_fan_low[i]) 907 sc->sc_fan[i].status = SENSOR_S_CRIT; 908 else 909 sc->sc_fan[i].status = SENSOR_S_OK; 910 sc->sc_fan[i].flags &= ~SENSOR_FINVALID; 911 } 912 913 for (i = 0; i < sc->sc_num_psu; i++) { 914 if (lom_read(sc, LOM_IDX_PSU1 + i, &val) || 915 !ISSET(val, LOM_PSU_PRESENT)) { 916 sc->sc_psu[i].flags |= SENSOR_FINVALID; 917 continue; 918 } 919 920 if (val & LOM_PSU_STANDBY) { 921 sc->sc_psu[i].value = 0; 922 sc->sc_psu[i].status = SENSOR_S_UNSPEC; 923 } else { 924 sc->sc_psu[i].value = 1; 925 if (ISSET(val, LOM_PSU_INPUTA) && 926 ISSET(val, LOM_PSU_INPUTB) && 927 ISSET(val, LOM_PSU_OUTPUT)) 928 sc->sc_psu[i].status = SENSOR_S_OK; 929 else 930 sc->sc_psu[i].status = SENSOR_S_CRIT; 931 } 932 sc->sc_psu[i].flags &= ~SENSOR_FINVALID; 933 } 934 935 for (i = 0; i < sc->sc_num_temp; i++) { 936 if (lom_read(sc, LOM_IDX_TEMP1 + i, &val)) { 937 sc->sc_temp[i].flags |= SENSOR_FINVALID; 938 continue; 939 } 940 941 sc->sc_temp[i].value = val * 1000000 + 273150000; 942 sc->sc_temp[i].flags &= ~SENSOR_FINVALID; 943 } 944 945 /* 946 * If our hostname is set and differs from what's stored in 947 * the LOM, write the new hostname back to the LOM. Note that 948 * we include the terminating NUL when writing the hostname 949 * back to the LOM, otherwise the LOM will print any trailing 950 * garbage. 951 */ 952 if (hostnamelen > 0 && 953 strncmp(sc->sc_hostname, hostname, sizeof(hostname)) != 0) { 954 if (sc->sc_type < LOM_LOMLITE2) 955 lom1_write_hostname(sc); 956 else 957 lom2_write_hostname(sc); 958 strlcpy(sc->sc_hostname, hostname, sizeof(hostname)); 959 } 960 } 961 962 void 963 lom1_write_hostname(struct lom_softc *sc) 964 { 965 char name[(LOM1_IDX_HOSTNAME12 - LOM1_IDX_HOSTNAME1 + 1) + 1]; 966 char *p; 967 int i; 968 969 /* 970 * LOMlite generally doesn't have enough space to store the 971 * fully qualified hostname. If the hostname is too long, 972 * strip off the domain name. 973 */ 974 strlcpy(name, hostname, sizeof(name)); 975 if (hostnamelen >= sizeof(name)) { 976 p = strchr(name, '.'); 977 if (p) 978 *p = '\0'; 979 } 980 981 for (i = 0; i < strlen(name) + 1; i++) 982 if (lom_write(sc, LOM1_IDX_HOSTNAME1 + i, name[i])) 983 break; 984 } 985 986 void 987 lom2_write_hostname(struct lom_softc *sc) 988 { 989 int i; 990 991 lom_write(sc, LOM2_IDX_HOSTNAMELEN, hostnamelen + 1); 992 for (i = 0; i < hostnamelen + 1; i++) 993 lom_write(sc, LOM2_IDX_HOSTNAME, hostname[i]); 994 } 995 996 void 997 lom_wdog_pat(void *arg) 998 { 999 struct lom_softc *sc = arg; 1000 1001 /* Pat the dog. */ 1002 sc->sc_wdog_pat.lc_cmd = LOM_IDX_WDOG_CTL | LOM_IDX_WRITE; 1003 sc->sc_wdog_pat.lc_data = sc->sc_wdog_ctl; 1004 lom_queue_cmd(sc, &sc->sc_wdog_pat); 1005 1006 timeout_add_sec(&sc->sc_wdog_to, LOM_WDOG_TIME_MAX / 2); 1007 } 1008 1009 int 1010 lom_wdog_cb(void *arg, int period) 1011 { 1012 struct lom_softc *sc = arg; 1013 1014 if (period > LOM_WDOG_TIME_MAX) 1015 period = LOM_WDOG_TIME_MAX; 1016 else if (period < 0) 1017 period = 0; 1018 1019 if (period == 0) { 1020 if (sc->sc_wdog_period != 0) { 1021 /* Stop watchdog from resetting the machine. */ 1022 sc->sc_wdog_ctl &= ~LOM_WDOG_RESET; 1023 lom_write(sc, LOM_IDX_WDOG_CTL, sc->sc_wdog_ctl); 1024 1025 lom_write(sc, LOM_IDX_WDOG_TIME, LOM_WDOG_TIME_MAX); 1026 timeout_add_sec(&sc->sc_wdog_to, LOM_WDOG_TIME_MAX / 2); 1027 } 1028 } else { 1029 if (sc->sc_wdog_period != period) { 1030 /* Set new timeout. */ 1031 lom_write(sc, LOM_IDX_WDOG_TIME, period); 1032 } 1033 if (sc->sc_wdog_period == 0) { 1034 /* Make watchdog reset the machine. */ 1035 sc->sc_wdog_ctl |= LOM_WDOG_RESET; 1036 lom_write(sc, LOM_IDX_WDOG_CTL, sc->sc_wdog_ctl); 1037 1038 timeout_del(&sc->sc_wdog_to); 1039 } else { 1040 /* Pat the dog. */ 1041 lom_dequeue_cmd(sc, &sc->sc_wdog_pat); 1042 sc->sc_wdog_pat.lc_cmd = LOM_IDX_WDOG_CTL | LOM_IDX_WRITE; 1043 sc->sc_wdog_pat.lc_data = sc->sc_wdog_ctl; 1044 lom_queue_cmd(sc, &sc->sc_wdog_pat); 1045 } 1046 } 1047 sc->sc_wdog_period = period; 1048 1049 return (period); 1050 } 1051 1052 void 1053 lom_shutdown(void *arg) 1054 { 1055 struct lom_softc *sc = arg; 1056 1057 sc->sc_wdog_ctl &= ~LOM_WDOG_ENABLE; 1058 lom_write(sc, LOM_IDX_WDOG_CTL, sc->sc_wdog_ctl); 1059 } 1060