lom.c revision 1.1 1 1.1 nakayama /* $NetBSD: lom.c,v 1.1 2009/10/02 15:09:16 nakayama Exp $ */
2 1.1 nakayama /* $OpenBSD: lom.c,v 1.15 2009/09/27 18:08:42 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.1 nakayama __KERNEL_RCSID(0, "$NetBSD: lom.c,v 1.1 2009/10/02 15:09:16 nakayama 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.1 nakayama
30 1.1 nakayama #include <machine/autoconf.h>
31 1.1 nakayama
32 1.1 nakayama #include <dev/ebus/ebusreg.h>
33 1.1 nakayama #include <dev/ebus/ebusvar.h>
34 1.1 nakayama #include <dev/sysmon/sysmonvar.h>
35 1.1 nakayama
36 1.1 nakayama /*
37 1.1 nakayama * LOMlite is a so far unidentified microcontroller.
38 1.1 nakayama */
39 1.1 nakayama #define LOM1_STATUS 0x00 /* R */
40 1.1 nakayama #define LOM1_STATUS_BUSY 0x80
41 1.1 nakayama #define LOM1_CMD 0x00 /* W */
42 1.1 nakayama #define LOM1_DATA 0x01 /* R/W */
43 1.1 nakayama
44 1.1 nakayama /*
45 1.1 nakayama * LOMlite2 is implemented as a H8/3437 microcontroller which has its
46 1.1 nakayama * on-chip host interface hooked up to EBus.
47 1.1 nakayama */
48 1.1 nakayama #define LOM2_DATA 0x00 /* R/W */
49 1.1 nakayama #define LOM2_CMD 0x01 /* W */
50 1.1 nakayama #define LOM2_STATUS 0x01 /* R */
51 1.1 nakayama #define LOM2_STATUS_OBF 0x01 /* Output Buffer Full */
52 1.1 nakayama #define LOM2_STATUS_IBF 0x02 /* Input Buffer Full */
53 1.1 nakayama
54 1.1 nakayama #define LOM_IDX_CMD 0x00
55 1.1 nakayama #define LOM_IDX_CMD_GENERIC 0x00
56 1.1 nakayama #define LOM_IDX_CMD_TEMP 0x04
57 1.1 nakayama #define LOM_IDX_CMD_FAN 0x05
58 1.1 nakayama
59 1.1 nakayama #define LOM_IDX_FW_REV 0x01 /* Firmware revision */
60 1.1 nakayama
61 1.1 nakayama #define LOM_IDX_FAN1 0x04 /* Fan speed */
62 1.1 nakayama #define LOM_IDX_FAN2 0x05
63 1.1 nakayama #define LOM_IDX_FAN3 0x06
64 1.1 nakayama #define LOM_IDX_FAN4 0x07
65 1.1 nakayama #define LOM_IDX_PSU1 0x08 /* PSU status */
66 1.1 nakayama #define LOM_IDX_PSU2 0x09
67 1.1 nakayama #define LOM_IDX_PSU3 0x0a
68 1.1 nakayama #define LOM_PSU_INPUTA 0x01
69 1.1 nakayama #define LOM_PSU_INPUTB 0x02
70 1.1 nakayama #define LOM_PSU_OUTPUT 0x04
71 1.1 nakayama #define LOM_PSU_PRESENT 0x08
72 1.1 nakayama #define LOM_PSU_STANDBY 0x10
73 1.1 nakayama
74 1.1 nakayama #define LOM_IDX_TEMP1 0x18 /* Temperature */
75 1.1 nakayama #define LOM_IDX_TEMP2 0x19
76 1.1 nakayama #define LOM_IDX_TEMP3 0x1a
77 1.1 nakayama #define LOM_IDX_TEMP4 0x1b
78 1.1 nakayama #define LOM_IDX_TEMP5 0x1c
79 1.1 nakayama #define LOM_IDX_TEMP6 0x1d
80 1.1 nakayama #define LOM_IDX_TEMP7 0x1e
81 1.1 nakayama #define LOM_IDX_TEMP8 0x1f
82 1.1 nakayama
83 1.1 nakayama #define LOM_IDX_LED1 0x25
84 1.1 nakayama
85 1.1 nakayama #define LOM_IDX_ALARM 0x30
86 1.1 nakayama #define LOM_IDX_WDOG_CTL 0x31
87 1.1 nakayama #define LOM_WDOG_ENABLE 0x01
88 1.1 nakayama #define LOM_WDOG_RESET 0x02
89 1.1 nakayama #define LOM_WDOG_AL3_WDOG 0x04
90 1.1 nakayama #define LOM_WDOG_AL3_FANPSU 0x08
91 1.1 nakayama #define LOM_IDX_WDOG_TIME 0x32
92 1.1 nakayama #define LOM_WDOG_TIME_MAX 126
93 1.1 nakayama
94 1.1 nakayama #define LOM1_IDX_HOSTNAME1 0x33
95 1.1 nakayama #define LOM1_IDX_HOSTNAME2 0x34
96 1.1 nakayama #define LOM1_IDX_HOSTNAME3 0x35
97 1.1 nakayama #define LOM1_IDX_HOSTNAME4 0x36
98 1.1 nakayama #define LOM1_IDX_HOSTNAME5 0x37
99 1.1 nakayama #define LOM1_IDX_HOSTNAME6 0x38
100 1.1 nakayama #define LOM1_IDX_HOSTNAME7 0x39
101 1.1 nakayama #define LOM1_IDX_HOSTNAME8 0x3a
102 1.1 nakayama #define LOM1_IDX_HOSTNAME9 0x3b
103 1.1 nakayama #define LOM1_IDX_HOSTNAME10 0x3c
104 1.1 nakayama #define LOM1_IDX_HOSTNAME11 0x3d
105 1.1 nakayama #define LOM1_IDX_HOSTNAME12 0x3e
106 1.1 nakayama
107 1.1 nakayama #define LOM2_IDX_HOSTNAMELEN 0x38
108 1.1 nakayama #define LOM2_IDX_HOSTNAME 0x39
109 1.1 nakayama
110 1.1 nakayama #define LOM_IDX_CONFIG 0x5d
111 1.1 nakayama #define LOM_IDX_FAN1_CAL 0x5e
112 1.1 nakayama #define LOM_IDX_FAN2_CAL 0x5f
113 1.1 nakayama #define LOM_IDX_FAN3_CAL 0x60
114 1.1 nakayama #define LOM_IDX_FAN4_CAL 0x61
115 1.1 nakayama #define LOM_IDX_FAN1_LOW 0x62
116 1.1 nakayama #define LOM_IDX_FAN2_LOW 0x63
117 1.1 nakayama #define LOM_IDX_FAN3_LOW 0x64
118 1.1 nakayama #define LOM_IDX_FAN4_LOW 0x65
119 1.1 nakayama
120 1.1 nakayama #define LOM_IDX_CONFIG2 0x66
121 1.1 nakayama #define LOM_IDX_CONFIG3 0x67
122 1.1 nakayama
123 1.1 nakayama #define LOM_IDX_PROBE55 0x7e /* Always returns 0x55 */
124 1.1 nakayama #define LOM_IDX_PROBEAA 0x7f /* Always returns 0xaa */
125 1.1 nakayama
126 1.1 nakayama #define LOM_IDX_WRITE 0x80
127 1.1 nakayama
128 1.1 nakayama #define LOM_IDX4_TEMP_NAME_START 0x40
129 1.1 nakayama #define LOM_IDX4_TEMP_NAME_END 0xff
130 1.1 nakayama
131 1.1 nakayama #define LOM_IDX5_FAN_NAME_START 0x40
132 1.1 nakayama #define LOM_IDX5_FAN_NAME_END 0xff
133 1.1 nakayama
134 1.1 nakayama #define LOM_MAX_FAN 4
135 1.1 nakayama #define LOM_MAX_PSU 3
136 1.1 nakayama #define LOM_MAX_TEMP 8
137 1.1 nakayama
138 1.1 nakayama struct lom_cmd {
139 1.1 nakayama uint8_t lc_cmd;
140 1.1 nakayama uint8_t lc_data;
141 1.1 nakayama
142 1.1 nakayama TAILQ_ENTRY(lom_cmd) lc_next;
143 1.1 nakayama };
144 1.1 nakayama
145 1.1 nakayama struct lom_softc {
146 1.1 nakayama device_t sc_dev;
147 1.1 nakayama bus_space_tag_t sc_iot;
148 1.1 nakayama bus_space_handle_t sc_ioh;
149 1.1 nakayama
150 1.1 nakayama int sc_type;
151 1.1 nakayama #define LOM_LOMLITE 0
152 1.1 nakayama #define LOM_LOMLITE2 2
153 1.1 nakayama int sc_space;
154 1.1 nakayama
155 1.1 nakayama struct sysmon_envsys *sc_sme;
156 1.1 nakayama envsys_data_t sc_fan[LOM_MAX_FAN];
157 1.1 nakayama envsys_data_t sc_psu[LOM_MAX_PSU];
158 1.1 nakayama envsys_data_t sc_temp[LOM_MAX_TEMP];
159 1.1 nakayama
160 1.1 nakayama int sc_num_fan;
161 1.1 nakayama int sc_num_psu;
162 1.1 nakayama int sc_num_temp;
163 1.1 nakayama
164 1.1 nakayama uint8_t sc_fan_cal[LOM_MAX_FAN];
165 1.1 nakayama uint8_t sc_fan_low[LOM_MAX_FAN];
166 1.1 nakayama
167 1.1 nakayama char sc_hostname[MAXHOSTNAMELEN];
168 1.1 nakayama
169 1.1 nakayama struct sysmon_wdog sc_smw;
170 1.1 nakayama int sc_wdog_period;
171 1.1 nakayama uint8_t sc_wdog_ctl;
172 1.1 nakayama struct lom_cmd sc_wdog_pat;
173 1.1 nakayama
174 1.1 nakayama TAILQ_HEAD(, lom_cmd) sc_queue;
175 1.1 nakayama kmutex_t sc_queue_mtx;
176 1.1 nakayama struct callout sc_state_to;
177 1.1 nakayama int sc_state;
178 1.1 nakayama #define LOM_STATE_IDLE 0
179 1.1 nakayama #define LOM_STATE_CMD 1
180 1.1 nakayama #define LOM_STATE_DATA 2
181 1.1 nakayama int sc_retry;
182 1.1 nakayama };
183 1.1 nakayama
184 1.1 nakayama static int lom_match(device_t, cfdata_t, void *);
185 1.1 nakayama static void lom_attach(device_t, device_t, void *);
186 1.1 nakayama
187 1.1 nakayama CFATTACH_DECL_NEW(lom, sizeof(struct lom_softc),
188 1.1 nakayama lom_match, lom_attach, NULL, NULL);
189 1.1 nakayama
190 1.1 nakayama static int lom_read(struct lom_softc *, uint8_t, uint8_t *);
191 1.1 nakayama static int lom_write(struct lom_softc *, uint8_t, uint8_t);
192 1.1 nakayama static void lom_queue_cmd(struct lom_softc *, struct lom_cmd *);
193 1.1 nakayama static int lom1_read(struct lom_softc *, uint8_t, uint8_t *);
194 1.1 nakayama static int lom1_write(struct lom_softc *, uint8_t, uint8_t);
195 1.1 nakayama static int lom1_read_polled(struct lom_softc *, uint8_t, uint8_t *);
196 1.1 nakayama static int lom1_write_polled(struct lom_softc *, uint8_t, uint8_t);
197 1.1 nakayama static void lom1_queue_cmd(struct lom_softc *, struct lom_cmd *);
198 1.1 nakayama static void lom1_dequeue_cmd(struct lom_softc *, struct lom_cmd *);
199 1.1 nakayama static void lom1_process_queue(void *);
200 1.1 nakayama static void lom1_process_queue_locked(struct lom_softc *);
201 1.1 nakayama static int lom2_read(struct lom_softc *, uint8_t, uint8_t *);
202 1.1 nakayama static int lom2_write(struct lom_softc *, uint8_t, uint8_t);
203 1.1 nakayama static void lom2_queue_cmd(struct lom_softc *, struct lom_cmd *);
204 1.1 nakayama
205 1.1 nakayama static int lom_init_desc(struct lom_softc *);
206 1.1 nakayama static void lom_refresh(struct sysmon_envsys *, envsys_data_t *);
207 1.1 nakayama static void lom1_write_hostname(struct lom_softc *);
208 1.1 nakayama static void lom2_write_hostname(struct lom_softc *);
209 1.1 nakayama
210 1.1 nakayama static int lom_wdog_tickle(struct sysmon_wdog *);
211 1.1 nakayama static int lom_wdog_setmode(struct sysmon_wdog *);
212 1.1 nakayama
213 1.1 nakayama static int
214 1.1 nakayama lom_match(device_t parent, cfdata_t match, void *aux)
215 1.1 nakayama {
216 1.1 nakayama struct ebus_attach_args *ea = aux;
217 1.1 nakayama
218 1.1 nakayama if (strcmp(ea->ea_name, "SUNW,lom") == 0 ||
219 1.1 nakayama strcmp(ea->ea_name, "SUNW,lomh") == 0)
220 1.1 nakayama return (1);
221 1.1 nakayama
222 1.1 nakayama return (0);
223 1.1 nakayama }
224 1.1 nakayama
225 1.1 nakayama static void
226 1.1 nakayama lom_attach(device_t parent, device_t self, void *aux)
227 1.1 nakayama {
228 1.1 nakayama struct lom_softc *sc = device_private(self);
229 1.1 nakayama struct ebus_attach_args *ea = aux;
230 1.1 nakayama uint8_t reg, fw_rev, config, config2, config3;
231 1.1 nakayama uint8_t cal, low;
232 1.1 nakayama int i;
233 1.1 nakayama
234 1.1 nakayama if (strcmp(ea->ea_name, "SUNW,lomh") == 0)
235 1.1 nakayama sc->sc_type = LOM_LOMLITE2;
236 1.1 nakayama
237 1.1 nakayama sc->sc_dev = self;
238 1.1 nakayama sc->sc_iot = ea->ea_bustag;
239 1.1 nakayama if (bus_space_map(sc->sc_iot, EBUS_ADDR_FROM_REG(&ea->ea_reg[0]),
240 1.1 nakayama ea->ea_reg[0].size, 0, &sc->sc_ioh) != 0) {
241 1.1 nakayama aprint_error(": can't map register space\n");
242 1.1 nakayama return;
243 1.1 nakayama }
244 1.1 nakayama
245 1.1 nakayama if (sc->sc_type < LOM_LOMLITE2) {
246 1.1 nakayama /* XXX Magic */
247 1.1 nakayama (void)bus_space_read_1(sc->sc_iot, sc->sc_ioh, 0);
248 1.1 nakayama bus_space_write_1(sc->sc_iot, sc->sc_ioh, 3, 0xca);
249 1.1 nakayama
250 1.1 nakayama TAILQ_INIT(&sc->sc_queue);
251 1.1 nakayama mutex_init(&sc->sc_queue_mtx, MUTEX_DEFAULT, IPL_VM);
252 1.1 nakayama callout_init(&sc->sc_state_to, 0);
253 1.1 nakayama callout_setfunc(&sc->sc_state_to, lom1_process_queue, sc);
254 1.1 nakayama }
255 1.1 nakayama
256 1.1 nakayama if (lom_read(sc, LOM_IDX_PROBE55, ®) || reg != 0x55 ||
257 1.1 nakayama lom_read(sc, LOM_IDX_PROBEAA, ®) || reg != 0xaa ||
258 1.1 nakayama lom_read(sc, LOM_IDX_FW_REV, &fw_rev) ||
259 1.1 nakayama lom_read(sc, LOM_IDX_CONFIG, &config))
260 1.1 nakayama {
261 1.1 nakayama aprint_error(": not responding\n");
262 1.1 nakayama return;
263 1.1 nakayama }
264 1.1 nakayama
265 1.1 nakayama aprint_normal(": %s: %s rev %d.%d\n", ea->ea_name,
266 1.1 nakayama sc->sc_type < LOM_LOMLITE2 ? "LOMlite" : "LOMlite2",
267 1.1 nakayama fw_rev >> 4, fw_rev & 0x0f);
268 1.1 nakayama
269 1.1 nakayama config2 = config3 = 0;
270 1.1 nakayama if (sc->sc_type >= LOM_LOMLITE2) {
271 1.1 nakayama lom_read(sc, LOM_IDX_CONFIG2, &config2);
272 1.1 nakayama lom_read(sc, LOM_IDX_CONFIG3, &config3);
273 1.1 nakayama }
274 1.1 nakayama
275 1.1 nakayama sc->sc_num_fan = min((config >> 5) & 0x7, LOM_MAX_FAN);
276 1.1 nakayama sc->sc_num_psu = min((config >> 3) & 0x3, LOM_MAX_PSU);
277 1.1 nakayama sc->sc_num_temp = min((config2 >> 4) & 0xf, LOM_MAX_TEMP);
278 1.1 nakayama
279 1.1 nakayama aprint_verbose_dev(self, "%d fan(s), %d PSU(s), %d temp sensor(s)\n",
280 1.1 nakayama sc->sc_num_fan, sc->sc_num_psu, sc->sc_num_temp);
281 1.1 nakayama
282 1.1 nakayama for (i = 0; i < sc->sc_num_fan; i++) {
283 1.1 nakayama if (lom_read(sc, LOM_IDX_FAN1_CAL + i, &cal) ||
284 1.1 nakayama lom_read(sc, LOM_IDX_FAN1_LOW + i, &low)) {
285 1.1 nakayama aprint_error_dev(self, "can't read fan information\n");
286 1.1 nakayama return;
287 1.1 nakayama }
288 1.1 nakayama sc->sc_fan_cal[i] = cal;
289 1.1 nakayama sc->sc_fan_low[i] = low;
290 1.1 nakayama }
291 1.1 nakayama
292 1.1 nakayama /* Initialize sensor data. */
293 1.1 nakayama sc->sc_sme = sysmon_envsys_create();
294 1.1 nakayama for (i = 0; i < sc->sc_num_fan; i++) {
295 1.1 nakayama sc->sc_fan[i].units = ENVSYS_SFANRPM;
296 1.1 nakayama snprintf(sc->sc_fan[i].desc, sizeof(sc->sc_fan[i].desc),
297 1.1 nakayama "fan%d", i + 1);
298 1.1 nakayama if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_fan[i])) {
299 1.1 nakayama sysmon_envsys_destroy(sc->sc_sme);
300 1.1 nakayama aprint_error_dev(self, "can't attach fan sensor\n");
301 1.1 nakayama return;
302 1.1 nakayama }
303 1.1 nakayama }
304 1.1 nakayama for (i = 0; i < sc->sc_num_psu; i++) {
305 1.1 nakayama sc->sc_psu[i].units = ENVSYS_INDICATOR;
306 1.1 nakayama snprintf(sc->sc_psu[i].desc, sizeof(sc->sc_psu[i].desc),
307 1.1 nakayama "PSU%d", i + 1);
308 1.1 nakayama if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_psu[i])) {
309 1.1 nakayama sysmon_envsys_destroy(sc->sc_sme);
310 1.1 nakayama aprint_error_dev(self, "can't attach PSU sensor\n");
311 1.1 nakayama return;
312 1.1 nakayama }
313 1.1 nakayama }
314 1.1 nakayama for (i = 0; i < sc->sc_num_temp; i++) {
315 1.1 nakayama sc->sc_temp[i].units = ENVSYS_STEMP;
316 1.1 nakayama snprintf(sc->sc_temp[i].desc, sizeof(sc->sc_temp[i].desc),
317 1.1 nakayama "temp%d", i + 1);
318 1.1 nakayama if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_temp[i])) {
319 1.1 nakayama sysmon_envsys_destroy(sc->sc_sme);
320 1.1 nakayama aprint_error_dev(self, "can't attach temp sensor\n");
321 1.1 nakayama return;
322 1.1 nakayama }
323 1.1 nakayama }
324 1.1 nakayama if (lom_init_desc(sc)) {
325 1.1 nakayama aprint_error_dev(self, "can't read sensor names\n");
326 1.1 nakayama sysmon_envsys_destroy(sc->sc_sme);
327 1.1 nakayama return;
328 1.1 nakayama }
329 1.1 nakayama
330 1.1 nakayama sc->sc_sme->sme_name = device_xname(self);
331 1.1 nakayama sc->sc_sme->sme_cookie = sc;
332 1.1 nakayama sc->sc_sme->sme_refresh = lom_refresh;
333 1.1 nakayama if (sysmon_envsys_register(sc->sc_sme)) {
334 1.1 nakayama aprint_error_dev(self,
335 1.1 nakayama "unable to register envsys with sysmon\n");
336 1.1 nakayama sysmon_envsys_destroy(sc->sc_sme);
337 1.1 nakayama return;
338 1.1 nakayama }
339 1.1 nakayama
340 1.1 nakayama /* Initialize watchdog. */
341 1.1 nakayama lom_write(sc, LOM_IDX_WDOG_TIME, LOM_WDOG_TIME_MAX);
342 1.1 nakayama lom_read(sc, LOM_IDX_WDOG_CTL, &sc->sc_wdog_ctl);
343 1.1 nakayama sc->sc_wdog_ctl &= ~(LOM_WDOG_ENABLE|LOM_WDOG_RESET);
344 1.1 nakayama lom_write(sc, LOM_IDX_WDOG_CTL, sc->sc_wdog_ctl);
345 1.1 nakayama
346 1.1 nakayama sc->sc_wdog_period = LOM_WDOG_TIME_MAX;
347 1.1 nakayama
348 1.1 nakayama sc->sc_smw.smw_name = device_xname(self);
349 1.1 nakayama sc->sc_smw.smw_cookie = sc;
350 1.1 nakayama sc->sc_smw.smw_setmode = lom_wdog_setmode;
351 1.1 nakayama sc->sc_smw.smw_tickle = lom_wdog_tickle;
352 1.1 nakayama sc->sc_smw.smw_period = sc->sc_wdog_period;
353 1.1 nakayama if (sysmon_wdog_register(&sc->sc_smw)) {
354 1.1 nakayama aprint_error_dev(self,
355 1.1 nakayama "unable to register wdog with sysmon\n");
356 1.1 nakayama return;
357 1.1 nakayama }
358 1.1 nakayama
359 1.1 nakayama aprint_verbose_dev(self, "Watchdog timer configured.\n");
360 1.1 nakayama }
361 1.1 nakayama
362 1.1 nakayama static int
363 1.1 nakayama lom_read(struct lom_softc *sc, uint8_t reg, uint8_t *val)
364 1.1 nakayama {
365 1.1 nakayama if (sc->sc_type < LOM_LOMLITE2)
366 1.1 nakayama return lom1_read(sc, reg, val);
367 1.1 nakayama else
368 1.1 nakayama return lom2_read(sc, reg, val);
369 1.1 nakayama }
370 1.1 nakayama
371 1.1 nakayama static int
372 1.1 nakayama lom_write(struct lom_softc *sc, uint8_t reg, uint8_t val)
373 1.1 nakayama {
374 1.1 nakayama if (sc->sc_type < LOM_LOMLITE2)
375 1.1 nakayama return lom1_write(sc, reg, val);
376 1.1 nakayama else
377 1.1 nakayama return lom2_write(sc, reg, val);
378 1.1 nakayama }
379 1.1 nakayama
380 1.1 nakayama static void
381 1.1 nakayama lom_queue_cmd(struct lom_softc *sc, struct lom_cmd *lc)
382 1.1 nakayama {
383 1.1 nakayama if (sc->sc_type < LOM_LOMLITE2)
384 1.1 nakayama return lom1_queue_cmd(sc, lc);
385 1.1 nakayama else
386 1.1 nakayama return lom2_queue_cmd(sc, lc);
387 1.1 nakayama }
388 1.1 nakayama
389 1.1 nakayama static int
390 1.1 nakayama lom1_read(struct lom_softc *sc, uint8_t reg, uint8_t *val)
391 1.1 nakayama {
392 1.1 nakayama struct lom_cmd lc;
393 1.1 nakayama int error;
394 1.1 nakayama
395 1.1 nakayama if (cold)
396 1.1 nakayama return lom1_read_polled(sc, reg, val);
397 1.1 nakayama
398 1.1 nakayama lc.lc_cmd = reg;
399 1.1 nakayama lc.lc_data = 0xff;
400 1.1 nakayama lom1_queue_cmd(sc, &lc);
401 1.1 nakayama
402 1.1 nakayama error = tsleep(&lc, PZERO, "lomrd", hz);
403 1.1 nakayama if (error)
404 1.1 nakayama lom1_dequeue_cmd(sc, &lc);
405 1.1 nakayama
406 1.1 nakayama *val = lc.lc_data;
407 1.1 nakayama
408 1.1 nakayama return (error);
409 1.1 nakayama }
410 1.1 nakayama
411 1.1 nakayama static int
412 1.1 nakayama lom1_write_polled(struct lom_softc *sc, uint8_t reg, uint8_t val)
413 1.1 nakayama {
414 1.1 nakayama struct lom_cmd lc;
415 1.1 nakayama int error;
416 1.1 nakayama
417 1.1 nakayama if (cold)
418 1.1 nakayama return lom1_write_polled(sc, reg, val);
419 1.1 nakayama
420 1.1 nakayama lc.lc_cmd = reg | LOM_IDX_WRITE;
421 1.1 nakayama lc.lc_data = val;
422 1.1 nakayama lom1_queue_cmd(sc, &lc);
423 1.1 nakayama
424 1.1 nakayama error = tsleep(&lc, PZERO, "lomwr", hz);
425 1.1 nakayama if (error)
426 1.1 nakayama lom1_dequeue_cmd(sc, &lc);
427 1.1 nakayama
428 1.1 nakayama return (error);
429 1.1 nakayama }
430 1.1 nakayama
431 1.1 nakayama static int
432 1.1 nakayama lom1_read_polled(struct lom_softc *sc, uint8_t reg, uint8_t *val)
433 1.1 nakayama {
434 1.1 nakayama uint8_t str;
435 1.1 nakayama int i;
436 1.1 nakayama
437 1.1 nakayama /* Wait for input buffer to become available. */
438 1.1 nakayama for (i = 30; i > 0; i--) {
439 1.1 nakayama str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS);
440 1.1 nakayama delay(1000);
441 1.1 nakayama if ((str & LOM1_STATUS_BUSY) == 0)
442 1.1 nakayama break;
443 1.1 nakayama }
444 1.1 nakayama if (i == 0)
445 1.1 nakayama return (ETIMEDOUT);
446 1.1 nakayama
447 1.1 nakayama bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_CMD, reg);
448 1.1 nakayama
449 1.1 nakayama /* Wait until the microcontroller fills output buffer. */
450 1.1 nakayama for (i = 30; i > 0; i--) {
451 1.1 nakayama str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS);
452 1.1 nakayama delay(1000);
453 1.1 nakayama if ((str & LOM1_STATUS_BUSY) == 0)
454 1.1 nakayama break;
455 1.1 nakayama }
456 1.1 nakayama if (i == 0)
457 1.1 nakayama return (ETIMEDOUT);
458 1.1 nakayama
459 1.1 nakayama *val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA);
460 1.1 nakayama return (0);
461 1.1 nakayama }
462 1.1 nakayama
463 1.1 nakayama static int
464 1.1 nakayama lom1_write(struct lom_softc *sc, uint8_t reg, uint8_t val)
465 1.1 nakayama {
466 1.1 nakayama uint8_t str;
467 1.1 nakayama int i;
468 1.1 nakayama
469 1.1 nakayama /* Wait for input buffer to become available. */
470 1.1 nakayama for (i = 30; i > 0; i--) {
471 1.1 nakayama str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS);
472 1.1 nakayama delay(1000);
473 1.1 nakayama if ((str & LOM1_STATUS_BUSY) == 0)
474 1.1 nakayama break;
475 1.1 nakayama }
476 1.1 nakayama if (i == 0)
477 1.1 nakayama return (ETIMEDOUT);
478 1.1 nakayama
479 1.1 nakayama reg |= LOM_IDX_WRITE;
480 1.1 nakayama bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_CMD, reg);
481 1.1 nakayama
482 1.1 nakayama /* Wait until the microcontroller fills output buffer. */
483 1.1 nakayama for (i = 30; i > 0; i--) {
484 1.1 nakayama str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS);
485 1.1 nakayama delay(1000);
486 1.1 nakayama if ((str & LOM1_STATUS_BUSY) == 0)
487 1.1 nakayama break;
488 1.1 nakayama }
489 1.1 nakayama if (i == 0)
490 1.1 nakayama return (ETIMEDOUT);
491 1.1 nakayama
492 1.1 nakayama bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA, val);
493 1.1 nakayama
494 1.1 nakayama return (0);
495 1.1 nakayama }
496 1.1 nakayama
497 1.1 nakayama static void
498 1.1 nakayama lom1_queue_cmd(struct lom_softc *sc, struct lom_cmd *lc)
499 1.1 nakayama {
500 1.1 nakayama mutex_enter(&sc->sc_queue_mtx);
501 1.1 nakayama TAILQ_INSERT_TAIL(&sc->sc_queue, lc, lc_next);
502 1.1 nakayama if (sc->sc_state == LOM_STATE_IDLE) {
503 1.1 nakayama sc->sc_state = LOM_STATE_CMD;
504 1.1 nakayama lom1_process_queue_locked(sc);
505 1.1 nakayama }
506 1.1 nakayama mutex_exit(&sc->sc_queue_mtx);
507 1.1 nakayama }
508 1.1 nakayama
509 1.1 nakayama static void
510 1.1 nakayama lom1_dequeue_cmd(struct lom_softc *sc, struct lom_cmd *lc)
511 1.1 nakayama {
512 1.1 nakayama struct lom_cmd *lcp;
513 1.1 nakayama
514 1.1 nakayama mutex_enter(&sc->sc_queue_mtx);
515 1.1 nakayama TAILQ_FOREACH(lcp, &sc->sc_queue, lc_next) {
516 1.1 nakayama if (lcp == lc) {
517 1.1 nakayama TAILQ_REMOVE(&sc->sc_queue, lc, lc_next);
518 1.1 nakayama break;
519 1.1 nakayama }
520 1.1 nakayama }
521 1.1 nakayama mutex_exit(&sc->sc_queue_mtx);
522 1.1 nakayama }
523 1.1 nakayama
524 1.1 nakayama static void
525 1.1 nakayama lom1_process_queue(void *arg)
526 1.1 nakayama {
527 1.1 nakayama struct lom_softc *sc = arg;
528 1.1 nakayama
529 1.1 nakayama mutex_enter(&sc->sc_queue_mtx);
530 1.1 nakayama lom1_process_queue_locked(sc);
531 1.1 nakayama mutex_exit(&sc->sc_queue_mtx);
532 1.1 nakayama }
533 1.1 nakayama
534 1.1 nakayama static void
535 1.1 nakayama lom1_process_queue_locked(struct lom_softc *sc)
536 1.1 nakayama {
537 1.1 nakayama struct lom_cmd *lc;
538 1.1 nakayama uint8_t str;
539 1.1 nakayama
540 1.1 nakayama lc = TAILQ_FIRST(&sc->sc_queue);
541 1.1 nakayama KASSERT(lc != NULL);
542 1.1 nakayama
543 1.1 nakayama str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS);
544 1.1 nakayama if (str & LOM1_STATUS_BUSY) {
545 1.1 nakayama if (sc->sc_retry++ > 30)
546 1.1 nakayama return;
547 1.1 nakayama callout_schedule(&sc->sc_state_to, mstohz(1));
548 1.1 nakayama return;
549 1.1 nakayama }
550 1.1 nakayama
551 1.1 nakayama sc->sc_retry = 0;
552 1.1 nakayama
553 1.1 nakayama if (sc->sc_state == LOM_STATE_CMD) {
554 1.1 nakayama bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_CMD, lc->lc_cmd);
555 1.1 nakayama sc->sc_state = LOM_STATE_DATA;
556 1.1 nakayama callout_schedule(&sc->sc_state_to, mstohz(250));
557 1.1 nakayama return;
558 1.1 nakayama }
559 1.1 nakayama
560 1.1 nakayama KASSERT(sc->sc_state == LOM_STATE_DATA);
561 1.1 nakayama if ((lc->lc_cmd & LOM_IDX_WRITE) == 0)
562 1.1 nakayama lc->lc_data = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA);
563 1.1 nakayama else
564 1.1 nakayama bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA, lc->lc_data);
565 1.1 nakayama
566 1.1 nakayama TAILQ_REMOVE(&sc->sc_queue, lc, lc_next);
567 1.1 nakayama
568 1.1 nakayama wakeup(lc);
569 1.1 nakayama
570 1.1 nakayama if (!TAILQ_EMPTY(&sc->sc_queue)) {
571 1.1 nakayama sc->sc_state = LOM_STATE_CMD;
572 1.1 nakayama callout_schedule(&sc->sc_state_to, mstohz(1));
573 1.1 nakayama return;
574 1.1 nakayama }
575 1.1 nakayama
576 1.1 nakayama sc->sc_state = LOM_STATE_IDLE;
577 1.1 nakayama }
578 1.1 nakayama
579 1.1 nakayama static int
580 1.1 nakayama lom2_read(struct lom_softc *sc, uint8_t reg, uint8_t *val)
581 1.1 nakayama {
582 1.1 nakayama uint8_t str;
583 1.1 nakayama int i;
584 1.1 nakayama
585 1.1 nakayama /* Wait for input buffer to become available. */
586 1.1 nakayama for (i = 1000; i > 0; i--) {
587 1.1 nakayama str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
588 1.1 nakayama delay(10);
589 1.1 nakayama if ((str & LOM2_STATUS_IBF) == 0)
590 1.1 nakayama break;
591 1.1 nakayama }
592 1.1 nakayama if (i == 0)
593 1.1 nakayama return (ETIMEDOUT);
594 1.1 nakayama
595 1.1 nakayama bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM2_CMD, reg);
596 1.1 nakayama
597 1.1 nakayama /* Wait until the microcontroller fills output buffer. */
598 1.1 nakayama for (i = 1000; i > 0; i--) {
599 1.1 nakayama str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
600 1.1 nakayama delay(10);
601 1.1 nakayama if (str & LOM2_STATUS_OBF)
602 1.1 nakayama break;
603 1.1 nakayama }
604 1.1 nakayama if (i == 0)
605 1.1 nakayama return (ETIMEDOUT);
606 1.1 nakayama
607 1.1 nakayama *val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA);
608 1.1 nakayama return (0);
609 1.1 nakayama }
610 1.1 nakayama
611 1.1 nakayama static int
612 1.1 nakayama lom2_write(struct lom_softc *sc, uint8_t reg, uint8_t val)
613 1.1 nakayama {
614 1.1 nakayama uint8_t str;
615 1.1 nakayama int i;
616 1.1 nakayama
617 1.1 nakayama /* Wait for input buffer to become available. */
618 1.1 nakayama for (i = 1000; i > 0; i--) {
619 1.1 nakayama str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
620 1.1 nakayama delay(10);
621 1.1 nakayama if ((str & LOM2_STATUS_IBF) == 0)
622 1.1 nakayama break;
623 1.1 nakayama }
624 1.1 nakayama if (i == 0)
625 1.1 nakayama return (ETIMEDOUT);
626 1.1 nakayama
627 1.1 nakayama if (sc->sc_space == LOM_IDX_CMD_GENERIC && reg != LOM_IDX_CMD)
628 1.1 nakayama reg |= 0x80;
629 1.1 nakayama
630 1.1 nakayama bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM2_CMD, reg);
631 1.1 nakayama
632 1.1 nakayama /* Wait until the microcontroller fills output buffer. */
633 1.1 nakayama for (i = 1000; i > 0; i--) {
634 1.1 nakayama str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
635 1.1 nakayama delay(10);
636 1.1 nakayama if (str & LOM2_STATUS_OBF)
637 1.1 nakayama break;
638 1.1 nakayama }
639 1.1 nakayama if (i == 0)
640 1.1 nakayama return (ETIMEDOUT);
641 1.1 nakayama
642 1.1 nakayama (void)bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA);
643 1.1 nakayama
644 1.1 nakayama /* Wait for input buffer to become available. */
645 1.1 nakayama for (i = 1000; i > 0; i--) {
646 1.1 nakayama str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
647 1.1 nakayama delay(10);
648 1.1 nakayama if ((str & LOM2_STATUS_IBF) == 0)
649 1.1 nakayama break;
650 1.1 nakayama }
651 1.1 nakayama if (i == 0)
652 1.1 nakayama return (ETIMEDOUT);
653 1.1 nakayama
654 1.1 nakayama bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA, val);
655 1.1 nakayama
656 1.1 nakayama /* Wait until the microcontroller fills output buffer. */
657 1.1 nakayama for (i = 1000; i > 0; i--) {
658 1.1 nakayama str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
659 1.1 nakayama delay(10);
660 1.1 nakayama if (str & LOM2_STATUS_OBF)
661 1.1 nakayama break;
662 1.1 nakayama }
663 1.1 nakayama if (i == 0)
664 1.1 nakayama return (ETIMEDOUT);
665 1.1 nakayama
666 1.1 nakayama (void)bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA);
667 1.1 nakayama
668 1.1 nakayama /* If we switched spaces, remember the one we're in now. */
669 1.1 nakayama if (reg == LOM_IDX_CMD)
670 1.1 nakayama sc->sc_space = val;
671 1.1 nakayama
672 1.1 nakayama return (0);
673 1.1 nakayama }
674 1.1 nakayama
675 1.1 nakayama static void
676 1.1 nakayama lom2_queue_cmd(struct lom_softc *sc, struct lom_cmd *lc)
677 1.1 nakayama {
678 1.1 nakayama KASSERT(lc->lc_cmd & LOM_IDX_WRITE);
679 1.1 nakayama lom2_write(sc, lc->lc_cmd, lc->lc_data);
680 1.1 nakayama }
681 1.1 nakayama
682 1.1 nakayama static int
683 1.1 nakayama lom_init_desc(struct lom_softc *sc)
684 1.1 nakayama {
685 1.1 nakayama uint8_t val;
686 1.1 nakayama int i, j, k;
687 1.1 nakayama int error;
688 1.1 nakayama
689 1.1 nakayama /* LOMlite doesn't provide sensor descriptions. */
690 1.1 nakayama if (sc->sc_type < LOM_LOMLITE2)
691 1.1 nakayama return (0);
692 1.1 nakayama
693 1.1 nakayama /*
694 1.1 nakayama * Read temperature sensor names.
695 1.1 nakayama */
696 1.1 nakayama error = lom_write(sc, LOM_IDX_CMD, LOM_IDX_CMD_TEMP);
697 1.1 nakayama if (error)
698 1.1 nakayama return (error);
699 1.1 nakayama
700 1.1 nakayama i = 0;
701 1.1 nakayama j = 0;
702 1.1 nakayama k = LOM_IDX4_TEMP_NAME_START;
703 1.1 nakayama while (k <= LOM_IDX4_TEMP_NAME_END) {
704 1.1 nakayama error = lom_read(sc, k++, &val);
705 1.1 nakayama if (error)
706 1.1 nakayama goto fail;
707 1.1 nakayama
708 1.1 nakayama if (val == 0xff)
709 1.1 nakayama break;
710 1.1 nakayama
711 1.1 nakayama if (j < sizeof (sc->sc_temp[i].desc) - 1)
712 1.1 nakayama sc->sc_temp[i].desc[j++] = val;
713 1.1 nakayama
714 1.1 nakayama if (val == '\0') {
715 1.1 nakayama i++;
716 1.1 nakayama j = 0;
717 1.1 nakayama if (i < sc->sc_num_temp)
718 1.1 nakayama continue;
719 1.1 nakayama
720 1.1 nakayama break;
721 1.1 nakayama }
722 1.1 nakayama }
723 1.1 nakayama
724 1.1 nakayama /*
725 1.1 nakayama * Read fan names.
726 1.1 nakayama */
727 1.1 nakayama error = lom_write(sc, LOM_IDX_CMD, LOM_IDX_CMD_FAN);
728 1.1 nakayama if (error)
729 1.1 nakayama return (error);
730 1.1 nakayama
731 1.1 nakayama i = 0;
732 1.1 nakayama j = 0;
733 1.1 nakayama k = LOM_IDX5_FAN_NAME_START;
734 1.1 nakayama while (k <= LOM_IDX5_FAN_NAME_END) {
735 1.1 nakayama error = lom_read(sc, k++, &val);
736 1.1 nakayama if (error)
737 1.1 nakayama goto fail;
738 1.1 nakayama
739 1.1 nakayama if (val == 0xff)
740 1.1 nakayama break;
741 1.1 nakayama
742 1.1 nakayama if (j < sizeof (sc->sc_fan[i].desc) - 1)
743 1.1 nakayama sc->sc_fan[i].desc[j++] = val;
744 1.1 nakayama
745 1.1 nakayama if (val == '\0') {
746 1.1 nakayama i++;
747 1.1 nakayama j = 0;
748 1.1 nakayama if (i < sc->sc_num_fan)
749 1.1 nakayama continue;
750 1.1 nakayama
751 1.1 nakayama break;
752 1.1 nakayama }
753 1.1 nakayama }
754 1.1 nakayama
755 1.1 nakayama fail:
756 1.1 nakayama lom_write(sc, LOM_IDX_CMD, LOM_IDX_CMD_GENERIC);
757 1.1 nakayama return (error);
758 1.1 nakayama }
759 1.1 nakayama
760 1.1 nakayama static void
761 1.1 nakayama lom_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
762 1.1 nakayama {
763 1.1 nakayama struct lom_softc *sc = sme->sme_cookie;
764 1.1 nakayama uint8_t val;
765 1.1 nakayama int i;
766 1.1 nakayama
767 1.1 nakayama for (i = 0; i < sc->sc_num_fan; i++) {
768 1.1 nakayama if (lom_read(sc, LOM_IDX_FAN1 + i, &val)) {
769 1.1 nakayama sc->sc_fan[i].state = ENVSYS_SINVALID;
770 1.1 nakayama continue;
771 1.1 nakayama }
772 1.1 nakayama
773 1.1 nakayama sc->sc_fan[i].value_cur = (60 * sc->sc_fan_cal[i] * val) / 100;
774 1.1 nakayama if (val < sc->sc_fan_low[i])
775 1.1 nakayama sc->sc_fan[i].state = ENVSYS_SCRITICAL;
776 1.1 nakayama else
777 1.1 nakayama sc->sc_fan[i].state = ENVSYS_SVALID;
778 1.1 nakayama }
779 1.1 nakayama
780 1.1 nakayama for (i = 0; i < sc->sc_num_psu; i++) {
781 1.1 nakayama if (lom_read(sc, LOM_IDX_PSU1 + i, &val) ||
782 1.1 nakayama !ISSET(val, LOM_PSU_PRESENT)) {
783 1.1 nakayama sc->sc_psu[i].state = ENVSYS_SINVALID;
784 1.1 nakayama continue;
785 1.1 nakayama }
786 1.1 nakayama
787 1.1 nakayama if (val & LOM_PSU_STANDBY) {
788 1.1 nakayama sc->sc_psu[i].value_cur = 0;
789 1.1 nakayama sc->sc_psu[i].state = ENVSYS_SVALID;
790 1.1 nakayama } else {
791 1.1 nakayama sc->sc_psu[i].value_cur = 1;
792 1.1 nakayama if (ISSET(val, LOM_PSU_INPUTA) &&
793 1.1 nakayama ISSET(val, LOM_PSU_INPUTB) &&
794 1.1 nakayama ISSET(val, LOM_PSU_OUTPUT))
795 1.1 nakayama sc->sc_psu[i].state = ENVSYS_SVALID;
796 1.1 nakayama else
797 1.1 nakayama sc->sc_psu[i].state = ENVSYS_SCRITICAL;
798 1.1 nakayama }
799 1.1 nakayama }
800 1.1 nakayama
801 1.1 nakayama for (i = 0; i < sc->sc_num_temp; i++) {
802 1.1 nakayama if (lom_read(sc, LOM_IDX_TEMP1 + i, &val)) {
803 1.1 nakayama sc->sc_temp[i].state = ENVSYS_SINVALID;
804 1.1 nakayama continue;
805 1.1 nakayama }
806 1.1 nakayama
807 1.1 nakayama sc->sc_temp[i].value_cur = val * 1000000 + 273150000;
808 1.1 nakayama sc->sc_temp[i].state = ENVSYS_SVALID;
809 1.1 nakayama }
810 1.1 nakayama
811 1.1 nakayama /*
812 1.1 nakayama * If our hostname is set and differs from what's stored in
813 1.1 nakayama * the LOM, write the new hostname back to the LOM. Note that
814 1.1 nakayama * we include the terminating NUL when writing the hostname
815 1.1 nakayama * back to the LOM, otherwise the LOM will print any trailing
816 1.1 nakayama * garbage.
817 1.1 nakayama */
818 1.1 nakayama if (hostnamelen > 0 &&
819 1.1 nakayama strncmp(sc->sc_hostname, hostname, sizeof(hostname)) != 0) {
820 1.1 nakayama if (sc->sc_type < LOM_LOMLITE2)
821 1.1 nakayama lom1_write_hostname(sc);
822 1.1 nakayama else
823 1.1 nakayama lom2_write_hostname(sc);
824 1.1 nakayama strlcpy(sc->sc_hostname, hostname, sizeof(hostname));
825 1.1 nakayama }
826 1.1 nakayama }
827 1.1 nakayama
828 1.1 nakayama static void
829 1.1 nakayama lom1_write_hostname(struct lom_softc *sc)
830 1.1 nakayama {
831 1.1 nakayama char name[LOM1_IDX_HOSTNAME12 - LOM1_IDX_HOSTNAME1 + 1];
832 1.1 nakayama char *p;
833 1.1 nakayama int i;
834 1.1 nakayama
835 1.1 nakayama /*
836 1.1 nakayama * LOMlite generally doesn't have enough space to store the
837 1.1 nakayama * fully qualified hostname. If the hostname is too long,
838 1.1 nakayama * strip off the domain name.
839 1.1 nakayama */
840 1.1 nakayama strlcpy(name, hostname, sizeof(name));
841 1.1 nakayama if (hostnamelen > sizeof(name)) {
842 1.1 nakayama p = strchr(name, '.');
843 1.1 nakayama if (p)
844 1.1 nakayama *p = '\0';
845 1.1 nakayama }
846 1.1 nakayama
847 1.1 nakayama for (i = 0; i < strlen(name) + 1; i++)
848 1.1 nakayama if (lom_write(sc, LOM1_IDX_HOSTNAME1 + i, name[i]))
849 1.1 nakayama break;
850 1.1 nakayama }
851 1.1 nakayama
852 1.1 nakayama static void
853 1.1 nakayama lom2_write_hostname(struct lom_softc *sc)
854 1.1 nakayama {
855 1.1 nakayama int i;
856 1.1 nakayama
857 1.1 nakayama lom_write(sc, LOM2_IDX_HOSTNAMELEN, hostnamelen + 1);
858 1.1 nakayama for (i = 0; i < hostnamelen + 1; i++)
859 1.1 nakayama lom_write(sc, LOM2_IDX_HOSTNAME, hostname[i]);
860 1.1 nakayama }
861 1.1 nakayama
862 1.1 nakayama static int
863 1.1 nakayama lom_wdog_tickle(struct sysmon_wdog *smw)
864 1.1 nakayama {
865 1.1 nakayama struct lom_softc *sc = smw->smw_cookie;
866 1.1 nakayama
867 1.1 nakayama /* Pat the dog. */
868 1.1 nakayama sc->sc_wdog_pat.lc_cmd = LOM_IDX_WDOG_CTL | LOM_IDX_WRITE;
869 1.1 nakayama sc->sc_wdog_pat.lc_data = sc->sc_wdog_ctl;
870 1.1 nakayama lom_queue_cmd(sc, &sc->sc_wdog_pat);
871 1.1 nakayama
872 1.1 nakayama return 0;
873 1.1 nakayama }
874 1.1 nakayama
875 1.1 nakayama static int
876 1.1 nakayama lom_wdog_setmode(struct sysmon_wdog *smw)
877 1.1 nakayama {
878 1.1 nakayama struct lom_softc *sc = smw->smw_cookie;
879 1.1 nakayama
880 1.1 nakayama if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) {
881 1.1 nakayama /* disable watchdog */
882 1.1 nakayama sc->sc_wdog_ctl &= ~(LOM_WDOG_ENABLE|LOM_WDOG_RESET);
883 1.1 nakayama lom_write(sc, LOM_IDX_WDOG_CTL, sc->sc_wdog_ctl);
884 1.1 nakayama } else {
885 1.1 nakayama if (smw->smw_period == WDOG_PERIOD_DEFAULT)
886 1.1 nakayama smw->smw_period = sc->sc_wdog_period;
887 1.1 nakayama else if (smw->smw_period == 0 ||
888 1.1 nakayama smw->smw_period > LOM_WDOG_TIME_MAX)
889 1.1 nakayama return EINVAL;
890 1.1 nakayama lom_write(sc, LOM_IDX_WDOG_TIME, smw->smw_period);
891 1.1 nakayama
892 1.1 nakayama /* enable watchdog */
893 1.1 nakayama sc->sc_wdog_ctl |= LOM_WDOG_ENABLE|LOM_WDOG_RESET;
894 1.1 nakayama sc->sc_wdog_pat.lc_cmd = LOM_IDX_WDOG_CTL | LOM_IDX_WRITE;
895 1.1 nakayama sc->sc_wdog_pat.lc_data = sc->sc_wdog_ctl;
896 1.1 nakayama lom_queue_cmd(sc, &sc->sc_wdog_pat);
897 1.1 nakayama }
898 1.1 nakayama
899 1.1 nakayama return 0;
900 1.1 nakayama }
901