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