1 /* $OpenBSD: lom.c,v 1.11 2009/09/23 22:04:02 kettenis 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_IDX4_TEMP_NAME_START 0x40 123 #define LOM_IDX4_TEMP_NAME_END 0xff 124 125 #define LOM_IDX5_FAN_NAME_START 0x40 126 #define LOM_IDX5_FAN_NAME_END 0xff 127 128 #define LOM_MAX_FAN 4 129 #define LOM_MAX_PSU 3 130 #define LOM_MAX_TEMP 8 131 132 struct lom_softc { 133 struct device sc_dev; 134 bus_space_tag_t sc_iot; 135 bus_space_handle_t sc_ioh; 136 137 int sc_type; 138 #define LOM_LOMLITE 0 139 #define LOM_LOMLITE2 2 140 int sc_space; 141 142 struct ksensor sc_fan[LOM_MAX_FAN]; 143 struct ksensor sc_psu[LOM_MAX_PSU]; 144 struct ksensor sc_temp[LOM_MAX_TEMP]; 145 struct ksensordev sc_sensordev; 146 147 int sc_num_fan; 148 int sc_num_psu; 149 int sc_num_temp; 150 151 uint8_t sc_fan_cal[LOM_MAX_FAN]; 152 uint8_t sc_fan_low[LOM_MAX_FAN]; 153 154 char sc_hostname[MAXHOSTNAMELEN]; 155 156 struct timeout sc_wdog_to; 157 int sc_wdog_period; 158 uint8_t sc_wdog_ctl; 159 160 uint8_t sc_cmd; 161 uint8_t sc_data; 162 struct timeout sc_state_to; 163 int sc_state; 164 #define LOM_STATE_IDLE 0 165 #define LOM_STATE_READ_CMD 1 166 #define LOM_STATE_READ_DATA 2 167 #define LOM_STATE_READ_DONE 3 168 }; 169 170 int lom_match(struct device *, void *, void *); 171 void lom_attach(struct device *, struct device *, void *); 172 173 struct cfattach lom_ca = { 174 sizeof(struct lom_softc), lom_match, lom_attach 175 }; 176 177 struct cfdriver lom_cd = { 178 NULL, "lom", DV_DULL 179 }; 180 181 int lom_read(struct lom_softc *, uint8_t, uint8_t *); 182 int lom_write(struct lom_softc *, uint8_t, uint8_t); 183 int lom1_read(struct lom_softc *, uint8_t, uint8_t *); 184 int lom1_read_polled(struct lom_softc *, uint8_t, uint8_t *); 185 int lom1_write(struct lom_softc *, uint8_t, uint8_t); 186 void lom1_state(void *); 187 int lom2_read(struct lom_softc *, uint8_t, uint8_t *); 188 int lom2_write(struct lom_softc *, uint8_t, uint8_t); 189 190 int lom_init_desc(struct lom_softc *sc); 191 void lom_refresh(void *); 192 void lom1_write_hostname(struct lom_softc *); 193 void lom2_write_hostname(struct lom_softc *); 194 195 void lom_wdog_pat(void *); 196 int lom_wdog_cb(void *, int); 197 198 int 199 lom_match(struct device *parent, void *match, void *aux) 200 { 201 struct ebus_attach_args *ea = aux; 202 203 if (strcmp(ea->ea_name, "SUNW,lom") == 0 || 204 strcmp(ea->ea_name, "SUNW,lomh") == 0) 205 return (1); 206 207 return (0); 208 } 209 210 void 211 lom_attach(struct device *parent, struct device *self, void *aux) 212 { 213 struct lom_softc *sc = (void *)self; 214 struct ebus_attach_args *ea = aux; 215 uint8_t reg, fw_rev, config, config2, config3; 216 uint8_t cal, low; 217 int i; 218 219 if (strcmp(ea->ea_name, "SUNW,lomh") == 0) 220 sc->sc_type = LOM_LOMLITE2; 221 222 if (ebus_bus_map(ea->ea_iotag, 0, 223 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), 224 ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) { 225 sc->sc_iot = ea->ea_iotag; 226 } else if (ebus_bus_map(ea->ea_memtag, 0, 227 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), 228 ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) { 229 sc->sc_iot = ea->ea_memtag; 230 } else { 231 printf(": can't map register space\n"); 232 return; 233 } 234 235 if (sc->sc_type < LOM_LOMLITE2) { 236 /* XXX Magic */ 237 bus_space_read_1(sc->sc_iot, sc->sc_ioh, 0); 238 bus_space_write_1(sc->sc_iot, sc->sc_ioh, 3, 0xca); 239 240 timeout_set(&sc->sc_state_to, lom1_state, sc); 241 } 242 243 if (lom_read(sc, LOM_IDX_PROBE55, ®) || reg != 0x55 || 244 lom_read(sc, LOM_IDX_PROBEAA, ®) || reg != 0xaa || 245 lom_read(sc, LOM_IDX_FW_REV, &fw_rev) || 246 lom_read(sc, LOM_IDX_CONFIG, &config)) 247 { 248 printf(": not responding\n"); 249 return; 250 } 251 252 config2 = config3 = 0; 253 if (sc->sc_type >= LOM_LOMLITE2) { 254 lom_read(sc, LOM_IDX_CONFIG2, &config2); 255 lom_read(sc, LOM_IDX_CONFIG3, &config3); 256 } 257 258 sc->sc_num_fan = min((config >> 5) & 0x7, LOM_MAX_FAN); 259 sc->sc_num_psu = min((config >> 3) & 0x3, LOM_MAX_PSU); 260 sc->sc_num_temp = min((config2 >> 4) & 0xf, LOM_MAX_TEMP); 261 262 for (i = 0; i < sc->sc_num_fan; i++) { 263 if (lom_read(sc, LOM_IDX_FAN1_CAL + i, &cal) || 264 lom_read(sc, LOM_IDX_FAN1_LOW + i, &low)) { 265 printf(": can't read fan information\n"); 266 return; 267 } 268 sc->sc_fan_cal[i] = cal; 269 sc->sc_fan_low[i] = low; 270 } 271 272 /* Initialize sensor data. */ 273 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, 274 sizeof(sc->sc_sensordev.xname)); 275 for (i = 0; i < sc->sc_num_fan; i++) { 276 sc->sc_fan[i].type = SENSOR_FANRPM; 277 sensor_attach(&sc->sc_sensordev, &sc->sc_fan[i]); 278 snprintf(sc->sc_fan[i].desc, sizeof(sc->sc_fan[i].desc), 279 "fan%d", i + 1); 280 } 281 for (i = 0; i < sc->sc_num_psu; i++) { 282 sc->sc_psu[i].type = SENSOR_INDICATOR; 283 sensor_attach(&sc->sc_sensordev, &sc->sc_psu[i]); 284 snprintf(sc->sc_psu[i].desc, sizeof(sc->sc_psu[i].desc), 285 "PSU%d", i + 1); 286 } 287 for (i = 0; i < sc->sc_num_temp; i++) { 288 sc->sc_temp[i].type = SENSOR_TEMP; 289 sensor_attach(&sc->sc_sensordev, &sc->sc_temp[i]); 290 } 291 if (lom_init_desc(sc)) { 292 printf(": can't read sensor names\n"); 293 return; 294 } 295 296 if (sensor_task_register(sc, lom_refresh, 5) == NULL) { 297 printf(": unable to register update task\n"); 298 return; 299 } 300 301 sensordev_install(&sc->sc_sensordev); 302 303 /* 304 * We configure the watchdog to turn on the fault LED when the 305 * watchdog timer expires. We run our own timeout to pat it 306 * such that this won't happen unless the kernel hangs. When 307 * the watchdog is explicitly configured using sysctl(8), we 308 * reconfigure it to reset the machine and let the standard 309 * watchdog(4) machinery take over. 310 */ 311 lom_write(sc, LOM_IDX_WDOG_TIME, LOM_WDOG_TIME_MAX); 312 lom_read(sc, LOM_IDX_WDOG_CTL, &sc->sc_wdog_ctl); 313 sc->sc_wdog_ctl &= ~LOM_WDOG_RESET; 314 sc->sc_wdog_ctl |= LOM_WDOG_ENABLE; 315 lom_write(sc, LOM_IDX_WDOG_CTL, sc->sc_wdog_ctl); 316 timeout_set(&sc->sc_wdog_to, lom_wdog_pat, sc); 317 timeout_add_sec(&sc->sc_wdog_to, LOM_WDOG_TIME_MAX / 2); 318 319 wdog_register(sc, lom_wdog_cb); 320 321 printf(": rev %d.%d\n", fw_rev >> 4, fw_rev & 0x0f); 322 } 323 324 int 325 lom_read(struct lom_softc *sc, uint8_t reg, uint8_t *val) 326 { 327 if (sc->sc_type < LOM_LOMLITE2) 328 return lom1_read(sc, reg, val); 329 else 330 return lom2_read(sc, reg, val); 331 } 332 333 int 334 lom_write(struct lom_softc *sc, uint8_t reg, uint8_t val) 335 { 336 if (sc->sc_type < LOM_LOMLITE2) 337 return lom1_write(sc, reg, val); 338 else 339 return lom2_write(sc, reg, val); 340 } 341 342 int 343 lom1_read(struct lom_softc *sc, uint8_t reg, uint8_t *val) 344 { 345 int error; 346 347 KASSERT(sc->sc_state == LOM_STATE_IDLE); 348 349 if (cold) 350 return lom1_read_polled(sc, reg, val); 351 352 sc->sc_cmd = reg; 353 sc->sc_state = LOM_STATE_READ_CMD; 354 timeout_add_msec(&sc->sc_state_to, 5); 355 356 error = tsleep(&sc->sc_state, PZERO, "lomrd", hz / 10); 357 KASSERT(sc->sc_state == LOM_STATE_READ_DONE); 358 359 *val = sc->sc_data; 360 sc->sc_state = LOM_STATE_IDLE; 361 362 return (error); 363 } 364 365 int 366 lom1_read_polled(struct lom_softc *sc, uint8_t reg, uint8_t *val) 367 { 368 uint8_t str; 369 int i; 370 371 delay(15000); 372 373 /* Wait for input buffer to become available. */ 374 for (i = 1000; i > 0; i--) { 375 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS); 376 delay(10); 377 if ((str & LOM1_STATUS_BUSY) == 0) 378 break; 379 } 380 if (i == 0) 381 return (ETIMEDOUT); 382 383 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_CMD, reg); 384 385 delay(15000); 386 387 /* Wait until the microcontroller fills output buffer. */ 388 for (i = 1000; i > 0; i--) { 389 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS); 390 delay(10); 391 if ((str & LOM1_STATUS_BUSY) == 0) 392 break; 393 } 394 if (i == 0) 395 return (ETIMEDOUT); 396 397 *val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA); 398 return (0); 399 } 400 401 int 402 lom1_write(struct lom_softc *sc, uint8_t reg, uint8_t val) 403 { 404 uint8_t str; 405 int i; 406 407 delay(15000); 408 409 /* Wait for input buffer to become available. */ 410 for (i = 1000; i > 0; i--) { 411 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS); 412 delay(10); 413 if ((str & LOM1_STATUS_BUSY) == 0) 414 break; 415 } 416 if (i == 0) 417 return (ETIMEDOUT); 418 419 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_CMD, reg | 0x80); 420 421 delay(15000); 422 423 /* Wait until the microcontroller fills output buffer. */ 424 for (i = 1000; i > 0; i--) { 425 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS); 426 delay(10); 427 if ((str & LOM1_STATUS_BUSY) == 0) 428 break; 429 } 430 if (i == 0) 431 return (ETIMEDOUT); 432 433 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA, val); 434 435 return (0); 436 } 437 438 void 439 lom1_state(void *arg) 440 { 441 struct lom_softc *sc = arg; 442 uint8_t str; 443 444 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS); 445 if (str & LOM1_STATUS_BUSY) { 446 timeout_add_msec(&sc->sc_state_to, 5); 447 return; 448 } 449 450 if (sc->sc_state == LOM_STATE_READ_CMD) { 451 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_CMD, sc->sc_cmd); 452 sc->sc_state = LOM_STATE_READ_DATA; 453 timeout_add_msec(&sc->sc_state_to, 5); 454 return; 455 } 456 457 KASSERT(sc->sc_state == LOM_STATE_READ_DATA); 458 sc->sc_data = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA); 459 sc->sc_state = LOM_STATE_READ_DONE; 460 wakeup(&sc->sc_state); 461 } 462 463 int 464 lom2_read(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 = 1000; i > 0; i--) { 471 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); 472 delay(10); 473 if ((str & LOM2_STATUS_IBF) == 0) 474 break; 475 } 476 if (i == 0) 477 return (ETIMEDOUT); 478 479 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM2_CMD, reg); 480 481 /* Wait until the microcontroller fills output buffer. */ 482 for (i = 1000; i > 0; i--) { 483 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); 484 delay(10); 485 if (str & LOM2_STATUS_OBF) 486 break; 487 } 488 if (i == 0) 489 return (ETIMEDOUT); 490 491 *val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA); 492 return (0); 493 } 494 495 int 496 lom2_write(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 = 1000; i > 0; i--) { 503 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); 504 delay(10); 505 if ((str & LOM2_STATUS_IBF) == 0) 506 break; 507 } 508 if (i == 0) 509 return (ETIMEDOUT); 510 511 if (sc->sc_space == LOM_IDX_CMD_GENERIC && reg != LOM_IDX_CMD) 512 reg |= 0x80; 513 514 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM2_CMD, reg); 515 516 /* Wait until the microcontroller fills output buffer. */ 517 for (i = 1000; i > 0; i--) { 518 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); 519 delay(10); 520 if (str & LOM2_STATUS_OBF) 521 break; 522 } 523 if (i == 0) 524 return (ETIMEDOUT); 525 526 bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA); 527 528 /* Wait for input buffer to become available. */ 529 for (i = 1000; i > 0; i--) { 530 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); 531 delay(10); 532 if ((str & LOM2_STATUS_IBF) == 0) 533 break; 534 } 535 if (i == 0) 536 return (ETIMEDOUT); 537 538 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA, val); 539 540 /* Wait until the microcontroller fills output buffer. */ 541 for (i = 1000; i > 0; i--) { 542 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); 543 delay(10); 544 if (str & LOM2_STATUS_OBF) 545 break; 546 } 547 if (i == 0) 548 return (ETIMEDOUT); 549 550 bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA); 551 552 /* If we switched spaces, remember the one we're in now. */ 553 if (reg == LOM_IDX_CMD) 554 sc->sc_space = val; 555 556 return (0); 557 } 558 559 int 560 lom_init_desc(struct lom_softc *sc) 561 { 562 uint8_t val; 563 int i, j, k; 564 int error; 565 566 /* LOMlite doesn't provide sensor descriptions. */ 567 if (sc->sc_type < LOM_LOMLITE2) 568 return (0); 569 570 /* 571 * Read temperature sensor names. 572 */ 573 error = lom_write(sc, LOM_IDX_CMD, LOM_IDX_CMD_TEMP); 574 if (error) 575 return (error); 576 577 i = 0; 578 j = 0; 579 k = LOM_IDX4_TEMP_NAME_START; 580 while (k <= LOM_IDX4_TEMP_NAME_END) { 581 error = lom_read(sc, k++, &val); 582 if (error) 583 goto fail; 584 585 if (val == 0xff) 586 break; 587 588 if (j < sizeof (sc->sc_temp[i].desc) - 1) 589 sc->sc_temp[i].desc[j++] = val; 590 591 if (val == '\0') { 592 i++; 593 j = 0; 594 if (i < sc->sc_num_temp) 595 continue; 596 597 break; 598 } 599 } 600 601 /* 602 * Read fan names. 603 */ 604 error = lom_write(sc, LOM_IDX_CMD, LOM_IDX_CMD_FAN); 605 if (error) 606 return (error); 607 608 i = 0; 609 j = 0; 610 k = LOM_IDX5_FAN_NAME_START; 611 while (k <= LOM_IDX5_FAN_NAME_END) { 612 error = lom_read(sc, k++, &val); 613 if (error) 614 goto fail; 615 616 if (val == 0xff) 617 break; 618 619 if (j < sizeof (sc->sc_fan[i].desc) - 1) 620 sc->sc_fan[i].desc[j++] = val; 621 622 if (val == '\0') { 623 i++; 624 j = 0; 625 if (i < sc->sc_num_fan) 626 continue; 627 628 break; 629 } 630 } 631 632 fail: 633 lom_write(sc, LOM_IDX_CMD, LOM_IDX_CMD_GENERIC); 634 return (error); 635 } 636 637 void 638 lom_refresh(void *arg) 639 { 640 struct lom_softc *sc = arg; 641 uint8_t val; 642 int i; 643 644 for (i = 0; i < sc->sc_num_fan; i++) { 645 if (lom_read(sc, LOM_IDX_FAN1 + i, &val)) { 646 sc->sc_fan[i].flags |= SENSOR_FINVALID; 647 continue; 648 } 649 650 sc->sc_fan[i].value = (60 * sc->sc_fan_cal[i] * val) / 100; 651 sc->sc_fan[i].flags &= ~SENSOR_FINVALID; 652 } 653 654 for (i = 0; i < sc->sc_num_psu; i++) { 655 if (lom_read(sc, LOM_IDX_PSU1 + i, &val) || 656 !ISSET(val, LOM_PSU_PRESENT)) { 657 sc->sc_psu[i].flags |= SENSOR_FINVALID; 658 continue; 659 } 660 661 if (val & LOM_PSU_STANDBY) { 662 sc->sc_psu[i].value = 0; 663 sc->sc_psu[i].status = SENSOR_S_UNSPEC; 664 } else { 665 sc->sc_psu[i].value = 1; 666 if (ISSET(val, LOM_PSU_INPUTA) && 667 ISSET(val, LOM_PSU_INPUTB) && 668 ISSET(val, LOM_PSU_OUTPUT)) 669 sc->sc_psu[i].status = SENSOR_S_OK; 670 else 671 sc->sc_psu[i].status = SENSOR_S_CRIT; 672 } 673 sc->sc_psu[i].flags &= ~SENSOR_FINVALID; 674 } 675 676 for (i = 0; i < sc->sc_num_temp; i++) { 677 if (lom_read(sc, LOM_IDX_TEMP1 + i, &val)) { 678 sc->sc_temp[i].flags |= SENSOR_FINVALID; 679 continue; 680 } 681 682 sc->sc_temp[i].value = val * 1000000 + 273150000; 683 sc->sc_temp[i].flags &= ~SENSOR_FINVALID; 684 } 685 686 /* 687 * If our hostname is set and differs from what's stored in 688 * the LOM, write the new hostname back to the LOM. Note that 689 * we include the terminating NUL when writing the hostname 690 * back to the LOM, otherwise the LOM will print any trailing 691 * garbage. 692 */ 693 if (hostnamelen > 0 && 694 strncmp(sc->sc_hostname, hostname, sizeof(hostname)) != 0) { 695 if (sc->sc_type < LOM_LOMLITE2) 696 lom1_write_hostname(sc); 697 else 698 lom2_write_hostname(sc); 699 strlcpy(sc->sc_hostname, hostname, sizeof(hostname)); 700 } 701 } 702 703 void 704 lom1_write_hostname(struct lom_softc *sc) 705 { 706 char name[LOM1_IDX_HOSTNAME12 - LOM1_IDX_HOSTNAME1 + 1]; 707 char *p; 708 int i; 709 710 /* 711 * LOMlite generally doesn't have enough space to store the 712 * fully qualified hostname. If the hostname is too long, 713 * strip off the domain name. 714 */ 715 strlcpy(name, hostname, sizeof(name)); 716 if (hostnamelen > sizeof(name)) { 717 p = strchr(name, '.'); 718 if (p) 719 *p = '\0'; 720 } 721 722 for (i = 0; i < strlen(name) + 1; i++) 723 lom_write(sc, LOM1_IDX_HOSTNAME1 + i, name[i]); 724 } 725 726 void 727 lom2_write_hostname(struct lom_softc *sc) 728 { 729 int i; 730 731 lom_write(sc, LOM2_IDX_HOSTNAMELEN, hostnamelen + 1); 732 for (i = 0; i < hostnamelen + 1; i++) 733 lom_write(sc, LOM2_IDX_HOSTNAME, hostname[i]); 734 } 735 736 void 737 lom_wdog_pat(void *arg) 738 { 739 struct lom_softc *sc; 740 741 /* Pat the dog. */ 742 lom_write(sc, LOM_IDX_WDOG_CTL, sc->sc_wdog_ctl); 743 744 timeout_add_sec(&sc->sc_wdog_to, LOM_WDOG_TIME_MAX / 2); 745 } 746 747 int 748 lom_wdog_cb(void *arg, int period) 749 { 750 struct lom_softc *sc = arg; 751 752 if (period > LOM_WDOG_TIME_MAX) 753 period = LOM_WDOG_TIME_MAX; 754 else if (period < 0) 755 period = 0; 756 757 if (period == 0) { 758 if (sc->sc_wdog_period != 0) { 759 /* Stop watchdog from resetting the machine. */ 760 sc->sc_wdog_ctl &= ~LOM_WDOG_RESET; 761 lom_write(sc, LOM_IDX_WDOG_CTL, sc->sc_wdog_ctl); 762 763 lom_write(sc, LOM_IDX_WDOG_TIME, LOM_WDOG_TIME_MAX); 764 timeout_add_sec(&sc->sc_wdog_to, LOM_WDOG_TIME_MAX / 2); 765 } 766 } else { 767 if (sc->sc_wdog_period != period) { 768 /* Set new timeout. */ 769 lom_write(sc, LOM_IDX_WDOG_TIME, period); 770 } 771 if (sc->sc_wdog_period == 0) { 772 /* Make watchdog reset the machine. */ 773 sc->sc_wdog_ctl |= LOM_WDOG_RESET; 774 lom_write(sc, LOM_IDX_WDOG_CTL, sc->sc_wdog_ctl); 775 776 timeout_del(&sc->sc_wdog_to); 777 } else { 778 /* Pat the dog. */ 779 lom_write(sc, LOM_IDX_WDOG_CTL, sc->sc_wdog_ctl); 780 } 781 } 782 sc->sc_wdog_period = period; 783 784 return (period); 785 } 786