ipmi.c revision 158651
1/*-
2 * Copyright (c) 2006 IronPort Systems Inc. <ambrisko@ironport.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/dev/ipmi/ipmi.c 158651 2006-05-16 14:37:58Z phk $");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/kernel.h>
33#include <sys/malloc.h>
34#include <sys/poll.h>
35#include <sys/selinfo.h>
36
37#include <sys/disk.h>
38#include <sys/module.h>
39#include <sys/bus.h>
40
41#include <machine/bus.h>
42#include <machine/resource.h>
43#include <sys/rman.h>
44#include <sys/watchdog.h>
45#include <sys/sysctl.h>
46
47#ifdef LOCAL_MODULE
48#include <ipmi.h>
49#include <ipmivars.h>
50#else
51#include <sys/ipmi.h>
52#include <dev/ipmi/ipmivars.h>
53#endif
54
55struct ipmi_done_list {
56	u_char		*data;
57	int		channel;
58	int		msgid;
59	int		len;
60	TAILQ_ENTRY(ipmi_done_list) list;
61};
62
63#define MAX_TIMEOUT 3 * hz
64
65static int ipmi_wait_for_ibf(device_t, int);
66static int ipmi_wait_for_obf(device_t, int);
67static void ipmi_clear_obf(device_t, int);
68static void ipmi_error(device_t);
69static void ipmi_check_read(device_t);
70static int ipmi_write(device_t, u_char *, int);
71static void ipmi_wait_for_tx_okay(device_t);
72static void ipmi_wait_for_rx_okay(device_t);
73static void ipmi_wait_for_not_busy(device_t);
74static void ipmi_set_busy(device_t);
75static int ipmi_ready_to_read(device_t);
76#ifdef IPMB
77static int ipmi_handle_attn(device_t dev);
78static int ipmi_ipmb_checksum(u_char, int);
79static int ipmi_ipmb_send_message(device_t, u_char, u_char, u_char,
80     u_char, u_char, int)
81#endif
82
83static d_ioctl_t ipmi_ioctl;
84static d_poll_t ipmi_poll;
85static d_open_t ipmi_open;
86static d_close_t ipmi_close;
87
88int ipmi_attached = 0;
89
90#define IPMI_MINOR	0
91
92static int on = 1;
93SYSCTL_NODE(_hw, OID_AUTO, ipmi, CTLFLAG_RD, 0, "IPMI driver parameters");
94SYSCTL_INT(_hw_ipmi, OID_AUTO, on, CTLFLAG_RW,
95        &on, 0, "");
96
97static struct cdevsw ipmi_cdevsw = {
98	.d_version =    D_VERSION,
99	.d_flags =      D_NEEDGIANT,
100	.d_open =	ipmi_open,
101	.d_close =	ipmi_close,
102	.d_ioctl =	ipmi_ioctl,
103	.d_poll =	ipmi_poll,
104	.d_name =	"ipmi",
105};
106
107MALLOC_DEFINE(M_IPMI, "ipmi", "ipmi");
108
109static	int
110ipmi_open(struct cdev *dev, int flags, int fmt, struct thread *td)
111{
112	struct ipmi_softc *sc;
113
114	if (!on)
115		return ENOENT;
116
117	sc = dev->si_drv1;
118	if (sc->ipmi_refcnt) {
119		return EBUSY;
120	}
121	sc->ipmi_refcnt = 1;
122
123	return 0;
124}
125
126static	int
127ipmi_poll(struct cdev *dev, int poll_events, struct thread *td)
128{
129	struct ipmi_softc *sc;
130	int revents = 0;
131
132	sc = dev->si_drv1;
133
134	ipmi_check_read(sc->ipmi_dev);
135
136	if (poll_events & (POLLIN | POLLRDNORM)) {
137		if (!TAILQ_EMPTY(&sc->ipmi_done))
138		    revents |= poll_events & (POLLIN | POLLRDNORM);
139		if (TAILQ_EMPTY(&sc->ipmi_done) && sc->ipmi_requests == 0) {
140		    revents |= POLLERR;
141		}
142	}
143
144	if (revents == 0) {
145		if (poll_events & (POLLIN | POLLRDNORM))
146			selrecord(td, &sc->ipmi_select);
147	}
148
149	return revents;
150}
151
152static	int
153ipmi_close(struct cdev *dev, int flags, int fmt, struct thread *td)
154{
155	struct ipmi_softc *sc;
156	int error = 0;
157
158	sc = dev->si_drv1;
159
160	sc->ipmi_refcnt = 0;
161
162	return error;
163}
164
165#ifdef IPMB
166static int
167ipmi_ipmb_checksum(u_char *data, int len)
168{
169	u_char sum = 0;
170
171	for (; len; len--) {
172		sum += *data++;
173	}
174	return -sum;
175}
176
177static int
178ipmi_ipmb_send_message(device_t dev, u_char channel, u_char netfn,
179    u_char command, u_char seq, u_char *data, int data_len)
180{
181	u_char *temp;
182	struct ipmi_softc *sc = device_get_softc(dev);
183	int error;
184	u_char slave_addr = 0x52;
185
186	temp = malloc(data_len + 10, M_IPMI, M_WAITOK);
187	bzero(temp, data_len + 10);
188	temp[0] = IPMI_APP_REQUEST << 2;
189	temp[1] = IPMI_SEND_MSG;
190	temp[2] = channel;
191	temp[3] = slave_addr;
192	temp[4] = netfn << 2;
193	temp[5] = ipmi_ipmb_check_sum(&temp[3], 2);
194	temp[6] = sc->ipmi_address;
195	temp[7] = seq << 2 | sc->ipmi_lun;
196	temp[8] = command;
197
198	bcopy(data, &temp[9], data_len);
199	temp[data_len + 9] = ipmi_ipmb_check(&temp[6], data_len + 3);
200	ipmi_write(sc->ipmi_dev, temp, data_len + 9);
201	free(temp, M_IPMI);
202
203	while (!ipmi_ready_to_read(dev))
204		DELAY(1000);
205	temp = malloc(IPMI_MAX_RX, M_IPMI, M_WAITOK);
206	bzero(temp, IPMI_MAX_RX);
207	error = ipmi_read(dev, temp, IPMI_MAX_RX);
208	free(temp, M_IPMI);
209
210	return error;
211}
212
213static int
214ipmi_handle_attn(device_t dev)
215{
216	u_char temp[IPMI_MAX_RX];
217	struct ipmi_softc *sc = device_get_softc(dev);
218	int error;
219
220	device_printf(sc->ipmi_dev, "BMC has a message\n");
221	temp[0] = IPMI_APP_REQUEST << 2;
222	temp[1] = IPMI_GET_MSG_FLAGS;
223	ipmi_write(sc->ipmi_dev, temp, 2);
224	while (!ipmi_ready_to_read(dev))
225		DELAY(1000);
226	bzero(temp, IPMI_MAX_RX);
227	error = ipmi_read(dev, temp, IPMI_MAX_RX);
228
229	if (temp[2] == 0) {
230		if (temp[3] & IPMI_MSG_BUFFER_FULL) {
231			device_printf(sc->ipmi_dev, "message buffer full");
232		}
233		if (temp[3] & IPMI_WDT_PRE_TIMEOUT) {
234			device_printf(sc->ipmi_dev,
235			    "watchdog about to go off");
236		}
237		if (temp[3] & IPMI_MSG_AVAILABLE) {
238			temp[0] = IPMI_APP_REQUEST << 2;
239			temp[1] = IPMI_GET_MSG;
240			ipmi_write(sc->ipmi_dev, temp, 2);
241			while (!ipmi_ready_to_read(dev))
242				DELAY(1000);
243			bzero(temp, IPMI_MAX_RX);
244			error = ipmi_read(dev, temp, IPMI_MAX_RX);
245
246			device_printf(sc->ipmi_dev, "throw out message ");
247			dump_buf(temp, 16);
248		}
249	} else
250		return -1;
251	return error;
252}
253#endif
254
255static int
256ipmi_ready_to_read(device_t dev)
257{
258	struct ipmi_softc *sc = device_get_softc(dev);
259	int status, flags;
260
261	if (sc->ipmi_bios_info.smic_mode) {
262		flags = INB(sc, sc->ipmi_smic_flags);
263#ifdef IPMB
264		if (flags & SMIC_STATUS_SMS_ATN) {
265			ipmi_handle_attn(dev);
266			return 0;
267		}
268#endif
269		if (flags & SMIC_STATUS_RX_RDY)
270			 return 1;
271	} else if (sc->ipmi_bios_info.kcs_mode) {
272		status = INB(sc, sc->ipmi_kcs_status_reg);
273#ifdef IPMB
274		if (status & KCS_STATUS_SMS_ATN) {
275			ipmi_handle_attn(dev);
276			return 0;
277		}
278#endif
279		if (status & KCS_STATUS_OBF)
280			 return 1;
281	} else {
282		device_printf(dev,"Unsupported mode\n");
283	}
284
285	return 0;
286}
287
288void
289ipmi_intr(void *arg) {
290	device_t  dev = arg;
291
292	ipmi_check_read(dev);
293}
294
295static void
296ipmi_check_read(device_t dev){
297	struct ipmi_softc *sc = device_get_softc(dev);
298	struct ipmi_done_list *item;
299	int status;
300	u_char *temp;
301
302	if (!sc->ipmi_requests)
303		return;
304
305	untimeout((timeout_t *)ipmi_check_read, dev, sc->ipmi_timeout_handle);
306
307	if(ipmi_ready_to_read(dev)) {
308		sc->ipmi_requests--;
309		temp = malloc(IPMI_MAX_RX, M_IPMI, M_WAITOK);
310		bzero(temp, IPMI_MAX_RX);
311		status = ipmi_read(dev, temp, IPMI_MAX_RX);
312		item = malloc(sizeof(struct ipmi_done_list), M_IPMI, M_WAITOK);
313		bzero(item, sizeof(struct ipmi_done_list));
314		item->data = temp;
315		item->len  = status;
316		if (ticks - sc->ipmi_timestamp > MAX_TIMEOUT) {
317			device_printf(dev, "read timeout when ready\n");
318			TAILQ_INSERT_TAIL(&sc->ipmi_done, item, list);
319			selwakeup(&sc->ipmi_select);
320		} else if (status) {
321			TAILQ_INSERT_TAIL(&sc->ipmi_done, item, list);
322			selwakeup(&sc->ipmi_select);
323		}
324	} else {
325		if (ticks - sc->ipmi_timestamp > MAX_TIMEOUT) {
326			sc->ipmi_requests--;
327			device_printf(dev, "read timeout when not ready\n");
328			temp = malloc(IPMI_MAX_RX, M_IPMI, M_WAITOK);
329			bzero(temp, IPMI_MAX_RX);
330			sc->ipmi_busy = 0;
331			wakeup(&sc->ipmi_busy);
332			status = -1;
333			item = malloc(sizeof(struct ipmi_done_list),
334			    M_IPMI, M_WAITOK);
335			bzero(item, sizeof(struct ipmi_done_list));
336			item->data = temp;
337			item->len  = status;
338			TAILQ_INSERT_TAIL(&sc->ipmi_done, item, list);
339			selwakeup(&sc->ipmi_select);
340		}
341	}
342	if (sc->ipmi_requests)
343		sc->ipmi_timeout_handle
344			= timeout((timeout_t *)ipmi_check_read, dev, hz/30);
345}
346
347static int
348ipmi_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t data,
349    int flags, struct thread *td)
350{
351	struct ipmi_softc *sc;
352	struct ipmi_req *req = (struct ipmi_req *)data;
353	struct ipmi_recv *recv = (struct ipmi_recv *)data;
354	struct ipmi_addr addr;
355	struct ipmi_done_list *item;
356	u_char *temp;
357	int error, len;
358
359	sc = dev->si_drv1;
360
361	switch (cmd) {
362	case IPMICTL_SEND_COMMAND:
363		/* clear out old stuff in queue of stuff done */
364		while((item = TAILQ_FIRST(&sc->ipmi_done))) {
365			TAILQ_REMOVE(&sc->ipmi_done, item, list);
366			free(item->data, M_IPMI);
367			free(item, M_IPMI);
368		}
369
370		error = copyin(req->addr, &addr, sizeof(addr));
371		temp = malloc(req->msg.data_len + 2, M_IPMI, M_WAITOK);
372		if (temp == NULL) {
373			return ENOMEM;
374		}
375		temp[0] = req->msg.netfn << 2;
376		temp[1] = req->msg.cmd;
377		error = copyin(req->msg.data, &temp[2],
378		    req->msg.data_len);
379		if (error != 0) {
380			free(temp, M_IPMI);
381			return error;
382		}
383		error = ipmi_write(sc->ipmi_dev,
384		    temp, req->msg.data_len + 2);
385		free(temp, M_IPMI);
386
387		if (error != 1)
388			return EIO;
389		sc->ipmi_requests++;
390		sc->ipmi_timestamp = ticks;
391		ipmi_check_read(sc->ipmi_dev);
392
393		return 0;
394	case IPMICTL_RECEIVE_MSG_TRUNC:
395	case IPMICTL_RECEIVE_MSG:
396		item = TAILQ_FIRST(&sc->ipmi_done);
397		if (!item) {
398			return EAGAIN;
399		}
400
401		error = copyin(recv->addr, &addr, sizeof(addr));
402		if (error != 0)
403			return error;
404		TAILQ_REMOVE(&sc->ipmi_done, item, list);
405		addr.channel = IPMI_BMC_CHANNEL;
406		recv->recv_type = IPMI_RESPONSE_RECV_TYPE;
407		recv->msgid = item->msgid;
408		recv->msg.netfn = item->data[0] >> 2;
409		recv->msg.cmd = item->data[1];
410		error = len = item->len;
411		len -= 2;
412		if (len < 0)
413			len = 1;
414		if (recv->msg.data_len < len && cmd == IPMICTL_RECEIVE_MSG) {
415			TAILQ_INSERT_HEAD(&sc->ipmi_done, item, list);
416			return EMSGSIZE;
417		}
418		len = min(recv->msg.data_len, len);
419		recv->msg.data_len = len;
420		error = copyout(&addr, recv->addr,sizeof(addr));
421		if (error == 0)
422			error = copyout(&item->data[2], recv->msg.data, len);
423		free(item->data, M_IPMI);
424		free(item, M_IPMI);
425
426		if (error != 0)
427			return error;
428		return 0;
429	case IPMICTL_SET_MY_ADDRESS_CMD:
430		sc->ipmi_address = *(int*)data;
431		return 0;
432	case IPMICTL_GET_MY_ADDRESS_CMD:
433		*(int*)data = sc->ipmi_address;
434		return 0;
435	case IPMICTL_SET_MY_LUN_CMD:
436		sc->ipmi_lun = *(int*)data & 0x3;
437		return 0;
438	case IPMICTL_GET_MY_LUN_CMD:
439		*(int*)data = sc->ipmi_lun;
440		return 0;
441	case IPMICTL_SET_GETS_EVENTS_CMD:
442		/*
443		device_printf(sc->ipmi_dev,
444		    "IPMICTL_SET_GETS_EVENTS_CMD NA\n");
445		*/
446		return 0;
447	case IPMICTL_REGISTER_FOR_CMD:
448	case IPMICTL_UNREGISTER_FOR_CMD:
449		return EOPNOTSUPP;
450	}
451
452	device_printf(sc->ipmi_dev, "Unknown IOCTL %lX\n", cmd);
453
454	return ENOIOCTL;
455}
456
457static int
458ipmi_wait_for_ibf(device_t dev, int state) {
459	struct ipmi_softc *sc = device_get_softc(dev);
460	int status, start = ticks;
461	int first = 1;
462
463	if (state == 0) {
464		/* WAIT FOR IBF = 0 */
465		do {
466			if (first)
467				first =0;
468			else
469				DELAY(100);
470			status = INB(sc, sc->ipmi_kcs_status_reg);
471		} while (ticks - start < MAX_TIMEOUT
472		    && status & KCS_STATUS_IBF);
473	} else {
474		/* WAIT FOR IBF = 1 */
475		do {
476			if (first)
477				first =0;
478			else
479				DELAY(100);
480			status = INB(sc, sc->ipmi_kcs_status_reg);
481		} while (ticks - start < MAX_TIMEOUT
482		    && !(status & KCS_STATUS_IBF));
483	}
484	return status;
485}
486
487static int
488ipmi_wait_for_obf(device_t dev, int state) {
489	struct ipmi_softc *sc = device_get_softc(dev);
490	int status, start = ticks;
491	int first = 1;
492
493	if (state == 0) {
494		/* WAIT FOR OBF = 0 */
495		do {
496			if (first)
497				first = 0;
498			else
499				DELAY(100);
500			status = INB(sc, sc->ipmi_kcs_status_reg);
501		} while (ticks - start < MAX_TIMEOUT
502		    && status & KCS_STATUS_OBF);
503	} else {
504		/* WAIT FOR OBF = 1 */
505		do {
506			if (first)
507				first =0;
508			else
509				DELAY(100);
510			status = INB(sc, sc->ipmi_kcs_status_reg);
511		} while (ticks - start < MAX_TIMEOUT
512		    && !(status & KCS_STATUS_OBF));
513	}
514	return status;
515}
516
517static void
518ipmi_clear_obf(device_t dev, int status) {
519	struct ipmi_softc *sc = device_get_softc(dev);
520	int data;
521
522	/* Clear OBF */
523	if (status & KCS_STATUS_OBF) {
524		data = INB(sc, sc->ipmi_kcs_data_out_reg);
525	}
526}
527
528static void
529ipmi_error(device_t dev) {
530	struct ipmi_softc *sc = device_get_softc(dev);
531	int status, data = 0;
532	int retry = 0;
533
534	for(;;){
535		status = ipmi_wait_for_ibf(dev, 0);
536
537		/* ABORT */
538		OUTB(sc, sc->ipmi_kcs_command_reg,
539		     KCS_CONTROL_GET_STATUS_ABORT);
540
541		/* Wait for IBF = 0 */
542		status = ipmi_wait_for_ibf(dev, 0);
543
544		/* Clear OBF */
545		ipmi_clear_obf(dev, status);
546
547		if (status & KCS_STATUS_OBF) {
548			data = INB(sc, sc->ipmi_kcs_data_out_reg);
549			device_printf(dev, "Data %x\n", data);
550		}
551
552		/* 0x00 to DATA_IN */
553		OUTB(sc, sc->ipmi_kcs_data_in_reg, 0x00);
554
555		/* Wait for IBF = 0 */
556		status = ipmi_wait_for_ibf(dev, 0);
557
558		if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_READ) {
559
560			/* Wait for OBF = 1 */
561			status = ipmi_wait_for_obf(dev, 1);
562
563			/* Read error status */
564			data = INB(sc, sc->ipmi_kcs_data_out_reg);
565
566			/* Write READ into Data_in */
567			OUTB(sc, sc->ipmi_kcs_data_in_reg, KCS_DATA_IN_READ);
568
569			/* Wait for IBF = 0 */
570			status = ipmi_wait_for_ibf(dev, 0);
571		}
572
573		/* IDLE STATE */
574		if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_IDLE) {
575			/* Wait for OBF = 1 */
576			status = ipmi_wait_for_obf(dev, 1);
577
578			/* Clear OBF */
579			ipmi_clear_obf(dev, status);
580			break;
581		}
582
583		retry++;
584		if (retry > 2) {
585			device_printf(dev, "Retry exhausted %x\n", retry);
586			break;
587		}
588	}
589}
590
591static void
592ipmi_wait_for_tx_okay(device_t dev) {
593	struct ipmi_softc *sc = device_get_softc(dev);
594	int flags;
595
596	do {
597		flags = INB(sc, sc->ipmi_smic_flags);
598	} while(!flags & SMIC_STATUS_TX_RDY);
599}
600
601static void
602ipmi_wait_for_rx_okay(device_t dev) {
603	struct ipmi_softc *sc = device_get_softc(dev);
604	int flags;
605
606	do {
607		flags = INB(sc, sc->ipmi_smic_flags);
608	} while(!flags & SMIC_STATUS_RX_RDY);
609}
610
611static void
612ipmi_wait_for_not_busy(device_t dev) {
613	struct ipmi_softc *sc = device_get_softc(dev);
614	int flags;
615
616	do {
617		flags = INB(sc, sc->ipmi_smic_flags);
618	} while(flags & SMIC_STATUS_BUSY);
619}
620
621static void
622ipmi_set_busy(device_t dev) {
623	struct ipmi_softc *sc = device_get_softc(dev);
624	int flags;
625
626	flags = INB(sc, sc->ipmi_smic_flags);
627	flags |= SMIC_STATUS_BUSY;
628	OUTB(sc, sc->ipmi_smic_flags, flags);
629}
630
631int
632ipmi_read(device_t dev, u_char *bytes, int len){
633	struct ipmi_softc *sc = device_get_softc(dev);
634	int status, flags, data, i = -1, error;
635
636	bzero(bytes, len);
637	if (sc->ipmi_bios_info.smic_mode) {
638		ipmi_wait_for_not_busy(dev);
639		do {
640			flags = INB(sc, sc->ipmi_smic_flags);
641		} while(!flags & SMIC_STATUS_RX_RDY);
642
643		OUTB(sc, sc->ipmi_smic_ctl_sts, SMIC_CC_SMS_RD_START);
644		ipmi_wait_for_rx_okay(dev);
645		ipmi_set_busy(dev);
646		ipmi_wait_for_not_busy(dev);
647		status = INB(sc, sc->ipmi_smic_ctl_sts);
648		if (status != SMIC_SC_SMS_RD_START) {
649			error = INB(sc, sc->ipmi_smic_data);
650			device_printf(dev, "Read did not start %x %x\n",
651			    status, error);
652			sc->ipmi_busy = 0;
653			return -1;
654		}
655		for (i = -1; ; len--) {
656			i++;
657			data = INB(sc, sc->ipmi_smic_data);
658			if (len > 0)
659				*bytes++ = data;
660			else {
661				device_printf(dev, "Read short %x\n", data);
662				break;
663			}
664			do {
665				flags = INB(sc, sc->ipmi_smic_flags);
666			} while(!flags & SMIC_STATUS_RX_RDY);
667
668			OUTB(sc, sc->ipmi_smic_ctl_sts, SMIC_CC_SMS_RD_NEXT);
669			ipmi_wait_for_rx_okay(dev);
670			ipmi_set_busy(dev);
671			ipmi_wait_for_not_busy(dev);
672			status = INB(sc, sc->ipmi_smic_ctl_sts);
673			if (status == SMIC_SC_SMS_RD_NEXT) {
674				continue;
675			} else if (status == SMIC_SC_SMS_RD_END) {
676				break;
677			} else {
678				device_printf(dev, "Read did not next %x\n",
679				    status);
680			}
681		}
682		i++;
683		data = INB(sc, sc->ipmi_smic_data);
684		if (len > 0)
685			*bytes++ = data;
686		else
687			device_printf(dev, "Read short %x\n", data);
688
689		OUTB(sc, sc->ipmi_smic_ctl_sts, SMIC_CC_SMS_RD_END);
690		i++;
691
692	} else if (sc->ipmi_bios_info.kcs_mode) {
693		for (i = -1; ; len--) {
694			/* Wait for IBF = 0 */
695			status = ipmi_wait_for_ibf(dev, 0);
696
697			/* Read State */
698			if (KCS_STATUS_STATE(status)
699			    == KCS_STATUS_STATE_READ) {
700				i++;
701
702				/* Wait for OBF = 1 */
703				status = ipmi_wait_for_obf(dev, 1);
704
705				/* Read Data_out */
706				data = INB(sc, sc->ipmi_kcs_data_out_reg);
707				if (len > 0)
708					*bytes++ = data;
709				else {
710					device_printf(dev, "Read short %x byte %d\n", data, i);
711					break;
712				}
713
714				/* Write READ into Data_in */
715				OUTB(sc, sc->ipmi_kcs_data_in_reg,
716				    KCS_DATA_IN_READ);
717
718				/* Idle State */
719			} else if (KCS_STATUS_STATE(status)
720			    == KCS_STATUS_STATE_IDLE) {
721				i++;
722
723				/* Wait for OBF = 1*/
724				status = ipmi_wait_for_obf(dev, 1);
725
726				/* Read Dummy */
727				data = INB(sc, sc->ipmi_kcs_data_out_reg);
728				break;
729
730				/* error state */
731			} else {
732				device_printf(dev,
733				    "read status error %x byte %d\n",
734				    status, i);
735				sc->ipmi_busy = 0;
736				ipmi_error(dev);
737				return -1;
738			}
739		}
740	} else {
741		device_printf(dev, "Unsupported mode\n");
742	}
743	sc->ipmi_busy = 0;
744	wakeup(&sc->ipmi_busy);
745
746	return i;
747}
748
749
750static int
751ipmi_write(device_t dev, u_char *bytes, int len){
752	struct ipmi_softc *sc = device_get_softc(dev);
753	int status, flags, retry;
754
755	while(sc->ipmi_busy){
756		status = tsleep(&sc->ipmi_busy, PCATCH, "ipmi", 0);
757		if (status)
758			return status;
759	}
760	sc->ipmi_busy = 1;
761	if (sc->ipmi_bios_info.smic_mode) {
762		ipmi_wait_for_not_busy(dev);
763
764		OUTB(sc, sc->ipmi_smic_ctl_sts, SMIC_CC_SMS_WR_START);
765		ipmi_wait_for_tx_okay(dev);
766		OUTB(sc, sc->ipmi_smic_data, *bytes++);
767		len--;
768		ipmi_set_busy(dev);
769		ipmi_wait_for_not_busy(dev);
770		status = INB(sc, sc->ipmi_smic_ctl_sts);
771		if (status != SMIC_SC_SMS_WR_START) {
772			device_printf(dev, "Write did not start %x\n",status);
773			sc->ipmi_busy = 0;
774			return -1;
775		}
776		for(len--; len; len--) {
777			OUTB(sc, sc->ipmi_smic_ctl_sts, SMIC_CC_SMS_WR_NEXT);
778			ipmi_wait_for_tx_okay(dev);
779			OUTB(sc, sc->ipmi_smic_data, *bytes++);
780			ipmi_set_busy(dev);
781			ipmi_wait_for_not_busy(dev);
782			status = INB(sc, sc->ipmi_smic_ctl_sts);
783			if (status != SMIC_SC_SMS_WR_NEXT) {
784				device_printf(dev, "Write did not next %x\n",
785				    status);
786				sc->ipmi_busy = 0;
787				return -1;
788			}
789		}
790		do {
791			flags = INB(sc, sc->ipmi_smic_flags);
792		} while(!flags & SMIC_STATUS_TX_RDY);
793		OUTB(sc, sc->ipmi_smic_ctl_sts, SMIC_CC_SMS_WR_END);
794		ipmi_wait_for_tx_okay(dev);
795		OUTB(sc, sc->ipmi_smic_data, *bytes);
796		ipmi_set_busy(dev);
797		ipmi_wait_for_not_busy(dev);
798		status = INB(sc, sc->ipmi_smic_ctl_sts);
799		if (status != SMIC_SC_SMS_WR_END) {
800			device_printf(dev, "Write did not end %x\n",status);
801			return -1;
802		}
803	} else if (sc->ipmi_bios_info.kcs_mode) {
804		for (retry = 0; retry < 10; retry++) {
805			/* Wait for IBF = 0 */
806			status = ipmi_wait_for_ibf(dev, 0);
807
808			/* Clear OBF */
809			ipmi_clear_obf(dev, status);
810
811			/* Write start to command */
812			OUTB(sc, sc->ipmi_kcs_command_reg,
813			     KCS_CONTROL_WRITE_START);
814
815			/* Wait for IBF = 0 */
816			status = ipmi_wait_for_ibf(dev, 0);
817			if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_WRITE)
818				break;
819			DELAY(1000000);
820		}
821
822		for(len--; len; len--) {
823			if (KCS_STATUS_STATE(status)
824			    != KCS_STATUS_STATE_WRITE) {
825				/* error state */
826				device_printf(dev, "status error %x\n",status);
827				ipmi_error(dev);
828				sc->ipmi_busy = 0;
829				return -1;
830				break;
831			} else {
832				/* Clear OBF */
833				ipmi_clear_obf(dev, status);
834
835				/* Data to Data */
836				OUTB(sc, sc->ipmi_kcs_data_out_reg, *bytes++);
837
838				/* Wait for IBF = 0 */
839				status = ipmi_wait_for_ibf(dev, 0);
840
841				if (KCS_STATUS_STATE(status)
842				    != KCS_STATUS_STATE_WRITE) {
843					device_printf(dev, "status error %x\n"
844					    ,status);
845					ipmi_error(dev);
846					return -1;
847				} else {
848					/* Clear OBF */
849					ipmi_clear_obf(dev, status);
850				}
851			}
852		}
853		/* Write end to command */
854		OUTB(sc, sc->ipmi_kcs_command_reg, KCS_CONTROL_WRITE_END);
855
856		/* Wait for IBF = 0 */
857		status = ipmi_wait_for_ibf(dev, 0);
858
859		if (KCS_STATUS_STATE(status) != KCS_STATUS_STATE_WRITE) {
860			/* error state */
861			device_printf(dev, "status error %x\n",status);
862			ipmi_error(dev);
863			sc->ipmi_busy = 0;
864			return -1;
865		} else {
866			/* Clear OBF */
867			ipmi_clear_obf(dev, status);
868			OUTB(sc, sc->ipmi_kcs_data_out_reg, *bytes++);
869		}
870	} else {
871		device_printf(dev, "Unsupported mode\n");
872	}
873	sc->ipmi_busy = 2;
874	return 1;
875}
876
877/*
878 * Watchdog event handler.
879 */
880
881static void
882ipmi_set_watchdog(device_t dev, int sec) {
883	u_char *temp;
884	int s;
885
886	temp = malloc(IPMI_MAX_RX, M_IPMI, M_WAITOK);
887
888	temp[0] = IPMI_APP_REQUEST << 2;
889	if (sec) {
890		temp[1] = IPMI_SET_WDOG;
891		temp[2] = IPMI_SET_WD_TIMER_DONT_STOP
892		    | IPMI_SET_WD_TIMER_SMS_OS;
893		temp[3] = IPMI_SET_WD_ACTION_RESET;
894		temp[4] = 0;
895		temp[5] = 0;	/* Timer use */
896		temp[6] = (sec * 10) & 0xff;
897		temp[7] = (sec * 10) / 2550;
898	} else {
899 		temp[1] = IPMI_SET_WDOG;
900		temp[2] = IPMI_SET_WD_TIMER_SMS_OS;
901		temp[3] = 0;
902		temp[4] = 0;
903		temp[5] = 0;	/* Timer use */
904		temp[6] = 0;
905		temp[7] = 0;
906	}
907
908	s = splhigh();
909	ipmi_write(dev, temp, 8);
910
911	while (!ipmi_ready_to_read(dev))
912		DELAY(1000);
913	bzero(temp, IPMI_MAX_RX);
914	ipmi_read(dev, temp, IPMI_MAX_RX);
915
916	if (sec) {
917		temp[0] = IPMI_APP_REQUEST << 2;
918		temp[1] = IPMI_RESET_WDOG;
919
920		ipmi_write(dev, temp, 2);
921
922		while (!ipmi_ready_to_read(dev))
923			DELAY(1000);
924		bzero(temp, IPMI_MAX_RX);
925		ipmi_read(dev, temp, IPMI_MAX_RX);
926	}
927	splx(s);
928
929	free(temp, M_IPMI);
930	/*
931	dump_watchdog(dev);
932	*/
933}
934
935static void
936ipmi_wd_event(void *arg, unsigned int cmd, int *error)
937{
938	struct ipmi_softc *sc = arg;
939	unsigned int timeout;
940
941	/* disable / enable */
942	if (!(cmd & WD_ACTIVE)) {
943		ipmi_set_watchdog(sc->ipmi_dev, 0);
944		*error = 0;
945		return;
946	}
947
948	cmd &= WD_INTERVAL;
949	/* convert from power-of-to-ns to WDT ticks */
950	if (cmd >= 64) {
951		*error = EINVAL;
952		return;
953	}
954	timeout = ((uint64_t)1 << cmd) / 1800000000;
955
956	/* reload */
957	ipmi_set_watchdog(sc->ipmi_dev, timeout);
958
959	*error = 0;
960}
961
962int
963ipmi_attach(device_t dev)
964{
965	struct ipmi_softc *sc = device_get_softc(dev);
966	u_char temp[1024];
967	int i;
968	int status;
969	int unit;
970
971	TAILQ_INIT(&sc->ipmi_done);
972	sc->ipmi_address = IPMI_BMC_SLAVE_ADDR;
973	sc->ipmi_lun = IPMI_BMC_SMS_LUN;
974	temp[0] = IPMI_APP_REQUEST << 2;
975	temp[1] = IPMI_GET_DEVICE_ID;
976	ipmi_write(dev, temp, 2);
977
978	while (!ipmi_ready_to_read(dev))
979		DELAY(1000);
980	bzero(temp, sizeof(temp));
981	ipmi_read(dev, temp, sizeof(temp));
982	device_printf(dev, "IPMI device rev. %d, firmware rev. %d.%d, "
983	    "version %d.%d\n",
984	     temp[4] & 0x0f,
985	     temp[5] & 0x0f, temp[7],
986	     temp[7] & 0x0f, temp[7] >> 4);
987
988	temp[0] = IPMI_APP_REQUEST << 2;
989	temp[1] = IPMI_CLEAR_FLAGS;
990	temp[2] = 8;
991	ipmi_write(dev, temp, 3);
992
993	while (!ipmi_ready_to_read(dev))
994		DELAY(1000);
995	bzero(temp, sizeof(temp));
996	ipmi_read(dev, temp, sizeof(temp));
997	if (temp[2] == 0xc0) {
998		device_printf(dev, "Clear flags is busy\n");
999	}
1000	if (temp[2] == 0xc1) {
1001		device_printf(dev, "Clear flags illegal\n");
1002	}
1003
1004	for(i = 0; i < 8; i++){
1005		temp[0] = IPMI_APP_REQUEST << 2;
1006		temp[1] = IPMI_GET_CHANNEL_INFO;
1007		temp[2] = i;
1008		ipmi_write(dev, temp, 3);
1009		while (!ipmi_ready_to_read(dev))
1010			DELAY(1000);
1011		bzero(temp, sizeof(temp));
1012		ipmi_read(dev, temp, sizeof(temp));
1013		if (temp[2]) {
1014			break;
1015		}
1016	}
1017	device_printf(dev, "Number of channels %d\n", i);
1018
1019	/* probe for watchdog */
1020	bzero(temp, sizeof(temp));
1021        temp[0] = IPMI_APP_REQUEST << 2;
1022        temp[1] = IPMI_GET_WDOG;
1023        status = ipmi_write(dev, temp, 2);
1024        while (!ipmi_ready_to_read(dev))
1025                DELAY(1000);
1026        bzero(temp, sizeof(temp));
1027        ipmi_read(dev, temp, sizeof(temp));
1028        if (temp[0] == 0x1c && temp[2] == 0x00) {
1029		device_printf(dev, "Attached watchdog\n");
1030		/* register the watchdog event handler */
1031		sc->ipmi_ev_tag = EVENTHANDLER_REGISTER(watchdog_list,
1032						   ipmi_wd_event, sc, 0);
1033	}
1034	unit = device_get_unit(sc->ipmi_dev);
1035	/* force device to be ipmi0 since that is what ipmitool expects */
1036	sc->ipmi_dev_t = make_dev(&ipmi_cdevsw, unit, UID_ROOT, GID_OPERATOR,
1037			     0660, "ipmi%d", 0);
1038	sc->ipmi_dev_t->si_drv1 = sc;
1039
1040	ipmi_attached = 1;
1041
1042	return 0;
1043}
1044
1045int
1046ipmi_detach(device_t dev)
1047{
1048	struct ipmi_softc *sc;
1049
1050	sc = device_get_softc(dev);
1051	if (sc->ipmi_requests)
1052		untimeout((timeout_t *)ipmi_check_read, dev,
1053		    sc->ipmi_timeout_handle);
1054	destroy_dev(sc->ipmi_dev_t);
1055	return 0;
1056}
1057
1058#ifdef IMPI_DEBUG
1059static void
1060dump_buf(u_char *data, int len){
1061	char buf[20];
1062	char line[1024];
1063	char temp[30];
1064	int count = 0;
1065	int i=0;
1066
1067	printf("Address %p len %d\n", data, len);
1068	if (len > 256)
1069		len = 256;
1070	line[0] = '\000';
1071	for (; len > 0; len--, data++) {
1072		sprintf(temp, "%02x ", *data);
1073		strcat(line, temp);
1074		if (*data >= ' ' && *data <= '~')
1075			buf[count] = *data;
1076		else if (*data >= 'A' && *data <= 'Z')
1077			buf[count] = *data;
1078		else
1079			buf[count] = '.';
1080		if (++count == 16) {
1081			buf[count] = '\000';
1082			count = 0;
1083			printf("  %3x  %s %s\n", i, line, buf);
1084			i+=16;
1085			line[0] = '\000';
1086		}
1087	}
1088	buf[count] = '\000';
1089
1090	for (; count != 16; count++) {
1091		strcat(line, "   ");
1092	}
1093	printf("  %3x  %s %s\n", i, line, buf);
1094}
1095#endif
1096