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