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$"); 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/bus.h> 33 #include <sys/condvar.h> 34 #include <sys/conf.h> 35 #include <sys/kernel.h> 36 #include <sys/malloc.h> 37 #include <sys/module.h> 38 #include <sys/poll.h> 39 #include <sys/rman.h> 40 #include <sys/selinfo.h> 41 #include <sys/sysctl.h> 42 #include <sys/watchdog.h> 43 44 #ifdef LOCAL_MODULE 45 #include <ipmi.h> 46 #include <ipmivars.h> 47 #else 48 #include <sys/ipmi.h> 49 #include <dev/ipmi/ipmivars.h> 50 #endif 51 52 #ifdef IPMB 53 static int ipmi_ipmb_checksum(u_char, int); 54 static int ipmi_ipmb_send_message(device_t, u_char, u_char, u_char, 55 u_char, u_char, int) 56 #endif 57 58 static d_ioctl_t ipmi_ioctl; 59 static d_poll_t ipmi_poll; 60 static d_open_t ipmi_open; 61 static void ipmi_dtor(void *arg); 62 63 int ipmi_attached = 0; 64 65 static int on = 1; 66 static SYSCTL_NODE(_hw, OID_AUTO, ipmi, CTLFLAG_RD, 0, 67 "IPMI driver parameters"); 68 SYSCTL_INT(_hw_ipmi, OID_AUTO, on, CTLFLAG_RW, 69 &on, 0, ""); 70 71 static struct cdevsw ipmi_cdevsw = { 72 .d_version = D_VERSION, 73 .d_open = ipmi_open, 74 .d_ioctl = ipmi_ioctl, 75 .d_poll = ipmi_poll, 76 .d_name = "ipmi", 77 }; 78 79 static MALLOC_DEFINE(M_IPMI, "ipmi", "ipmi"); 80 81 static int 82 ipmi_open(struct cdev *cdev, int flags, int fmt, struct thread *td) 83 { 84 struct ipmi_device *dev; 85 struct ipmi_softc *sc; 86 int error; 87 88 if (!on) 89 return (ENOENT); 90 91 /* Initialize the per file descriptor data. */ 92 dev = malloc(sizeof(struct ipmi_device), M_IPMI, M_WAITOK | M_ZERO); 93 error = devfs_set_cdevpriv(dev, ipmi_dtor); 94 if (error) { 95 free(dev, M_IPMI); 96 return (error); 97 } 98 99 sc = cdev->si_drv1; 100 TAILQ_INIT(&dev->ipmi_completed_requests); 101 dev->ipmi_address = IPMI_BMC_SLAVE_ADDR; 102 dev->ipmi_lun = IPMI_BMC_SMS_LUN; 103 dev->ipmi_softc = sc; 104 IPMI_LOCK(sc); 105 sc->ipmi_opened++; 106 IPMI_UNLOCK(sc); 107 108 return (0); 109 } 110 111 static int 112 ipmi_poll(struct cdev *cdev, int poll_events, struct thread *td) 113 { 114 struct ipmi_device *dev; 115 struct ipmi_softc *sc; 116 int revents = 0; 117 118 if (devfs_get_cdevpriv((void **)&dev)) 119 return (0); 120 121 sc = cdev->si_drv1; 122 IPMI_LOCK(sc); 123 if (poll_events & (POLLIN | POLLRDNORM)) { 124 if (!TAILQ_EMPTY(&dev->ipmi_completed_requests)) 125 revents |= poll_events & (POLLIN | POLLRDNORM); 126 if (dev->ipmi_requests == 0) 127 revents |= POLLERR; 128 } 129 130 if (revents == 0) { 131 if (poll_events & (POLLIN | POLLRDNORM)) 132 selrecord(td, &dev->ipmi_select); 133 } 134 IPMI_UNLOCK(sc); 135 136 return (revents); 137 } 138 139 static void 140 ipmi_purge_completed_requests(struct ipmi_device *dev) 141 { 142 struct ipmi_request *req; 143 144 while (!TAILQ_EMPTY(&dev->ipmi_completed_requests)) { 145 req = TAILQ_FIRST(&dev->ipmi_completed_requests); 146 TAILQ_REMOVE(&dev->ipmi_completed_requests, req, ir_link); 147 dev->ipmi_requests--; 148 ipmi_free_request(req); 149 } 150 } 151 152 static void 153 ipmi_dtor(void *arg) 154 { 155 struct ipmi_request *req, *nreq; 156 struct ipmi_device *dev; 157 struct ipmi_softc *sc; 158 159 dev = arg; 160 sc = dev->ipmi_softc; 161 162 IPMI_LOCK(sc); 163 if (dev->ipmi_requests) { 164 /* Throw away any pending requests for this device. */ 165 TAILQ_FOREACH_SAFE(req, &sc->ipmi_pending_requests, ir_link, 166 nreq) { 167 if (req->ir_owner == dev) { 168 TAILQ_REMOVE(&sc->ipmi_pending_requests, req, 169 ir_link); 170 dev->ipmi_requests--; 171 ipmi_free_request(req); 172 } 173 } 174 175 /* Throw away any pending completed requests for this device. */ 176 ipmi_purge_completed_requests(dev); 177 178 /* 179 * If we still have outstanding requests, they must be stuck 180 * in an interface driver, so wait for those to drain. 181 */ 182 dev->ipmi_closing = 1; 183 while (dev->ipmi_requests > 0) { 184 msleep(&dev->ipmi_requests, &sc->ipmi_lock, PWAIT, 185 "ipmidrain", 0); 186 ipmi_purge_completed_requests(dev); 187 } 188 } 189 sc->ipmi_opened--; 190 IPMI_UNLOCK(sc); 191 192 /* Cleanup. */ 193 free(dev, M_IPMI); 194 } 195 196 #ifdef IPMB 197 static int 198 ipmi_ipmb_checksum(u_char *data, int len) 199 { 200 u_char sum = 0; 201 202 for (; len; len--) { 203 sum += *data++; 204 } 205 return (-sum); 206 } 207 208 /* XXX: Needs work */ 209 static int 210 ipmi_ipmb_send_message(device_t dev, u_char channel, u_char netfn, 211 u_char command, u_char seq, u_char *data, int data_len) 212 { 213 struct ipmi_softc *sc = device_get_softc(dev); 214 struct ipmi_request *req; 215 u_char slave_addr = 0x52; 216 int error; 217 218 req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0), 219 IPMI_SEND_MSG, data_len + 8, 0); 220 req->ir_request[0] = channel; 221 req->ir_request[1] = slave_addr; 222 req->ir_request[2] = IPMI_ADDR(netfn, 0); 223 req->ir_request[3] = ipmi_ipmb_checksum(&req->ir_request[1], 2); 224 req->ir_request[4] = sc->ipmi_address; 225 req->ir_request[5] = IPMI_ADDR(seq, sc->ipmi_lun); 226 req->ir_request[6] = command; 227 228 bcopy(data, &req->ir_request[7], data_len); 229 temp[data_len + 7] = ipmi_ipmb_checksum(&req->ir_request[4], 230 data_len + 3); 231 232 ipmi_submit_driver_request(sc, req); 233 error = req->ir_error; 234 ipmi_free_request(req); 235 236 return (error); 237 } 238 239 static int 240 ipmi_handle_attn(struct ipmi_softc *sc) 241 { 242 struct ipmi_request *req; 243 int error; 244 245 device_printf(sc->ipmi_dev, "BMC has a message\n"); 246 req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0), 247 IPMI_GET_MSG_FLAGS, 0, 1); 248 249 ipmi_submit_driver_request(sc, req); 250 251 if (req->ir_error == 0 && req->ir_compcode == 0) { 252 if (req->ir_reply[0] & IPMI_MSG_BUFFER_FULL) { 253 device_printf(sc->ipmi_dev, "message buffer full"); 254 } 255 if (req->ir_reply[0] & IPMI_WDT_PRE_TIMEOUT) { 256 device_printf(sc->ipmi_dev, 257 "watchdog about to go off"); 258 } 259 if (req->ir_reply[0] & IPMI_MSG_AVAILABLE) { 260 ipmi_free_request(req); 261 262 req = ipmi_alloc_driver_request( 263 IPMI_ADDR(IPMI_APP_REQUEST, 0), IPMI_GET_MSG, 0, 264 16); 265 266 device_printf(sc->ipmi_dev, "throw out message "); 267 dump_buf(temp, 16); 268 } 269 } 270 error = req->ir_error; 271 ipmi_free_request(req); 272 273 return (error); 274 } 275 #endif 276 277 #ifdef IPMICTL_SEND_COMMAND_32 278 #define PTRIN(p) ((void *)(uintptr_t)(p)) 279 #define PTROUT(p) ((uintptr_t)(p)) 280 #endif 281 282 static int 283 ipmi_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, 284 int flags, struct thread *td) 285 { 286 struct ipmi_softc *sc; 287 struct ipmi_device *dev; 288 struct ipmi_request *kreq; 289 struct ipmi_req *req = (struct ipmi_req *)data; 290 struct ipmi_recv *recv = (struct ipmi_recv *)data; 291 struct ipmi_addr addr; 292 #ifdef IPMICTL_SEND_COMMAND_32 293 struct ipmi_req32 *req32 = (struct ipmi_req32 *)data; 294 struct ipmi_recv32 *recv32 = (struct ipmi_recv32 *)data; 295 union { 296 struct ipmi_req req; 297 struct ipmi_recv recv; 298 } thunk32; 299 #endif 300 int error, len; 301 302 error = devfs_get_cdevpriv((void **)&dev); 303 if (error) 304 return (error); 305 306 sc = cdev->si_drv1; 307 308 #ifdef IPMICTL_SEND_COMMAND_32 309 /* Convert 32-bit structures to native. */ 310 switch (cmd) { 311 case IPMICTL_SEND_COMMAND_32: 312 req = &thunk32.req; 313 req->addr = PTRIN(req32->addr); 314 req->addr_len = req32->addr_len; 315 req->msgid = req32->msgid; 316 req->msg.netfn = req32->msg.netfn; 317 req->msg.cmd = req32->msg.cmd; 318 req->msg.data_len = req32->msg.data_len; 319 req->msg.data = PTRIN(req32->msg.data); 320 break; 321 case IPMICTL_RECEIVE_MSG_TRUNC_32: 322 case IPMICTL_RECEIVE_MSG_32: 323 recv = &thunk32.recv; 324 recv->addr = PTRIN(recv32->addr); 325 recv->addr_len = recv32->addr_len; 326 recv->msg.data_len = recv32->msg.data_len; 327 recv->msg.data = PTRIN(recv32->msg.data); 328 break; 329 } 330 #endif 331 332 switch (cmd) { 333 #ifdef IPMICTL_SEND_COMMAND_32 334 case IPMICTL_SEND_COMMAND_32: 335 #endif 336 case IPMICTL_SEND_COMMAND: 337 /* 338 * XXX: Need to add proper handling of this. 339 */ 340 error = copyin(req->addr, &addr, sizeof(addr)); 341 if (error) 342 return (error); 343 344 IPMI_LOCK(sc); 345 /* clear out old stuff in queue of stuff done */ 346 /* XXX: This seems odd. */ 347 while ((kreq = TAILQ_FIRST(&dev->ipmi_completed_requests))) { 348 TAILQ_REMOVE(&dev->ipmi_completed_requests, kreq, 349 ir_link); 350 dev->ipmi_requests--; 351 ipmi_free_request(kreq); 352 } 353 IPMI_UNLOCK(sc); 354 355 kreq = ipmi_alloc_request(dev, req->msgid, 356 IPMI_ADDR(req->msg.netfn, 0), req->msg.cmd, 357 req->msg.data_len, IPMI_MAX_RX); 358 error = copyin(req->msg.data, kreq->ir_request, 359 req->msg.data_len); 360 if (error) { 361 ipmi_free_request(kreq); 362 return (error); 363 } 364 IPMI_LOCK(sc); 365 dev->ipmi_requests++; 366 error = sc->ipmi_enqueue_request(sc, kreq); 367 IPMI_UNLOCK(sc); 368 if (error) 369 return (error); 370 break; 371 #ifdef IPMICTL_SEND_COMMAND_32 372 case IPMICTL_RECEIVE_MSG_TRUNC_32: 373 case IPMICTL_RECEIVE_MSG_32: 374 #endif 375 case IPMICTL_RECEIVE_MSG_TRUNC: 376 case IPMICTL_RECEIVE_MSG: 377 error = copyin(recv->addr, &addr, sizeof(addr)); 378 if (error) 379 return (error); 380 381 IPMI_LOCK(sc); 382 kreq = TAILQ_FIRST(&dev->ipmi_completed_requests); 383 if (kreq == NULL) { 384 IPMI_UNLOCK(sc); 385 return (EAGAIN); 386 } 387 addr.channel = IPMI_BMC_CHANNEL; 388 /* XXX */ 389 recv->recv_type = IPMI_RESPONSE_RECV_TYPE; 390 recv->msgid = kreq->ir_msgid; 391 recv->msg.netfn = IPMI_REPLY_ADDR(kreq->ir_addr) >> 2; 392 recv->msg.cmd = kreq->ir_command; 393 error = kreq->ir_error; 394 if (error) { 395 TAILQ_REMOVE(&dev->ipmi_completed_requests, kreq, 396 ir_link); 397 dev->ipmi_requests--; 398 IPMI_UNLOCK(sc); 399 ipmi_free_request(kreq); 400 return (error); 401 } 402 len = kreq->ir_replylen + 1; 403 if (recv->msg.data_len < len && 404 (cmd == IPMICTL_RECEIVE_MSG 405 #ifdef IPMICTL_RECEIVE_MSG_32 406 || cmd == IPMICTL_RECEIVE_MSG_32 407 #endif 408 )) { 409 IPMI_UNLOCK(sc); 410 return (EMSGSIZE); 411 } 412 TAILQ_REMOVE(&dev->ipmi_completed_requests, kreq, ir_link); 413 dev->ipmi_requests--; 414 IPMI_UNLOCK(sc); 415 len = min(recv->msg.data_len, len); 416 recv->msg.data_len = len; 417 error = copyout(&addr, recv->addr,sizeof(addr)); 418 if (error == 0) 419 error = copyout(&kreq->ir_compcode, recv->msg.data, 1); 420 if (error == 0) 421 error = copyout(kreq->ir_reply, recv->msg.data + 1, 422 len - 1); 423 ipmi_free_request(kreq); 424 if (error) 425 return (error); 426 break; 427 case IPMICTL_SET_MY_ADDRESS_CMD: 428 IPMI_LOCK(sc); 429 dev->ipmi_address = *(int*)data; 430 IPMI_UNLOCK(sc); 431 break; 432 case IPMICTL_GET_MY_ADDRESS_CMD: 433 IPMI_LOCK(sc); 434 *(int*)data = dev->ipmi_address; 435 IPMI_UNLOCK(sc); 436 break; 437 case IPMICTL_SET_MY_LUN_CMD: 438 IPMI_LOCK(sc); 439 dev->ipmi_lun = *(int*)data & 0x3; 440 IPMI_UNLOCK(sc); 441 break; 442 case IPMICTL_GET_MY_LUN_CMD: 443 IPMI_LOCK(sc); 444 *(int*)data = dev->ipmi_lun; 445 IPMI_UNLOCK(sc); 446 break; 447 case IPMICTL_SET_GETS_EVENTS_CMD: 448 /* 449 device_printf(sc->ipmi_dev, 450 "IPMICTL_SET_GETS_EVENTS_CMD NA\n"); 451 */ 452 break; 453 case IPMICTL_REGISTER_FOR_CMD: 454 case IPMICTL_UNREGISTER_FOR_CMD: 455 return (EOPNOTSUPP); 456 default: 457 device_printf(sc->ipmi_dev, "Unknown IOCTL %lX\n", cmd); 458 return (ENOIOCTL); 459 } 460 461 #ifdef IPMICTL_SEND_COMMAND_32 462 /* Update changed fields in 32-bit structures. */ 463 switch (cmd) { 464 case IPMICTL_RECEIVE_MSG_TRUNC_32: 465 case IPMICTL_RECEIVE_MSG_32: 466 recv32->recv_type = recv->recv_type; 467 recv32->msgid = recv->msgid; 468 recv32->msg.netfn = recv->msg.netfn; 469 recv32->msg.cmd = recv->msg.cmd; 470 recv32->msg.data_len = recv->msg.data_len; 471 break; 472 } 473 #endif 474 return (0); 475 } 476 477 /* 478 * Request management. 479 */ 480 481 /* Allocate a new request with request and reply buffers. */ 482 struct ipmi_request * 483 ipmi_alloc_request(struct ipmi_device *dev, long msgid, uint8_t addr, 484 uint8_t command, size_t requestlen, size_t replylen) 485 { 486 struct ipmi_request *req; 487 488 req = malloc(sizeof(struct ipmi_request) + requestlen + replylen, 489 M_IPMI, M_WAITOK | M_ZERO); 490 req->ir_owner = dev; 491 req->ir_msgid = msgid; 492 req->ir_addr = addr; 493 req->ir_command = command; 494 if (requestlen) { 495 req->ir_request = (char *)&req[1]; 496 req->ir_requestlen = requestlen; 497 } 498 if (replylen) { 499 req->ir_reply = (char *)&req[1] + requestlen; 500 req->ir_replybuflen = replylen; 501 } 502 return (req); 503 } 504 505 /* Free a request no longer in use. */ 506 void 507 ipmi_free_request(struct ipmi_request *req) 508 { 509 510 free(req, M_IPMI); 511 } 512 513 /* Store a processed request on the appropriate completion queue. */ 514 void 515 ipmi_complete_request(struct ipmi_softc *sc, struct ipmi_request *req) 516 { 517 struct ipmi_device *dev; 518 519 IPMI_LOCK_ASSERT(sc); 520 521 /* 522 * Anonymous requests (from inside the driver) always have a 523 * waiter that we awaken. 524 */ 525 if (req->ir_owner == NULL) 526 wakeup(req); 527 else { 528 dev = req->ir_owner; 529 TAILQ_INSERT_TAIL(&dev->ipmi_completed_requests, req, ir_link); 530 selwakeup(&dev->ipmi_select); 531 if (dev->ipmi_closing) 532 wakeup(&dev->ipmi_requests); 533 } 534 } 535 536 /* Enqueue an internal driver request and wait until it is completed. */ 537 int 538 ipmi_submit_driver_request(struct ipmi_softc *sc, struct ipmi_request *req, 539 int timo) 540 { 541 int error; 542 543 IPMI_LOCK(sc); 544 error = sc->ipmi_enqueue_request(sc, req); 545 if (error == 0) 546 error = msleep(req, &sc->ipmi_lock, 0, "ipmireq", timo); 547 if (error == 0) 548 error = req->ir_error; 549 IPMI_UNLOCK(sc); 550 return (error); 551 } 552 553 /* 554 * Helper routine for polled system interfaces that use 555 * ipmi_polled_enqueue_request() to queue requests. This request 556 * waits until there is a pending request and then returns the first 557 * request. If the driver is shutting down, it returns NULL. 558 */ 559 struct ipmi_request * 560 ipmi_dequeue_request(struct ipmi_softc *sc) 561 { 562 struct ipmi_request *req; 563 564 IPMI_LOCK_ASSERT(sc); 565 566 while (!sc->ipmi_detaching && TAILQ_EMPTY(&sc->ipmi_pending_requests)) 567 cv_wait(&sc->ipmi_request_added, &sc->ipmi_lock); 568 if (sc->ipmi_detaching) 569 return (NULL); 570 571 req = TAILQ_FIRST(&sc->ipmi_pending_requests); 572 TAILQ_REMOVE(&sc->ipmi_pending_requests, req, ir_link); 573 return (req); 574 } 575 576 /* Default implementation of ipmi_enqueue_request() for polled interfaces. */ 577 int 578 ipmi_polled_enqueue_request(struct ipmi_softc *sc, struct ipmi_request *req) 579 { 580 581 IPMI_LOCK_ASSERT(sc); 582 583 TAILQ_INSERT_TAIL(&sc->ipmi_pending_requests, req, ir_link); 584 cv_signal(&sc->ipmi_request_added); 585 return (0); 586 } 587 588 /* 589 * Watchdog event handler. 590 */ 591 592 static int 593 ipmi_set_watchdog(struct ipmi_softc *sc, unsigned int sec) 594 { 595 struct ipmi_request *req; 596 int error; 597 598 if (sec > 0xffff / 10) 599 return (EINVAL); 600 601 req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0), 602 IPMI_SET_WDOG, 6, 0); 603 604 if (sec) { 605 req->ir_request[0] = IPMI_SET_WD_TIMER_DONT_STOP 606 | IPMI_SET_WD_TIMER_SMS_OS; 607 req->ir_request[1] = IPMI_SET_WD_ACTION_RESET; 608 req->ir_request[2] = 0; 609 req->ir_request[3] = 0; /* Timer use */ 610 req->ir_request[4] = (sec * 10) & 0xff; 611 req->ir_request[5] = (sec * 10) >> 8; 612 } else { 613 req->ir_request[0] = IPMI_SET_WD_TIMER_SMS_OS; 614 req->ir_request[1] = 0; 615 req->ir_request[2] = 0; 616 req->ir_request[3] = 0; /* Timer use */ 617 req->ir_request[4] = 0; 618 req->ir_request[5] = 0; 619 } 620 621 error = ipmi_submit_driver_request(sc, req, 0); 622 if (error) 623 device_printf(sc->ipmi_dev, "Failed to set watchdog\n"); 624 else if (sec) { 625 ipmi_free_request(req); 626 627 req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0), 628 IPMI_RESET_WDOG, 0, 0); 629 630 error = ipmi_submit_driver_request(sc, req, 0); 631 if (error) 632 device_printf(sc->ipmi_dev, 633 "Failed to reset watchdog\n"); 634 } 635 636 ipmi_free_request(req); 637 return (error); 638 /* 639 dump_watchdog(sc); 640 */ 641 } 642 643 static void 644 ipmi_wd_event(void *arg, unsigned int cmd, int *error) 645 { 646 struct ipmi_softc *sc = arg; 647 unsigned int timeout; 648 int e; 649 650 if (dumping) 651 return; 652 653 cmd &= WD_INTERVAL; 654 if (cmd > 0 && cmd <= 63) { 655 timeout = ((uint64_t)1 << cmd) / 1000000000; 656 if (timeout == 0) 657 timeout = 1; 658 e = ipmi_set_watchdog(sc, timeout); 659 if (e == 0) { 660 *error = 0; 661 sc->ipmi_watchdog_active = 1; 662 } else 663 (void)ipmi_set_watchdog(sc, 0); 664 } else if (atomic_readandclear_int(&sc->ipmi_watchdog_active) != 0) { 665 e = ipmi_set_watchdog(sc, 0); 666 if (e != 0 && cmd == 0) 667 *error = EOPNOTSUPP; 668 } 669 } 670 671 static void 672 ipmi_startup(void *arg) 673 { 674 struct ipmi_softc *sc = arg; 675 struct ipmi_request *req; 676 device_t dev; 677 int error, i; 678 679 config_intrhook_disestablish(&sc->ipmi_ich); 680 dev = sc->ipmi_dev; 681 682 /* Initialize interface-independent state. */ 683 mtx_init(&sc->ipmi_lock, device_get_nameunit(dev), "ipmi", MTX_DEF); 684 cv_init(&sc->ipmi_request_added, "ipmireq"); 685 TAILQ_INIT(&sc->ipmi_pending_requests); 686 687 /* Initialize interface-dependent state. */ 688 error = sc->ipmi_startup(sc); 689 if (error) { 690 device_printf(dev, "Failed to initialize interface: %d\n", 691 error); 692 return; 693 } 694 695 /* Send a GET_DEVICE_ID request. */ 696 req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0), 697 IPMI_GET_DEVICE_ID, 0, 15); 698 699 error = ipmi_submit_driver_request(sc, req, MAX_TIMEOUT); 700 if (error == EWOULDBLOCK) { 701 device_printf(dev, "Timed out waiting for GET_DEVICE_ID\n"); 702 ipmi_free_request(req); 703 return; 704 } else if (error) { 705 device_printf(dev, "Failed GET_DEVICE_ID: %d\n", error); 706 ipmi_free_request(req); 707 return; 708 } else if (req->ir_compcode != 0) { 709 device_printf(dev, 710 "Bad completion code for GET_DEVICE_ID: %d\n", 711 req->ir_compcode); 712 ipmi_free_request(req); 713 return; 714 } else if (req->ir_replylen < 5) { 715 device_printf(dev, "Short reply for GET_DEVICE_ID: %d\n", 716 req->ir_replylen); 717 ipmi_free_request(req); 718 return; 719 } 720 721 device_printf(dev, "IPMI device rev. %d, firmware rev. %d.%d%d, " 722 "version %d.%d\n", 723 req->ir_reply[1] & 0x0f, 724 req->ir_reply[2] & 0x7f, req->ir_reply[3] >> 4, req->ir_reply[3] & 0x0f, 725 req->ir_reply[4] & 0x0f, req->ir_reply[4] >> 4); 726 727 ipmi_free_request(req); 728 729 req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0), 730 IPMI_CLEAR_FLAGS, 1, 0); 731 732 ipmi_submit_driver_request(sc, req, 0); 733 734 /* XXX: Magic numbers */ 735 if (req->ir_compcode == 0xc0) { 736 device_printf(dev, "Clear flags is busy\n"); 737 } 738 if (req->ir_compcode == 0xc1) { 739 device_printf(dev, "Clear flags illegal\n"); 740 } 741 ipmi_free_request(req); 742 743 for (i = 0; i < 8; i++) { 744 req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0), 745 IPMI_GET_CHANNEL_INFO, 1, 0); 746 req->ir_request[0] = i; 747 748 ipmi_submit_driver_request(sc, req, 0); 749 750 if (req->ir_compcode != 0) { 751 ipmi_free_request(req); 752 break; 753 } 754 ipmi_free_request(req); 755 } 756 device_printf(dev, "Number of channels %d\n", i); 757 758 /* probe for watchdog */ 759 req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0), 760 IPMI_GET_WDOG, 0, 0); 761 762 ipmi_submit_driver_request(sc, req, 0); 763 764 if (req->ir_compcode == 0x00) { 765 device_printf(dev, "Attached watchdog\n"); 766 /* register the watchdog event handler */ 767 sc->ipmi_watchdog_tag = EVENTHANDLER_REGISTER(watchdog_list, 768 ipmi_wd_event, sc, 0); 769 } 770 ipmi_free_request(req); 771 772 sc->ipmi_cdev = make_dev(&ipmi_cdevsw, device_get_unit(dev), 773 UID_ROOT, GID_OPERATOR, 0660, "ipmi%d", device_get_unit(dev)); 774 if (sc->ipmi_cdev == NULL) { 775 device_printf(dev, "Failed to create cdev\n"); 776 return; 777 } 778 sc->ipmi_cdev->si_drv1 = sc; 779 } 780 781 int 782 ipmi_attach(device_t dev) 783 { 784 struct ipmi_softc *sc = device_get_softc(dev); 785 int error; 786 787 if (sc->ipmi_irq_res != NULL && sc->ipmi_intr != NULL) { 788 error = bus_setup_intr(dev, sc->ipmi_irq_res, INTR_TYPE_MISC, 789 NULL, sc->ipmi_intr, sc, &sc->ipmi_irq); 790 if (error) { 791 device_printf(dev, "can't set up interrupt\n"); 792 return (error); 793 } 794 } 795 796 bzero(&sc->ipmi_ich, sizeof(struct intr_config_hook)); 797 sc->ipmi_ich.ich_func = ipmi_startup; 798 sc->ipmi_ich.ich_arg = sc; 799 if (config_intrhook_establish(&sc->ipmi_ich) != 0) { 800 device_printf(dev, "can't establish configuration hook\n"); 801 return (ENOMEM); 802 } 803 804 ipmi_attached = 1; 805 return (0); 806 } 807 808 int 809 ipmi_detach(device_t dev) 810 { 811 struct ipmi_softc *sc; 812 813 sc = device_get_softc(dev); 814 815 /* Fail if there are any open handles. */ 816 IPMI_LOCK(sc); 817 if (sc->ipmi_opened) { 818 IPMI_UNLOCK(sc); 819 return (EBUSY); 820 } 821 IPMI_UNLOCK(sc); 822 if (sc->ipmi_cdev) 823 destroy_dev(sc->ipmi_cdev); 824 825 /* Detach from watchdog handling and turn off watchdog. */ 826 if (sc->ipmi_watchdog_tag) { 827 EVENTHANDLER_DEREGISTER(watchdog_list, sc->ipmi_watchdog_tag); 828 ipmi_set_watchdog(sc, 0); 829 } 830 831 /* XXX: should use shutdown callout I think. */ 832 /* If the backend uses a kthread, shut it down. */ 833 IPMI_LOCK(sc); 834 sc->ipmi_detaching = 1; 835 if (sc->ipmi_kthread) { 836 cv_broadcast(&sc->ipmi_request_added); 837 msleep(sc->ipmi_kthread, &sc->ipmi_lock, 0, "ipmi_wait", 0); 838 } 839 IPMI_UNLOCK(sc); 840 if (sc->ipmi_irq) 841 bus_teardown_intr(dev, sc->ipmi_irq_res, sc->ipmi_irq); 842 843 ipmi_release_resources(dev); 844 mtx_destroy(&sc->ipmi_lock); 845 return (0); 846 } 847 848 void 849 ipmi_release_resources(device_t dev) 850 { 851 struct ipmi_softc *sc; 852 int i; 853 854 sc = device_get_softc(dev); 855 if (sc->ipmi_irq) 856 bus_teardown_intr(dev, sc->ipmi_irq_res, sc->ipmi_irq); 857 if (sc->ipmi_irq_res) 858 bus_release_resource(dev, SYS_RES_IRQ, sc->ipmi_irq_rid, 859 sc->ipmi_irq_res); 860 for (i = 0; i < MAX_RES; i++) 861 if (sc->ipmi_io_res[i]) 862 bus_release_resource(dev, sc->ipmi_io_type, 863 sc->ipmi_io_rid + i, sc->ipmi_io_res[i]); 864 } 865 866 devclass_t ipmi_devclass; 867 868 /* XXX: Why? */ 869 static void 870 ipmi_unload(void *arg) 871 { 872 device_t * devs; 873 int count; 874 int i; 875 876 if (devclass_get_devices(ipmi_devclass, &devs, &count) != 0) 877 return; 878 for (i = 0; i < count; i++) 879 device_delete_child(device_get_parent(devs[i]), devs[i]); 880 free(devs, M_TEMP); 881 } 882 SYSUNINIT(ipmi_unload, SI_SUB_DRIVERS, SI_ORDER_FIRST, ipmi_unload, NULL); 883 884 #ifdef IMPI_DEBUG 885 static void 886 dump_buf(u_char *data, int len) 887 { 888 char buf[20]; 889 char line[1024]; 890 char temp[30]; 891 int count = 0; 892 int i=0; 893 894 printf("Address %p len %d\n", data, len); 895 if (len > 256) 896 len = 256; 897 line[0] = '\000'; 898 for (; len > 0; len--, data++) { 899 sprintf(temp, "%02x ", *data); 900 strcat(line, temp); 901 if (*data >= ' ' && *data <= '~') 902 buf[count] = *data; 903 else if (*data >= 'A' && *data <= 'Z') 904 buf[count] = *data; 905 else 906 buf[count] = '.'; 907 if (++count == 16) { 908 buf[count] = '\000'; 909 count = 0; 910 printf(" %3x %s %s\n", i, line, buf); 911 i+=16; 912 line[0] = '\000'; 913 } 914 } 915 buf[count] = '\000'; 916 917 for (; count != 16; count++) { 918 strcat(line, " "); 919 } 920 printf(" %3x %s %s\n", i, line, buf); 921 } 922 #endif 923