2 * Copyright (c) 2006 IronPort Systems Inc. <ambrisko@ironport.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
26 * $FreeBSD: head/sys/dev/ipmi/ipmi.c 257421 2013-10-31 05:13:53Z glebius $
29 #include <sys/param.h>
30 #include <sys/systm.h>
32 #include <sys/condvar.h>
34 #include <sys/kernel.h>
35 #include <sys/malloc.h>
36 #include <sys/module.h>
38 #include <sys/sysctl.h>
40 #include <sys/device.h>
41 #include <sys/devfs.h>
48 #include <dev/misc/ipmi/ipmivars.h>
52 static int ipmi_ipmb_checksum(u_char, int);
53 static int ipmi_ipmb_send_message(device_t, u_char, u_char, u_char,
57 static d_ioctl_t ipmi_ioctl;
58 static d_kqfilter_t ipmi_kqfilter;
59 static d_open_t ipmi_open;
60 static void ipmi_dtor(void *arg);
62 static void ipmi_filter_detach(struct knote *);
63 static int ipmi_filter_read(struct knote *, long);
65 int ipmi_attached = 0;
68 static SYSCTL_NODE(_hw, OID_AUTO, ipmi, CTLFLAG_RD, 0,
69 "IPMI driver parameters");
70 SYSCTL_INT(_hw_ipmi, OID_AUTO, on, CTLFLAG_RW,
73 static struct dev_ops ipmi_ops = {
74 { "ipmi", 0, D_MPSAFE },
76 .d_ioctl = ipmi_ioctl,
77 .d_kqfilter = ipmi_kqfilter,
80 static int ipmi_watchdog_sysctl_enable(SYSCTL_HANDLER_ARGS);
81 static int ipmi_watchdog_sysctl_period(SYSCTL_HANDLER_ARGS);
83 static MALLOC_DEFINE(M_IPMI, "ipmi", "ipmi");
86 ipmi_open(struct dev_open_args *ap)
88 struct file *fp = ap->a_fp;
89 cdev_t cdev = ap->a_head.a_dev;
90 struct ipmi_device *dev;
91 struct ipmi_softc *sc;
97 /* Initialize the per file descriptor data. */
98 dev = kmalloc(sizeof(struct ipmi_device), M_IPMI, M_WAITOK | M_ZERO);
99 error = devfs_set_cdevpriv(fp, dev, ipmi_dtor);
106 TAILQ_INIT(&dev->ipmi_completed_requests);
107 dev->ipmi_address = IPMI_BMC_SLAVE_ADDR;
108 dev->ipmi_lun = IPMI_BMC_SMS_LUN;
109 dev->ipmi_softc = sc;
117 static struct filterops ipmi_filterops = {
118 FILTEROP_ISFD | FILTEROP_MPSAFE,
125 ipmi_kqfilter(struct dev_kqfilter_args *ap)
127 cdev_t cdev = ap->a_head.a_dev;
128 struct file *fp = ap->a_fp;
129 struct knote *kn = ap->a_kn;
130 struct ipmi_softc *sc = cdev->si_drv1;
131 struct ipmi_device *dev;
136 switch(kn->kn_filter) {
138 if (devfs_get_cdevpriv(fp, (void **)&dev))
140 kn->kn_fop = &ipmi_filterops;
141 kn->kn_hook = (caddr_t)dev;
144 ap->a_result = EOPNOTSUPP;
148 klist = &sc->ipmi_kq.ki_note;
149 knote_insert(klist, kn);
155 ipmi_filter_detach(struct knote *kn)
157 struct ipmi_device *dev = (struct ipmi_device *)kn->kn_hook;
158 struct ipmi_softc *sc = dev->ipmi_softc;
161 klist = &sc->ipmi_kq.ki_note;
162 knote_remove(klist, kn);
166 ipmi_filter_read(struct knote *kn, long hint)
168 struct ipmi_device *dev = (struct ipmi_device *)kn->kn_hook;
169 struct ipmi_softc *sc = dev->ipmi_softc;
173 if (!TAILQ_EMPTY(&dev->ipmi_completed_requests))
175 if (dev->ipmi_requests == 0)
176 kn->kn_flags |= EV_ERROR;
183 ipmi_purge_completed_requests(struct ipmi_device *dev)
185 struct ipmi_request *req;
187 while (!TAILQ_EMPTY(&dev->ipmi_completed_requests)) {
188 req = TAILQ_FIRST(&dev->ipmi_completed_requests);
189 TAILQ_REMOVE(&dev->ipmi_completed_requests, req, ir_link);
190 dev->ipmi_requests--;
191 ipmi_free_request(req);
198 struct ipmi_request *req, *nreq;
199 struct ipmi_device *dev;
200 struct ipmi_softc *sc;
203 sc = dev->ipmi_softc;
206 if (dev->ipmi_requests) {
207 /* Throw away any pending requests for this device. */
208 TAILQ_FOREACH_MUTABLE(req, &sc->ipmi_pending_requests, ir_link,
210 if (req->ir_owner == dev) {
211 TAILQ_REMOVE(&sc->ipmi_pending_requests, req,
213 dev->ipmi_requests--;
214 ipmi_free_request(req);
218 /* Throw away any pending completed requests for this device. */
219 ipmi_purge_completed_requests(dev);
222 * If we still have outstanding requests, they must be stuck
223 * in an interface driver, so wait for those to drain.
225 dev->ipmi_closing = 1;
226 while (dev->ipmi_requests > 0) {
227 lksleep(&dev->ipmi_requests, &sc->ipmi_lock, 0,
229 ipmi_purge_completed_requests(dev);
241 ipmi_ipmb_checksum(u_char *data, int len)
251 /* XXX: Needs work */
253 ipmi_ipmb_send_message(device_t dev, u_char channel, u_char netfn,
254 u_char command, u_char seq, u_char *data, int data_len)
256 struct ipmi_softc *sc = device_get_softc(dev);
257 struct ipmi_request *req;
258 u_char slave_addr = 0x52;
261 req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0),
262 IPMI_SEND_MSG, data_len + 8, 0);
263 req->ir_request[0] = channel;
264 req->ir_request[1] = slave_addr;
265 req->ir_request[2] = IPMI_ADDR(netfn, 0);
266 req->ir_request[3] = ipmi_ipmb_checksum(&req->ir_request[1], 2);
267 req->ir_request[4] = sc->ipmi_address;
268 req->ir_request[5] = IPMI_ADDR(seq, sc->ipmi_lun);
269 req->ir_request[6] = command;
271 bcopy(data, &req->ir_request[7], data_len);
272 temp[data_len + 7] = ipmi_ipmb_checksum(&req->ir_request[4],
275 ipmi_submit_driver_request(sc, req);
276 error = req->ir_error;
277 ipmi_free_request(req);
283 ipmi_handle_attn(struct ipmi_softc *sc)
285 struct ipmi_request *req;
288 device_printf(sc->ipmi_dev, "BMC has a message\n");
289 req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0),
290 IPMI_GET_MSG_FLAGS, 0, 1);
292 ipmi_submit_driver_request(sc, req);
294 if (req->ir_error == 0 && req->ir_compcode == 0) {
295 if (req->ir_reply[0] & IPMI_MSG_BUFFER_FULL) {
296 device_printf(sc->ipmi_dev, "message buffer full");
298 if (req->ir_reply[0] & IPMI_WDT_PRE_TIMEOUT) {
299 device_printf(sc->ipmi_dev,
300 "watchdog about to go off");
302 if (req->ir_reply[0] & IPMI_MSG_AVAILABLE) {
303 ipmi_free_request(req);
305 req = ipmi_alloc_driver_request(
306 IPMI_ADDR(IPMI_APP_REQUEST, 0), IPMI_GET_MSG, 0,
309 device_printf(sc->ipmi_dev, "throw out message ");
313 error = req->ir_error;
314 ipmi_free_request(req);
320 #ifdef IPMICTL_SEND_COMMAND_32
321 #define PTRIN(p) ((void *)(uintptr_t)(p))
322 #define PTROUT(p) ((uintptr_t)(p))
326 ipmi_ioctl(struct dev_ioctl_args *ap)
328 struct file *fp = ap->a_fp;
329 cdev_t cdev = ap->a_head.a_dev;
330 u_long cmd = ap->a_cmd;
331 caddr_t data = ap->a_data;
332 struct ipmi_softc *sc;
333 struct ipmi_device *dev;
334 struct ipmi_request *kreq;
335 struct ipmi_req *req = (struct ipmi_req *)data;
336 struct ipmi_recv *recv = (struct ipmi_recv *)data;
337 struct ipmi_addr addr;
338 #ifdef IPMICTL_SEND_COMMAND_32
339 struct ipmi_req32 *req32 = (struct ipmi_req32 *)data;
340 struct ipmi_recv32 *recv32 = (struct ipmi_recv32 *)data;
343 struct ipmi_recv recv;
348 error = devfs_get_cdevpriv(fp, (void **)&dev);
354 #ifdef IPMICTL_SEND_COMMAND_32
355 /* Convert 32-bit structures to native. */
357 case IPMICTL_SEND_COMMAND_32:
359 req->addr = PTRIN(req32->addr);
360 req->addr_len = req32->addr_len;
361 req->msgid = req32->msgid;
362 req->msg.netfn = req32->msg.netfn;
363 req->msg.cmd = req32->msg.cmd;
364 req->msg.data_len = req32->msg.data_len;
365 req->msg.data = PTRIN(req32->msg.data);
367 case IPMICTL_RECEIVE_MSG_TRUNC_32:
368 case IPMICTL_RECEIVE_MSG_32:
369 recv = &thunk32.recv;
370 recv->addr = PTRIN(recv32->addr);
371 recv->addr_len = recv32->addr_len;
372 recv->msg.data_len = recv32->msg.data_len;
373 recv->msg.data = PTRIN(recv32->msg.data);
379 #ifdef IPMICTL_SEND_COMMAND_32
380 case IPMICTL_SEND_COMMAND_32:
382 case IPMICTL_SEND_COMMAND:
384 * XXX: Need to add proper handling of this.
386 error = copyin(req->addr, &addr, sizeof(addr));
391 /* clear out old stuff in queue of stuff done */
392 /* XXX: This seems odd. */
393 while ((kreq = TAILQ_FIRST(&dev->ipmi_completed_requests))) {
394 TAILQ_REMOVE(&dev->ipmi_completed_requests, kreq,
396 dev->ipmi_requests--;
397 ipmi_free_request(kreq);
401 kreq = ipmi_alloc_request(dev, req->msgid,
402 IPMI_ADDR(req->msg.netfn, 0), req->msg.cmd,
403 req->msg.data_len, IPMI_MAX_RX);
404 error = copyin(req->msg.data, kreq->ir_request,
407 ipmi_free_request(kreq);
411 dev->ipmi_requests++;
412 error = sc->ipmi_enqueue_request(sc, kreq);
417 #ifdef IPMICTL_SEND_COMMAND_32
418 case IPMICTL_RECEIVE_MSG_TRUNC_32:
419 case IPMICTL_RECEIVE_MSG_32:
421 case IPMICTL_RECEIVE_MSG_TRUNC:
422 case IPMICTL_RECEIVE_MSG:
423 error = copyin(recv->addr, &addr, sizeof(addr));
428 kreq = TAILQ_FIRST(&dev->ipmi_completed_requests);
433 addr.channel = IPMI_BMC_CHANNEL;
435 recv->recv_type = IPMI_RESPONSE_RECV_TYPE;
436 recv->msgid = kreq->ir_msgid;
437 recv->msg.netfn = IPMI_REPLY_ADDR(kreq->ir_addr) >> 2;
438 recv->msg.cmd = kreq->ir_command;
439 error = kreq->ir_error;
441 TAILQ_REMOVE(&dev->ipmi_completed_requests, kreq,
443 dev->ipmi_requests--;
445 ipmi_free_request(kreq);
448 len = kreq->ir_replylen + 1;
449 if (recv->msg.data_len < len &&
450 (cmd == IPMICTL_RECEIVE_MSG
451 #ifdef IPMICTL_RECEIVE_MSG_32
452 || cmd == IPMICTL_RECEIVE_MSG_32
458 TAILQ_REMOVE(&dev->ipmi_completed_requests, kreq, ir_link);
459 dev->ipmi_requests--;
461 len = min(recv->msg.data_len, len);
462 recv->msg.data_len = len;
463 error = copyout(&addr, recv->addr,sizeof(addr));
465 error = copyout(&kreq->ir_compcode, recv->msg.data, 1);
467 error = copyout(kreq->ir_reply, recv->msg.data + 1,
469 ipmi_free_request(kreq);
473 case IPMICTL_SET_MY_ADDRESS_CMD:
475 dev->ipmi_address = *(int*)data;
478 case IPMICTL_GET_MY_ADDRESS_CMD:
480 *(int*)data = dev->ipmi_address;
483 case IPMICTL_SET_MY_LUN_CMD:
485 dev->ipmi_lun = *(int*)data & 0x3;
488 case IPMICTL_GET_MY_LUN_CMD:
490 *(int*)data = dev->ipmi_lun;
493 case IPMICTL_SET_GETS_EVENTS_CMD:
495 device_printf(sc->ipmi_dev,
496 "IPMICTL_SET_GETS_EVENTS_CMD NA\n");
499 case IPMICTL_REGISTER_FOR_CMD:
500 case IPMICTL_UNREGISTER_FOR_CMD:
503 device_printf(sc->ipmi_dev, "Unknown IOCTL %lX\n", cmd);
507 #ifdef IPMICTL_SEND_COMMAND_32
508 /* Update changed fields in 32-bit structures. */
510 case IPMICTL_RECEIVE_MSG_TRUNC_32:
511 case IPMICTL_RECEIVE_MSG_32:
512 recv32->recv_type = recv->recv_type;
513 recv32->msgid = recv->msgid;
514 recv32->msg.netfn = recv->msg.netfn;
515 recv32->msg.cmd = recv->msg.cmd;
516 recv32->msg.data_len = recv->msg.data_len;
524 * Request management.
527 /* Allocate a new request with request and reply buffers. */
528 struct ipmi_request *
529 ipmi_alloc_request(struct ipmi_device *dev, long msgid, uint8_t addr,
530 uint8_t command, size_t requestlen, size_t replylen)
532 struct ipmi_request *req;
534 req = kmalloc(sizeof(struct ipmi_request) + requestlen + replylen,
535 M_IPMI, M_WAITOK | M_ZERO);
537 req->ir_msgid = msgid;
539 req->ir_command = command;
541 req->ir_request = (char *)&req[1];
542 req->ir_requestlen = requestlen;
545 req->ir_reply = (char *)&req[1] + requestlen;
546 req->ir_replybuflen = replylen;
551 /* Free a request no longer in use. */
553 ipmi_free_request(struct ipmi_request *req)
559 /* Store a processed request on the appropriate completion queue. */
561 ipmi_complete_request(struct ipmi_softc *sc, struct ipmi_request *req)
563 struct ipmi_device *dev;
565 IPMI_LOCK_ASSERT(sc);
568 * Anonymous requests (from inside the driver) always have a
569 * waiter that we awaken.
571 if (req->ir_owner == NULL)
575 TAILQ_INSERT_TAIL(&dev->ipmi_completed_requests, req, ir_link);
576 KNOTE(&sc->ipmi_kq.ki_note, 0);
577 if (dev->ipmi_closing)
578 wakeup(&dev->ipmi_requests);
582 /* Enqueue an internal driver request and wait until it is completed. */
584 ipmi_submit_driver_request(struct ipmi_softc *sc, struct ipmi_request *req,
590 error = sc->ipmi_enqueue_request(sc, req);
592 error = lksleep(req, &sc->ipmi_lock, 0, "ipmireq", timo);
594 error = req->ir_error;
600 * Helper routine for polled system interfaces that use
601 * ipmi_polled_enqueue_request() to queue requests. This request
602 * waits until there is a pending request and then returns the first
603 * request. If the driver is shutting down, it returns NULL.
605 struct ipmi_request *
606 ipmi_dequeue_request(struct ipmi_softc *sc)
608 struct ipmi_request *req;
610 IPMI_LOCK_ASSERT(sc);
612 while (!sc->ipmi_detaching && TAILQ_EMPTY(&sc->ipmi_pending_requests))
613 cv_wait(&sc->ipmi_request_added, &sc->ipmi_lock);
614 if (sc->ipmi_detaching)
617 req = TAILQ_FIRST(&sc->ipmi_pending_requests);
618 TAILQ_REMOVE(&sc->ipmi_pending_requests, req, ir_link);
622 /* Default implementation of ipmi_enqueue_request() for polled interfaces. */
624 ipmi_polled_enqueue_request(struct ipmi_softc *sc, struct ipmi_request *req)
626 IPMI_LOCK_ASSERT(sc);
628 TAILQ_INSERT_TAIL(&sc->ipmi_pending_requests, req, ir_link);
630 cv_signal(&sc->ipmi_request_added);
635 * Watchdog event handler.
638 ipmi_set_watchdog(struct ipmi_softc *sc, unsigned int sec)
640 struct ipmi_request *req;
643 if (sec > 0xffff / 10)
646 req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0),
647 IPMI_SET_WDOG, 6, 0);
650 req->ir_request[0] = IPMI_SET_WD_TIMER_DONT_STOP
651 | IPMI_SET_WD_TIMER_SMS_OS;
652 req->ir_request[1] = IPMI_SET_WD_ACTION_RESET;
653 req->ir_request[2] = 0;
654 req->ir_request[3] = 0; /* Timer use */
655 req->ir_request[4] = (sec * 10) & 0xff;
656 req->ir_request[5] = (sec * 10) >> 8;
658 req->ir_request[0] = IPMI_SET_WD_TIMER_SMS_OS;
659 req->ir_request[1] = 0;
660 req->ir_request[2] = 0;
661 req->ir_request[3] = 0; /* Timer use */
662 req->ir_request[4] = 0;
663 req->ir_request[5] = 0;
665 error = ipmi_submit_driver_request(sc, req, 0);
667 device_printf(sc->ipmi_dev, "Failed to set watchdog\n");
669 ipmi_free_request(req);
671 req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0),
672 IPMI_RESET_WDOG, 0, 0);
674 error = ipmi_submit_driver_request(sc, req, 0);
676 device_printf(sc->ipmi_dev,
677 "Failed to reset watchdog\n");
680 ipmi_free_request(req);
688 ipmi_watchdog(void *arg)
690 struct ipmi_softc *sc = (struct ipmi_softc *)arg;
693 if(sc->ipmi_wdog_period) {
694 e = ipmi_set_watchdog(sc, sc->ipmi_wdog_period + 1);
697 sc->ipmi_watchdog_active = 1;
699 ipmi_set_watchdog(sc, 0);
701 callout_reset(&sc->ipmi_watchdog,
702 sc->ipmi_wdog_period * hz,
703 &ipmi_watchdog, (void *)sc);
708 ipmi_startup(void *arg)
710 struct ipmi_softc *sc = arg;
711 struct ipmi_request *req;
715 config_intrhook_disestablish(&sc->ipmi_ich);
718 /* Initialize interface-independent state. */
719 lockinit(&sc->ipmi_lock, device_get_nameunit(dev), 0, LK_CANRECURSE);
720 cv_init(&sc->ipmi_request_added, "ipmireq");
721 TAILQ_INIT(&sc->ipmi_pending_requests);
723 /* Initialize interface-dependent state. */
724 error = sc->ipmi_startup(sc);
726 device_printf(dev, "Failed to initialize interface: %d\n",
731 /* Send a GET_DEVICE_ID request. */
732 req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0),
733 IPMI_GET_DEVICE_ID, 0, 15);
735 error = ipmi_submit_driver_request(sc, req, MAX_TIMEOUT);
736 if (error == EWOULDBLOCK) {
737 device_printf(dev, "Timed out waiting for GET_DEVICE_ID\n");
738 ipmi_free_request(req);
741 device_printf(dev, "Failed GET_DEVICE_ID: %d\n", error);
742 ipmi_free_request(req);
744 } else if (req->ir_compcode != 0) {
746 "Bad completion code for GET_DEVICE_ID: %d\n",
748 ipmi_free_request(req);
750 } else if (req->ir_replylen < 5) {
751 device_printf(dev, "Short reply for GET_DEVICE_ID: %d\n",
753 ipmi_free_request(req);
757 device_printf(dev, "IPMI device rev. %d, firmware rev. %d.%d%d, "
759 req->ir_reply[1] & 0x0f,
760 req->ir_reply[2] & 0x7f, req->ir_reply[3] >> 4, req->ir_reply[3] & 0x0f,
761 req->ir_reply[4] & 0x0f, req->ir_reply[4] >> 4);
763 ipmi_free_request(req);
765 req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0),
766 IPMI_CLEAR_FLAGS, 1, 0);
768 ipmi_submit_driver_request(sc, req, 0);
770 /* XXX: Magic numbers */
771 if (req->ir_compcode == 0xc0) {
772 device_printf(dev, "Clear flags is busy\n");
774 if (req->ir_compcode == 0xc1) {
775 device_printf(dev, "Clear flags illegal\n");
777 ipmi_free_request(req);
779 for (i = 0; i < 8; i++) {
780 req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0),
781 IPMI_GET_CHANNEL_INFO, 1, 0);
782 req->ir_request[0] = i;
784 ipmi_submit_driver_request(sc, req, 0);
786 if (req->ir_compcode != 0) {
787 ipmi_free_request(req);
790 ipmi_free_request(req);
792 device_printf(dev, "Number of channels %d\n", i);
794 /* probe for watchdog */
795 req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0),
796 IPMI_GET_WDOG, 0, 0);
798 ipmi_submit_driver_request(sc, req, 0);
800 if (req->ir_compcode == 0x00) {
801 struct sysctl_ctx_list *ctx;
802 struct sysctl_oid *tree;
803 struct sysctl_oid_list *child;
805 device_printf(dev, "Attached watchdog\n");
806 /* register the watchdog event handler */
807 /* XXX profmakx: our wdog driver holds a spinlock while
808 running the watchdog function, but since the ipmi watchdog
809 function sleeps, this doesn't work. Hack something with
811 callout_init(&sc->ipmi_watchdog);
812 sc->ipmi_wdog_enable = 0;
813 sc->ipmi_wdog_period = 30;
815 ctx = device_get_sysctl_ctx(dev);
816 tree = device_get_sysctl_tree(dev);
817 child = SYSCTL_CHILDREN(tree);
819 SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "watchdog_enable",
820 CTLTYPE_INT | CTLFLAG_RW, sc, 0,
821 ipmi_watchdog_sysctl_enable, "I",
822 "ipmi watchdog enable");
823 SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "watchdog_period",
824 CTLTYPE_INT | CTLFLAG_RW, sc, 0,
825 ipmi_watchdog_sysctl_period, "I",
826 "ipmi watchdog period");
829 ipmi_free_request(req);
831 sc->ipmi_cdev = make_dev(&ipmi_ops, device_get_unit(dev),
832 UID_ROOT, GID_OPERATOR, 0660, "ipmi%d", device_get_unit(dev));
833 if (sc->ipmi_cdev == NULL) {
834 device_printf(dev, "Failed to create cdev\n");
837 sc->ipmi_cdev->si_drv1 = sc;
841 ipmi_attach(device_t dev)
843 struct ipmi_softc *sc = device_get_softc(dev);
846 if (sc->ipmi_irq_res != NULL && sc->ipmi_intr != NULL) {
847 error = bus_setup_intr(dev, sc->ipmi_irq_res, 0,
848 sc->ipmi_intr, sc, &sc->ipmi_irq, NULL);
850 device_printf(dev, "can't set up interrupt\n");
855 bzero(&sc->ipmi_ich, sizeof(struct intr_config_hook));
856 sc->ipmi_ich.ich_func = ipmi_startup;
857 sc->ipmi_ich.ich_arg = sc;
858 sc->ipmi_ich.ich_desc = "ipmi";
859 if (config_intrhook_establish(&sc->ipmi_ich) != 0) {
860 device_printf(dev, "can't establish configuration hook\n");
869 ipmi_detach(device_t dev)
871 struct ipmi_softc *sc;
873 sc = device_get_softc(dev);
875 /* Fail if there are any open handles. */
877 if (sc->ipmi_opened) {
883 destroy_dev(sc->ipmi_cdev);
885 /* Detach from watchdog handling and turn off watchdog. */
886 callout_stop_sync(&sc->ipmi_watchdog);
887 ipmi_set_watchdog(sc, 0);
889 /* XXX: should use shutdown callout I think. */
890 /* If the backend uses a kthread, shut it down. */
892 sc->ipmi_detaching = 1;
893 if (sc->ipmi_kthread) {
894 cv_broadcast(&sc->ipmi_request_added);
895 lksleep(sc->ipmi_kthread, &sc->ipmi_lock, 0, "ipmi_wait", 0);
899 bus_teardown_intr(dev, sc->ipmi_irq_res, sc->ipmi_irq);
901 ipmi_release_resources(dev);
902 lockuninit(&sc->ipmi_lock);
907 ipmi_release_resources(device_t dev)
909 struct ipmi_softc *sc;
912 sc = device_get_softc(dev);
914 bus_teardown_intr(dev, sc->ipmi_irq_res, sc->ipmi_irq);
915 if (sc->ipmi_irq_res)
916 bus_release_resource(dev, SYS_RES_IRQ, sc->ipmi_irq_rid,
918 for (i = 0; i < MAX_RES; i++)
919 if (sc->ipmi_io_res[i])
920 bus_release_resource(dev, sc->ipmi_io_type,
921 sc->ipmi_io_rid + i, sc->ipmi_io_res[i]);
924 devclass_t ipmi_devclass;
928 ipmi_unload(void *arg)
934 if (devclass_get_devices(ipmi_devclass, &devs, &count) != 0)
936 for (i = 0; i < count; i++)
937 device_delete_child(device_get_parent(devs[i]), devs[i]);
940 SYSUNINIT(ipmi_unload, SI_SUB_DRIVERS, SI_ORDER_FIRST, ipmi_unload, NULL);
943 ipmi_watchdog_sysctl_enable(SYSCTL_HANDLER_ARGS)
945 struct ipmi_softc *sc;
952 enable = sc->ipmi_wdog_enable;
955 error = sysctl_handle_int(oidp, &enable, 0, req);
956 if(error || req->newptr == NULL)
960 sc->ipmi_wdog_enable = enable;
963 if (sc->ipmi_wdog_enable==0) {
964 callout_stop(&sc->ipmi_watchdog);
965 ipmi_set_watchdog(sc, 0);
967 callout_reset(&sc->ipmi_watchdog,
968 sc->ipmi_wdog_period * hz,
969 &ipmi_watchdog, (void *)sc);
970 ipmi_set_watchdog(sc, sc->ipmi_wdog_period + 1);
976 ipmi_watchdog_sysctl_period(SYSCTL_HANDLER_ARGS)
978 struct ipmi_softc *sc;
985 period = sc->ipmi_wdog_period;
988 error = sysctl_handle_int(oidp, &period, 30, req);
990 if (error || req->newptr == NULL)
994 sc->ipmi_wdog_period = period;
1002 dump_buf(u_char *data, int len)
1010 printf("Address %p len %d\n", data, len);
1014 for (; len > 0; len--, data++) {
1015 sprintf(temp, "%02x ", *data);
1017 if (*data >= ' ' && *data <= '~')
1019 else if (*data >= 'A' && *data <= 'Z')
1023 if (++count == 16) {
1024 buf[count] = '\000';
1026 printf(" %3x %s %s\n", i, line, buf);
1031 buf[count] = '\000';
1033 for (; count != 16; count++) {
1036 printf(" %3x %s %s\n", i, line, buf);