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