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 * $FreeBSD: head/sys/dev/ipmi/ipmi.c 257421 2013-10-31 05:13:53Z glebius $ 27 */ 28 29 #include <sys/param.h> 30 #include <sys/systm.h> 31 #include <sys/bus.h> 32 #include <sys/condvar.h> 33 #include <sys/conf.h> 34 #include <sys/kernel.h> 35 #include <sys/malloc.h> 36 #include <sys/module.h> 37 #include <sys/rman.h> 38 #include <sys/sysctl.h> 39 #include <sys/wdog.h> 40 #include <sys/device.h> 41 #include <sys/devfs.h> 42 43 #ifdef LOCAL_MODULE 44 #include <ipmi.h> 45 #include <ipmivars.h> 46 #else 47 #include <sys/ipmi.h> 48 #include <dev/misc/ipmi/ipmivars.h> 49 #endif 50 51 #ifdef IPMB 52 static int ipmi_ipmb_checksum(u_char, int); 53 static int ipmi_ipmb_send_message(device_t, u_char, u_char, u_char, 54 u_char, u_char, int) 55 #endif 56 57 static d_ioctl_t ipmi_ioctl; 58 static d_kqfilter_t ipmi_kqfilter; 59 static d_open_t ipmi_open; 60 static d_priv_dtor_t ipmi_dtor; 61 62 static void ipmi_filter_detach(struct knote *); 63 static int ipmi_filter_read(struct knote *, long); 64 65 int ipmi_attached = 0; 66 67 static int on = 1; 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, 71 &on, 0, ""); 72 73 static struct dev_ops ipmi_ops = { 74 { "ipmi", 0, D_MPSAFE }, 75 .d_open = ipmi_open, 76 .d_ioctl = ipmi_ioctl, 77 .d_kqfilter = ipmi_kqfilter, 78 }; 79 80 static int ipmi_watchdog_sysctl_enable(SYSCTL_HANDLER_ARGS); 81 static int ipmi_watchdog_sysctl_period(SYSCTL_HANDLER_ARGS); 82 83 static MALLOC_DEFINE(M_IPMI, "ipmi", "ipmi"); 84 85 static int 86 ipmi_open(struct dev_open_args *ap) 87 { 88 struct file *fp = ap->a_fpp ? *ap->a_fpp : NULL; 89 cdev_t cdev = ap->a_head.a_dev; 90 struct ipmi_device *dev; 91 struct ipmi_softc *sc; 92 int error; 93 94 if (!on) 95 return (ENOENT); 96 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); 100 if (error) { 101 kfree(dev, M_IPMI); 102 return (error); 103 } 104 105 sc = cdev->si_drv1; 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; 110 IPMI_LOCK(sc); 111 sc->ipmi_opened++; 112 IPMI_UNLOCK(sc); 113 114 return (0); 115 } 116 117 static struct filterops ipmi_filterops = { 118 FILTEROP_ISFD | FILTEROP_MPSAFE, 119 NULL, 120 ipmi_filter_detach, 121 ipmi_filter_read 122 }; 123 124 static int 125 ipmi_kqfilter(struct dev_kqfilter_args *ap) 126 { 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; 132 struct klist *klist; 133 134 ap->a_result = 0; 135 136 switch(kn->kn_filter) { 137 case EVFILT_READ: 138 if (devfs_get_cdevpriv(fp, (void **)&dev)) 139 return EOPNOTSUPP; 140 kn->kn_fop = &ipmi_filterops; 141 kn->kn_hook = (caddr_t)dev; 142 break; 143 default: 144 ap->a_result = EOPNOTSUPP; 145 return (0); 146 } 147 148 klist = &sc->ipmi_kq.ki_note; 149 knote_insert(klist, kn); 150 151 return (0); 152 } 153 154 static void 155 ipmi_filter_detach(struct knote *kn) 156 { 157 struct ipmi_device *dev = (struct ipmi_device *)kn->kn_hook; 158 struct ipmi_softc *sc = dev->ipmi_softc; 159 struct klist *klist; 160 161 klist = &sc->ipmi_kq.ki_note; 162 knote_remove(klist, kn); 163 } 164 165 static int 166 ipmi_filter_read(struct knote *kn, long hint) 167 { 168 struct ipmi_device *dev = (struct ipmi_device *)kn->kn_hook; 169 struct ipmi_softc *sc = dev->ipmi_softc; 170 int ret = 0; 171 172 IPMI_LOCK(sc); 173 if (!TAILQ_EMPTY(&dev->ipmi_completed_requests)) 174 ret = 1; 175 if (dev->ipmi_requests == 0) 176 kn->kn_flags |= EV_ERROR; 177 IPMI_UNLOCK(sc); 178 179 return (ret); 180 } 181 182 static void 183 ipmi_purge_completed_requests(struct ipmi_device *dev) 184 { 185 struct ipmi_request *req; 186 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); 192 } 193 } 194 195 static void 196 ipmi_dtor(void *arg) 197 { 198 struct ipmi_request *req, *nreq; 199 struct ipmi_device *dev; 200 struct ipmi_softc *sc; 201 202 dev = arg; 203 sc = dev->ipmi_softc; 204 205 IPMI_LOCK(sc); 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, 209 nreq) { 210 if (req->ir_owner == dev) { 211 TAILQ_REMOVE(&sc->ipmi_pending_requests, req, 212 ir_link); 213 dev->ipmi_requests--; 214 ipmi_free_request(req); 215 } 216 } 217 218 /* Throw away any pending completed requests for this device. */ 219 ipmi_purge_completed_requests(dev); 220 221 /* 222 * If we still have outstanding requests, they must be stuck 223 * in an interface driver, so wait for those to drain. 224 */ 225 dev->ipmi_closing = 1; 226 while (dev->ipmi_requests > 0) { 227 lksleep(&dev->ipmi_requests, &sc->ipmi_lock, 0, 228 "ipmidrain", 0); 229 ipmi_purge_completed_requests(dev); 230 } 231 } 232 sc->ipmi_opened--; 233 IPMI_UNLOCK(sc); 234 235 /* Cleanup. */ 236 kfree(dev, M_IPMI); 237 } 238 239 #ifdef IPMB 240 static int 241 ipmi_ipmb_checksum(u_char *data, int len) 242 { 243 u_char sum = 0; 244 245 for (; len; len--) { 246 sum += *data++; 247 } 248 return (-sum); 249 } 250 251 /* XXX: Needs work */ 252 static int 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) 255 { 256 struct ipmi_softc *sc = device_get_softc(dev); 257 struct ipmi_request *req; 258 u_char slave_addr = 0x52; 259 int error; 260 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; 270 271 bcopy(data, &req->ir_request[7], data_len); 272 temp[data_len + 7] = ipmi_ipmb_checksum(&req->ir_request[4], 273 data_len + 3); 274 275 ipmi_submit_driver_request(sc, req); 276 error = req->ir_error; 277 ipmi_free_request(req); 278 279 return (error); 280 } 281 282 static int 283 ipmi_handle_attn(struct ipmi_softc *sc) 284 { 285 struct ipmi_request *req; 286 int error; 287 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); 291 292 ipmi_submit_driver_request(sc, req); 293 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"); 297 } 298 if (req->ir_reply[0] & IPMI_WDT_PRE_TIMEOUT) { 299 device_printf(sc->ipmi_dev, 300 "watchdog about to go off"); 301 } 302 if (req->ir_reply[0] & IPMI_MSG_AVAILABLE) { 303 ipmi_free_request(req); 304 305 req = ipmi_alloc_driver_request( 306 IPMI_ADDR(IPMI_APP_REQUEST, 0), IPMI_GET_MSG, 0, 307 16); 308 309 device_printf(sc->ipmi_dev, "throw out message "); 310 dump_buf(temp, 16); 311 } 312 } 313 error = req->ir_error; 314 ipmi_free_request(req); 315 316 return (error); 317 } 318 #endif 319 320 #ifdef IPMICTL_SEND_COMMAND_32 321 #define PTRIN(p) ((void *)(uintptr_t)(p)) 322 #define PTROUT(p) ((uintptr_t)(p)) 323 #endif 324 325 static int 326 ipmi_ioctl(struct dev_ioctl_args *ap) 327 { 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; 341 union { 342 struct ipmi_req req; 343 struct ipmi_recv recv; 344 } thunk32; 345 #endif 346 int error, len; 347 348 error = devfs_get_cdevpriv(fp, (void **)&dev); 349 if (error) 350 return (error); 351 352 sc = cdev->si_drv1; 353 354 #ifdef IPMICTL_SEND_COMMAND_32 355 /* Convert 32-bit structures to native. */ 356 switch (cmd) { 357 case IPMICTL_SEND_COMMAND_32: 358 req = &thunk32.req; 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); 366 break; 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); 374 break; 375 } 376 #endif 377 378 switch (cmd) { 379 #ifdef IPMICTL_SEND_COMMAND_32 380 case IPMICTL_SEND_COMMAND_32: 381 #endif 382 case IPMICTL_SEND_COMMAND: 383 /* 384 * XXX: Need to add proper handling of this. 385 */ 386 error = copyin(req->addr, &addr, sizeof(addr)); 387 if (error) 388 return (error); 389 390 IPMI_LOCK(sc); 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, 395 ir_link); 396 dev->ipmi_requests--; 397 ipmi_free_request(kreq); 398 } 399 IPMI_UNLOCK(sc); 400 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, 405 req->msg.data_len); 406 if (error) { 407 ipmi_free_request(kreq); 408 return (error); 409 } 410 IPMI_LOCK(sc); 411 dev->ipmi_requests++; 412 error = sc->ipmi_enqueue_request(sc, kreq); 413 IPMI_UNLOCK(sc); 414 if (error) 415 return (error); 416 break; 417 #ifdef IPMICTL_SEND_COMMAND_32 418 case IPMICTL_RECEIVE_MSG_TRUNC_32: 419 case IPMICTL_RECEIVE_MSG_32: 420 #endif 421 case IPMICTL_RECEIVE_MSG_TRUNC: 422 case IPMICTL_RECEIVE_MSG: 423 error = copyin(recv->addr, &addr, sizeof(addr)); 424 if (error) 425 return (error); 426 427 IPMI_LOCK(sc); 428 kreq = TAILQ_FIRST(&dev->ipmi_completed_requests); 429 if (kreq == NULL) { 430 IPMI_UNLOCK(sc); 431 return (EAGAIN); 432 } 433 addr.channel = IPMI_BMC_CHANNEL; 434 /* XXX */ 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; 440 if (error) { 441 TAILQ_REMOVE(&dev->ipmi_completed_requests, kreq, 442 ir_link); 443 dev->ipmi_requests--; 444 IPMI_UNLOCK(sc); 445 ipmi_free_request(kreq); 446 return (error); 447 } 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 453 #endif 454 )) { 455 IPMI_UNLOCK(sc); 456 return (EMSGSIZE); 457 } 458 TAILQ_REMOVE(&dev->ipmi_completed_requests, kreq, ir_link); 459 dev->ipmi_requests--; 460 IPMI_UNLOCK(sc); 461 len = min(recv->msg.data_len, len); 462 recv->msg.data_len = len; 463 error = copyout(&addr, recv->addr,sizeof(addr)); 464 if (error == 0) 465 error = copyout(&kreq->ir_compcode, recv->msg.data, 1); 466 if (error == 0) 467 error = copyout(kreq->ir_reply, recv->msg.data + 1, 468 len - 1); 469 ipmi_free_request(kreq); 470 if (error) 471 return (error); 472 break; 473 case IPMICTL_SET_MY_ADDRESS_CMD: 474 IPMI_LOCK(sc); 475 dev->ipmi_address = *(int*)data; 476 IPMI_UNLOCK(sc); 477 break; 478 case IPMICTL_GET_MY_ADDRESS_CMD: 479 IPMI_LOCK(sc); 480 *(int*)data = dev->ipmi_address; 481 IPMI_UNLOCK(sc); 482 break; 483 case IPMICTL_SET_MY_LUN_CMD: 484 IPMI_LOCK(sc); 485 dev->ipmi_lun = *(int*)data & 0x3; 486 IPMI_UNLOCK(sc); 487 break; 488 case IPMICTL_GET_MY_LUN_CMD: 489 IPMI_LOCK(sc); 490 *(int*)data = dev->ipmi_lun; 491 IPMI_UNLOCK(sc); 492 break; 493 case IPMICTL_SET_GETS_EVENTS_CMD: 494 /* 495 device_printf(sc->ipmi_dev, 496 "IPMICTL_SET_GETS_EVENTS_CMD NA\n"); 497 */ 498 break; 499 case IPMICTL_REGISTER_FOR_CMD: 500 case IPMICTL_UNREGISTER_FOR_CMD: 501 return (EOPNOTSUPP); 502 default: 503 device_printf(sc->ipmi_dev, "Unknown IOCTL %lX\n", cmd); 504 return (ENOIOCTL); 505 } 506 507 #ifdef IPMICTL_SEND_COMMAND_32 508 /* Update changed fields in 32-bit structures. */ 509 switch (cmd) { 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; 517 break; 518 } 519 #endif 520 return (0); 521 } 522 523 /* 524 * Request management. 525 */ 526 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) 531 { 532 struct ipmi_request *req; 533 534 req = kmalloc(sizeof(struct ipmi_request) + requestlen + replylen, 535 M_IPMI, M_WAITOK | M_ZERO); 536 req->ir_owner = dev; 537 req->ir_msgid = msgid; 538 req->ir_addr = addr; 539 req->ir_command = command; 540 if (requestlen) { 541 req->ir_request = (char *)&req[1]; 542 req->ir_requestlen = requestlen; 543 } 544 if (replylen) { 545 req->ir_reply = (char *)&req[1] + requestlen; 546 req->ir_replybuflen = replylen; 547 } 548 return (req); 549 } 550 551 /* Free a request no longer in use. */ 552 void 553 ipmi_free_request(struct ipmi_request *req) 554 { 555 556 kfree(req, M_IPMI); 557 } 558 559 /* Store a processed request on the appropriate completion queue. */ 560 void 561 ipmi_complete_request(struct ipmi_softc *sc, struct ipmi_request *req) 562 { 563 struct ipmi_device *dev; 564 565 IPMI_LOCK_ASSERT(sc); 566 567 /* 568 * Anonymous requests (from inside the driver) always have a 569 * waiter that we awaken. 570 */ 571 if (req->ir_owner == NULL) 572 wakeup(req); 573 else { 574 dev = req->ir_owner; 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); 579 } 580 } 581 582 /* Enqueue an internal driver request and wait until it is completed. */ 583 int 584 ipmi_submit_driver_request(struct ipmi_softc *sc, struct ipmi_request *req, 585 int timo) 586 { 587 int error; 588 589 IPMI_LOCK(sc); 590 error = sc->ipmi_enqueue_request(sc, req); 591 if (error == 0) 592 error = lksleep(req, &sc->ipmi_lock, 0, "ipmireq", timo); 593 if (error == 0) 594 error = req->ir_error; 595 IPMI_UNLOCK(sc); 596 return (error); 597 } 598 599 /* 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. 604 */ 605 struct ipmi_request * 606 ipmi_dequeue_request(struct ipmi_softc *sc) 607 { 608 struct ipmi_request *req; 609 610 IPMI_LOCK_ASSERT(sc); 611 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) 615 return (NULL); 616 617 req = TAILQ_FIRST(&sc->ipmi_pending_requests); 618 TAILQ_REMOVE(&sc->ipmi_pending_requests, req, ir_link); 619 return (req); 620 } 621 622 /* Default implementation of ipmi_enqueue_request() for polled interfaces. */ 623 int 624 ipmi_polled_enqueue_request(struct ipmi_softc *sc, struct ipmi_request *req) 625 { 626 IPMI_LOCK_ASSERT(sc); 627 628 TAILQ_INSERT_TAIL(&sc->ipmi_pending_requests, req, ir_link); 629 630 cv_signal(&sc->ipmi_request_added); 631 return (0); 632 } 633 634 /* 635 * Watchdog event handler. 636 */ 637 static int 638 ipmi_set_watchdog(struct ipmi_softc *sc, unsigned int sec) 639 { 640 struct ipmi_request *req; 641 int error; 642 643 if (sec > 0xffff / 10) 644 return (EINVAL); 645 646 req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0), 647 IPMI_SET_WDOG, 6, 0); 648 649 if (sec) { 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; 657 } else { 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; 664 } 665 error = ipmi_submit_driver_request(sc, req, 0); 666 if (error) 667 device_printf(sc->ipmi_dev, "Failed to set watchdog\n"); 668 else if (sec) { 669 ipmi_free_request(req); 670 671 req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0), 672 IPMI_RESET_WDOG, 0, 0); 673 674 error = ipmi_submit_driver_request(sc, req, 0); 675 if (error) 676 device_printf(sc->ipmi_dev, 677 "Failed to reset watchdog\n"); 678 } 679 680 ipmi_free_request(req); 681 return (error); 682 /* 683 dump_watchdog(sc); 684 */ 685 } 686 687 static void 688 ipmi_watchdog(void *arg) 689 { 690 struct ipmi_softc *sc = (struct ipmi_softc *)arg; 691 int e; 692 693 if(sc->ipmi_wdog_period) { 694 e = ipmi_set_watchdog(sc, sc->ipmi_wdog_period + 1); 695 696 if (e == 0) 697 sc->ipmi_watchdog_active = 1; 698 else 699 ipmi_set_watchdog(sc, 0); 700 701 callout_reset(&sc->ipmi_watchdog, 702 sc->ipmi_wdog_period * hz, 703 &ipmi_watchdog, (void *)sc); 704 } 705 } 706 707 static void 708 ipmi_startup(void *arg) 709 { 710 struct ipmi_softc *sc = arg; 711 struct ipmi_request *req; 712 device_t dev; 713 int error, i; 714 715 config_intrhook_disestablish(&sc->ipmi_ich); 716 dev = sc->ipmi_dev; 717 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); 722 723 /* Initialize interface-dependent state. */ 724 error = sc->ipmi_startup(sc); 725 if (error) { 726 device_printf(dev, "Failed to initialize interface: %d\n", 727 error); 728 return; 729 } 730 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); 734 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); 739 return; 740 } else if (error) { 741 device_printf(dev, "Failed GET_DEVICE_ID: %d\n", error); 742 ipmi_free_request(req); 743 return; 744 } else if (req->ir_compcode != 0) { 745 device_printf(dev, 746 "Bad completion code for GET_DEVICE_ID: %d\n", 747 req->ir_compcode); 748 ipmi_free_request(req); 749 return; 750 } else if (req->ir_replylen < 5) { 751 device_printf(dev, "Short reply for GET_DEVICE_ID: %d\n", 752 req->ir_replylen); 753 ipmi_free_request(req); 754 return; 755 } 756 757 device_printf(dev, "IPMI device rev. %d, firmware rev. %d.%d%d, " 758 "version %d.%d\n", 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); 762 763 ipmi_free_request(req); 764 765 req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0), 766 IPMI_CLEAR_FLAGS, 1, 0); 767 768 ipmi_submit_driver_request(sc, req, 0); 769 770 /* XXX: Magic numbers */ 771 if (req->ir_compcode == 0xc0) { 772 device_printf(dev, "Clear flags is busy\n"); 773 } 774 if (req->ir_compcode == 0xc1) { 775 device_printf(dev, "Clear flags illegal\n"); 776 } 777 ipmi_free_request(req); 778 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; 783 784 ipmi_submit_driver_request(sc, req, 0); 785 786 if (req->ir_compcode != 0) { 787 ipmi_free_request(req); 788 break; 789 } 790 ipmi_free_request(req); 791 } 792 device_printf(dev, "Number of channels %d\n", i); 793 794 /* probe for watchdog */ 795 req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0), 796 IPMI_GET_WDOG, 0, 0); 797 798 ipmi_submit_driver_request(sc, req, 0); 799 800 if (req->ir_compcode == 0x00) { 801 struct sysctl_ctx_list *ctx; 802 struct sysctl_oid *tree; 803 struct sysctl_oid_list *child; 804 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 810 a callout */ 811 callout_init(&sc->ipmi_watchdog); 812 sc->ipmi_wdog_enable = 0; 813 sc->ipmi_wdog_period = 30; 814 815 ctx = device_get_sysctl_ctx(dev); 816 tree = device_get_sysctl_tree(dev); 817 child = SYSCTL_CHILDREN(tree); 818 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"); 827 828 } 829 ipmi_free_request(req); 830 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"); 835 return; 836 } 837 sc->ipmi_cdev->si_drv1 = sc; 838 } 839 840 int 841 ipmi_attach(device_t dev) 842 { 843 struct ipmi_softc *sc = device_get_softc(dev); 844 int error; 845 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); 849 if (error) { 850 device_printf(dev, "can't set up interrupt\n"); 851 return (error); 852 } 853 } 854 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"); 861 return (ENOMEM); 862 } 863 864 ipmi_attached = 1; 865 return (0); 866 } 867 868 int 869 ipmi_detach(device_t dev) 870 { 871 struct ipmi_softc *sc; 872 873 sc = device_get_softc(dev); 874 875 /* Fail if there are any open handles. */ 876 IPMI_LOCK(sc); 877 if (sc->ipmi_opened) { 878 IPMI_UNLOCK(sc); 879 return (EBUSY); 880 } 881 IPMI_UNLOCK(sc); 882 if (sc->ipmi_cdev) 883 destroy_dev(sc->ipmi_cdev); 884 885 /* Detach from watchdog handling and turn off watchdog. */ 886 callout_cancel(&sc->ipmi_watchdog); 887 ipmi_set_watchdog(sc, 0); 888 889 /* XXX: should use shutdown callout I think. */ 890 /* If the backend uses a kthread, shut it down. */ 891 IPMI_LOCK(sc); 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); 896 } 897 IPMI_UNLOCK(sc); 898 if (sc->ipmi_irq) 899 bus_teardown_intr(dev, sc->ipmi_irq_res, sc->ipmi_irq); 900 901 ipmi_release_resources(dev); 902 lockuninit(&sc->ipmi_lock); 903 return (0); 904 } 905 906 void 907 ipmi_release_resources(device_t dev) 908 { 909 struct ipmi_softc *sc; 910 int i; 911 912 sc = device_get_softc(dev); 913 if (sc->ipmi_irq) 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, 917 sc->ipmi_irq_res); 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]); 922 } 923 924 devclass_t ipmi_devclass; 925 926 /* XXX: Why? */ 927 static void 928 ipmi_unload(void *arg) 929 { 930 device_t * devs; 931 int count; 932 int i; 933 934 if (devclass_get_devices(ipmi_devclass, &devs, &count) != 0) 935 return; 936 for (i = 0; i < count; i++) 937 device_delete_child(device_get_parent(devs[i]), devs[i]); 938 kfree(devs, M_TEMP); 939 } 940 SYSUNINIT(ipmi_unload, SI_SUB_DRIVERS, SI_ORDER_FIRST, ipmi_unload, NULL); 941 942 static int 943 ipmi_watchdog_sysctl_enable(SYSCTL_HANDLER_ARGS) 944 { 945 struct ipmi_softc *sc; 946 int enable; 947 int error; 948 949 sc = oidp->oid_arg1; 950 951 IPMI_LOCK(sc); 952 enable = sc->ipmi_wdog_enable; 953 IPMI_UNLOCK(sc); 954 955 error = sysctl_handle_int(oidp, &enable, 0, req); 956 if(error || req->newptr == NULL) 957 return error; 958 959 IPMI_LOCK(sc); 960 sc->ipmi_wdog_enable = enable; 961 IPMI_UNLOCK(sc); 962 963 if (sc->ipmi_wdog_enable==0) { 964 callout_stop(&sc->ipmi_watchdog); 965 ipmi_set_watchdog(sc, 0); 966 } else { 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); 971 } 972 return 0; 973 } 974 975 static int 976 ipmi_watchdog_sysctl_period(SYSCTL_HANDLER_ARGS) 977 { 978 struct ipmi_softc *sc; 979 int error; 980 int period; 981 982 sc = oidp->oid_arg1; 983 984 IPMI_LOCK(sc); 985 period = sc->ipmi_wdog_period; 986 IPMI_UNLOCK(sc); 987 988 error = sysctl_handle_int(oidp, &period, 30, req); 989 990 if (error || req->newptr == NULL) 991 return error; 992 993 IPMI_LOCK(sc); 994 sc->ipmi_wdog_period = period; 995 IPMI_UNLOCK(sc); 996 997 return 0; 998 } 999 1000 #ifdef IMPI_DEBUG 1001 static void 1002 dump_buf(u_char *data, int len) 1003 { 1004 char buf[20]; 1005 char line[1024]; 1006 char temp[30]; 1007 int count = 0; 1008 int i=0; 1009 1010 printf("Address %p len %d\n", data, len); 1011 if (len > 256) 1012 len = 256; 1013 line[0] = '\000'; 1014 for (; len > 0; len--, data++) { 1015 sprintf(temp, "%02x ", *data); 1016 strcat(line, temp); 1017 if (*data >= ' ' && *data <= '~') 1018 buf[count] = *data; 1019 else if (*data >= 'A' && *data <= 'Z') 1020 buf[count] = *data; 1021 else 1022 buf[count] = '.'; 1023 if (++count == 16) { 1024 buf[count] = '\000'; 1025 count = 0; 1026 printf(" %3x %s %s\n", i, line, buf); 1027 i+=16; 1028 line[0] = '\000'; 1029 } 1030 } 1031 buf[count] = '\000'; 1032 1033 for (; count != 16; count++) { 1034 strcat(line, " "); 1035 } 1036 printf(" %3x %s %s\n", i, line, buf); 1037 } 1038 #endif 1039