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