xref: /netbsd-src/sys/dev/usb/usb.c (revision 95d875fb90b1458e4f1de6950286ddcd6644bc61)
1 /*	$NetBSD: usb.c,v 1.36 1999/12/22 23:54:09 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 
165 static 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 
194 #if defined(__FreeBSD__)
195 	printf("%s", USBDEVNAME(sc->sc_dev));
196 	sc->sc_dev = self;
197 #endif
198 
199 	DPRINTF(("usbd_attach\n"));
200 
201 	usbd_init();
202 	sc->sc_bus = aux;
203 	sc->sc_bus->usbctl = sc;
204 	sc->sc_port.power = USB_MAX_POWER;
205 
206 	usbrev = sc->sc_bus->usbrev;
207 	printf(": USB revision %s", usbrev_str[usbrev]);
208 	if (usbrev != USBREV_1_0 && usbrev != USBREV_1_1) {
209 		printf(", not supported\n");
210 		USB_ATTACH_ERROR_RETURN;
211 	}
212 	printf("\n");
213 
214 	/* Make sure not to use tsleep() if we are cold booting. */
215 	if (cold)
216 		sc->sc_bus->use_polling++;
217 
218 	err = usbd_new_device(USBDEV(sc->sc_dev), sc->sc_bus, 0, 0, 0,
219 		  &sc->sc_port);
220 	if (!err) {
221 		dev = sc->sc_port.device;
222 		if (dev->hub == NULL) {
223 			sc->sc_dying = 1;
224 			printf("%s: root device is not a hub\n",
225 			       USBDEVNAME(sc->sc_dev));
226 			USB_ATTACH_ERROR_RETURN;
227 		}
228 		sc->sc_bus->root_hub = dev;
229 #if 1
230 		/*
231 		 * Turning this code off will delay attachment of USB devices
232 		 * until the USB event thread is running, which means that
233 		 * the keyboard will not work until after cold boot.
234 		 */
235 		if (cold && (sc->sc_dev.dv_cfdata->cf_flags & 1))
236 			dev->hub->explore(sc->sc_bus->root_hub);
237 #endif
238 	} else {
239 		printf("%s: root hub problem, error=%d\n",
240 		       USBDEVNAME(sc->sc_dev), err);
241 		sc->sc_dying = 1;
242 	}
243 	if (cold)
244 		sc->sc_bus->use_polling--;
245 
246 	kthread_create(usb_create_event_thread, sc);
247 
248 #if defined(__FreeBSD__)
249 	make_dev(&usb_cdevsw, device_get_unit(self), UID_ROOT, GID_OPERATOR,
250 		 0644, "usb%d", device_get_unit(self));
251 #endif
252 
253 	USB_ATTACH_SUCCESS_RETURN;
254 }
255 
256 #if defined(__NetBSD__) || defined(__OpenBSD__)
257 void
258 usb_create_event_thread(arg)
259 	void *arg;
260 {
261 	struct usb_softc *sc = arg;
262 
263 	if (kthread_create1(usb_event_thread, sc, &sc->sc_event_thread,
264 			   "%s", sc->sc_dev.dv_xname)) {
265 		printf("%s: unable to create event thread for\n",
266 		       sc->sc_dev.dv_xname);
267 		panic("usb_create_event_thread");
268 	}
269 }
270 
271 void
272 usb_event_thread(arg)
273 	void *arg;
274 {
275 	struct usb_softc *sc = arg;
276 
277 	DPRINTF(("usb_event_thread: start\n"));
278 
279 	while (!sc->sc_dying) {
280 #ifdef USB_DEBUG
281 		if (usb_noexplore < 2)
282 #endif
283 		usb_discover(sc);
284 		(void)tsleep(&sc->sc_bus->needs_explore, PWAIT, "usbevt",
285 #ifdef USB_DEBUG
286 			     usb_noexplore ? 0 :
287 #endif
288 			     hz*60
289 			);
290 		DPRINTFN(2,("usb_event_thread: woke up\n"));
291 	}
292 	sc->sc_event_thread = 0;
293 
294 	/* In case parent is waiting for us to exit. */
295 	wakeup(sc);
296 
297 	DPRINTF(("usb_event_thread: exit\n"));
298 	kthread_exit(0);
299 }
300 
301 int
302 usbctlprint(aux, pnp)
303 	void *aux;
304 	const char *pnp;
305 {
306 	/* only "usb"es can attach to host controllers */
307 	if (pnp)
308 		printf("usb at %s", pnp);
309 
310 	return (UNCONF);
311 }
312 #endif /* defined(__NetBSD__) || defined(__OpenBSD__) */
313 
314 int
315 usbopen(dev, flag, mode, p)
316 	dev_t dev;
317 	int flag, mode;
318 	struct proc *p;
319 {
320 	int unit = minor(dev);
321 	struct usb_softc *sc;
322 
323 	if (unit == USB_DEV_MINOR) {
324 		if (usb_dev_open)
325 			return (EBUSY);
326 		usb_dev_open = 1;
327 		usb_async_proc = 0;
328 		return (0);
329 	}
330 
331 	USB_GET_SC_OPEN(usb, unit, sc);
332 
333 	if (sc->sc_dying)
334 		return (EIO);
335 
336 	return (0);
337 }
338 
339 int
340 usbread(dev, uio, flag)
341 	dev_t dev;
342 	struct uio *uio;
343 	int flag;
344 {
345 	struct usb_event ue;
346 	int s, error, n;
347 
348 	if (minor(dev) != USB_DEV_MINOR)
349 		return (ENXIO);
350 
351 	if (uio->uio_resid != sizeof(struct usb_event))
352 		return (EINVAL);
353 
354 	error = 0;
355 	s = splusb();
356 	for (;;) {
357 		n = usb_get_next_event(&ue);
358 		if (n != 0)
359 			break;
360 		if (flag & IO_NDELAY) {
361 			error = EWOULDBLOCK;
362 			break;
363 		}
364 		error = tsleep(&usb_events, PZERO | PCATCH, "usbrea", 0);
365 		if (error)
366 			break;
367 	}
368 	splx(s);
369 	if (!error)
370 		error = uiomove((void *)&ue, uio->uio_resid, uio);
371 
372 	return (error);
373 }
374 
375 int
376 usbclose(dev, flag, mode, p)
377 	dev_t dev;
378 	int flag, mode;
379 	struct proc *p;
380 {
381 	int unit = minor(dev);
382 
383 	if (unit == USB_DEV_MINOR) {
384 		usb_async_proc = 0;
385 		usb_dev_open = 0;
386 	}
387 
388 	return (0);
389 }
390 
391 int
392 usbioctl(devt, cmd, data, flag, p)
393 	dev_t devt;
394 	u_long cmd;
395 	caddr_t data;
396 	int flag;
397 	struct proc *p;
398 {
399 	struct usb_softc *sc;
400 	int unit = minor(devt);
401 
402 	if (unit == USB_DEV_MINOR) {
403 		switch (cmd) {
404 		case FIONBIO:
405 			/* All handled in the upper FS layer. */
406 			return (0);
407 
408 		case FIOASYNC:
409 			if (*(int *)data)
410 				usb_async_proc = p;
411 			else
412 				usb_async_proc = 0;
413 			return (0);
414 
415 		default:
416 			return (EINVAL);
417 		}
418 	}
419 
420 	USB_GET_SC(usb, unit, sc);
421 
422 	if (sc->sc_dying)
423 		return (EIO);
424 
425 	switch (cmd) {
426 #if defined(__FreeBSD__)
427 	/* This part should be deleted when kthreads is available */
428   	case USB_DISCOVER:
429   		usb_discover(sc);
430   		break;
431 #endif
432 #ifdef USB_DEBUG
433 	case USB_SETDEBUG:
434 		usbdebug  = ((*(int *)data) & 0x000000ff);
435 #ifdef UHCI_DEBUG
436 		uhcidebug = ((*(int *)data) & 0x0000ff00) >> 8;
437 #endif
438 #ifdef OHCI_DEBUG
439 		ohcidebug = ((*(int *)data) & 0x00ff0000) >> 16;
440 #endif
441 		break;
442 #endif
443 	case USB_REQUEST:
444 	{
445 		struct usb_ctl_request *ur = (void *)data;
446 		int len = UGETW(ur->request.wLength);
447 		struct iovec iov;
448 		struct uio uio;
449 		void *ptr = 0;
450 		int addr = ur->addr;
451 		usbd_status err;
452 		int error = 0;
453 
454 		DPRINTF(("usbioctl: USB_REQUEST addr=%d len=%d\n", addr, len));
455 		if (len < 0 || len > 32768)
456 			return (EINVAL);
457 		if (addr < 0 || addr >= USB_MAX_DEVICES ||
458 		    sc->sc_bus->devices[addr] == 0)
459 			return (EINVAL);
460 		if (len != 0) {
461 			iov.iov_base = (caddr_t)ur->data;
462 			iov.iov_len = len;
463 			uio.uio_iov = &iov;
464 			uio.uio_iovcnt = 1;
465 			uio.uio_resid = len;
466 			uio.uio_offset = 0;
467 			uio.uio_segflg = UIO_USERSPACE;
468 			uio.uio_rw =
469 				ur->request.bmRequestType & UT_READ ?
470 				UIO_READ : UIO_WRITE;
471 			uio.uio_procp = p;
472 			ptr = malloc(len, M_TEMP, M_WAITOK);
473 			if (uio.uio_rw == UIO_WRITE) {
474 				error = uiomove(ptr, len, &uio);
475 				if (error)
476 					goto ret;
477 			}
478 		}
479 		err = usbd_do_request_flags(sc->sc_bus->devices[addr],
480 			  &ur->request, ptr, ur->flags, &ur->actlen);
481 		if (err) {
482 			error = EIO;
483 			goto ret;
484 		}
485 		if (len != 0) {
486 			if (uio.uio_rw == UIO_READ) {
487 				error = uiomove(ptr, len, &uio);
488 				if (error)
489 					goto ret;
490 			}
491 		}
492 	ret:
493 		if (ptr)
494 			free(ptr, M_TEMP);
495 		return (error);
496 	}
497 
498 	case USB_DEVICEINFO:
499 	{
500 		struct usb_device_info *di = (void *)data;
501 		int addr = di->addr;
502 		usbd_device_handle dev;
503 
504 		if (addr < 1 || addr >= USB_MAX_DEVICES)
505 			return (EINVAL);
506 		dev = sc->sc_bus->devices[addr];
507 		if (dev == NULL)
508 			return (ENXIO);
509 		usbd_fill_deviceinfo(dev, di);
510 		break;
511 	}
512 
513 	case USB_DEVICESTATS:
514 		*(struct usb_device_stats *)data = sc->sc_bus->stats;
515 		break;
516 
517 	default:
518 		return (EINVAL);
519 	}
520 	return (0);
521 }
522 
523 int
524 usbpoll(dev, events, p)
525 	dev_t dev;
526 	int events;
527 	struct proc *p;
528 {
529 	int revents, mask, s;
530 
531 	if (minor(dev) == USB_DEV_MINOR) {
532 		revents = 0;
533 		mask = POLLIN | POLLRDNORM;
534 
535 		s = splusb();
536 		if (events & mask && usb_nevents > 0)
537 			revents |= events & mask;
538 		if (revents == 0 && events & mask)
539 			selrecord(p, &usb_selevent);
540 		splx(s);
541 
542 		return (revents);
543 	} else {
544 #if defined(__FreeBSD__)
545 		/* This part should be deleted when kthreads is available */
546 		struct usb_softc *sc;
547 		int unit = minor(dev);
548 
549 		USB_GET_SC(usb, unit, sc);
550 
551 		revents = 0;
552 		mask = POLLOUT | POLLRDNORM;
553 
554 		s = splusb();
555 		if (events & mask && sc->sc_bus->needs_explore)
556 			revents |= events & mask;
557 		if (revents == 0 && events & mask)
558 			selrecord(p, &sc->sc_consel);
559 		splx(s);
560 
561 		return (revents);
562 #else
563 		return (ENXIO);
564 #endif
565 	}
566 }
567 
568 /* Explore device tree from the root. */
569 usbd_status
570 usb_discover(sc)
571 	struct usb_softc *sc;
572 {
573 #if defined(__FreeBSD__)
574 	/* The splxxx parts should be deleted when kthreads is available */
575 	int s;
576 #endif
577 
578 	/*
579 	 * We need mutual exclusion while traversing the device tree,
580 	 * but this is guaranteed since this function is only called
581 	 * from the event thread for the controller.
582 	 */
583 #if defined(__FreeBSD__)
584 	s = splusb();
585 #endif
586 	while (sc->sc_bus->needs_explore && !sc->sc_dying) {
587 		sc->sc_bus->needs_explore = 0;
588 #if defined(__FreeBSD__)
589 		splx(s);
590 #endif
591 		sc->sc_bus->root_hub->hub->explore(sc->sc_bus->root_hub);
592 #if defined(__FreeBSD__)
593 		s = splusb();
594 #endif
595 	}
596 #if defined(__FreeBSD__)
597 	splx(s);
598 #endif
599 
600 	return (USBD_NORMAL_COMPLETION);
601 }
602 
603 void
604 usb_needs_explore(bus)
605 	usbd_bus_handle bus;
606 {
607 	bus->needs_explore = 1;
608 #if defined(__FreeBSD__)
609 	/* This part should be deleted when kthreads is available */
610 	selwakeup(&bus->usbctl->sc_consel);
611 #endif
612 	wakeup(&bus->needs_explore);
613 }
614 
615 /* Called at splusb() */
616 int
617 usb_get_next_event(ue)
618 	struct usb_event *ue;
619 {
620 	struct usb_event_q *ueq;
621 
622 	if (usb_nevents <= 0)
623 		return (0);
624 	ueq = SIMPLEQ_FIRST(&usb_events);
625 	*ue = ueq->ue;
626 	SIMPLEQ_REMOVE_HEAD(&usb_events, ueq, next);
627 	free(ueq, M_USBDEV);
628 	usb_nevents--;
629 	return (1);
630 }
631 
632 void
633 usbd_add_event(type, dev)
634 	int type;
635 	usbd_device_handle dev;
636 {
637 	struct usb_event_q *ueq;
638 	struct usb_event ue;
639 	struct timeval thetime;
640 	int s;
641 
642 	s = splusb();
643 	if (++usb_nevents >= USB_MAX_EVENTS) {
644 		/* Too many queued events, drop an old one. */
645 		DPRINTFN(-1,("usb: event dropped\n"));
646 		(void)usb_get_next_event(&ue);
647 	}
648 	/* Don't want to wait here inside splusb() */
649 	ueq = malloc(sizeof *ueq, M_USBDEV, M_NOWAIT);
650 	if (ueq == NULL) {
651 		printf("usb: no memory, event dropped\n");
652 		splx(s);
653 		return;
654 	}
655 	ueq->ue.ue_type = type;
656 	ueq->ue.ue_cookie = dev->cookie;
657 	usbd_fill_deviceinfo(dev, &ueq->ue.ue_device);
658 	microtime(&thetime);
659 	TIMEVAL_TO_TIMESPEC(&thetime, &ueq->ue.ue_time);
660 	SIMPLEQ_INSERT_TAIL(&usb_events, ueq, next);
661 	wakeup(&usb_events);
662 	selwakeup(&usb_selevent);
663 	if (usb_async_proc != NULL)
664 		psignal(usb_async_proc, SIGIO);
665 	splx(s);
666 }
667 
668 #if defined(__NetBSD__) || defined(__OpenBSD__)
669 int
670 usb_activate(self, act)
671 	device_ptr_t self;
672 	enum devact act;
673 {
674 	struct usb_softc *sc = (struct usb_softc *)self;
675 	usbd_device_handle dev = sc->sc_port.device;
676 	int i, rv = 0;
677 
678 	switch (act) {
679 	case DVACT_ACTIVATE:
680 		return (EOPNOTSUPP);
681 		break;
682 
683 	case DVACT_DEACTIVATE:
684 		sc->sc_dying = 1;
685 		if (dev && dev->cdesc && dev->subdevs) {
686 			for (i = 0; dev->subdevs[i]; i++)
687 				rv |= config_deactivate(dev->subdevs[i]);
688 		}
689 		break;
690 	}
691 	return (rv);
692 }
693 
694 int
695 usb_detach(self, flags)
696 	device_ptr_t self;
697 	int flags;
698 {
699 	struct usb_softc *sc = (struct usb_softc *)self;
700 
701 	DPRINTF(("usb_detach: start\n"));
702 
703 	sc->sc_dying = 1;
704 
705 	/* Make all devices disconnect. */
706 	if (sc->sc_port.device)
707 		usb_disconnect_port(&sc->sc_port, self);
708 
709 	/* Kill off event thread. */
710 	if (sc->sc_event_thread) {
711 		wakeup(&sc->sc_bus->needs_explore);
712 		if (tsleep(sc, PWAIT, "usbdet", hz * 60))
713 			printf("%s: event thread didn't die\n",
714 			       USBDEVNAME(sc->sc_dev));
715 		DPRINTF(("usb_detach: event thread dead\n"));
716 	}
717 
718 	usbd_finish();
719 	return (0);
720 }
721 #elif defined(__FreeBSD__)
722 int
723 usb_detach(device_t self)
724 {
725 	DPRINTF(("%s: unload, prevented\n", USBDEVNAME(self)));
726 
727 	return (EINVAL);
728 }
729 #endif
730 
731 
732 #if defined(__FreeBSD__)
733 DRIVER_MODULE(usb, ohci, usb_driver, usb_devclass, 0, 0);
734 DRIVER_MODULE(usb, uhci, usb_driver, usb_devclass, 0, 0);
735 #endif
736