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