1/*	$NetBSD: lom.c,v 1.16 2018/09/03 16:29:27 riastradh 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.16 2018/09/03 16:29:27 riastradh 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
144struct lom_cmd {
145	uint8_t			lc_cmd;
146	uint8_t			lc_data;
147
148	TAILQ_ENTRY(lom_cmd)	lc_next;
149};
150
151struct 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
200static int	lom_match(device_t, cfdata_t, void *);
201static void	lom_attach(device_t, device_t, void *);
202
203CFATTACH_DECL_NEW(lom, sizeof(struct lom_softc),
204    lom_match, lom_attach, NULL, NULL);
205
206static int	lom_read(struct lom_softc *, uint8_t, uint8_t *);
207static int	lom_write(struct lom_softc *, uint8_t, uint8_t);
208static void	lom_queue_cmd(struct lom_softc *, struct lom_cmd *);
209static void	lom_dequeue_cmd(struct lom_softc *, struct lom_cmd *);
210static int	lom1_read(struct lom_softc *, uint8_t, uint8_t *);
211static int	lom1_write(struct lom_softc *, uint8_t, uint8_t);
212static int	lom1_read_polled(struct lom_softc *, uint8_t, uint8_t *);
213static int	lom1_write_polled(struct lom_softc *, uint8_t, uint8_t);
214static void	lom1_queue_cmd(struct lom_softc *, struct lom_cmd *);
215static void	lom1_process_queue(void *);
216static void	lom1_process_queue_locked(struct lom_softc *);
217static int	lom2_read(struct lom_softc *, uint8_t, uint8_t *);
218static int	lom2_write(struct lom_softc *, uint8_t, uint8_t);
219static int	lom2_read_polled(struct lom_softc *, uint8_t, uint8_t *);
220static int	lom2_write_polled(struct lom_softc *, uint8_t, uint8_t);
221static void	lom2_queue_cmd(struct lom_softc *, struct lom_cmd *);
222static int	lom2_intr(void *);
223
224static int	lom_init_desc(struct lom_softc *);
225static void	lom_refresh(struct sysmon_envsys *, envsys_data_t *);
226static void	lom_refresh_alarm(struct lom_softc *, envsys_data_t *, uint32_t);
227static void	lom_refresh_fan(struct lom_softc *, envsys_data_t *, uint32_t);
228static void	lom_refresh_psu(struct lom_softc *, envsys_data_t *, uint32_t);
229static void	lom_refresh_temp(struct lom_softc *, envsys_data_t *, uint32_t);
230static void	lom1_write_hostname(struct lom_softc *);
231static void	lom2_write_hostname(struct lom_softc *);
232
233static int	lom_wdog_tickle(struct sysmon_wdog *);
234static int	lom_wdog_setmode(struct sysmon_wdog *);
235
236static bool	lom_shutdown(device_t, int);
237
238SYSCTL_SETUP_PROTO(sysctl_lom_setup);
239static int	lom_sysctl_alarm(SYSCTLFN_PROTO);
240
241static const char *nodename[LOM_MAX_ALARM] =
242    { "fault_led", "alarm1", "alarm2", "alarm3" };
243#ifdef SYSCTL_INCLUDE_DESCR
244static const char *nodedesc[LOM_MAX_ALARM] =
245    { "Fault LED status", "Alarm1 status", "Alarm2 status ", "Alarm3 status" };
246#endif
247static const struct timeval refresh_interval = { 1, 0 };
248
249static int
250lom_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
261static void
262lom_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, err;
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) || reg != 0x55 ||
294	    lom_read(sc, LOM_IDX_PROBEAA, &reg) || 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 = uimin((config >> 5) & 0x7, LOM_MAX_FAN);
327	sc->sc_num_psu = uimin((config >> 3) & 0x3, LOM_MAX_PSU);
328	sc->sc_num_temp = uimin((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	err = sysmon_envsys_register(sc->sc_sme);
419	if (err) {
420		aprint_error_dev(self,
421		    "unable to register envsys with sysmon, error %d\n", err);
422		sysmon_envsys_destroy(sc->sc_sme);
423		return;
424	}
425
426	/* Initialize watchdog. */
427	lom_write(sc, LOM_IDX_WDOG_TIME, LOM_WDOG_TIME_MAX);
428	lom_read(sc, LOM_IDX_WDOG_CTL, &sc->sc_wdog_ctl);
429	sc->sc_wdog_ctl &= ~(LOM_WDOG_ENABLE|LOM_WDOG_RESET);
430	lom_write(sc, LOM_IDX_WDOG_CTL, sc->sc_wdog_ctl);
431
432	sc->sc_wdog_period = LOM_WDOG_TIME_MAX;
433
434	sc->sc_smw.smw_name = device_xname(self);
435	sc->sc_smw.smw_cookie = sc;
436	sc->sc_smw.smw_setmode = lom_wdog_setmode;
437	sc->sc_smw.smw_tickle = lom_wdog_tickle;
438	sc->sc_smw.smw_period = sc->sc_wdog_period;
439	if (sysmon_wdog_register(&sc->sc_smw)) {
440		aprint_error_dev(self,
441		    "unable to register wdog with sysmon\n");
442		return;
443	}
444
445	aprint_verbose_dev(self, "Watchdog timer configured.\n");
446
447	if (!pmf_device_register1(self, NULL, NULL, lom_shutdown))
448		aprint_error_dev(self, "unable to register power handler\n");
449}
450
451static int
452lom_read(struct lom_softc *sc, uint8_t reg, uint8_t *val)
453{
454	if (sc->sc_type < LOM_LOMLITE2)
455		return lom1_read(sc, reg, val);
456	else
457		return lom2_read(sc, reg, val);
458}
459
460static int
461lom_write(struct lom_softc *sc, uint8_t reg, uint8_t val)
462{
463	if (sc->sc_type < LOM_LOMLITE2)
464		return lom1_write(sc, reg, val);
465	else
466		return lom2_write(sc, reg, val);
467}
468
469static void
470lom_queue_cmd(struct lom_softc *sc, struct lom_cmd *lc)
471{
472	if (sc->sc_type < LOM_LOMLITE2)
473		return lom1_queue_cmd(sc, lc);
474	else
475		return lom2_queue_cmd(sc, lc);
476}
477
478static void
479lom_dequeue_cmd(struct lom_softc *sc, struct lom_cmd *lc)
480{
481	struct lom_cmd *lcp;
482
483	mutex_enter(&sc->sc_queue_mtx);
484	TAILQ_FOREACH(lcp, &sc->sc_queue, lc_next) {
485		if (lcp == lc) {
486			TAILQ_REMOVE(&sc->sc_queue, lc, lc_next);
487			break;
488		}
489	}
490	mutex_exit(&sc->sc_queue_mtx);
491}
492
493static int
494lom1_read(struct lom_softc *sc, uint8_t reg, uint8_t *val)
495{
496	struct lom_cmd lc;
497	int error;
498
499	if (cold)
500		return lom1_read_polled(sc, reg, val);
501
502	lc.lc_cmd = reg;
503	lc.lc_data = 0xff;
504	lom1_queue_cmd(sc, &lc);
505
506	error = tsleep(&lc, PZERO, "lomrd", hz);
507	if (error)
508		lom_dequeue_cmd(sc, &lc);
509
510	*val = lc.lc_data;
511
512	return (error);
513}
514
515static int
516lom1_write(struct lom_softc *sc, uint8_t reg, uint8_t val)
517{
518	struct lom_cmd lc;
519	int error;
520
521	if (cold)
522		return lom1_write_polled(sc, reg, val);
523
524	lc.lc_cmd = reg | LOM_IDX_WRITE;
525	lc.lc_data = val;
526	lom1_queue_cmd(sc, &lc);
527
528	error = tsleep(&lc, PZERO, "lomwr", 2 * hz);
529	if (error)
530		lom_dequeue_cmd(sc, &lc);
531
532	return (error);
533}
534
535static int
536lom1_read_polled(struct lom_softc *sc, uint8_t reg, uint8_t *val)
537{
538	uint8_t str;
539	int i;
540
541	/* Wait for input buffer to become available. */
542	for (i = 30; i > 0; i--) {
543		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS);
544		delay(1000);
545		if ((str & LOM1_STATUS_BUSY) == 0)
546			break;
547	}
548	if (i == 0)
549		return (ETIMEDOUT);
550
551	bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_CMD, reg);
552
553	/* Wait until the microcontroller fills output buffer. */
554	for (i = 30; i > 0; i--) {
555		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS);
556		delay(1000);
557		if ((str & LOM1_STATUS_BUSY) == 0)
558			break;
559	}
560	if (i == 0)
561		return (ETIMEDOUT);
562
563	*val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA);
564	return (0);
565}
566
567static int
568lom1_write_polled(struct lom_softc *sc, uint8_t reg, uint8_t val)
569{
570	uint8_t str;
571	int i;
572
573	/* Wait for input buffer to become available. */
574	for (i = 30; i > 0; i--) {
575		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS);
576		delay(1000);
577		if ((str & LOM1_STATUS_BUSY) == 0)
578			break;
579	}
580	if (i == 0)
581		return (ETIMEDOUT);
582
583	reg |= LOM_IDX_WRITE;
584	bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_CMD, reg);
585
586	/* Wait until the microcontroller fills output buffer. */
587	for (i = 30; i > 0; i--) {
588		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS);
589		delay(1000);
590		if ((str & LOM1_STATUS_BUSY) == 0)
591			break;
592	}
593	if (i == 0)
594		return (ETIMEDOUT);
595
596	bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA, val);
597
598	return (0);
599}
600
601static void
602lom1_queue_cmd(struct lom_softc *sc, struct lom_cmd *lc)
603{
604	struct lom_cmd *lcp;
605
606	mutex_enter(&sc->sc_queue_mtx);
607	TAILQ_FOREACH(lcp, &sc->sc_queue, lc_next) {
608		if (lcp == lc) {
609			mutex_exit(&sc->sc_queue_mtx);
610			return;
611		}
612	}
613	TAILQ_INSERT_TAIL(&sc->sc_queue, lc, lc_next);
614	if (sc->sc_state == LOM_STATE_IDLE) {
615		sc->sc_state = LOM_STATE_CMD;
616		lom1_process_queue_locked(sc);
617	}
618	mutex_exit(&sc->sc_queue_mtx);
619}
620
621static void
622lom1_process_queue(void *arg)
623{
624	struct lom_softc *sc = arg;
625
626	mutex_enter(&sc->sc_queue_mtx);
627	lom1_process_queue_locked(sc);
628	mutex_exit(&sc->sc_queue_mtx);
629}
630
631static void
632lom1_process_queue_locked(struct lom_softc *sc)
633{
634	struct lom_cmd *lc;
635	uint8_t str;
636
637	lc = TAILQ_FIRST(&sc->sc_queue);
638	if (lc == NULL) {
639		sc->sc_state = LOM_STATE_IDLE;
640		return;
641	}
642
643	str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS);
644	if (str & LOM1_STATUS_BUSY) {
645		if (sc->sc_retry++ < 30) {
646			callout_schedule(&sc->sc_state_to, mstohz(1));
647			return;
648		}
649
650		/*
651		 * Looks like the microcontroller got wedged.  Unwedge
652		 * it by writing this magic value.  Give it some time
653		 * to recover.
654		 */
655		bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA, 0xac);
656		callout_schedule(&sc->sc_state_to, mstohz(1000));
657		sc->sc_state = LOM_STATE_CMD;
658		return;
659	}
660
661	sc->sc_retry = 0;
662
663	if (sc->sc_state == LOM_STATE_CMD) {
664		bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_CMD, lc->lc_cmd);
665		sc->sc_state = LOM_STATE_DATA;
666		callout_schedule(&sc->sc_state_to, mstohz(250));
667		return;
668	}
669
670	KASSERT(sc->sc_state == LOM_STATE_DATA);
671	if ((lc->lc_cmd & LOM_IDX_WRITE) == 0)
672		lc->lc_data = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA);
673	else
674		bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA, lc->lc_data);
675
676	TAILQ_REMOVE(&sc->sc_queue, lc, lc_next);
677
678	wakeup(lc);
679
680	if (!TAILQ_EMPTY(&sc->sc_queue)) {
681		sc->sc_state = LOM_STATE_CMD;
682		callout_schedule(&sc->sc_state_to, mstohz(1));
683		return;
684	}
685
686	sc->sc_state = LOM_STATE_IDLE;
687}
688
689static int
690lom2_read(struct lom_softc *sc, uint8_t reg, uint8_t *val)
691{
692	struct lom_cmd lc;
693	int error;
694
695	if (cold)
696		return lom2_read_polled(sc, reg, val);
697
698	lc.lc_cmd = reg;
699	lc.lc_data = 0xff;
700	lom2_queue_cmd(sc, &lc);
701
702	error = tsleep(&lc, PZERO, "lom2rd", hz);
703	if (error)
704		lom_dequeue_cmd(sc, &lc);
705
706	*val = lc.lc_data;
707
708	return (error);
709}
710
711static int
712lom2_read_polled(struct lom_softc *sc, uint8_t reg, uint8_t *val)
713{
714	uint8_t str;
715	int i;
716
717	/* Wait for input buffer to become available. */
718	for (i = 1000; i > 0; i--) {
719		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
720		delay(10);
721		if ((str & LOM2_STATUS_IBF) == 0)
722			break;
723	}
724	if (i == 0)
725		return (ETIMEDOUT);
726
727	bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM2_CMD, reg);
728
729	/* Wait until the microcontroller fills output buffer. */
730	for (i = 1000; i > 0; i--) {
731		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
732		delay(10);
733		if (str & LOM2_STATUS_OBF)
734			break;
735	}
736	if (i == 0)
737		return (ETIMEDOUT);
738
739	*val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA);
740	return (0);
741}
742
743static int
744lom2_write(struct lom_softc *sc, uint8_t reg, uint8_t val)
745{
746	struct lom_cmd lc;
747	int error;
748
749	if (cold)
750		return lom2_write_polled(sc, reg, val);
751
752	lc.lc_cmd = reg | LOM_IDX_WRITE;
753	lc.lc_data = val;
754	lom2_queue_cmd(sc, &lc);
755
756	error = tsleep(&lc, PZERO, "lom2wr", hz);
757	if (error)
758		lom_dequeue_cmd(sc, &lc);
759
760	return (error);
761}
762
763static int
764lom2_write_polled(struct lom_softc *sc, uint8_t reg, uint8_t val)
765{
766	uint8_t str;
767	int i;
768
769	/* Wait for input buffer to become available. */
770	for (i = 1000; i > 0; i--) {
771		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
772		delay(10);
773		if ((str & LOM2_STATUS_IBF) == 0)
774			break;
775	}
776	if (i == 0)
777		return (ETIMEDOUT);
778
779	if (sc->sc_space == LOM_IDX_CMD_GENERIC && reg != LOM_IDX_CMD)
780		reg |= LOM_IDX_WRITE;
781
782	bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM2_CMD, reg);
783
784	/* Wait until the microcontroller fills output buffer. */
785	for (i = 1000; i > 0; i--) {
786		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
787		delay(10);
788		if (str & LOM2_STATUS_OBF)
789			break;
790	}
791	if (i == 0)
792		return (ETIMEDOUT);
793
794	(void)bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA);
795
796	/* Wait for input buffer to become available. */
797	for (i = 1000; i > 0; i--) {
798		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
799		delay(10);
800		if ((str & LOM2_STATUS_IBF) == 0)
801			break;
802	}
803	if (i == 0)
804		return (ETIMEDOUT);
805
806	bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA, val);
807
808	/* Wait until the microcontroller fills output buffer. */
809	for (i = 1000; i > 0; i--) {
810		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
811		delay(10);
812		if (str & LOM2_STATUS_OBF)
813			break;
814	}
815	if (i == 0)
816		return (ETIMEDOUT);
817
818	(void)bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA);
819
820	/* If we switched spaces, remember the one we're in now. */
821	if (reg == LOM_IDX_CMD)
822		sc->sc_space = val;
823
824	return (0);
825}
826
827static void
828lom2_queue_cmd(struct lom_softc *sc, struct lom_cmd *lc)
829{
830	struct lom_cmd *lcp;
831	uint8_t str;
832
833	mutex_enter(&sc->sc_queue_mtx);
834	TAILQ_FOREACH(lcp, &sc->sc_queue, lc_next) {
835		if (lcp == lc) {
836			mutex_exit(&sc->sc_queue_mtx);
837			return;
838		}
839	}
840	TAILQ_INSERT_TAIL(&sc->sc_queue, lc, lc_next);
841	if (sc->sc_state == LOM_STATE_IDLE) {
842		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
843		if ((str & LOM2_STATUS_IBF) == 0) {
844			lc = TAILQ_FIRST(&sc->sc_queue);
845			bus_space_write_1(sc->sc_iot, sc->sc_ioh,
846			    LOM2_CMD, lc->lc_cmd);
847			sc->sc_state = LOM_STATE_DATA;
848		}
849	}
850	mutex_exit(&sc->sc_queue_mtx);
851}
852
853static int
854lom2_intr(void *arg)
855{
856	struct lom_softc *sc = arg;
857	struct lom_cmd *lc;
858	uint8_t str, obr;
859
860	mutex_enter(&sc->sc_queue_mtx);
861
862	str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
863	obr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA);
864
865	lc = TAILQ_FIRST(&sc->sc_queue);
866	if (lc == NULL) {
867		mutex_exit(&sc->sc_queue_mtx);
868		return (0);
869	}
870
871	if (lc->lc_cmd & LOM_IDX_WRITE) {
872		if ((str & LOM2_STATUS_IBF) == 0) {
873			bus_space_write_1(sc->sc_iot, sc->sc_ioh,
874			    LOM2_DATA, lc->lc_data);
875			lc->lc_cmd &= ~LOM_IDX_WRITE;
876		}
877		mutex_exit(&sc->sc_queue_mtx);
878		return (1);
879	}
880
881	KASSERT(sc->sc_state == LOM_STATE_DATA);
882	lc->lc_data = obr;
883
884	TAILQ_REMOVE(&sc->sc_queue, lc, lc_next);
885
886	wakeup(lc);
887
888	sc->sc_state = LOM_STATE_IDLE;
889
890	if (!TAILQ_EMPTY(&sc->sc_queue)) {
891		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
892		if ((str & LOM2_STATUS_IBF) == 0) {
893			lc = TAILQ_FIRST(&sc->sc_queue);
894			bus_space_write_1(sc->sc_iot, sc->sc_ioh,
895			    LOM2_CMD, lc->lc_cmd);
896			sc->sc_state = LOM_STATE_DATA;
897		}
898	}
899
900	mutex_exit(&sc->sc_queue_mtx);
901
902	return (1);
903}
904
905static int
906lom_init_desc(struct lom_softc *sc)
907{
908	uint8_t val;
909	int i, j, k;
910	int error;
911
912	/* LOMlite doesn't provide sensor descriptions. */
913	if (sc->sc_type < LOM_LOMLITE2)
914		return (0);
915
916	/*
917	 * Read temperature sensor names.
918	 */
919	error = lom_write(sc, LOM_IDX_CMD, LOM_IDX_CMD_TEMP);
920	if (error)
921		return (error);
922
923	i = 0;
924	j = 0;
925	k = LOM_IDX4_TEMP_NAME_START;
926	while (k <= LOM_IDX4_TEMP_NAME_END) {
927		error = lom_read(sc, k++, &val);
928		if (error)
929			goto fail;
930
931		if (val == 0xff)
932			break;
933
934		if (j < sizeof (sc->sc_temp[i].desc) - 1)
935			sc->sc_temp[i].desc[j++] = val;
936
937		if (val == '\0') {
938			i++;
939			j = 0;
940			if (i < sc->sc_num_temp)
941				continue;
942
943			break;
944		}
945	}
946
947	/*
948	 * Read fan names.
949	 */
950	error = lom_write(sc, LOM_IDX_CMD, LOM_IDX_CMD_FAN);
951	if (error)
952		return (error);
953
954	i = 0;
955	j = 0;
956	k = LOM_IDX5_FAN_NAME_START;
957	while (k <= LOM_IDX5_FAN_NAME_END) {
958		error = lom_read(sc, k++, &val);
959		if (error)
960			goto fail;
961
962		if (val == 0xff)
963			break;
964
965		if (j < sizeof (sc->sc_fan[i].desc) - 1)
966			sc->sc_fan[i].desc[j++] = val;
967
968		if (val == '\0') {
969			i++;
970			j = 0;
971			if (i < sc->sc_num_fan)
972				continue;
973
974			break;
975		}
976	}
977
978fail:
979	lom_write(sc, LOM_IDX_CMD, LOM_IDX_CMD_GENERIC);
980	return (error);
981}
982
983static void
984lom_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
985{
986	struct lom_softc *sc = sme->sme_cookie;
987	uint32_t i;
988
989	/* Sensor number */
990	i = edata->sensor;
991
992	/* Sensor type */
993	switch (edata->units) {
994	case ENVSYS_INDICATOR:
995		if (i < sc->sc_num_alarm)
996			lom_refresh_alarm(sc, edata, i);
997		else
998			lom_refresh_psu(sc, edata,
999			    i - sc->sc_num_alarm - sc->sc_num_fan);
1000		break;
1001	case ENVSYS_SFANRPM:
1002		lom_refresh_fan(sc, edata, i - sc->sc_num_alarm);
1003		break;
1004	case ENVSYS_STEMP:
1005		lom_refresh_temp(sc, edata,
1006		    i - sc->sc_num_alarm - sc->sc_num_fan - sc->sc_num_psu);
1007		break;
1008	default:
1009		edata->state = ENVSYS_SINVALID;
1010		break;
1011	}
1012
1013	/*
1014	 * If our hostname is set and differs from what's stored in
1015	 * the LOM, write the new hostname back to the LOM.  Note that
1016	 * we include the terminating NUL when writing the hostname
1017	 * back to the LOM, otherwise the LOM will print any trailing
1018	 * garbage.
1019	 */
1020	if (i == 0 && hostnamelen > 0 &&
1021	    strncmp(sc->sc_hostname, hostname, sizeof(hostname)) != 0) {
1022		if (sc->sc_type < LOM_LOMLITE2)
1023			lom1_write_hostname(sc);
1024		else
1025			lom2_write_hostname(sc);
1026		strlcpy(sc->sc_hostname, hostname, sizeof(hostname));
1027	}
1028}
1029
1030static void
1031lom_refresh_alarm(struct lom_softc *sc, envsys_data_t *edata, uint32_t i)
1032{
1033	uint8_t val;
1034
1035	/* Fault LED or Alarms */
1036	KASSERT(i < sc->sc_num_alarm);
1037
1038	/* Read new value at most once every second. */
1039	if (ratecheck(&sc->sc_alarm_lastread, &refresh_interval)) {
1040		if (lom_read(sc, LOM_IDX_ALARM, &val)) {
1041			edata->state = ENVSYS_SINVALID;
1042			return;
1043		}
1044		sc->sc_alarm_lastval = val;
1045	} else {
1046		val = sc->sc_alarm_lastval;
1047	}
1048
1049	if (i == 0) {
1050		/* Fault LED */
1051		if ((val & LOM_ALARM_FAULT) == LOM_ALARM_FAULT)
1052			edata->value_cur = 0;
1053		else
1054			edata->value_cur = 1;
1055	} else {
1056		/* Alarms */
1057		if ((val & (LOM_ALARM_1 << (i - 1))) == 0)
1058			edata->value_cur = 0;
1059		else
1060			edata->value_cur = 1;
1061	}
1062	edata->state = ENVSYS_SVALID;
1063}
1064
1065static void
1066lom_refresh_fan(struct lom_softc *sc, envsys_data_t *edata, uint32_t i)
1067{
1068	uint8_t val;
1069
1070	/* Fan speed */
1071	KASSERT(i < sc->sc_num_fan);
1072
1073	/* Read new value at most once every second. */
1074	if (!ratecheck(&sc->sc_fan_lastread[i], &refresh_interval))
1075		return;
1076
1077	if (lom_read(sc, LOM_IDX_FAN1 + i, &val)) {
1078		edata->state = ENVSYS_SINVALID;
1079	} else {
1080		edata->value_cur = (60 * sc->sc_fan_cal[i] * val) / 100;
1081		if (val < sc->sc_fan_low[i])
1082			edata->state = ENVSYS_SCRITICAL;
1083		else
1084			edata->state = ENVSYS_SVALID;
1085	}
1086}
1087
1088static void
1089lom_refresh_psu(struct lom_softc *sc, envsys_data_t *edata, uint32_t i)
1090{
1091	uint8_t val;
1092
1093	/* PSU status */
1094	KASSERT(i < sc->sc_num_psu);
1095
1096	/* Read new value at most once every second. */
1097	if (!ratecheck(&sc->sc_psu_lastread[i], &refresh_interval))
1098		return;
1099
1100	if (lom_read(sc, LOM_IDX_PSU1 + i, &val) ||
1101	    !ISSET(val, LOM_PSU_PRESENT)) {
1102		edata->state = ENVSYS_SINVALID;
1103	} else {
1104		if (val & LOM_PSU_STANDBY) {
1105			edata->value_cur = 0;
1106			edata->state = ENVSYS_SVALID;
1107		} else {
1108			edata->value_cur = 1;
1109			if (ISSET(val, LOM_PSU_INPUTA) &&
1110			    ISSET(val, LOM_PSU_INPUTB) &&
1111			    ISSET(val, LOM_PSU_OUTPUT))
1112				edata->state = ENVSYS_SVALID;
1113			else
1114				edata->state = ENVSYS_SCRITICAL;
1115		}
1116	}
1117}
1118
1119static void
1120lom_refresh_temp(struct lom_softc *sc, envsys_data_t *edata, uint32_t i)
1121{
1122	uint8_t val;
1123
1124	/* Temperature */
1125	KASSERT(i < sc->sc_num_temp);
1126
1127	/* Read new value at most once every second. */
1128	if (!ratecheck(&sc->sc_temp_lastread[i], &refresh_interval))
1129		return;
1130
1131	if (lom_read(sc, LOM_IDX_TEMP1 + i, &val)) {
1132		edata->state = ENVSYS_SINVALID;
1133	} else {
1134		edata->value_cur = val * 1000000 + 273150000;
1135		edata->state = ENVSYS_SVALID;
1136	}
1137}
1138
1139static void
1140lom1_write_hostname(struct lom_softc *sc)
1141{
1142	char name[(LOM1_IDX_HOSTNAME12 - LOM1_IDX_HOSTNAME1 + 1) + 1];
1143	char *p;
1144	int i;
1145
1146	/*
1147	 * LOMlite generally doesn't have enough space to store the
1148	 * fully qualified hostname.  If the hostname is too long,
1149	 * strip off the domain name.
1150	 */
1151	strlcpy(name, hostname, sizeof(name));
1152	if (hostnamelen >= sizeof(name)) {
1153		p = strchr(name, '.');
1154		if (p)
1155			*p = '\0';
1156	}
1157
1158	for (i = 0; i < strlen(name) + 1; i++)
1159		if (lom_write(sc, LOM1_IDX_HOSTNAME1 + i, name[i]))
1160			break;
1161}
1162
1163static void
1164lom2_write_hostname(struct lom_softc *sc)
1165{
1166	int i;
1167
1168	lom_write(sc, LOM2_IDX_HOSTNAMELEN, hostnamelen + 1);
1169	for (i = 0; i < hostnamelen + 1; i++)
1170		lom_write(sc, LOM2_IDX_HOSTNAME, hostname[i]);
1171}
1172
1173static int
1174lom_wdog_tickle(struct sysmon_wdog *smw)
1175{
1176	struct lom_softc *sc = smw->smw_cookie;
1177
1178	/* Pat the dog. */
1179	sc->sc_wdog_pat.lc_cmd = LOM_IDX_WDOG_CTL | LOM_IDX_WRITE;
1180	sc->sc_wdog_pat.lc_data = sc->sc_wdog_ctl;
1181	lom_queue_cmd(sc, &sc->sc_wdog_pat);
1182
1183	return 0;
1184}
1185
1186static int
1187lom_wdog_setmode(struct sysmon_wdog *smw)
1188{
1189	struct lom_softc *sc = smw->smw_cookie;
1190
1191	if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) {
1192		/* disable watchdog */
1193		sc->sc_wdog_ctl &= ~(LOM_WDOG_ENABLE|LOM_WDOG_RESET);
1194		lom_write(sc, LOM_IDX_WDOG_CTL, sc->sc_wdog_ctl);
1195	} else {
1196		if (smw->smw_period == WDOG_PERIOD_DEFAULT)
1197			smw->smw_period = sc->sc_wdog_period;
1198		else if (smw->smw_period == 0 ||
1199		    smw->smw_period > LOM_WDOG_TIME_MAX)
1200			return EINVAL;
1201		lom_write(sc, LOM_IDX_WDOG_TIME, smw->smw_period);
1202
1203		/* enable watchdog */
1204		lom_dequeue_cmd(sc, &sc->sc_wdog_pat);
1205		sc->sc_wdog_ctl |= LOM_WDOG_ENABLE|LOM_WDOG_RESET;
1206		sc->sc_wdog_pat.lc_cmd = LOM_IDX_WDOG_CTL | LOM_IDX_WRITE;
1207		sc->sc_wdog_pat.lc_data = sc->sc_wdog_ctl;
1208		lom_queue_cmd(sc, &sc->sc_wdog_pat);
1209	}
1210
1211	return 0;
1212}
1213
1214static bool
1215lom_shutdown(device_t dev, int how)
1216{
1217	struct lom_softc *sc = device_private(dev);
1218
1219	sc->sc_wdog_ctl &= ~LOM_WDOG_ENABLE;
1220	lom_write(sc, LOM_IDX_WDOG_CTL, sc->sc_wdog_ctl);
1221	return true;
1222}
1223
1224static int
1225lom_sysctl_alarm(SYSCTLFN_ARGS)
1226{
1227	struct sysctlnode node;
1228	struct lom_softc *sc;
1229	int i, tmp, error;
1230	uint8_t val;
1231
1232	node = *rnode;
1233	sc = node.sysctl_data;
1234
1235	for (i = 0; i < sc->sc_num_alarm; i++) {
1236		if (node.sysctl_num == sc->sc_sysctl_num[i]) {
1237			lom_refresh_alarm(sc, &sc->sc_alarm[i], i);
1238			tmp = sc->sc_alarm[i].value_cur;
1239			node.sysctl_data = &tmp;
1240			error = sysctl_lookup(SYSCTLFN_CALL(&node));
1241			if (error || newp == NULL)
1242				return error;
1243			if (tmp < 0 || tmp > 1)
1244				return EINVAL;
1245
1246			if (lom_read(sc, LOM_IDX_ALARM, &val))
1247				return EINVAL;
1248			if (i == 0) {
1249				/* Fault LED */
1250				if (tmp != 0)
1251					val &= ~LOM_ALARM_FAULT;
1252				else
1253					val |= LOM_ALARM_FAULT;
1254			} else {
1255				/* Alarms */
1256				if (tmp != 0)
1257					val |= LOM_ALARM_1 << (i - 1);
1258				else
1259					val &= ~(LOM_ALARM_1 << (i - 1));
1260			}
1261			if (lom_write(sc, LOM_IDX_ALARM, val))
1262				return EINVAL;
1263
1264			sc->sc_alarm[i].value_cur = tmp;
1265			return 0;
1266		}
1267	}
1268
1269	return ENOENT;
1270}
1271