xref: /openbsd/sys/arch/sparc64/dev/lom.c (revision fc69c4e1)
1 /*	$OpenBSD: lom.c,v 1.11 2009/09/23 22:04:02 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_IDX4_TEMP_NAME_START	0x40
123 #define LOM_IDX4_TEMP_NAME_END		0xff
124 
125 #define LOM_IDX5_FAN_NAME_START		0x40
126 #define LOM_IDX5_FAN_NAME_END		0xff
127 
128 #define LOM_MAX_FAN	4
129 #define LOM_MAX_PSU	3
130 #define LOM_MAX_TEMP	8
131 
132 struct lom_softc {
133 	struct device		sc_dev;
134 	bus_space_tag_t		sc_iot;
135 	bus_space_handle_t	sc_ioh;
136 
137 	int			sc_type;
138 #define LOM_LOMLITE		0
139 #define LOM_LOMLITE2		2
140 	int			sc_space;
141 
142 	struct ksensor		sc_fan[LOM_MAX_FAN];
143 	struct ksensor		sc_psu[LOM_MAX_PSU];
144 	struct ksensor		sc_temp[LOM_MAX_TEMP];
145 	struct ksensordev	sc_sensordev;
146 
147 	int			sc_num_fan;
148 	int			sc_num_psu;
149 	int			sc_num_temp;
150 
151 	uint8_t			sc_fan_cal[LOM_MAX_FAN];
152 	uint8_t			sc_fan_low[LOM_MAX_FAN];
153 
154 	char			sc_hostname[MAXHOSTNAMELEN];
155 
156 	struct timeout		sc_wdog_to;
157 	int			sc_wdog_period;
158 	uint8_t			sc_wdog_ctl;
159 
160 	uint8_t			sc_cmd;
161 	uint8_t			sc_data;
162 	struct timeout		sc_state_to;
163 	int			sc_state;
164 #define LOM_STATE_IDLE		0
165 #define LOM_STATE_READ_CMD	1
166 #define LOM_STATE_READ_DATA	2
167 #define LOM_STATE_READ_DONE	3
168 };
169 
170 int	lom_match(struct device *, void *, void *);
171 void	lom_attach(struct device *, struct device *, void *);
172 
173 struct cfattach lom_ca = {
174 	sizeof(struct lom_softc), lom_match, lom_attach
175 };
176 
177 struct cfdriver lom_cd = {
178 	NULL, "lom", DV_DULL
179 };
180 
181 int	lom_read(struct lom_softc *, uint8_t, uint8_t *);
182 int	lom_write(struct lom_softc *, uint8_t, uint8_t);
183 int	lom1_read(struct lom_softc *, uint8_t, uint8_t *);
184 int	lom1_read_polled(struct lom_softc *, uint8_t, uint8_t *);
185 int	lom1_write(struct lom_softc *, uint8_t, uint8_t);
186 void	lom1_state(void *);
187 int	lom2_read(struct lom_softc *, uint8_t, uint8_t *);
188 int	lom2_write(struct lom_softc *, uint8_t, uint8_t);
189 
190 int	lom_init_desc(struct lom_softc *sc);
191 void	lom_refresh(void *);
192 void	lom1_write_hostname(struct lom_softc *);
193 void	lom2_write_hostname(struct lom_softc *);
194 
195 void	lom_wdog_pat(void *);
196 int	lom_wdog_cb(void *, int);
197 
198 int
199 lom_match(struct device *parent, void *match, void *aux)
200 {
201 	struct ebus_attach_args *ea = aux;
202 
203 	if (strcmp(ea->ea_name, "SUNW,lom") == 0 ||
204 	    strcmp(ea->ea_name, "SUNW,lomh") == 0)
205 		return (1);
206 
207 	return (0);
208 }
209 
210 void
211 lom_attach(struct device *parent, struct device *self, void *aux)
212 {
213 	struct lom_softc *sc = (void *)self;
214 	struct ebus_attach_args *ea = aux;
215 	uint8_t reg, fw_rev, config, config2, config3;
216 	uint8_t cal, low;
217 	int i;
218 
219 	if (strcmp(ea->ea_name, "SUNW,lomh") == 0)
220 		sc->sc_type = LOM_LOMLITE2;
221 
222 	if (ebus_bus_map(ea->ea_iotag, 0,
223 	    EBUS_PADDR_FROM_REG(&ea->ea_regs[0]),
224 	    ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) {
225 		sc->sc_iot = ea->ea_iotag;
226 	} else if (ebus_bus_map(ea->ea_memtag, 0,
227 	    EBUS_PADDR_FROM_REG(&ea->ea_regs[0]),
228 	    ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) {
229 		sc->sc_iot = ea->ea_memtag;
230 	} else {
231 		printf(": can't map register space\n");
232                 return;
233 	}
234 
235 	if (sc->sc_type < LOM_LOMLITE2) {
236 		/* XXX Magic */
237 		bus_space_read_1(sc->sc_iot, sc->sc_ioh, 0);
238 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, 3, 0xca);
239 
240 		timeout_set(&sc->sc_state_to, lom1_state, sc);
241 	}
242 
243 	if (lom_read(sc, LOM_IDX_PROBE55, &reg) || reg != 0x55 ||
244 	    lom_read(sc, LOM_IDX_PROBEAA, &reg) || reg != 0xaa ||
245 	    lom_read(sc, LOM_IDX_FW_REV, &fw_rev) ||
246 	    lom_read(sc, LOM_IDX_CONFIG, &config))
247 	{
248 		printf(": not responding\n");
249 		return;
250 	}
251 
252 	config2 = config3 = 0;
253 	if (sc->sc_type >= LOM_LOMLITE2) {
254 		lom_read(sc, LOM_IDX_CONFIG2, &config2);
255 		lom_read(sc, LOM_IDX_CONFIG3, &config3);
256 	}
257 
258 	sc->sc_num_fan = min((config >> 5) & 0x7, LOM_MAX_FAN);
259 	sc->sc_num_psu = min((config >> 3) & 0x3, LOM_MAX_PSU);
260 	sc->sc_num_temp = min((config2 >> 4) & 0xf, LOM_MAX_TEMP);
261 
262 	for (i = 0; i < sc->sc_num_fan; i++) {
263 		if (lom_read(sc, LOM_IDX_FAN1_CAL + i, &cal) ||
264 		    lom_read(sc, LOM_IDX_FAN1_LOW + i, &low)) {
265 			printf(": can't read fan information\n");
266 			return;
267 		}
268 		sc->sc_fan_cal[i] = cal;
269 		sc->sc_fan_low[i] = low;
270 	}
271 
272 	/* Initialize sensor data. */
273 	strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
274 	    sizeof(sc->sc_sensordev.xname));
275 	for (i = 0; i < sc->sc_num_fan; i++) {
276 		sc->sc_fan[i].type = SENSOR_FANRPM;
277 		sensor_attach(&sc->sc_sensordev, &sc->sc_fan[i]);
278 		snprintf(sc->sc_fan[i].desc, sizeof(sc->sc_fan[i].desc),
279 		    "fan%d", i + 1);
280 	}
281 	for (i = 0; i < sc->sc_num_psu; i++) {
282 		sc->sc_psu[i].type = SENSOR_INDICATOR;
283 		sensor_attach(&sc->sc_sensordev, &sc->sc_psu[i]);
284 		snprintf(sc->sc_psu[i].desc, sizeof(sc->sc_psu[i].desc),
285 		    "PSU%d", i + 1);
286 	}
287 	for (i = 0; i < sc->sc_num_temp; i++) {
288 		sc->sc_temp[i].type = SENSOR_TEMP;
289 		sensor_attach(&sc->sc_sensordev, &sc->sc_temp[i]);
290 	}
291 	if (lom_init_desc(sc)) {
292 		printf(": can't read sensor names\n");
293 		return;
294 	}
295 
296 	if (sensor_task_register(sc, lom_refresh, 5) == NULL) {
297 		printf(": unable to register update task\n");
298 		return;
299 	}
300 
301 	sensordev_install(&sc->sc_sensordev);
302 
303 	/*
304 	 * We configure the watchdog to turn on the fault LED when the
305 	 * watchdog timer expires.  We run our own timeout to pat it
306 	 * such that this won't happen unless the kernel hangs.  When
307 	 * the watchdog is explicitly configured using sysctl(8), we
308 	 * reconfigure it to reset the machine and let the standard
309 	 * watchdog(4) machinery take over.
310 	 */
311 	lom_write(sc, LOM_IDX_WDOG_TIME, LOM_WDOG_TIME_MAX);
312 	lom_read(sc, LOM_IDX_WDOG_CTL, &sc->sc_wdog_ctl);
313 	sc->sc_wdog_ctl &= ~LOM_WDOG_RESET;
314 	sc->sc_wdog_ctl |= LOM_WDOG_ENABLE;
315 	lom_write(sc, LOM_IDX_WDOG_CTL, sc->sc_wdog_ctl);
316 	timeout_set(&sc->sc_wdog_to, lom_wdog_pat, sc);
317 	timeout_add_sec(&sc->sc_wdog_to, LOM_WDOG_TIME_MAX / 2);
318 
319 	wdog_register(sc, lom_wdog_cb);
320 
321 	printf(": rev %d.%d\n", fw_rev >> 4, fw_rev & 0x0f);
322 }
323 
324 int
325 lom_read(struct lom_softc *sc, uint8_t reg, uint8_t *val)
326 {
327 	if (sc->sc_type < LOM_LOMLITE2)
328 		return lom1_read(sc, reg, val);
329 	else
330 		return lom2_read(sc, reg, val);
331 }
332 
333 int
334 lom_write(struct lom_softc *sc, uint8_t reg, uint8_t val)
335 {
336 	if (sc->sc_type < LOM_LOMLITE2)
337 		return lom1_write(sc, reg, val);
338 	else
339 		return lom2_write(sc, reg, val);
340 }
341 
342 int
343 lom1_read(struct lom_softc *sc, uint8_t reg, uint8_t *val)
344 {
345 	int error;
346 
347 	KASSERT(sc->sc_state == LOM_STATE_IDLE);
348 
349 	if (cold)
350 		return lom1_read_polled(sc, reg, val);
351 
352 	sc->sc_cmd = reg;
353 	sc->sc_state = LOM_STATE_READ_CMD;
354 	timeout_add_msec(&sc->sc_state_to, 5);
355 
356 	error = tsleep(&sc->sc_state, PZERO, "lomrd", hz / 10);
357 	KASSERT(sc->sc_state == LOM_STATE_READ_DONE);
358 
359 	*val = sc->sc_data;
360 	sc->sc_state = LOM_STATE_IDLE;
361 
362 	return (error);
363 }
364 
365 int
366 lom1_read_polled(struct lom_softc *sc, uint8_t reg, uint8_t *val)
367 {
368 	uint8_t str;
369 	int i;
370 
371 	delay(15000);
372 
373 	/* Wait for input buffer to become available. */
374 	for (i = 1000; i > 0; i--) {
375 		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS);
376 		delay(10);
377 		if ((str & LOM1_STATUS_BUSY) == 0)
378 			break;
379 	}
380 	if (i == 0)
381 		return (ETIMEDOUT);
382 
383 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_CMD, reg);
384 
385 	delay(15000);
386 
387 	/* Wait until the microcontroller fills output buffer. */
388 	for (i = 1000; i > 0; i--) {
389 		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS);
390 		delay(10);
391 		if ((str & LOM1_STATUS_BUSY) == 0)
392 			break;
393 	}
394 	if (i == 0)
395 		return (ETIMEDOUT);
396 
397 	*val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA);
398 	return (0);
399 }
400 
401 int
402 lom1_write(struct lom_softc *sc, uint8_t reg, uint8_t val)
403 {
404 	uint8_t str;
405 	int i;
406 
407 	delay(15000);
408 
409 	/* Wait for input buffer to become available. */
410 	for (i = 1000; i > 0; i--) {
411 		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS);
412 		delay(10);
413 		if ((str & LOM1_STATUS_BUSY) == 0)
414 			break;
415 	}
416 	if (i == 0)
417 		return (ETIMEDOUT);
418 
419 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_CMD, reg | 0x80);
420 
421 	delay(15000);
422 
423 	/* Wait until the microcontroller fills output buffer. */
424 	for (i = 1000; i > 0; i--) {
425 		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS);
426 		delay(10);
427 		if ((str & LOM1_STATUS_BUSY) == 0)
428 			break;
429 	}
430 	if (i == 0)
431 		return (ETIMEDOUT);
432 
433 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA, val);
434 
435 	return (0);
436 }
437 
438 void
439 lom1_state(void *arg)
440 {
441 	struct lom_softc *sc = arg;
442 	uint8_t str;
443 
444 	str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS);
445 	if (str & LOM1_STATUS_BUSY) {
446 		timeout_add_msec(&sc->sc_state_to, 5);
447 		return;
448 	}
449 
450 	if (sc->sc_state == LOM_STATE_READ_CMD) {
451 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_CMD, sc->sc_cmd);
452 		sc->sc_state = LOM_STATE_READ_DATA;
453 		timeout_add_msec(&sc->sc_state_to, 5);
454 		return;
455 	}
456 
457 	KASSERT(sc->sc_state == LOM_STATE_READ_DATA);
458 	sc->sc_data = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA);
459 	sc->sc_state = LOM_STATE_READ_DONE;
460 	wakeup(&sc->sc_state);
461 }
462 
463 int
464 lom2_read(struct lom_softc *sc, uint8_t reg, uint8_t *val)
465 {
466 	uint8_t str;
467 	int i;
468 
469 	/* Wait for input buffer to become available. */
470 	for (i = 1000; i > 0; i--) {
471 		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
472 		delay(10);
473 		if ((str & LOM2_STATUS_IBF) == 0)
474 			break;
475 	}
476 	if (i == 0)
477 		return (ETIMEDOUT);
478 
479 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM2_CMD, reg);
480 
481 	/* Wait until the microcontroller fills output buffer. */
482 	for (i = 1000; i > 0; i--) {
483 		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
484 		delay(10);
485 		if (str & LOM2_STATUS_OBF)
486 			break;
487 	}
488 	if (i == 0)
489 		return (ETIMEDOUT);
490 
491 	*val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA);
492 	return (0);
493 }
494 
495 int
496 lom2_write(struct lom_softc *sc, uint8_t reg, uint8_t val)
497 {
498 	uint8_t str;
499 	int i;
500 
501 	/* Wait for input buffer to become available. */
502 	for (i = 1000; i > 0; i--) {
503 		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
504 		delay(10);
505 		if ((str & LOM2_STATUS_IBF) == 0)
506 			break;
507 	}
508 	if (i == 0)
509 		return (ETIMEDOUT);
510 
511 	if (sc->sc_space == LOM_IDX_CMD_GENERIC && reg != LOM_IDX_CMD)
512 		reg |= 0x80;
513 
514 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM2_CMD, reg);
515 
516 	/* Wait until the microcontroller fills output buffer. */
517 	for (i = 1000; i > 0; i--) {
518 		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
519 		delay(10);
520 		if (str & LOM2_STATUS_OBF)
521 			break;
522 	}
523 	if (i == 0)
524 		return (ETIMEDOUT);
525 
526 	bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA);
527 
528 	/* Wait for input buffer to become available. */
529 	for (i = 1000; i > 0; i--) {
530 		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
531 		delay(10);
532 		if ((str & LOM2_STATUS_IBF) == 0)
533 			break;
534 	}
535 	if (i == 0)
536 		return (ETIMEDOUT);
537 
538 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA, val);
539 
540 	/* Wait until the microcontroller fills output buffer. */
541 	for (i = 1000; i > 0; i--) {
542 		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
543 		delay(10);
544 		if (str & LOM2_STATUS_OBF)
545 			break;
546 	}
547 	if (i == 0)
548 		return (ETIMEDOUT);
549 
550 	bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA);
551 
552 	/* If we switched spaces, remember the one we're in now. */
553 	if (reg == LOM_IDX_CMD)
554 		sc->sc_space = val;
555 
556 	return (0);
557 }
558 
559 int
560 lom_init_desc(struct lom_softc *sc)
561 {
562 	uint8_t val;
563 	int i, j, k;
564 	int error;
565 
566 	/* LOMlite doesn't provide sensor descriptions. */
567 	if (sc->sc_type < LOM_LOMLITE2)
568 		return (0);
569 
570 	/*
571 	 * Read temperature sensor names.
572 	 */
573 	error = lom_write(sc, LOM_IDX_CMD, LOM_IDX_CMD_TEMP);
574 	if (error)
575 		return (error);
576 
577 	i = 0;
578 	j = 0;
579 	k = LOM_IDX4_TEMP_NAME_START;
580 	while (k <= LOM_IDX4_TEMP_NAME_END) {
581 		error = lom_read(sc, k++, &val);
582 		if (error)
583 			goto fail;
584 
585 		if (val == 0xff)
586 			break;
587 
588 		if (j < sizeof (sc->sc_temp[i].desc) - 1)
589 			sc->sc_temp[i].desc[j++] = val;
590 
591 		if (val == '\0') {
592 			i++;
593 			j = 0;
594 			if (i < sc->sc_num_temp)
595 				continue;
596 
597 			break;
598 		}
599 	}
600 
601 	/*
602 	 * Read fan names.
603 	 */
604 	error = lom_write(sc, LOM_IDX_CMD, LOM_IDX_CMD_FAN);
605 	if (error)
606 		return (error);
607 
608 	i = 0;
609 	j = 0;
610 	k = LOM_IDX5_FAN_NAME_START;
611 	while (k <= LOM_IDX5_FAN_NAME_END) {
612 		error = lom_read(sc, k++, &val);
613 		if (error)
614 			goto fail;
615 
616 		if (val == 0xff)
617 			break;
618 
619 		if (j < sizeof (sc->sc_fan[i].desc) - 1)
620 			sc->sc_fan[i].desc[j++] = val;
621 
622 		if (val == '\0') {
623 			i++;
624 			j = 0;
625 			if (i < sc->sc_num_fan)
626 				continue;
627 
628 			break;
629 		}
630 	}
631 
632 fail:
633 	lom_write(sc, LOM_IDX_CMD, LOM_IDX_CMD_GENERIC);
634 	return (error);
635 }
636 
637 void
638 lom_refresh(void *arg)
639 {
640 	struct lom_softc *sc = arg;
641 	uint8_t val;
642 	int i;
643 
644 	for (i = 0; i < sc->sc_num_fan; i++) {
645 		if (lom_read(sc, LOM_IDX_FAN1 + i, &val)) {
646 			sc->sc_fan[i].flags |= SENSOR_FINVALID;
647 			continue;
648 		}
649 
650 		sc->sc_fan[i].value = (60 * sc->sc_fan_cal[i] * val) / 100;
651 		sc->sc_fan[i].flags &= ~SENSOR_FINVALID;
652 	}
653 
654 	for (i = 0; i < sc->sc_num_psu; i++) {
655 		if (lom_read(sc, LOM_IDX_PSU1 + i, &val) ||
656 		    !ISSET(val, LOM_PSU_PRESENT)) {
657 			sc->sc_psu[i].flags |= SENSOR_FINVALID;
658 			continue;
659 		}
660 
661 		if (val & LOM_PSU_STANDBY) {
662 			sc->sc_psu[i].value = 0;
663 			sc->sc_psu[i].status = SENSOR_S_UNSPEC;
664 		} else {
665 			sc->sc_psu[i].value = 1;
666 			if (ISSET(val, LOM_PSU_INPUTA) &&
667 			    ISSET(val, LOM_PSU_INPUTB) &&
668 			    ISSET(val, LOM_PSU_OUTPUT))
669 				sc->sc_psu[i].status = SENSOR_S_OK;
670 			else
671 				sc->sc_psu[i].status = SENSOR_S_CRIT;
672 		}
673 		sc->sc_psu[i].flags &= ~SENSOR_FINVALID;
674 	}
675 
676 	for (i = 0; i < sc->sc_num_temp; i++) {
677 		if (lom_read(sc, LOM_IDX_TEMP1 + i, &val)) {
678 			sc->sc_temp[i].flags |= SENSOR_FINVALID;
679 			continue;
680 		}
681 
682 		sc->sc_temp[i].value = val * 1000000 + 273150000;
683 		sc->sc_temp[i].flags &= ~SENSOR_FINVALID;
684 	}
685 
686 	/*
687 	 * If our hostname is set and differs from what's stored in
688 	 * the LOM, write the new hostname back to the LOM.  Note that
689 	 * we include the terminating NUL when writing the hostname
690 	 * back to the LOM, otherwise the LOM will print any trailing
691 	 * garbage.
692 	 */
693 	if (hostnamelen > 0 &&
694 	    strncmp(sc->sc_hostname, hostname, sizeof(hostname)) != 0) {
695 		if (sc->sc_type < LOM_LOMLITE2)
696 			lom1_write_hostname(sc);
697 		else
698 			lom2_write_hostname(sc);
699 		strlcpy(sc->sc_hostname, hostname, sizeof(hostname));
700 	}
701 }
702 
703 void
704 lom1_write_hostname(struct lom_softc *sc)
705 {
706 	char name[LOM1_IDX_HOSTNAME12 - LOM1_IDX_HOSTNAME1 + 1];
707 	char *p;
708 	int i;
709 
710 	/*
711 	 * LOMlite generally doesn't have enough space to store the
712 	 * fully qualified hostname.  If the hostname is too long,
713 	 * strip off the domain name.
714 	 */
715 	strlcpy(name, hostname, sizeof(name));
716 	if (hostnamelen > sizeof(name)) {
717 		p = strchr(name, '.');
718 		if (p)
719 			*p = '\0';
720 	}
721 
722 	for (i = 0; i < strlen(name) + 1; i++)
723 		lom_write(sc, LOM1_IDX_HOSTNAME1 + i, name[i]);
724 }
725 
726 void
727 lom2_write_hostname(struct lom_softc *sc)
728 {
729 	int i;
730 
731 	lom_write(sc, LOM2_IDX_HOSTNAMELEN, hostnamelen + 1);
732 	for (i = 0; i < hostnamelen + 1; i++)
733 		lom_write(sc, LOM2_IDX_HOSTNAME, hostname[i]);
734 }
735 
736 void
737 lom_wdog_pat(void *arg)
738 {
739 	struct lom_softc *sc;
740 
741 	/* Pat the dog. */
742 	lom_write(sc, LOM_IDX_WDOG_CTL, sc->sc_wdog_ctl);
743 
744 	timeout_add_sec(&sc->sc_wdog_to, LOM_WDOG_TIME_MAX / 2);
745 }
746 
747 int
748 lom_wdog_cb(void *arg, int period)
749 {
750 	struct lom_softc *sc = arg;
751 
752 	if (period > LOM_WDOG_TIME_MAX)
753 		period = LOM_WDOG_TIME_MAX;
754 	else if (period < 0)
755 		period = 0;
756 
757 	if (period == 0) {
758 		if (sc->sc_wdog_period != 0) {
759 			/* Stop watchdog from resetting the machine. */
760 			sc->sc_wdog_ctl &= ~LOM_WDOG_RESET;
761 			lom_write(sc, LOM_IDX_WDOG_CTL, sc->sc_wdog_ctl);
762 
763 			lom_write(sc, LOM_IDX_WDOG_TIME, LOM_WDOG_TIME_MAX);
764 			timeout_add_sec(&sc->sc_wdog_to, LOM_WDOG_TIME_MAX / 2);
765 		}
766 	} else {
767 		if (sc->sc_wdog_period != period) {
768 			/* Set new timeout. */
769 			lom_write(sc, LOM_IDX_WDOG_TIME, period);
770 		}
771 		if (sc->sc_wdog_period == 0) {
772 			/* Make watchdog reset the machine. */
773 			sc->sc_wdog_ctl |= LOM_WDOG_RESET;
774 			lom_write(sc, LOM_IDX_WDOG_CTL, sc->sc_wdog_ctl);
775 
776 			timeout_del(&sc->sc_wdog_to);
777 		} else {
778 			/* Pat the dog. */
779 			lom_write(sc, LOM_IDX_WDOG_CTL, sc->sc_wdog_ctl);
780 		}
781 	}
782 	sc->sc_wdog_period = period;
783 
784 	return (period);
785 }
786