1 /* $NetBSD: usb.c,v 1.65 2002/01/03 22:20:45 augustss Exp $ */ 2 3 /* 4 * Copyright (c) 1998, 2002 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Lennart Augustsson (lennart@augustsson.net) at 9 * Carlstedt Research & Technology. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* 41 * USB specifications and other documentation can be found at 42 * http://www.usb.org/developers/data/ and 43 * http://www.usb.org/developers/index.html . 44 */ 45 46 #include <sys/cdefs.h> 47 __KERNEL_RCSID(0, "$NetBSD: usb.c,v 1.65 2002/01/03 22:20:45 augustss Exp $"); 48 49 #include <sys/param.h> 50 #include <sys/systm.h> 51 #include <sys/kernel.h> 52 #include <sys/malloc.h> 53 #include <sys/device.h> 54 #include <sys/kthread.h> 55 #include <sys/proc.h> 56 #include <sys/conf.h> 57 #include <sys/poll.h> 58 #include <sys/select.h> 59 #include <sys/vnode.h> 60 #include <sys/signalvar.h> 61 62 #include <dev/usb/usb.h> 63 #include <dev/usb/usbdi.h> 64 #include <dev/usb/usbdi_util.h> 65 66 #define USB_DEV_MINOR 255 67 68 #include <machine/bus.h> 69 70 #include <dev/usb/usbdivar.h> 71 #include <dev/usb/usb_quirks.h> 72 73 #ifdef USB_DEBUG 74 #define DPRINTF(x) if (usbdebug) logprintf x 75 #define DPRINTFN(n,x) if (usbdebug>(n)) logprintf x 76 int usbdebug = 0; 77 #ifdef UHCI_DEBUG 78 int uhcidebug; 79 #endif 80 #ifdef OHCI_DEBUG 81 int ohcidebug; 82 #endif 83 /* 84 * 0 - do usual exploration 85 * 1 - do not use timeout exploration 86 * >1 - do no exploration 87 */ 88 int usb_noexplore = 0; 89 #else 90 #define DPRINTF(x) 91 #define DPRINTFN(n,x) 92 #endif 93 94 struct usb_softc { 95 USBBASEDEVICE sc_dev; /* base device */ 96 usbd_bus_handle sc_bus; /* USB controller */ 97 struct usbd_port sc_port; /* dummy port for root hub */ 98 99 struct proc *sc_event_thread; 100 101 char sc_dying; 102 }; 103 104 TAILQ_HEAD(, usb_task) usb_all_tasks; 105 106 cdev_decl(usb); 107 108 Static void usb_discover(void *); 109 Static void usb_create_event_thread(void *); 110 Static void usb_event_thread(void *); 111 Static void usb_task_thread(void *); 112 Static struct proc *usb_task_thread_proc = NULL; 113 114 #define USB_MAX_EVENTS 100 115 struct usb_event_q { 116 struct usb_event ue; 117 SIMPLEQ_ENTRY(usb_event_q) next; 118 }; 119 Static SIMPLEQ_HEAD(, usb_event_q) usb_events = 120 SIMPLEQ_HEAD_INITIALIZER(usb_events); 121 Static int usb_nevents = 0; 122 Static struct selinfo usb_selevent; 123 Static usb_proc_ptr usb_async_proc; /* process that wants USB SIGIO */ 124 Static int usb_dev_open = 0; 125 Static void usb_add_event(int, struct usb_event *); 126 127 Static int usb_get_next_event(struct usb_event *); 128 129 Static const char *usbrev_str[] = USBREV_STR; 130 131 USB_DECLARE_DRIVER(usb); 132 133 USB_MATCH(usb) 134 { 135 DPRINTF(("usbd_match\n")); 136 return (UMATCH_GENERIC); 137 } 138 139 USB_ATTACH(usb) 140 { 141 struct usb_softc *sc = (struct usb_softc *)self; 142 usbd_device_handle dev; 143 usbd_status err; 144 int usbrev; 145 int speed; 146 struct usb_event ue; 147 148 DPRINTF(("usbd_attach\n")); 149 150 usbd_init(); 151 sc->sc_bus = aux; 152 sc->sc_bus->usbctl = sc; 153 sc->sc_port.power = USB_MAX_POWER; 154 155 usbrev = sc->sc_bus->usbrev; 156 printf(": USB revision %s", usbrev_str[usbrev]); 157 switch (usbrev) { 158 case USBREV_1_0: 159 case USBREV_1_1: 160 speed = USB_SPEED_FULL; 161 break; 162 case USBREV_2_0: 163 speed = USB_SPEED_HIGH; 164 break; 165 default: 166 printf(", not supported\n"); 167 sc->sc_dying = 1; 168 USB_ATTACH_ERROR_RETURN; 169 } 170 printf("\n"); 171 172 /* Make sure not to use tsleep() if we are cold booting. */ 173 if (cold) 174 sc->sc_bus->use_polling++; 175 176 ue.u.ue_ctrlr.ue_bus = USBDEVUNIT(sc->sc_dev); 177 usb_add_event(USB_EVENT_CTRLR_ATTACH, &ue); 178 179 #ifdef USB_USE_SOFTINTR 180 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 181 /* XXX we should have our own level */ 182 sc->sc_bus->soft = softintr_establish(IPL_SOFTNET, 183 sc->sc_bus->methods->soft_intr, sc->sc_bus); 184 if (sc->sc_bus->soft == NULL) { 185 printf("%s: can't register softintr\n", USBDEVNAME(sc->sc_dev)); 186 sc->sc_dying = 1; 187 USB_ATTACH_ERROR_RETURN; 188 } 189 #else 190 callout_init(&sc->sc_bus->softi); 191 #endif 192 #endif 193 194 err = usbd_new_device(USBDEV(sc->sc_dev), sc->sc_bus, 0, speed, 0, 195 &sc->sc_port); 196 if (!err) { 197 dev = sc->sc_port.device; 198 if (dev->hub == NULL) { 199 sc->sc_dying = 1; 200 printf("%s: root device is not a hub\n", 201 USBDEVNAME(sc->sc_dev)); 202 USB_ATTACH_ERROR_RETURN; 203 } 204 sc->sc_bus->root_hub = dev; 205 #if 1 206 /* 207 * Turning this code off will delay attachment of USB devices 208 * until the USB event thread is running, which means that 209 * the keyboard will not work until after cold boot. 210 */ 211 if (cold && (sc->sc_dev.dv_cfdata->cf_flags & 1)) 212 dev->hub->explore(sc->sc_bus->root_hub); 213 #endif 214 } else { 215 printf("%s: root hub problem, error=%d\n", 216 USBDEVNAME(sc->sc_dev), err); 217 sc->sc_dying = 1; 218 } 219 if (cold) 220 sc->sc_bus->use_polling--; 221 222 config_pending_incr(); 223 usb_kthread_create(usb_create_event_thread, sc); 224 225 USB_ATTACH_SUCCESS_RETURN; 226 } 227 228 #if defined(__NetBSD__) || defined(__OpenBSD__) 229 void 230 usb_create_event_thread(void *arg) 231 { 232 struct usb_softc *sc = arg; 233 static int created = 0; 234 235 if (usb_kthread_create1(usb_event_thread, sc, &sc->sc_event_thread, 236 "%s", sc->sc_dev.dv_xname)) { 237 printf("%s: unable to create event thread for\n", 238 sc->sc_dev.dv_xname); 239 panic("usb_create_event_thread"); 240 } 241 if (!created) { 242 created = 1; 243 TAILQ_INIT(&usb_all_tasks); 244 if (usb_kthread_create1(usb_task_thread, NULL, 245 &usb_task_thread_proc, "usbtask")) { 246 printf("unable to create task thread\n"); 247 panic("usb_create_event_thread task"); 248 } 249 } 250 } 251 252 /* 253 * Add a task to be performed by the task thread. This function can be 254 * called from any context and the task will be executed in a process 255 * context ASAP. 256 */ 257 void 258 usb_add_task(usbd_device_handle dev, struct usb_task *task) 259 { 260 int s; 261 262 s = splusb(); 263 if (!task->onqueue) { 264 DPRINTFN(2,("usb_add_task: task=%p\n", task)); 265 TAILQ_INSERT_TAIL(&usb_all_tasks, task, next); 266 task->onqueue = 1; 267 } else { 268 DPRINTFN(3,("usb_add_task: task=%p on q\n", task)); 269 } 270 wakeup(&usb_all_tasks); 271 splx(s); 272 } 273 274 void 275 usb_rem_task(usbd_device_handle dev, struct usb_task *task) 276 { 277 int s; 278 279 s = splusb(); 280 if (task->onqueue) { 281 TAILQ_REMOVE(&usb_all_tasks, task, next); 282 task->onqueue = 0; 283 } 284 splx(s); 285 } 286 287 void 288 usb_event_thread(void *arg) 289 { 290 struct usb_softc *sc = arg; 291 292 DPRINTF(("usb_event_thread: start\n")); 293 294 /* 295 * In case this controller is a companion controller to an 296 * EHCI controller we need to wait until the EHCI controller 297 * has grabbed the port. 298 * XXX It would be nicer to do this with a tsleep(), but I don't 299 * know how to synchronize the creation of the threads so it 300 * will work. 301 */ 302 usb_delay_ms(sc->sc_bus, 500); 303 304 /* Make sure first discover does something. */ 305 sc->sc_bus->needs_explore = 1; 306 usb_discover(sc); 307 config_pending_decr(); 308 309 while (!sc->sc_dying) { 310 #ifdef USB_DEBUG 311 if (usb_noexplore < 2) 312 #endif 313 usb_discover(sc); 314 #ifdef USB_DEBUG 315 (void)tsleep(&sc->sc_bus->needs_explore, PWAIT, "usbevt", 316 usb_noexplore ? 0 : hz * 60); 317 #else 318 (void)tsleep(&sc->sc_bus->needs_explore, PWAIT, "usbevt", 319 hz * 60); 320 #endif 321 DPRINTFN(2,("usb_event_thread: woke up\n")); 322 } 323 sc->sc_event_thread = NULL; 324 325 /* In case parent is waiting for us to exit. */ 326 wakeup(sc); 327 328 DPRINTF(("usb_event_thread: exit\n")); 329 kthread_exit(0); 330 } 331 332 void 333 usb_task_thread(void *arg) 334 { 335 struct usb_task *task; 336 int s; 337 338 DPRINTF(("usb_task_thread: start\n")); 339 340 s = splusb(); 341 for (;;) { 342 task = TAILQ_FIRST(&usb_all_tasks); 343 if (task == NULL) { 344 tsleep(&usb_all_tasks, PWAIT, "usbtsk", 0); 345 task = TAILQ_FIRST(&usb_all_tasks); 346 } 347 DPRINTFN(2,("usb_task_thread: woke up task=%p\n", task)); 348 if (task != NULL) { 349 TAILQ_REMOVE(&usb_all_tasks, task, next); 350 task->onqueue = 0; 351 splx(s); 352 task->fun(task->arg); 353 s = splusb(); 354 } 355 } 356 } 357 358 int 359 usbctlprint(void *aux, const char *pnp) 360 { 361 /* only "usb"es can attach to host controllers */ 362 if (pnp) 363 printf("usb at %s", pnp); 364 365 return (UNCONF); 366 } 367 #endif /* defined(__NetBSD__) || defined(__OpenBSD__) */ 368 369 int 370 usbopen(dev_t dev, int flag, int mode, usb_proc_ptr p) 371 { 372 int unit = minor(dev); 373 struct usb_softc *sc; 374 375 if (unit == USB_DEV_MINOR) { 376 if (usb_dev_open) 377 return (EBUSY); 378 usb_dev_open = 1; 379 usb_async_proc = 0; 380 return (0); 381 } 382 383 USB_GET_SC_OPEN(usb, unit, sc); 384 385 if (sc->sc_dying) 386 return (EIO); 387 388 return (0); 389 } 390 391 int 392 usbread(dev_t dev, struct uio *uio, int flag) 393 { 394 struct usb_event ue; 395 int s, error, n; 396 397 if (minor(dev) != USB_DEV_MINOR) 398 return (ENXIO); 399 400 if (uio->uio_resid != sizeof(struct usb_event)) 401 return (EINVAL); 402 403 error = 0; 404 s = splusb(); 405 for (;;) { 406 n = usb_get_next_event(&ue); 407 if (n != 0) 408 break; 409 if (flag & IO_NDELAY) { 410 error = EWOULDBLOCK; 411 break; 412 } 413 error = tsleep(&usb_events, PZERO | PCATCH, "usbrea", 0); 414 if (error) 415 break; 416 } 417 splx(s); 418 if (!error) 419 error = uiomove((void *)&ue, uio->uio_resid, uio); 420 421 return (error); 422 } 423 424 int 425 usbclose(dev_t dev, int flag, int mode, usb_proc_ptr p) 426 { 427 int unit = minor(dev); 428 429 if (unit == USB_DEV_MINOR) { 430 usb_async_proc = 0; 431 usb_dev_open = 0; 432 } 433 434 return (0); 435 } 436 437 int 438 usbioctl(dev_t devt, u_long cmd, caddr_t data, int flag, usb_proc_ptr p) 439 { 440 struct usb_softc *sc; 441 int unit = minor(devt); 442 443 if (unit == USB_DEV_MINOR) { 444 switch (cmd) { 445 case FIONBIO: 446 /* All handled in the upper FS layer. */ 447 return (0); 448 449 case FIOASYNC: 450 if (*(int *)data) 451 usb_async_proc = p; 452 else 453 usb_async_proc = 0; 454 return (0); 455 456 default: 457 return (EINVAL); 458 } 459 } 460 461 USB_GET_SC(usb, unit, sc); 462 463 if (sc->sc_dying) 464 return (EIO); 465 466 switch (cmd) { 467 #ifdef USB_DEBUG 468 case USB_SETDEBUG: 469 usbdebug = ((*(int *)data) & 0x000000ff); 470 #ifdef UHCI_DEBUG 471 uhcidebug = ((*(int *)data) & 0x0000ff00) >> 8; 472 #endif 473 #ifdef OHCI_DEBUG 474 ohcidebug = ((*(int *)data) & 0x00ff0000) >> 16; 475 #endif 476 break; 477 #endif /* USB_DEBUG */ 478 case USB_REQUEST: 479 { 480 struct usb_ctl_request *ur = (void *)data; 481 int len = UGETW(ur->request.wLength); 482 struct iovec iov; 483 struct uio uio; 484 void *ptr = 0; 485 int addr = ur->addr; 486 usbd_status err; 487 int error = 0; 488 489 DPRINTF(("usbioctl: USB_REQUEST addr=%d len=%d\n", addr, len)); 490 if (len < 0 || len > 32768) 491 return (EINVAL); 492 if (addr < 0 || addr >= USB_MAX_DEVICES || 493 sc->sc_bus->devices[addr] == 0) 494 return (EINVAL); 495 if (len != 0) { 496 iov.iov_base = (caddr_t)ur->data; 497 iov.iov_len = len; 498 uio.uio_iov = &iov; 499 uio.uio_iovcnt = 1; 500 uio.uio_resid = len; 501 uio.uio_offset = 0; 502 uio.uio_segflg = UIO_USERSPACE; 503 uio.uio_rw = 504 ur->request.bmRequestType & UT_READ ? 505 UIO_READ : UIO_WRITE; 506 uio.uio_procp = p; 507 ptr = malloc(len, M_TEMP, M_WAITOK); 508 if (uio.uio_rw == UIO_WRITE) { 509 error = uiomove(ptr, len, &uio); 510 if (error) 511 goto ret; 512 } 513 } 514 err = usbd_do_request_flags(sc->sc_bus->devices[addr], 515 &ur->request, ptr, ur->flags, &ur->actlen); 516 if (err) { 517 error = EIO; 518 goto ret; 519 } 520 if (len != 0) { 521 if (uio.uio_rw == UIO_READ) { 522 error = uiomove(ptr, len, &uio); 523 if (error) 524 goto ret; 525 } 526 } 527 ret: 528 if (ptr) 529 free(ptr, M_TEMP); 530 return (error); 531 } 532 533 case USB_DEVICEINFO: 534 { 535 struct usb_device_info *di = (void *)data; 536 int addr = di->addr; 537 usbd_device_handle dev; 538 539 if (addr < 1 || addr >= USB_MAX_DEVICES) 540 return (EINVAL); 541 dev = sc->sc_bus->devices[addr]; 542 if (dev == NULL) 543 return (ENXIO); 544 usbd_fill_deviceinfo(dev, di, 1); 545 break; 546 } 547 548 case USB_DEVICESTATS: 549 *(struct usb_device_stats *)data = sc->sc_bus->stats; 550 break; 551 552 default: 553 return (EINVAL); 554 } 555 return (0); 556 } 557 558 int 559 usbpoll(dev_t dev, int events, usb_proc_ptr p) 560 { 561 int revents, mask, s; 562 563 if (minor(dev) == USB_DEV_MINOR) { 564 revents = 0; 565 mask = POLLIN | POLLRDNORM; 566 567 s = splusb(); 568 if (events & mask && usb_nevents > 0) 569 revents |= events & mask; 570 if (revents == 0 && events & mask) 571 selrecord(p, &usb_selevent); 572 splx(s); 573 574 return (revents); 575 } else { 576 return (ENXIO); 577 } 578 } 579 580 /* Explore device tree from the root. */ 581 Static void 582 usb_discover(void *v) 583 { 584 struct usb_softc *sc = v; 585 586 DPRINTFN(2,("usb_discover\n")); 587 #ifdef USB_DEBUG 588 if (usb_noexplore > 1) 589 return; 590 #endif 591 /* 592 * We need mutual exclusion while traversing the device tree, 593 * but this is guaranteed since this function is only called 594 * from the event thread for the controller. 595 */ 596 while (sc->sc_bus->needs_explore && !sc->sc_dying) { 597 sc->sc_bus->needs_explore = 0; 598 sc->sc_bus->root_hub->hub->explore(sc->sc_bus->root_hub); 599 } 600 } 601 602 void 603 usb_needs_explore(usbd_device_handle dev) 604 { 605 DPRINTFN(2,("usb_needs_explore\n")); 606 dev->bus->needs_explore = 1; 607 wakeup(&dev->bus->needs_explore); 608 } 609 610 /* Called at splusb() */ 611 int 612 usb_get_next_event(struct usb_event *ue) 613 { 614 struct usb_event_q *ueq; 615 616 if (usb_nevents <= 0) 617 return (0); 618 ueq = SIMPLEQ_FIRST(&usb_events); 619 #ifdef DIAGNOSTIC 620 if (ueq == NULL) { 621 printf("usb: usb_nevents got out of sync! %d\n", usb_nevents); 622 usb_nevents = 0; 623 return (0); 624 } 625 #endif 626 *ue = ueq->ue; 627 SIMPLEQ_REMOVE_HEAD(&usb_events, ueq, next); 628 free(ueq, M_USBDEV); 629 usb_nevents--; 630 return (1); 631 } 632 633 void 634 usbd_add_dev_event(int type, usbd_device_handle udev) 635 { 636 struct usb_event ue; 637 638 usbd_fill_deviceinfo(udev, &ue.u.ue_device, USB_EVENT_IS_ATTACH(type)); 639 usb_add_event(type, &ue); 640 } 641 642 void 643 usbd_add_drv_event(int type, usbd_device_handle udev, device_ptr_t dev) 644 { 645 struct usb_event ue; 646 647 ue.u.ue_driver.ue_cookie = udev->cookie; 648 strncpy(ue.u.ue_driver.ue_devname, USBDEVPTRNAME(dev), 649 sizeof ue.u.ue_driver.ue_devname); 650 usb_add_event(type, &ue); 651 } 652 653 Static void 654 usb_add_event(int type, struct usb_event *uep) 655 { 656 struct usb_event_q *ueq; 657 struct usb_event ue; 658 struct timeval thetime; 659 int s; 660 661 microtime(&thetime); 662 /* Don't want to wait here inside splusb() */ 663 ueq = malloc(sizeof *ueq, M_USBDEV, M_WAITOK); 664 ueq->ue = *uep; 665 ueq->ue.ue_type = type; 666 TIMEVAL_TO_TIMESPEC(&thetime, &ueq->ue.ue_time); 667 668 s = splusb(); 669 if (++usb_nevents >= USB_MAX_EVENTS) { 670 /* Too many queued events, drop an old one. */ 671 DPRINTFN(-1,("usb: event dropped\n")); 672 (void)usb_get_next_event(&ue); 673 } 674 SIMPLEQ_INSERT_TAIL(&usb_events, ueq, next); 675 wakeup(&usb_events); 676 selwakeup(&usb_selevent); 677 if (usb_async_proc != NULL) 678 psignal(usb_async_proc, SIGIO); 679 splx(s); 680 } 681 682 void 683 usb_schedsoftintr(usbd_bus_handle bus) 684 { 685 DPRINTFN(10,("usb_schedsoftintr: polling=%d\n", bus->use_polling)); 686 #ifdef USB_USE_SOFTINTR 687 if (bus->use_polling) { 688 bus->methods->soft_intr(bus); 689 } else { 690 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 691 softintr_schedule(bus->soft); 692 #else 693 if (!callout_pending(&bus->softi)) 694 callout_reset(&bus->softi, 0, bus->methods->soft_intr, 695 bus); 696 #endif /* __HAVE_GENERIC_SOFT_INTERRUPTS */ 697 } 698 #else 699 bus->methods->soft_intr(bus); 700 #endif /* USB_USE_SOFTINTR */ 701 } 702 703 int 704 usb_activate(device_ptr_t self, enum devact act) 705 { 706 struct usb_softc *sc = (struct usb_softc *)self; 707 usbd_device_handle dev = sc->sc_port.device; 708 int i, rv = 0; 709 710 switch (act) { 711 case DVACT_ACTIVATE: 712 return (EOPNOTSUPP); 713 break; 714 715 case DVACT_DEACTIVATE: 716 sc->sc_dying = 1; 717 if (dev != NULL && dev->cdesc != NULL && dev->subdevs != NULL) { 718 for (i = 0; dev->subdevs[i]; i++) 719 rv |= config_deactivate(dev->subdevs[i]); 720 } 721 break; 722 } 723 return (rv); 724 } 725 726 int 727 usb_detach(device_ptr_t self, int flags) 728 { 729 struct usb_softc *sc = (struct usb_softc *)self; 730 struct usb_event ue; 731 732 DPRINTF(("usb_detach: start\n")); 733 734 sc->sc_dying = 1; 735 736 /* Make all devices disconnect. */ 737 if (sc->sc_port.device != NULL) 738 usb_disconnect_port(&sc->sc_port, self); 739 740 /* Kill off event thread. */ 741 if (sc->sc_event_thread != NULL) { 742 wakeup(&sc->sc_bus->needs_explore); 743 if (tsleep(sc, PWAIT, "usbdet", hz * 60)) 744 printf("%s: event thread didn't die\n", 745 USBDEVNAME(sc->sc_dev)); 746 DPRINTF(("usb_detach: event thread dead\n")); 747 } 748 749 usbd_finish(); 750 751 #ifdef USB_USE_SOFTINTR 752 #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS 753 if (sc->sc_bus->soft != NULL) { 754 softintr_disestablish(sc->sc_bus->soft); 755 sc->sc_bus->soft = NULL; 756 } 757 #else 758 callout_stop(&sc->sc_bus->softi); 759 #endif 760 #endif 761 762 ue.u.ue_ctrlr.ue_bus = USBDEVUNIT(sc->sc_dev); 763 usb_add_event(USB_EVENT_CTRLR_DETACH, &ue); 764 765 return (0); 766 } 767