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