1 /* $NetBSD: lom.c,v 1.7 2011/02/28 14:29:29 nakayama Exp $ */ 2 /* $OpenBSD: lom.c,v 1.21 2010/02/28 20:44:39 kettenis Exp $ */ 3 /* 4 * Copyright (c) 2009 Mark Kettenis 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 <sys/cdefs.h> 20 __KERNEL_RCSID(0, "$NetBSD: lom.c,v 1.7 2011/02/28 14:29:29 nakayama Exp $"); 21 22 #include <sys/param.h> 23 #include <sys/device.h> 24 #include <sys/kernel.h> 25 #include <sys/proc.h> 26 #include <sys/envsys.h> 27 #include <sys/systm.h> 28 #include <sys/callout.h> 29 #include <sys/sysctl.h> 30 31 #include <machine/autoconf.h> 32 33 #include <dev/ebus/ebusreg.h> 34 #include <dev/ebus/ebusvar.h> 35 #include <dev/sysmon/sysmonvar.h> 36 37 /* 38 * LOMlite is a so far unidentified microcontroller. 39 */ 40 #define LOM1_STATUS 0x00 /* R */ 41 #define LOM1_STATUS_BUSY 0x80 42 #define LOM1_CMD 0x00 /* W */ 43 #define LOM1_DATA 0x01 /* R/W */ 44 45 /* 46 * LOMlite2 is implemented as a H8/3437 microcontroller which has its 47 * on-chip host interface hooked up to EBus. 48 */ 49 #define LOM2_DATA 0x00 /* R/W */ 50 #define LOM2_CMD 0x01 /* W */ 51 #define LOM2_STATUS 0x01 /* R */ 52 #define LOM2_STATUS_OBF 0x01 /* Output Buffer Full */ 53 #define LOM2_STATUS_IBF 0x02 /* Input Buffer Full */ 54 55 #define LOM_IDX_CMD 0x00 56 #define LOM_IDX_CMD_GENERIC 0x00 57 #define LOM_IDX_CMD_TEMP 0x04 58 #define LOM_IDX_CMD_FAN 0x05 59 60 #define LOM_IDX_FW_REV 0x01 /* Firmware revision */ 61 62 #define LOM_IDX_FAN1 0x04 /* Fan speed */ 63 #define LOM_IDX_FAN2 0x05 64 #define LOM_IDX_FAN3 0x06 65 #define LOM_IDX_FAN4 0x07 66 #define LOM_IDX_PSU1 0x08 /* PSU status */ 67 #define LOM_IDX_PSU2 0x09 68 #define LOM_IDX_PSU3 0x0a 69 #define LOM_PSU_INPUTA 0x01 70 #define LOM_PSU_INPUTB 0x02 71 #define LOM_PSU_OUTPUT 0x04 72 #define LOM_PSU_PRESENT 0x08 73 #define LOM_PSU_STANDBY 0x10 74 75 #define LOM_IDX_TEMP1 0x18 /* Temperature */ 76 #define LOM_IDX_TEMP2 0x19 77 #define LOM_IDX_TEMP3 0x1a 78 #define LOM_IDX_TEMP4 0x1b 79 #define LOM_IDX_TEMP5 0x1c 80 #define LOM_IDX_TEMP6 0x1d 81 #define LOM_IDX_TEMP7 0x1e 82 #define LOM_IDX_TEMP8 0x1f 83 84 #define LOM_IDX_LED1 0x25 85 86 #define LOM_IDX_ALARM 0x30 87 #define LOM_ALARM_1 0x01 88 #define LOM_ALARM_2 0x02 89 #define LOM_ALARM_3 0x04 90 #define LOM_ALARM_FAULT 0xf0 91 #define LOM_IDX_WDOG_CTL 0x31 92 #define LOM_WDOG_ENABLE 0x01 93 #define LOM_WDOG_RESET 0x02 94 #define LOM_WDOG_AL3_WDOG 0x04 95 #define LOM_WDOG_AL3_FANPSU 0x08 96 #define LOM_IDX_WDOG_TIME 0x32 97 #define LOM_WDOG_TIME_MAX 126 98 99 #define LOM1_IDX_HOSTNAME1 0x33 100 #define LOM1_IDX_HOSTNAME2 0x34 101 #define LOM1_IDX_HOSTNAME3 0x35 102 #define LOM1_IDX_HOSTNAME4 0x36 103 #define LOM1_IDX_HOSTNAME5 0x37 104 #define LOM1_IDX_HOSTNAME6 0x38 105 #define LOM1_IDX_HOSTNAME7 0x39 106 #define LOM1_IDX_HOSTNAME8 0x3a 107 #define LOM1_IDX_HOSTNAME9 0x3b 108 #define LOM1_IDX_HOSTNAME10 0x3c 109 #define LOM1_IDX_HOSTNAME11 0x3d 110 #define LOM1_IDX_HOSTNAME12 0x3e 111 112 #define LOM2_IDX_HOSTNAMELEN 0x38 113 #define LOM2_IDX_HOSTNAME 0x39 114 115 #define LOM_IDX_CONFIG 0x5d 116 #define LOM_IDX_FAN1_CAL 0x5e 117 #define LOM_IDX_FAN2_CAL 0x5f 118 #define LOM_IDX_FAN3_CAL 0x60 119 #define LOM_IDX_FAN4_CAL 0x61 120 #define LOM_IDX_FAN1_LOW 0x62 121 #define LOM_IDX_FAN2_LOW 0x63 122 #define LOM_IDX_FAN3_LOW 0x64 123 #define LOM_IDX_FAN4_LOW 0x65 124 125 #define LOM_IDX_CONFIG2 0x66 126 #define LOM_IDX_CONFIG3 0x67 127 128 #define LOM_IDX_PROBE55 0x7e /* Always returns 0x55 */ 129 #define LOM_IDX_PROBEAA 0x7f /* Always returns 0xaa */ 130 131 #define LOM_IDX_WRITE 0x80 132 133 #define LOM_IDX4_TEMP_NAME_START 0x40 134 #define LOM_IDX4_TEMP_NAME_END 0xff 135 136 #define LOM_IDX5_FAN_NAME_START 0x40 137 #define LOM_IDX5_FAN_NAME_END 0xff 138 139 #define LOM_MAX_ALARM 4 140 #define LOM_MAX_FAN 4 141 #define LOM_MAX_PSU 3 142 #define LOM_MAX_TEMP 8 143 144 struct lom_cmd { 145 uint8_t lc_cmd; 146 uint8_t lc_data; 147 148 TAILQ_ENTRY(lom_cmd) lc_next; 149 }; 150 151 struct lom_softc { 152 device_t sc_dev; 153 bus_space_tag_t sc_iot; 154 bus_space_handle_t sc_ioh; 155 156 int sc_type; 157 #define LOM_LOMLITE 0 158 #define LOM_LOMLITE2 2 159 int sc_space; 160 161 struct sysmon_envsys *sc_sme; 162 envsys_data_t sc_alarm[LOM_MAX_ALARM]; 163 envsys_data_t sc_fan[LOM_MAX_FAN]; 164 envsys_data_t sc_psu[LOM_MAX_PSU]; 165 envsys_data_t sc_temp[LOM_MAX_TEMP]; 166 167 int sc_num_alarm; 168 int sc_num_fan; 169 int sc_num_psu; 170 int sc_num_temp; 171 172 int32_t sc_sysctl_num[LOM_MAX_ALARM]; 173 174 uint8_t sc_fan_cal[LOM_MAX_FAN]; 175 uint8_t sc_fan_low[LOM_MAX_FAN]; 176 177 char sc_hostname[MAXHOSTNAMELEN]; 178 179 struct sysmon_wdog sc_smw; 180 int sc_wdog_period; 181 uint8_t sc_wdog_ctl; 182 struct lom_cmd sc_wdog_pat; 183 184 TAILQ_HEAD(, lom_cmd) sc_queue; 185 kmutex_t sc_queue_mtx; 186 struct callout sc_state_to; 187 int sc_state; 188 #define LOM_STATE_IDLE 0 189 #define LOM_STATE_CMD 1 190 #define LOM_STATE_DATA 2 191 int sc_retry; 192 }; 193 194 static int lom_match(device_t, cfdata_t, void *); 195 static void lom_attach(device_t, device_t, void *); 196 197 CFATTACH_DECL_NEW(lom, sizeof(struct lom_softc), 198 lom_match, lom_attach, NULL, NULL); 199 200 static int lom_read(struct lom_softc *, uint8_t, uint8_t *); 201 static int lom_write(struct lom_softc *, uint8_t, uint8_t); 202 static void lom_queue_cmd(struct lom_softc *, struct lom_cmd *); 203 static void lom_dequeue_cmd(struct lom_softc *, struct lom_cmd *); 204 static int lom1_read(struct lom_softc *, uint8_t, uint8_t *); 205 static int lom1_write(struct lom_softc *, uint8_t, uint8_t); 206 static int lom1_read_polled(struct lom_softc *, uint8_t, uint8_t *); 207 static int lom1_write_polled(struct lom_softc *, uint8_t, uint8_t); 208 static void lom1_queue_cmd(struct lom_softc *, struct lom_cmd *); 209 static void lom1_process_queue(void *); 210 static void lom1_process_queue_locked(struct lom_softc *); 211 static int lom2_read(struct lom_softc *, uint8_t, uint8_t *); 212 static int lom2_write(struct lom_softc *, uint8_t, uint8_t); 213 static int lom2_read_polled(struct lom_softc *, uint8_t, uint8_t *); 214 static int lom2_write_polled(struct lom_softc *, uint8_t, uint8_t); 215 static void lom2_queue_cmd(struct lom_softc *, struct lom_cmd *); 216 static int lom2_intr(void *); 217 218 static int lom_init_desc(struct lom_softc *); 219 static void lom_refresh(struct sysmon_envsys *, envsys_data_t *); 220 static void lom_refresh_alarm(struct lom_softc *, envsys_data_t *, uint32_t); 221 static void lom_refresh_fan(struct lom_softc *, envsys_data_t *, uint32_t); 222 static void lom_refresh_psu(struct lom_softc *, envsys_data_t *, uint32_t); 223 static void lom_refresh_temp(struct lom_softc *, envsys_data_t *, uint32_t); 224 static void lom1_write_hostname(struct lom_softc *); 225 static void lom2_write_hostname(struct lom_softc *); 226 227 static int lom_wdog_tickle(struct sysmon_wdog *); 228 static int lom_wdog_setmode(struct sysmon_wdog *); 229 230 static bool lom_shutdown(device_t, int); 231 232 SYSCTL_SETUP_PROTO(sysctl_lom_setup); 233 static int lom_sysctl_alarm(SYSCTLFN_PROTO); 234 235 static int hw_node = CTL_EOL; 236 static const char *nodename[LOM_MAX_ALARM] = 237 { "fault_led", "alarm1", "alarm2", "alarm3" }; 238 #ifdef SYSCTL_INCLUDE_DESCR 239 static const char *nodedesc[LOM_MAX_ALARM] = 240 { "Fault LED status", "Alarm1 status", "Alarm2 status ", "Alarm3 status" }; 241 #endif 242 243 static int 244 lom_match(device_t parent, cfdata_t match, void *aux) 245 { 246 struct ebus_attach_args *ea = aux; 247 248 if (strcmp(ea->ea_name, "SUNW,lom") == 0 || 249 strcmp(ea->ea_name, "SUNW,lomh") == 0) 250 return (1); 251 252 return (0); 253 } 254 255 static void 256 lom_attach(device_t parent, device_t self, void *aux) 257 { 258 struct lom_softc *sc = device_private(self); 259 struct ebus_attach_args *ea = aux; 260 uint8_t reg, fw_rev, config, config2, config3; 261 uint8_t cal, low; 262 int i; 263 const struct sysctlnode *node = NULL, *newnode; 264 265 if (strcmp(ea->ea_name, "SUNW,lomh") == 0) { 266 if (ea->ea_nintr < 1) { 267 aprint_error(": no interrupt\n"); 268 return; 269 } 270 sc->sc_type = LOM_LOMLITE2; 271 } 272 273 sc->sc_dev = self; 274 sc->sc_iot = ea->ea_bustag; 275 if (bus_space_map(sc->sc_iot, EBUS_ADDR_FROM_REG(&ea->ea_reg[0]), 276 ea->ea_reg[0].size, 0, &sc->sc_ioh) != 0) { 277 aprint_error(": can't map register space\n"); 278 return; 279 } 280 281 if (sc->sc_type < LOM_LOMLITE2) { 282 /* XXX Magic */ 283 (void)bus_space_read_1(sc->sc_iot, sc->sc_ioh, 0); 284 bus_space_write_1(sc->sc_iot, sc->sc_ioh, 3, 0xca); 285 } 286 287 if (lom_read(sc, LOM_IDX_PROBE55, ®) || reg != 0x55 || 288 lom_read(sc, LOM_IDX_PROBEAA, ®) || reg != 0xaa || 289 lom_read(sc, LOM_IDX_FW_REV, &fw_rev) || 290 lom_read(sc, LOM_IDX_CONFIG, &config)) 291 { 292 aprint_error(": not responding\n"); 293 return; 294 } 295 296 aprint_normal(": %s: %s rev %d.%d\n", ea->ea_name, 297 sc->sc_type < LOM_LOMLITE2 ? "LOMlite" : "LOMlite2", 298 fw_rev >> 4, fw_rev & 0x0f); 299 300 TAILQ_INIT(&sc->sc_queue); 301 mutex_init(&sc->sc_queue_mtx, MUTEX_DEFAULT, IPL_BIO); 302 303 config2 = config3 = 0; 304 if (sc->sc_type < LOM_LOMLITE2) { 305 /* 306 * LOMlite doesn't do interrupts so we limp along on 307 * timeouts. 308 */ 309 callout_init(&sc->sc_state_to, 0); 310 callout_setfunc(&sc->sc_state_to, lom1_process_queue, sc); 311 } else { 312 lom_read(sc, LOM_IDX_CONFIG2, &config2); 313 lom_read(sc, LOM_IDX_CONFIG3, &config3); 314 315 bus_intr_establish(sc->sc_iot, ea->ea_intr[0], 316 IPL_BIO, lom2_intr, sc); 317 } 318 319 sc->sc_num_alarm = LOM_MAX_ALARM; 320 sc->sc_num_fan = min((config >> 5) & 0x7, LOM_MAX_FAN); 321 sc->sc_num_psu = min((config >> 3) & 0x3, LOM_MAX_PSU); 322 sc->sc_num_temp = min((config2 >> 4) & 0xf, LOM_MAX_TEMP); 323 324 aprint_verbose_dev(self, "%d fan(s), %d PSU(s), %d temp sensor(s)\n", 325 sc->sc_num_fan, sc->sc_num_psu, sc->sc_num_temp); 326 327 for (i = 0; i < sc->sc_num_fan; i++) { 328 if (lom_read(sc, LOM_IDX_FAN1_CAL + i, &cal) || 329 lom_read(sc, LOM_IDX_FAN1_LOW + i, &low)) { 330 aprint_error_dev(self, "can't read fan information\n"); 331 return; 332 } 333 sc->sc_fan_cal[i] = cal; 334 sc->sc_fan_low[i] = low; 335 } 336 337 /* Setup our sysctl subtree, hw.lomN */ 338 if (hw_node != CTL_EOL) 339 sysctl_createv(NULL, 0, NULL, &node, 340 0, CTLTYPE_NODE, device_xname(self), NULL, 341 NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL); 342 343 /* Initialize sensor data. */ 344 sc->sc_sme = sysmon_envsys_create(); 345 for (i = 0; i < sc->sc_num_alarm; i++) { 346 sc->sc_alarm[i].units = ENVSYS_INDICATOR; 347 snprintf(sc->sc_alarm[i].desc, sizeof(sc->sc_alarm[i].desc), 348 i == 0 ? "Fault LED" : "Alarm%d", i); 349 if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_alarm[i])) { 350 sysmon_envsys_destroy(sc->sc_sme); 351 aprint_error_dev(self, "can't attach alarm sensor\n"); 352 return; 353 } 354 if (node != NULL) { 355 sysctl_createv(NULL, 0, NULL, &newnode, 356 CTLFLAG_READWRITE, CTLTYPE_INT, nodename[i], 357 SYSCTL_DESCR(nodedesc[i]), 358 lom_sysctl_alarm, 0, sc, 0, 359 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL); 360 if (newnode != NULL) 361 sc->sc_sysctl_num[i] = newnode->sysctl_num; 362 else 363 sc->sc_sysctl_num[i] = 0; 364 } 365 } 366 for (i = 0; i < sc->sc_num_fan; i++) { 367 sc->sc_fan[i].units = ENVSYS_SFANRPM; 368 snprintf(sc->sc_fan[i].desc, sizeof(sc->sc_fan[i].desc), 369 "fan%d", i + 1); 370 if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_fan[i])) { 371 sysmon_envsys_destroy(sc->sc_sme); 372 aprint_error_dev(self, "can't attach fan sensor\n"); 373 return; 374 } 375 } 376 for (i = 0; i < sc->sc_num_psu; i++) { 377 sc->sc_psu[i].units = ENVSYS_INDICATOR; 378 snprintf(sc->sc_psu[i].desc, sizeof(sc->sc_psu[i].desc), 379 "PSU%d", i + 1); 380 if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_psu[i])) { 381 sysmon_envsys_destroy(sc->sc_sme); 382 aprint_error_dev(self, "can't attach PSU sensor\n"); 383 return; 384 } 385 } 386 for (i = 0; i < sc->sc_num_temp; i++) { 387 sc->sc_temp[i].units = ENVSYS_STEMP; 388 snprintf(sc->sc_temp[i].desc, sizeof(sc->sc_temp[i].desc), 389 "temp%d", i + 1); 390 if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_temp[i])) { 391 sysmon_envsys_destroy(sc->sc_sme); 392 aprint_error_dev(self, "can't attach temp sensor\n"); 393 return; 394 } 395 } 396 if (lom_init_desc(sc)) { 397 aprint_error_dev(self, "can't read sensor names\n"); 398 sysmon_envsys_destroy(sc->sc_sme); 399 return; 400 } 401 402 sc->sc_sme->sme_name = device_xname(self); 403 sc->sc_sme->sme_cookie = sc; 404 sc->sc_sme->sme_refresh = lom_refresh; 405 if (sysmon_envsys_register(sc->sc_sme)) { 406 aprint_error_dev(self, 407 "unable to register envsys with sysmon\n"); 408 sysmon_envsys_destroy(sc->sc_sme); 409 return; 410 } 411 412 /* Initialize watchdog. */ 413 lom_write(sc, LOM_IDX_WDOG_TIME, LOM_WDOG_TIME_MAX); 414 lom_read(sc, LOM_IDX_WDOG_CTL, &sc->sc_wdog_ctl); 415 sc->sc_wdog_ctl &= ~(LOM_WDOG_ENABLE|LOM_WDOG_RESET); 416 lom_write(sc, LOM_IDX_WDOG_CTL, sc->sc_wdog_ctl); 417 418 sc->sc_wdog_period = LOM_WDOG_TIME_MAX; 419 420 sc->sc_smw.smw_name = device_xname(self); 421 sc->sc_smw.smw_cookie = sc; 422 sc->sc_smw.smw_setmode = lom_wdog_setmode; 423 sc->sc_smw.smw_tickle = lom_wdog_tickle; 424 sc->sc_smw.smw_period = sc->sc_wdog_period; 425 if (sysmon_wdog_register(&sc->sc_smw)) { 426 aprint_error_dev(self, 427 "unable to register wdog with sysmon\n"); 428 return; 429 } 430 431 aprint_verbose_dev(self, "Watchdog timer configured.\n"); 432 433 if (!pmf_device_register1(self, NULL, NULL, lom_shutdown)) 434 aprint_error_dev(self, "unable to register power handler\n"); 435 } 436 437 static int 438 lom_read(struct lom_softc *sc, uint8_t reg, uint8_t *val) 439 { 440 if (sc->sc_type < LOM_LOMLITE2) 441 return lom1_read(sc, reg, val); 442 else 443 return lom2_read(sc, reg, val); 444 } 445 446 static int 447 lom_write(struct lom_softc *sc, uint8_t reg, uint8_t val) 448 { 449 if (sc->sc_type < LOM_LOMLITE2) 450 return lom1_write(sc, reg, val); 451 else 452 return lom2_write(sc, reg, val); 453 } 454 455 static void 456 lom_queue_cmd(struct lom_softc *sc, struct lom_cmd *lc) 457 { 458 if (sc->sc_type < LOM_LOMLITE2) 459 return lom1_queue_cmd(sc, lc); 460 else 461 return lom2_queue_cmd(sc, lc); 462 } 463 464 static void 465 lom_dequeue_cmd(struct lom_softc *sc, struct lom_cmd *lc) 466 { 467 struct lom_cmd *lcp; 468 469 mutex_enter(&sc->sc_queue_mtx); 470 TAILQ_FOREACH(lcp, &sc->sc_queue, lc_next) { 471 if (lcp == lc) { 472 TAILQ_REMOVE(&sc->sc_queue, lc, lc_next); 473 break; 474 } 475 } 476 mutex_exit(&sc->sc_queue_mtx); 477 } 478 479 static int 480 lom1_read(struct lom_softc *sc, uint8_t reg, uint8_t *val) 481 { 482 struct lom_cmd lc; 483 int error; 484 485 if (cold) 486 return lom1_read_polled(sc, reg, val); 487 488 lc.lc_cmd = reg; 489 lc.lc_data = 0xff; 490 lom1_queue_cmd(sc, &lc); 491 492 error = tsleep(&lc, PZERO, "lomrd", hz); 493 if (error) 494 lom_dequeue_cmd(sc, &lc); 495 496 *val = lc.lc_data; 497 498 return (error); 499 } 500 501 static int 502 lom1_write(struct lom_softc *sc, uint8_t reg, uint8_t val) 503 { 504 struct lom_cmd lc; 505 int error; 506 507 if (cold) 508 return lom1_write_polled(sc, reg, val); 509 510 lc.lc_cmd = reg | LOM_IDX_WRITE; 511 lc.lc_data = val; 512 lom1_queue_cmd(sc, &lc); 513 514 error = tsleep(&lc, PZERO, "lomwr", 2 * hz); 515 if (error) 516 lom_dequeue_cmd(sc, &lc); 517 518 return (error); 519 } 520 521 static int 522 lom1_read_polled(struct lom_softc *sc, uint8_t reg, uint8_t *val) 523 { 524 uint8_t str; 525 int i; 526 527 /* Wait for input buffer to become available. */ 528 for (i = 30; i > 0; i--) { 529 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS); 530 delay(1000); 531 if ((str & LOM1_STATUS_BUSY) == 0) 532 break; 533 } 534 if (i == 0) 535 return (ETIMEDOUT); 536 537 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_CMD, reg); 538 539 /* Wait until the microcontroller fills output buffer. */ 540 for (i = 30; i > 0; i--) { 541 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS); 542 delay(1000); 543 if ((str & LOM1_STATUS_BUSY) == 0) 544 break; 545 } 546 if (i == 0) 547 return (ETIMEDOUT); 548 549 *val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA); 550 return (0); 551 } 552 553 static int 554 lom1_write_polled(struct lom_softc *sc, uint8_t reg, uint8_t val) 555 { 556 uint8_t str; 557 int i; 558 559 /* Wait for input buffer to become available. */ 560 for (i = 30; i > 0; i--) { 561 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS); 562 delay(1000); 563 if ((str & LOM1_STATUS_BUSY) == 0) 564 break; 565 } 566 if (i == 0) 567 return (ETIMEDOUT); 568 569 reg |= LOM_IDX_WRITE; 570 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_CMD, reg); 571 572 /* Wait until the microcontroller fills output buffer. */ 573 for (i = 30; i > 0; i--) { 574 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS); 575 delay(1000); 576 if ((str & LOM1_STATUS_BUSY) == 0) 577 break; 578 } 579 if (i == 0) 580 return (ETIMEDOUT); 581 582 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA, val); 583 584 return (0); 585 } 586 587 static void 588 lom1_queue_cmd(struct lom_softc *sc, struct lom_cmd *lc) 589 { 590 mutex_enter(&sc->sc_queue_mtx); 591 TAILQ_INSERT_TAIL(&sc->sc_queue, lc, lc_next); 592 if (sc->sc_state == LOM_STATE_IDLE) { 593 sc->sc_state = LOM_STATE_CMD; 594 lom1_process_queue_locked(sc); 595 } 596 mutex_exit(&sc->sc_queue_mtx); 597 } 598 599 static void 600 lom1_process_queue(void *arg) 601 { 602 struct lom_softc *sc = arg; 603 604 mutex_enter(&sc->sc_queue_mtx); 605 lom1_process_queue_locked(sc); 606 mutex_exit(&sc->sc_queue_mtx); 607 } 608 609 static void 610 lom1_process_queue_locked(struct lom_softc *sc) 611 { 612 struct lom_cmd *lc; 613 uint8_t str; 614 615 lc = TAILQ_FIRST(&sc->sc_queue); 616 if (lc == NULL) { 617 sc->sc_state = LOM_STATE_IDLE; 618 return; 619 } 620 621 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS); 622 if (str & LOM1_STATUS_BUSY) { 623 if (sc->sc_retry++ < 30) { 624 callout_schedule(&sc->sc_state_to, mstohz(1)); 625 return; 626 } 627 628 /* 629 * Looks like the microcontroller got wedged. Unwedge 630 * it by writing this magic value. Give it some time 631 * to recover. 632 */ 633 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA, 0xac); 634 callout_schedule(&sc->sc_state_to, mstohz(1000)); 635 sc->sc_state = LOM_STATE_CMD; 636 return; 637 } 638 639 sc->sc_retry = 0; 640 641 if (sc->sc_state == LOM_STATE_CMD) { 642 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_CMD, lc->lc_cmd); 643 sc->sc_state = LOM_STATE_DATA; 644 callout_schedule(&sc->sc_state_to, mstohz(250)); 645 return; 646 } 647 648 KASSERT(sc->sc_state == LOM_STATE_DATA); 649 if ((lc->lc_cmd & LOM_IDX_WRITE) == 0) 650 lc->lc_data = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA); 651 else 652 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA, lc->lc_data); 653 654 TAILQ_REMOVE(&sc->sc_queue, lc, lc_next); 655 656 wakeup(lc); 657 658 if (!TAILQ_EMPTY(&sc->sc_queue)) { 659 sc->sc_state = LOM_STATE_CMD; 660 callout_schedule(&sc->sc_state_to, mstohz(1)); 661 return; 662 } 663 664 sc->sc_state = LOM_STATE_IDLE; 665 } 666 667 static int 668 lom2_read(struct lom_softc *sc, uint8_t reg, uint8_t *val) 669 { 670 struct lom_cmd lc; 671 int error; 672 673 if (cold) 674 return lom2_read_polled(sc, reg, val); 675 676 lc.lc_cmd = reg; 677 lc.lc_data = 0xff; 678 lom2_queue_cmd(sc, &lc); 679 680 error = tsleep(&lc, PZERO, "lom2rd", hz); 681 if (error) 682 lom_dequeue_cmd(sc, &lc); 683 684 *val = lc.lc_data; 685 686 return (error); 687 } 688 689 static int 690 lom2_read_polled(struct lom_softc *sc, uint8_t reg, uint8_t *val) 691 { 692 uint8_t str; 693 int i; 694 695 /* Wait for input buffer to become available. */ 696 for (i = 1000; i > 0; i--) { 697 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); 698 delay(10); 699 if ((str & LOM2_STATUS_IBF) == 0) 700 break; 701 } 702 if (i == 0) 703 return (ETIMEDOUT); 704 705 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM2_CMD, reg); 706 707 /* Wait until the microcontroller fills output buffer. */ 708 for (i = 1000; i > 0; i--) { 709 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); 710 delay(10); 711 if (str & LOM2_STATUS_OBF) 712 break; 713 } 714 if (i == 0) 715 return (ETIMEDOUT); 716 717 *val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA); 718 return (0); 719 } 720 721 static int 722 lom2_write(struct lom_softc *sc, uint8_t reg, uint8_t val) 723 { 724 struct lom_cmd lc; 725 int error; 726 727 if (cold) 728 return lom2_write_polled(sc, reg, val); 729 730 lc.lc_cmd = reg | LOM_IDX_WRITE; 731 lc.lc_data = val; 732 lom2_queue_cmd(sc, &lc); 733 734 error = tsleep(&lc, PZERO, "lom2wr", hz); 735 if (error) 736 lom_dequeue_cmd(sc, &lc); 737 738 return (error); 739 } 740 741 static int 742 lom2_write_polled(struct lom_softc *sc, uint8_t reg, uint8_t val) 743 { 744 uint8_t str; 745 int i; 746 747 /* Wait for input buffer to become available. */ 748 for (i = 1000; i > 0; i--) { 749 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); 750 delay(10); 751 if ((str & LOM2_STATUS_IBF) == 0) 752 break; 753 } 754 if (i == 0) 755 return (ETIMEDOUT); 756 757 if (sc->sc_space == LOM_IDX_CMD_GENERIC && reg != LOM_IDX_CMD) 758 reg |= LOM_IDX_WRITE; 759 760 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM2_CMD, reg); 761 762 /* Wait until the microcontroller fills output buffer. */ 763 for (i = 1000; i > 0; i--) { 764 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); 765 delay(10); 766 if (str & LOM2_STATUS_OBF) 767 break; 768 } 769 if (i == 0) 770 return (ETIMEDOUT); 771 772 (void)bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA); 773 774 /* Wait for input buffer to become available. */ 775 for (i = 1000; i > 0; i--) { 776 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); 777 delay(10); 778 if ((str & LOM2_STATUS_IBF) == 0) 779 break; 780 } 781 if (i == 0) 782 return (ETIMEDOUT); 783 784 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA, val); 785 786 /* Wait until the microcontroller fills output buffer. */ 787 for (i = 1000; i > 0; i--) { 788 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); 789 delay(10); 790 if (str & LOM2_STATUS_OBF) 791 break; 792 } 793 if (i == 0) 794 return (ETIMEDOUT); 795 796 (void)bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA); 797 798 /* If we switched spaces, remember the one we're in now. */ 799 if (reg == LOM_IDX_CMD) 800 sc->sc_space = val; 801 802 return (0); 803 } 804 805 static void 806 lom2_queue_cmd(struct lom_softc *sc, struct lom_cmd *lc) 807 { 808 uint8_t str; 809 810 mutex_enter(&sc->sc_queue_mtx); 811 TAILQ_INSERT_TAIL(&sc->sc_queue, lc, lc_next); 812 if (sc->sc_state == LOM_STATE_IDLE) { 813 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); 814 if ((str & LOM2_STATUS_IBF) == 0) { 815 bus_space_write_1(sc->sc_iot, sc->sc_ioh, 816 LOM2_CMD, lc->lc_cmd); 817 sc->sc_state = LOM_STATE_DATA; 818 } 819 } 820 mutex_exit(&sc->sc_queue_mtx); 821 } 822 823 static int 824 lom2_intr(void *arg) 825 { 826 struct lom_softc *sc = arg; 827 struct lom_cmd *lc; 828 uint8_t str, obr; 829 830 mutex_enter(&sc->sc_queue_mtx); 831 832 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); 833 obr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA); 834 835 lc = TAILQ_FIRST(&sc->sc_queue); 836 if (lc == NULL) { 837 mutex_exit(&sc->sc_queue_mtx); 838 return (0); 839 } 840 841 if (lc->lc_cmd & LOM_IDX_WRITE) { 842 bus_space_write_1(sc->sc_iot, sc->sc_ioh, 843 LOM2_DATA, lc->lc_data); 844 lc->lc_cmd &= ~LOM_IDX_WRITE; 845 mutex_exit(&sc->sc_queue_mtx); 846 return (1); 847 } 848 849 KASSERT(sc->sc_state = LOM_STATE_DATA); 850 lc->lc_data = obr; 851 852 TAILQ_REMOVE(&sc->sc_queue, lc, lc_next); 853 854 wakeup(lc); 855 856 sc->sc_state = LOM_STATE_IDLE; 857 858 if (!TAILQ_EMPTY(&sc->sc_queue)) { 859 str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS); 860 if ((str & LOM2_STATUS_IBF) == 0) { 861 bus_space_write_1(sc->sc_iot, sc->sc_ioh, 862 LOM2_CMD, lc->lc_cmd); 863 sc->sc_state = LOM_STATE_DATA; 864 } 865 } 866 867 mutex_exit(&sc->sc_queue_mtx); 868 869 return (1); 870 } 871 872 static int 873 lom_init_desc(struct lom_softc *sc) 874 { 875 uint8_t val; 876 int i, j, k; 877 int error; 878 879 /* LOMlite doesn't provide sensor descriptions. */ 880 if (sc->sc_type < LOM_LOMLITE2) 881 return (0); 882 883 /* 884 * Read temperature sensor names. 885 */ 886 error = lom_write(sc, LOM_IDX_CMD, LOM_IDX_CMD_TEMP); 887 if (error) 888 return (error); 889 890 i = 0; 891 j = 0; 892 k = LOM_IDX4_TEMP_NAME_START; 893 while (k <= LOM_IDX4_TEMP_NAME_END) { 894 error = lom_read(sc, k++, &val); 895 if (error) 896 goto fail; 897 898 if (val == 0xff) 899 break; 900 901 if (j < sizeof (sc->sc_temp[i].desc) - 1) 902 sc->sc_temp[i].desc[j++] = val; 903 904 if (val == '\0') { 905 i++; 906 j = 0; 907 if (i < sc->sc_num_temp) 908 continue; 909 910 break; 911 } 912 } 913 914 /* 915 * Read fan names. 916 */ 917 error = lom_write(sc, LOM_IDX_CMD, LOM_IDX_CMD_FAN); 918 if (error) 919 return (error); 920 921 i = 0; 922 j = 0; 923 k = LOM_IDX5_FAN_NAME_START; 924 while (k <= LOM_IDX5_FAN_NAME_END) { 925 error = lom_read(sc, k++, &val); 926 if (error) 927 goto fail; 928 929 if (val == 0xff) 930 break; 931 932 if (j < sizeof (sc->sc_fan[i].desc) - 1) 933 sc->sc_fan[i].desc[j++] = val; 934 935 if (val == '\0') { 936 i++; 937 j = 0; 938 if (i < sc->sc_num_fan) 939 continue; 940 941 break; 942 } 943 } 944 945 fail: 946 lom_write(sc, LOM_IDX_CMD, LOM_IDX_CMD_GENERIC); 947 return (error); 948 } 949 950 static void 951 lom_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 952 { 953 struct lom_softc *sc = sme->sme_cookie; 954 uint32_t i; 955 956 /* Sensor number */ 957 i = edata->sensor; 958 959 /* Sensor type */ 960 switch (edata->units) { 961 case ENVSYS_INDICATOR: 962 if (i < sc->sc_num_alarm) 963 lom_refresh_alarm(sc, edata, i); 964 else 965 lom_refresh_psu(sc, edata, 966 i - sc->sc_num_alarm - sc->sc_num_fan); 967 break; 968 case ENVSYS_SFANRPM: 969 lom_refresh_fan(sc, edata, i - sc->sc_num_alarm); 970 break; 971 case ENVSYS_STEMP: 972 lom_refresh_temp(sc, edata, 973 i - sc->sc_num_alarm - sc->sc_num_fan - sc->sc_num_psu); 974 break; 975 default: 976 edata->state = ENVSYS_SINVALID; 977 break; 978 } 979 980 /* 981 * If our hostname is set and differs from what's stored in 982 * the LOM, write the new hostname back to the LOM. Note that 983 * we include the terminating NUL when writing the hostname 984 * back to the LOM, otherwise the LOM will print any trailing 985 * garbage. 986 */ 987 if (i == 0 && hostnamelen > 0 && 988 strncmp(sc->sc_hostname, hostname, sizeof(hostname)) != 0) { 989 if (sc->sc_type < LOM_LOMLITE2) 990 lom1_write_hostname(sc); 991 else 992 lom2_write_hostname(sc); 993 strlcpy(sc->sc_hostname, hostname, sizeof(hostname)); 994 } 995 } 996 997 static void 998 lom_refresh_alarm(struct lom_softc *sc, envsys_data_t *edata, uint32_t i) 999 { 1000 uint8_t val; 1001 1002 /* Fault LED or Alarms */ 1003 KASSERT(i < sc->sc_num_alarm); 1004 1005 if (lom_read(sc, LOM_IDX_ALARM, &val)) { 1006 edata->state = ENVSYS_SINVALID; 1007 } else { 1008 if (i == 0) { 1009 /* Fault LED */ 1010 if ((val & LOM_ALARM_FAULT) == LOM_ALARM_FAULT) 1011 edata->value_cur = 0; 1012 else 1013 edata->value_cur = 1; 1014 } else { 1015 /* Alarms */ 1016 if ((val & (LOM_ALARM_1 << (i - 1))) == 0) 1017 edata->value_cur = 0; 1018 else 1019 edata->value_cur = 1; 1020 } 1021 edata->state = ENVSYS_SVALID; 1022 } 1023 } 1024 1025 static void 1026 lom_refresh_fan(struct lom_softc *sc, envsys_data_t *edata, uint32_t i) 1027 { 1028 uint8_t val; 1029 1030 /* Fan speed */ 1031 KASSERT(i < sc->sc_num_fan); 1032 1033 if (lom_read(sc, LOM_IDX_FAN1 + i, &val)) { 1034 edata->state = ENVSYS_SINVALID; 1035 } else { 1036 edata->value_cur = (60 * sc->sc_fan_cal[i] * val) / 100; 1037 if (val < sc->sc_fan_low[i]) 1038 edata->state = ENVSYS_SCRITICAL; 1039 else 1040 edata->state = ENVSYS_SVALID; 1041 } 1042 } 1043 1044 static void 1045 lom_refresh_psu(struct lom_softc *sc, envsys_data_t *edata, uint32_t i) 1046 { 1047 uint8_t val; 1048 1049 /* PSU status */ 1050 KASSERT(i < sc->sc_num_psu); 1051 1052 if (lom_read(sc, LOM_IDX_PSU1 + i, &val) || 1053 !ISSET(val, LOM_PSU_PRESENT)) { 1054 edata->state = ENVSYS_SINVALID; 1055 } else { 1056 if (val & LOM_PSU_STANDBY) { 1057 edata->value_cur = 0; 1058 edata->state = ENVSYS_SVALID; 1059 } else { 1060 edata->value_cur = 1; 1061 if (ISSET(val, LOM_PSU_INPUTA) && 1062 ISSET(val, LOM_PSU_INPUTB) && 1063 ISSET(val, LOM_PSU_OUTPUT)) 1064 edata->state = ENVSYS_SVALID; 1065 else 1066 edata->state = ENVSYS_SCRITICAL; 1067 } 1068 } 1069 } 1070 1071 static void 1072 lom_refresh_temp(struct lom_softc *sc, envsys_data_t *edata, uint32_t i) 1073 { 1074 uint8_t val; 1075 1076 /* Temperature */ 1077 KASSERT(i < sc->sc_num_temp); 1078 1079 if (lom_read(sc, LOM_IDX_TEMP1 + i, &val)) { 1080 edata->state = ENVSYS_SINVALID; 1081 } else { 1082 edata->value_cur = val * 1000000 + 273150000; 1083 edata->state = ENVSYS_SVALID; 1084 } 1085 } 1086 1087 static void 1088 lom1_write_hostname(struct lom_softc *sc) 1089 { 1090 char name[(LOM1_IDX_HOSTNAME12 - LOM1_IDX_HOSTNAME1 + 1) + 1]; 1091 char *p; 1092 int i; 1093 1094 /* 1095 * LOMlite generally doesn't have enough space to store the 1096 * fully qualified hostname. If the hostname is too long, 1097 * strip off the domain name. 1098 */ 1099 strlcpy(name, hostname, sizeof(name)); 1100 if (hostnamelen >= sizeof(name)) { 1101 p = strchr(name, '.'); 1102 if (p) 1103 *p = '\0'; 1104 } 1105 1106 for (i = 0; i < strlen(name) + 1; i++) 1107 if (lom_write(sc, LOM1_IDX_HOSTNAME1 + i, name[i])) 1108 break; 1109 } 1110 1111 static void 1112 lom2_write_hostname(struct lom_softc *sc) 1113 { 1114 int i; 1115 1116 lom_write(sc, LOM2_IDX_HOSTNAMELEN, hostnamelen + 1); 1117 for (i = 0; i < hostnamelen + 1; i++) 1118 lom_write(sc, LOM2_IDX_HOSTNAME, hostname[i]); 1119 } 1120 1121 static int 1122 lom_wdog_tickle(struct sysmon_wdog *smw) 1123 { 1124 struct lom_softc *sc = smw->smw_cookie; 1125 1126 /* Pat the dog. */ 1127 sc->sc_wdog_pat.lc_cmd = LOM_IDX_WDOG_CTL | LOM_IDX_WRITE; 1128 sc->sc_wdog_pat.lc_data = sc->sc_wdog_ctl; 1129 lom_queue_cmd(sc, &sc->sc_wdog_pat); 1130 1131 return 0; 1132 } 1133 1134 static int 1135 lom_wdog_setmode(struct sysmon_wdog *smw) 1136 { 1137 struct lom_softc *sc = smw->smw_cookie; 1138 1139 if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) { 1140 /* disable watchdog */ 1141 sc->sc_wdog_ctl &= ~(LOM_WDOG_ENABLE|LOM_WDOG_RESET); 1142 lom_write(sc, LOM_IDX_WDOG_CTL, sc->sc_wdog_ctl); 1143 } else { 1144 if (smw->smw_period == WDOG_PERIOD_DEFAULT) 1145 smw->smw_period = sc->sc_wdog_period; 1146 else if (smw->smw_period == 0 || 1147 smw->smw_period > LOM_WDOG_TIME_MAX) 1148 return EINVAL; 1149 lom_write(sc, LOM_IDX_WDOG_TIME, smw->smw_period); 1150 1151 /* enable watchdog */ 1152 lom_dequeue_cmd(sc, &sc->sc_wdog_pat); 1153 sc->sc_wdog_ctl |= LOM_WDOG_ENABLE|LOM_WDOG_RESET; 1154 sc->sc_wdog_pat.lc_cmd = LOM_IDX_WDOG_CTL | LOM_IDX_WRITE; 1155 sc->sc_wdog_pat.lc_data = sc->sc_wdog_ctl; 1156 lom_queue_cmd(sc, &sc->sc_wdog_pat); 1157 } 1158 1159 return 0; 1160 } 1161 1162 static bool 1163 lom_shutdown(device_t dev, int how) 1164 { 1165 struct lom_softc *sc = device_private(dev); 1166 1167 sc->sc_wdog_ctl &= ~LOM_WDOG_ENABLE; 1168 lom_write(sc, LOM_IDX_WDOG_CTL, sc->sc_wdog_ctl); 1169 return true; 1170 } 1171 1172 SYSCTL_SETUP(sysctl_lom_setup, "sysctl hw.lom subtree setup") 1173 { 1174 const struct sysctlnode *node; 1175 1176 if (sysctl_createv(clog, 0, NULL, &node, 1177 CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw", NULL, 1178 NULL, 0, NULL, 0, CTL_HW, CTL_EOL) != 0) 1179 return; 1180 1181 hw_node = node->sysctl_num; 1182 } 1183 1184 static int 1185 lom_sysctl_alarm(SYSCTLFN_ARGS) 1186 { 1187 struct sysctlnode node; 1188 struct lom_softc *sc; 1189 int i, tmp, error; 1190 uint8_t val; 1191 1192 node = *rnode; 1193 sc = node.sysctl_data; 1194 1195 for (i = 0; i < sc->sc_num_alarm; i++) { 1196 if (node.sysctl_num == sc->sc_sysctl_num[i]) { 1197 lom_refresh_alarm(sc, &sc->sc_alarm[i], i); 1198 tmp = sc->sc_alarm[i].value_cur; 1199 node.sysctl_data = &tmp; 1200 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1201 if (error || newp == NULL) 1202 return error; 1203 if (tmp < 0 || tmp > 1) 1204 return EINVAL; 1205 1206 if (lom_read(sc, LOM_IDX_ALARM, &val)) 1207 return EINVAL; 1208 if (i == 0) { 1209 /* Fault LED */ 1210 if (tmp != 0) 1211 val &= ~LOM_ALARM_FAULT; 1212 else 1213 val |= LOM_ALARM_FAULT; 1214 } else { 1215 /* Alarms */ 1216 if (tmp != 0) 1217 val |= LOM_ALARM_1 << (i - 1); 1218 else 1219 val &= ~(LOM_ALARM_1 << (i - 1)); 1220 } 1221 if (lom_write(sc, LOM_IDX_ALARM, val)) 1222 return EINVAL; 1223 1224 sc->sc_alarm[i].value_cur = tmp; 1225 return 0; 1226 } 1227 } 1228 1229 return ENOENT; 1230 } 1231