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