xref: /openbsd-src/sys/dev/ipmi.c (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
1 /*	$OpenBSD: ipmi.c,v 1.72 2014/07/12 18:48:17 tedu Exp $ */
2 
3 /*
4  * Copyright (c) 2005 Jordan Hargrave
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/types.h>
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/device.h>
34 #include <sys/extent.h>
35 #include <sys/timeout.h>
36 #include <sys/sensors.h>
37 #include <sys/malloc.h>
38 #include <sys/kthread.h>
39 
40 #include <machine/bus.h>
41 #include <machine/intr.h>
42 #include <machine/smbiosvar.h>
43 
44 #include <dev/isa/isareg.h>
45 #include <dev/isa/isavar.h>
46 
47 #include <dev/ipmivar.h>
48 
49 struct ipmi_sensor {
50 	u_int8_t	*i_sdr;
51 	int		i_num;
52 	int		stype;
53 	int		etype;
54 	struct		ksensor i_sensor;
55 	SLIST_ENTRY(ipmi_sensor) list;
56 };
57 
58 int	ipmi_nintr;
59 int	ipmi_poll = 1;
60 int	ipmi_enabled = 0;
61 
62 #define SENSOR_REFRESH_RATE (5 * hz)
63 
64 #define SMBIOS_TYPE_IPMI	0x26
65 
66 #define DEVNAME(s)  ((s)->sc_dev.dv_xname)
67 
68 /*
69  * Format of SMBIOS IPMI Flags
70  *
71  * bit0: interrupt trigger mode (1=level, 0=edge)
72  * bit1: interrupt polarity (1=active high, 0=active low)
73  * bit2: reserved
74  * bit3: address LSB (1=odd,0=even)
75  * bit4: interrupt (1=specified, 0=not specified)
76  * bit5: reserved
77  * bit6/7: register spacing (1,4,2,err)
78  */
79 #define SMIPMI_FLAG_IRQLVL		(1L << 0)
80 #define SMIPMI_FLAG_IRQEN		(1L << 3)
81 #define SMIPMI_FLAG_ODDOFFSET		(1L << 4)
82 #define SMIPMI_FLAG_IFSPACING(x)	(((x)>>6)&0x3)
83 #define	 IPMI_IOSPACING_BYTE		 0
84 #define	 IPMI_IOSPACING_WORD		 2
85 #define	 IPMI_IOSPACING_DWORD		 1
86 
87 #define IPMI_BTMSG_LEN			0
88 #define IPMI_BTMSG_NFLN			1
89 #define IPMI_BTMSG_SEQ			2
90 #define IPMI_BTMSG_CMD			3
91 #define IPMI_BTMSG_CCODE		4
92 #define IPMI_BTMSG_DATASND		4
93 #define IPMI_BTMSG_DATARCV		5
94 
95 #define IPMI_MSG_NFLN			0
96 #define IPMI_MSG_CMD			1
97 #define IPMI_MSG_CCODE			2
98 #define IPMI_MSG_DATASND		2
99 #define IPMI_MSG_DATARCV		3
100 
101 #define IPMI_SENSOR_TYPE_TEMP		0x0101
102 #define IPMI_SENSOR_TYPE_VOLT		0x0102
103 #define IPMI_SENSOR_TYPE_FAN		0x0104
104 #define IPMI_SENSOR_TYPE_INTRUSION	0x6F05
105 #define IPMI_SENSOR_TYPE_PWRSUPPLY	0x6F08
106 
107 #define IPMI_NAME_UNICODE		0x00
108 #define IPMI_NAME_BCDPLUS		0x01
109 #define IPMI_NAME_ASCII6BIT		0x02
110 #define IPMI_NAME_ASCII8BIT		0x03
111 
112 #define IPMI_ENTITY_PWRSUPPLY		0x0A
113 
114 #define IPMI_INVALID_SENSOR		(1L << 5)
115 
116 #define IPMI_SDR_TYPEFULL		1
117 #define IPMI_SDR_TYPECOMPACT		2
118 
119 #define byteof(x) ((x) >> 3)
120 #define bitof(x)  (1L << ((x) & 0x7))
121 #define TB(b,m)	  (data[2+byteof(b)] & bitof(b))
122 
123 #ifdef IPMI_DEBUG
124 int	ipmi_dbg = 0;
125 #define dbg_printf(lvl, fmt...) \
126 	if (ipmi_dbg >= lvl) \
127 		printf(fmt);
128 #define dbg_dump(lvl, msg, len, buf) \
129 	if (len && ipmi_dbg >= lvl) \
130 		dumpb(msg, len, (const u_int8_t *)(buf));
131 #else
132 #define dbg_printf(lvl, fmt...)
133 #define dbg_dump(lvl, msg, len, buf)
134 #endif
135 
136 long signextend(unsigned long, int);
137 
138 SLIST_HEAD(ipmi_sensors_head, ipmi_sensor);
139 struct ipmi_sensors_head ipmi_sensor_list =
140     SLIST_HEAD_INITIALIZER(ipmi_sensor_list);
141 
142 struct timeout ipmi_timeout;
143 
144 void	dumpb(const char *, int, const u_int8_t *);
145 
146 int	read_sensor(struct ipmi_softc *, struct ipmi_sensor *);
147 int	add_sdr_sensor(struct ipmi_softc *, u_int8_t *);
148 int	get_sdr_partial(struct ipmi_softc *, u_int16_t, u_int16_t,
149 	    u_int8_t, u_int8_t, void *, u_int16_t *);
150 int	get_sdr(struct ipmi_softc *, u_int16_t, u_int16_t *);
151 
152 int	ipmi_sendcmd(struct ipmi_softc *, int, int, int, int, int, const void*);
153 int	ipmi_recvcmd(struct ipmi_softc *, int, int *, void *);
154 void	ipmi_delay(struct ipmi_softc *, int);
155 
156 int	ipmi_watchdog(void *, int);
157 
158 int	ipmi_intr(void *);
159 int	ipmi_match(struct device *, void *, void *);
160 void	ipmi_attach(struct device *, struct device *, void *);
161 
162 long	ipow(long, int);
163 long	ipmi_convert(u_int8_t, struct sdrtype1 *, long);
164 void	ipmi_sensor_name(char *, int, u_int8_t, u_int8_t *);
165 
166 /* BMC Helper Functions */
167 u_int8_t bmc_read(struct ipmi_softc *, int);
168 void	bmc_write(struct ipmi_softc *, int, u_int8_t);
169 int	bmc_io_wait(struct ipmi_softc *, int, u_int8_t, u_int8_t, const char *);
170 int	bmc_io_wait_cold(struct ipmi_softc *, int, u_int8_t, u_int8_t,
171     const char *);
172 void	_bmc_io_wait(void *);
173 
174 void	*bt_buildmsg(struct ipmi_softc *, int, int, int, const void *, int *);
175 void	*cmn_buildmsg(struct ipmi_softc *, int, int, int, const void *, int *);
176 
177 int	getbits(u_int8_t *, int, int);
178 int	ipmi_sensor_type(int, int, int);
179 
180 void	ipmi_smbios_probe(struct smbios_ipmi *, struct ipmi_attach_args *);
181 void	ipmi_refresh_sensors(struct ipmi_softc *sc);
182 int	ipmi_map_regs(struct ipmi_softc *sc, struct ipmi_attach_args *ia);
183 void	ipmi_unmap_regs(struct ipmi_softc *);
184 
185 void	*scan_sig(long, long, int, int, const void *);
186 
187 int	ipmi_test_threshold(u_int8_t, u_int8_t, u_int8_t, u_int8_t, int);
188 int	ipmi_sensor_status(struct ipmi_softc *, struct ipmi_sensor *,
189     u_int8_t *);
190 
191 int	 add_child_sensors(struct ipmi_softc *, u_int8_t *, int, int, int,
192     int, int, int, const char *);
193 
194 struct ipmi_if kcs_if = {
195 	"KCS",
196 	IPMI_IF_KCS_NREGS,
197 	cmn_buildmsg,
198 	kcs_sendmsg,
199 	kcs_recvmsg,
200 	kcs_reset,
201 	kcs_probe,
202 };
203 
204 struct ipmi_if smic_if = {
205 	"SMIC",
206 	IPMI_IF_SMIC_NREGS,
207 	cmn_buildmsg,
208 	smic_sendmsg,
209 	smic_recvmsg,
210 	smic_reset,
211 	smic_probe,
212 };
213 
214 struct ipmi_if bt_if = {
215 	"BT",
216 	IPMI_IF_BT_NREGS,
217 	bt_buildmsg,
218 	bt_sendmsg,
219 	bt_recvmsg,
220 	bt_reset,
221 	bt_probe,
222 };
223 
224 struct ipmi_if *ipmi_get_if(int);
225 
226 struct ipmi_if *
227 ipmi_get_if(int iftype)
228 {
229 	switch (iftype) {
230 	case IPMI_IF_KCS:
231 		return (&kcs_if);
232 	case IPMI_IF_SMIC:
233 		return (&smic_if);
234 	case IPMI_IF_BT:
235 		return (&bt_if);
236 	}
237 
238 	return (NULL);
239 }
240 
241 /*
242  * BMC Helper Functions
243  */
244 u_int8_t
245 bmc_read(struct ipmi_softc *sc, int offset)
246 {
247 	return (bus_space_read_1(sc->sc_iot, sc->sc_ioh,
248 	    offset * sc->sc_if_iospacing));
249 }
250 
251 void
252 bmc_write(struct ipmi_softc *sc, int offset, u_int8_t val)
253 {
254 	bus_space_write_1(sc->sc_iot, sc->sc_ioh,
255 	    offset * sc->sc_if_iospacing, val);
256 }
257 
258 void
259 _bmc_io_wait(void *arg)
260 {
261 	struct ipmi_softc	*sc = arg;
262 	struct ipmi_bmc_args	*a = sc->sc_iowait_args;
263 
264 	*a->v = bmc_read(sc, a->offset);
265 	if ((*a->v & a->mask) == a->value) {
266 		sc->sc_wakeup = 0;
267 		wakeup(sc);
268 		return;
269 	}
270 
271 	if (++sc->sc_retries > sc->sc_max_retries) {
272 		sc->sc_wakeup = 0;
273 		wakeup(sc);
274 		return;
275 	}
276 
277 	timeout_add(&sc->sc_timeout, 1);
278 }
279 
280 int
281 bmc_io_wait(struct ipmi_softc *sc, int offset, u_int8_t mask, u_int8_t value,
282     const char *lbl)
283 {
284 	volatile u_int8_t	v;
285 	struct ipmi_bmc_args	args;
286 
287 	if (cold)
288 		return (bmc_io_wait_cold(sc, offset, mask, value, lbl));
289 
290 	sc->sc_retries = 0;
291 	sc->sc_wakeup = 1;
292 
293 	args.offset = offset;
294 	args.mask = mask;
295 	args.value = value;
296 	args.v = &v;
297 	sc->sc_iowait_args = &args;
298 
299 	_bmc_io_wait(sc);
300 
301 	while (sc->sc_wakeup)
302 		tsleep(sc, PWAIT, lbl, 0);
303 
304 	if (sc->sc_retries > sc->sc_max_retries) {
305 		dbg_printf(1, "%s: bmc_io_wait fails : v=%.2x m=%.2x "
306 		    "b=%.2x %s\n", DEVNAME(sc), v, mask, value, lbl);
307 		return (-1);
308 	}
309 
310 	return (v);
311 }
312 
313 int
314 bmc_io_wait_cold(struct ipmi_softc *sc, int offset, u_int8_t mask,
315     u_int8_t value, const char *lbl)
316 {
317 	volatile u_int8_t	v;
318 	int			count = 5000000; /* == 5s XXX can be shorter */
319 
320 	while (count--) {
321 		v = bmc_read(sc, offset);
322 		if ((v & mask) == value)
323 			return v;
324 
325 		delay(1);
326 	}
327 
328 	dbg_printf(1, "%s: bmc_io_wait_cold fails : *v=%.2x m=%.2x b=%.2x %s\n",
329 	    DEVNAME(sc), v, mask, value, lbl);
330 	return (-1);
331 
332 }
333 
334 #define NETFN_LUN(nf,ln) (((nf) << 2) | ((ln) & 0x3))
335 
336 /*
337  * BT interface
338  */
339 #define _BT_CTRL_REG			0
340 #define	  BT_CLR_WR_PTR			(1L << 0)
341 #define	  BT_CLR_RD_PTR			(1L << 1)
342 #define	  BT_HOST2BMC_ATN		(1L << 2)
343 #define	  BT_BMC2HOST_ATN		(1L << 3)
344 #define	  BT_EVT_ATN			(1L << 4)
345 #define	  BT_HOST_BUSY			(1L << 6)
346 #define	  BT_BMC_BUSY			(1L << 7)
347 
348 #define	  BT_READY	(BT_HOST_BUSY|BT_HOST2BMC_ATN|BT_BMC2HOST_ATN)
349 
350 #define _BT_DATAIN_REG			1
351 #define _BT_DATAOUT_REG			1
352 
353 #define _BT_INTMASK_REG			2
354 #define	 BT_IM_HIRQ_PEND		(1L << 1)
355 #define	 BT_IM_SCI_EN			(1L << 2)
356 #define	 BT_IM_SMI_EN			(1L << 3)
357 #define	 BT_IM_NMI2SMI			(1L << 4)
358 
359 int bt_read(struct ipmi_softc *, int);
360 int bt_write(struct ipmi_softc *, int, uint8_t);
361 
362 int
363 bt_read(struct ipmi_softc *sc, int reg)
364 {
365 	return bmc_read(sc, reg);
366 }
367 
368 int
369 bt_write(struct ipmi_softc *sc, int reg, uint8_t data)
370 {
371 	if (bmc_io_wait(sc, _BT_CTRL_REG, BT_BMC_BUSY, 0, "bt_write") < 0)
372 		return (-1);
373 
374 	bmc_write(sc, reg, data);
375 	return (0);
376 }
377 
378 int
379 bt_sendmsg(struct ipmi_softc *sc, int len, const u_int8_t *data)
380 {
381 	int i;
382 
383 	bt_write(sc, _BT_CTRL_REG, BT_CLR_WR_PTR);
384 	for (i = 0; i < len; i++)
385 		bt_write(sc, _BT_DATAOUT_REG, data[i]);
386 
387 	bt_write(sc, _BT_CTRL_REG, BT_HOST2BMC_ATN);
388 	if (bmc_io_wait(sc, _BT_CTRL_REG, BT_HOST2BMC_ATN | BT_BMC_BUSY, 0,
389 	    "bt_sendwait") < 0)
390 		return (-1);
391 
392 	return (0);
393 }
394 
395 int
396 bt_recvmsg(struct ipmi_softc *sc, int maxlen, int *rxlen, u_int8_t *data)
397 {
398 	u_int8_t len, v, i;
399 
400 	if (bmc_io_wait(sc, _BT_CTRL_REG, BT_BMC2HOST_ATN, BT_BMC2HOST_ATN,
401 	    "bt_recvwait") < 0)
402 		return (-1);
403 
404 	bt_write(sc, _BT_CTRL_REG, BT_HOST_BUSY);
405 	bt_write(sc, _BT_CTRL_REG, BT_BMC2HOST_ATN);
406 	bt_write(sc, _BT_CTRL_REG, BT_CLR_RD_PTR);
407 	len = bt_read(sc, _BT_DATAIN_REG);
408 	for (i = IPMI_BTMSG_NFLN; i <= len; i++) {
409 		v = bt_read(sc, _BT_DATAIN_REG);
410 		if (i != IPMI_BTMSG_SEQ)
411 			*(data++) = v;
412 	}
413 	bt_write(sc, _BT_CTRL_REG, BT_HOST_BUSY);
414 	*rxlen = len - 1;
415 
416 	return (0);
417 }
418 
419 int
420 bt_reset(struct ipmi_softc *sc)
421 {
422 	return (-1);
423 }
424 
425 int
426 bt_probe(struct ipmi_softc *sc)
427 {
428 	u_int8_t rv;
429 
430 	rv = bmc_read(sc, _BT_CTRL_REG);
431 	rv &= BT_HOST_BUSY;
432 	rv |= BT_CLR_WR_PTR|BT_CLR_RD_PTR|BT_BMC2HOST_ATN|BT_HOST2BMC_ATN;
433 	bmc_write(sc, _BT_CTRL_REG, rv);
434 
435 	rv = bmc_read(sc, _BT_INTMASK_REG);
436 	rv &= BT_IM_SCI_EN|BT_IM_SMI_EN|BT_IM_NMI2SMI;
437 	rv |= BT_IM_HIRQ_PEND;
438 	bmc_write(sc, _BT_INTMASK_REG, rv);
439 
440 #if 0
441 	printf("bt_probe: %2x\n", v);
442 	printf(" WR    : %2x\n", v & BT_CLR_WR_PTR);
443 	printf(" RD    : %2x\n", v & BT_CLR_RD_PTR);
444 	printf(" H2B   : %2x\n", v & BT_HOST2BMC_ATN);
445 	printf(" B2H   : %2x\n", v & BT_BMC2HOST_ATN);
446 	printf(" EVT   : %2x\n", v & BT_EVT_ATN);
447 	printf(" HBSY  : %2x\n", v & BT_HOST_BUSY);
448 	printf(" BBSY  : %2x\n", v & BT_BMC_BUSY);
449 #endif
450 	return (0);
451 }
452 
453 /*
454  * SMIC interface
455  */
456 #define _SMIC_DATAIN_REG		0
457 #define _SMIC_DATAOUT_REG		0
458 
459 #define _SMIC_CTRL_REG			1
460 #define	  SMS_CC_GET_STATUS		 0x40
461 #define	  SMS_CC_START_TRANSFER		 0x41
462 #define	  SMS_CC_NEXT_TRANSFER		 0x42
463 #define	  SMS_CC_END_TRANSFER		 0x43
464 #define	  SMS_CC_START_RECEIVE		 0x44
465 #define	  SMS_CC_NEXT_RECEIVE		 0x45
466 #define	  SMS_CC_END_RECEIVE		 0x46
467 #define	  SMS_CC_TRANSFER_ABORT		 0x47
468 
469 #define	  SMS_SC_READY			 0xc0
470 #define	  SMS_SC_WRITE_START		 0xc1
471 #define	  SMS_SC_WRITE_NEXT		 0xc2
472 #define	  SMS_SC_WRITE_END		 0xc3
473 #define	  SMS_SC_READ_START		 0xc4
474 #define	  SMS_SC_READ_NEXT		 0xc5
475 #define	  SMS_SC_READ_END		 0xc6
476 
477 #define _SMIC_FLAG_REG			2
478 #define	  SMIC_BUSY			(1L << 0)
479 #define	  SMIC_SMS_ATN			(1L << 2)
480 #define	  SMIC_EVT_ATN			(1L << 3)
481 #define	  SMIC_SMI			(1L << 4)
482 #define	  SMIC_TX_DATA_RDY		(1L << 6)
483 #define	  SMIC_RX_DATA_RDY		(1L << 7)
484 
485 int	smic_wait(struct ipmi_softc *, u_int8_t, u_int8_t, const char *);
486 int	smic_write_cmd_data(struct ipmi_softc *, u_int8_t, const u_int8_t *);
487 int	smic_read_data(struct ipmi_softc *, u_int8_t *);
488 
489 int
490 smic_wait(struct ipmi_softc *sc, u_int8_t mask, u_int8_t val, const char *lbl)
491 {
492 	int v;
493 
494 	/* Wait for expected flag bits */
495 	v = bmc_io_wait(sc, _SMIC_FLAG_REG, mask, val, "smicwait");
496 	if (v < 0)
497 		return (-1);
498 
499 	/* Return current status */
500 	v = bmc_read(sc, _SMIC_CTRL_REG);
501 	dbg_printf(99, "smic_wait = %.2x\n", v);
502 	return (v);
503 }
504 
505 int
506 smic_write_cmd_data(struct ipmi_softc *sc, u_int8_t cmd, const u_int8_t *data)
507 {
508 	int	sts, v;
509 
510 	dbg_printf(50, "smic_wcd: %.2x %.2x\n", cmd, data ? *data : -1);
511 	sts = smic_wait(sc, SMIC_TX_DATA_RDY | SMIC_BUSY, SMIC_TX_DATA_RDY,
512 	    "smic_write_cmd_data ready");
513 	if (sts < 0)
514 		return (sts);
515 
516 	bmc_write(sc, _SMIC_CTRL_REG, cmd);
517 	if (data)
518 		bmc_write(sc, _SMIC_DATAOUT_REG, *data);
519 
520 	/* Toggle BUSY bit, then wait for busy bit to clear */
521 	v = bmc_read(sc, _SMIC_FLAG_REG);
522 	bmc_write(sc, _SMIC_FLAG_REG, v | SMIC_BUSY);
523 
524 	return (smic_wait(sc, SMIC_BUSY, 0, "smic_write_cmd_data busy"));
525 }
526 
527 int
528 smic_read_data(struct ipmi_softc *sc, u_int8_t *data)
529 {
530 	int sts;
531 
532 	sts = smic_wait(sc, SMIC_RX_DATA_RDY | SMIC_BUSY, SMIC_RX_DATA_RDY,
533 	    "smic_read_data");
534 	if (sts >= 0) {
535 		*data = bmc_read(sc, _SMIC_DATAIN_REG);
536 		dbg_printf(50, "smic_readdata: %.2x\n", *data);
537 	}
538 	return (sts);
539 }
540 
541 #define ErrStat(a,b) if (a) printf(b);
542 
543 int
544 smic_sendmsg(struct ipmi_softc *sc, int len, const u_int8_t *data)
545 {
546 	int sts, idx;
547 
548 	sts = smic_write_cmd_data(sc, SMS_CC_START_TRANSFER, &data[0]);
549 	ErrStat(sts != SMS_SC_WRITE_START, "wstart");
550 	for (idx = 1; idx < len - 1; idx++) {
551 		sts = smic_write_cmd_data(sc, SMS_CC_NEXT_TRANSFER,
552 		    &data[idx]);
553 		ErrStat(sts != SMS_SC_WRITE_NEXT, "write");
554 	}
555 	sts = smic_write_cmd_data(sc, SMS_CC_END_TRANSFER, &data[idx]);
556 	if (sts != SMS_SC_WRITE_END) {
557 		dbg_printf(50, "smic_sendmsg %d/%d = %.2x\n", idx, len, sts);
558 		return (-1);
559 	}
560 
561 	return (0);
562 }
563 
564 int
565 smic_recvmsg(struct ipmi_softc *sc, int maxlen, int *len, u_int8_t *data)
566 {
567 	int sts, idx;
568 
569 	*len = 0;
570 	sts = smic_wait(sc, SMIC_RX_DATA_RDY, SMIC_RX_DATA_RDY, "smic_recvmsg");
571 	if (sts < 0)
572 		return (-1);
573 
574 	sts = smic_write_cmd_data(sc, SMS_CC_START_RECEIVE, NULL);
575 	ErrStat(sts != SMS_SC_READ_START, "rstart");
576 	for (idx = 0;; ) {
577 		sts = smic_read_data(sc, &data[idx++]);
578 		if (sts != SMS_SC_READ_START && sts != SMS_SC_READ_NEXT)
579 			break;
580 		smic_write_cmd_data(sc, SMS_CC_NEXT_RECEIVE, NULL);
581 	}
582 	ErrStat(sts != SMS_SC_READ_END, "rend");
583 
584 	*len = idx;
585 
586 	sts = smic_write_cmd_data(sc, SMS_CC_END_RECEIVE, NULL);
587 	if (sts != SMS_SC_READY) {
588 		dbg_printf(50, "smic_recvmsg %d/%d = %.2x\n", idx, maxlen, sts);
589 		return (-1);
590 	}
591 
592 	return (0);
593 }
594 
595 int
596 smic_reset(struct ipmi_softc *sc)
597 {
598 	return (-1);
599 }
600 
601 int
602 smic_probe(struct ipmi_softc *sc)
603 {
604 	/* Flag register should not be 0xFF on a good system */
605 	if (bmc_read(sc, _SMIC_FLAG_REG) == 0xFF)
606 		return (-1);
607 
608 	return (0);
609 }
610 
611 /*
612  * KCS interface
613  */
614 #define _KCS_DATAIN_REGISTER		0
615 #define _KCS_DATAOUT_REGISTER		0
616 #define	  KCS_READ_NEXT			0x68
617 
618 #define _KCS_COMMAND_REGISTER		1
619 #define	  KCS_GET_STATUS		0x60
620 #define	  KCS_WRITE_START		0x61
621 #define	  KCS_WRITE_END			0x62
622 
623 #define _KCS_STATUS_REGISTER		1
624 #define	  KCS_OBF			(1L << 0)
625 #define	  KCS_IBF			(1L << 1)
626 #define	  KCS_SMS_ATN			(1L << 2)
627 #define	  KCS_CD			(1L << 3)
628 #define	  KCS_OEM1			(1L << 4)
629 #define	  KCS_OEM2			(1L << 5)
630 #define	  KCS_STATE_MASK		0xc0
631 #define	    KCS_IDLE_STATE		0x00
632 #define	    KCS_READ_STATE		0x40
633 #define	    KCS_WRITE_STATE		0x80
634 #define	    KCS_ERROR_STATE		0xC0
635 
636 int	kcs_wait(struct ipmi_softc *, u_int8_t, u_int8_t, const char *);
637 int	kcs_write_cmd(struct ipmi_softc *, u_int8_t);
638 int	kcs_write_data(struct ipmi_softc *, u_int8_t);
639 int	kcs_read_data(struct ipmi_softc *, u_int8_t *);
640 
641 int
642 kcs_wait(struct ipmi_softc *sc, u_int8_t mask, u_int8_t value, const char *lbl)
643 {
644 	int v;
645 
646 	v = bmc_io_wait(sc, _KCS_STATUS_REGISTER, mask, value, lbl);
647 	if (v < 0)
648 		return (v);
649 
650 	/* Check if output buffer full, read dummy byte	 */
651 	if ((v & (KCS_OBF | KCS_STATE_MASK)) == (KCS_OBF | KCS_WRITE_STATE))
652 		bmc_read(sc, _KCS_DATAIN_REGISTER);
653 
654 	/* Check for error state */
655 	if ((v & KCS_STATE_MASK) == KCS_ERROR_STATE) {
656 		bmc_write(sc, _KCS_COMMAND_REGISTER, KCS_GET_STATUS);
657 		while (bmc_read(sc, _KCS_STATUS_REGISTER) & KCS_IBF)
658 			;
659 		printf("%s: error code: %x\n", DEVNAME(sc),
660 		    bmc_read(sc, _KCS_DATAIN_REGISTER));
661 	}
662 
663 	return (v & KCS_STATE_MASK);
664 }
665 
666 int
667 kcs_write_cmd(struct ipmi_softc *sc, u_int8_t cmd)
668 {
669 	/* ASSERT: IBF and OBF are clear */
670 	dbg_printf(50, "kcswritecmd: %.2x\n", cmd);
671 	bmc_write(sc, _KCS_COMMAND_REGISTER, cmd);
672 
673 	return (kcs_wait(sc, KCS_IBF, 0, "write_cmd"));
674 }
675 
676 int
677 kcs_write_data(struct ipmi_softc *sc, u_int8_t data)
678 {
679 	/* ASSERT: IBF and OBF are clear */
680 	dbg_printf(50, "kcswritedata: %.2x\n", data);
681 	bmc_write(sc, _KCS_DATAOUT_REGISTER, data);
682 
683 	return (kcs_wait(sc, KCS_IBF, 0, "write_data"));
684 }
685 
686 int
687 kcs_read_data(struct ipmi_softc *sc, u_int8_t * data)
688 {
689 	int sts;
690 
691 	sts = kcs_wait(sc, KCS_IBF | KCS_OBF, KCS_OBF, "read_data");
692 	if (sts != KCS_READ_STATE)
693 		return (sts);
694 
695 	/* ASSERT: OBF is set read data, request next byte */
696 	*data = bmc_read(sc, _KCS_DATAIN_REGISTER);
697 	bmc_write(sc, _KCS_DATAOUT_REGISTER, KCS_READ_NEXT);
698 
699 	dbg_printf(50, "kcsreaddata: %.2x\n", *data);
700 
701 	return (sts);
702 }
703 
704 /* Exported KCS functions */
705 int
706 kcs_sendmsg(struct ipmi_softc *sc, int len, const u_int8_t * data)
707 {
708 	int idx, sts;
709 
710 	/* ASSERT: IBF is clear */
711 	dbg_dump(50, "kcs sendmsg", len, data);
712 	sts = kcs_write_cmd(sc, KCS_WRITE_START);
713 	for (idx = 0; idx < len; idx++) {
714 		if (idx == len - 1)
715 			sts = kcs_write_cmd(sc, KCS_WRITE_END);
716 
717 		if (sts != KCS_WRITE_STATE)
718 			break;
719 
720 		sts = kcs_write_data(sc, data[idx]);
721 	}
722 	if (sts != KCS_READ_STATE) {
723 		dbg_printf(1, "kcs sendmsg = %d/%d <%.2x>\n", idx, len, sts);
724 		dbg_dump(1, "kcs_sendmsg", len, data);
725 		return (-1);
726 	}
727 
728 	return (0);
729 }
730 
731 int
732 kcs_recvmsg(struct ipmi_softc *sc, int maxlen, int *rxlen, u_int8_t * data)
733 {
734 	int idx, sts;
735 
736 	for (idx = 0; idx < maxlen; idx++) {
737 		sts = kcs_read_data(sc, &data[idx]);
738 		if (sts != KCS_READ_STATE)
739 			break;
740 	}
741 	sts = kcs_wait(sc, KCS_IBF, 0, "recv");
742 	*rxlen = idx;
743 	if (sts != KCS_IDLE_STATE) {
744 		dbg_printf(1, "kcs read = %d/%d <%.2x>\n", idx, maxlen, sts);
745 		return (-1);
746 	}
747 
748 	dbg_dump(50, "kcs recvmsg", idx, data);
749 
750 	return (0);
751 }
752 
753 int
754 kcs_reset(struct ipmi_softc *sc)
755 {
756 	return (-1);
757 }
758 
759 int
760 kcs_probe(struct ipmi_softc *sc)
761 {
762 	u_int8_t v;
763 
764 	v = bmc_read(sc, _KCS_STATUS_REGISTER);
765 #if 0
766 	printf("kcs_probe: %2x\n", v);
767 	printf(" STS: %2x\n", v & KCS_STATE_MASK);
768 	printf(" ATN: %2x\n", v & KCS_SMS_ATN);
769 	printf(" C/D: %2x\n", v & KCS_CD);
770 	printf(" IBF: %2x\n", v & KCS_IBF);
771 	printf(" OBF: %2x\n", v & KCS_OBF);
772 #endif
773 	return (0);
774 }
775 
776 /*
777  * IPMI code
778  */
779 #define READ_SMS_BUFFER		0x37
780 #define WRITE_I2C		0x50
781 
782 #define GET_MESSAGE_CMD		0x33
783 #define SEND_MESSAGE_CMD	0x34
784 
785 #define IPMB_CHANNEL_NUMBER	0
786 
787 #define PUBLIC_BUS		0
788 
789 #define MIN_I2C_PACKET_SIZE	3
790 #define MIN_IMB_PACKET_SIZE	7	/* one byte for cksum */
791 
792 #define MIN_BTBMC_REQ_SIZE	4
793 #define MIN_BTBMC_RSP_SIZE	5
794 #define MIN_BMC_REQ_SIZE	2
795 #define MIN_BMC_RSP_SIZE	3
796 
797 #define BMC_SA			0x20	/* BMC/ESM3 */
798 #define FPC_SA			0x22	/* front panel */
799 #define BP_SA			0xC0	/* Primary Backplane */
800 #define BP2_SA			0xC2	/* Secondary Backplane */
801 #define PBP_SA			0xC4	/* Peripheral Backplane */
802 #define DRAC_SA			0x28	/* DRAC-III */
803 #define DRAC3_SA		0x30	/* DRAC-III */
804 #define BMC_LUN			0
805 #define SMS_LUN			2
806 
807 struct ipmi_request {
808 	u_int8_t	rsSa;
809 	u_int8_t	rsLun;
810 	u_int8_t	netFn;
811 	u_int8_t	cmd;
812 	u_int8_t	data_len;
813 	u_int8_t	*data;
814 };
815 
816 struct ipmi_response {
817 	u_int8_t	cCode;
818 	u_int8_t	data_len;
819 	u_int8_t	*data;
820 };
821 
822 struct ipmi_bmc_request {
823 	u_int8_t	bmc_nfLn;
824 	u_int8_t	bmc_cmd;
825 	u_int8_t	bmc_data_len;
826 	u_int8_t	bmc_data[1];
827 };
828 
829 struct ipmi_bmc_response {
830 	u_int8_t	bmc_nfLn;
831 	u_int8_t	bmc_cmd;
832 	u_int8_t	bmc_cCode;
833 	u_int8_t	bmc_data_len;
834 	u_int8_t	bmc_data[1];
835 };
836 
837 struct cfattach ipmi_ca = {
838 	sizeof(struct ipmi_softc), ipmi_match, ipmi_attach
839 };
840 
841 struct cfdriver ipmi_cd = {
842 	NULL, "ipmi", DV_DULL
843 };
844 
845 /* Scan memory for signature */
846 void *
847 scan_sig(long start, long end, int skip, int len, const void *data)
848 {
849 	void *va;
850 
851 	while (start < end) {
852 		va = ISA_HOLE_VADDR(start);
853 		if (memcmp(va, data, len) == 0)
854 			return (va);
855 
856 		start += skip;
857 	}
858 
859 	return (NULL);
860 }
861 
862 void
863 dumpb(const char *lbl, int len, const u_int8_t *data)
864 {
865 	int idx;
866 
867 	printf("%s: ", lbl);
868 	for (idx = 0; idx < len; idx++)
869 		printf("%.2x ", data[idx]);
870 
871 	printf("\n");
872 }
873 
874 void
875 ipmi_smbios_probe(struct smbios_ipmi *pipmi, struct ipmi_attach_args *ia)
876 {
877 
878 	dbg_printf(1, "ipmi_smbios_probe: %02x %02x %02x %02x %08llx %02x "
879 	    "%02x\n",
880 	    pipmi->smipmi_if_type,
881 	    pipmi->smipmi_if_rev,
882 	    pipmi->smipmi_i2c_address,
883 	    pipmi->smipmi_nvram_address,
884 	    pipmi->smipmi_base_address,
885 	    pipmi->smipmi_base_flags,
886 	    pipmi->smipmi_irq);
887 
888 	ia->iaa_if_type = pipmi->smipmi_if_type;
889 	ia->iaa_if_rev = pipmi->smipmi_if_rev;
890 	ia->iaa_if_irq = (pipmi->smipmi_base_flags & SMIPMI_FLAG_IRQEN) ?
891 	    pipmi->smipmi_irq : -1;
892 	ia->iaa_if_irqlvl = (pipmi->smipmi_base_flags & SMIPMI_FLAG_IRQLVL) ?
893 	    IST_LEVEL : IST_EDGE;
894 
895 	switch (SMIPMI_FLAG_IFSPACING(pipmi->smipmi_base_flags)) {
896 	case IPMI_IOSPACING_BYTE:
897 		ia->iaa_if_iospacing = 1;
898 		break;
899 
900 	case IPMI_IOSPACING_DWORD:
901 		ia->iaa_if_iospacing = 4;
902 		break;
903 
904 	case IPMI_IOSPACING_WORD:
905 		ia->iaa_if_iospacing = 2;
906 		break;
907 
908 	default:
909 		ia->iaa_if_iospacing = 1;
910 		printf("ipmi: unknown register spacing\n");
911 	}
912 
913 	/* Calculate base address (PCI BAR format) */
914 	if (pipmi->smipmi_base_address & 0x1) {
915 		ia->iaa_if_iotype = 'i';
916 		ia->iaa_if_iobase = pipmi->smipmi_base_address & ~0x1;
917 	} else {
918 		ia->iaa_if_iotype = 'm';
919 		ia->iaa_if_iobase = pipmi->smipmi_base_address & ~0xF;
920 	}
921 	if (pipmi->smipmi_base_flags & SMIPMI_FLAG_ODDOFFSET)
922 		ia->iaa_if_iobase++;
923 
924 	if (pipmi->smipmi_base_flags == 0x7f) {
925 		/* IBM 325 eServer workaround */
926 		ia->iaa_if_iospacing = 1;
927 		ia->iaa_if_iobase = pipmi->smipmi_base_address;
928 		ia->iaa_if_iotype = 'i';
929 		return;
930 	}
931 }
932 
933 /*
934  * bt_buildmsg builds an IPMI message from a nfLun, cmd, and data
935  * This is used by BT protocol
936  *
937  * Returns a buffer to an allocated message, txlen contains length
938  *   of allocated message
939  */
940 void *
941 bt_buildmsg(struct ipmi_softc *sc, int nfLun, int cmd, int len,
942     const void *data, int *txlen)
943 {
944 	u_int8_t *buf;
945 
946 	/* Block transfer needs 4 extra bytes: length/netfn/seq/cmd + data */
947 	*txlen = len + 4;
948 	buf = malloc(*txlen, M_DEVBUF, M_NOWAIT);
949 	if (buf == NULL)
950 		return (NULL);
951 
952 	buf[IPMI_BTMSG_LEN] = len + 3;
953 	buf[IPMI_BTMSG_NFLN] = nfLun;
954 	buf[IPMI_BTMSG_SEQ] = sc->sc_btseq++;
955 	buf[IPMI_BTMSG_CMD] = cmd;
956 	if (len && data)
957 		memcpy(buf + IPMI_BTMSG_DATASND, data, len);
958 
959 	return (buf);
960 }
961 
962 /*
963  * cmn_buildmsg builds an IPMI message from a nfLun, cmd, and data
964  * This is used by both SMIC and KCS protocols
965  *
966  * Returns a buffer to an allocated message, txlen contains length
967  *   of allocated message
968  */
969 void *
970 cmn_buildmsg(struct ipmi_softc *sc, int nfLun, int cmd, int len,
971     const void *data, int *txlen)
972 {
973 	u_int8_t *buf;
974 
975 	/* Common needs two extra bytes: nfLun/cmd + data */
976 	*txlen = len + 2;
977 	buf = malloc(*txlen, M_DEVBUF, M_NOWAIT);
978 	if (buf == NULL)
979 		return (NULL);
980 
981 	buf[IPMI_MSG_NFLN] = nfLun;
982 	buf[IPMI_MSG_CMD] = cmd;
983 	if (len && data)
984 		memcpy(buf + IPMI_MSG_DATASND, data, len);
985 
986 	return (buf);
987 }
988 
989 /* Send an IPMI command */
990 int
991 ipmi_sendcmd(struct ipmi_softc *sc, int rssa, int rslun, int netfn, int cmd,
992     int txlen, const void *data)
993 {
994 	u_int8_t	*buf;
995 	int		rc = -1;
996 
997 	dbg_printf(50, "ipmi_sendcmd: rssa=%.2x nfln=%.2x cmd=%.2x len=%.2x\n",
998 	    rssa, NETFN_LUN(netfn, rslun), cmd, txlen);
999 	dbg_dump(10, " send", txlen, data);
1000 	if (rssa != BMC_SA) {
1001 #if 0
1002 		buf = sc->sc_if->buildmsg(sc, NETFN_LUN(APP_NETFN, BMC_LUN),
1003 		    APP_SEND_MESSAGE, 7 + txlen, NULL, &txlen);
1004 		pI2C->bus = (sc->if_ver == 0x09) ?
1005 		    PUBLIC_BUS :
1006 		    IPMB_CHANNEL_NUMBER;
1007 
1008 		imbreq->rsSa = rssa;
1009 		imbreq->nfLn = NETFN_LUN(netfn, rslun);
1010 		imbreq->cSum1 = -(imbreq->rsSa + imbreq->nfLn);
1011 		imbreq->rqSa = BMC_SA;
1012 		imbreq->seqLn = NETFN_LUN(sc->imb_seq++, SMS_LUN);
1013 		imbreq->cmd = cmd;
1014 		if (txlen)
1015 			memcpy(imbreq->data, data, txlen);
1016 		/* Set message checksum */
1017 		imbreq->data[txlen] = cksum8(&imbreq->rqSa, txlen + 3);
1018 #endif
1019 		goto done;
1020 	} else
1021 		buf = sc->sc_if->buildmsg(sc, NETFN_LUN(netfn, rslun), cmd,
1022 		    txlen, data, &txlen);
1023 
1024 	if (buf == NULL) {
1025 		printf("%s: sendcmd malloc fails\n", DEVNAME(sc));
1026 		goto done;
1027 	}
1028 	rc = sc->sc_if->sendmsg(sc, txlen, buf);
1029 	free(buf, M_DEVBUF, 0);
1030 
1031 	ipmi_delay(sc, 5); /* give bmc chance to digest command */
1032 
1033 done:
1034 	return (rc);
1035 }
1036 
1037 int
1038 ipmi_recvcmd(struct ipmi_softc *sc, int maxlen, int *rxlen, void *data)
1039 {
1040 	u_int8_t	*buf, rc = 0;
1041 	int		rawlen;
1042 
1043 	/* Need three extra bytes: netfn/cmd/ccode + data */
1044 	buf = malloc(maxlen + 3, M_DEVBUF, M_NOWAIT);
1045 	if (buf == NULL) {
1046 		printf("%s: ipmi_recvcmd: malloc fails\n", DEVNAME(sc));
1047 		return (-1);
1048 	}
1049 	/* Receive message from interface, copy out result data */
1050 	if (sc->sc_if->recvmsg(sc, maxlen + 3, &rawlen, buf))
1051 		return (-1);
1052 
1053 	*rxlen = rawlen - IPMI_MSG_DATARCV;
1054 	if (*rxlen > 0 && data)
1055 		memcpy(data, buf + IPMI_MSG_DATARCV, *rxlen);
1056 
1057 	rc = buf[IPMI_MSG_CCODE];
1058 #ifdef IPMI_DEBUG
1059 	if (rc != 0)
1060 		dbg_printf(1, "ipmi_recvmsg: nfln=%.2x cmd=%.2x err=%.2x\n",
1061 		    buf[IPMI_MSG_NFLN], buf[IPMI_MSG_CMD], buf[IPMI_MSG_CCODE]);
1062 #endif
1063 
1064 	dbg_printf(50, "ipmi_recvcmd: nfln=%.2x cmd=%.2x err=%.2x len=%.2x\n",
1065 	    buf[IPMI_MSG_NFLN], buf[IPMI_MSG_CMD], buf[IPMI_MSG_CCODE],
1066 	    *rxlen);
1067 	dbg_dump(10, " recv", *rxlen, data);
1068 
1069 	free(buf, M_DEVBUF, 0);
1070 
1071 	ipmi_delay(sc, 5); /* give bmc chance to digest command */
1072 
1073 	return (rc);
1074 }
1075 
1076 void
1077 ipmi_delay(struct ipmi_softc *sc, int period)
1078 {
1079 	/* period is in 10 ms increments */
1080 	if (cold)
1081 		delay(period * 10000);
1082 	else
1083 		while (tsleep(sc, PWAIT, "ipmicmd", period) != EWOULDBLOCK);
1084 }
1085 
1086 /* Read a partial SDR entry */
1087 int
1088 get_sdr_partial(struct ipmi_softc *sc, u_int16_t recordId, u_int16_t reserveId,
1089     u_int8_t offset, u_int8_t length, void *buffer, u_int16_t *nxtRecordId)
1090 {
1091 	u_int8_t	cmd[8 + 255];	/* 8 + max of length */
1092 	int		len;
1093 
1094 	((u_int16_t *) cmd)[0] = reserveId;
1095 	((u_int16_t *) cmd)[1] = recordId;
1096 	cmd[4] = offset;
1097 	cmd[5] = length;
1098 	if (ipmi_sendcmd(sc, BMC_SA, 0, STORAGE_NETFN, STORAGE_GET_SDR, 6,
1099 	    cmd)) {
1100 		printf("%s: sendcmd fails\n", DEVNAME(sc));
1101 		return (-1);
1102 	}
1103 	if (ipmi_recvcmd(sc, 8 + length, &len, cmd)) {
1104 		printf("%s: getSdrPartial: recvcmd fails\n", DEVNAME(sc));
1105 		return (-1);
1106 	}
1107 	if (nxtRecordId)
1108 		*nxtRecordId = *(uint16_t *) cmd;
1109 	memcpy(buffer, cmd + 2, len - 2);
1110 
1111 	return (0);
1112 }
1113 
1114 int maxsdrlen = 0x10;
1115 
1116 /* Read an entire SDR; pass to add sensor */
1117 int
1118 get_sdr(struct ipmi_softc *sc, u_int16_t recid, u_int16_t *nxtrec)
1119 {
1120 	u_int16_t	resid = 0;
1121 	int		len, sdrlen, offset;
1122 	u_int8_t	*psdr;
1123 	struct sdrhdr	shdr;
1124 
1125 	/* Reserve SDR */
1126 	if (ipmi_sendcmd(sc, BMC_SA, 0, STORAGE_NETFN, STORAGE_RESERVE_SDR,
1127 	    0, NULL)) {
1128 		printf("%s: reserve send fails\n", DEVNAME(sc));
1129 		return (1);
1130 	}
1131 	if (ipmi_recvcmd(sc, sizeof(resid), &len, &resid)) {
1132 		printf("%s: reserve recv fails\n", DEVNAME(sc));
1133 		return (1);
1134 	}
1135 	/* Get SDR Header */
1136 	if (get_sdr_partial(sc, recid, resid, 0, sizeof shdr, &shdr, nxtrec)) {
1137 		printf("%s: get header fails\n", DEVNAME(sc));
1138 		return (1);
1139 	}
1140 	/* Allocate space for entire SDR Length of SDR in header does not
1141 	 * include header length */
1142 	sdrlen = sizeof(shdr) + shdr.record_length;
1143 	psdr = malloc(sdrlen, M_DEVBUF, M_NOWAIT);
1144 	if (psdr == NULL)
1145 		return (1);
1146 
1147 	memcpy(psdr, &shdr, sizeof(shdr));
1148 
1149 	/* Read SDR Data maxsdrlen bytes at a time */
1150 	for (offset = sizeof(shdr); offset < sdrlen; offset += maxsdrlen) {
1151 		len = sdrlen - offset;
1152 		if (len > maxsdrlen)
1153 			len = maxsdrlen;
1154 
1155 		if (get_sdr_partial(sc, recid, resid, offset, len,
1156 		    psdr + offset, NULL)) {
1157 			printf("%s: get chunk: %d,%d fails\n", DEVNAME(sc),
1158 			    offset, len);
1159 			free(psdr, M_DEVBUF, 0);
1160 			return (1);
1161 		}
1162 	}
1163 
1164 	/* Add SDR to sensor list, if not wanted, free buffer */
1165 	if (add_sdr_sensor(sc, psdr) == 0)
1166 		free(psdr, M_DEVBUF, 0);
1167 
1168 	return (0);
1169 }
1170 
1171 int
1172 getbits(u_int8_t *bytes, int bitpos, int bitlen)
1173 {
1174 	int	v;
1175 	int	mask;
1176 
1177 	bitpos += bitlen - 1;
1178 	for (v = 0; bitlen--;) {
1179 		v <<= 1;
1180 		mask = 1L << (bitpos & 7);
1181 		if (bytes[bitpos >> 3] & mask)
1182 			v |= 1;
1183 		bitpos--;
1184 	}
1185 
1186 	return (v);
1187 }
1188 
1189 /* Decode IPMI sensor name */
1190 void
1191 ipmi_sensor_name(char *name, int len, u_int8_t typelen, u_int8_t *bits)
1192 {
1193 	int	i, slen;
1194 	char	bcdplus[] = "0123456789 -.:,_";
1195 
1196 	slen = typelen & 0x1F;
1197 	switch (typelen >> 6) {
1198 	case IPMI_NAME_UNICODE:
1199 		//unicode
1200 		break;
1201 
1202 	case IPMI_NAME_BCDPLUS:
1203 		/* Characters are encoded in 4-bit BCDPLUS */
1204 		if (len < slen * 2 + 1)
1205 			slen = (len >> 1) - 1;
1206 		for (i = 0; i < slen; i++) {
1207 			*(name++) = bcdplus[bits[i] >> 4];
1208 			*(name++) = bcdplus[bits[i] & 0xF];
1209 		}
1210 		break;
1211 
1212 	case IPMI_NAME_ASCII6BIT:
1213 		/* Characters are encoded in 6-bit ASCII
1214 		 *   0x00 - 0x3F maps to 0x20 - 0x5F */
1215 		/* XXX: need to calculate max len: slen = 3/4 * len */
1216 		if (len < slen + 1)
1217 			slen = len - 1;
1218 		for (i = 0; i < slen * 8; i += 6)
1219 			*(name++) = getbits(bits, i, 6) + ' ';
1220 		break;
1221 
1222 	case IPMI_NAME_ASCII8BIT:
1223 		/* Characters are 8-bit ascii */
1224 		if (len < slen + 1)
1225 			slen = len - 1;
1226 		while (slen--)
1227 			*(name++) = *(bits++);
1228 		break;
1229 	}
1230 	*name = 0;
1231 }
1232 
1233 /* Calculate val * 10^exp */
1234 long
1235 ipow(long val, int exp)
1236 {
1237 	while (exp > 0) {
1238 		val *= 10;
1239 		exp--;
1240 	}
1241 
1242 	while (exp < 0) {
1243 		val /= 10;
1244 		exp++;
1245 	}
1246 
1247 	return (val);
1248 }
1249 
1250 /* Sign extend a n-bit value */
1251 long
1252 signextend(unsigned long val, int bits)
1253 {
1254 	long msk = (1L << (bits-1))-1;
1255 
1256 	return (-(val & ~msk) | val);
1257 }
1258 
1259 /* Convert IPMI reading from sensor factors */
1260 long
1261 ipmi_convert(u_int8_t v, struct sdrtype1 *s1, long adj)
1262 {
1263 	short	M, B;
1264 	char	K1, K2;
1265 	long	val;
1266 
1267 	/* Calculate linear reading variables */
1268 	M  = signextend((((short)(s1->m_tolerance & 0xC0)) << 2) + s1->m, 10);
1269 	B  = signextend((((short)(s1->b_accuracy & 0xC0)) << 2) + s1->b, 10);
1270 	K1 = signextend(s1->rbexp & 0xF, 4);
1271 	K2 = signextend(s1->rbexp >> 4, 4);
1272 
1273 	/* Calculate sensor reading:
1274 	 *  y = L((M * v + (B * 10^K1)) * 10^(K2+adj)
1275 	 *
1276 	 * This commutes out to:
1277 	 *  y = L(M*v * 10^(K2+adj) + B * 10^(K1+K2+adj)); */
1278 	val = ipow(M * v, K2 + adj) + ipow(B, K1 + K2 + adj);
1279 
1280 	/* Linearization function: y = f(x) 0 : y = x 1 : y = ln(x) 2 : y =
1281 	 * log10(x) 3 : y = log2(x) 4 : y = e^x 5 : y = 10^x 6 : y = 2^x 7 : y
1282 	 * = 1/x 8 : y = x^2 9 : y = x^3 10 : y = square root(x) 11 : y = cube
1283 	 * root(x) */
1284 	return (val);
1285 }
1286 
1287 int
1288 ipmi_test_threshold(u_int8_t v, u_int8_t valid, u_int8_t hi, u_int8_t lo,
1289     int sign)
1290 {
1291 	dbg_printf(10, "thresh: %.2x %.2x %.2x %d %d\n", v, lo, hi,valid, sign);
1292 	if (sign)
1293 		return ((valid & 1 && lo != 0x00 && (int8_t)v <= (int8_t)lo) ||
1294 		    (valid & 8 && hi != 0xFF && (int8_t)v >= (int8_t)hi));
1295 
1296 	return ((valid & 1 && lo != 0x00 && v <= lo) ||
1297 	    (valid & 8 && hi != 0xFF && v >= hi));
1298 }
1299 
1300 int
1301 ipmi_sensor_status(struct ipmi_softc *sc, struct ipmi_sensor *psensor,
1302     u_int8_t *reading)
1303 {
1304 	u_int8_t	data[32];
1305 	struct sdrtype1	*s1 = (struct sdrtype1 *)psensor->i_sdr;
1306 	int		rxlen, etype;
1307 	int		sign = s1->units1 >> 7 & 1;
1308 
1309 	/* Get reading of sensor */
1310 	switch (psensor->i_sensor.type) {
1311 	case SENSOR_TEMP:
1312 		psensor->i_sensor.value = ipmi_convert(reading[0], s1, 6);
1313 		psensor->i_sensor.value += 273150000;
1314 		break;
1315 
1316 	case SENSOR_VOLTS_DC:
1317 		psensor->i_sensor.value = ipmi_convert(reading[0], s1, 6);
1318 		break;
1319 
1320 	case SENSOR_FANRPM:
1321 		psensor->i_sensor.value = ipmi_convert(reading[0], s1, 0);
1322 		if (((s1->units1>>3)&0x7) == 0x3)
1323 			psensor->i_sensor.value *= 60; // RPS -> RPM
1324 		break;
1325 	default:
1326 		break;
1327 	}
1328 
1329 	/* Return Sensor Status */
1330 	etype = (psensor->etype << 8) + psensor->stype;
1331 	switch (etype) {
1332 	case IPMI_SENSOR_TYPE_TEMP:
1333 	case IPMI_SENSOR_TYPE_VOLT:
1334 	case IPMI_SENSOR_TYPE_FAN:
1335 		data[0] = psensor->i_num;
1336 		if (ipmi_sendcmd(sc, s1->owner_id, s1->owner_lun,
1337 		    SE_NETFN, SE_GET_SENSOR_THRESHOLD, 1, data) ||
1338 		    ipmi_recvcmd(sc, sizeof(data), &rxlen, data))
1339 			return (SENSOR_S_UNKNOWN);
1340 
1341 		dbg_printf(25, "recvdata: %.2x %.2x %.2x %.2x %.2x %.2x %.2x\n",
1342 		    data[0], data[1], data[2], data[3], data[4], data[5],
1343 		    data[6]);
1344 
1345 		if (ipmi_test_threshold(*reading, data[0] >> 2 ,
1346 		    data[6], data[3], sign))
1347 			return (SENSOR_S_CRIT);
1348 
1349 		if (ipmi_test_threshold(*reading, data[0] >> 1,
1350 		    data[5], data[2], sign))
1351 			return (SENSOR_S_CRIT);
1352 
1353 		if (ipmi_test_threshold(*reading, data[0] ,
1354 		    data[4], data[1], sign))
1355 			return (SENSOR_S_WARN);
1356 
1357 		break;
1358 
1359 	case IPMI_SENSOR_TYPE_INTRUSION:
1360 		psensor->i_sensor.value = (reading[2] & 1) ? 1 : 0;
1361 		if (reading[2] & 0x1)
1362 			return (SENSOR_S_CRIT);
1363 		break;
1364 
1365 	case IPMI_SENSOR_TYPE_PWRSUPPLY:
1366 		/* Reading: 1 = present+powered, 0 = otherwise */
1367 		psensor->i_sensor.value = (reading[2] & 1) ? 1 : 0;
1368 		if (reading[2] & 0x10) {
1369 			/* XXX: Need sysctl type for Power Supply types
1370 			 *   ok: power supply installed && powered
1371 			 * warn: power supply installed && !powered
1372 			 * crit: power supply !installed
1373 			 */
1374 			return (SENSOR_S_CRIT);
1375 		}
1376 		if (reading[2] & 0x08) {
1377 			/* Power supply AC lost */
1378 			return (SENSOR_S_WARN);
1379 		}
1380 		break;
1381 	}
1382 
1383 	return (SENSOR_S_OK);
1384 }
1385 
1386 int
1387 read_sensor(struct ipmi_softc *sc, struct ipmi_sensor *psensor)
1388 {
1389 	struct sdrtype1	*s1 = (struct sdrtype1 *) psensor->i_sdr;
1390 	u_int8_t	data[8];
1391 	int		rxlen, rv = -1;
1392 
1393 	if (!cold)
1394 		rw_enter_write(&sc->sc_lock);
1395 
1396 	memset(data, 0, sizeof(data));
1397 	data[0] = psensor->i_num;
1398 	if (ipmi_sendcmd(sc, s1->owner_id, s1->owner_lun, SE_NETFN,
1399 	    SE_GET_SENSOR_READING, 1, data))
1400 		goto done;
1401 
1402 	if (ipmi_recvcmd(sc, sizeof(data), &rxlen, data))
1403 		goto done;
1404 
1405 	dbg_printf(10, "values=%.2x %.2x %.2x %.2x %s\n",
1406 	    data[0],data[1],data[2],data[3], psensor->i_sensor.desc);
1407 	psensor->i_sensor.flags &= ~SENSOR_FINVALID;
1408 	if (data[1] & IPMI_INVALID_SENSOR) {
1409 		/* Check if sensor is valid */
1410 		psensor->i_sensor.flags |= SENSOR_FINVALID;
1411 	}
1412 	psensor->i_sensor.status = ipmi_sensor_status(sc, psensor, data);
1413 	rv = 0;
1414 done:
1415 	if (!cold)
1416 		rw_exit_write(&sc->sc_lock);
1417 	return (rv);
1418 }
1419 
1420 int
1421 ipmi_sensor_type(int type, int ext_type, int entity)
1422 {
1423 	switch (ext_type << 8L | type) {
1424 	case IPMI_SENSOR_TYPE_TEMP:
1425 		return (SENSOR_TEMP);
1426 
1427 	case IPMI_SENSOR_TYPE_VOLT:
1428 		return (SENSOR_VOLTS_DC);
1429 
1430 	case IPMI_SENSOR_TYPE_FAN:
1431 		return (SENSOR_FANRPM);
1432 
1433 	case IPMI_SENSOR_TYPE_PWRSUPPLY:
1434 		if (entity == IPMI_ENTITY_PWRSUPPLY)
1435 			return (SENSOR_INDICATOR);
1436 		break;
1437 
1438 	case IPMI_SENSOR_TYPE_INTRUSION:
1439 		return (SENSOR_INDICATOR);
1440 	}
1441 
1442 	return (-1);
1443 }
1444 
1445 /* Add Sensor to BSD Sysctl interface */
1446 int
1447 add_sdr_sensor(struct ipmi_softc *sc, u_int8_t *psdr)
1448 {
1449 	int			rc;
1450 	struct sdrtype1		*s1 = (struct sdrtype1 *)psdr;
1451 	struct sdrtype2		*s2 = (struct sdrtype2 *)psdr;
1452 	char			name[64];
1453 
1454 	switch (s1->sdrhdr.record_type) {
1455 	case IPMI_SDR_TYPEFULL:
1456 		ipmi_sensor_name(name, sizeof(name), s1->typelen, s1->name);
1457 		rc = add_child_sensors(sc, psdr, 1, s1->sensor_num,
1458 		    s1->sensor_type, s1->event_code, 0, s1->entity_id, name);
1459 		break;
1460 
1461 	case IPMI_SDR_TYPECOMPACT:
1462 		ipmi_sensor_name(name, sizeof(name), s2->typelen, s2->name);
1463 		rc = add_child_sensors(sc, psdr, s2->share1 & 0xF,
1464 		    s2->sensor_num, s2->sensor_type, s2->event_code,
1465 		    s2->share2 & 0x7F, s2->entity_id, name);
1466 		break;
1467 
1468 	default:
1469 		return (0);
1470 	}
1471 
1472 	return rc;
1473 }
1474 
1475 int
1476 add_child_sensors(struct ipmi_softc *sc, u_int8_t *psdr, int count,
1477     int sensor_num, int sensor_type, int ext_type, int sensor_base,
1478     int entity, const char *name)
1479 {
1480 	int			typ, idx;
1481 	struct ipmi_sensor	*psensor;
1482 #ifdef IPMI_DEBUG
1483 	struct sdrtype1		*s1 = (struct sdrtype1 *)psdr;
1484 #endif
1485 
1486 	typ = ipmi_sensor_type(sensor_type, ext_type, entity);
1487 	if (typ == -1) {
1488 		dbg_printf(5, "Unknown sensor type:%.2x et:%.2x sn:%.2x "
1489 		    "name:%s\n", sensor_type, ext_type, sensor_num, name);
1490 		return 0;
1491 	}
1492 	for (idx = 0; idx < count; idx++) {
1493 		psensor = malloc(sizeof(*psensor), M_DEVBUF, M_NOWAIT | M_ZERO);
1494 		if (psensor == NULL)
1495 			break;
1496 
1497 		/* Initialize BSD Sensor info */
1498 		psensor->i_sdr = psdr;
1499 		psensor->i_num = sensor_num + idx;
1500 		psensor->stype = sensor_type;
1501 		psensor->etype = ext_type;
1502 		psensor->i_sensor.type = typ;
1503 		if (count > 1)
1504 			snprintf(psensor->i_sensor.desc,
1505 			    sizeof(psensor->i_sensor.desc),
1506 			    "%s - %d", name, sensor_base + idx);
1507 		else
1508 			strlcpy(psensor->i_sensor.desc, name,
1509 			    sizeof(psensor->i_sensor.desc));
1510 
1511 		dbg_printf(5, "add sensor:%.4x %.2x:%d ent:%.2x:%.2x %s\n",
1512 		    s1->sdrhdr.record_id, s1->sensor_type,
1513 		    typ, s1->entity_id, s1->entity_instance,
1514 		    psensor->i_sensor.desc);
1515 		if (read_sensor(sc, psensor) == 0) {
1516 			SLIST_INSERT_HEAD(&ipmi_sensor_list, psensor, list);
1517 			sensor_attach(&sc->sc_sensordev, &psensor->i_sensor);
1518 			dbg_printf(5, "	 reading: %lld [%s]\n",
1519 			    psensor->i_sensor.value,
1520 			    psensor->i_sensor.desc);
1521 		}
1522 	}
1523 
1524 	return (1);
1525 }
1526 
1527 /* Interrupt handler */
1528 int
1529 ipmi_intr(void *arg)
1530 {
1531 	struct ipmi_softc	*sc = (struct ipmi_softc *)arg;
1532 	int			v;
1533 
1534 	v = bmc_read(sc, _KCS_STATUS_REGISTER);
1535 	if (v & KCS_OBF)
1536 		++ipmi_nintr;
1537 
1538 	return (0);
1539 }
1540 
1541 /* Handle IPMI Timer - reread sensor values */
1542 void
1543 ipmi_refresh_sensors(struct ipmi_softc *sc)
1544 {
1545 	if (!ipmi_poll)
1546 		return;
1547 
1548 	if (SLIST_EMPTY(&ipmi_sensor_list))
1549 		return;
1550 
1551 	sc->current_sensor = SLIST_NEXT(sc->current_sensor, list);
1552 	if (sc->current_sensor == NULL)
1553 		sc->current_sensor = SLIST_FIRST(&ipmi_sensor_list);
1554 
1555 	if (read_sensor(sc, sc->current_sensor)) {
1556 		dbg_printf(1, "%s: error reading: %s\n", DEVNAME(sc),
1557 		    sc->current_sensor->i_sensor.desc);
1558 		return;
1559 	}
1560 }
1561 
1562 int
1563 ipmi_map_regs(struct ipmi_softc *sc, struct ipmi_attach_args *ia)
1564 {
1565 	sc->sc_if = ipmi_get_if(ia->iaa_if_type);
1566 	if (sc->sc_if == NULL)
1567 		return (-1);
1568 
1569 	if (ia->iaa_if_iotype == 'i')
1570 		sc->sc_iot = ia->iaa_iot;
1571 	else
1572 		sc->sc_iot = ia->iaa_memt;
1573 
1574 	sc->sc_if_rev = ia->iaa_if_rev;
1575 	sc->sc_if_iospacing = ia->iaa_if_iospacing;
1576 	if (bus_space_map(sc->sc_iot, ia->iaa_if_iobase,
1577 	    sc->sc_if->nregs * sc->sc_if_iospacing,
1578 	    0, &sc->sc_ioh)) {
1579 		printf("%s: bus_space_map(%lx %x %x 0 %p) failed\n",
1580 		    DEVNAME(sc),
1581 		    (unsigned long)sc->sc_iot, ia->iaa_if_iobase,
1582 		    sc->sc_if->nregs * sc->sc_if_iospacing, &sc->sc_ioh);
1583 		return (-1);
1584 	}
1585 #if 0
1586 	if (iaa->if_if_irq != -1)
1587 		sc->ih = isa_intr_establish(-1, iaa->if_if_irq,
1588 		    iaa->if_irqlvl, IPL_BIO, ipmi_intr, sc, DEVNAME(sc));
1589 #endif
1590 	return (0);
1591 }
1592 
1593 void
1594 ipmi_unmap_regs(struct ipmi_softc *sc)
1595 {
1596 	bus_space_unmap(sc->sc_iot, sc->sc_ioh,
1597 	    sc->sc_if->nregs * sc->sc_if_iospacing);
1598 }
1599 
1600 void
1601 ipmi_poll_thread(void *arg)
1602 {
1603 	struct ipmi_thread	*thread = arg;
1604 	struct ipmi_softc 	*sc = thread->sc;
1605 	u_int16_t		rec;
1606 
1607 	/* Scan SDRs, add sensors */
1608 	for (rec = 0; rec != 0xFFFF;) {
1609 		if (get_sdr(sc, rec, &rec)) {
1610 			ipmi_unmap_regs(sc);
1611 			printf("%s: no SDRs IPMI disabled\n", DEVNAME(sc));
1612 			goto done;
1613 		}
1614 		while (tsleep(sc, PUSER + 1, "ipmirun", 1) != EWOULDBLOCK);
1615 	}
1616 
1617 	/* initialize sensor list for thread */
1618 	if (SLIST_EMPTY(&ipmi_sensor_list))
1619 		goto done;
1620 	else
1621 		sc->current_sensor = SLIST_FIRST(&ipmi_sensor_list);
1622 
1623 	strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
1624 	    sizeof(sc->sc_sensordev.xname));
1625 	sensordev_install(&sc->sc_sensordev);
1626 
1627 	while (thread->running) {
1628 		ipmi_refresh_sensors(sc);
1629 		tsleep(thread, PWAIT, "ipmi_poll", SENSOR_REFRESH_RATE);
1630 	}
1631 
1632 done:
1633 	kthread_exit(0);
1634 }
1635 
1636 void
1637 ipmi_create_thread(void *arg)
1638 {
1639 	struct ipmi_softc	*sc = arg;
1640 
1641 	if (kthread_create(ipmi_poll_thread, sc->sc_thread, NULL,
1642 	    DEVNAME(sc)) != 0) {
1643 		printf("%s: unable to create run thread, ipmi disabled\n",
1644 		    DEVNAME(sc));
1645 		return;
1646 	}
1647 }
1648 
1649 int
1650 ipmi_probe(void *aux)
1651 {
1652 	struct ipmi_attach_args *ia = aux;
1653 	struct dmd_ipmi *pipmi;
1654 	struct smbtable tbl;
1655 
1656 	tbl.cookie = 0;
1657 	if (smbios_find_table(SMBIOS_TYPE_IPMIDEV, &tbl))
1658 		ipmi_smbios_probe(tbl.tblhdr, ia);
1659 	else {
1660 		pipmi = (struct dmd_ipmi *)scan_sig(0xC0000L, 0xFFFFFL, 16, 4,
1661 		    "IPMI");
1662 		/* XXX hack to find Dell PowerEdge 8450 */
1663 		if (pipmi == NULL) {
1664 			/* no IPMI found */
1665 			return (0);
1666 		}
1667 
1668 		/* we have an IPMI signature, fill in attach arg structure */
1669 		ia->iaa_if_type = pipmi->dmd_if_type;
1670 		ia->iaa_if_rev = pipmi->dmd_if_rev;
1671 	}
1672 
1673 	return (1);
1674 }
1675 
1676 int
1677 ipmi_match(struct device *parent, void *match, void *aux)
1678 {
1679 	struct ipmi_softc	sc;
1680 	struct ipmi_attach_args *ia = aux;
1681 	struct cfdata		*cf = match;
1682 	u_int8_t		cmd[32];
1683 	int			len;
1684 	int			rv = 0;
1685 
1686 	if (strcmp(ia->iaa_name, cf->cf_driver->cd_name))
1687 		return (0);
1688 
1689 	/* XXX local softc is wrong wrong wrong */
1690 	strlcpy(sc.sc_dev.dv_xname, "ipmi0", sizeof(sc.sc_dev.dv_xname));
1691 	/* Map registers */
1692 	if (ipmi_map_regs(&sc, ia) == 0) {
1693 		sc.sc_if->probe(&sc);
1694 
1695 		/* Identify BMC device early to detect lying bios */
1696 		if (ipmi_sendcmd(&sc, BMC_SA, 0, APP_NETFN, APP_GET_DEVICE_ID,
1697 		    0, NULL)) {
1698 			dbg_printf(1, ": unable to send get device id "
1699 			    "command\n");
1700 			goto unmap;
1701 		}
1702 		if (ipmi_recvcmd(&sc, sizeof(cmd), &len, cmd)) {
1703 			dbg_printf(1, ": unable to retrieve device id\n");
1704 			goto unmap;
1705 		}
1706 
1707 		dbg_dump(1, "bmc data", len, cmd);
1708 unmap:
1709 		rv = 1; /* GETID worked, we got IPMI */
1710 		ipmi_unmap_regs(&sc);
1711 	}
1712 
1713 	return (rv);
1714 }
1715 
1716 void
1717 ipmi_attach(struct device *parent, struct device *self, void *aux)
1718 {
1719 	struct ipmi_softc	*sc = (void *) self;
1720 	struct ipmi_attach_args *ia = aux;
1721 
1722 	/* Map registers */
1723 	ipmi_map_regs(sc, ia);
1724 
1725 	sc->sc_thread = malloc(sizeof(struct ipmi_thread), M_DEVBUF, M_NOWAIT);
1726 	if (sc->sc_thread == NULL) {
1727 		printf(": unable to allocate thread\n");
1728 		return;
1729 	}
1730 	sc->sc_thread->sc = sc;
1731 	sc->sc_thread->running = 1;
1732 
1733 	/* Setup threads */
1734 	kthread_create_deferred(ipmi_create_thread, sc);
1735 
1736 	printf(": version %d.%d interface %s %sbase 0x%x/%x spacing %d",
1737 	    ia->iaa_if_rev >> 4, ia->iaa_if_rev & 0xF, sc->sc_if->name,
1738 	    ia->iaa_if_iotype == 'i' ? "io" : "mem", ia->iaa_if_iobase,
1739 	    ia->iaa_if_iospacing * sc->sc_if->nregs, ia->iaa_if_iospacing);
1740 	if (ia->iaa_if_irq != -1)
1741 		printf(" irq %d", ia->iaa_if_irq);
1742 	printf("\n");
1743 
1744 	/* setup flag to exclude iic */
1745 	ipmi_enabled = 1;
1746 
1747 	/* Setup Watchdog timer */
1748 	sc->sc_wdog_period = 0;
1749 	wdog_register(ipmi_watchdog, sc);
1750 
1751 	/* lock around read_sensor so that no one messes with the bmc regs */
1752 	rw_init(&sc->sc_lock, DEVNAME(sc));
1753 
1754 	/* setup ticker */
1755 	sc->sc_retries = 0;
1756 	sc->sc_wakeup = 0;
1757 	sc->sc_max_retries = 50; /* 50 * 1/100 = 0.5 seconds max */
1758 	timeout_set(&sc->sc_timeout, _bmc_io_wait, sc);
1759 }
1760 
1761 int
1762 ipmi_watchdog(void *arg, int period)
1763 {
1764 	struct ipmi_softc	*sc = arg;
1765 	struct ipmi_watchdog	wdog;
1766 	int			s, rc, len;
1767 
1768 	if (sc->sc_wdog_period == period) {
1769 		if (period != 0) {
1770 			s = splsoftclock();
1771 			/* tickle the watchdog */
1772 			rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN,
1773 			    APP_RESET_WATCHDOG, 0, NULL);
1774 			rc = ipmi_recvcmd(sc, 0, &len, NULL);
1775 			splx(s);
1776 		}
1777 		return (period);
1778 	}
1779 
1780 	if (period < 10 && period > 0)
1781 		period = 10;
1782 
1783 	s = splsoftclock();
1784 	/* XXX what to do if poking wdog fails? */
1785 	rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN,
1786 	    APP_GET_WATCHDOG_TIMER, 0, NULL);
1787 	rc = ipmi_recvcmd(sc, sizeof(wdog), &len, &wdog);
1788 
1789 	/* Period is 10ths/sec */
1790 	wdog.wdog_timeout = htole32(period * 10);
1791 	wdog.wdog_action &= ~IPMI_WDOG_MASK;
1792 	wdog.wdog_action |= (period == 0) ? IPMI_WDOG_DISABLED :
1793 	    IPMI_WDOG_REBOOT;
1794 
1795 	rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN,
1796 	    APP_SET_WATCHDOG_TIMER, sizeof(wdog), &wdog);
1797 	rc = ipmi_recvcmd(sc, 0, &len, NULL);
1798 
1799 	splx(s);
1800 
1801 	sc->sc_wdog_period = period;
1802 	return (period);
1803 }
1804