1 /* $NetBSD: usb.c,v 1.39 2000/02/22 11:30:56 augustss Exp $ */ 2 /* $FreeBSD: src/sys/dev/usb/usb.c,v 1.20 1999/11/17 22:33:46 n_hibma 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 static usbd_status usb_discover __P((struct usb_softc *)); 150 static void usb_create_event_thread __P((void *)); 151 static void usb_event_thread __P((void *)); 152 153 #define USB_MAX_EVENTS 50 154 struct usb_event_q { 155 struct usb_event ue; 156 SIMPLEQ_ENTRY(usb_event_q) next; 157 }; 158 static SIMPLEQ_HEAD(, usb_event_q) usb_events = 159 SIMPLEQ_HEAD_INITIALIZER(usb_events); 160 static int usb_nevents = 0; 161 static struct selinfo usb_selevent; 162 static struct proc *usb_async_proc; /* process who wants USB SIGIO */ 163 static int usb_dev_open = 0; 164 static void usb_add_event __P((int, struct usb_event *)); 165 166 static int usb_get_next_event __P((struct usb_event *)); 167 168 #if defined(__NetBSD__) || defined(__OpenBSD__) 169 /* Flag to see if we are in the cold boot process. */ 170 extern int cold; 171 #endif 172 173 static const char *usbrev_str[] = USBREV_STR; 174 175 USB_DECLARE_DRIVER(usb); 176 177 USB_MATCH(usb) 178 { 179 DPRINTF(("usbd_match\n")); 180 return (UMATCH_GENERIC); 181 } 182 183 USB_ATTACH(usb) 184 { 185 #if defined(__NetBSD__) || defined(__OpenBSD__) 186 struct usb_softc *sc = (struct usb_softc *)self; 187 #elif defined(__FreeBSD__) 188 struct usb_softc *sc = device_get_softc(self); 189 void *aux = device_get_ivars(self); 190 #endif 191 usbd_device_handle dev; 192 usbd_status err; 193 int usbrev; 194 struct usb_event ue; 195 196 #if defined(__FreeBSD__) 197 printf("%s", USBDEVNAME(sc->sc_dev)); 198 sc->sc_dev = self; 199 #endif 200 201 DPRINTF(("usbd_attach\n")); 202 203 usbd_init(); 204 sc->sc_bus = aux; 205 sc->sc_bus->usbctl = sc; 206 sc->sc_port.power = USB_MAX_POWER; 207 208 usbrev = sc->sc_bus->usbrev; 209 printf(": USB revision %s", usbrev_str[usbrev]); 210 if (usbrev != USBREV_1_0 && usbrev != USBREV_1_1) { 211 printf(", not supported\n"); 212 USB_ATTACH_ERROR_RETURN; 213 } 214 printf("\n"); 215 216 /* Make sure not to use tsleep() if we are cold booting. */ 217 if (cold) 218 sc->sc_bus->use_polling++; 219 220 ue.u.ue_ctrlr.ue_bus = USBDEVUNIT(sc->sc_dev); 221 usb_add_event(USB_EVENT_CTRLR_ATTACH, &ue); 222 223 err = usbd_new_device(USBDEV(sc->sc_dev), sc->sc_bus, 0, 0, 0, 224 &sc->sc_port); 225 if (!err) { 226 dev = sc->sc_port.device; 227 if (dev->hub == NULL) { 228 sc->sc_dying = 1; 229 printf("%s: root device is not a hub\n", 230 USBDEVNAME(sc->sc_dev)); 231 USB_ATTACH_ERROR_RETURN; 232 } 233 sc->sc_bus->root_hub = dev; 234 #if 1 235 /* 236 * Turning this code off will delay attachment of USB devices 237 * until the USB event thread is running, which means that 238 * the keyboard will not work until after cold boot. 239 */ 240 if (cold && (sc->sc_dev.dv_cfdata->cf_flags & 1)) 241 dev->hub->explore(sc->sc_bus->root_hub); 242 #endif 243 } else { 244 printf("%s: root hub problem, error=%d\n", 245 USBDEVNAME(sc->sc_dev), err); 246 sc->sc_dying = 1; 247 } 248 if (cold) 249 sc->sc_bus->use_polling--; 250 251 config_pending_incr(); 252 kthread_create(usb_create_event_thread, sc); 253 254 #if defined(__FreeBSD__) 255 make_dev(&usb_cdevsw, device_get_unit(self), UID_ROOT, GID_OPERATOR, 256 0644, "usb%d", device_get_unit(self)); 257 #endif 258 259 USB_ATTACH_SUCCESS_RETURN; 260 } 261 262 #if defined(__NetBSD__) || defined(__OpenBSD__) 263 void 264 usb_create_event_thread(arg) 265 void *arg; 266 { 267 struct usb_softc *sc = arg; 268 269 if (kthread_create1(usb_event_thread, sc, &sc->sc_event_thread, 270 "%s", sc->sc_dev.dv_xname)) { 271 printf("%s: unable to create event thread for\n", 272 sc->sc_dev.dv_xname); 273 panic("usb_create_event_thread"); 274 } 275 } 276 277 void 278 usb_event_thread(arg) 279 void *arg; 280 { 281 struct usb_softc *sc = arg; 282 int first = 1; 283 284 DPRINTF(("usb_event_thread: start\n")); 285 286 while (!sc->sc_dying) { 287 #ifdef USB_DEBUG 288 if (usb_noexplore < 2) 289 #endif 290 usb_discover(sc); 291 if (first) { 292 config_pending_decr(); 293 first = 0; 294 } 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((void *)&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 /* 590 * We need mutual exclusion while traversing the device tree, 591 * but this is guaranteed since this function is only called 592 * from the event thread for the controller. 593 */ 594 #if defined(__FreeBSD__) 595 s = splusb(); 596 #endif 597 while (sc->sc_bus->needs_explore && !sc->sc_dying) { 598 sc->sc_bus->needs_explore = 0; 599 #if defined(__FreeBSD__) 600 splx(s); 601 #endif 602 sc->sc_bus->root_hub->hub->explore(sc->sc_bus->root_hub); 603 #if defined(__FreeBSD__) 604 s = splusb(); 605 #endif 606 } 607 #if defined(__FreeBSD__) 608 splx(s); 609 #endif 610 611 return (USBD_NORMAL_COMPLETION); 612 } 613 614 void 615 usb_needs_explore(bus) 616 usbd_bus_handle bus; 617 { 618 bus->needs_explore = 1; 619 #if defined(__FreeBSD__) 620 /* This part should be deleted when kthreads is available */ 621 selwakeup(&bus->usbctl->sc_consel); 622 #endif 623 wakeup(&bus->needs_explore); 624 } 625 626 /* Called at splusb() */ 627 int 628 usb_get_next_event(ue) 629 struct usb_event *ue; 630 { 631 struct usb_event_q *ueq; 632 633 if (usb_nevents <= 0) 634 return (0); 635 ueq = SIMPLEQ_FIRST(&usb_events); 636 *ue = ueq->ue; 637 SIMPLEQ_REMOVE_HEAD(&usb_events, ueq, next); 638 free(ueq, M_USBDEV); 639 usb_nevents--; 640 return (1); 641 } 642 643 void 644 usbd_add_dev_event(type, udev) 645 int type; 646 usbd_device_handle udev; 647 { 648 struct usb_event ue; 649 650 usbd_fill_deviceinfo(udev, &ue.u.ue_device); 651 usb_add_event(type, &ue); 652 } 653 654 void 655 usbd_add_drv_event(type, udev, dev) 656 int type; 657 usbd_device_handle udev; 658 device_ptr_t dev; 659 { 660 struct usb_event ue; 661 662 ue.u.ue_driver.ue_cookie = udev->cookie; 663 strncpy(ue.u.ue_driver.ue_devname, USBDEVPTRNAME(dev), 664 sizeof ue.u.ue_driver.ue_devname); 665 usb_add_event(type, &ue); 666 } 667 668 static void 669 usb_add_event(type, uep) 670 int type; 671 struct usb_event *uep; 672 { 673 struct usb_event_q *ueq; 674 struct usb_event ue; 675 struct timeval thetime; 676 int s; 677 678 microtime(&thetime); 679 /* Don't want to wait here inside splusb() */ 680 ueq = malloc(sizeof *ueq, M_USBDEV, M_WAITOK); 681 ueq->ue = *uep; 682 ueq->ue.ue_type = type; 683 TIMEVAL_TO_TIMESPEC(&thetime, &ueq->ue.ue_time); 684 685 s = splusb(); 686 if (++usb_nevents >= USB_MAX_EVENTS) { 687 /* Too many queued events, drop an old one. */ 688 DPRINTFN(-1,("usb: event dropped\n")); 689 (void)usb_get_next_event(&ue); 690 } 691 SIMPLEQ_INSERT_TAIL(&usb_events, ueq, next); 692 wakeup(&usb_events); 693 selwakeup(&usb_selevent); 694 if (usb_async_proc != NULL) 695 psignal(usb_async_proc, SIGIO); 696 splx(s); 697 } 698 void 699 usb_schedsoftintr(bus) 700 struct usbd_bus *bus; 701 { 702 bus->methods->soft_intr(bus); 703 } 704 705 #if defined(__NetBSD__) || defined(__OpenBSD__) 706 int 707 usb_activate(self, act) 708 device_ptr_t self; 709 enum devact act; 710 { 711 struct usb_softc *sc = (struct usb_softc *)self; 712 usbd_device_handle dev = sc->sc_port.device; 713 int i, rv = 0; 714 715 switch (act) { 716 case DVACT_ACTIVATE: 717 return (EOPNOTSUPP); 718 break; 719 720 case DVACT_DEACTIVATE: 721 sc->sc_dying = 1; 722 if (dev && dev->cdesc && dev->subdevs) { 723 for (i = 0; dev->subdevs[i]; i++) 724 rv |= config_deactivate(dev->subdevs[i]); 725 } 726 break; 727 } 728 return (rv); 729 } 730 731 int 732 usb_detach(self, flags) 733 device_ptr_t self; 734 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) 745 usb_disconnect_port(&sc->sc_port, self); 746 747 /* Kill off event thread. */ 748 if (sc->sc_event_thread) { 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 ue.u.ue_ctrlr.ue_bus = USBDEVUNIT(sc->sc_dev); 759 usb_add_event(USB_EVENT_CTRLR_DETACH, &ue); 760 761 return (0); 762 } 763 #elif defined(__FreeBSD__) 764 int 765 usb_detach(device_t self) 766 { 767 DPRINTF(("%s: unload, prevented\n", USBDEVNAME(self))); 768 769 return (EINVAL); 770 } 771 #endif 772 773 774 #if defined(__FreeBSD__) 775 DRIVER_MODULE(usb, ohci, usb_driver, usb_devclass, 0, 0); 776 DRIVER_MODULE(usb, uhci, usb_driver, usb_devclass, 0, 0); 777 #endif 778