diff options
author | Aaron Campbell <aaron@cvs.openbsd.org> | 2000-03-26 08:39:47 +0000 |
---|---|---|
committer | Aaron Campbell <aaron@cvs.openbsd.org> | 2000-03-26 08:39:47 +0000 |
commit | 28320e899fbfbbe660f759f96511b4ed754a9a0b (patch) | |
tree | 789ef853a5b4025e2d189b0a56408bd794bdadbc /sys/dev/usb/usb.c | |
parent | ee37c844b6cad757fe1b782a43e759d2e9570934 (diff) |
Sync with NetBSD.
Diffstat (limited to 'sys/dev/usb/usb.c')
-rw-r--r-- | sys/dev/usb/usb.c | 251 |
1 files changed, 181 insertions, 70 deletions
diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c index e23f43d46c0..22a3b3777cd 100644 --- a/sys/dev/usb/usb.c +++ b/sys/dev/usb/usb.c @@ -1,5 +1,5 @@ -/* $OpenBSD: usb.c,v 1.7 1999/11/11 15:57:40 ho Exp $ */ -/* $NetBSD: usb.c,v 1.28 1999/10/13 08:10:57 augustss Exp $ */ +/* $OpenBSD: usb.c,v 1.8 2000/03/26 08:39:46 aaron Exp $ */ +/* $NetBSD: usb.c,v 1.41 2000/03/16 00:46:38 augustss Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -51,15 +51,15 @@ #if defined(__NetBSD__) || defined(__OpenBSD__) #include <sys/device.h> #include <sys/kthread.h> +#include <sys/proc.h> #elif defined(__FreeBSD__) #include <sys/module.h> #include <sys/bus.h> -#include <sys/ioccom.h> +#include <sys/filio.h> #include <sys/uio.h> #endif #include <sys/conf.h> #include <sys/poll.h> -#include <sys/proc.h> #include <sys/select.h> #include <sys/vnode.h> #include <sys/signalvar.h> @@ -87,8 +87,17 @@ MALLOC_DEFINE(M_USBHC, "USBHC", "USB host controller"); #define DPRINTF(x) if (usbdebug) logprintf x #define DPRINTFN(n,x) if (usbdebug>(n)) logprintf x int usbdebug = 0; -int uhcidebug; -int ohcidebug; +#ifdef UHCI_DEBUG +int uhcidebug; +#endif +#ifdef OHCI_DEBUG +int ohcidebug; +#endif +/* + * 0 - do usual exploration + * 1 - do not use timeout exploration + * >1 - do no exploration + */ int usb_noexplore = 0; #else #define DPRINTF(x) @@ -100,8 +109,12 @@ struct usb_softc { usbd_bus_handle sc_bus; /* USB controller */ struct usbd_port sc_port; /* dummy port for root hub */ +#if defined (__FreeBSD__) + /* This part should be deleted when kthreads is available */ struct selinfo sc_consel; /* waiting for connect change */ +#else struct proc *sc_event_thread; +#endif char sc_dying; }; @@ -111,6 +124,7 @@ cdev_decl(usb); #elif defined(__FreeBSD__) d_open_t usbopen; d_close_t usbclose; +d_read_t usbread; d_ioctl_t usbioctl; int usbpoll __P((dev_t, int, struct proc *)); @@ -136,7 +150,7 @@ usbd_status usb_discover __P((struct usb_softc *)); void usb_create_event_thread __P((void *)); void usb_event_thread __P((void *)); -#define USB_MAX_EVENTS 50 +#define USB_MAX_EVENTS 100 struct usb_event_q { struct usb_event ue; SIMPLEQ_ENTRY(usb_event_q) next; @@ -146,11 +160,16 @@ int usb_nevents = 0; struct selinfo usb_selevent; struct proc *usb_async_proc; /* process who wants USB SIGIO */ int usb_dev_open = 0; +void usb_add_event __P((int, struct usb_event *)); int usb_get_next_event __P((struct usb_event *)); +#if defined(__NetBSD__) || defined(__OpenBSD__) /* Flag to see if we are in the cold boot process. */ extern int cold; +#endif + +static const char *usbrev_str[] = USBREV_STR; USB_DECLARE_DRIVER(usb); @@ -169,25 +188,42 @@ USB_ATTACH(usb) void *aux = device_get_ivars(self); #endif usbd_device_handle dev; - usbd_status r; - -#if defined(__NetBSD__) || defined(__OpenBSD__) - printf("\n"); -#elif defined(__FreeBSD__) + usbd_status err; + int usbrev; + struct usb_event ue; + +#if defined(__FreeBSD__) + printf("%s", USBDEVNAME(sc->sc_dev)); sc->sc_dev = self; #endif DPRINTF(("usbd_attach\n")); + usbd_init(); sc->sc_bus = aux; sc->sc_bus->usbctl = sc; sc->sc_port.power = USB_MAX_POWER; - r = usbd_new_device(USBDEV(sc->sc_dev), sc->sc_bus, 0, 0, 0, - &sc->sc_port); - if (r == USBD_NORMAL_COMPLETION) { + usbrev = sc->sc_bus->usbrev; + printf(": USB revision %s", usbrev_str[usbrev]); + if (usbrev != USBREV_1_0 && usbrev != USBREV_1_1) { + printf(", not supported\n"); + USB_ATTACH_ERROR_RETURN; + } + printf("\n"); + + /* Make sure not to use tsleep() if we are cold booting. */ + if (cold) + sc->sc_bus->use_polling++; + + ue.u.ue_ctrlr.ue_bus = USBDEVUNIT(sc->sc_dev); + usb_add_event(USB_EVENT_CTRLR_ATTACH, &ue); + + err = usbd_new_device(USBDEV(sc->sc_dev), sc->sc_bus, 0, 0, 0, + &sc->sc_port); + if (!err) { dev = sc->sc_port.device; - if (!dev->hub) { + if (dev->hub == NULL) { sc->sc_dying = 1; printf("%s: root device is not a hub\n", USBDEVNAME(sc->sc_dev)); @@ -200,23 +236,18 @@ USB_ATTACH(usb) * until the USB event thread is running, which means that * the keyboard will not work until after cold boot. */ - if (cold) { - sc->sc_bus->use_polling++; + if (cold && (sc->sc_dev.dv_cfdata->cf_flags & 1) dev->hub->explore(sc->sc_bus->root_hub); - sc->sc_bus->use_polling--; - } #endif } else { printf("%s: root hub problem, error=%d\n", - USBDEVNAME(sc->sc_dev), r); + USBDEVNAME(sc->sc_dev), err); sc->sc_dying = 1; } + if (cold) + sc->sc_bus->use_polling--; -#if defined(__NetBSD__) - kthread_create(usb_create_event_thread, sc); -#elif defined(__OpenBSD__) kthread_create_deferred(usb_create_event_thread, sc); -#endif #if defined(__FreeBSD__) make_dev(&usb_cdevsw, device_get_unit(self), UID_ROOT, GID_OPERATOR, @@ -253,13 +284,20 @@ usb_event_thread(arg) DPRINTF(("usb_event_thread: start\n")); + /* Make sure first discover does something. */ + sc->sc_bus->needs_explore = 1; + while (!sc->sc_dying) { #ifdef USB_DEBUG - if (!usb_noexplore) + if (usb_noexplore < 2) #endif usb_discover(sc); - (void)tsleep(&sc->sc_bus->needs_explore, - PWAIT, "usbevt", hz*60); + (void)tsleep(&sc->sc_bus->needs_explore, PWAIT, "usbevt", +#ifdef USB_DEBUG + usb_noexplore ? 0 : +#endif + hz*60 + ); DPRINTFN(2,("usb_event_thread: woke up\n")); } sc->sc_event_thread = 0; @@ -397,13 +435,20 @@ usbioctl(devt, cmd, data, flag, p) switch (cmd) { #if defined(__FreeBSD__) + /* This part should be deleted when kthreads is available */ case USB_DISCOVER: usb_discover(sc); break; #endif #ifdef USB_DEBUG case USB_SETDEBUG: - usbdebug = uhcidebug = ohcidebug = *(int *)data; + usbdebug = ((*(int *)data) & 0x000000ff); +#ifdef UHCI_DEBUG + uhcidebug = ((*(int *)data) & 0x0000ff00) >> 8; +#endif +#ifdef OHCI_DEBUG + ohcidebug = ((*(int *)data) & 0x00ff0000) >> 16; +#endif break; #endif case USB_REQUEST: @@ -414,7 +459,7 @@ usbioctl(devt, cmd, data, flag, p) struct uio uio; void *ptr = 0; int addr = ur->addr; - usbd_status r; + usbd_status err; int error = 0; DPRINTF(("usbioctl: USB_REQUEST addr=%d len=%d\n", addr, len)); @@ -442,10 +487,9 @@ usbioctl(devt, cmd, data, flag, p) goto ret; } } - r = usbd_do_request_flags(sc->sc_bus->devices[addr], - &ur->request, ptr, - ur->flags, &ur->actlen); - if (r != USBD_NORMAL_COMPLETION) { + err = usbd_do_request_flags(sc->sc_bus->devices[addr], + &ur->request, ptr, ur->flags, &ur->actlen); + if (err) { error = EIO; goto ret; } @@ -466,14 +510,14 @@ usbioctl(devt, cmd, data, flag, p) { struct usb_device_info *di = (void *)data; int addr = di->addr; - usbd_device_handle devh; + usbd_device_handle dev; if (addr < 1 || addr >= USB_MAX_DEVICES) return (EINVAL); - devh = sc->sc_bus->devices[addr]; - if (devh == 0) + dev = sc->sc_bus->devices[addr]; + if (dev == NULL) return (ENXIO); - usbd_fill_deviceinfo(devh, di); + usbd_fill_deviceinfo(dev, di); break; } @@ -495,25 +539,41 @@ usbpoll(dev, events, p) { int revents, mask, s; - if (minor(dev) != USB_DEV_MINOR) - return (ENXIO); + if (minor(dev) != USB_DEV_MINOR) { + revents = 0; + mask = POLLIN | POLLRDNORM; - revents = 0; - s = splusb(); - mask = POLLIN | POLLRDNORM; - if (events & mask) - if (usb_nevents > 0) + s = splusb(); + if (events & mask && usb_nevents > 0) revents |= events & mask; - - DPRINTFN(2, ("usbpoll: revents=0x%x\n", revents)); - if (revents == 0) { - if (events & mask) { - DPRINTFN(2, ("usbpoll: selrecord\n")); + if (revents == 0 && events & mask) selrecord(p, &usb_selevent); - } + splx(s); + + return(revents); + } else { +#if defined(__FreeBSD__) + /* This part should be deleted when kthreads is available */ + struct usb_softc *sc; + int unit = minor(dev); + + USB_GET_SC(usb, unit, sc); + + revents = 0; + mask = POLLOUT | POLLRDNORM; + + s = splusb(); + if (events & mask && sc->sc_bus->needs_explore) + revents |= events & mask; + if (revents == 0 && events & mask) + selrecord(p, &sc->sc_consel); + splx(s); + + return (revents); +#else + return (ENXIO); +#endif } - splx(s); - return (revents); } /* Explore device tree from the root. */ @@ -521,15 +581,31 @@ usbd_status usb_discover(sc) struct usb_softc *sc; { +#if defined(__FreeBSD__) + /* The splxxx parts should be deleted when kthreads is available */ + int s; +#endif /* * We need mutual exclusion while traversing the device tree, * but this is guaranteed since this function is only called * from the event thread for the controller. */ - do { +#if defined(__FreeBSD__) + s = splusb(); +#endif + while (sc->sc_bus->needs_explore && !sc->sc_dying) { sc->sc_bus->needs_explore = 0; +#if defined(__FreeBSD__) + splx(s); +#endif sc->sc_bus->root_hub->hub->explore(sc->sc_bus->root_hub); - } while (sc->sc_bus->needs_explore && !sc->sc_dying); +#if defined(__FreeBSD__) + s = splusb(); +#endif + } +#if defined(__FreeBSD__) + splx(s); +#endif return (USBD_NORMAL_COMPLETION); } @@ -538,6 +614,10 @@ usb_needs_explore(bus) usbd_bus_handle bus; { bus->needs_explore = 1; +#if defined(__FreeBSD__) + /* This part should be deleted when kthreads is available */ + selwakeup(&bus->usbctl->sc_consel); +#endif wakeup(&bus->needs_explore); } @@ -559,40 +639,66 @@ usb_get_next_event(ue) } void -usbd_add_event(type, devh) +usbd_add_dev_event(type, udev) + int type; + usbd_device_handle udev; +{ + struct usb_event ue; + + usbd_fill_deviceinfo(udev, &ue.u.ue_device); + usb_add_event(type, &ue); +} + +void +usbd_add_drv_event(type, udev, dev) int type; - usbd_device_handle devh; + usbd_device_handle udev; + device_ptr_t dev; +{ + struct usb_event ue; + + ue.u.ue_driver.ue_cookie = udev->cookie; + strncpy(ue.u.ue_driver.ue_devname, USBDEVPTRNAME(dev), + sizeof ue.u.ue_driver.ue_devname); + usb_add_event(type, &ue); +} + +void +usb_add_event(type, uep) + int type; + struct usb_event *uep; { struct usb_event_q *ueq; struct usb_event ue; struct timeval thetime; int s; + microtime(&thetime); + /* Don't want to wait here inside splusb() */ + ueq = malloc(sizeof *ueq, M_USBDEV, M_WAITOK); + ueq->ue = *uep; + ueq->ue.ue_type = type; + TIMEVAL_TO_TIMESPEC(&thetime, &ueq->ue.ue_time); + s = splusb(); if (++usb_nevents >= USB_MAX_EVENTS) { /* Too many queued events, drop an old one. */ DPRINTFN(-1,("usb: event dropped\n")); (void)usb_get_next_event(&ue); } - /* Don't want to wait here inside splusb() */ - ueq = malloc(sizeof *ueq, M_USBDEV, M_NOWAIT); - if (ueq == 0) { - printf("usb: no memory, event dropped\n"); - splx(s); - return; - } - ueq->ue.ue_type = type; - ueq->ue.ue_cookie = devh->cookie; - usbd_fill_deviceinfo(devh, &ueq->ue.ue_device); - microtime(&thetime); - TIMEVAL_TO_TIMESPEC(&thetime, &ueq->ue.ue_time); SIMPLEQ_INSERT_TAIL(&usb_events, ueq, next); wakeup(&usb_events); selwakeup(&usb_selevent); - if (usb_async_proc) + if (usb_async_proc != NULL) psignal(usb_async_proc, SIGIO); splx(s); } +void +usb_schedsoftintr(bus) + struct usbd_bus *bus; +{ + bus->methods->soft_intr(bus); +} #if defined(__NetBSD__) || defined(__OpenBSD__) int @@ -626,6 +732,7 @@ usb_detach(self, flags) int flags; { struct usb_softc *sc = (struct usb_softc *)self; + struct usb_event ue; DPRINTF(("usb_detach: start\n")); @@ -645,6 +752,10 @@ usb_detach(self, flags) } usbd_finish(); + + ue.u.ue_ctrlr.ue_bus = USBDEVUNIT(sc->sc_dev); + usb_add_event(USB_EVENT_CTRLR_DETACH, &ue); + return (0); } #elif defined(__FreeBSD__) |