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