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