xref: /netbsd-src/sys/arch/sparc64/dev/lom.c (revision d1579b2d70337e1b895f03478838f880e450f6da)
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 
144 struct lom_cmd {
145 	uint8_t			lc_cmd;
146 	uint8_t			lc_data;
147 
148 	TAILQ_ENTRY(lom_cmd)	lc_next;
149 };
150 
151 struct lom_softc {
152 	device_t		sc_dev;
153 	bus_space_tag_t		sc_iot;
154 	bus_space_handle_t	sc_ioh;
155 
156 	int			sc_type;
157 #define LOM_LOMLITE		0
158 #define LOM_LOMLITE2		2
159 	int			sc_space;
160 
161 	struct sysmon_envsys	*sc_sme;
162 	envsys_data_t		sc_alarm[LOM_MAX_ALARM];
163 	envsys_data_t		sc_fan[LOM_MAX_FAN];
164 	envsys_data_t		sc_psu[LOM_MAX_PSU];
165 	envsys_data_t		sc_temp[LOM_MAX_TEMP];
166 
167 	int			sc_num_alarm;
168 	int			sc_num_fan;
169 	int			sc_num_psu;
170 	int			sc_num_temp;
171 
172 	int32_t			sc_sysctl_num[LOM_MAX_ALARM];
173 
174 	struct timeval		sc_alarm_lastread;
175 	uint8_t			sc_alarm_lastval;
176 	struct timeval		sc_fan_lastread[LOM_MAX_FAN];
177 	struct timeval		sc_psu_lastread[LOM_MAX_PSU];
178 	struct timeval		sc_temp_lastread[LOM_MAX_TEMP];
179 
180 	uint8_t			sc_fan_cal[LOM_MAX_FAN];
181 	uint8_t			sc_fan_low[LOM_MAX_FAN];
182 
183 	char			sc_hostname[MAXHOSTNAMELEN];
184 
185 	struct sysmon_wdog	sc_smw;
186 	int			sc_wdog_period;
187 	uint8_t			sc_wdog_ctl;
188 	struct lom_cmd		sc_wdog_pat;
189 
190 	TAILQ_HEAD(, lom_cmd)	sc_queue;
191 	kmutex_t		sc_queue_mtx;
192 	struct callout		sc_state_to;
193 	int			sc_state;
194 #define LOM_STATE_IDLE		0
195 #define LOM_STATE_CMD		1
196 #define LOM_STATE_DATA		2
197 	int			sc_retry;
198 };
199 
200 static int	lom_match(device_t, cfdata_t, void *);
201 static void	lom_attach(device_t, device_t, void *);
202 
203 CFATTACH_DECL_NEW(lom, sizeof(struct lom_softc),
204     lom_match, lom_attach, NULL, NULL);
205 
206 static int	lom_read(struct lom_softc *, uint8_t, uint8_t *);
207 static int	lom_write(struct lom_softc *, uint8_t, uint8_t);
208 static void	lom_queue_cmd(struct lom_softc *, struct lom_cmd *);
209 static void	lom_dequeue_cmd(struct lom_softc *, struct lom_cmd *);
210 static int	lom1_read(struct lom_softc *, uint8_t, uint8_t *);
211 static int	lom1_write(struct lom_softc *, uint8_t, uint8_t);
212 static int	lom1_read_polled(struct lom_softc *, uint8_t, uint8_t *);
213 static int	lom1_write_polled(struct lom_softc *, uint8_t, uint8_t);
214 static void	lom1_queue_cmd(struct lom_softc *, struct lom_cmd *);
215 static void	lom1_process_queue(void *);
216 static void	lom1_process_queue_locked(struct lom_softc *);
217 static int	lom2_read(struct lom_softc *, uint8_t, uint8_t *);
218 static int	lom2_write(struct lom_softc *, uint8_t, uint8_t);
219 static int	lom2_read_polled(struct lom_softc *, uint8_t, uint8_t *);
220 static int	lom2_write_polled(struct lom_softc *, uint8_t, uint8_t);
221 static void	lom2_queue_cmd(struct lom_softc *, struct lom_cmd *);
222 static int	lom2_intr(void *);
223 
224 static int	lom_init_desc(struct lom_softc *);
225 static void	lom_refresh(struct sysmon_envsys *, envsys_data_t *);
226 static void	lom_refresh_alarm(struct lom_softc *, envsys_data_t *, uint32_t);
227 static void	lom_refresh_fan(struct lom_softc *, envsys_data_t *, uint32_t);
228 static void	lom_refresh_psu(struct lom_softc *, envsys_data_t *, uint32_t);
229 static void	lom_refresh_temp(struct lom_softc *, envsys_data_t *, uint32_t);
230 static void	lom1_write_hostname(struct lom_softc *);
231 static void	lom2_write_hostname(struct lom_softc *);
232 
233 static int	lom_wdog_tickle(struct sysmon_wdog *);
234 static int	lom_wdog_setmode(struct sysmon_wdog *);
235 
236 static bool	lom_shutdown(device_t, int);
237 
238 SYSCTL_SETUP_PROTO(sysctl_lom_setup);
239 static int	lom_sysctl_alarm(SYSCTLFN_PROTO);
240 
241 static const char *nodename[LOM_MAX_ALARM] =
242     { "fault_led", "alarm1", "alarm2", "alarm3" };
243 #ifdef SYSCTL_INCLUDE_DESCR
244 static const char *nodedesc[LOM_MAX_ALARM] =
245     { "Fault LED status", "Alarm1 status", "Alarm2 status ", "Alarm3 status" };
246 #endif
247 static const struct timeval refresh_interval = { 1, 0 };
248 
249 static int
lom_match(device_t parent,cfdata_t match,void * aux)250 lom_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 
261 static void
lom_attach(device_t parent,device_t self,void * aux)262 lom_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 
451 static int
lom_read(struct lom_softc * sc,uint8_t reg,uint8_t * val)452 lom_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 
460 static int
lom_write(struct lom_softc * sc,uint8_t reg,uint8_t val)461 lom_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 
469 static void
lom_queue_cmd(struct lom_softc * sc,struct lom_cmd * lc)470 lom_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 
478 static void
lom_dequeue_cmd(struct lom_softc * sc,struct lom_cmd * lc)479 lom_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 
493 static int
lom1_read(struct lom_softc * sc,uint8_t reg,uint8_t * val)494 lom1_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 
515 static int
lom1_write(struct lom_softc * sc,uint8_t reg,uint8_t val)516 lom1_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 
535 static int
lom1_read_polled(struct lom_softc * sc,uint8_t reg,uint8_t * val)536 lom1_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 
567 static int
lom1_write_polled(struct lom_softc * sc,uint8_t reg,uint8_t val)568 lom1_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 
601 static void
lom1_queue_cmd(struct lom_softc * sc,struct lom_cmd * lc)602 lom1_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 
621 static void
lom1_process_queue(void * arg)622 lom1_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 
631 static void
lom1_process_queue_locked(struct lom_softc * sc)632 lom1_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 
689 static int
lom2_read(struct lom_softc * sc,uint8_t reg,uint8_t * val)690 lom2_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 
711 static int
lom2_read_polled(struct lom_softc * sc,uint8_t reg,uint8_t * val)712 lom2_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 
743 static int
lom2_write(struct lom_softc * sc,uint8_t reg,uint8_t val)744 lom2_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 
763 static int
lom2_write_polled(struct lom_softc * sc,uint8_t reg,uint8_t val)764 lom2_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 
827 static void
lom2_queue_cmd(struct lom_softc * sc,struct lom_cmd * lc)828 lom2_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 
853 static int
lom2_intr(void * arg)854 lom2_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 
905 static int
lom_init_desc(struct lom_softc * sc)906 lom_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 
978 fail:
979 	lom_write(sc, LOM_IDX_CMD, LOM_IDX_CMD_GENERIC);
980 	return (error);
981 }
982 
983 static void
lom_refresh(struct sysmon_envsys * sme,envsys_data_t * edata)984 lom_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 
1030 static void
lom_refresh_alarm(struct lom_softc * sc,envsys_data_t * edata,uint32_t i)1031 lom_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 
1065 static void
lom_refresh_fan(struct lom_softc * sc,envsys_data_t * edata,uint32_t i)1066 lom_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 
1088 static void
lom_refresh_psu(struct lom_softc * sc,envsys_data_t * edata,uint32_t i)1089 lom_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 
1119 static void
lom_refresh_temp(struct lom_softc * sc,envsys_data_t * edata,uint32_t i)1120 lom_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 
1139 static void
lom1_write_hostname(struct lom_softc * sc)1140 lom1_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 
1163 static void
lom2_write_hostname(struct lom_softc * sc)1164 lom2_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 
1173 static int
lom_wdog_tickle(struct sysmon_wdog * smw)1174 lom_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 
1186 static int
lom_wdog_setmode(struct sysmon_wdog * smw)1187 lom_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 
1214 static bool
lom_shutdown(device_t dev,int how)1215 lom_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 
1224 static int
lom_sysctl_alarm(SYSCTLFN_ARGS)1225 lom_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