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