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