Sync with NetBSD.
authoraaron <aaron@openbsd.org>
Sun, 26 Mar 2000 08:39:45 +0000 (08:39 +0000)
committeraaron <aaron@openbsd.org>
Sun, 26 Mar 2000 08:39:45 +0000 (08:39 +0000)
25 files changed:
sys/dev/usb/hid.c
sys/dev/usb/ohci.c
sys/dev/usb/ohcireg.h
sys/dev/usb/ohcivar.h
sys/dev/usb/uaudio.c
sys/dev/usb/uaudioreg.h
sys/dev/usb/ugen.c
sys/dev/usb/uhci.c
sys/dev/usb/uhcireg.h
sys/dev/usb/uhcivar.h
sys/dev/usb/uhid.c
sys/dev/usb/uhub.c
sys/dev/usb/usb.c
sys/dev/usb/usb.h
sys/dev/usb/usb_mem.c
sys/dev/usb/usb_mem.h
sys/dev/usb/usb_port.h
sys/dev/usb/usb_quirks.c
sys/dev/usb/usb_quirks.h
sys/dev/usb/usb_subr.c
sys/dev/usb/usbdi.c
sys/dev/usb/usbdi.h
sys/dev/usb/usbdi_util.c
sys/dev/usb/usbdi_util.h
sys/dev/usb/usbdivar.h

index d2ef61d..58db47c 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: hid.c,v 1.3 1999/11/07 21:30:18 fgsch Exp $   */
-/*     $NetBSD: hid.c,v 1.7 1999/01/08 11:58:25 augustss Exp $ */
+/*     $OpenBSD: hid.c,v 1.4 2000/03/26 08:39:45 aaron Exp $   */
+/*     $NetBSD: hid.c,v 1.12 2000/03/17 18:16:18 augustss Exp $        */
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#if defined(__NetBSD__) || defined(__OpenBSD__)
 #include <sys/kernel.h>
-#include <sys/malloc.h>
-#if defined(__FreeBSD__)
-#include <sys/bus.h>
 #endif
+#include <sys/malloc.h>
  
 #include <dev/usb/usb.h>
 #include <dev/usb/usbhid.h>
@@ -112,7 +111,7 @@ void
 hid_end_parse(s)
        struct hid_data *s;
 {
-       while (s->cur.next) {
+       while (s->cur.next != NULL) {
                struct hid_item *hi = s->cur.next->next;
                free(s->cur.next, M_TEMP);
                s->cur.next = hi;
@@ -126,7 +125,8 @@ hid_get_item(s, h)
        struct hid_item *h;
 {
        struct hid_item *c = &s->cur;
-       int bTag, bType, bSize;
+       unsigned int bTag, bType, bSize;
+       struct hid_location oldloc;
        u_char *data;
        int32_t dval;
        u_char *p;
@@ -134,7 +134,7 @@ hid_get_item(s, h)
        int i;
 
  top:
-       if (s->multimax) {
+       if (s->multimax != 0) {
                if (s->multi < s->multimax) {
                        c->usage = s->usages[min(s->multi, s->nu-1)];
                        s->multi++;
@@ -300,7 +300,9 @@ hid_get_item(s, h)
                                break;
                        case 11: /* Pop */
                                hi = c->next;
+                               oldloc = c->loc;
                                s->cur = *hi;
+                               c->loc = oldloc;
                                free(hi, M_TEMP);
                                break;
                        default:
@@ -381,11 +383,11 @@ hid_report_size(buf, len, k, idp)
 
        id = 0;
        for (d = hid_start_parse(buf, len, 1<<k); hid_get_item(d, &h); )
-               if (h.report_ID)
+               if (h.report_ID != 0)
                        id = h.report_ID;
        hid_end_parse(d);
        size = h.loc.pos;
-       if (id) {
+       if (id != 0) {
                size += 8;
                *idp = id;      /* XXX wrong */
        } else
@@ -407,9 +409,9 @@ hid_locate(desc, size, u, k, loc, flags)
 
        for (d = hid_start_parse(desc, size, 1<<k); hid_get_item(d, &h); ) {
                if (h.kind == k && !(h.flags & HIO_CONST) && h.usage == u) {
-                       if (loc)
+                       if (loc != NULL)
                                *loc = h.loc;
-                       if (flags)
+                       if (flags != NULL)
                                *flags = h.flags;
                        hid_end_parse(d);
                        return (1);
@@ -457,15 +459,15 @@ hid_is_collection(desc, size, usage)
 {
        struct hid_data *hd;
        struct hid_item hi;
-       int r;
+       int err;
 
        hd = hid_start_parse(desc, size, hid_input);
-       if (!hd)
+       if (hd == NULL)
                return (0);
 
-       r = hid_get_item(hd, &hi) &&
+       err = hid_get_item(hd, &hi) &&
            hi.kind == hid_collection &&
            hi.usage == usage;
        hid_end_parse(hd);
-       return (r);
+       return (err);
 }
index fcabdb8..d57b51f 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: ohci.c,v 1.7 1999/11/07 21:30:19 fgsch Exp $  */
-/*     $NetBSD: ohci.c,v 1.48 1999/09/15 21:14:03 augustss Exp $       */
+/*     $OpenBSD: ohci.c,v 1.8 2000/03/26 08:39:45 aaron Exp $  */
+/*     $NetBSD: ohci.c,v 1.78 2000/03/20 00:37:00 augustss Exp $       */
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
 
 #include <sys/param.h>
 #include <sys/systm.h>
-#include <sys/kernel.h>
 #include <sys/malloc.h>
 #if defined(__NetBSD__) || defined(__OpenBSD__)
+#include <sys/kernel.h>
 #include <sys/device.h>
+#include <sys/select.h>
 #elif defined(__FreeBSD__)
 #include <sys/module.h>
 #include <sys/bus.h>
 #include <machine/bus_pio.h>
 #include <machine/bus_memio.h>
+#if defined(DIAGNOSTIC) && defined(__i386__) && defined(__FreeBSD__)
+#include <machine/cpu.h>
+#endif
 #endif
 #include <sys/proc.h>
 #include <sys/queue.h>
-#include <sys/select.h>
 
 #include <machine/bus.h>
 #include <machine/endian.h>
@@ -75,6 +78,7 @@
 
 #if defined(__FreeBSD__)
 #include <machine/clock.h>
+
 #define delay(d)                DELAY(d)
 #endif
 
@@ -111,64 +115,77 @@ void              ohci_free_sed __P((ohci_softc_t *, ohci_soft_ed_t *));
 ohci_soft_td_t *ohci_alloc_std __P((ohci_softc_t *));
 void           ohci_free_std __P((ohci_softc_t *, ohci_soft_td_t *));
 
+ohci_soft_itd_t *ohci_alloc_sitd __P((ohci_softc_t *));
+void ohci_free_sitd __P((ohci_softc_t *, ohci_soft_itd_t *));
+
+#if 0
 void           ohci_free_std_chain __P((ohci_softc_t *, 
                                         ohci_soft_td_t *, ohci_soft_td_t *));
+#endif
 usbd_status    ohci_alloc_std_chain __P((struct ohci_pipe *, ohci_softc_t *,
-                                         int, int, int, usb_dma_t *, 
+                                         int, int, usbd_xfer_handle,
                                          ohci_soft_td_t *,
                                          ohci_soft_td_t **));
 
+void           ohci_shutdown __P((void *v));
 void           ohci_power __P((int, void *));
 usbd_status    ohci_open __P((usbd_pipe_handle));
 void           ohci_poll __P((struct usbd_bus *));
-void           ohci_waitintr __P((ohci_softc_t *, usbd_request_handle));
-void           ohci_rhsc __P((ohci_softc_t *, usbd_request_handle));
-void           ohci_process_done __P((ohci_softc_t *, ohci_physaddr_t));
+void           ohci_softintr __P((struct usbd_bus *));
+void           ohci_waitintr __P((ohci_softc_t *, usbd_xfer_handle));
+void           ohci_rhsc __P((ohci_softc_t *, usbd_xfer_handle));
 
-usbd_status    ohci_device_request __P((usbd_request_handle reqh));
+usbd_status    ohci_device_request __P((usbd_xfer_handle xfer));
 void           ohci_add_ed __P((ohci_soft_ed_t *, ohci_soft_ed_t *));
 void           ohci_rem_ed __P((ohci_soft_ed_t *, ohci_soft_ed_t *));
 void           ohci_hash_add_td __P((ohci_softc_t *, ohci_soft_td_t *));
 void           ohci_hash_rem_td __P((ohci_softc_t *, ohci_soft_td_t *));
 ohci_soft_td_t *ohci_hash_find_td __P((ohci_softc_t *, ohci_physaddr_t));
 
+usbd_status    ohci_setup_isoc __P((usbd_pipe_handle pipe));
+void           ohci_device_isoc_enter __P((usbd_xfer_handle));
+
 usbd_status    ohci_allocm __P((struct usbd_bus *, usb_dma_t *, u_int32_t));
 void           ohci_freem __P((struct usbd_bus *, usb_dma_t *));
 
-usbd_status    ohci_root_ctrl_transfer __P((usbd_request_handle));
-usbd_status    ohci_root_ctrl_start __P((usbd_request_handle));
-void           ohci_root_ctrl_abort __P((usbd_request_handle));
+usbd_xfer_handle ohci_allocx __P((struct usbd_bus *));
+void           ohci_freex __P((struct usbd_bus *, usbd_xfer_handle));
+
+usbd_status    ohci_root_ctrl_transfer __P((usbd_xfer_handle));
+usbd_status    ohci_root_ctrl_start __P((usbd_xfer_handle));
+void           ohci_root_ctrl_abort __P((usbd_xfer_handle));
 void           ohci_root_ctrl_close __P((usbd_pipe_handle));
+void           ohci_root_ctrl_done __P((usbd_xfer_handle));
 
-usbd_status    ohci_root_intr_transfer __P((usbd_request_handle));
-usbd_status    ohci_root_intr_start __P((usbd_request_handle));
-void           ohci_root_intr_abort __P((usbd_request_handle));
+usbd_status    ohci_root_intr_transfer __P((usbd_xfer_handle));
+usbd_status    ohci_root_intr_start __P((usbd_xfer_handle));
+void           ohci_root_intr_abort __P((usbd_xfer_handle));
 void           ohci_root_intr_close __P((usbd_pipe_handle));
-void           ohci_root_intr_done  __P((usbd_request_handle));
+void           ohci_root_intr_done  __P((usbd_xfer_handle));
 
-usbd_status    ohci_device_ctrl_transfer __P((usbd_request_handle));
-usbd_status    ohci_device_ctrl_start __P((usbd_request_handle));
-void           ohci_device_ctrl_abort __P((usbd_request_handle));
+usbd_status    ohci_device_ctrl_transfer __P((usbd_xfer_handle));
+usbd_status    ohci_device_ctrl_start __P((usbd_xfer_handle));
+void           ohci_device_ctrl_abort __P((usbd_xfer_handle));
 void           ohci_device_ctrl_close __P((usbd_pipe_handle));
-void           ohci_device_ctrl_done  __P((usbd_request_handle));
+void           ohci_device_ctrl_done  __P((usbd_xfer_handle));
 
-usbd_status    ohci_device_bulk_transfer __P((usbd_request_handle));
-usbd_status    ohci_device_bulk_start __P((usbd_request_handle));
-void           ohci_device_bulk_abort __P((usbd_request_handle));
+usbd_status    ohci_device_bulk_transfer __P((usbd_xfer_handle));
+usbd_status    ohci_device_bulk_start __P((usbd_xfer_handle));
+void           ohci_device_bulk_abort __P((usbd_xfer_handle));
 void           ohci_device_bulk_close __P((usbd_pipe_handle));
-void           ohci_device_bulk_done  __P((usbd_request_handle));
+void           ohci_device_bulk_done  __P((usbd_xfer_handle));
 
-usbd_status    ohci_device_intr_transfer __P((usbd_request_handle));
-usbd_status    ohci_device_intr_start __P((usbd_request_handle));
-void           ohci_device_intr_abort __P((usbd_request_handle));
+usbd_status    ohci_device_intr_transfer __P((usbd_xfer_handle));
+usbd_status    ohci_device_intr_start __P((usbd_xfer_handle));
+void           ohci_device_intr_abort __P((usbd_xfer_handle));
 void           ohci_device_intr_close __P((usbd_pipe_handle));
-void           ohci_device_intr_done  __P((usbd_request_handle));
+void           ohci_device_intr_done  __P((usbd_xfer_handle));
 
-usbd_status    ohci_device_isoc_transfer __P((usbd_request_handle));
-usbd_status    ohci_device_isoc_start __P((usbd_request_handle));
-void           ohci_device_isoc_abort __P((usbd_request_handle));
+usbd_status    ohci_device_isoc_transfer __P((usbd_xfer_handle));
+usbd_status    ohci_device_isoc_start __P((usbd_xfer_handle));
+void           ohci_device_isoc_abort __P((usbd_xfer_handle));
 void           ohci_device_isoc_close __P((usbd_pipe_handle));
-void           ohci_device_isoc_done  __P((usbd_request_handle));
+void           ohci_device_isoc_done  __P((usbd_xfer_handle));
 
 usbd_status    ohci_device_setintr __P((ohci_softc_t *sc, 
                                         struct ohci_pipe *pipe, int ival));
@@ -180,15 +197,14 @@ void              ohci_rhsc_able __P((ohci_softc_t *, int));
 
 void           ohci_close_pipe __P((usbd_pipe_handle pipe, 
                                     ohci_soft_ed_t *head));
-void           ohci_abort_req __P((usbd_request_handle reqh,
+void           ohci_abort_xfer __P((usbd_xfer_handle xfer,
                                        usbd_status status));
-void           ohci_abort_req_end __P((void *));
+void           ohci_abort_xfer_end __P((void *));
 
 void           ohci_device_clear_toggle __P((usbd_pipe_handle pipe));
 void           ohci_noop __P((usbd_pipe_handle pipe));
 
 #ifdef OHCI_DEBUG
-ohci_softc_t   *thesc;
 void           ohci_dumpregs __P((ohci_softc_t *));
 void           ohci_dump_tds __P((ohci_soft_td_t *));
 void           ohci_dump_td __P((ohci_soft_td_t *));
@@ -209,7 +225,10 @@ static u_int8_t revbits[OHCI_NO_INTRS] =
 struct ohci_pipe {
        struct usbd_pipe pipe;
        ohci_soft_ed_t *sed;
-       ohci_soft_td_t *tail;
+       union {
+               ohci_soft_td_t *td;
+               ohci_soft_itd_t *itd;
+       } tail;
        /* Info needed for different pipe kinds. */
        union {
                /* Control pipe */
@@ -231,6 +250,7 @@ struct ohci_pipe {
                /* Iso pipe */
                struct iso {
                        int xxxxx;
+                       int next, inuse;
                } iso;
        } u;
 };
@@ -239,9 +259,12 @@ struct ohci_pipe {
 
 struct usbd_bus_methods ohci_bus_methods = {
        ohci_open,
+       ohci_softintr,
        ohci_poll,
        ohci_allocm,
        ohci_freem,
+       ohci_allocx,
+       ohci_freex,
 };
 
 struct usbd_pipe_methods ohci_root_ctrl_methods = {    
@@ -250,7 +273,7 @@ struct usbd_pipe_methods ohci_root_ctrl_methods = {
        ohci_root_ctrl_abort,
        ohci_root_ctrl_close,
        ohci_noop,
-       0,
+       ohci_root_ctrl_done,
 };
 
 struct usbd_pipe_methods ohci_root_intr_methods = {    
@@ -289,7 +312,6 @@ struct usbd_pipe_methods ohci_device_bulk_methods = {
        ohci_device_bulk_done,
 };
 
-#if 0
 struct usbd_pipe_methods ohci_device_isoc_methods = {
        ohci_device_isoc_transfer,
        ohci_device_isoc_start,
@@ -298,8 +320,8 @@ struct usbd_pipe_methods ohci_device_isoc_methods = {
        ohci_noop,
        ohci_device_isoc_done,
 };
-#endif
 
+#if defined(__NetBSD__) || defined(__OpenBSD__)
 int
 ohci_activate(self, act)
        device_ptr_t self;
@@ -335,25 +357,28 @@ ohci_detach(sc, flags)
                return (rv);
 
        powerhook_disestablish(sc->sc_powerhook);
+       shutdownhook_disestablish(sc->sc_shutdownhook);
+
        /* free data structures XXX */
 
        return (rv);
 }
+#endif
 
 ohci_soft_ed_t *
 ohci_alloc_sed(sc)
        ohci_softc_t *sc;
 {
        ohci_soft_ed_t *sed;
-       usbd_status r;
+       usbd_status err;
        int i, offs;
        usb_dma_t dma;
 
-       if (!sc->sc_freeeds) {
+       if (sc->sc_freeeds == NULL) {
                DPRINTFN(2, ("ohci_alloc_sed: allocating chunk\n"));
-               r = usb_allocmem(&sc->sc_bus, OHCI_SED_SIZE * OHCI_SED_CHUNK,
+               err = usb_allocmem(&sc->sc_bus, OHCI_SED_SIZE * OHCI_SED_CHUNK,
                                 OHCI_ED_ALIGN, &dma);
-               if (r != USBD_NORMAL_COMPLETION)
+               if (err)
                        return (0);
                for(i = 0; i < OHCI_SED_CHUNK; i++) {
                        offs = i * OHCI_SED_SIZE;
@@ -384,16 +409,18 @@ ohci_alloc_std(sc)
        ohci_softc_t *sc;
 {
        ohci_soft_td_t *std;
-       usbd_status r;
+       usbd_status err;
        int i, offs;
        usb_dma_t dma;
+       int s;
 
-       if (!sc->sc_freetds) {
+       if (sc->sc_freetds == NULL) {
                DPRINTFN(2, ("ohci_alloc_std: allocating chunk\n"));
-               r = usb_allocmem(&sc->sc_bus, OHCI_STD_SIZE * OHCI_STD_CHUNK,
+               err = usb_allocmem(&sc->sc_bus, OHCI_STD_SIZE * OHCI_STD_CHUNK,
                                 OHCI_TD_ALIGN, &dma);
-               if (r != USBD_NORMAL_COMPLETION)
+               if (err)
                        return (0);
+               s = splusb();
                for(i = 0; i < OHCI_STD_CHUNK; i++) {
                        offs = i * OHCI_STD_SIZE;
                        std = (ohci_soft_td_t *)((char *)KERNADDR(&dma) +offs);
@@ -401,11 +428,18 @@ ohci_alloc_std(sc)
                        std->nexttd = sc->sc_freetds;
                        sc->sc_freetds = std;
                }
+               splx(s);
        }
+
+       s = splusb();
        std = sc->sc_freetds;
        sc->sc_freetds = std->nexttd;
        memset(&std->td, 0, sizeof(ohci_td_t));
        std->nexttd = 0;
+
+       ohci_hash_add_td(sc, std);
+       splx(s);
+
        return (std);
 }
 
@@ -414,33 +448,46 @@ ohci_free_std(sc, std)
        ohci_softc_t *sc;
        ohci_soft_td_t *std;
 {
+       int s;
+
+       s = splusb();
+       ohci_hash_rem_td(sc, std);
+
        std->nexttd = sc->sc_freetds;
        sc->sc_freetds = std;
+       splx(s);
 }
 
 usbd_status
-ohci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
-       struct ohci_pipe *upipe;
+ohci_alloc_std_chain(opipe, sc, alen, rd, xfer, sp, ep)
+       struct ohci_pipe *opipe;
        ohci_softc_t *sc;
-       int len, rd, shortok;
-       usb_dma_t *dma;
+       int alen, rd;
+       usbd_xfer_handle xfer;
        ohci_soft_td_t *sp, **ep;
 {
        ohci_soft_td_t *next, *cur;
        ohci_physaddr_t dataphys, dataphysend;
-       u_int32_t intr;
-       int curlen;
+       u_int32_t tdflags;
+       int len, curlen;
+       usb_dma_t *dma = &xfer->dmabuf;
+       u_int16_t flags = xfer->flags;
 
-       DPRINTFN(len >= 4096,("ohci_alloc_std_chain: start len=%d\n", len));
+       DPRINTFN(alen < 4096,("ohci_alloc_std_chain: start len=%d\n", alen));
+
+       len = alen;
        cur = sp;
        dataphys = DMAADDR(dma);
        dataphysend = OHCI_PAGE(dataphys + len - 1);
+       tdflags = LE(
+           (rd ? OHCI_TD_IN : OHCI_TD_OUT) |
+           (flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0) |
+           OHCI_TD_NOCC | OHCI_TD_TOGGLE_CARRY | OHCI_TD_NOINTR);
+
        for (;;) {
                next = ohci_alloc_std(sc);
-               if (next == 0) {
-                       /* XXX free chain */
-                       return (USBD_NOMEM);
-               }
+               if (next == NULL)
+                       goto nomem;
 
                /* The OHCI hardware can handle at most one page crossing. */
                if (OHCI_PAGE(dataphys) == dataphysend ||
@@ -451,6 +498,12 @@ ohci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
                        /* must use multiple TDs, fill as much as possible. */
                        curlen = 2 * OHCI_PAGE_SIZE - 
                                 (dataphys & (OHCI_PAGE_SIZE-1));
+                       /* the length must be a multiple of the max size */
+                       curlen -= curlen % UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize);
+#ifdef DIAGNOSTIC
+                       if (curlen == 0)
+                               panic("ohci_alloc_std: curlen == 0\n");
+#endif
                }
                DPRINTFN(4,("ohci_alloc_std_chain: dataphys=0x%08x "
                            "dataphysend=0x%08x len=%d curlen=%d\n",
@@ -458,17 +511,14 @@ ohci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
                            len, curlen));
                len -= curlen;
 
-               intr = len == 0 ? OHCI_TD_SET_DI(1) : OHCI_TD_NOINTR;
-               cur->td.td_flags = LE(
-                       (rd ? OHCI_TD_IN : OHCI_TD_OUT) | OHCI_TD_NOCC |
-                       intr | OHCI_TD_TOGGLE_CARRY |
-                       (shortok ? OHCI_TD_R : 0));
+               cur->td.td_flags = tdflags;
                cur->td.td_cbp = LE(dataphys);
                cur->nexttd = next;
                cur->td.td_nexttd = LE(next->physaddr);
                cur->td.td_be = LE(dataphys + curlen - 1);
                cur->len = curlen;
                cur->flags = OHCI_ADD_LEN;
+               cur->xfer = xfer;
                DPRINTFN(10,("ohci_alloc_std_chain: cbp=0x%08x be=0x%08x\n",
                            dataphys, dataphys + curlen - 1));
                if (len == 0)
@@ -477,12 +527,35 @@ ohci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
                dataphys += curlen;
                cur = next;
        }
-       cur->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
-       *ep = next;
+       if ((flags & USBD_FORCE_SHORT_XFER) &&
+           alen % UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize) == 0) {
+               /* Force a 0 length transfer at the end. */
+
+               cur = next;
+               next = ohci_alloc_std(sc);
+               if (next == NULL)
+                       goto nomem;
+
+               cur->td.td_flags = tdflags;
+               cur->td.td_cbp = 0; /* indicate 0 length packet */
+               cur->nexttd = next;
+               cur->td.td_nexttd = LE(next->physaddr);
+               cur->td.td_be = ~0;
+               cur->len = 0;
+               cur->flags = 0;
+               cur->xfer = xfer;
+               DPRINTFN(2,("ohci_alloc_std_chain: add 0 xfer\n"));
+       }
+       *ep = cur;
 
        return (USBD_NORMAL_COMPLETION);
+
+nomem:
+       /* XXX free chain */
+       return (USBD_NOMEM);
 }
 
+#if 0
 void
 ohci_free_std_chain(sc, std, stdend)
        ohci_softc_t *sc;
@@ -496,84 +569,131 @@ ohci_free_std_chain(sc, std, stdend)
                ohci_free_std(sc, std);
        }
 }
+#endif
+
+ohci_soft_itd_t *
+ohci_alloc_sitd(sc)
+       ohci_softc_t *sc;
+{
+       ohci_soft_itd_t *sitd;
+       usbd_status err;
+       int i, offs;
+       usb_dma_t dma;
+
+       if (sc->sc_freeitds == NULL) {
+               DPRINTFN(2, ("ohci_alloc_sitd: allocating chunk\n"));
+               err = usb_allocmem(&sc->sc_bus, OHCI_STD_SIZE * OHCI_STD_CHUNK,
+                         OHCI_TD_ALIGN, &dma);
+               if (err)
+                       return (0);
+               for (i = 0; i < OHCI_STD_CHUNK; i++) {
+                       offs = i * OHCI_STD_SIZE;
+                       sitd = (ohci_soft_itd_t *)((char*)KERNADDR(&dma)+offs);
+                       sitd->physaddr = DMAADDR(&dma) + offs;
+                       sitd->nextitd = sc->sc_freeitds;
+                       sc->sc_freeitds = sitd;
+               }
+       }
+       sitd = sc->sc_freeitds;
+       sc->sc_freeitds = sitd->nextitd;
+       memset(&sitd->itd, 0, sizeof(ohci_itd_t));
+       sitd->nextitd = 0;
+       return (sitd);
+}
+
+void
+ohci_free_sitd(sc, sitd)
+       ohci_softc_t *sc;
+       ohci_soft_itd_t *sitd;
+{
+       sitd->nextitd = sc->sc_freeitds;
+       sc->sc_freeitds = sitd;
+}
 
 usbd_status
 ohci_init(sc)
        ohci_softc_t *sc;
 {
        ohci_soft_ed_t *sed, *psed;
-       usbd_status r;
-       int rev;
+       usbd_status err;
        int i;
-       u_int32_t s, ctl, ival, hcr, fm, per;
+       u_int32_t s, ctl, ival, hcr, fm, per, rev, desca;
 
        DPRINTF(("ohci_init: start\n"));
-       rev = OREAD4(sc, OHCI_REVISION);
 #if defined(__OpenBSD__)
-       printf(" version %d.%d%s", 
+       printf(",");
 #else
-       printf("%s: OHCI version %d.%d%s\n", USBDEVNAME(sc->sc_bus.bdev),
+       printf("%s:", USBDEVNAME(sc->sc_bus.bdev));
 #endif
-              OHCI_REV_HI(rev), OHCI_REV_LO(rev),
+       rev = OREAD4(sc, OHCI_REVISION);
+       printf(" OHCI version %d.%d%s\n", OHCI_REV_HI(rev), OHCI_REV_LO(rev),
               OHCI_REV_LEGACY(rev) ? ", legacy support" : "");
        if (OHCI_REV_HI(rev) != 1 || OHCI_REV_LO(rev) != 0) {
-#if defined(__OpenBSD__)
-               printf(": unsupported\n");
-#else
                printf("%s: unsupported OHCI revision\n", 
                       USBDEVNAME(sc->sc_bus.bdev));
-#endif
+               sc->sc_bus.usbrev = USBREV_UNKNOWN;
                return (USBD_INVAL);
-#if defined(__OpenBSD__)
-       } else {
-               printf("\n");
-#endif
        }
+       sc->sc_bus.usbrev = USBREV_1_0;
 
        for (i = 0; i < OHCI_HASH_SIZE; i++)
                LIST_INIT(&sc->sc_hash_tds[i]);
 
+       SIMPLEQ_INIT(&sc->sc_free_xfers);
+
+       /* XXX determine alignment by R/W */
        /* Allocate the HCCA area. */
-       r = usb_allocmem(&sc->sc_bus, OHCI_HCCA_SIZE, 
+       err = usb_allocmem(&sc->sc_bus, OHCI_HCCA_SIZE, 
                         OHCI_HCCA_ALIGN, &sc->sc_hccadma);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       if (err)
+               return (err);
        sc->sc_hcca = (struct ohci_hcca *)KERNADDR(&sc->sc_hccadma);
        memset(sc->sc_hcca, 0, OHCI_HCCA_SIZE);
 
        sc->sc_eintrs = OHCI_NORMAL_INTRS;
 
+       /* Allocate dummy ED that starts the control list. */
        sc->sc_ctrl_head = ohci_alloc_sed(sc);
-       if (!sc->sc_ctrl_head) {
-               r = USBD_NOMEM;
+       if (sc->sc_ctrl_head == NULL) {
+               err = USBD_NOMEM;
                goto bad1;
        }
        sc->sc_ctrl_head->ed.ed_flags |= LE(OHCI_ED_SKIP);
 
+       /* Allocate dummy ED that starts the bulk list. */
        sc->sc_bulk_head = ohci_alloc_sed(sc);
-       if (!sc->sc_bulk_head) {
-               r = USBD_NOMEM;
+       if (sc->sc_bulk_head == NULL) {
+               err = USBD_NOMEM;
                goto bad2;
        }
        sc->sc_bulk_head->ed.ed_flags |= LE(OHCI_ED_SKIP);
 
+       /* Allocate dummy ED that starts the isochronous list. */
+       sc->sc_isoc_head = ohci_alloc_sed(sc);
+       if (sc->sc_isoc_head == NULL) {
+               err = USBD_NOMEM;
+               goto bad3;
+       }
+       sc->sc_isoc_head->ed.ed_flags |= LE(OHCI_ED_SKIP);
+
        /* Allocate all the dummy EDs that make up the interrupt tree. */
        for (i = 0; i < OHCI_NO_EDS; i++) {
                sed = ohci_alloc_sed(sc);
-               if (!sed) {
+               if (sed == NULL) {
                        while (--i >= 0)
                                ohci_free_sed(sc, sc->sc_eds[i]);
-                       r = USBD_NOMEM;
-                       goto bad3;
+                       err = USBD_NOMEM;
+                       goto bad4;
                }
                /* All ED fields are set to 0. */
                sc->sc_eds[i] = sed;
                sed->ed.ed_flags |= LE(OHCI_ED_SKIP);
-               if (i != 0) {
+               if (i != 0)
                        psed = sc->sc_eds[(i-1) / 2];
-                       sed->next = psed;
-                       sed->ed.ed_nexted = LE(psed->physaddr);
-               }
+               else
+                       psed = sc->sc_isoc_head;
+               sed->next = psed;
+               sed->ed.ed_nexted = LE(psed->physaddr);
        }
        /* 
         * Fill HCCA interrupt table.  The bit reversal is to get
@@ -583,6 +703,17 @@ ohci_init(sc)
                sc->sc_hcca->hcca_interrupt_table[revbits[i]] = 
                        LE(sc->sc_eds[OHCI_NO_EDS-OHCI_NO_INTRS+i]->physaddr);
 
+#ifdef OHCI_DEBUG
+       if (ohcidebug > 15) {
+               for (i = 0; i < OHCI_NO_EDS; i++) {
+                       printf("ed#%d ", i);
+                       ohci_dump_ed(sc->sc_eds[i]);
+               }
+               printf("iso ");
+               ohci_dump_ed(sc->sc_isoc_head);
+       }
+#endif
+
        /* Determine in what context we are running. */
        ctl = OREAD4(sc, OHCI_CONTROL);
        if (ctl & OHCI_IR) {
@@ -591,7 +722,7 @@ ohci_init(sc)
                s = OREAD4(sc, OHCI_COMMAND_STATUS);
                OWRITE4(sc, OHCI_COMMAND_STATUS, s | OHCI_OCR);
                for (i = 0; i < 100 && (ctl & OHCI_IR); i++) {
-                       delay(1000);
+                       usb_delay_ms(&sc->sc_bus, 1);
                        ctl = OREAD4(sc, OHCI_CONTROL);
                }
                if ((ctl & OHCI_IR) == 0) {
@@ -605,13 +736,13 @@ ohci_init(sc)
                DPRINTF(("ohci_init: BIOS active\n"));
                if ((ctl & OHCI_HCFS_MASK) != OHCI_HCFS_OPERATIONAL) {
                        OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_OPERATIONAL);
-                       delay(USB_RESUME_DELAY * 1000);
+                       usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY);
                }
        } else {
                DPRINTF(("ohci_init: cold started\n"));
        reset:
                /* Controller was cold started. */
-               delay(USB_BUS_RESET_DELAY * 1000);
+               usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY);
        }
 
        /*
@@ -620,7 +751,7 @@ ohci_init(sc)
         */
        DPRINTF(("%s: resetting\n", USBDEVNAME(sc->sc_bus.bdev)));
        OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
-       delay(USB_BUS_RESET_DELAY * 1000);
+       usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY);
 
        /* We now own the host controller and the bus has been reset. */
        ival = OHCI_GET_IVAL(OREAD4(sc, OHCI_FM_INTERVAL));
@@ -635,23 +766,24 @@ ohci_init(sc)
        }
        if (hcr) {
                printf("%s: reset timeout\n", USBDEVNAME(sc->sc_bus.bdev));
-               r = USBD_IOERROR;
-               goto bad3;
+               err = USBD_IOERROR;
+               goto bad5;
        }
 #ifdef OHCI_DEBUG
-       thesc = sc;
        if (ohcidebug > 15)
                ohci_dumpregs(sc);
 #endif
 
-       /* The controller is now in suspend state, we have 2ms to finish. */
+       /* The controller is now in SUSPEND state, we have 2ms to finish. */
 
        /* Set up HC registers. */
        OWRITE4(sc, OHCI_HCCA, DMAADDR(&sc->sc_hccadma));
        OWRITE4(sc, OHCI_CONTROL_HEAD_ED, sc->sc_ctrl_head->physaddr);
        OWRITE4(sc, OHCI_BULK_HEAD_ED, sc->sc_bulk_head->physaddr);
+       /* disable all interrupts and then switch on all desired interrupts */
        OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS);
        OWRITE4(sc, OHCI_INTERRUPT_ENABLE, sc->sc_eintrs | OHCI_MIE);
+       /* switch on desired functional features */
        ctl = OREAD4(sc, OHCI_CONTROL);
        ctl &= ~(OHCI_CBSR_MASK | OHCI_LES | OHCI_HCFS_MASK | OHCI_IR);
        ctl |= OHCI_PLE | OHCI_IE | OHCI_CLE | OHCI_BLE |
@@ -670,7 +802,12 @@ ohci_init(sc)
        per = OHCI_PERIODIC(ival); /* 90% periodic */
        OWRITE4(sc, OHCI_PERIODIC_START, per);
 
-       OWRITE4(sc, OHCI_RH_STATUS, OHCI_LPSC); /* Enable port power */
+       /* Fiddle the No OverCurrent Protection bit to avoid chip bug. */
+       desca = OREAD4(sc, OHCI_RH_DESCRIPTOR_A);
+       OWRITE4(sc, OHCI_RH_DESCRIPTOR_A, desca | OHCI_NOCP);
+       OWRITE4(sc, OHCI_RH_STATUS, OHCI_LPSC); /* Enable port power */
+       usb_delay_ms(&sc->sc_bus, 5);
+       OWRITE4(sc, OHCI_RH_DESCRIPTOR_A, desca);
 
        sc->sc_noport = OHCI_GET_NDP(OREAD4(sc, OHCI_RH_DESCRIPTOR_A));
 
@@ -684,16 +821,22 @@ ohci_init(sc)
        sc->sc_bus.pipe_size = sizeof(struct ohci_pipe);
 
        sc->sc_powerhook = powerhook_establish(ohci_power, sc);
+       sc->sc_shutdownhook = shutdownhook_establish(ohci_shutdown, sc);
 
        return (USBD_NORMAL_COMPLETION);
 
+ bad5:
+       for (i = 0; i < OHCI_NO_EDS; i++)
+               ohci_free_sed(sc, sc->sc_eds[i]);
+ bad4:
+       ohci_free_sed(sc, sc->sc_isoc_head);
  bad3:
        ohci_free_sed(sc, sc->sc_ctrl_head);
  bad2:
        ohci_free_sed(sc, sc->sc_bulk_head);
  bad1:
        usb_freemem(&sc->sc_bus, &sc->sc_hccadma);
-       return (r);
+       return (err);
 }
 
 usbd_status
@@ -721,7 +864,49 @@ ohci_freem(bus, dma)
        usb_freemem(&sc->sc_bus, dma);
 }
 
-#if defined(__NetBSD__) || defined(__OpenBSD__)
+usbd_xfer_handle
+ohci_allocx(bus)
+       struct usbd_bus *bus;
+{
+       struct ohci_softc *sc = (struct ohci_softc *)bus;
+       usbd_xfer_handle xfer;
+
+       xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers);
+       if (xfer != NULL)
+               SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, xfer, next);    
+       else
+               xfer = malloc(sizeof(*xfer), M_USB, M_NOWAIT);
+       if (xfer != NULL)
+               memset(xfer, 0, sizeof *xfer);
+       return (xfer);
+}
+
+void ohci_freex(bus, xfer)
+       struct usbd_bus *bus;
+       usbd_xfer_handle xfer;
+{
+       struct ohci_softc *sc = (struct ohci_softc *)bus;
+
+       SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next);
+}
+
+void
+ohci_shutdown(v)
+       void *v;
+{
+       ohci_softc_t *sc = v;
+
+       DPRINTF(("ohci_shutdown: stopping the HC\n"));
+       OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
+}
+
+/*
+ * Handle suspend/resume.
+ *
+ * We need to switch to polling mode here, because this routine is
+ * called from an interrupt context.  This is all right since we
+ * are almost suspended anyway.
+ */
 void
 ohci_power(why, v)
        int why;
@@ -735,12 +920,8 @@ ohci_power(why, v)
        ohci_dumpregs(sc);
 #endif
 }
-#endif /* defined(__NetBSD__) || defined(__OpenBSD__) */
 
 #ifdef OHCI_DEBUG
-void ohcidump(void);
-void ohcidump(void) { ohci_dumpregs(thesc); }
-
 void
 ohci_dumpregs(sc)
        ohci_softc_t *sc;
@@ -782,11 +963,29 @@ ohci_dumpregs(sc)
 }
 #endif
 
+int ohci_intr1 __P((ohci_softc_t *));
+
 int
 ohci_intr(p)
        void *p;
 {
        ohci_softc_t *sc = p;
+
+       /* If we get an interrupt while polling, then just ignore it. */
+       if (sc->sc_bus.use_polling) {
+#ifdef DIAGNOSTIC
+               printf("ohci_intr: ignored interrupt while polling\n");
+#endif
+               return (0);
+       }
+
+       return (ohci_intr1(sc));
+}
+
+int
+ohci_intr1(sc)
+       ohci_softc_t *sc;
+{
        u_int32_t intrs, eintrs;
        ohci_physaddr_t done;
 
@@ -808,8 +1007,10 @@ ohci_intr(p)
                        intrs |= OREAD4(sc, OHCI_INTERRUPT_STATUS);
        } else
                intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS);
+
        if (!intrs)
                return (0);
+
        intrs &= ~OHCI_MIE;
        OWRITE4(sc, OHCI_INTERRUPT_STATUS, intrs); /* Acknowledge */
        eintrs = intrs & sc->sc_eintrs;
@@ -818,7 +1019,7 @@ ohci_intr(p)
 
        sc->sc_bus.intr_context++;
        sc->sc_bus.no_intrs++;
-       DPRINTFN(7, ("ohci_intr: sc=%p intrs=%x(%x) eintr=%x\n", 
+       DPRINTFN(7, ("ohci_intr: sc=%p intrs=0x%x(0x%x) eintr=0x%x\n", 
                     sc, (u_int)intrs, OREAD4(sc, OHCI_INTERRUPT_STATUS),
                     (u_int)eintrs));
 
@@ -828,7 +1029,21 @@ ohci_intr(p)
                intrs &= ~OHCI_SO;
        }
        if (eintrs & OHCI_WDH) {
-               ohci_process_done(sc, done &~ OHCI_DONE_INTRS);
+               done &= ~OHCI_DONE_INTRS;
+               if (sc->sc_done == 0)
+                       sc->sc_done = done;
+               else {
+                       /* Tack on at end of the sc_dne. */
+                       ohci_physaddr_t ldone;
+                       ohci_soft_td_t *std;
+
+                       for (ldone = sc->sc_done; ldone != 0;
+                            ldone = LE(std->td.td_nexttd))
+                               std = ohci_hash_find_td(sc, ldone);
+                       std->td.td_nexttd = LE(done);
+               }
+               sc->sc_hcca->hcca_done_head = 0;
+               usb_schedsoftintr(&sc->sc_bus);
                intrs &= ~OHCI_WDH;
        }
        if (eintrs & OHCI_RD) {
@@ -842,7 +1057,7 @@ ohci_intr(p)
                /* XXX what else */
        }
        if (eintrs & OHCI_RHSC) {
-               ohci_rhsc(sc, sc->sc_intrreqh);
+               ohci_rhsc(sc, sc->sc_intrxfer);
                intrs &= ~OHCI_RHSC;
 
                /* 
@@ -890,23 +1105,34 @@ char *ohci_cc_strs[] = {
        "DATA_UNDERRUN",
        "BUFFER_OVERRUN",
        "BUFFER_UNDERRUN",
+       "reserved",
+       "reserved",
+       "NOT ACCESSED",
        "NOT_ACCESSED",
 };
 #endif
 
 void
-ohci_process_done(sc, done)
-       ohci_softc_t *sc;
-       ohci_physaddr_t done;
+ohci_softintr(bus)
+       struct usbd_bus *bus;
 {
+       ohci_softc_t *sc = (ohci_softc_t *)bus;
+       ohci_physaddr_t done;
        ohci_soft_td_t *std, *sdone, *stdnext;
-       usbd_request_handle reqh;
-       int len, cc;
+       usbd_xfer_handle xfer;
+       int len, cc, s;
+
+       sc->sc_bus.intr_context++;
+
+       s = splhardusb();
+       done = sc->sc_done;
+       sc->sc_done = 0;
+       splx(s);
 
        DPRINTFN(10,("ohci_process_done: done=0x%08lx\n", (u_long)done));
 
        /* Reverse the done list. */
-       for (sdone = 0; done; done = LE(std->td.td_nexttd)) {
+       for (sdone = NULL; done != 0; done = LE(std->td.td_nexttd)) {
                std = ohci_hash_find_td(sc, done);
                std->dnext = sdone;
                sdone = std;
@@ -920,29 +1146,30 @@ ohci_process_done(sc, done)
 #endif
 
        for (std = sdone; std; std = stdnext) {
-               reqh = std->reqh;
+               xfer = std->xfer;
                stdnext = std->dnext;
-               DPRINTFN(10, ("ohci_process_done: std=%p reqh=%p hcpriv=%p\n",
-                               std, reqh, reqh->hcpriv));
+               DPRINTFN(10, ("ohci_process_done: std=%p xfer=%p hcpriv=%p\n",
+                               std, xfer, xfer ? xfer->hcpriv : 0));
                cc = OHCI_TD_GET_CC(LE(std->td.td_flags));
-               usb_untimeout(ohci_timeout, reqh, reqh->timo_handle);
-               if (reqh->status == USBD_CANCELLED ||
-                   reqh->status == USBD_TIMEOUT) {
+               usb_untimeout(ohci_timeout, xfer, xfer->timo_handle);
+               if (xfer->status == USBD_CANCELLED ||
+                   xfer->status == USBD_TIMEOUT) {
                        DPRINTF(("ohci_process_done: cancel/timeout %p\n",
-                                reqh));
+                                xfer));
                        /* Handled by abort routine. */
                } else if (cc == OHCI_CC_NO_ERROR) {
                        len = std->len;
                        if (std->td.td_cbp != 0)
                                len -= LE(std->td.td_be) -
                                       LE(std->td.td_cbp) + 1;
+                       DPRINTFN(10, ("ohci_process_done: len=%d, flags=0x%x\n",
+                                     len, std->flags));
                        if (std->flags & OHCI_ADD_LEN)
-                               reqh->actlen += len;
+                               xfer->actlen += len;
                        if (std->flags & OHCI_CALL_DONE) {
-                               reqh->status = USBD_NORMAL_COMPLETION;
-                               usb_transfer_complete(reqh);
+                               xfer->status = USBD_NORMAL_COMPLETION;
+                               usb_transfer_complete(xfer);
                        }
-                       ohci_hash_rem_td(sc, std);
                        ohci_free_std(sc, std);
                } else {
                        /*
@@ -952,16 +1179,15 @@ ohci_process_done(sc, done)
                         */
                        ohci_soft_td_t *p, *n;
                        struct ohci_pipe *opipe = 
-                               (struct ohci_pipe *)reqh->pipe;
+                               (struct ohci_pipe *)xfer->pipe;
 
-                       DPRINTFN(-1,("ohci_process_done: error cc=%d (%s)\n",
+                       DPRINTF(("ohci_process_done: error cc=%d (%s)\n",
                         OHCI_TD_GET_CC(LE(std->td.td_flags)),
                         ohci_cc_strs[OHCI_TD_GET_CC(LE(std->td.td_flags))]));
 
                        /* remove TDs */
-                       for (p = std; p->reqh == reqh; p = n) {
+                       for (p = std; p->xfer == xfer; p = n) {
                                n = p->nexttd;
-                               ohci_hash_rem_td(sc, p);
                                ohci_free_std(sc, p);
                        }
 
@@ -970,87 +1196,87 @@ ohci_process_done(sc, done)
                        OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
 
                        if (cc == OHCI_CC_STALL)
-                               reqh->status = USBD_STALLED;
+                               xfer->status = USBD_STALLED;
                        else
-                               reqh->status = USBD_IOERROR;
-                       usb_transfer_complete(reqh);
+                               xfer->status = USBD_IOERROR;
+                       usb_transfer_complete(xfer);
                }
        }
+
+       sc->sc_bus.intr_context--;
 }
 
 void
-ohci_device_ctrl_done(reqh)
-       usbd_request_handle reqh;
+ohci_device_ctrl_done(xfer)
+       usbd_xfer_handle xfer;
 {
-       DPRINTFN(10,("ohci_ctrl_done: reqh=%p\n", reqh));
+       DPRINTFN(10,("ohci_ctrl_done: xfer=%p\n", xfer));
 
 #ifdef DIAGNOSTIC
-       if (!(reqh->rqflags & URQ_REQUEST)) {
+       if (!(xfer->rqflags & URQ_REQUEST)) {
                panic("ohci_ctrl_done: not a request\n");
        }
 #endif
-       reqh->hcpriv = 0;
+       xfer->hcpriv = NULL;
 }
 
 void
-ohci_device_intr_done(reqh)
-       usbd_request_handle reqh;
+ohci_device_intr_done(xfer)
+       usbd_xfer_handle xfer;
 {
-       struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe;
+       struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
        ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
        ohci_soft_ed_t *sed = opipe->sed;
        ohci_soft_td_t *data, *tail;
 
+       DPRINTFN(10,("ohci_intr_done: xfer=%p, actlen=%d\n", 
+                    xfer, xfer->actlen));
 
-       DPRINTFN(10,("ohci_intr_done: reqh=%p, actlen=%d\n", 
-                    reqh, reqh->actlen));
+       xfer->hcpriv = NULL;
 
-       reqh->hcpriv = 0;
-
-       if (reqh->pipe->repeat) {
-               data = opipe->tail;
+       if (xfer->pipe->repeat) {
+               data = opipe->tail.td;
                tail = ohci_alloc_std(sc); /* XXX should reuse TD */
-               if (!tail) {
-                       reqh->status = USBD_NOMEM;
+               if (tail == NULL) {
+                       xfer->status = USBD_NOMEM;
                        return;
                }
-               tail->reqh = 0;
+               tail->xfer = NULL;
                
                data->td.td_flags = LE(
                        OHCI_TD_IN | OHCI_TD_NOCC | 
                        OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY);
-               if (reqh->flags & USBD_SHORT_XFER_OK)
+               if (xfer->flags & USBD_SHORT_XFER_OK)
                        data->td.td_flags |= LE(OHCI_TD_R);
-               data->td.td_cbp = LE(DMAADDR(&reqh->dmabuf));
+               data->td.td_cbp = LE(DMAADDR(&xfer->dmabuf));
                data->nexttd = tail;
                data->td.td_nexttd = LE(tail->physaddr);
-               data->td.td_be = LE(LE(data->td.td_cbp) + reqh->length - 1);
-               data->len = reqh->length;
-               data->reqh = reqh;
+               data->td.td_be = LE(LE(data->td.td_cbp) + xfer->length - 1);
+               data->len = xfer->length;
+               data->xfer = xfer;
                data->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
-               reqh->hcpriv = data;
-               reqh->actlen = 0;
+               xfer->hcpriv = data;
+               xfer->actlen = 0;
 
-               ohci_hash_add_td(sc, data);
                sed->ed.ed_tailp = LE(tail->physaddr);
-               opipe->tail = tail;
+               opipe->tail.td = tail;
        }
 }
 
 void
-ohci_device_bulk_done(reqh)
-       usbd_request_handle reqh;
+ohci_device_bulk_done(xfer)
+       usbd_xfer_handle xfer;
 {
-       DPRINTFN(10,("ohci_bulk_done: reqh=%p, actlen=%d\n", 
-                    reqh, reqh->actlen));
+       DPRINTFN(10,("ohci_bulk_done: xfer=%p, actlen=%d\n", 
+                    xfer, xfer->actlen));
 
-       reqh->hcpriv = 0;
+       xfer->hcpriv = 0;
 }
 
 void
-ohci_rhsc(sc, reqh)
+ohci_rhsc(sc, xfer)
        ohci_softc_t *sc;
-       usbd_request_handle reqh;
+       usbd_xfer_handle xfer;
 {
        usbd_pipe_handle pipe;
        struct ohci_pipe *opipe;
@@ -1059,36 +1285,43 @@ ohci_rhsc(sc, reqh)
        int hstatus;
 
        hstatus = OREAD4(sc, OHCI_RH_STATUS);
-       DPRINTF(("ohci_rhsc: sc=%p reqh=%p hstatus=0x%08x\n", 
-                sc, reqh, hstatus));
+       DPRINTF(("ohci_rhsc: sc=%p xfer=%p hstatus=0x%08x\n", 
+                sc, xfer, hstatus));
 
-       if (reqh == 0) {
+       if (xfer == 0) {
                /* Just ignore the change. */
                return;
        }
 
-       pipe = reqh->pipe;
+       pipe = xfer->pipe;
        opipe = (struct ohci_pipe *)pipe;
 
-       p = KERNADDR(&reqh->dmabuf);
-       m = min(sc->sc_noport, reqh->length * 8 - 1);
-       memset(p, 0, reqh->length);
+       p = KERNADDR(&xfer->dmabuf);
+       m = min(sc->sc_noport, xfer->length * 8 - 1);
+       memset(p, 0, xfer->length);
        for (i = 1; i <= m; i++) {
                if (OREAD4(sc, OHCI_RH_PORT_STATUS(i)) >> 16)
                        p[i/8] |= 1 << (i%8);
        }
        DPRINTF(("ohci_rhsc: change=0x%02x\n", *p));
-       reqh->actlen = reqh->length;
-       reqh->status = USBD_NORMAL_COMPLETION;
+       xfer->actlen = xfer->length;
+       xfer->status = USBD_NORMAL_COMPLETION;
+
+       usb_transfer_complete(xfer);
+}
 
-       usb_transfer_complete(reqh);
+void
+ohci_root_intr_done(xfer)
+       usbd_xfer_handle xfer;
+{
+       xfer->hcpriv = NULL;
 }
 
 void
-ohci_root_intr_done(reqh)
-       usbd_request_handle reqh;
+ohci_root_ctrl_done(xfer)
+       usbd_xfer_handle xfer;
 {
-       reqh->hcpriv = 0;
+       xfer->hcpriv = NULL;
 }
 
 /*
@@ -1097,15 +1330,15 @@ ohci_root_intr_done(reqh)
  * too long.
  */
 void
-ohci_waitintr(sc, reqh)
+ohci_waitintr(sc, xfer)
        ohci_softc_t *sc;
-       usbd_request_handle reqh;
+       usbd_xfer_handle xfer;
 {
-       int timo = reqh->timeout;
+       int timo = xfer->timeout;
        int usecs;
        u_int32_t intrs;
 
-       reqh->status = USBD_IN_PROGRESS;
+       xfer->status = USBD_IN_PROGRESS;
        for (usecs = timo * 1000000 / hz; usecs > 0; usecs -= 1000) {
                usb_delay_ms(&sc->sc_bus, 1);
                intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS) & sc->sc_eintrs;
@@ -1115,16 +1348,16 @@ ohci_waitintr(sc, reqh)
                        ohci_dumpregs(sc);
 #endif
                if (intrs) {
-                       ohci_intr(sc);
-                       if (reqh->status != USBD_IN_PROGRESS)
+                       ohci_intr1(sc);
+                       if (xfer->status != USBD_IN_PROGRESS)
                                return;
                }
        }
 
        /* Timeout */
        DPRINTF(("ohci_waitintr: timeout\n"));
-       reqh->status = USBD_TIMEOUT;
-       usb_transfer_complete(reqh);
+       xfer->status = USBD_TIMEOUT;
+       usb_transfer_complete(xfer);
        /* XXX should free TD */
 }
 
@@ -1135,23 +1368,23 @@ ohci_poll(bus)
        ohci_softc_t *sc = (ohci_softc_t *)bus;
 
        if (OREAD4(sc, OHCI_INTERRUPT_STATUS) & sc->sc_eintrs)
-               ohci_intr(sc);
+               ohci_intr1(sc);
 }
 
 usbd_status
-ohci_device_request(reqh)
-       usbd_request_handle reqh;
+ohci_device_request(xfer)
+       usbd_xfer_handle xfer;
 {
-       struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe;
-       usb_device_request_t *req = &reqh->request;
+       struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
+       usb_device_request_t *req = &xfer->request;
        usbd_device_handle dev = opipe->pipe.device;
        ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
        int addr = dev->address;
-       ohci_soft_td_t *setup, *data = 0, *stat, *next, *tail;
+       ohci_soft_td_t *setup, *stat, *next, *tail;
        ohci_soft_ed_t *sed;
        int isread;
        int len;
-       usbd_status r;
+       usbd_status err;
        int s;
 
        isread = req->bmRequestType & UT_READ;
@@ -1163,54 +1396,44 @@ ohci_device_request(reqh)
                    UGETW(req->wIndex), len, addr, 
                    opipe->pipe.endpoint->edesc->bEndpointAddress));
 
-       setup = opipe->tail;
+       setup = opipe->tail.td;
        stat = ohci_alloc_std(sc);
-       if (!stat) {
-               r = USBD_NOMEM;
+       if (stat == NULL) {
+               err = USBD_NOMEM;
                goto bad1;
        }
        tail = ohci_alloc_std(sc);
-       if (!tail) {
-               r = USBD_NOMEM;
+       if (tail == NULL) {
+               err = USBD_NOMEM;
                goto bad2;
        }
-       tail->reqh = 0;
+       tail->xfer = NULL;
 
        sed = opipe->sed;
        opipe->u.ctl.length = len;
 
        /* Update device address and length since they may have changed. */
        /* XXX This only needs to be done once, but it's too early in open. */
+       /* XXXX Should not touch ED here! */
        sed->ed.ed_flags = LE(
         (LE(sed->ed.ed_flags) & ~(OHCI_ED_ADDRMASK | OHCI_ED_MAXPMASK)) |
         OHCI_ED_SET_FA(addr) |
         OHCI_ED_SET_MAXP(UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize)));
 
+       next = stat;
+
        /* Set up data transaction */
        if (len != 0) {
-               data = ohci_alloc_std(sc);
-               if (!data) {
-                       r = USBD_NOMEM;
+               ohci_soft_td_t *std = stat;
+
+               err = ohci_alloc_std_chain(opipe, sc, len, isread, xfer,
+                           std, &stat);
+               stat = stat->nexttd; /* point at free TD */
+               if (err)
                        goto bad3;
-               }
-               data->td.td_flags = LE(
-                       (isread ? OHCI_TD_IN : OHCI_TD_OUT) | OHCI_TD_NOCC |
-                       OHCI_TD_TOGGLE_1 | OHCI_TD_NOINTR |
-                       (reqh->flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0));
-               data->td.td_cbp = LE(DMAADDR(&reqh->dmabuf));
-               data->nexttd = stat;
-               data->td.td_nexttd = LE(stat->physaddr);
-               data->td.td_be = LE(LE(data->td.td_cbp) + len - 1);
-               data->len = len;
-               data->reqh = reqh;
-               data->flags = OHCI_ADD_LEN;
-
-               next = data;
-               stat->flags = OHCI_CALL_DONE;
-       } else {
-               next = stat;
-               /* XXX ADD_LEN? */
-               stat->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
+               /* Start toggle at 1 and then use the carried toggle. */
+               std->td.td_flags &= LE(~OHCI_TD_TOGGLE_MASK);
+               std->td.td_flags |= LE(OHCI_TD_TOGGLE_1);
        }
 
        memcpy(KERNADDR(&opipe->u.ctl.reqdma), req, sizeof *req);
@@ -1221,20 +1444,21 @@ ohci_device_request(reqh)
        setup->nexttd = next;
        setup->td.td_nexttd = LE(next->physaddr);
        setup->td.td_be = LE(LE(setup->td.td_cbp) + sizeof *req - 1);
-       setup->len = 0;         /* XXX The number of byte we count */
-       setup->reqh = reqh;
+       setup->len = 0;
+       setup->xfer = xfer;
        setup->flags = 0;
-       reqh->hcpriv = setup;
+       xfer->hcpriv = setup;
 
        stat->td.td_flags = LE(
-               (isread ? OHCI_TD_OUT : OHCI_TD_IN) | OHCI_TD_NOCC |
-               OHCI_TD_TOGGLE_1 | OHCI_TD_SET_DI(1));
+               (isread ? OHCI_TD_OUT : OHCI_TD_IN) |
+               OHCI_TD_NOCC | OHCI_TD_TOGGLE_1 | OHCI_TD_SET_DI(1));
        stat->td.td_cbp = 0;
        stat->nexttd = tail;
        stat->td.td_nexttd = LE(tail->physaddr);
        stat->td.td_be = 0;
+       stat->flags = OHCI_CALL_DONE;
        stat->len = 0;
-       stat->reqh = reqh;
+       stat->xfer = xfer;
 
 #ifdef OHCI_DEBUG
        if (ohcidebug > 5) {
@@ -1246,22 +1470,18 @@ ohci_device_request(reqh)
 
        /* Insert ED in schedule */
        s = splusb();
-       ohci_hash_add_td(sc, setup);
-       if (len != 0)
-               ohci_hash_add_td(sc, data);
-       ohci_hash_add_td(sc, stat);
        sed->ed.ed_tailp = LE(tail->physaddr);
-       opipe->tail = tail;
+       opipe->tail.td = tail;
        OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
-       if (reqh->timeout && !sc->sc_bus.use_polling) {
-                usb_timeout(ohci_timeout, reqh,
-                           MS_TO_TICKS(reqh->timeout), reqh->timo_handle);
+       if (xfer->timeout && !sc->sc_bus.use_polling) {
+                usb_timeout(ohci_timeout, xfer,
+                           MS_TO_TICKS(xfer->timeout), xfer->timo_handle);
        }
        splx(s);
 
-#ifdef OHCI_DEBUG
-       if (ohcidebug > 5) {
-               delay(5000);
+#if 0
+       if (ohcidebug > 10) {
+               delay(10000);
                DPRINTF(("ohci_device_request: status=%x\n",
                         OREAD4(sc, OHCI_COMMAND_STATUS)));
                ohci_dump_ed(sed);
@@ -1276,7 +1496,7 @@ ohci_device_request(reqh)
  bad2:
        ohci_free_std(sc, stat);
  bad1:
-       return (r);
+       return (err);
 }
 
 /*
@@ -1307,9 +1527,9 @@ ohci_rem_ed(sed, head)
        SPLUSBCHECK;
 
        /* XXX */
-       for (p = head; p && p->next != sed; p = p->next)
+       for (p = head; p != NULL && p->next != sed; p = p->next)
                ;
-       if (!p)
+       if (p == NULL)
                panic("ohci_rem_ed: ED not found\n");
        p->next = sed->next;
        p->ed.ed_nexted = sed->ed.ed_nexted;
@@ -1359,7 +1579,7 @@ ohci_hash_find_td(sc, a)
        ohci_soft_td_t *std;
 
        for (std = LIST_FIRST(&sc->sc_hash_tds[h]); 
-            std != 0
+            std != NULL
             std = LIST_NEXT(std, hnext))
                if (std->physaddr == a)
                        return (std);
@@ -1370,15 +1590,15 @@ void
 ohci_timeout(addr)
        void *addr;
 {
-       usbd_request_handle reqh = addr;
+       usbd_xfer_handle xfer = addr;
        int s;
 
-       DPRINTF(("ohci_timeout: reqh=%p\n", reqh));
+       DPRINTF(("ohci_timeout: xfer=%p\n", xfer));
 
        s = splusb();
-       reqh->device->bus->intr_context++;
-       ohci_abort_req(reqh, USBD_TIMEOUT);
-       reqh->device->bus->intr_context--;
+       xfer->device->bus->intr_context++;
+       ohci_abort_xfer(xfer, USBD_TIMEOUT);
+       xfer->device->bus->intr_context--;
        splx(s);
 }
 
@@ -1411,8 +1631,8 @@ void
 ohci_dump_ed(sed)
        ohci_soft_ed_t *sed;
 {
-       DPRINTF(("ED(%p) at %08lx: addr=%d endpt=%d maxp=%d %b\ntailp=0x%08lx "
-                "headp=%b nexted=0x%08lx\n",
+       DPRINTF(("ED(%p) at 0x%08lx: addr=%d endpt=%d maxp=%d %b\ntailp=0x%08lx "
+                "headsflags=%b headp=%b nexted=0x%08lx\n",
                 sed, (u_long)sed->physaddr, 
                 OHCI_ED_GET_FA(LE(sed->ed.ed_flags)),
                 OHCI_ED_GET_EN(LE(sed->ed.ed_flags)),
@@ -1422,6 +1642,7 @@ ohci_dump_ed(sed)
                 (u_long)LE(sed->ed.ed_tailp),
                 (u_long)LE(sed->ed.ed_headp),
                 "\20\1HALT\2CARRY",
+                (u_long)LE(sed->ed.ed_headp),
                 (u_long)LE(sed->ed.ed_nexted)));
 }
 #endif
@@ -1435,10 +1656,15 @@ ohci_open(pipe)
        usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc;
        struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
        u_int8_t addr = dev->address;
+       u_int8_t xfertype = ed->bmAttributes & UE_XFERTYPE;
        ohci_soft_ed_t *sed;
        ohci_soft_td_t *std;
-       usbd_status r;
+       ohci_soft_itd_t *sitd;
+       ohci_physaddr_t tdphys;
+       u_int32_t fmt;
+       usbd_status err;
        int s;
+       int ival;
 
        DPRINTFN(1, ("ohci_open: pipe=%p, addr=%d, endpt=%d (%d)\n",
                     pipe, addr, ed->bEndpointAddress, sc->sc_addr));
@@ -1455,30 +1681,43 @@ ohci_open(pipe)
                }
        } else {
                sed = ohci_alloc_sed(sc);
-               if (sed == 0)
+               if (sed == NULL)
                        goto bad0;
-               std = ohci_alloc_std(sc);
-               if (std == 0)
-                       goto bad1;
                opipe->sed = sed;
-               opipe->tail = std;
+               if (xfertype == UE_ISOCHRONOUS) {
+                       sitd = ohci_alloc_sitd(sc);
+                       if (sitd == NULL) {
+                               ohci_free_sitd(sc, sitd);
+                               goto bad1;
+                       }
+                       opipe->tail.itd = sitd;
+                       tdphys = LE(sitd->physaddr);
+                       fmt = OHCI_ED_FORMAT_ISO;
+               } else {
+                       std = ohci_alloc_std(sc);
+                       if (std == NULL) {
+                               ohci_free_std(sc, std);
+                               goto bad1;
+                       }
+                       opipe->tail.td = std;
+                       tdphys = LE(std->physaddr);
+                       fmt = OHCI_ED_FORMAT_GEN;
+               }
                sed->ed.ed_flags = LE(
                        OHCI_ED_SET_FA(addr) | 
                        OHCI_ED_SET_EN(ed->bEndpointAddress) |
                        OHCI_ED_DIR_TD | 
-                       (dev->lowspeed ? OHCI_ED_SPEED : 0) | 
-                       ((ed->bmAttributes & UE_XFERTYPE) == UE_ISOCHRONOUS ?
-                        OHCI_ED_FORMAT_ISO : OHCI_ED_FORMAT_GEN) |
+                       (dev->lowspeed ? OHCI_ED_SPEED : 0) | fmt |
                        OHCI_ED_SET_MAXP(UGETW(ed->wMaxPacketSize)));
-               sed->ed.ed_headp = sed->ed.ed_tailp = LE(std->physaddr);
+               sed->ed.ed_headp = sed->ed.ed_tailp = tdphys;
 
-               switch (ed->bmAttributes & UE_XFERTYPE) {
+               switch (xfertype) {
                case UE_CONTROL:
                        pipe->methods = &ohci_device_ctrl_methods;
-                       r = usb_allocmem(&sc->sc_bus, 
+                       err = usb_allocmem(&sc->sc_bus, 
                                         sizeof(usb_device_request_t), 
                                         0, &opipe->u.ctl.reqdma);
-                       if (r != USBD_NORMAL_COMPLETION)
+                       if (err)
                                goto bad;
                        s = splusb();
                        ohci_add_ed(sed, sc->sc_ctrl_head);
@@ -1486,10 +1725,13 @@ ohci_open(pipe)
                        break;
                case UE_INTERRUPT:
                        pipe->methods = &ohci_device_intr_methods;
-                       return (ohci_device_setintr(sc, opipe, ed->bInterval));
+                       ival = pipe->interval;
+                       if (ival == USBD_DEFAULT_INTERVAL)
+                               ival = ed->bInterval;
+                       return (ohci_device_setintr(sc, opipe, ival));
                case UE_ISOCHRONOUS:
-                       printf("ohci_open: open iso unimplemented\n");
-                       return (USBD_INVAL);
+                       pipe->methods = &ohci_device_isoc_methods;
+                       return (ohci_setup_isoc(pipe));
                case UE_BULK:
                        pipe->methods = &ohci_device_bulk_methods;
                        s = splusb();
@@ -1526,12 +1768,12 @@ ohci_close_pipe(pipe, head)
        s = splusb();
 #ifdef DIAGNOSTIC
        sed->ed.ed_flags |= LE(OHCI_ED_SKIP);
-       if ((sed->ed.ed_tailp & LE(OHCI_TAILMASK)) != 
-           (sed->ed.ed_headp & LE(OHCI_TAILMASK))) {
+       if ((sed->ed.ed_tailp & LE(OHCI_HEADMASK)) != 
+           (sed->ed.ed_headp & LE(OHCI_HEADMASK))) {
                ohci_physaddr_t td = sed->ed.ed_headp;
                ohci_soft_td_t *std;
                for (std = LIST_FIRST(&sc->sc_hash_tds[HASH(td)]); 
-                    std != 0; 
+                    std != NULL;
                     std = LIST_NEXT(std, hnext))
                    if (std->physaddr == td)
                        break;
@@ -1540,14 +1782,13 @@ ohci_close_pipe(pipe, head)
                       (int)LE(sed->ed.ed_headp), (int)LE(sed->ed.ed_tailp),
                       pipe, std);
                usb_delay_ms(&sc->sc_bus, 2);
-               if ((sed->ed.ed_tailp & LE(OHCI_TAILMASK)) != 
-                   (sed->ed.ed_headp & LE(OHCI_TAILMASK)))
+               if ((sed->ed.ed_tailp & LE(OHCI_HEADMASK)) !=
+                   (sed->ed.ed_headp & LE(OHCI_HEADMASK)))
                        printf("ohci_close_pipe: pipe still not empty\n");
        }
 #endif
        ohci_rem_ed(sed, head);
        splx(s);
-       ohci_free_std(sc, opipe->tail);
        ohci_free_sed(sc, opipe->sed);
 }
 
@@ -1562,38 +1803,47 @@ ohci_close_pipe(pipe, head)
  * interrupt processing to process it.
  */
 void
-ohci_abort_req(reqh, status)
-       usbd_request_handle reqh;
+ohci_abort_xfer(xfer, status)
+       usbd_xfer_handle xfer;
        usbd_status status;
 {
-       struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe;
+       struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
        ohci_soft_ed_t *sed;
 
-       DPRINTF(("ohci_abort_req: reqh=%p pipe=%p\n", reqh, opipe));
+       DPRINTF(("ohci_abort_xfer: xfer=%p pipe=%p\n", xfer, opipe));
 
-       reqh->status = status;
+       xfer->status = status;
 
-       usb_untimeout(ohci_timeout, reqh, reqh->timo_handle);
+       usb_untimeout(ohci_timeout, xfer, xfer->timo_handle);
 
        sed = opipe->sed;
-       DPRINTFN(1,("ohci_abort_req: stop ed=%p\n", sed));
+       DPRINTFN(1,("ohci_abort_xfer: stop ed=%p\n", sed));
        sed->ed.ed_flags |= LE(OHCI_ED_SKIP); /* force hardware skip */
 
-       if (reqh->device->bus->intr_context) {
+#if 1
+       if (xfer->device->bus->intr_context) {
                /* We have no process context, so we can't use tsleep(). */
-               timeout(ohci_abort_req_end, reqh, hz / USB_FRAMES_PER_SECOND);
+               timeout(ohci_abort_xfer_end, xfer, hz / USB_FRAMES_PER_SECOND);
        } else {
+#if defined(DIAGNOSTIC) && defined(__i386__) && defined(__FreeBSD__)
+               KASSERT(intr_nesting_level == 0,
+                       ("ohci_abort_req in interrupt context"));
+#endif
                usb_delay_ms(opipe->pipe.device->bus, 1);
-               ohci_abort_req_end(reqh);
+               ohci_abort_xfer_end(xfer);
        }
+#else
+       delay(1000);
+       ohci_abort_xfer_end(xfer);
+#endif
 }
 
 void
-ohci_abort_req_end(v)
+ohci_abort_xfer_end(v)
        void *v;
 {
-       usbd_request_handle reqh = v;
-       struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe;
+       usbd_xfer_handle xfer = v;
+       struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
        ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
        ohci_soft_ed_t *sed;
        ohci_soft_td_t *p, *n;
@@ -1601,26 +1851,25 @@ ohci_abort_req_end(v)
 
        s = splusb();
 
-       p = reqh->hcpriv;
+       p = xfer->hcpriv;
 #ifdef DIAGNOSTIC
-       if (!p) {
-               printf("ohci_abort_req: hcpriv==0\n");
+       if (p == NULL) {
+               printf("ohci_abort_xfer: hcpriv==0\n");
                return;
        }
 #endif
-       for (; p->reqh == reqh; p = n) {
+       for (; p->xfer == xfer; p = n) {
                n = p->nexttd;
-               ohci_hash_rem_td(sc, p);
                ohci_free_std(sc, p);
        }
 
        sed = opipe->sed;
-       DPRINTFN(2,("ohci_abort_req: set hd=%x, tl=%x\n",
+       DPRINTFN(2,("ohci_abort_xfer: set hd=%x, tl=%x\n",
                    (int)LE(p->physaddr), (int)LE(sed->ed.ed_tailp)));
        sed->ed.ed_headp = p->physaddr; /* unlink TDs */
        sed->ed.ed_flags &= LE(~OHCI_ED_SKIP); /* remove hardware skip */
 
-       usb_transfer_complete(reqh);
+       usb_transfer_complete(xfer);
 
        splx(s);
 }
@@ -1632,8 +1881,8 @@ usb_device_descriptor_t ohci_devd = {
        USB_DEVICE_DESCRIPTOR_SIZE,
        UDESC_DEVICE,           /* type */
        {0x00, 0x01},           /* USB version */
-       UCLASS_HUB,             /* class */
-       USUBCLASS_HUB,          /* subclass */
+       UDCLASS_HUB,            /* class */
+       UDSUBCLASS_HUB,         /* subclass */
        0,                      /* protocol */
        64,                     /* max packet */
        {0},{0},{0x00,0x01},    /* device id */
@@ -1660,8 +1909,8 @@ usb_interface_descriptor_t ohci_ifcd = {
        0,
        0,
        1,
-       UCLASS_HUB,
-       USUBCLASS_HUB,
+       UICLASS_HUB,
+       UISUBCLASS_HUB,
        0,
        0
 };
@@ -1709,40 +1958,40 @@ ohci_str(p, l, s)
  * Simulate a hardware hub by handling all the necessary requests.
  */
 usbd_status
-ohci_root_ctrl_transfer(reqh)
-       usbd_request_handle reqh;
+ohci_root_ctrl_transfer(xfer)
+       usbd_xfer_handle xfer;
 {
-       usbd_status r;
+       usbd_status err;
 
        /* Insert last in queue. */
-       r = usb_insert_transfer(reqh);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = usb_insert_transfer(xfer);
+       if (err)
+               return (err);
 
        /* Pipe isn't running, start first */
-       return (ohci_root_ctrl_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
+       return (ohci_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
 }
 
 usbd_status
-ohci_root_ctrl_start(reqh)
-       usbd_request_handle reqh;
+ohci_root_ctrl_start(xfer)
+       usbd_xfer_handle xfer;
 {
-       ohci_softc_t *sc = (ohci_softc_t *)reqh->pipe->device->bus;
+       ohci_softc_t *sc = (ohci_softc_t *)xfer->pipe->device->bus;
        usb_device_request_t *req;
        void *buf = NULL;
        int port, i;
        int s, len, value, index, l, totlen = 0;
        usb_port_status_t ps;
        usb_hub_descriptor_t hubd;
-       usbd_status r;
+       usbd_status err;
        u_int32_t v;
 
 #ifdef DIAGNOSTIC
-       if (!(reqh->rqflags & URQ_REQUEST))
+       if (!(xfer->rqflags & URQ_REQUEST))
                /* XXX panic */
                return (USBD_INVAL);
 #endif
-       req = &reqh->request;
+       req = &xfer->request;
 
        DPRINTFN(4,("ohci_root_ctrl_control type=0x%02x request=%02x\n", 
                    req->bmRequestType, req->bRequest));
@@ -1752,7 +2001,7 @@ ohci_root_ctrl_start(reqh)
        index = UGETW(req->wIndex);
 
        if (len != 0)
-               buf = KERNADDR(&reqh->dmabuf);
+               buf = KERNADDR(&xfer->dmabuf);
 
 #define C(x,y) ((x) | ((y) << 8))
        switch(C(req->bRequest, req->bmRequestType)) {
@@ -1775,7 +2024,7 @@ ohci_root_ctrl_start(reqh)
                switch(value >> 8) {
                case UDESC_DEVICE:
                        if ((value & 0xff) != 0) {
-                               r = USBD_IOERROR;
+                               err = USBD_IOERROR;
                                goto ret;
                        }
                        totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE);
@@ -1784,7 +2033,7 @@ ohci_root_ctrl_start(reqh)
                        break;
                case UDESC_CONFIG:
                        if ((value & 0xff) != 0) {
-                               r = USBD_IOERROR;
+                               err = USBD_IOERROR;
                                goto ret;
                        }
                        totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE);
@@ -1815,7 +2064,7 @@ ohci_root_ctrl_start(reqh)
                        }
                        break;
                default:
-                       r = USBD_IOERROR;
+                       err = USBD_IOERROR;
                        goto ret;
                }
                break;
@@ -1840,14 +2089,14 @@ ohci_root_ctrl_start(reqh)
                break;
        case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
                if (value >= USB_MAX_DEVICES) {
-                       r = USBD_IOERROR;
+                       err = USBD_IOERROR;
                        goto ret;
                }
                sc->sc_addr = value;
                break;
        case C(UR_SET_CONFIG, UT_WRITE_DEVICE):
                if (value != 0 && value != 1) {
-                       r = USBD_IOERROR;
+                       err = USBD_IOERROR;
                        goto ret;
                }
                sc->sc_conf = value;
@@ -1857,7 +2106,7 @@ ohci_root_ctrl_start(reqh)
        case C(UR_SET_FEATURE, UT_WRITE_DEVICE):
        case C(UR_SET_FEATURE, UT_WRITE_INTERFACE):
        case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT):
-               r = USBD_IOERROR;
+               err = USBD_IOERROR;
                goto ret;
        case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE):
                break;
@@ -1871,7 +2120,7 @@ ohci_root_ctrl_start(reqh)
                             "port=%d feature=%d\n",
                             index, value));
                if (index < 1 || index > sc->sc_noport) {
-                       r = USBD_IOERROR;
+                       err = USBD_IOERROR;
                        goto ret;
                }
                port = OHCI_RH_PORT_STATUS(index);
@@ -1901,7 +2150,7 @@ ohci_root_ctrl_start(reqh)
                        OWRITE4(sc, port, UPS_C_PORT_RESET << 16);
                        break;
                default:
-                       r = USBD_IOERROR;
+                       err = USBD_IOERROR;
                        goto ret;
                }
                switch(value) {
@@ -1920,7 +2169,7 @@ ohci_root_ctrl_start(reqh)
                break;
        case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
                if (value != 0) {
-                       r = USBD_IOERROR;
+                       err = USBD_IOERROR;
                        goto ret;
                }
                v = OREAD4(sc, OHCI_RH_DESCRIPTOR_A);
@@ -1942,7 +2191,7 @@ ohci_root_ctrl_start(reqh)
                break;
        case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
                if (len != 4) {
-                       r = USBD_IOERROR;
+                       err = USBD_IOERROR;
                        goto ret;
                }
                memset(buf, 0, len); /* ? XXX */
@@ -1952,11 +2201,11 @@ ohci_root_ctrl_start(reqh)
                DPRINTFN(8,("ohci_root_ctrl_transfer: get port status i=%d\n",
                            index));
                if (index < 1 || index > sc->sc_noport) {
-                       r = USBD_IOERROR;
+                       err = USBD_IOERROR;
                        goto ret;
                }
                if (len != 4) {
-                       r = USBD_IOERROR;
+                       err = USBD_IOERROR;
                        goto ret;
                }
                v = OREAD4(sc, OHCI_RH_PORT_STATUS(index));
@@ -1969,13 +2218,13 @@ ohci_root_ctrl_start(reqh)
                totlen = l;
                break;
        case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE):
-               r = USBD_IOERROR;
+               err = USBD_IOERROR;
                goto ret;
        case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE):
                break;
        case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
                if (index < 1 || index > sc->sc_noport) {
-                       r = USBD_IOERROR;
+                       err = USBD_IOERROR;
                        goto ret;
                }
                port = OHCI_RH_PORT_STATUS(index);
@@ -2004,28 +2253,28 @@ ohci_root_ctrl_start(reqh)
                        OWRITE4(sc, port, UPS_PORT_POWER);
                        break;
                default:
-                       r = USBD_IOERROR;
+                       err = USBD_IOERROR;
                        goto ret;
                }
                break;
        default:
-               r = USBD_IOERROR;
+               err = USBD_IOERROR;
                goto ret;
        }
-       reqh->actlen = totlen;
-       r = USBD_NORMAL_COMPLETION;
+       xfer->actlen = totlen;
+       err = USBD_NORMAL_COMPLETION;
  ret:
-       reqh->status = r;
+       xfer->status = err;
        s = splusb();
-       usb_transfer_complete(reqh);
+       usb_transfer_complete(xfer);
        splx(s);
        return (USBD_IN_PROGRESS);
 }
 
 /* Abort a root control request. */
 void
-ohci_root_ctrl_abort(reqh)
-       usbd_request_handle reqh;
+ohci_root_ctrl_abort(xfer)
+       usbd_xfer_handle xfer;
 {
        /* Nothing to do, all transfers are synchronous. */
 }
@@ -2040,43 +2289,47 @@ ohci_root_ctrl_close(pipe)
 }
 
 usbd_status
-ohci_root_intr_transfer(reqh)
-       usbd_request_handle reqh;
+ohci_root_intr_transfer(xfer)
+       usbd_xfer_handle xfer;
 {
-       usbd_status r;
+       usbd_status err;
 
        /* Insert last in queue. */
-       r = usb_insert_transfer(reqh);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = usb_insert_transfer(xfer);
+       if (err)
+               return (err);
 
        /* Pipe isn't running, start first */
-       return (ohci_root_intr_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
+       return (ohci_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
 }
 
 usbd_status
-ohci_root_intr_start(reqh)
-       usbd_request_handle reqh;
+ohci_root_intr_start(xfer)
+       usbd_xfer_handle xfer;
 {
-       usbd_pipe_handle pipe = reqh->pipe;
+       usbd_pipe_handle pipe = xfer->pipe;
        ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
 
-       sc->sc_intrreqh = reqh;
+       sc->sc_intrxfer = xfer;
 
        return (USBD_IN_PROGRESS);
 }
 
 /* Abort a root interrupt request. */
 void
-ohci_root_intr_abort(reqh)
-       usbd_request_handle reqh;
+ohci_root_intr_abort(xfer)
+       usbd_xfer_handle xfer;
 {
-       if (reqh->pipe->intrreqh == reqh) {
+       int s;
+
+       if (xfer->pipe->intrxfer == xfer) {
                DPRINTF(("ohci_root_intr_abort: remove\n"));
-               reqh->pipe->intrreqh = 0;
+               xfer->pipe->intrxfer = NULL;
        }
-       reqh->status = USBD_CANCELLED;
-       usb_transfer_complete(reqh);
+       xfer->status = USBD_CANCELLED;
+       s = splusb();
+       usb_transfer_complete(xfer);
+       splx(s);
 }
 
 /* Close the root pipe. */
@@ -2088,57 +2341,57 @@ ohci_root_intr_close(pipe)
        
        DPRINTF(("ohci_root_intr_close\n"));
 
-       sc->sc_intrreqh = 0;
+       sc->sc_intrxfer = NULL;
 }
 
 /************************/
 
 usbd_status
-ohci_device_ctrl_transfer(reqh)
-       usbd_request_handle reqh;
+ohci_device_ctrl_transfer(xfer)
+       usbd_xfer_handle xfer;
 {
-       usbd_status r;
+       usbd_status err;
 
        /* Insert last in queue. */
-       r = usb_insert_transfer(reqh);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = usb_insert_transfer(xfer);
+       if (err)
+               return (err);
 
        /* Pipe isn't running, start first */
-       return (ohci_device_ctrl_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
+       return (ohci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
 }
 
 usbd_status
-ohci_device_ctrl_start(reqh)
-       usbd_request_handle reqh;
+ohci_device_ctrl_start(xfer)
+       usbd_xfer_handle xfer;
 {
-       ohci_softc_t *sc = (ohci_softc_t *)reqh->pipe->device->bus;
-       usbd_status r;
+       ohci_softc_t *sc = (ohci_softc_t *)xfer->pipe->device->bus;
+       usbd_status err;
 
 #ifdef DIAGNOSTIC
-       if (!(reqh->rqflags & URQ_REQUEST)) {
+       if (!(xfer->rqflags & URQ_REQUEST)) {
                /* XXX panic */
                printf("ohci_device_ctrl_transfer: not a request\n");
                return (USBD_INVAL);
        }
 #endif
 
-       r = ohci_device_request(reqh);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = ohci_device_request(xfer);
+       if (err)
+               return (err);
 
        if (sc->sc_bus.use_polling)
-               ohci_waitintr(sc, reqh);
+               ohci_waitintr(sc, xfer);
        return (USBD_IN_PROGRESS);
 }
 
 /* Abort a device control request. */
 void
-ohci_device_ctrl_abort(reqh)
-       usbd_request_handle reqh;
+ohci_device_ctrl_abort(xfer)
+       usbd_xfer_handle xfer;
 {
-       DPRINTF(("ohci_device_ctrl_abort: reqh=%p\n", reqh));
-       ohci_abort_req(reqh, USBD_CANCELLED);
+       DPRINTF(("ohci_device_ctrl_abort: xfer=%p\n", xfer));
+       ohci_abort_xfer(xfer, USBD_CANCELLED);
 }
 
 /* Close a device control pipe. */
@@ -2146,10 +2399,12 @@ void
 ohci_device_ctrl_close(pipe)
        usbd_pipe_handle pipe;
 {
+       struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
        ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
 
        DPRINTF(("ohci_device_ctrl_close: pipe=%p\n", pipe));
        ohci_close_pipe(pipe, sc->sc_ctrl_head);
+       ohci_free_std(sc, opipe->tail.td);
 }
 
 /************************/
@@ -2160,7 +2415,7 @@ ohci_device_clear_toggle(pipe)
 {
        struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
 
-       opipe->sed->ed.ed_tailp &= LE(~OHCI_TOGGLECARRY);
+       opipe->sed->ed.ed_headp &= LE(~OHCI_TOGGLECARRY);
 }
 
 void
@@ -2170,48 +2425,48 @@ ohci_noop(pipe)
 }
 
 usbd_status
-ohci_device_bulk_transfer(reqh)
-       usbd_request_handle reqh;
+ohci_device_bulk_transfer(xfer)
+       usbd_xfer_handle xfer;
 {
-       usbd_status r;
+       usbd_status err;
 
        /* Insert last in queue. */
-       r = usb_insert_transfer(reqh);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = usb_insert_transfer(xfer);
+       if (err)
+               return (err);
 
        /* Pipe isn't running, start first */
-       return (ohci_device_bulk_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
+       return (ohci_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
 }
 
 usbd_status
-ohci_device_bulk_start(reqh)
-       usbd_request_handle reqh;
+ohci_device_bulk_start(xfer)
+       usbd_xfer_handle xfer;
 {
-       struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe;
+       struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
        usbd_device_handle dev = opipe->pipe.device;
        ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
        int addr = dev->address;
        ohci_soft_td_t *data, *tail, *tdp;
        ohci_soft_ed_t *sed;
        int s, len, isread, endpt;
-       usbd_status r;
+       usbd_status err;
 
 #ifdef DIAGNOSTIC
-       if (reqh->rqflags & URQ_REQUEST) {
+       if (xfer->rqflags & URQ_REQUEST) {
                /* XXX panic */
                printf("ohci_device_bulk_start: a request\n");
                return (USBD_INVAL);
        }
 #endif
 
-       len = reqh->length;
-       endpt = reqh->pipe->endpoint->edesc->bEndpointAddress;
+       len = xfer->length;
+       endpt = xfer->pipe->endpoint->edesc->bEndpointAddress;
        isread = UE_GET_DIR(endpt) == UE_DIR_IN;
        sed = opipe->sed;
 
-       DPRINTFN(4,("ohci_device_bulk_start: reqh=%p len=%d isread=%d "
-                   "flags=%d endpt=%d\n", reqh, len, isread, reqh->flags,
+       DPRINTFN(4,("ohci_device_bulk_start: xfer=%p len=%d isread=%d "
+                   "flags=%d endpt=%d\n", xfer, len, isread, xfer->flags,
                    endpt));
 
        opipe->u.bulk.isread = isread;
@@ -2223,15 +2478,18 @@ ohci_device_bulk_start(reqh)
                OHCI_ED_SET_FA(addr));
 
        /* Allocate a chain of new TDs (including a new tail). */
-       data = opipe->tail;
-       r = ohci_alloc_std_chain(opipe, sc, len, isread, 
-                                reqh->flags & USBD_SHORT_XFER_OK,
-                                &reqh->dmabuf, data, &tail);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
-
-       tail->reqh = 0;
-       reqh->hcpriv = data;
+       data = opipe->tail.td;
+       err = ohci_alloc_std_chain(opipe, sc, len, isread,  xfer, data, &tail);
+       /* We want interrupt at the end of the transfer. */
+       tail->td.td_flags &= LE(~OHCI_TD_INTR_MASK);
+       tail->td.td_flags |= LE(OHCI_TD_SET_DI(1));
+       tail->flags |= OHCI_CALL_DONE;
+       tail = tail->nexttd;    /* point at sentinel */
+       if (err)
+               return (err);
+
+       tail->xfer = NULL;
+       xfer->hcpriv = data;
 
        DPRINTFN(4,("ohci_device_bulk_start: ed_flags=0x%08x td_flags=0x%08x "
                    "td_cbp=0x%08x td_be=0x%08x\n",
@@ -2239,7 +2497,7 @@ ohci_device_bulk_start(reqh)
                    (int)LE(data->td.td_cbp), (int)LE(data->td.td_be)));
 
 #ifdef OHCI_DEBUG
-       if (ohcidebug > 4) {
+       if (ohcidebug > 5) {
                ohci_dump_ed(sed);
                ohci_dump_tds(data);
        }
@@ -2248,22 +2506,21 @@ ohci_device_bulk_start(reqh)
        /* Insert ED in schedule */
        s = splusb();
        for (tdp = data; tdp != tail; tdp = tdp->nexttd) {
-               tdp->reqh = reqh;
-               ohci_hash_add_td(sc, tdp);
+               tdp->xfer = xfer;
        }
        sed->ed.ed_tailp = LE(tail->physaddr);
-       opipe->tail = tail;
+       opipe->tail.td = tail;
        sed->ed.ed_flags &= LE(~OHCI_ED_SKIP);
        OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF);
-       if (reqh->timeout && !sc->sc_bus.use_polling) {
-                usb_timeout(ohci_timeout, reqh,
-                           MS_TO_TICKS(reqh->timeout), reqh->timo_handle);
+       if (xfer->timeout && !sc->sc_bus.use_polling) {
+                usb_timeout(ohci_timeout, xfer,
+                           MS_TO_TICKS(xfer->timeout), xfer->timo_handle);
        }
 
 #if 0
 /* This goes wrong if we are too slow. */
-       if (ohcidebug > 5) {
-               delay(5000);
+       if (ohcidebug > 10) {
+               delay(10000);
                DPRINTF(("ohci_device_intr_transfer: status=%x\n",
                         OREAD4(sc, OHCI_COMMAND_STATUS)));
                ohci_dump_ed(sed);
@@ -2277,11 +2534,11 @@ ohci_device_bulk_start(reqh)
 }
 
 void
-ohci_device_bulk_abort(reqh)
-       usbd_request_handle reqh;
+ohci_device_bulk_abort(xfer)
+       usbd_xfer_handle xfer;
 {
-       DPRINTF(("ohci_device_bulk_abort: reqh=%p\n", reqh));
-       ohci_abort_req(reqh, USBD_CANCELLED);
+       DPRINTF(("ohci_device_bulk_abort: xfer=%p\n", xfer));
+       ohci_abort_xfer(xfer, USBD_CANCELLED);
 }
 
 /* 
@@ -2291,34 +2548,36 @@ void
 ohci_device_bulk_close(pipe)
        usbd_pipe_handle pipe;
 {
+       struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
        ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
 
        DPRINTF(("ohci_device_bulk_close: pipe=%p\n", pipe));
        ohci_close_pipe(pipe, sc->sc_bulk_head);
+       ohci_free_std(sc, opipe->tail.td);
 }
 
 /************************/
 
 usbd_status
-ohci_device_intr_transfer(reqh)
-       usbd_request_handle reqh;
+ohci_device_intr_transfer(xfer)
+       usbd_xfer_handle xfer;
 {
-       usbd_status r;
+       usbd_status err;
 
        /* Insert last in queue. */
-       r = usb_insert_transfer(reqh);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = usb_insert_transfer(xfer);
+       if (err)
+               return (err);
 
        /* Pipe isn't running, start first */
-       return (ohci_device_intr_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
+       return (ohci_device_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
 }
 
 usbd_status
-ohci_device_intr_start(reqh)
-       usbd_request_handle reqh;
+ohci_device_intr_start(xfer)
+       usbd_xfer_handle xfer;
 {
-       struct ohci_pipe *opipe = (struct ohci_pipe *)reqh->pipe;
+       struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
        usbd_device_handle dev = opipe->pipe.device;
        ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
        ohci_soft_ed_t *sed = opipe->sed;
@@ -2326,36 +2585,36 @@ ohci_device_intr_start(reqh)
        int len;
        int s;
 
-       DPRINTFN(3, ("ohci_device_intr_transfer: reqh=%p len=%d "
+       DPRINTFN(3, ("ohci_device_intr_transfer: xfer=%p len=%d "
                     "flags=%d priv=%p\n",
-                    reqh, reqh->length, reqh->flags, reqh->priv));
+                    xfer, xfer->length, xfer->flags, xfer->priv));
 
 #ifdef DIAGNOSTIC
-       if (reqh->rqflags & URQ_REQUEST)
+       if (xfer->rqflags & URQ_REQUEST)
                panic("ohci_device_intr_transfer: a request\n");
 #endif
 
-       len = reqh->length;
+       len = xfer->length;
 
-       data = opipe->tail;
+       data = opipe->tail.td;
        tail = ohci_alloc_std(sc);
-       if (!tail)
+       if (tail == NULL)
                return (USBD_NOMEM);
-       tail->reqh = 0;
+       tail->xfer = NULL;
 
        data->td.td_flags = LE(
                OHCI_TD_IN | OHCI_TD_NOCC | 
                OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY);
-       if (reqh->flags & USBD_SHORT_XFER_OK)
+       if (xfer->flags & USBD_SHORT_XFER_OK)
                data->td.td_flags |= LE(OHCI_TD_R);
-       data->td.td_cbp = LE(DMAADDR(&reqh->dmabuf));
+       data->td.td_cbp = LE(DMAADDR(&xfer->dmabuf));
        data->nexttd = tail;
        data->td.td_nexttd = LE(tail->physaddr);
        data->td.td_be = LE(LE(data->td.td_cbp) + len - 1);
        data->len = len;
-       data->reqh = reqh;
+       data->xfer = xfer;
        data->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
-       reqh->hcpriv = data;
+       xfer->hcpriv = data;
 
 #ifdef OHCI_DEBUG
        if (ohcidebug > 5) {
@@ -2367,9 +2626,8 @@ ohci_device_intr_start(reqh)
 
        /* Insert ED in schedule */
        s = splusb();
-       ohci_hash_add_td(sc, data);
        sed->ed.ed_tailp = LE(tail->physaddr);
-       opipe->tail = tail;
+       opipe->tail.td = tail;
        sed->ed.ed_flags &= LE(~OHCI_ED_SKIP);
 
 #if 0
@@ -2379,7 +2637,7 @@ ohci_device_intr_start(reqh)
  * TD is gone.
  */
        if (ohcidebug > 5) {
-               delay(5000);
+               usb_delay_ms(&sc->sc_bus, 5);
                DPRINTF(("ohci_device_intr_transfer: status=%x\n",
                         OREAD4(sc, OHCI_COMMAND_STATUS)));
                ohci_dump_ed(sed);
@@ -2393,14 +2651,14 @@ ohci_device_intr_start(reqh)
 
 /* Abort a device control request. */
 void
-ohci_device_intr_abort(reqh)
-       usbd_request_handle reqh;
+ohci_device_intr_abort(xfer)
+       usbd_xfer_handle xfer;
 {
-       if (reqh->pipe->intrreqh == reqh) {
+       if (xfer->pipe->intrxfer == xfer) {
                DPRINTF(("ohci_device_intr_abort: remove\n"));
-               reqh->pipe->intrreqh = 0;
+               xfer->pipe->intrxfer = NULL;
        }
-       ohci_abort_req(reqh, USBD_CANCELLED);
+       ohci_abort_xfer(xfer, USBD_CANCELLED);
 }
 
 /* Close a device interrupt pipe. */
@@ -2420,14 +2678,16 @@ ohci_device_intr_close(pipe)
                    pipe, nslots, pos));
        s = splusb();
        sed->ed.ed_flags |= LE(OHCI_ED_SKIP);
-       if ((sed->ed.ed_tailp & LE(OHCI_TAILMASK)) != 
-           (sed->ed.ed_headp & LE(OHCI_TAILMASK)))
+       if ((sed->ed.ed_tailp & LE(OHCI_HEADMASK)) != 
+           (sed->ed.ed_headp & LE(OHCI_HEADMASK)))
                usb_delay_ms(&sc->sc_bus, 2);
 
        for (p = sc->sc_eds[pos]; p && p->next != sed; p = p->next)
                ;
-       if (!p)
+#ifdef DIAGNOSTIC
+       if (p == NULL)
                panic("ohci_device_intr_close: ED not found\n");
+#endif
        p->next = sed->next;
        p->ed.ed_nexted = sed->ed.ed_nexted;
        splx(s);
@@ -2435,7 +2695,7 @@ ohci_device_intr_close(pipe)
        for (j = 0; j < nslots; j++)
                --sc->sc_bws[(pos * nslots + j) % OHCI_NO_INTRS];
 
-       ohci_free_std(sc, opipe->tail);
+       ohci_free_std(sc, opipe->tail.td);
        ohci_free_sed(sc, opipe->sed);
 }
 
@@ -2504,3 +2764,149 @@ ohci_device_setintr(sc, opipe, ival)
        return (USBD_NORMAL_COMPLETION);
 }
 
+/***********************/
+
+usbd_status
+ohci_device_isoc_transfer(xfer)
+       usbd_xfer_handle xfer;
+{
+       usbd_status err;
+
+       DPRINTFN(5,("ohci_device_isoc_transfer: xfer=%p\n", xfer));
+
+       /* Put it on our queue, */
+       err = usb_insert_transfer(xfer);
+
+       /* bail out on error, */
+       if (err && err != USBD_IN_PROGRESS)
+               return (err);
+
+       /* XXX should check inuse here */
+
+       /* insert into schedule */
+       ohci_device_isoc_enter(xfer);
+
+       /* and put on interrupt list if the pipe wasn't running */
+       if (!err)
+               ohci_device_isoc_start(SIMPLEQ_FIRST(&xfer->pipe->queue));
+
+       return (err);
+}
+
+void
+ohci_device_isoc_enter(xfer)
+       usbd_xfer_handle xfer;
+{
+       struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
+       usbd_device_handle dev = opipe->pipe.device;
+       ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
+       ohci_soft_ed_t *sed = opipe->sed;
+       struct iso *iso = &opipe->u.iso;
+       ohci_soft_itd_t *sitd, *nsitd;
+       ohci_physaddr_t buf, offs;
+       int i, ncur, nframes;
+       int ncross;
+       int s;
+
+       s = splusb();
+       sitd = opipe->tail.itd;
+       buf = DMAADDR(&xfer->dmabuf);
+       sitd->itd.itd_bp0 = LE(buf & OHCI_ITD_PAGE_MASK);
+       nframes = xfer->nframes;
+       offs = buf & OHCI_ITD_OFFSET_MASK;
+       ncross = 0;
+       for (i = ncur = 0; i < nframes; i ++, ncur++) {
+               if (ncur == OHCI_ITD_NOFFSET || /* all offsets used */
+                   ncross > 1) {               /* too many page crossings */
+                       nsitd = ohci_alloc_sitd(sc);
+                       if (nsitd == NULL) {
+                               /* XXX what now? */
+                               return;
+                       }
+                       sitd->nextitd = nsitd;
+                       sitd->itd.itd_nextitd = LE(nsitd->physaddr);
+                       sitd->itd.itd_flags = LE(
+                               OHCI_ITD_NOCC |
+                               OHCI_ITD_SET_SF(iso->next) |
+                               OHCI_ITD_NOINTR |
+                               OHCI_ITD_SET_FC(OHCI_ITD_NOFFSET));
+                       sitd->itd.itd_be = LE(LE(sitd->itd.itd_bp0) + offs - 1);
+                       nsitd->itd.itd_bp0 = LE((buf + offs) & OHCI_ITD_PAGE_MASK);
+                       sitd = nsitd;
+                       iso->next = iso->next + ncur;
+                       ncur = 0;
+                       ncross = 0;
+               }
+               /* XXX byte order */
+               sitd->itd.itd_offset[i] =
+                   offs | (ncross == 1 ? OHCI_ITD_PAGE_SELECT : 0);
+               offs += xfer->frlengths[i];
+               /* XXX update ncross */
+       }
+       nsitd = ohci_alloc_sitd(sc);
+       if (nsitd == NULL) {
+               /* XXX what now? */
+               return;
+       }
+       sitd->nextitd = nsitd;
+       sitd->itd.itd_nextitd = LE(nsitd->physaddr);
+       sitd->itd.itd_flags = LE(
+               OHCI_ITD_NOCC |
+               OHCI_ITD_SET_SF(iso->next) |
+               OHCI_ITD_SET_DI(0) |
+               OHCI_ITD_SET_FC(ncur));
+       sitd->itd.itd_be = LE(LE(sitd->itd.itd_bp0) + offs - 1);
+       iso->next = iso->next + ncur;
+
+       opipe->tail.itd = nsitd;
+       sed->ed.ed_tailp = LE(nsitd->physaddr);
+       /* XXX update ED */
+       splx(s);
+}
+
+usbd_status
+ohci_device_isoc_start(xfer)
+       usbd_xfer_handle xfer;
+{
+       printf("ohci_device_isoc_start: not implemented\n");
+       return (USBD_INVAL);
+}
+
+void
+ohci_device_isoc_abort(xfer)
+       usbd_xfer_handle xfer;
+{
+}
+
+void
+ohci_device_isoc_done(xfer)
+       usbd_xfer_handle xfer;
+{
+       printf("ohci_device_isoc_done: not implemented\n");
+}
+
+usbd_status
+ohci_setup_isoc(pipe)
+       usbd_pipe_handle pipe;
+{
+       struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
+       struct iso *iso = &opipe->u.iso;
+
+       iso->next = -1;
+       iso->inuse = 0;
+
+       return (USBD_NORMAL_COMPLETION);
+}
+
+void
+ohci_device_isoc_close(pipe)
+       usbd_pipe_handle pipe;
+{
+       struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
+       ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
+
+       DPRINTF(("ohci_device_isoc_close: pipe=%p\n", pipe));
+       ohci_close_pipe(pipe, sc->sc_isoc_head);
+       ohci_free_sitd(sc, opipe->tail.itd);
+}
+
index 67b010a..c9700f6 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: ohcireg.h,v 1.3 1999/09/27 18:03:55 fgsch Exp $       */
-/*     $NetBSD: ohcireg.h,v 1.9 1999/09/15 21:14:03 augustss Exp $     */
+/*     $OpenBSD: ohcireg.h,v 1.4 2000/03/26 08:39:45 aaron Exp $       */
+/*     $NetBSD: ohcireg.h,v 1.15 2000/03/19 22:24:58 augustss Exp $    */
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
 #define  OHCI_GET_NDP(s)       ((s) & 0xff)
 #define  OHCI_PSM              0x0100     /* Power Switching Mode */
 #define  OHCI_NPS              0x0200     /* No Power Switching */
+#define  OHCI_DT               0x0400     /* Device Type */
+#define  OHCI_OCPM             0x0800     /* Overcurrent Protection Mode */
+#define  OHCI_NOCP             0x1000     /* No Overcurrent Protection */
 #define  OHCI_GET_POTPGT(s)    ((s) >> 24)
 #define OHCI_RH_DESCRIPTOR_B   0x4c
 #define OHCI_RH_STATUS         0x50
@@ -162,10 +165,10 @@ typedef struct {
 #define OHCI_ED_SET_MAXP(s)    ((s) << 16)
 #define OHCI_ED_MAXPMASK       (0x7ff << 16)
        ohci_physaddr_t ed_tailp;
-#define OHCI_HALTED            0x00000002
-#define OHCI_TOGGLECARRY       0x00000001
-#define OHCI_TAILMASK          0xfffffffc
        ohci_physaddr_t ed_headp;
+#define OHCI_HALTED            0x00000001
+#define OHCI_TOGGLECARRY       0x00000002
+#define OHCI_HEADMASK          0xfffffffc
        ohci_physaddr_t ed_nexted;
 } ohci_ed_t;
 /* #define OHCI_ED_SIZE 16 */
@@ -181,9 +184,11 @@ typedef struct {
 #define OHCI_TD_GET_DI(x)      (((x) >> 21) & 7)       /* Delay Interrupt */
 #define OHCI_TD_SET_DI(x)      ((x) << 21)
 #define  OHCI_TD_NOINTR                0x00e00000
+#define  OHCI_TD_INTR_MASK     0x00e00000
 #define OHCI_TD_TOGGLE_CARRY   0x00000000
 #define OHCI_TD_TOGGLE_0       0x02000000
 #define OHCI_TD_TOGGLE_1       0x03000000
+#define OHCI_TD_TOGGLE_MASK    0x03000000
 #define OHCI_TD_GET_EC(x)      (((x) >> 26) & 3)       /* Error Count */
 #define OHCI_TD_GET_CC(x)      ((x) >> 28)             /* Condition Code */
 #define  OHCI_TD_NOCC          0xf0000000
@@ -194,6 +199,32 @@ typedef struct {
 /* #define OHCI_TD_SIZE 16 */
 #define OHCI_TD_ALIGN 16
 
+#define OHCI_ITD_NOFFSET 8
+typedef struct {
+       u_int32_t       itd_flags;
+#define OHCI_ITD_GET_SF(x)     ((x) & 0x0000ffff)
+#define OHCI_ITD_SET_SF(x)     ((x) & 0xffff)
+#define OHCI_ITD_GET_DI(x)     (((x) >> 21) & 7)       /* Delay interrupt */
+#define OHCI_ITD_SET_DI(x)     ((x) << 21)
+#define OHCI_ITD_NOINTR                0x00e00000
+#define OHCI_ITD_GET_FC(x)     ((((x) >> 24) & 7)+1)   /* Frame Count */
+#define OHCI_ITD_SET_FC(x)     (((x)-1) << 24)
+#define OHCI_ITD_GET_CC(x)     ((x) >> 28)             /* Condition Code */
+#define OHCI_ITD_NOCC          0xf0000000
+       ohci_physaddr_t itd_bp0;                        /* Buffer Page 0 */
+#define OHCI_ITD_OFFSET_MASK   0x00000fff
+#define OHCI_ITD_PAGE_MASK     (~OHCI_ITD_OFFSET_MASK)
+       ohci_physaddr_t itd_nextitd;                    /* Next ITD */
+       ohci_physaddr_t itd_be;                         /* Buffer End */
+       u_int16_t       itd_offset[OHCI_ITD_NOFFSET];   /* Buffer offsets */
+#define itd_pswn itd_offset                            /* Packet Status Word */
+#define OHCI_ITD_PAGE_SELECT   0x00001000
+#define OHCI_ITD_PSW_LENGTH(x) ((x) & 0xfff)           /* Transfer length */
+#define OHCI_ITD_PSW_GET_CC(x) ((x) >> 12)             /* Condition Code */
+} ohci_itd_t;
+/* #define OHCI_ITD_SIZE 32 */
+#define OHCI_ITD_ALIGN 32
+
 #define OHCI_CC_NO_ERROR               0
 #define OHCI_CC_CRC                    1
 #define OHCI_CC_BIT_STUFFING           2
index e33423d..a0ad463 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: ohcivar.h,v 1.6 1999/11/07 21:30:19 fgsch Exp $       */
-/*     $NetBSD: ohcivar.h,v 1.11 1999/09/15 21:14:03 augustss Exp $    */
+/*     $OpenBSD: ohcivar.h,v 1.7 2000/03/26 08:39:45 aaron Exp $       */
+/*     $NetBSD: ohcivar.h,v 1.20 2000/02/22 11:30:55 augustss Exp $    */
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -52,7 +52,7 @@ typedef struct ohci_soft_td {
        struct ohci_soft_td *dnext; /* next in done list */
        ohci_physaddr_t physaddr;
        LIST_ENTRY(ohci_soft_td) hnext;
-       usbd_request_handle reqh;
+       usbd_xfer_handle xfer;
        u_int16_t len;
        u_int16_t flags;
 #define OHCI_CALL_DONE 0x0001
@@ -61,6 +61,14 @@ typedef struct ohci_soft_td {
 #define OHCI_STD_SIZE ((sizeof (struct ohci_soft_td) + OHCI_TD_ALIGN - 1) / OHCI_TD_ALIGN * OHCI_TD_ALIGN)
 #define OHCI_STD_CHUNK 128
 
+typedef struct ohci_soft_itd {
+       ohci_itd_t itd;
+       struct ohci_soft_itd *nextitd; /* mirrors nexttd in ITD */
+       ohci_physaddr_t physaddr;
+} ohci_soft_itd_t;
+#define OHCI_SITD_SIZE ((sizeof (struct ohci_soft_itd) + OHCI_ITD_ALIGN - 1) / OHCI_ITD_ALIGN * OHCI_ITD_ALIGN)
+#define OHCI_SITD_CHUNK 64
+
 #define OHCI_NO_EDS (2*OHCI_NO_INTRS-1)
 
 #define OHCI_HASH_SIZE 128
@@ -76,6 +84,7 @@ typedef struct ohci_softc {
        u_int sc_bws[OHCI_NO_INTRS];
 
        u_int32_t sc_eintrs;
+       ohci_soft_ed_t *sc_isoc_head;
        ohci_soft_ed_t *sc_ctrl_head;
        ohci_soft_ed_t *sc_bulk_head;
 
@@ -87,19 +96,30 @@ typedef struct ohci_softc {
 
        ohci_soft_ed_t *sc_freeeds;
        ohci_soft_td_t *sc_freetds;
+       ohci_soft_itd_t *sc_freeitds;
+
+       SIMPLEQ_HEAD(, usbd_xfer) sc_free_xfers; /* free xfers */
 
-       usbd_request_handle sc_intrreqh;
+       usbd_xfer_handle sc_intrxfer;
+
+       ohci_physaddr_t sc_done;
 
        char sc_vendor[16];
        int sc_id_vendor;
 
-       void *sc_powerhook;
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+       void *sc_powerhook;             /* cookie from power hook */
+       void *sc_shutdownhook;          /* cookie from shutdown hook */
+#endif
+
        device_ptr_t sc_child;
 } ohci_softc_t;
 
 usbd_status    ohci_init __P((ohci_softc_t *));
 int            ohci_intr __P((void *));
+#if defined(__NetBSD__) || defined(__OpenBSD__)
 int            ohci_detach __P((ohci_softc_t *, int));
 int            ohci_activate __P((device_ptr_t, enum devact));
+#endif
 
 #define MS_TO_TICKS(ms) ((ms) * hz / 1000)
index 2c18681..558f721 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: uaudio.c,v 1.1 1999/11/11 15:54:59 ho Exp $   */
-/*     $NetBSD: uaudio.c,v 1.5 1999/10/25 10:16:49 augustss Exp $      */
+/*     $OpenBSD: uaudio.c,v 1.2 2000/03/26 08:39:45 aaron Exp $        */
+/*     $NetBSD: uaudio.c,v 1.20 2000/03/24 13:02:00 augustss Exp $     */
 
 /*
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -132,11 +132,13 @@ struct chan {
        int     curchanbuf;
        struct chanbuf {
                struct chan         *chan;
-               usbd_request_handle reqh;
+               usbd_xfer_handle xfer;
                u_char              *buffer;
                u_int16_t           sizes[UAUDIO_NFRAMES];
                u_int16_t           size;
        } chanbufs[UAUDIO_NCHANBUFS];
+
+       struct uaudio_softc *sc; /* our softc */
 };
 
 struct uaudio_softc {
@@ -154,6 +156,8 @@ struct uaudio_softc {
 
        int     sc_nullalt;
 
+       int     sc_audio_rev;
+
        struct as_info *sc_alts;
        int     sc_nalts;
        int     sc_props;
@@ -204,6 +208,9 @@ void uaudio_add_selector __P((struct uaudio_softc *sc, usb_descriptor_t *v,
                              usb_descriptor_t **dps));
 void uaudio_add_feature __P((struct uaudio_softc *sc, usb_descriptor_t *v, 
                             usb_descriptor_t **dps));
+void uaudio_add_processing_updown __P((struct uaudio_softc *sc,
+                                      usb_descriptor_t *v,
+                                      usb_descriptor_t **dps));
 void uaudio_add_processing __P((struct uaudio_softc *sc, usb_descriptor_t *v, 
                                usb_descriptor_t **dps));
 void uaudio_add_extension __P((struct uaudio_softc *sc, usb_descriptor_t *v, 
@@ -232,11 +239,11 @@ void      uaudio_chan_free_buffers __P((struct uaudio_softc *, struct chan *));
 void   uaudio_chan_set_param __P((struct chan *ch, struct audio_params *param,
                                   u_char *start, u_char *end, int blksize));
 void   uaudio_chan_ptransfer __P((struct chan *ch));
-void   uaudio_chan_pintr __P((usbd_request_handle reqh
+void   uaudio_chan_pintr __P((usbd_xfer_handle xfer
                               usbd_private_handle priv, usbd_status status));
 
 void   uaudio_chan_rtransfer __P((struct chan *ch));
-void   uaudio_chan_rintr __P((usbd_request_handle reqh
+void   uaudio_chan_rintr __P((usbd_xfer_handle xfer
                               usbd_private_handle priv, usbd_status status));
 
 
@@ -304,14 +311,15 @@ USB_MATCH(uaudio)
        USB_MATCH_START(uaudio, uaa);
        usb_interface_descriptor_t *id;
        
-       if (!uaa->iface)
+       if (uaa->iface == NULL)
                return (UMATCH_NONE);
 
        id = usbd_get_interface_descriptor(uaa->iface);
        /* Trigger on the control interface. */
-       if (!id || 
-           id->bInterfaceClass != UCLASS_AUDIO ||
-           id->bInterfaceSubClass != USUBCLASS_AUDIOCONTROL)
+       if (id == NULL || 
+           id->bInterfaceClass != UICLASS_AUDIO ||
+           id->bInterfaceSubClass != UISUBCLASS_AUDIOCONTROL ||
+           (usbd_get_quirks(uaa->device)->uq_flags & UQ_BAD_AUDIO))
                return (UMATCH_NONE);
 
        return (UMATCH_IFACECLASS_IFACESUBCLASS);
@@ -323,7 +331,7 @@ USB_ATTACH(uaudio)
        usb_interface_descriptor_t *id;
        usb_config_descriptor_t *cdesc;
        char devinfo[1024];
-       usbd_status r;
+       usbd_status err;
        int i;
 
        usbd_devinfo(uaa->device, 0, devinfo);
@@ -332,36 +340,50 @@ USB_ATTACH(uaudio)
        sc->sc_udev = uaa->device;
 
        cdesc = usbd_get_config_descriptor(sc->sc_udev);
-       if (!cdesc)
+       if (cdesc == NULL) {
+               printf("%s: failed to get configuration descriptor\n",
+                      USBDEVNAME(sc->sc_dev));
                USB_ATTACH_ERROR_RETURN;
+       }
 
-       r = uaudio_identify(sc, cdesc);
-       if (r != USBD_NORMAL_COMPLETION) {
+       err = uaudio_identify(sc, cdesc);
+       if (err) {
                printf("%s: audio descriptors make no sense, error=%d\n",
-                      USBDEVNAME(sc->sc_dev), r);
+                      USBDEVNAME(sc->sc_dev), err);
                USB_ATTACH_ERROR_RETURN;
        }
 
        sc->sc_ac_ifaceh = uaa->iface;
        /* Pick up the AS interface. */
        for (i = 0; i < uaa->nifaces; i++) {
-               if (uaa->ifaces[i]) {
+               if (uaa->ifaces[i] != NULL) {
                        id = usbd_get_interface_descriptor(uaa->ifaces[i]);
-                       if (id->bInterfaceNumber == sc->sc_as_iface) {
+                       if (id != NULL &&
+                           id->bInterfaceNumber == sc->sc_as_iface) {
                                sc->sc_as_ifaceh = uaa->ifaces[i];
-                               uaa->ifaces[i] = 0;
+                               uaa->ifaces[i] = NULL;
+                               break;
                        }
                }
        }
 
-       if (!sc->sc_as_ifaceh) {
+       if (sc->sc_as_ifaceh == NULL) {
                printf("%s: missing AS interface(s)\n",USBDEVNAME(sc->sc_dev));
                USB_ATTACH_ERROR_RETURN;
        }
 
+       printf("%s: streaming interface %d, audio rev %d.%02x\n",
+              USBDEVNAME(sc->sc_dev), sc->sc_as_iface,
+              sc->sc_audio_rev >> 8, sc->sc_audio_rev & 0xff);
+
+       sc->sc_chan.sc = sc;
+
        DPRINTF(("uaudio_attach: doing audio_attach_mi\n"));
        /* sc->sc_audiodev = */ audio_attach_mi(&uaudio_hw_if, sc, &sc->sc_dev);
 
+       usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
+                          USBDEV(sc->sc_dev));
+
        USB_ATTACH_SUCCESS_RETURN;
 }
 
@@ -395,9 +417,15 @@ uaudio_detach(self, flags)
        struct uaudio_softc *sc = (struct uaudio_softc *)self;
        int rv = 0;
 
-       if (sc->sc_audiodev)
+       /* Wait for outstanding requests to complete. */
+       usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES);
+
+       if (sc->sc_audiodev != NULL)
                rv = config_detach(sc->sc_audiodev, flags);
 
+       usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
+                          USBDEV(sc->sc_dev));
+
        return (rv);
 }
 
@@ -484,7 +512,7 @@ uaudio_find_iface(buf, size, offsp, subtype)
                d = (void *)(buf + *offsp);
                *offsp += d->bLength;
                if (d->bDescriptorType == UDESC_INTERFACE &&
-                   d->bInterfaceClass == UCLASS_AUDIO &&
+                   d->bInterfaceClass == UICLASS_AUDIO &&
                    d->bInterfaceSubClass == subtype)
                        return (d);
        }
@@ -496,7 +524,7 @@ uaudio_mixer_add_ctl(sc, mc)
        struct uaudio_softc *sc;
        struct mixerctl *mc;
 {
-       if (sc->sc_nctls == 0)
+       if (sc->sc_nctls == NULL)
                sc->sc_ctls = malloc(sizeof *mc, M_USBDEV, M_NOWAIT);
        else
 #ifdef __OpenBSD__
@@ -514,7 +542,7 @@ uaudio_mixer_add_ctl(sc, mc)
                                      (sc->sc_nctls+1) * sizeof *mc,
                                      M_USBDEV, M_NOWAIT);
 #endif
-       if (sc->sc_ctls == 0) {
+       if (sc->sc_ctls == NULL) {
                printf("uaudio_mixer_add_ctl: no memory\n");
                return;
        }
@@ -623,7 +651,7 @@ uaudio_get_cluster(id, dps)
  bad:
        printf("uaudio_get_cluster: bad data\n");
        memset(&r, 0, sizeof r);
-       return r;
+       return (r);
 
 }
 
@@ -644,7 +672,6 @@ uaudio_add_input(sc, v, dps)
                    d->bNrChannels, UGETW(d->wChannelConfig),
                    d->iChannelNames, d->iTerminal));
 #endif
-       printf("uaudio_add_input: not implemented\n");
 }
 
 void
@@ -837,7 +864,7 @@ uaudio_add_feature(sc, v, dps)
                        mix.ctlunit = AudioNtreble;
                        break;
                case GRAPHIC_EQUALIZER_CONTROL:
-                       continue; /* don't add anything */
+                       continue; /* XXX don't add anything */
                        break;
                case AGC_CONTROL:
                        mix.type = MIX_ON_OFF;
@@ -872,20 +899,89 @@ uaudio_add_feature(sc, v, dps)
        }
 }
 
+void
+uaudio_add_processing_updown(sc, v, dps)
+       struct uaudio_softc *sc;
+       usb_descriptor_t *v;
+       usb_descriptor_t **dps;
+{
+       struct usb_audio_processing_unit *d = 
+           (struct usb_audio_processing_unit *)v;
+       struct usb_audio_processing_unit_1 *d1 =
+           (struct usb_audio_processing_unit_1 *)&d->baSourceId[d->bNrInPins];
+       struct usb_audio_processing_unit_updown *ud =
+           (struct usb_audio_processing_unit_updown *)
+               &d1->bmControls[d1->bControlSize];
+       struct mixerctl mix;
+       int i;
+
+       DPRINTFN(2,("uaudio_add_processing_updown: bUnitId=%d bNrModes=%d\n",
+                   d->bUnitId, ud->bNrModes));
+
+       if (!(d1->bmControls[0] & UA_PROC_MASK(UD_MODE_SELECT_CONTROL))) {
+               DPRINTF(("uaudio_add_processing_updown: no mode select\n"));
+               return;
+       }
+
+       mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
+       mix.nchan = 1;
+       mix.wValue[0] = MAKE(UD_MODE_SELECT_CONTROL, 0);
+       mix.class = -1;
+       mix.type = MIX_ON_OFF; /* XXX */
+       mix.ctlunit = "";
+       sprintf(mix.ctlname, "pro%d-mode", d->bUnitId);
+
+       for (i = 0; i < ud->bNrModes; i++) {
+               DPRINTFN(2,("uaudio_add_processing_updown: i=%d bm=0x%x\n",
+                           i, UGETW(ud->waModes[i])));
+               /* XXX */
+       }
+       uaudio_mixer_add_ctl(sc, &mix);
+}
+
 void
 uaudio_add_processing(sc, v, dps)
        struct uaudio_softc *sc;
        usb_descriptor_t *v;
        usb_descriptor_t **dps;
 {
-#ifdef UAUDIO_DEBUG
        struct usb_audio_processing_unit *d = 
-               (struct usb_audio_processing_unit *)v;
+           (struct usb_audio_processing_unit *)v;
+       struct usb_audio_processing_unit_1 *d1 =
+           (struct usb_audio_processing_unit_1 *)&d->baSourceId[d->bNrInPins];
+       int ptype = UGETW(d->wProcessType);
+       struct mixerctl mix;
 
-       DPRINTFN(2,("uaudio_add_processing: bUnitId=%d bNrInPins=%d\n",
-                   d->bUnitId, d->bNrInPins));
-       printf("uaudio_add_processing: NOT IMPLEMENTED\n");
+       DPRINTFN(2,("uaudio_add_processing: wProcessType=%d bUnitId=%d "
+                   "bNrInPins=%d\n", ptype, d->bUnitId, d->bNrInPins));
+
+       if (d1->bmControls[0] & UA_PROC_ENABLE_MASK) {
+               mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
+               mix.nchan = 1;
+               mix.wValue[0] = MAKE(XX_ENABLE_CONTROL, 0);
+               mix.class = -1;
+               mix.type = MIX_ON_OFF;
+               mix.ctlunit = "";
+               sprintf(mix.ctlname, "pro%d.%d-enable", d->bUnitId, ptype);
+               uaudio_mixer_add_ctl(sc, &mix);
+       }
+
+       switch (ptype) {
+       case UPDOWNMIX_PROCESS:
+               uaudio_add_processing_updown(sc, v, dps);
+               break;
+       case DOLBY_PROLOGIC_PROCESS:
+       case P3D_STEREO_EXTENDER_PROCESS:
+       case REVERBATION_PROCESS:
+       case CHORUS_PROCESS:
+       case DYN_RANGE_COMP_PROCESS:
+       default:
+#ifdef UAUDIO_DEBUG
+               printf("uaudio_add_processing: unit %d, type=%d not impl.\n",
+                      d->bUnitId, ptype);
 #endif
+               break;
+       }
 }
 
 void
@@ -903,7 +999,7 @@ uaudio_add_extension(sc, v, dps)
        DPRINTFN(2,("uaudio_add_extension: bUnitId=%d bNrInPins=%d\n",
                    d->bUnitId, d->bNrInPins));
 
-       if (d1->bmControls[0] & (1 << UA_EXT_ENABLE)) {
+       if (d1->bmControls[0] & UA_EXT_ENABLE_MASK) {
                mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
                mix.nchan = 1;
                mix.wValue[0] = MAKE(UA_EXT_ENABLE, 0);
@@ -920,11 +1016,11 @@ uaudio_identify(sc, cdesc)
        struct uaudio_softc *sc;
        usb_config_descriptor_t *cdesc;
 {
-       usbd_status r;
+       usbd_status err;
 
-       r = uaudio_identify_ac(sc, cdesc);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = uaudio_identify_ac(sc, cdesc);
+       if (err)
+               return (err);
        return (uaudio_identify_as(sc, cdesc));
 }
 
@@ -933,7 +1029,7 @@ uaudio_add_alt(sc, ai)
        struct uaudio_softc *sc;
        struct as_info *ai;
 {
-       if (sc->sc_nalts == 0)
+       if (sc->sc_nalts == NULL)
                sc->sc_alts = malloc(sizeof *ai, M_USBDEV, M_NOWAIT);
        else
 #ifdef __OpenBSD__
@@ -1084,7 +1180,7 @@ uaudio_identify_as(sc, cdesc)
        usb_config_descriptor_t *cdesc;
 {
        usb_interface_descriptor_t *id;
-       usbd_status r;
+       usbd_status err;
        char *buf;
        int size, offs;
 
@@ -1093,8 +1189,8 @@ uaudio_identify_as(sc, cdesc)
 
        /* Locate the AudioStreaming interface descriptor. */
        offs = 0;
-       id = uaudio_find_iface(buf, size, &offs, USUBCLASS_AUDIOSTREAM);
-       if (!id)
+       id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOSTREAM);
+       if (id == NULL)
                return (USBD_INVAL);
        sc->sc_as_iface = id->bInterfaceNumber;
        DPRINTF(("uaudio_identify_as: AS interface is %d\n", sc->sc_as_iface));
@@ -1110,7 +1206,7 @@ uaudio_identify_as(sc, cdesc)
                        sc->sc_nullalt = id->bAlternateSetting;
                        break;
                case 1:
-                       r = uaudio_process_as(sc, buf, &offs, size, id);
+                       err = uaudio_process_as(sc, buf, &offs, size, id);
                        break;
                default:
 #ifdef AUDIO_DEBUG
@@ -1120,7 +1216,7 @@ uaudio_identify_as(sc, cdesc)
 #endif
                        break;
                }
-               id = uaudio_find_iface(buf, size, &offs,USUBCLASS_AUDIOSTREAM);
+               id = uaudio_find_iface(buf, size, &offs,UISUBCLASS_AUDIOSTREAM);
                if (!id)
                        break;
        }
@@ -1151,8 +1247,8 @@ uaudio_identify_ac(sc, cdesc)
 
        /* Locate the AudioControl interface descriptor. */
        offs = 0;
-       id = uaudio_find_iface(buf, size, &offs, USUBCLASS_AUDIOCONTROL);
-       if (!id)
+       id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOCONTROL);
+       if (id == NULL)
                return (USBD_INVAL);
        if (offs + sizeof *acdp > size)
                return (USBD_INVAL);
@@ -1173,8 +1269,9 @@ uaudio_identify_ac(sc, cdesc)
             UGETW(acdp->bcdADC) != UAUDIO_VERSION)
                return (USBD_INVAL);
 
+       sc->sc_audio_rev = UGETW(acdp->bcdADC);
        DPRINTFN(2,("uaudio_identify: found AC header, vers=%03x, len=%d\n",
-                UGETW(acdp->bcdADC), aclen));
+                sc->sc_audio_rev, aclen));
 
        sc->sc_nullalt = -1;
 
@@ -1204,7 +1301,7 @@ uaudio_identify_ac(sc, cdesc)
 
        for (i = 0; i < ndps; i++) {
                dp = dps[i];
-               if (dp == 0)
+               if (dp == NULL)
                        continue;
                DPRINTF(("uaudio_identify: subtype=%d\n", 
                         dp->bDescriptorSubtype));
@@ -1362,7 +1459,7 @@ uaudio_halt_out_dma(addr)
        struct uaudio_softc *sc = addr;
 
        DPRINTF(("uaudio_halt_out_dma: enter\n"));
-       if (sc->sc_chan.pipe) {
+       if (sc->sc_chan.pipe != NULL) {
                uaudio_chan_close(sc, &sc->sc_chan);
                sc->sc_chan.pipe = 0;
                uaudio_chan_free_buffers(sc, &sc->sc_chan);
@@ -1377,7 +1474,7 @@ uaudio_halt_in_dma(addr)
        struct uaudio_softc *sc = addr;
 
        DPRINTF(("uaudio_halt_in_dma: enter\n"));
-       if (sc->sc_chan.pipe) {
+       if (sc->sc_chan.pipe != NULL) {
                uaudio_chan_close(sc, &sc->sc_chan);
                sc->sc_chan.pipe = 0;
                uaudio_chan_free_buffers(sc, &sc->sc_chan);
@@ -1437,9 +1534,6 @@ uaudio_get_props(addr)
 {
        struct uaudio_softc *sc = addr;
 
-       if (sc->sc_dying)
-               return (EIO);
-    
        return (sc->sc_props);
 }
 
@@ -1450,7 +1544,7 @@ uaudio_get(sc, which, type, wValue, wIndex, len)
 {
        usb_device_request_t req;
        u_int8_t data[4];
-       usbd_status r;
+       usbd_status err;
        int val;
 
        if (wValue == -1)
@@ -1464,9 +1558,9 @@ uaudio_get(sc, which, type, wValue, wIndex, len)
        DPRINTFN(2,("uaudio_get: type=0x%02x req=0x%02x wValue=0x%04x "
                    "wIndex=0x%04x len=%d\n", 
                    type, which, wValue, wIndex, len));
-       r = usbd_do_request(sc->sc_udev, &req, &data);
-       if (r != USBD_NORMAL_COMPLETION) {
-               DPRINTF(("uaudio_get: r=%d\n", r));
+       err = usbd_do_request(sc->sc_udev, &req, &data);
+       if (err) {
+               DPRINTF(("uaudio_get: err=%s\n", usbd_errstr(err)));
                return (-1);
        }
        switch (len) {
@@ -1491,7 +1585,7 @@ uaudio_set(sc, which, type, wValue, wIndex, len, val)
 {
        usb_device_request_t req;
        u_int8_t data[4];
-       usbd_status r;
+       usbd_status err;
 
        if (wValue == -1)
                return;
@@ -1515,9 +1609,9 @@ uaudio_set(sc, which, type, wValue, wIndex, len, val)
        DPRINTFN(2,("uaudio_set: type=0x%02x req=0x%02x wValue=0x%04x "
                    "wIndex=0x%04x len=%d, val=%d\n", 
                    type, which, wValue, wIndex, len, val & 0xffff));
-       r = usbd_do_request(sc->sc_udev, &req, &data);
+       err = usbd_do_request(sc->sc_udev, &req, &data);
 #ifdef UAUDIO_DEBUG
-       if (r != USBD_NORMAL_COMPLETION)
+       if (err)
                DPRINTF(("uaudio_set: r=%d\n", r));
 #endif
 }
@@ -1687,7 +1781,7 @@ uaudio_trigger_input(addr, start, end, blksize, intr, arg, param)
 {
        struct uaudio_softc *sc = addr;
        struct chan *ch = &sc->sc_chan;
-       usbd_status r;
+       usbd_status err;
        int i, s;
 
        if (sc->sc_dying)
@@ -1701,12 +1795,12 @@ uaudio_trigger_input(addr, start, end, blksize, intr, arg, param)
                    "fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame,
                    ch->fraction));
 
-       r = uaudio_chan_alloc_buffers(sc, ch);
-       if (r != USBD_NORMAL_COMPLETION)
+       err = uaudio_chan_alloc_buffers(sc, ch);
+       if (err)
                return (EIO);
 
-       r = uaudio_chan_open(sc, ch);
-       if (r != USBD_NORMAL_COMPLETION) {
+       err = uaudio_chan_open(sc, ch);
+       if (err) {
                uaudio_chan_free_buffers(sc, ch);
                return (EIO);
        }
@@ -1733,7 +1827,7 @@ uaudio_trigger_output(addr, start, end, blksize, intr, arg, param)
 {
        struct uaudio_softc *sc = addr;
        struct chan *ch = &sc->sc_chan;
-       usbd_status r;
+       usbd_status err;
        int i, s;
 
        if (sc->sc_dying)
@@ -1747,12 +1841,12 @@ uaudio_trigger_output(addr, start, end, blksize, intr, arg, param)
                    "fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame,
                    ch->fraction));
 
-       r = uaudio_chan_alloc_buffers(sc, ch);
-       if (r != USBD_NORMAL_COMPLETION)
+       err = uaudio_chan_alloc_buffers(sc, ch);
+       if (err)
                return (EIO);
 
-       r = uaudio_chan_open(sc, ch);
-       if (r != USBD_NORMAL_COMPLETION) {
+       err = uaudio_chan_open(sc, ch);
+       if (err) {
                uaudio_chan_free_buffers(sc, ch);
                return (EIO);
        }
@@ -1776,29 +1870,29 @@ uaudio_chan_open(sc, ch)
 {
        struct as_info *as = &sc->sc_alts[sc->sc_curaltidx];
        int endpt = as->edesc->bEndpointAddress;
-       usbd_status r;
+       usbd_status err;
 
        DPRINTF(("uaudio_open_chan: endpt=0x%02x, speed=%d, alt=%d\n", 
                 endpt, ch->sample_rate, as->alt));
 
        /* Set alternate interface corresponding to the mode. */
-       r = usbd_set_interface(sc->sc_as_ifaceh, as->alt);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = usbd_set_interface(sc->sc_as_ifaceh, as->alt);
+       if (err)
+               return (err);
 
        /* Some devices do not support this request, so ignore errors. */
 #ifdef UAUDIO_DEBUG
-       r = uaudio_set_speed(sc, endpt, ch->sample_rate);
-       if (r != USBD_NORMAL_COMPLETION)
+       err = uaudio_set_speed(sc, endpt, ch->sample_rate);
+       if (err)
                DPRINTF(("uaudio_chan_open: set_speed failed r=%s\n",
-                        usbd_errstr(r)));
+                        usbd_errstr(err)));
 #else
        (void)uaudio_set_speed(sc, endpt, ch->sample_rate);
 #endif
 
        DPRINTF(("uaudio_open_chan: create pipe to 0x%02x\n", endpt));
-       r = usbd_open_pipe(sc->sc_as_ifaceh, endpt, 0, &ch->pipe);
-       return (r);
+       err = usbd_open_pipe(sc->sc_as_ifaceh, endpt, 0, &ch->pipe);
+       return (err);
 }
 
 void
@@ -1820,17 +1914,17 @@ uaudio_chan_alloc_buffers(sc, ch)
        struct uaudio_softc *sc;
        struct chan *ch;
 {
-       usbd_request_handle reqh;
+       usbd_xfer_handle xfer;
        void *buf;
        int i, size;
 
        size = (ch->bytes_per_frame + ch->sample_size) * UAUDIO_NFRAMES;
        for (i = 0; i < UAUDIO_NCHANBUFS; i++) {
-               reqh = usbd_alloc_request(sc->sc_udev);
-               if (reqh == 0)
+               xfer = usbd_alloc_xfer(sc->sc_udev);
+               if (xfer == 0)
                        goto bad;
-               ch->chanbufs[i].reqh = reqh;
-               buf = usbd_alloc_buffer(reqh, size);
+               ch->chanbufs[i].xfer = xfer;
+               buf = usbd_alloc_buffer(xfer, size);
                if (buf == 0) {
                        i++;
                        goto bad;
@@ -1844,7 +1938,7 @@ uaudio_chan_alloc_buffers(sc, ch)
 bad:
        while (--i >= 0)
                /* implicit buffer free */
-               usbd_free_request(ch->chanbufs[i].reqh);
+               usbd_free_xfer(ch->chanbufs[i].xfer);
        return (USBD_NOMEM);
 }
 
@@ -1856,7 +1950,7 @@ uaudio_chan_free_buffers(sc, ch)
        int i;
 
        for (i = 0; i < UAUDIO_NCHANBUFS; i++)
-               usbd_free_request(ch->chanbufs[i].reqh);
+               usbd_free_xfer(ch->chanbufs[i].xfer);
 }
 
 /* Called at splusb() */
@@ -1867,6 +1961,9 @@ uaudio_chan_ptransfer(ch)
        struct chanbuf *cb;
        int i, n, size, residue, total;
 
+       if (ch->sc->sc_dying)
+               return;
+
        /* Pick the next channel buffer. */
        cb = &ch->chanbufs[ch->curchanbuf];
        if (++ch->curchanbuf >= UAUDIO_NCHANBUFS)
@@ -1913,18 +2010,18 @@ uaudio_chan_ptransfer(ch)
        }
 #endif
 
-       DPRINTFN(5,("uaudio_chan_transfer: ptransfer reqh=%p\n", cb->reqh));
+       DPRINTFN(5,("uaudio_chan_transfer: ptransfer xfer=%p\n", cb->xfer));
        /* Fill the request */
-       usbd_setup_isoc_request(cb->reqh, ch->pipe, cb, cb->sizes, 
+       usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes,
                                UAUDIO_NFRAMES, USBD_NO_COPY, 
                                uaudio_chan_pintr);
 
-       (void)usbd_transfer(cb->reqh);
+       (void)usbd_transfer(cb->xfer);
 }
 
 void
-uaudio_chan_pintr(reqh, priv, status)
-       usbd_request_handle reqh;
+uaudio_chan_pintr(xfer, priv, status)
+       usbd_xfer_handle xfer;
        usbd_private_handle priv;
        usbd_status status;
 {
@@ -1937,7 +2034,7 @@ uaudio_chan_pintr(reqh, priv, status)
        if (status == USBD_CANCELLED)
                return;
 
-       usbd_get_request_status(reqh, 0, 0, &count, 0);
+       usbd_get_xfer_status(xfer, NULL, NULL, &count, 0);
        DPRINTFN(5,("uaudio_chan_pintr: count=%d, transferred=%d\n",
                    count, ch->transferred));
 #ifdef DIAGNOSTIC
@@ -1970,6 +2067,9 @@ uaudio_chan_rtransfer(ch)
        struct chanbuf *cb;
        int i, size, residue, total;
 
+       if (ch->sc->sc_dying)
+               return;
+
        /* Pick the next channel buffer. */
        cb = &ch->chanbufs[ch->curchanbuf];
        if (++ch->curchanbuf >= UAUDIO_NCHANBUFS)
@@ -2001,18 +2101,18 @@ uaudio_chan_rtransfer(ch)
        }
 #endif
 
-       DPRINTFN(5,("uaudio_chan_rtransfer: transfer reqh=%p\n", cb->reqh));
+       DPRINTFN(5,("uaudio_chan_rtransfer: transfer xfer=%p\n", cb->xfer));
        /* Fill the request */
-       usbd_setup_isoc_request(cb->reqh, ch->pipe, cb, cb->sizes, 
+       usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes, 
                                UAUDIO_NFRAMES, USBD_NO_COPY, 
                                uaudio_chan_rintr);
 
-       (void)usbd_transfer(cb->reqh);
+       (void)usbd_transfer(cb->xfer);
 }
 
 void
-uaudio_chan_rintr(reqh, priv, status)
-       usbd_request_handle reqh;
+uaudio_chan_rintr(xfer, priv, status)
+       usbd_xfer_handle xfer;
        usbd_private_handle priv;
        usbd_status status;
 {
@@ -2025,7 +2125,7 @@ uaudio_chan_rintr(reqh, priv, status)
        if (status == USBD_CANCELLED)
                return;
 
-       usbd_get_request_status(reqh, 0, 0, &count, 0);
+       usbd_get_xfer_status(xfer, NULL, NULL, &count, 0);
        DPRINTFN(5,("uaudio_chan_rintr: count=%d, transferred=%d\n",
                    count, ch->transferred));
 #ifdef DIAGNOSTIC
@@ -2098,6 +2198,7 @@ uaudio_set_params(addr, setmode, usemode, p, r)
 {
        struct uaudio_softc *sc = addr;
        int flags = sc->sc_altflags;
+       int pfactor, rfactor;
        int enc, i, j;
        void (*pswcode) __P((void *, u_char *buf, int cnt));
        void (*rswcode) __P((void *, u_char *buf, int cnt));
@@ -2105,10 +2206,11 @@ uaudio_set_params(addr, setmode, usemode, p, r)
        if (sc->sc_dying)
                return (EIO);
 
-       if (sc->sc_chan.pipe)
+       if (sc->sc_chan.pipe != NULL)
                return (EBUSY);
 
         pswcode = rswcode = 0;
+       pfactor = rfactor = 1;
        enc = p->encoding;
         switch (p->encoding) {
         case AUDIO_ENCODING_SLINEAR_BE:
@@ -2155,6 +2257,13 @@ uaudio_set_params(addr, setmode, usemode, p, r)
                                pswcode = mulaw_to_slinear8;
                                rswcode = slinear8_to_mulaw;
                                enc = AUDIO_ENCODING_SLINEAR_LE;
+#if 0
+                       } else if (flags & HAS_16) {
+                               pswcode = mulaw_to_slinear16_le;
+                               pfactor = 2;
+                               /* XXX recording not handled */
+                               enc = AUDIO_ENCODING_SLINEAR_LE;
+#endif
                        } else
                                return (EINVAL);
                }
@@ -2169,6 +2278,13 @@ uaudio_set_params(addr, setmode, usemode, p, r)
                                pswcode = alaw_to_slinear8;
                                rswcode = slinear8_to_alaw;
                                enc = AUDIO_ENCODING_SLINEAR_LE;
+#if 0
+                       } else if (flags & HAS_16) {
+                               pswcode = alaw_to_slinear16_le;
+                               pfactor = 2;
+                               /* XXX recording not handled */
+                               enc = AUDIO_ENCODING_SLINEAR_LE;
+#endif
                        } else
                                return (EINVAL);
                }
@@ -2188,11 +2304,15 @@ uaudio_set_params(addr, setmode, usemode, p, r)
                    p->precision ==a1d->bBitResolution &&
                    enc == sc->sc_alts[i].encoding) {
                        if (a1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
+                               DPRINTFN(2,("uaudio_set_params: cont %d-%d\n",
+                                   UA_SAMP_LO(a1d), UA_SAMP_HI(a1d)));
                                if (UA_SAMP_LO(a1d) < p->sample_rate &&
                                    p->sample_rate < UA_SAMP_HI(a1d))
                                        goto found;
                        } else {
                                for (j = 0; j < a1d->bSamFreqType; j++) {
+                                       DPRINTFN(2,("uaudio_set_params: disc #"
+                                           "%d: %d\n", j, UA_GETSAMP(a1d, j)));
                                        /* XXX allow for some slack */
                                        if (UA_GETSAMP(a1d, j) ==
                                            p->sample_rate)
@@ -2206,6 +2326,8 @@ uaudio_set_params(addr, setmode, usemode, p, r)
  found:
         p->sw_code = pswcode;
         r->sw_code = rswcode;
+       p->factor = pfactor;
+       r->factor = rfactor;
        sc->sc_curaltidx = i;
 
        DPRINTF(("uaudio_set_params: use altidx=%d, altno=%d\n", 
index 113752e..15da30f 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: uaudioreg.h,v 1.1 1999/11/11 15:54:59 ho Exp $        */
-/*     $NetBSD: uaudioreg.h,v 1.2 1999/10/13 20:13:29 augustss Exp $   */
+/*     $OpenBSD: uaudioreg.h,v 1.2 2000/03/26 08:39:45 aaron Exp $     */
+/*     $NetBSD: uaudioreg.h,v 1.4 2000/01/16 09:32:56 augustss Exp $   */
 
 /*
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -156,14 +156,14 @@ struct usb_audio_mixer_unit {
        uByte           bDescriptorSubtype;
        uByte           bUnitId;
        uByte           bNrInPins;
-       uByte           baSourceId[255]; /* length is really bNrInPins */
+       uByte           baSourceId[255]; /* [bNrInPins] */
        /* struct usb_audio_mixer_unit_1 */
 };
 struct usb_audio_mixer_unit_1 {
        uByte           bNrChannels;
        uWord           wChannelConfig;
        uByte           iChannelNames;
-       uByte           bmControls[255];
+       uByte           bmControls[255]; /* [bNrChannels] */
        /*uByte         iMixer;*/
 };
 
@@ -174,7 +174,7 @@ struct usb_audio_selector_unit {
        uByte           bDescriptorSubtype;
        uByte           bUnitId;
        uByte           bNrInPins;
-       uByte           baSourceId[255];
+       uByte           baSourceId[255]; /* [bNrInPins] */
        /* uByte        iSelector; */
 };
 
@@ -198,7 +198,7 @@ struct usb_audio_processing_unit {
        uByte           bUnitId;
        uWord           wProcessType;
        uByte           bNrInPins;
-       uByte           baSourceId[255];
+       uByte           baSourceId[255]; /* [bNrInPins] */
        /* struct usb_audio_processing_unit_1 */
 };
 struct usb_audio_processing_unit_1{
@@ -206,8 +206,14 @@ struct usb_audio_processing_unit_1{
        uWord           wChannelConfig;
        uByte           iChannelNames;
        uByte           bControlSize;
-       uByte           bmControls[255];
-       /*uByte         iProcessing;*/
+       uByte           bmControls[255]; /* [bControlSize] */
+#define UA_PROC_ENABLE_MASK 1
+};
+
+struct usb_audio_processing_unit_updown {
+       uByte           iProcessing;
+       uByte           bNrModes;
+       uWord           waModes[255]; /* [bNrModes] */
 };
 
 /* UDESCSUB_AC_EXTENSION */
@@ -218,7 +224,7 @@ struct usb_audio_extension_unit {
        uByte           bUnitId;
        uWord           wExtensionCode;
        uByte           bNrInPins;
-       uByte           baSourceId[255];
+       uByte           baSourceId[255]; /* [bNrInPins] */
        /* struct usb_audio_extension_unit_1 */
 };
 struct usb_audio_extension_unit_1 {
@@ -226,8 +232,9 @@ struct usb_audio_extension_unit_1 {
        uWord           wChannelConfig;
        uByte           iChannelNames;
        uByte           bControlSize;
-       uByte           bmControls[255];
-#define UA_EXT_ENABLE 0
+       uByte           bmControls[255]; /* [bControlSize] */
+#define UA_EXT_ENABLE_MASK 1
+#define UA_EXT_ENABLE 1
        /*uByte         iExtension;*/
 };
 
@@ -276,3 +283,39 @@ struct usb_audio_extension_unit_1 {
 #define FORMAT_TYPE_I 1
 #define FORMAT_TYPE_II 2
 #define FORMAT_TYPE_III 3
+
+#define UA_PROC_MASK(n)  (1 << ((n)-1))
+#define PROCESS_UNDEFINED              0
+#define XX_ENABLE_CONTROL              1
+
+#define UPDOWNMIX_PROCESS              1
+#define UD_ENABLE_CONTROL              1
+#define UD_MODE_SELECT_CONTROL         2
+
+#define DOLBY_PROLOGIC_PROCESS         2
+#define DP_ENABLE_CONTROL              1
+#define DP_MODE_SELECT_CONTROL         2
+
+#define P3D_STEREO_EXTENDER_PROCESS    3
+#define P3D_ENABLE_CONTROL             1
+#define P3D_SPACIOUSNESS_CONTROL       2
+
+#define REVERBATION_PROCESS            4
+#define RV_ENABLE_CONTROL              1
+#define RV_LEVEL_CONTROL               2
+#define RV_TIME_CONTROL                        3
+#define RV_FEEDBACK_CONTROL            4
+
+#define CHORUS_PROCESS                 5
+#define CH_ENABLE_CONTROL              1
+#define CH_LEVEL_CONTROL               2
+#define CH_RATE_CONTROL                        3
+#define CH_DEPTH_CONTROL               4
+
+#define DYN_RANGE_COMP_PROCESS         6
+#define DR_ENABLE_CONTROL              1
+#define DR_COMPRESSION_RATE_CONTROL    2
+#define DR_MAXAMPL_CONTROL             3
+#define DR_THRESHOLD_CONTROL           4
+#define DR_ATTACK_TIME_CONTROL         5
+#define DR_RELEASE_TIME_CONTROL                6
index f49ca1d..a8f62e2 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: ugen.c,v 1.7 1999/11/07 21:30:19 fgsch Exp $  */
-/*     $NetBSD: ugen.c,v 1.27 1999/10/28 12:08:38 augustss Exp $       */
+/*     $OpenBSD: ugen.c,v 1.8 2000/03/26 08:39:45 aaron Exp $  */
+/*     $NetBSD: ugen.c,v 1.36 2000/03/06 20:59:17 augustss Exp $       */
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -124,24 +124,19 @@ static struct cdevsw ugen_cdevsw = {
        /* read */      ugenread,
        /* write */     ugenwrite,
        /* ioctl */     ugenioctl,
-       /* stop */      nostop,
-       /* reset */     noreset,
-       /* devtotty */  nodevtotty,
        /* poll */      ugenpoll,
        /* mmap */      nommap,
        /* strategy */  nostrategy,
        /* name */      "ugen",
-       /* parms */     noparms,
        /* maj */       UGEN_CDEV_MAJOR,
        /* dump */      nodump,
        /* psize */     nopsize,
        /* flags */     0,
-       /* maxio */     0,
        /* bmaj */      -1
 };
 #endif
 
-void ugenintr __P((usbd_request_handle reqh, usbd_private_handle addr, 
+void ugenintr __P((usbd_xfer_handle xfer, usbd_private_handle addr, 
                   usbd_status status));
 
 int ugen_do_read __P((struct ugen_softc *, int, struct uio *, int));
@@ -173,23 +168,49 @@ USB_MATCH(ugen)
 USB_ATTACH(ugen)
 {
        USB_ATTACH_START(ugen, sc, uaa);
+       usbd_device_handle udev;
        char devinfo[1024];
-       usbd_status r;
+       usbd_status err;
        int conf;
        
        usbd_devinfo(uaa->device, 0, devinfo);
        USB_ATTACH_SETUP;
        printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
 
-       sc->sc_udev = uaa->device;
-       conf = 1;               /* XXX should not hard code 1 */
-       r = ugen_set_config(sc, conf);
-       if (r != USBD_NORMAL_COMPLETION) {
+       sc->sc_udev = udev = uaa->device;
+
+       /* First set configuration index 0, the default one for ugen. */
+       err = usbd_set_config_index(udev, 0, 0);
+       if (err) {
+               printf("%s: setting configuration index 0 failed\n",
+                      USBDEVNAME(sc->sc_dev));
+               sc->sc_dying = 1;
+               USB_ATTACH_ERROR_RETURN;
+       }
+       conf = usbd_get_config_descriptor(udev)->bConfigurationValue;
+
+       /* Set up all the local state for this configuration. */
+       err = ugen_set_config(sc, conf);
+       if (err) {
                printf("%s: setting configuration %d failed\n", 
                       USBDEVNAME(sc->sc_dev), conf);
                sc->sc_dying = 1;
                USB_ATTACH_ERROR_RETURN;
        }
+
+#ifdef __FreeBSD__
+       {
+               struct int global_init_done = 0;
+               if (!global_init_done) {
+                       cdevsw_add(&ugen_cdevsw);
+                       global_init_done = 1;
+               }
+       }
+#endif
+
+       usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
+                          USBDEV(sc->sc_dev));
+
        USB_ATTACH_SUCCESS_RETURN;
 }
 
@@ -204,30 +225,30 @@ ugen_set_config(sc, configno)
        struct ugen_endpoint *sce;
        u_int8_t niface, nendpt;
        int ifaceno, endptno, endpt;
-       usbd_status r;
+       usbd_status err;
        int dir;
 
        DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n",
                    USBDEVNAME(sc->sc_dev), configno, sc));
+       /* Avoid setting the current value. */
        if (usbd_get_config_descriptor(dev)->bConfigurationValue != configno) {
-               /* Avoid setting the current value. */
-               r = usbd_set_config_no(dev, configno, 0);
-               if (r != USBD_NORMAL_COMPLETION)
-                       return (r);
+               err = usbd_set_config_no(dev, configno, 0);
+               if (err)
+                       return (err);
        }
 
-       r = usbd_interface_count(dev, &niface);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = usbd_interface_count(dev, &niface);
+       if (err)
+               return (err);
        memset(sc->sc_endpoints, 0, sizeof sc->sc_endpoints);
        for (ifaceno = 0; ifaceno < niface; ifaceno++) {
                DPRINTFN(1,("ugen_set_config: ifaceno %d\n", ifaceno));
-               r = usbd_device2interface_handle(dev, ifaceno, &iface);
-               if (r != USBD_NORMAL_COMPLETION)
-                       return (r);
-               r = usbd_endpoint_count(iface, &nendpt);
-               if (r != USBD_NORMAL_COMPLETION)
-                       return (r);
+               err = usbd_device2interface_handle(dev, ifaceno, &iface);
+               if (err)
+                       return (err);
+               err = usbd_endpoint_count(iface, &nendpt);
+               if (err)
+                       return (err);
                for (endptno = 0; endptno < nendpt; endptno++) {
                        ed = usbd_interface2endpoint_descriptor(iface,endptno);
                        endpt = ed->bEndpointAddress;
@@ -258,13 +279,14 @@ ugenopen(dev, flag, mode, p)
        usb_endpoint_descriptor_t *edesc;
        struct ugen_endpoint *sce;
        int dir, isize;
-       usbd_status r;
+       usbd_status err;
 
        USB_GET_SC_OPEN(ugen, unit, sc);
+
        DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n", 
                     flag, mode, unit, endpt));
 
-       if (sc->sc_dying)
+       if (sc == NULL || sc->sc_dying)
                return (ENXIO);
 
        if (sc->sc_is_open[endpt])
@@ -274,6 +296,7 @@ ugenopen(dev, flag, mode, p)
                sc->sc_is_open[USB_CONTROL_ENDPOINT] = 1;
                return (0);
        }
+
        /* Make sure there are pipes for all directions. */
        for (dir = OUT; dir <= IN; dir++) {
                if (flag & (dir == OUT ? FWRITE : FREAD)) {
@@ -304,11 +327,12 @@ ugenopen(dev, flag, mode, p)
                                     endpt, isize));
                         if (clalloc(&sce->q, UGEN_IBSIZE, 0) == -1)
                                 return (ENOMEM);
-                       r = usbd_open_pipe_intr(sce->iface, 
+                       err = usbd_open_pipe_intr(sce->iface, 
                                edesc->bEndpointAddress, 
                                USBD_SHORT_XFER_OK, &sce->pipeh, sce, 
-                               sce->ibuf, isize, ugenintr);
-                       if (r != USBD_NORMAL_COMPLETION) {
+                               sce->ibuf, isize, ugenintr,
+                               USBD_DEFAULT_INTERVAL);
+                       if (err) {
                                free(sce->ibuf, M_USBDEV);
                                clfree(&sce->q);
                                return (EIO);
@@ -316,10 +340,10 @@ ugenopen(dev, flag, mode, p)
                        DPRINTFN(5, ("ugenopen: interrupt open done\n"));
                        break;
                case UE_BULK:
-                       r = usbd_open_pipe(sce->iface, 
+                       err = usbd_open_pipe(sce->iface, 
                                           edesc->bEndpointAddress, 0, 
                                           &sce->pipeh);
-                       if (r != USBD_NORMAL_COMPLETION)
+                       if (err)
                                return (EIO);
                        break;
                case UE_CONTROL:
@@ -344,6 +368,7 @@ ugenclose(dev, flag, mode, p)
        int dir;
 
        USB_GET_SC(ugen, UGENUNIT(dev), sc);
+
        DPRINTFN(5, ("ugenclose: flag=%d, mode=%d, unit=%d, endpt=%d\n",
                     flag, mode, UGENUNIT(dev), endpt));
 
@@ -364,7 +389,7 @@ ugenclose(dev, flag, mode, p)
                if (!(flag & (dir == OUT ? FWRITE : FREAD)))
                        continue;
                sce = &sc->sc_endpoints[endpt][dir];
-               if (!sce || !sce->pipeh)
+               if (sce == NULL || sce->pipeh == NULL)
                        continue;
                DPRINTFN(5, ("ugenclose: endpt=%d dir=%d sce=%p\n", 
                             endpt, dir, sce));
@@ -375,7 +400,7 @@ ugenclose(dev, flag, mode, p)
                
                if (sce->ibuf) {
                        free(sce->ibuf, M_USBDEV);
-                       sce->ibuf = 0;
+                       sce->ibuf = NULL;
                        clfree(&sce->q);
                }
        }
@@ -394,8 +419,8 @@ ugen_do_read(sc, endpt, uio, flag)
        struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][IN];
        u_int32_t n, tn;
        char buf[UGEN_BBSIZE];
-       usbd_request_handle reqh;
-       usbd_status r;
+       usbd_xfer_handle xfer;
+       usbd_status err;
        int s;
        int error = 0;
        u_char buffer[UGEN_CHUNK];
@@ -460,21 +485,21 @@ ugen_do_read(sc, endpt, uio, flag)
                }
                break;
        case UE_BULK:
-               reqh = usbd_alloc_request(sc->sc_udev);
-               if (reqh == 0)
+               xfer = usbd_alloc_xfer(sc->sc_udev);
+               if (xfer == 0)
                        return (ENOMEM);
                while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) {
                        DPRINTFN(1, ("ugenread: start transfer %d bytes\n",n));
                        tn = n;
-                       r = usbd_bulk_transfer(
-                               reqh, sce->pipeh,
+                       err = usbd_bulk_transfer(
+                               xfer, sce->pipeh,
                                sce->state & UGEN_SHORT_OK ? 
                                    USBD_SHORT_XFER_OK : 0, 
                                sce->timeout, buf, &tn, "ugenrb");
-                       if (r != USBD_NORMAL_COMPLETION) {
-                               if (r == USBD_INTERRUPTED)
+                       if (err) {
+                               if (err == USBD_INTERRUPTED)
                                        error = EINTR;
-                               else if (r == USBD_TIMEOUT)
+                               else if (err == USBD_TIMEOUT)
                                        error = ETIMEDOUT;
                                else
                                        error = EIO;
@@ -485,7 +510,7 @@ ugen_do_read(sc, endpt, uio, flag)
                        if (error || tn < n)
                                break;
                }
-               usbd_free_request(reqh);
+               usbd_free_xfer(xfer);
                break;
        default:
                return (ENXIO);
@@ -504,6 +529,7 @@ ugenread(dev, uio, flag)
        int error;
 
        USB_GET_SC(ugen, UGENUNIT(dev), sc);
+
        sc->sc_refcnt++;
        error = ugen_do_read(sc, endpt, uio, flag);
        if (--sc->sc_refcnt < 0)
@@ -522,12 +548,10 @@ ugen_do_write(sc, endpt, uio, flag)
        u_int32_t n;
        int error = 0;
        char buf[UGEN_BBSIZE];
-       usbd_request_handle reqh;
-       usbd_status r;
+       usbd_xfer_handle xfer;
+       usbd_status err;
 
-#if defined(__NetBSD__) || defined(__OpenBSD__)
        DPRINTFN(5, ("ugenwrite: %d:%d\n", sc->sc_dev.dv_unit, endpt));
-#endif
 
        if (sc->sc_dying)
                return (EIO);
@@ -548,25 +572,27 @@ ugen_do_write(sc, endpt, uio, flag)
 
        switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
        case UE_BULK:
-               reqh = usbd_alloc_request(sc->sc_udev);
-               if (reqh == 0)
+               xfer = usbd_alloc_xfer(sc->sc_udev);
+               if (xfer == 0)
                        return (EIO);
                while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) {
                        error = uiomove(buf, n, uio);
                        if (error)
                                break;
                        DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n));
-                       r = usbd_bulk_transfer(reqh, sce->pipeh, 0, 
+                       err = usbd_bulk_transfer(xfer, sce->pipeh, 0, 
                                               sce->timeout, buf, &n,"ugenwb");
-                       if (r != USBD_NORMAL_COMPLETION) {
-                               if (r == USBD_INTERRUPTED)
+                       if (err) {
+                               if (err == USBD_INTERRUPTED)
                                        error = EINTR;
+                               else if (err == USBD_TIMEOUT)
+                                       error = ETIMEDOUT;
                                else
                                        error = EIO;
                                break;
                        }
                }
-               usbd_free_request(reqh);
+               usbd_free_xfer(xfer);
                break;
        default:
                return (ENXIO);
@@ -585,6 +611,7 @@ ugenwrite(dev, uio, flag)
        int error;
 
        USB_GET_SC(ugen, UGENUNIT(dev), sc);
+
        sc->sc_refcnt++;
        error = ugen_do_write(sc, endpt, uio, flag);
        if (--sc->sc_refcnt < 0)
@@ -660,12 +687,15 @@ USB_DETACH(ugen)
        /* XXX not implemented yet */
 #endif
 
+       usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
+                          USBDEV(sc->sc_dev));
+
        return (0);
 }
 
 void
-ugenintr(reqh, addr, status)
-       usbd_request_handle reqh;
+ugenintr(xfer, addr, status)
+       usbd_xfer_handle xfer;
        usbd_private_handle addr;
        usbd_status status;
 {
@@ -683,11 +713,11 @@ ugenintr(reqh, addr, status)
                return;
        }
 
-       usbd_get_request_status(reqh, 0, 0, &count, 0);
+       usbd_get_xfer_status(xfer, NULL, NULL, &count, 0);
        ibuf = sce->ibuf;
 
-       DPRINTFN(5, ("ugenintr: reqh=%p status=%d count=%d\n", 
-                    reqh, status, count));
+       DPRINTFN(5, ("ugenintr: xfer=%p status=%d count=%d\n", 
+                    xfer, status, count));
        DPRINTFN(5, ("          data = %02x %02x %02x\n",
                     ibuf[0], ibuf[1], ibuf[2]));
 
@@ -708,25 +738,25 @@ ugen_set_interface(sc, ifaceidx, altno)
 {
        usbd_interface_handle iface;
        usb_endpoint_descriptor_t *ed;
-       usbd_status r;
+       usbd_status err;
        struct ugen_endpoint *sce;
        u_int8_t niface, nendpt, endptno, endpt;
        int dir;
 
        DPRINTFN(15, ("ugen_set_interface %d %d\n", ifaceidx, altno));
 
-       r = usbd_interface_count(sc->sc_udev, &niface);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = usbd_interface_count(sc->sc_udev, &niface);
+       if (err)
+               return (err);
        if (ifaceidx < 0 || ifaceidx >= niface)
                return (USBD_INVAL);
        
-       r = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
-       r = usbd_endpoint_count(iface, &nendpt);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);
+       if (err)
+               return (err);
+       err = usbd_endpoint_count(iface, &nendpt);
+       if (err)
+               return (err);
        for (endptno = 0; endptno < nendpt; endptno++) {
                ed = usbd_interface2endpoint_descriptor(iface,endptno);
                endpt = ed->bEndpointAddress;
@@ -738,13 +768,13 @@ ugen_set_interface(sc, ifaceidx, altno)
        }
 
        /* change setting */
-       r = usbd_set_interface(iface, altno);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = usbd_set_interface(iface, altno);
+       if (err)
+               return (err);
 
-       r = usbd_endpoint_count(iface, &nendpt);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = usbd_endpoint_count(iface, &nendpt);
+       if (err)
+               return (err);
        for (endptno = 0; endptno < nendpt; endptno++) {
                ed = usbd_interface2endpoint_descriptor(iface,endptno);
                endpt = ed->bEndpointAddress;
@@ -766,7 +796,7 @@ ugen_get_cdesc(sc, index, lenp)
 {
        usb_config_descriptor_t *cdesc, *tdesc, cdescr;
        int len;
-       usbd_status r;
+       usbd_status err;
 
        if (index == USB_CURRENT_CONFIG_INDEX) {
                tdesc = usbd_get_config_descriptor(sc->sc_udev);
@@ -777,16 +807,16 @@ ugen_get_cdesc(sc, index, lenp)
                memcpy(cdesc, tdesc, len);
                DPRINTFN(5,("ugen_get_cdesc: current, len=%d\n", len));
        } else {
-               r = usbd_get_config_desc(sc->sc_udev, index, &cdescr);
-               if (r != USBD_NORMAL_COMPLETION)
+               err = usbd_get_config_desc(sc->sc_udev, index, &cdescr);
+               if (err)
                        return (0);
                len = UGETW(cdescr.wTotalLength);
                DPRINTFN(5,("ugen_get_cdesc: index=%d, len=%d\n", index, len));
                if (lenp)
                        *lenp = len;
                cdesc = malloc(len, M_TEMP, M_WAITOK);
-               r = usbd_get_config_desc_full(sc->sc_udev, index, cdesc, len);
-               if (r != USBD_NORMAL_COMPLETION) {
+               err = usbd_get_config_desc_full(sc->sc_udev, index, cdesc, len);
+               if (err) {
                        free(cdesc, M_TEMP);
                        return (0);
                }
@@ -800,11 +830,11 @@ ugen_get_alt_index(sc, ifaceidx)
        int ifaceidx;
 {
        usbd_interface_handle iface;
-       usbd_status r;
+       usbd_status err;
 
-       r = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);
-       if (r != USBD_NORMAL_COMPLETION)
-                       return (-1);
+       err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);
+       if (err)
+               return (-1);
        return (usbd_get_interface_altindex(iface));
 }
 
@@ -818,7 +848,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p)
        struct proc *p;
 {
        struct ugen_endpoint *sce;
-       usbd_status r;
+       usbd_status err;
        usbd_interface_handle iface;
        struct usb_config_desc *cd;
        usb_config_descriptor_t *cdesc;
@@ -876,32 +906,32 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p)
                return (EINVAL);
 
        switch (cmd) {
-#ifdef USB_DEBUG
+#ifdef UGEN_DEBUG
        case USB_SETDEBUG:
                ugendebug = *(int *)addr;
                break;
 #endif
        case USB_GET_CONFIG:
-               r = usbd_get_config(sc->sc_udev, &conf);
-               if (r != USBD_NORMAL_COMPLETION)
+               err = usbd_get_config(sc->sc_udev, &conf);
+               if (err)
                        return (EIO);
                *(int *)addr = conf;
                break;
        case USB_SET_CONFIG:
                if (!(flag & FWRITE))
                        return (EPERM);
-               r = ugen_set_config(sc, *(int *)addr);
-               if (r != USBD_NORMAL_COMPLETION)
+               err = ugen_set_config(sc, *(int *)addr);
+               if (err)
                        return (EIO);
                break;
        case USB_GET_ALTINTERFACE:
                ai = (struct usb_alt_interface *)addr;
-               r = usbd_device2interface_handle(sc->sc_udev, 
+               err = usbd_device2interface_handle(sc->sc_udev, 
                                                 ai->interface_index, &iface);
-               if (r != USBD_NORMAL_COMPLETION)
+               if (err)
                        return (EINVAL);
                idesc = usbd_get_interface_descriptor(iface);
-               if (!idesc)
+               if (idesc == NULL)
                        return (EIO);
                ai->alt_no = idesc->bAlternateSetting;
                break;
@@ -909,21 +939,21 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p)
                if (!(flag & FWRITE))
                        return (EPERM);
                ai = (struct usb_alt_interface *)addr;
-               r = usbd_device2interface_handle(sc->sc_udev, 
+               err = usbd_device2interface_handle(sc->sc_udev, 
                                                 ai->interface_index, &iface);
-               if (r != USBD_NORMAL_COMPLETION)
+               if (err)
                        return (EINVAL);
-               r = ugen_set_interface(sc, ai->interface_index, ai->alt_no);
-               if (r != USBD_NORMAL_COMPLETION)
+               err = ugen_set_interface(sc, ai->interface_index, ai->alt_no);
+               if (err)
                        return (EINVAL);
                break;
        case USB_GET_NO_ALT:
                ai = (struct usb_alt_interface *)addr;
                cdesc = ugen_get_cdesc(sc, ai->config_index, 0);
-               if (!cdesc)
+               if (cdesc == NULL)
                        return (EINVAL);
                idesc = usbd_find_idesc(cdesc, ai->interface_index, 0);
-               if (!idesc) {
+               if (idesc == NULL) {
                        free(cdesc, M_TEMP);
                        return (EINVAL);
                }
@@ -937,7 +967,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p)
        case USB_GET_CONFIG_DESC:
                cd = (struct usb_config_desc *)addr;
                cdesc = ugen_get_cdesc(sc, cd->config_index, 0);
-               if (!cdesc)
+               if (cdesc == NULL)
                        return (EINVAL);
                cd->desc = *cdesc;
                free(cdesc, M_TEMP);
@@ -945,7 +975,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p)
        case USB_GET_INTERFACE_DESC:
                id = (struct usb_interface_desc *)addr;
                cdesc = ugen_get_cdesc(sc, id->config_index, 0);
-               if (!cdesc)
+               if (cdesc == NULL)
                        return (EINVAL);
                if (id->config_index == USB_CURRENT_CONFIG_INDEX &&
                    id->alt_index == USB_CURRENT_ALT_INDEX)
@@ -953,7 +983,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p)
                else
                        alt = id->alt_index;
                idesc = usbd_find_idesc(cdesc, id->interface_index, alt);
-               if (!idesc) {
+               if (idesc == NULL) {
                        free(cdesc, M_TEMP);
                        return (EINVAL);
                }
@@ -963,7 +993,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p)
        case USB_GET_ENDPOINT_DESC:
                ed = (struct usb_endpoint_desc *)addr;
                cdesc = ugen_get_cdesc(sc, ed->config_index, 0);
-               if (!cdesc)
+               if (cdesc == NULL)
                        return (EINVAL);
                if (ed->config_index == USB_CURRENT_CONFIG_INDEX &&
                    ed->alt_index == USB_CURRENT_ALT_INDEX)
@@ -972,7 +1002,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p)
                        alt = ed->alt_index;
                edesc = usbd_find_edesc(cdesc, ed->interface_index, 
                                        alt, ed->endpoint_index);
-               if (!edesc) {
+               if (edesc == NULL) {
                        free(cdesc, M_TEMP);
                        return (EINVAL);
                }
@@ -1005,9 +1035,9 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p)
        }
        case USB_GET_STRING_DESC:
                si = (struct usb_string_desc *)addr;
-               r = usbd_get_string_desc(sc->sc_udev, si->string_index, 
+               err = usbd_get_string_desc(sc->sc_udev, si->string_index, 
                                         si->language_id, &si->desc);
-               if (r != USBD_NORMAL_COMPLETION)
+               if (err)
                        return (EINVAL);
                break;
        case USB_DO_REQUEST:
@@ -1017,7 +1047,7 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p)
                struct iovec iov;
                struct uio uio;
                void *ptr = 0;
-               usbd_status r;
+               usbd_status err;
                int error = 0;
 
                if (!(flag & FWRITE))
@@ -1052,9 +1082,9 @@ ugen_do_ioctl(sc, endpt, cmd, addr, flag, p)
                                        goto ret;
                        }
                }
-               r = usbd_do_request_flags(sc->sc_udev, &ur->request, 
+               err = usbd_do_request_flags(sc->sc_udev, &ur->request, 
                                          ptr, ur->flags, &ur->actlen);
-               if (r != USBD_NORMAL_COMPLETION) {
+               if (err) {
                        error = EIO;
                        goto ret;
                }
@@ -1093,6 +1123,7 @@ ugenioctl(dev, cmd, addr, flag, p)
        int error;
 
        USB_GET_SC(ugen, UGENUNIT(dev), sc);
+
        sc->sc_refcnt++;
        error = ugen_do_ioctl(sc, endpt, cmd, addr, flag, p);
        if (--sc->sc_refcnt < 0)
@@ -1121,7 +1152,7 @@ ugenpoll(dev, events, p)
                return (EINVAL);
 #ifdef DIAGNOSTIC
        if (!sce->edesc) {
-               printf("ugenwrite: no edesc\n");
+               printf("ugenpoll: no edesc\n");
                return (EIO);
        }
        if (!sce->pipeh) {
@@ -1156,5 +1187,5 @@ ugenpoll(dev, events, p)
 }
 
 #if defined(__FreeBSD__)
-DEV_DRIVER_MODULE(ugen, uhub, ugen_driver, ugen_devclass, ugen_cdevsw, usbd_driver_load, 0);
+DRIVER_MODULE(ugen, uhub, ugen_driver, ugen_devclass, usbd_driver_load, 0);
 #endif
index a92739a..14c9c56 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: uhci.c,v 1.6 1999/11/07 21:30:19 fgsch Exp $  */
-/*     $NetBSD: uhci.c,v 1.62 1999/10/23 00:21:01 augustss Exp $       */
+/*     $OpenBSD: uhci.c,v 1.7 2000/03/26 08:39:45 aaron Exp $  */
+/*     $NetBSD: uhci.c,v 1.87 2000/02/29 21:37:01 augustss Exp $       */
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
  * USB Universal Host Controller driver.
  * Handles e.g. PIIX3 and PIIX4.
  *
- * Data sheets: ftp://download.intel.com/design/intarch/datashts/29055002.pdf
- *              ftp://download.intel.com/design/intarch/datashts/29056201.pdf
  * UHCI spec: http://www.intel.com/design/usb/uhci11d.pdf
  * USB spec: http://www.usb.org/developers/data/usb11.pdf
+ * PIIXn spec: ftp://download.intel.com/design/intarch/datashts/29055002.pdf
+ *             ftp://download.intel.com/design/intarch/datashts/29056201.pdf
  */
 
 #include <sys/param.h>
 #include <sys/malloc.h>
 #if defined(__NetBSD__) || defined(__OpenBSD__)
 #include <sys/device.h>
+#include <sys/select.h>
 #elif defined(__FreeBSD__)
 #include <sys/module.h>
 #include <sys/bus.h>
+#include <machine/bus_pio.h>
+#if defined(DIAGNOSTIC) && defined(__i386)
+#include <machine/cpu.h>
+#endif
 #endif
 #include <sys/proc.h>
 #include <sys/queue.h>
-#include <sys/select.h>
 
-#if defined(__FreeBSD__)
-#include <machine/bus_pio.h>
-#endif
 #include <machine/bus.h>
 #include <machine/endian.h>
 
@@ -91,10 +92,10 @@ struct cfdriver uhci_cd = {
 };
 #endif
 
-#ifdef USB_DEBUG
+#ifdef UHCI_DEBUG
 #define DPRINTF(x)     if (uhcidebug) printf x
 #define DPRINTFN(n,x)  if (uhcidebug>(n)) printf x
-extern int uhcidebug;
+int uhcidebug = 0;
 #else
 #define DPRINTF(x)
 #define DPRINTFN(n,x)
@@ -149,6 +150,7 @@ struct uhci_pipe {
 LIST_HEAD(, uhci_intr_info) uhci_ii_free;
 
 void           uhci_busreset __P((uhci_softc_t *));
+void           uhci_shutdown __P((void *v));
 void           uhci_power __P((int, void *));
 usbd_status    uhci_run __P((uhci_softc_t *, int run));
 uhci_soft_td_t *uhci_alloc_std __P((uhci_softc_t *));
@@ -166,15 +168,15 @@ void              uhci_exit_ctl_q __P((uhci_softc_t *, uhci_soft_qh_t *));
 void           uhci_free_std_chain __P((uhci_softc_t *, 
                                         uhci_soft_td_t *, uhci_soft_td_t *));
 usbd_status    uhci_alloc_std_chain __P((struct uhci_pipe *, uhci_softc_t *,
-                                         int, int, int, usb_dma_t *, 
+                                         int, int, u_int16_t, usb_dma_t *, 
                                          uhci_soft_td_t **,
                                          uhci_soft_td_t **));
 void           uhci_timo __P((void *));
-void           uhci_waitintr __P((uhci_softc_t *, usbd_request_handle));
+void           uhci_waitintr __P((uhci_softc_t *, usbd_xfer_handle));
 void           uhci_check_intr __P((uhci_softc_t *, uhci_intr_info_t *));
 void           uhci_idone __P((uhci_intr_info_t *));
-void           uhci_abort_req __P((usbd_request_handle, usbd_status status));
-void           uhci_abort_req_end __P((void *v));
+void           uhci_abort_xfer __P((usbd_xfer_handle, usbd_status status));
+void           uhci_abort_xfer_end __P((void *v));
 void           uhci_timeout __P((void *));
 void           uhci_wakeup_ctrl __P((void *, int, int, void *, int));
 void           uhci_lock_frames __P((uhci_softc_t *));
@@ -184,53 +186,59 @@ void              uhci_add_bulk __P((uhci_softc_t *, uhci_soft_qh_t *));
 void           uhci_remove_ctrl __P((uhci_softc_t *, uhci_soft_qh_t *));
 void           uhci_remove_bulk __P((uhci_softc_t *, uhci_soft_qh_t *));
 int            uhci_str __P((usb_string_descriptor_t *, int, char *));
+
 usbd_status    uhci_setup_isoc __P((usbd_pipe_handle pipe));
-void           uhci_device_isoc_enter __P((usbd_request_handle));
+void           uhci_device_isoc_enter __P((usbd_xfer_handle));
 
-void           uhci_wakeup_cb __P((usbd_request_handle reqh));
+void           uhci_wakeup_cb __P((usbd_xfer_handle xfer));
 
 usbd_status    uhci_allocm __P((struct usbd_bus *, usb_dma_t *, u_int32_t));
 void           uhci_freem __P((struct usbd_bus *, usb_dma_t *));
 
-usbd_status    uhci_device_ctrl_transfer __P((usbd_request_handle));
-usbd_status    uhci_device_ctrl_start __P((usbd_request_handle));
-void           uhci_device_ctrl_abort __P((usbd_request_handle));
+usbd_xfer_handle uhci_allocx __P((struct usbd_bus *));
+void           uhci_freex __P((struct usbd_bus *, usbd_xfer_handle));
+
+usbd_status    uhci_device_ctrl_transfer __P((usbd_xfer_handle));
+usbd_status    uhci_device_ctrl_start __P((usbd_xfer_handle));
+void           uhci_device_ctrl_abort __P((usbd_xfer_handle));
 void           uhci_device_ctrl_close __P((usbd_pipe_handle));
-void           uhci_device_ctrl_done  __P((usbd_request_handle));
+void           uhci_device_ctrl_done  __P((usbd_xfer_handle));
 
-usbd_status    uhci_device_intr_transfer __P((usbd_request_handle));
-usbd_status    uhci_device_intr_start __P((usbd_request_handle));
-void           uhci_device_intr_abort __P((usbd_request_handle));
+usbd_status    uhci_device_intr_transfer __P((usbd_xfer_handle));
+usbd_status    uhci_device_intr_start __P((usbd_xfer_handle));
+void           uhci_device_intr_abort __P((usbd_xfer_handle));
 void           uhci_device_intr_close __P((usbd_pipe_handle));
-void           uhci_device_intr_done  __P((usbd_request_handle));
+void           uhci_device_intr_done  __P((usbd_xfer_handle));
 
-usbd_status    uhci_device_bulk_transfer __P((usbd_request_handle));
-usbd_status    uhci_device_bulk_start __P((usbd_request_handle));
-void           uhci_device_bulk_abort __P((usbd_request_handle));
+usbd_status    uhci_device_bulk_transfer __P((usbd_xfer_handle));
+usbd_status    uhci_device_bulk_start __P((usbd_xfer_handle));
+void           uhci_device_bulk_abort __P((usbd_xfer_handle));
 void           uhci_device_bulk_close __P((usbd_pipe_handle));
-void           uhci_device_bulk_done  __P((usbd_request_handle));
+void           uhci_device_bulk_done  __P((usbd_xfer_handle));
 
-usbd_status    uhci_device_isoc_transfer __P((usbd_request_handle));
-usbd_status    uhci_device_isoc_start __P((usbd_request_handle));
-void           uhci_device_isoc_abort __P((usbd_request_handle));
+usbd_status    uhci_device_isoc_transfer __P((usbd_xfer_handle));
+usbd_status    uhci_device_isoc_start __P((usbd_xfer_handle));
+void           uhci_device_isoc_abort __P((usbd_xfer_handle));
 void           uhci_device_isoc_close __P((usbd_pipe_handle));
-void           uhci_device_isoc_done  __P((usbd_request_handle));
+void           uhci_device_isoc_done  __P((usbd_xfer_handle));
 
-usbd_status    uhci_root_ctrl_transfer __P((usbd_request_handle));
-usbd_status    uhci_root_ctrl_start __P((usbd_request_handle));
-void           uhci_root_ctrl_abort __P((usbd_request_handle));
+usbd_status    uhci_root_ctrl_transfer __P((usbd_xfer_handle));
+usbd_status    uhci_root_ctrl_start __P((usbd_xfer_handle));
+void           uhci_root_ctrl_abort __P((usbd_xfer_handle));
 void           uhci_root_ctrl_close __P((usbd_pipe_handle));
+void           uhci_root_ctrl_done __P((usbd_xfer_handle));
 
-usbd_status    uhci_root_intr_transfer __P((usbd_request_handle));
-usbd_status    uhci_root_intr_start __P((usbd_request_handle));
-void           uhci_root_intr_abort __P((usbd_request_handle));
+usbd_status    uhci_root_intr_transfer __P((usbd_xfer_handle));
+usbd_status    uhci_root_intr_start __P((usbd_xfer_handle));
+void           uhci_root_intr_abort __P((usbd_xfer_handle));
 void           uhci_root_intr_close __P((usbd_pipe_handle));
-void           uhci_root_intr_done  __P((usbd_request_handle));
+void           uhci_root_intr_done  __P((usbd_xfer_handle));
 
 usbd_status    uhci_open __P((usbd_pipe_handle));
 void           uhci_poll __P((struct usbd_bus *));
+void           uhci_softintr __P((struct usbd_bus *));
 
-usbd_status    uhci_device_request __P((usbd_request_handle reqh));
+usbd_status    uhci_device_request __P((usbd_xfer_handle xfer));
 
 void           uhci_add_intr __P((uhci_softc_t *, int, uhci_soft_qh_t *));
 void           uhci_remove_intr __P((uhci_softc_t *, int, uhci_soft_qh_t *));
@@ -242,12 +250,14 @@ void              uhci_noop __P((usbd_pipe_handle pipe));
 
 #ifdef UHCI_DEBUG
 static void    uhci_dumpregs __P((uhci_softc_t *));
-void           uhci_dump_tds __P((uhci_soft_td_t *));
+void           uhci_dump_qhs __P((uhci_soft_qh_t *));
 void           uhci_dump_qh __P((uhci_soft_qh_t *));
 void           uhci_dump __P((void));
+void           uhci_dump_tds __P((uhci_soft_td_t *));
 void           uhci_dump_td __P((uhci_soft_td_t *));
 #endif
 
+#define UWRITE1(sc, r, x) bus_space_write_2((sc)->iot, (sc)->ioh, (r), (x))
 #define UWRITE2(sc, r, x) bus_space_write_2((sc)->iot, (sc)->ioh, (r), (x))
 #define UWRITE4(sc, r, x) bus_space_write_4((sc)->iot, (sc)->ioh, (r), (x))
 #define UREAD1(sc, r) bus_space_read_1((sc)->iot, (sc)->ioh, (r))
@@ -265,9 +275,12 @@ void               uhci_dump_td __P((uhci_soft_td_t *));
 
 struct usbd_bus_methods uhci_bus_methods = {
        uhci_open,
+       uhci_softintr,
        uhci_poll,
        uhci_allocm,
        uhci_freem,
+       uhci_allocx,
+       uhci_freex,
 };
 
 struct usbd_pipe_methods uhci_root_ctrl_methods = {    
@@ -276,7 +289,7 @@ struct usbd_pipe_methods uhci_root_ctrl_methods = {
        uhci_root_ctrl_abort,
        uhci_root_ctrl_close,
        uhci_noop,
-       0,
+       uhci_root_ctrl_done,
 };
 
 struct usbd_pipe_methods uhci_root_intr_methods = {    
@@ -337,14 +350,14 @@ usbd_status
 uhci_init(sc)
        uhci_softc_t *sc;
 {
-       usbd_status r;
+       usbd_status err;
        int i, j;
        uhci_soft_qh_t *csqh, *bsqh, *sqh;
        uhci_soft_td_t *std;
 
        DPRINTFN(1,("uhci_init: start\n"));
 
-#if defined(UHCI_DEBUG)
+#ifdef UHCI_DEBUG
        if (uhcidebug > 2)
                uhci_dumpregs(sc);
 #endif
@@ -355,18 +368,18 @@ uhci_init(sc)
        uhci_busreset(sc);
 
        /* Allocate and initialize real frame array. */
-       r = usb_allocmem(&sc->sc_bus, 
+       err = usb_allocmem(&sc->sc_bus, 
                         UHCI_FRAMELIST_COUNT * sizeof(uhci_physaddr_t),
                         UHCI_FRAMELIST_ALIGN, &sc->sc_dma);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       if (err)
+               return (err);
        sc->sc_pframes = KERNADDR(&sc->sc_dma);
        UWRITE2(sc, UHCI_FRNUM, 0);             /* set frame number to 0 */
        UWRITE4(sc, UHCI_FLBASEADDR, DMAADDR(&sc->sc_dma)); /* set frame list*/
 
        /* Allocate the dummy QH where bulk traffic will be queued. */
        bsqh = uhci_alloc_sqh(sc);
-       if (!bsqh)
+       if (bsqh == NULL)
                return (USBD_NOMEM);
        bsqh->qh.qh_hlink = LE(UHCI_PTR_T);     /* end of QH chain */
        bsqh->qh.qh_elink = LE(UHCI_PTR_T);
@@ -374,7 +387,7 @@ uhci_init(sc)
 
        /* Allocate the dummy QH where control traffic will be queued. */
        csqh = uhci_alloc_sqh(sc);
-       if (!csqh)
+       if (csqh == NULL)
                return (USBD_NOMEM);
        csqh->hlink = bsqh;
        csqh->qh.qh_hlink = LE(bsqh->physaddr | UHCI_PTR_Q);
@@ -389,7 +402,7 @@ uhci_init(sc)
        for(i = 0; i < UHCI_VFRAMELIST_COUNT; i++) {
                std = uhci_alloc_std(sc);
                sqh = uhci_alloc_sqh(sc);
-               if (!std || !sqh)
+               if (std == NULL || sqh == NULL)
                        return (USBD_NOMEM);
                std->link.sqh = sqh;
                std->td.td_link = LE(sqh->physaddr | UHCI_PTR_Q);
@@ -412,6 +425,8 @@ uhci_init(sc)
 
        LIST_INIT(&sc->sc_intrhead);
 
+       SIMPLEQ_INIT(&sc->sc_free_xfers);
+
        /* Set up the bus struct. */
        sc->sc_bus.methods = &uhci_bus_methods;
        sc->sc_bus.pipe_size = sizeof(struct uhci_pipe);
@@ -419,13 +434,18 @@ uhci_init(sc)
        sc->sc_suspend = PWR_RESUME;
        sc->sc_powerhook = powerhook_establish(uhci_power, sc);
 
+       sc->sc_shutdownhook = shutdownhook_establish(uhci_shutdown, sc);
+
        DPRINTFN(1,("uhci_init: enabling\n"));
        UWRITE2(sc, UHCI_INTR, UHCI_INTR_TOCRCIE | UHCI_INTR_RIE | 
                UHCI_INTR_IOCE | UHCI_INTR_SPIE);       /* enable interrupts */
 
+       UHCICMD(sc, UHCI_CMD_MAXP); /* Assume 64 byte packets at frame end */
+
        return (uhci_run(sc, 1));               /* and here we go... */
 }
 
+#if defined(__NetBSD__) || defined(__OpenBSD__)
 int
 uhci_activate(self, act)
        device_ptr_t self;
@@ -452,6 +472,7 @@ uhci_detach(sc, flags)
        struct uhci_softc *sc;
        int flags;
 {
+       usbd_xfer_handle xfer;
        int rv = 0;
 
        if (sc->sc_child != NULL)
@@ -461,10 +482,22 @@ uhci_detach(sc, flags)
                return (rv);
 
        powerhook_disestablish(sc->sc_powerhook);
-       /* free data structures XXX */
+       shutdownhook_disestablish(sc->sc_shutdownhook);
+
+       /* Free all xfers associated with this HC. */
+       for (;;) {
+               xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers);
+               if (xfer == NULL)
+                       break;
+               SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, xfer, next);
+               free(xfer, M_USB);
+       }
+
+       /* XXX free other data structures XXX */
 
        return (rv);
 }
+#endif
 
 usbd_status
 uhci_allocm(bus, dma, size)
@@ -472,11 +505,8 @@ uhci_allocm(bus, dma, size)
        usb_dma_t *dma;
        u_int32_t size;
 {
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-       struct uhci_softc *sc = (struct uhci_softc *)bus;
-#endif
-
-       return (usb_allocmem(&sc->sc_bus, size, 0, dma));
+       return (usb_allocmem(&((struct uhci_softc *)bus)->sc_bus, size, 0,
+                            dma));
 }
 
 void
@@ -484,14 +514,49 @@ uhci_freem(bus, dma)
        struct usbd_bus *bus;
        usb_dma_t *dma;
 {
-#if defined(__NetBSD__) || defined(__OpenBSD__)
+       usb_freemem(&((struct uhci_softc *)bus)->sc_bus, dma);
+}
+
+usbd_xfer_handle
+uhci_allocx(bus)
+       struct usbd_bus *bus;
+{
        struct uhci_softc *sc = (struct uhci_softc *)bus;
-#endif
+       usbd_xfer_handle xfer;
 
-       usb_freemem(&sc->sc_bus, dma);
+       xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers);
+       if (xfer != NULL)
+               SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, xfer, next);
+       else
+               xfer = malloc(sizeof(*xfer), M_USB, M_NOWAIT);
+       if (xfer != NULL)
+               memset(xfer, 0, sizeof *xfer);
+       return (xfer);
+}
+
+void
+uhci_freex(bus, xfer)
+       struct usbd_bus *bus;
+       usbd_xfer_handle xfer;
+{
+       struct uhci_softc *sc = (struct uhci_softc *)bus;
+
+       SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next);
+}
+
+/*
+ * Shut down the controller when the system is going down.
+ */
+void
+uhci_shutdown(v)
+       void *v;
+{
+       uhci_softc_t *sc = v;
+
+       DPRINTF(("uhci_shutdown: stopping the HC\n"));
+       uhci_run(sc, 0); /* stop the controller */
 }
 
-#if defined(__NetBSD__) || defined(__OpenBSD__)
 /*
  * Handle suspend/resume.
  *
@@ -515,26 +580,26 @@ uhci_power(why, v)
                 sc, why, sc->sc_suspend, cmd));
 
        if (why != PWR_RESUME) {
-#if defined(UHCI_DEBUG)
+#ifdef UHCI_DEBUG
                if (uhcidebug > 2)
                        uhci_dumpregs(sc);
 #endif
-               if (sc->sc_has_timo)
+               if (sc->sc_has_timo != NULL)
                        usb_untimeout(uhci_timo, sc->sc_has_timo, 
                                      sc->sc_has_timo->timo_handle);
                sc->sc_bus.use_polling++;
                uhci_run(sc, 0); /* stop the controller */
+
+               /* save some state if BIOS doesn't */
+               sc->sc_saved_frnum = UREAD2(sc, UHCI_FRNUM);
+               sc->sc_saved_sof = UREAD1(sc, UHCI_SOF);
+
                UHCICMD(sc, cmd | UHCI_CMD_EGSM); /* enter global suspend */
                usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT);
                sc->sc_suspend = why;
                sc->sc_bus.use_polling--;
                DPRINTF(("uhci_power: cmd=0x%x\n", UREAD2(sc, UHCI_CMD)));
        } else {
-               /*
-                * XXX We should really do much more here in case the
-                * controller registers have been lost and BIOS has
-                * not restored them.
-                */
 #ifdef DIAGNOSTIC
                if (sc->sc_suspend == PWR_RESUME)
                        printf("uhci_power: weird, resume without suspend.\n");
@@ -543,6 +608,12 @@ uhci_power(why, v)
                sc->sc_suspend = why;
                if (cmd & UHCI_CMD_RS)
                        uhci_run(sc, 0); /* in case BIOS has started it */
+
+               /* restore saved state */
+               UWRITE4(sc, UHCI_FLBASEADDR, DMAADDR(&sc->sc_dma));
+               UWRITE2(sc, UHCI_FRNUM, sc->sc_saved_frnum);
+               UWRITE1(sc, UHCI_SOF, sc->sc_saved_sof);
+
                UHCICMD(sc, cmd | UHCI_CMD_FGR); /* force global resume */
                usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY);
                UHCICMD(sc, cmd & ~UHCI_CMD_EGSM); /* back to normal */
@@ -551,17 +622,16 @@ uhci_power(why, v)
                uhci_run(sc, 1); /* and start traffic again */
                usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY);
                sc->sc_bus.use_polling--;
-               if (sc->sc_has_timo)
+               if (sc->sc_has_timo != NULL)
                        usb_timeout(uhci_timo, sc->sc_has_timo, 
                                    sc->sc_ival, sc->sc_has_timo->timo_handle);
-#if defined(UHCI_DEBUG)
+#ifdef UHCI_DEBUG
                if (uhcidebug > 2)
                        uhci_dumpregs(sc);
 #endif
        }
        splx(s);
 }
-#endif /* defined(__NetBSD__) || defined(__OpenBSD__) */
 
 #ifdef UHCI_DEBUG
 static void
@@ -609,14 +679,13 @@ uhci_dump_td(p)
 }
 
 void
-uhci_dump_qh(p)
-       uhci_soft_qh_t *p;
+uhci_dump_qh(sqh)
+       uhci_soft_qh_t *sqh;
 {
-       DPRINTFN(-1,("QH(%p) at %08x: hlink=%08x elink=%08x\n", p, 
-                   (int)p->physaddr, LE(p->qh.qh_hlink), LE(p->qh.qh_elink)));
+       DPRINTFN(-1,("QH(%p) at %08x: hlink=%08x elink=%08x\n", sqh,
+           (int)sqh->physaddr, LE(sqh->qh.qh_hlink), LE(sqh->qh.qh_elink)));
 }
 
-
 #if 0
 void
 uhci_dump()
@@ -630,14 +699,54 @@ uhci_dump()
 }
 #endif
 
+void
+uhci_dump_qhs(sqh)
+       uhci_soft_qh_t *sqh;
+{
+       uhci_dump_qh(sqh);
+
+       /* uhci_dump_sqh displays all the QHs and TDs from the given QH onwards
+        * Traverses sideways first, then down.
+        *
+        * QH1
+        * QH2
+        * No QH
+        * TD2.1
+        * TD2.2
+        * TD1.1
+        * etc.
+        *
+        * TD2.x being the TDs queued at QH2 and QH1 being referenced from QH1.
+        */
+
+       if (sqh->hlink != NULL && !(sqh->qh.qh_hlink & UHCI_PTR_T))
+               uhci_dump_qhs(sqh->hlink);
+       else
+               DPRINTF(("No QH\n"));
+
+       if (sqh->elink != NULL && !(sqh->qh.qh_elink & UHCI_PTR_T))
+               uhci_dump_tds(sqh->elink);
+       else
+               DPRINTF(("No TD\n"));
+}
+
 void
 uhci_dump_tds(std)
        uhci_soft_td_t *std;
 {
-       uhci_soft_td_t *p;
+       uhci_soft_td_t *td;
+
+       for(td = std; td != NULL; td = td->link.std) {
+               uhci_dump_td(td);
 
-       for(p = std; p; p = p->link.std)
-               uhci_dump_td(p);
+               /* Check whether the link pointer in this TD marks
+                * the link pointer as end of queue. This avoids
+                * printing the free list in case the queue/TD has
+                * already been moved there (seatbelt).
+                */
+               if (td->td.td_link & UHCI_PTR_T || td->td.td_link == 0)
+                       break;
+       }
 }
 #endif
 
@@ -649,17 +758,17 @@ void
 uhci_timo(addr)
        void *addr;
 {
-       usbd_request_handle reqh = addr;
-       usbd_pipe_handle pipe = reqh->pipe;
+       usbd_xfer_handle xfer = addr;
+       usbd_pipe_handle pipe = xfer->pipe;
        uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus;
        int s;
        u_char *p;
 
-       DPRINTFN(15, ("uhci_timo\n"));
+       DPRINTFN(20, ("uhci_timo\n"));
 
-       usb_timeout(uhci_timo, reqh, sc->sc_ival, reqh->timo_handle);
+       usb_timeout(uhci_timo, xfer, sc->sc_ival, xfer->timo_handle);
 
-       p = KERNADDR(&reqh->dmabuf);
+       p = KERNADDR(&xfer->dmabuf);
        p[0] = 0;
        if (UREAD2(sc, UHCI_PORTSC1) & (UHCI_PORTSC_CSC|UHCI_PORTSC_OCIC))
                p[0] |= 1<<1;
@@ -669,19 +778,25 @@ uhci_timo(addr)
                /* No change, try again in a while */
                return;
 
-       reqh->actlen = 1;
-       reqh->status = USBD_NORMAL_COMPLETION;
+       xfer->actlen = 1;
+       xfer->status = USBD_NORMAL_COMPLETION;
        s = splusb();
-       reqh->hcpriv = 0;
-       reqh->device->bus->intr_context++;
-       usb_transfer_complete(reqh);
-       reqh->device->bus->intr_context--;
+       xfer->hcpriv = 0;
+       xfer->device->bus->intr_context++;
+       usb_transfer_complete(xfer);
+       xfer->device->bus->intr_context--;
        splx(s);
 }
 
 void
-uhci_root_intr_done(reqh)
-       usbd_request_handle reqh;
+uhci_root_intr_done(xfer)
+       usbd_xfer_handle xfer;
+{
+}
+
+void
+uhci_root_ctrl_done(xfer)
+       usbd_xfer_handle xfer;
 {
 }
 
@@ -691,7 +806,8 @@ uhci_lock_frames(sc)
        uhci_softc_t *sc;
 {
        int s = splusb();
-       while (sc->sc_vflock) {
+
+       while (sc->sc_vflock & UHCI_HAS_LOCK) {
                sc->sc_vflock |= UHCI_WANT_LOCK;
                tsleep(&sc->sc_vflock, PRIBIO, "uhcqhl", 0);
        }
@@ -704,6 +820,7 @@ uhci_unlock_frames(sc)
        uhci_softc_t *sc;
 {
        int s = splusb();
+
        sc->sc_vflock &= ~UHCI_HAS_LOCK;
        if (sc->sc_vflock & UHCI_WANT_LOCK)
                wakeup(&sc->sc_vflock);
@@ -838,9 +955,8 @@ uhci_intr(arg)
        uhci_softc_t *sc = arg;
        int status;
        int ack;
-       uhci_intr_info_t *ii;
 
-#if defined(UHCI_DEBUG)
+#ifdef UHCI_DEBUG
        if (uhcidebug > 15) {
                DPRINTF(("%s: uhci_intr\n", USBDEVNAME(sc->sc_bus.bdev)));
                uhci_dumpregs(sc);
@@ -867,17 +983,18 @@ uhci_intr(arg)
        }
        if (status & UHCI_STS_HSE) {
                ack |= UHCI_STS_HSE;
-               printf("%s: host controller process error\n", 
-                      USBDEVNAME(sc->sc_bus.bdev));
+               printf("%s: host system error\n", USBDEVNAME(sc->sc_bus.bdev));
        }
        if (status & UHCI_STS_HCPE) {
                ack |= UHCI_STS_HCPE;
-               printf("%s: host system error\n", USBDEVNAME(sc->sc_bus.bdev));
+               printf("%s: host controller process error\n",
+                      USBDEVNAME(sc->sc_bus.bdev));
        }
        if (status & UHCI_STS_HCH) {
                /* no acknowledge needed */
                printf("%s: host controller halted\n", 
                       USBDEVNAME(sc->sc_bus.bdev));
+               sc->sc_dying = 1;
        }
 
        if (ack)        /* acknowledge the ints */
@@ -885,8 +1002,24 @@ uhci_intr(arg)
        else    /* nothing to acknowledge */
                return (0);
 
-       sc->sc_bus.intr_context++;
        sc->sc_bus.no_intrs++;
+       usb_schedsoftintr(&sc->sc_bus);
+
+       DPRINTFN(10, ("%s: uhci_intr: exit\n", USBDEVNAME(sc->sc_bus.bdev)));
+
+       return (1);
+}
+
+void
+uhci_softintr(bus)
+       struct usbd_bus *bus;
+{
+       uhci_softc_t *sc = (uhci_softc_t *)bus;
+       uhci_intr_info_t *ii;
+
+       DPRINTFN(10,("%s: uhci_softintr\n", USBDEVNAME(sc->sc_bus.bdev)));
+
+       sc->sc_bus.intr_context++;
 
        /*
         * Interrupts on UHCI really suck.  When the host controller
@@ -902,11 +1035,7 @@ uhci_intr(arg)
        for (ii = LIST_FIRST(&sc->sc_intrhead); ii; ii = LIST_NEXT(ii, list))
                uhci_check_intr(sc, ii);
 
-       DPRINTFN(10, ("uhci_intr: exit\n"));
-
        sc->sc_bus.intr_context--;
-
-       return (1);
 }
 
 /* Check for an interrupt. */
@@ -920,16 +1049,16 @@ uhci_check_intr(sc, ii)
 
        DPRINTFN(15, ("uhci_check_intr: ii=%p\n", ii));
 #ifdef DIAGNOSTIC
-       if (!ii) {
+       if (ii == NULL) {
                printf("uhci_check_intr: no ii? %p\n", ii);
                return;
        }
 #endif
-       if (!ii->stdstart)
+       if (ii->stdstart == NULL)
                return;
        lstd = ii->stdend;
 #ifdef DIAGNOSTIC
-       if (!lstd) {
+       if (lstd == NULL) {
                printf("uhci_check_intr: std==0\n");
                return;
        }
@@ -943,9 +1072,16 @@ uhci_check_intr(sc, ii)
                DPRINTFN(15, ("uhci_check_intr: active ii=%p\n", ii));
                for (std = ii->stdstart; std != lstd; std = std->link.std) {
                        status = LE(std->td.td_status);
-                       if ((status & UHCI_TD_STALLED) ||
-                            (status & (UHCI_TD_SPD | UHCI_TD_ACTIVE)) == 
-                            UHCI_TD_SPD)
+                       /* If there's an active TD the xfer isn't done. */
+                       if (status & UHCI_TD_ACTIVE)
+                               break;
+                       /* Any kind of error makes the xfer done. */
+                       if (status & UHCI_TD_STALLED)
+                               goto done;
+                       /* We want short packets, and it is short: it's done */
+                       if ((status & UHCI_TD_SPD) &&
+                           UHCI_TD_GET_ACTLEN(status) <
+                           UHCI_TD_GET_MAXLEN(LE(std->td.td_token)))
                                goto done;
                }
                DPRINTFN(15, ("uhci_check_intr: ii=%p std=%p still active\n",
@@ -953,6 +1089,7 @@ uhci_check_intr(sc, ii)
                return;
        }
  done:
+       DPRINTFN(15, ("uhci_check_intr: ii=%p done\n", ii));
        usb_untimeout(uhci_timeout, ii, ii->timeout_handle);
        uhci_idone(ii);
 }
@@ -962,10 +1099,10 @@ void
 uhci_idone(ii)
        uhci_intr_info_t *ii;
 {
-       usbd_request_handle reqh = ii->reqh;
-       struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
+       usbd_xfer_handle xfer = ii->xfer;
+       struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
        uhci_soft_td_t *std;
-       u_int32_t status;
+       u_int32_t status = 0, nstatus;
        int actlen;
 
 #ifdef DIAGNOSTIC
@@ -981,22 +1118,22 @@ uhci_idone(ii)
        }
 #endif
 
-       if (reqh->status == USBD_CANCELLED ||
-           reqh->status == USBD_TIMEOUT) {
-               DPRINTF(("uhci_idone: aborted reqh=%p\n", reqh));
+       if (xfer->status == USBD_CANCELLED ||
+           xfer->status == USBD_TIMEOUT) {
+               DPRINTF(("uhci_idone: aborted xfer=%p\n", xfer));
                return;
        }
 
-       if (reqh->nframes) {
+       if (xfer->nframes != 0) {
                /* Isoc transfer, do things differently. */
                uhci_soft_td_t **stds = upipe->u.iso.stds;
                int i, n, nframes;
 
                DPRINTFN(5,("uhci_idone: ii=%p isoc ready\n", ii));
 
-               nframes = reqh->nframes;
+               nframes = xfer->nframes;
                actlen = 0;
-               n = reqh->hcprivint;
+               n = xfer->hcprivint;
                for (i = 0; i < nframes; i++) {
                        std = stds[n];
 #ifdef UHCI_DEBUG
@@ -1011,15 +1148,16 @@ uhci_idone(ii)
                        actlen += UHCI_TD_GET_ACTLEN(status);
                }
                upipe->u.iso.inuse -= nframes;
-               reqh->actlen = actlen;
-               reqh->status = USBD_NORMAL_COMPLETION;
-               reqh->hcpriv = ii;
-               usb_transfer_complete(reqh);
+               xfer->actlen = actlen;
+               xfer->status = USBD_NORMAL_COMPLETION;
+               xfer->hcpriv = ii;
+               usb_transfer_complete(xfer);
                return;
        }
 
 #ifdef UHCI_DEBUG
-       DPRINTFN(10, ("uhci_idone: ii=%p ready\n", ii));
+       DPRINTFN(10, ("uhci_idone: ii=%p, xfer=%p, pipe=%p ready\n",
+                     ii, xfer, upipe));
        if (uhcidebug > 10)
                uhci_dump_tds(ii->stdstart);
 #endif
@@ -1027,40 +1165,41 @@ uhci_idone(ii)
        /* The transfer is done, compute actual length and status. */
        /* XXX Is this correct for control xfers? */
        actlen = 0;
-       for (std = ii->stdstart; std; std = std->link.std) {
-               status = LE(std->td.td_status);
-               if (status & UHCI_TD_ACTIVE)
+       for (std = ii->stdstart; std != NULL; std = std->link.std) {
+               nstatus = LE(std->td.td_status);
+               if (nstatus & UHCI_TD_ACTIVE)
                        break;
-               if (UHCI_TD_GET_PID(LE(std->td.td_token)) != 
-                   UHCI_TD_PID_SETUP)
+
+               status = nstatus;
+               if (UHCI_TD_GET_PID(LE(std->td.td_token)) != UHCI_TD_PID_SETUP)
                        actlen += UHCI_TD_GET_ACTLEN(status);
        }
        /* If there are left over TDs we need to update the toggle. */
-       if (std)
+       if (std != NULL)
                upipe->nexttoggle = UHCI_TD_GET_DT(LE(std->td.td_token));
 
        status &= UHCI_TD_ERROR;
        DPRINTFN(10, ("uhci_check_intr: actlen=%d, status=0x%x\n", 
                      actlen, status));
-       reqh->actlen = actlen;
+       xfer->actlen = actlen;
        if (status != 0) {
-               DPRINTFN(-1+((status&UHCI_TD_STALLED)!=0),
+               DPRINTFN((status == UHCI_TD_STALLED)*10,
                         ("uhci_idone: error, addr=%d, endpt=0x%02x, "
                          "status 0x%b\n",
-                         reqh->pipe->device->address,
-                         reqh->pipe->endpoint->edesc->bEndpointAddress,
+                         xfer->pipe->device->address,
+                         xfer->pipe->endpoint->edesc->bEndpointAddress,
                          (int)status, 
                          "\20\22BITSTUFF\23CRCTO\24NAK\25BABBLE\26DBUFFER\27"
                          "STALLED\30ACTIVE"));
                if (status == UHCI_TD_STALLED)
-                       reqh->status = USBD_STALLED;
+                       xfer->status = USBD_STALLED;
                else
-                       reqh->status = USBD_IOERROR; /* more info XXX */
+                       xfer->status = USBD_IOERROR; /* more info XXX */
        } else {
-               reqh->status = USBD_NORMAL_COMPLETION;
+               xfer->status = USBD_NORMAL_COMPLETION;
        }
-       reqh->hcpriv = ii;
-       usb_transfer_complete(reqh);
+       xfer->hcpriv = ii;
+       usb_transfer_complete(xfer);
 }
 
 /*
@@ -1074,9 +1213,14 @@ uhci_timeout(addr)
 
        DPRINTF(("uhci_timeout: ii=%p\n", ii));
 
-       ii->reqh->device->bus->intr_context++;
-       uhci_abort_req(ii->reqh, USBD_TIMEOUT);
-       ii->reqh->device->bus->intr_context--;
+#ifdef UHCI_DEBUG
+       if (uhcidebug > 10)
+               uhci_dump_tds(ii->stdstart);
+#endif
+
+       ii->xfer->device->bus->intr_context++;
+       uhci_abort_xfer(ii->xfer, USBD_TIMEOUT);
+       ii->xfer->device->bus->intr_context--;
 }
 
 /*
@@ -1086,22 +1230,22 @@ uhci_timeout(addr)
  * Only used during boot when interrupts are not enabled yet.
  */
 void
-uhci_waitintr(sc, reqh)
+uhci_waitintr(sc, xfer)
        uhci_softc_t *sc;
-       usbd_request_handle reqh;
+       usbd_xfer_handle xfer;
 {
-       int timo = reqh->timeout;
+       int timo = xfer->timeout;
        uhci_intr_info_t *ii;
 
        DPRINTFN(10,("uhci_waitintr: timeout = %dms\n", timo));
 
-       reqh->status = USBD_IN_PROGRESS;
+       xfer->status = USBD_IN_PROGRESS;
        for (; timo >= 0; timo--) {
                usb_delay_ms(&sc->sc_bus, 1);
                DPRINTFN(20,("uhci_waitintr: 0x%04x\n", UREAD2(sc, UHCI_STS)));
                if (UREAD2(sc, UHCI_STS) & UHCI_STS_USBINT) {
                        uhci_intr(sc);
-                       if (reqh->status != USBD_IN_PROGRESS)
+                       if (xfer->status != USBD_IN_PROGRESS)
                                return;
                }
        }
@@ -1109,11 +1253,11 @@ uhci_waitintr(sc, reqh)
        /* Timeout */
        DPRINTF(("uhci_waitintr: timeout\n"));
        for (ii = LIST_FIRST(&sc->sc_intrhead);
-            ii && ii->reqh != reqh
+            ii != NULL && ii->xfer != xfer
             ii = LIST_NEXT(ii, list))
                ;
 #ifdef DIAGNOSTIC
-       if (!ii)
+       if (ii == NULL)
                panic("uhci_waitintr: lost intr_info\n");
 #endif
        uhci_idone(ii);
@@ -1154,11 +1298,17 @@ uhci_run(sc, run)
        int run;
 {
        int s, n, running;
+       u_int16_t cmd;
 
        run = run != 0;
        s = splusb();
        DPRINTF(("uhci_run: setting run=%d\n", run));
-       UHCICMD(sc, run ? UHCI_CMD_RS : 0);
+       cmd = UREAD2(sc, UHCI_CMD);
+       if (run)
+               cmd |= UHCI_CMD_RS;
+       else
+               cmd &= ~UHCI_CMD_RS;
+       UHCICMD(sc, cmd);
        for(n = 0; n < 10; n++) {
                running = !(UREAD2(sc, UHCI_STS) & UHCI_STS_HCH);
                /* return when we've entered the state we want */
@@ -1191,15 +1341,15 @@ uhci_alloc_std(sc)
        uhci_softc_t *sc;
 {
        uhci_soft_td_t *std;
-       usbd_status r;
+       usbd_status err;
        int i, offs;
        usb_dma_t dma;
 
-       if (!sc->sc_freetds) {
+       if (sc->sc_freetds == NULL) {
                DPRINTFN(2,("uhci_alloc_std: allocating chunk\n"));
-               r = usb_allocmem(&sc->sc_bus, UHCI_STD_SIZE * UHCI_STD_CHUNK,
+               err = usb_allocmem(&sc->sc_bus, UHCI_STD_SIZE * UHCI_STD_CHUNK,
                                 UHCI_TD_ALIGN, &dma);
-               if (r != USBD_NORMAL_COMPLETION)
+               if (err)
                        return (0);
                for(i = 0; i < UHCI_STD_CHUNK; i++) {
                        offs = i * UHCI_STD_SIZE;
@@ -1222,7 +1372,7 @@ uhci_free_std(sc, std)
 {
 #ifdef DIAGNOSTIC
 #define TD_IS_FREE 0x12345678
-       if (LE(std->td.td_token) == TD_IS_FREE) {
+       if (std->td.td_token == LE(TD_IS_FREE)) {
                printf("uhci_free_std: freeing free TD %p\n", std);
                return;
        }
@@ -1237,15 +1387,15 @@ uhci_alloc_sqh(sc)
        uhci_softc_t *sc;
 {
        uhci_soft_qh_t *sqh;
-       usbd_status r;
+       usbd_status err;
        int i, offs;
        usb_dma_t dma;
 
-       if (!sc->sc_freeqhs) {
+       if (sc->sc_freeqhs == NULL) {
                DPRINTFN(2, ("uhci_alloc_sqh: allocating chunk\n"));
-               r = usb_allocmem(&sc->sc_bus, UHCI_SQH_SIZE * UHCI_SQH_CHUNK,
+               err = usb_allocmem(&sc->sc_bus, UHCI_SQH_SIZE * UHCI_SQH_CHUNK,
                                 UHCI_QH_ALIGN, &dma);
-               if (r != USBD_NORMAL_COMPLETION)
+               if (err)
                        return 0;
                for(i = 0; i < UHCI_SQH_CHUNK; i++) {
                        offs = i * UHCI_SQH_SIZE;
@@ -1301,10 +1451,11 @@ uhci_free_std_chain(sc, std, stdend)
 }
 
 usbd_status
-uhci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
+uhci_alloc_std_chain(upipe, sc, len, rd, flags, dma, sp, ep)
        struct uhci_pipe *upipe;
        uhci_softc_t *sc;
-       int len, rd, shortok;
+       int len, rd;
+       u_int16_t flags;
        usb_dma_t *dma;
        uhci_soft_td_t **sp, **ep;
 {
@@ -1316,20 +1467,22 @@ uhci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
        int endpt = upipe->pipe.endpoint->edesc->bEndpointAddress;
 
        DPRINTFN(8, ("uhci_alloc_std_chain: addr=%d endpt=%d len=%d ls=%d "
-                     "shortok=%d\n", addr, UE_GET_ADDR(endpt), len, 
-                     upipe->pipe.device->lowspeed, shortok));
-       if (len == 0) {
-               *sp = *ep = 0;
-               DPRINTFN(-1,("uhci_alloc_std_chain: len=0\n"));
-               return (USBD_NORMAL_COMPLETION);
-       }
+                    "flags=0x%x\n", addr, UE_GET_ADDR(endpt), len,
+                    upipe->pipe.device->lowspeed, flags));
        maxp = UGETW(upipe->pipe.endpoint->edesc->wMaxPacketSize);
        if (maxp == 0) {
                printf("uhci_alloc_std_chain: maxp=0\n");
                return (USBD_INVAL);
        }
        ntd = (len + maxp - 1) / maxp;
+       if ((flags & USBD_FORCE_SHORT_XFER) && len % maxp == 0)
+               ntd++;
        DPRINTFN(10, ("uhci_alloc_std_chain: maxp=%d ntd=%d\n", maxp, ntd));
+       if (ntd == 0) {
+               *sp = *ep = 0;
+               DPRINTFN(-1,("uhci_alloc_std_chain: ntd=0\n"));
+               return (USBD_NORMAL_COMPLETION);
+       }
        tog = upipe->nexttoggle;
        if (ntd % 2 == 0)
                tog ^= 1;
@@ -1340,23 +1493,27 @@ uhci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
        status = UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(3) | UHCI_TD_ACTIVE);
        if (upipe->pipe.device->lowspeed)
                status |= UHCI_TD_LS;
-       if (shortok)
+       if (flags & USBD_SHORT_XFER_OK)
                status |= UHCI_TD_SPD;
        for (i = ntd; i >= 0; i--) {
                p = uhci_alloc_std(sc);
-               if (!p) {
+               if (p == NULL) {
                        uhci_free_std_chain(sc, lastp, 0);
                        return (USBD_NOMEM);
                }
                p->link.std = lastp;
-               p->td.td_link = LE(lastlink);
+               if (lastlink == UHCI_PTR_T)
+                       p->td.td_link = LE(lastlink);
+               else
+                       p->td.td_link = LE(lastlink|UHCI_PTR_VF);
                lastp = p;
                lastlink = p->physaddr;
                p->td.td_status = LE(status);
                if (i == ntd) {
                        /* last TD */
                        l = len % maxp;
-                       if (l == 0) l = maxp;
+                       if (l == 0 && !(flags & USBD_FORCE_SHORT_XFER))
+                               l = maxp;
                        *ep = p;
                } else
                        l = maxp;
@@ -1387,55 +1544,59 @@ uhci_noop(pipe)
 }
 
 usbd_status
-uhci_device_bulk_transfer(reqh)
-       usbd_request_handle reqh;
+uhci_device_bulk_transfer(xfer)
+       usbd_xfer_handle xfer;
 {
-       usbd_status r;
+       usbd_status err;
 
        /* Insert last in queue. */
-       r = usb_insert_transfer(reqh);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = usb_insert_transfer(xfer);
+       if (err)
+               return (err);
 
-       /* Pipe isn't running, start first */
-       return (uhci_device_bulk_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
+       /* Pipe isn't running (otherwise err would be USBD_INPROG),
+        * start first
+        */
+       return (uhci_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
 }
 
 usbd_status
-uhci_device_bulk_start(reqh)
-       usbd_request_handle reqh;
+uhci_device_bulk_start(xfer)
+       usbd_xfer_handle xfer;
 {
-       struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
+       struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
        usbd_device_handle dev = upipe->pipe.device;
        uhci_softc_t *sc = (uhci_softc_t *)dev->bus;
        uhci_intr_info_t *ii = upipe->iinfo;
        uhci_soft_td_t *data, *dataend;
        uhci_soft_qh_t *sqh;
-       usbd_status r;
+       usbd_status err;
        int len, isread, endpt;
        int s;
 
-       DPRINTFN(3, ("uhci_device_bulk_transfer: reqh=%p len=%d flags=%d\n",
-                    reqh, reqh->length, reqh->flags));
+       DPRINTFN(3, ("uhci_device_bulk_transfer: xfer=%p len=%d flags=%d\n",
+                    xfer, xfer->length, xfer->flags));
+
+       if (sc->sc_dying)
+               return (USBD_IOERROR);
 
 #ifdef DIAGNOSTIC
-       if (reqh->rqflags & URQ_REQUEST)
+       if (xfer->rqflags & URQ_REQUEST)
                panic("uhci_device_bulk_transfer: a request\n");
 #endif
 
-       len = reqh->length;
-       endpt = reqh->pipe->endpoint->edesc->bEndpointAddress;
+       len = xfer->length;
+       endpt = xfer->pipe->endpoint->edesc->bEndpointAddress;
        isread = UE_GET_DIR(endpt) == UE_DIR_IN;
        sqh = upipe->u.bulk.sqh;
 
        upipe->u.bulk.isread = isread;
        upipe->u.bulk.length = len;
 
-       r = uhci_alloc_std_chain(upipe, sc, len, isread, 
-                                reqh->flags & USBD_SHORT_XFER_OK,
-                                &reqh->dmabuf, &data, &dataend);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = uhci_alloc_std_chain(upipe, sc, len, isread, xfer->flags,
+                                &xfer->dmabuf, &data, &dataend);
+       if (err)
+               return (err);
        dataend->td.td_status |= LE(UHCI_TD_IOC);
 
 #ifdef UHCI_DEBUG
@@ -1446,13 +1607,16 @@ uhci_device_bulk_start(reqh)
 #endif
 
        /* Set up interrupt info. */
-       ii->reqh = reqh;
+       ii->xfer = xfer;
        ii->stdstart = data;
        ii->stdend = dataend;
 #if defined(__FreeBSD__)
        callout_handle_init(&ii->timeout_handle);
 #endif
 #ifdef DIAGNOSTIC
+       if (!ii->isdone) {
+               printf("uhci_device_bulk_transfer: not done, ii=%p\n", ii);
+       }
        ii->isdone = 0;
 #endif
 
@@ -1464,8 +1628,8 @@ uhci_device_bulk_start(reqh)
        uhci_add_bulk(sc, sqh);
        LIST_INSERT_HEAD(&sc->sc_intrhead, ii, list);
 
-       if (reqh->timeout && !sc->sc_bus.use_polling) {
-               usb_timeout(uhci_timeout, ii, MS_TO_TICKS(reqh->timeout),
+       if (xfer->timeout && !sc->sc_bus.use_polling) {
+               usb_timeout(uhci_timeout, ii, MS_TO_TICKS(xfer->timeout),
                            ii->timeout_handle);
        }
        splx(s);
@@ -1478,31 +1642,33 @@ uhci_device_bulk_start(reqh)
 #endif
 
        if (sc->sc_bus.use_polling)
-               uhci_waitintr(sc, reqh);
+               uhci_waitintr(sc, xfer);
 
        return (USBD_IN_PROGRESS);
 }
 
 /* Abort a device bulk request. */
 void
-uhci_device_bulk_abort(reqh)
-       usbd_request_handle reqh;
+uhci_device_bulk_abort(xfer)
+       usbd_xfer_handle xfer;
 {
        DPRINTF(("uhci_device_bulk_abort:\n"));
-       uhci_abort_req(reqh, USBD_CANCELLED);
+       uhci_abort_xfer(xfer, USBD_CANCELLED);
 }
 
 void
-uhci_abort_req(reqh, status)
-       usbd_request_handle reqh;
+uhci_abort_xfer(xfer, status)
+       usbd_xfer_handle xfer;
        usbd_status status;
 {
-       struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
+       struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
        uhci_intr_info_t *ii = upipe->iinfo;
        uhci_soft_td_t *std;
 
+       DPRINTFN(1,("uhci_abort_xfer: xfer=%p, status=%d\n", xfer, status));
+
        /* Make interrupt routine ignore it, */
-       reqh->status = status;
+       xfer->status = status;
 
        /* don't timeout, */
        usb_untimeout(uhci_timeout, ii, ii->timeout_handle);
@@ -1511,28 +1677,37 @@ uhci_abort_req(reqh, status)
        for (std = ii->stdstart; std != 0; std = std->link.std)
                std->td.td_status &= LE(~(UHCI_TD_ACTIVE | UHCI_TD_IOC));
 
-       reqh->hcpriv = ii;
+       xfer->hcpriv = ii;
 
-       /* make sure hardware has completed, */
-       if (reqh->device->bus->intr_context) {
+#if 1
+       /* Make sure hardware has completed, */
+       if (xfer->device->bus->intr_context) {
                /* We have no process context, so we can't use tsleep(). */
-               timeout(uhci_abort_req_end, reqh, hz / USB_FRAMES_PER_SECOND);
+               timeout(uhci_abort_xfer_end, xfer, hz / USB_FRAMES_PER_SECOND);
        } else {
-               usb_delay_ms(reqh->pipe->device->bus, 1);
+#if defined(DIAGNOSTIC) && defined(__i386__) && defined(__FreeBSD__)
+               KASSERT(intr_nesting_level == 0,
+                       ("ohci_abort_req in interrupt context"));
+#endif
+               usb_delay_ms(xfer->pipe->device->bus, 1);
                /* and call final part of interrupt handler. */
-               uhci_abort_req_end(reqh);
+               uhci_abort_xfer_end(xfer);
        }
+#else
+       delay(1000);
+       uhci_abort_xfer_end(xfer);
+#endif
 }
 
 void
-uhci_abort_req_end(v)
+uhci_abort_xfer_end(v)
        void *v;
 {
-       usbd_request_handle reqh = v;
+       usbd_xfer_handle xfer = v;
        int s;
 
        s = splusb();
-       usb_transfer_complete(reqh);
+       usb_transfer_complete(xfer);
        splx(s);
 }
 
@@ -1547,86 +1722,95 @@ uhci_device_bulk_close(pipe)
 
        uhci_free_sqh(sc, upipe->u.bulk.sqh);
        uhci_free_intr_info(upipe->iinfo);
-       /* XXX free other resources */
+       /* XXX free other resources? */
 }
 
 usbd_status
-uhci_device_ctrl_transfer(reqh)
-       usbd_request_handle reqh;
+uhci_device_ctrl_transfer(xfer)
+       usbd_xfer_handle xfer;
 {
-       usbd_status r;
+       usbd_status err;
 
        /* Insert last in queue. */
-       r = usb_insert_transfer(reqh);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = usb_insert_transfer(xfer);
+       if (err)
+               return (err);
 
-       /* Pipe isn't running, start first */
-       return (uhci_device_ctrl_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
+       /* Pipe isn't running (otherwise err would be USBD_INPROG),
+        * start first
+        */
+       return (uhci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
 }
 
 usbd_status
-uhci_device_ctrl_start(reqh)
-       usbd_request_handle reqh;
+uhci_device_ctrl_start(xfer)
+       usbd_xfer_handle xfer;
 {
-       uhci_softc_t *sc = (uhci_softc_t *)reqh->pipe->device->bus;
-       usbd_status r;
+       uhci_softc_t *sc = (uhci_softc_t *)xfer->pipe->device->bus;
+       usbd_status err;
+
+       if (sc->sc_dying)
+               return (USBD_IOERROR);
 
 #ifdef DIAGNOSTIC
-       if (!(reqh->rqflags & URQ_REQUEST))
+       if (!(xfer->rqflags & URQ_REQUEST))
                panic("uhci_device_ctrl_transfer: not a request\n");
 #endif
 
-       r = uhci_device_request(reqh);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = uhci_device_request(xfer);
+       if (err)
+               return (err);
 
        if (sc->sc_bus.use_polling)
-               uhci_waitintr(sc, reqh);
+               uhci_waitintr(sc, xfer);
        return (USBD_IN_PROGRESS);
 }
 
 usbd_status
-uhci_device_intr_transfer(reqh)
-       usbd_request_handle reqh;
+uhci_device_intr_transfer(xfer)
+       usbd_xfer_handle xfer;
 {
-       usbd_status r;
+       usbd_status err;
 
        /* Insert last in queue. */
-       r = usb_insert_transfer(reqh);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = usb_insert_transfer(xfer);
+       if (err)
+               return (err);
 
-       /* Pipe isn't running, start first */
-       return (uhci_device_intr_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
+       /* Pipe isn't running (otherwise err would be USBD_INPROG),
+        * start first
+        */
+       return (uhci_device_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
 }
 
 usbd_status
-uhci_device_intr_start(reqh)
-       usbd_request_handle reqh;
+uhci_device_intr_start(xfer)
+       usbd_xfer_handle xfer;
 {
-       struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
+       struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
        usbd_device_handle dev = upipe->pipe.device;
        uhci_softc_t *sc = (uhci_softc_t *)dev->bus;
        uhci_intr_info_t *ii = upipe->iinfo;
        uhci_soft_td_t *data, *dataend;
        uhci_soft_qh_t *sqh;
-       usbd_status r;
+       usbd_status err;
        int i, s;
 
-       DPRINTFN(3,("uhci_device_intr_transfer: reqh=%p len=%d flags=%d\n",
-                   reqh, reqh->length, reqh->flags));
+       if (sc->sc_dying)
+               return (USBD_IOERROR);
+
+       DPRINTFN(3,("uhci_device_intr_transfer: xfer=%p len=%d flags=%d\n",
+                   xfer, xfer->length, xfer->flags));
 
 #ifdef DIAGNOSTIC
-       if (reqh->rqflags & URQ_REQUEST)
+       if (xfer->rqflags & URQ_REQUEST)
                panic("uhci_device_intr_transfer: a request\n");
 #endif
 
-       r = uhci_alloc_std_chain(upipe, sc, reqh->length, 1,
-                                reqh->flags & USBD_SHORT_XFER_OK,
-                                &reqh->dmabuf, &data, &dataend);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = uhci_alloc_std_chain(upipe, sc, xfer->length, 1, xfer->flags,
+                                &xfer->dmabuf, &data, &dataend);
+       if (err)
+               return (err);
        dataend->td.td_status |= LE(UHCI_TD_IOC);
 
 #ifdef UHCI_DEBUG
@@ -1639,13 +1823,16 @@ uhci_device_intr_start(reqh)
 
        s = splusb();
        /* Set up interrupt info. */
-       ii->reqh = reqh;
+       ii->xfer = xfer;
        ii->stdstart = data;
        ii->stdend = dataend;
 #if defined(__FreeBSD__)
        callout_handle_init(&ii->timeout_handle);
 #endif
 #ifdef DIAGNOSTIC
+       if (!ii->isdone) {
+               printf("uhci_device_intr_transfer: not done, ii=%p\n", ii);
+       }
        ii->isdone = 0;
 #endif
 
@@ -1671,11 +1858,11 @@ uhci_device_intr_start(reqh)
 
 /* Abort a device control request. */
 void
-uhci_device_ctrl_abort(reqh)
-       usbd_request_handle reqh;
+uhci_device_ctrl_abort(xfer)
+       usbd_xfer_handle xfer;
 {
        DPRINTF(("uhci_device_ctrl_abort:\n"));
-       uhci_abort_req(reqh, USBD_CANCELLED);
+       uhci_abort_xfer(xfer, USBD_CANCELLED);
 }
 
 /* Close a device control pipe. */
@@ -1691,15 +1878,15 @@ uhci_device_ctrl_close(pipe)
 
 /* Abort a device interrupt request. */
 void
-uhci_device_intr_abort(reqh)
-       usbd_request_handle reqh;
+uhci_device_intr_abort(xfer)
+       usbd_xfer_handle xfer;
 {
-       DPRINTFN(1,("uhci_device_intr_abort: reqh=%p\n", reqh));
-       if (reqh->pipe->intrreqh == reqh) {
+       DPRINTFN(1,("uhci_device_intr_abort: xfer=%p\n", xfer));
+       if (xfer->pipe->intrxfer == xfer) {
                DPRINTFN(1,("uhci_device_intr_abort: remove\n"));
-               reqh->pipe->intrreqh = 0;
+               xfer->pipe->intrxfer = 0;
        }
-       uhci_abort_req(reqh, USBD_CANCELLED);
+       uhci_abort_xfer(xfer, USBD_CANCELLED);
 }
 
 /* Close a device interrupt pipe. */
@@ -1740,11 +1927,11 @@ uhci_device_intr_close(pipe)
 }
 
 usbd_status
-uhci_device_request(reqh)
-       usbd_request_handle reqh;
+uhci_device_request(xfer)
+       usbd_xfer_handle xfer;
 {
-       struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
-       usb_device_request_t *req = &reqh->request;
+       struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
+       usb_device_request_t *req = &xfer->request;
        usbd_device_handle dev = upipe->pipe.device;
        uhci_softc_t *sc = (uhci_softc_t *)dev->bus;
        int addr = dev->address;
@@ -1754,7 +1941,7 @@ uhci_device_request(reqh)
        uhci_soft_qh_t *sqh;
        int len;
        u_int32_t ls;
-       usbd_status r;
+       usbd_status err;
        int isread;
        int s;
 
@@ -1775,14 +1962,13 @@ uhci_device_request(reqh)
        /* Set up data transaction */
        if (len != 0) {
                upipe->nexttoggle = 1;
-               r = uhci_alloc_std_chain(upipe, sc, len, isread, 
-                                        reqh->flags & USBD_SHORT_XFER_OK,
-                                        &reqh->dmabuf, &data, &dataend);
-               if (r != USBD_NORMAL_COMPLETION)
-                       return (r);
+               err = uhci_alloc_std_chain(upipe, sc, len, isread, xfer->flags,
+                                        &xfer->dmabuf, &data, &dataend);
+               if (err)
+                       return (err);
                next = data;
                dataend->link.std = stat;
-               dataend->td.td_link = LE(stat->physaddr);
+               dataend->td.td_link = LE(stat->physaddr | UHCI_PTR_VF);
        } else {
                next = stat;
        }
@@ -1791,7 +1977,7 @@ uhci_device_request(reqh)
        memcpy(KERNADDR(&upipe->u.ctl.reqdma), req, sizeof *req);
 
        setup->link.std = next;
-       setup->td.td_link = LE(next->physaddr);
+       setup->td.td_link = LE(next->physaddr | UHCI_PTR_VF);
        setup->td.td_status = LE(UHCI_TD_SET_ERRCNT(3) | ls | UHCI_TD_ACTIVE);
        setup->td.td_token = LE(UHCI_TD_SETUP(sizeof *req, endpt, addr));
        setup->td.td_buffer = LE(DMAADDR(&upipe->u.ctl.reqdma));
@@ -1806,20 +1992,23 @@ uhci_device_request(reqh)
        stat->td.td_buffer = LE(0);
 
 #ifdef UHCI_DEBUG
-       if (uhcidebug > 20) {
+       if (uhcidebug > 10) {
                DPRINTF(("uhci_device_request: before transfer\n"));
                uhci_dump_tds(setup);
        }
 #endif
 
        /* Set up interrupt info. */
-       ii->reqh = reqh;
+       ii->xfer = xfer;
        ii->stdstart = setup;
        ii->stdend = stat;
 #if defined(__FreeBSD__)
        callout_handle_init(&ii->timeout_handle);
 #endif
 #ifdef DIAGNOSTIC
+       if (!ii->isdone) {
+               printf("uhci_device_request: not done, ii=%p\n", ii);
+       }
        ii->isdone = 0;
 #endif
 
@@ -1844,21 +2033,22 @@ uhci_device_request(reqh)
                        link = LE(std->td.td_link);
                        uhci_dump_td(std);
                }
-               for (sxqh = xqh = (uhci_soft_qh_t *)std;
-                    xqh;
+               sxqh = (uhci_soft_qh_t *)std;
+               uhci_dump_qh(sxqh);
+               for (xqh = sxqh;
+                    xqh != NULL;
                     xqh = (maxqh++ == 5 || xqh->hlink==sxqh || 
                             xqh->hlink==xqh ? NULL : xqh->hlink)) {
                        uhci_dump_qh(xqh);
-                       uhci_dump_qh(sxqh);
                }
                DPRINTF(("Enqueued QH:\n"));
                uhci_dump_qh(sqh);
                uhci_dump_tds(sqh->elink);
        }
 #endif
-       if (reqh->timeout && !sc->sc_bus.use_polling) {
+       if (xfer->timeout && !sc->sc_bus.use_polling) {
                usb_timeout(uhci_timeout, ii,
-                            MS_TO_TICKS(reqh->timeout), ii->timeout_handle);
+                            MS_TO_TICKS(xfer->timeout), ii->timeout_handle);
        }
        splx(s);
 
@@ -1866,37 +2056,37 @@ uhci_device_request(reqh)
 }
 
 usbd_status
-uhci_device_isoc_transfer(reqh)
-       usbd_request_handle reqh;
+uhci_device_isoc_transfer(xfer)
+       usbd_xfer_handle xfer;
 {
-       usbd_status r;
+       usbd_status err;
 
-       DPRINTFN(5,("uhci_device_isoc_transfer: reqh=%p\n", reqh));
+       DPRINTFN(5,("uhci_device_isoc_transfer: xfer=%p\n", xfer));
 
        /* Put it on our queue, */
-       r = usb_insert_transfer(reqh);
+       err = usb_insert_transfer(xfer);
 
        /* bail out on error, */
-       if (r != USBD_NORMAL_COMPLETION && r != USBD_IN_PROGRESS)
-               return (r);
+       if (err && err != USBD_IN_PROGRESS)
+               return (err);
 
        /* XXX should check inuse here */
 
        /* insert into schedule, */
-       uhci_device_isoc_enter(reqh);
+       uhci_device_isoc_enter(xfer);
 
        /* and put on interrupt list if the pipe wasn't running */
-       if (r == USBD_NORMAL_COMPLETION)
-               uhci_device_isoc_start(SIMPLEQ_FIRST(&reqh->pipe->queue));
+       if (!err)
+               uhci_device_isoc_start(SIMPLEQ_FIRST(&xfer->pipe->queue));
 
-       return (r);
+       return (err);
 }
 
 void
-uhci_device_isoc_enter(reqh)
-       usbd_request_handle reqh;
+uhci_device_isoc_enter(xfer)
+       usbd_xfer_handle xfer;
 {
-       struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
+       struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
        usbd_device_handle dev = upipe->pipe.device;
        uhci_softc_t *sc = (uhci_softc_t *)dev->bus;
        struct iso *iso = &upipe->u.iso;
@@ -1904,12 +2094,16 @@ uhci_device_isoc_enter(reqh)
        u_int32_t buf, len, status;
        int s, i, next, nframes;
 
-       DPRINTFN(5,("uhci_device_isoc_enter: used=%d next=%d reqh=%p "
+       DPRINTFN(5,("uhci_device_isoc_enter: used=%d next=%d xfer=%p "
                    "nframes=%d\n",
-                   iso->inuse, iso->next, reqh, reqh->nframes));
+                   iso->inuse, iso->next, xfer, xfer->nframes));
+
+       if (sc->sc_dying)
+               return;
 
-       if (reqh->status == USBD_IN_PROGRESS) {
+       if (xfer->status == USBD_IN_PROGRESS) {
                /* This request has already been entered into the frame list */
+               /* XXX */
        }
 
 #ifdef DIAGNOSTIC
@@ -1924,20 +2118,20 @@ uhci_device_isoc_enter(reqh)
                DPRINTFN(2,("uhci_device_isoc_enter: start next=%d\n", next));
        }
 
-       reqh->status = USBD_IN_PROGRESS;
-       reqh->hcprivint = next;
+       xfer->status = USBD_IN_PROGRESS;
+       xfer->hcprivint = next;
 
-       buf = DMAADDR(&reqh->dmabuf);
+       buf = DMAADDR(&xfer->dmabuf);
        status = LE(UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(0) |
                                        UHCI_TD_ACTIVE |
                                        UHCI_TD_IOS));
-       nframes = reqh->nframes;
+       nframes = xfer->nframes;
        s = splusb();
        for (i = 0; i < nframes; i++) {
                std = iso->stds[next];
                if (++next >= UHCI_VFRAMELIST_COUNT)
                        next = 0;
-               len = reqh->frlengths[i];
+               len = xfer->frlengths[i];
                std->td.td_buffer = LE(buf);
                if (i == nframes - 1)
                        status |= LE(UHCI_TD_IOC);
@@ -1953,28 +2147,31 @@ uhci_device_isoc_enter(reqh)
                buf += len;
        }
        iso->next = next;
-       iso->inuse += reqh->nframes;
+       iso->inuse += xfer->nframes;
 
        splx(s);
 }
 
 usbd_status
-uhci_device_isoc_start(reqh)
-       usbd_request_handle reqh;
+uhci_device_isoc_start(xfer)
+       usbd_xfer_handle xfer;
 {
-       struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
+       struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
        uhci_softc_t *sc = (uhci_softc_t *)upipe->pipe.device->bus;
        uhci_intr_info_t *ii = upipe->iinfo;
        uhci_soft_td_t *end;
        int s, i;
 
+       if (sc->sc_dying)
+               return (USBD_IOERROR);
+
 #ifdef DIAGNOSTIC
-       if (reqh->status != USBD_IN_PROGRESS)
-               printf("uhci_device_isoc_start: not in progress %p\n", reqh);
+       if (xfer->status != USBD_IN_PROGRESS)
+               printf("uhci_device_isoc_start: not in progress %p\n", xfer);
 #endif
 
        /* Find the last TD */
-       i = reqh->hcprivint + reqh->nframes;
+       i = xfer->hcprivint + xfer->nframes;
        if (i >= UHCI_VFRAMELIST_COUNT)
                i -= UHCI_VFRAMELIST_COUNT;
        end = upipe->u.iso.stds[i];
@@ -1982,13 +2179,16 @@ uhci_device_isoc_start(reqh)
        s = splusb();
        
        /* Set up interrupt info. */
-       ii->reqh = reqh;
+       ii->xfer = xfer;
        ii->stdstart = end;
        ii->stdend = end;
 #if defined(__FreeBSD__)
        callout_handle_init(&ii->timeout_handle);
 #endif
 #ifdef DIAGNOSTIC
+       if (!ii->isdone) {
+               printf("uhci_device_isoc_start: not done, ii=%p\n", ii);
+       }
        ii->isdone = 0;
 #endif
        LIST_INSERT_HEAD(&sc->sc_intrhead, ii, list);
@@ -1999,21 +2199,21 @@ uhci_device_isoc_start(reqh)
 }
 
 void
-uhci_device_isoc_abort(reqh)
-       usbd_request_handle reqh;
+uhci_device_isoc_abort(xfer)
+       usbd_xfer_handle xfer;
 {
-       struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
+       struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
        uhci_intr_info_t *ii = upipe->iinfo;
        uhci_soft_td_t **stds = upipe->u.iso.stds;
        uhci_soft_td_t *std;
        int i, n, nframes;
 
        /* Make interrupt routine ignore it, */
-       reqh->status = USBD_CANCELLED;
+       xfer->status = USBD_CANCELLED;
 
        /* make hardware ignore it, */
-       nframes = reqh->nframes;
-       n = reqh->hcprivint;
+       nframes = xfer->nframes;
+       n = xfer->hcprivint;
        for (i = 0; i < nframes; i++) {
                std = stds[n];
                std->td.td_status &= LE(~(UHCI_TD_ACTIVE | UHCI_TD_IOC));
@@ -2021,16 +2221,16 @@ uhci_device_isoc_abort(reqh)
                        n = 0;
        }
 
-       reqh->hcpriv = ii;
+       xfer->hcpriv = ii;
 
        /* make sure hardware has completed, */
-       if (reqh->device->bus->intr_context) {
+       if (xfer->device->bus->intr_context) {
                /* We have no process context, so we can't use tsleep(). */
-               timeout(uhci_abort_req_end, reqh, hz / USB_FRAMES_PER_SECOND);
+               timeout(uhci_abort_xfer_end, xfer, hz / USB_FRAMES_PER_SECOND);
        } else {
-               usb_delay_ms(reqh->pipe->device->bus, 1);
+               usb_delay_ms(xfer->pipe->device->bus, 1);
                /* and call final part of interrupt handler. */
-               uhci_abort_req_end(reqh);
+               uhci_abort_xfer_end(xfer);
        }
 }
 
@@ -2061,10 +2261,10 @@ uhci_device_isoc_close(pipe)
        for (i = 0; i < UHCI_VFRAMELIST_COUNT; i++) {
                std = iso->stds[i];
                for (vstd = sc->sc_vframes[i].htd;
-                    vstd && vstd->link.std != std;
+                    vstd != NULL && vstd->link.std != std;
                     vstd = vstd->link.std)
                        ;
-               if (!vstd) {
+               if (vstd == NULL) {
                        /*panic*/
                        printf("uhci_device_isoc_close: %p not found\n", std);
                        uhci_unlock_frames(sc);
@@ -2136,12 +2336,12 @@ uhci_setup_isoc(pipe)
 }
 
 void
-uhci_device_isoc_done(reqh)
-       usbd_request_handle reqh;
+uhci_device_isoc_done(xfer)
+       usbd_xfer_handle xfer;
 {
-       uhci_intr_info_t *ii = reqh->hcpriv;
+       uhci_intr_info_t *ii = xfer->hcpriv;
 
-       DPRINTFN(4, ("uhci_isoc_done: length=%d\n", reqh->actlen));
+       DPRINTFN(4, ("uhci_isoc_done: length=%d\n", xfer->actlen));
 
        /* Turn off the interrupt since it is active even if the TD is not. */
        ii->stdend->td.td_status &= LE(~UHCI_TD_IOC);
@@ -2150,16 +2350,16 @@ uhci_device_isoc_done(reqh)
 }
 
 void
-uhci_device_intr_done(reqh)
-       usbd_request_handle reqh;
+uhci_device_intr_done(xfer)
+       usbd_xfer_handle xfer;
 {
-       uhci_intr_info_t *ii = reqh->hcpriv;
+       uhci_intr_info_t *ii = xfer->hcpriv;
        uhci_softc_t *sc = ii->sc;
-       struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
+       struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
        uhci_soft_qh_t *sqh;
        int i, npoll;
 
-       DPRINTFN(5, ("uhci_intr_done: length=%d\n", reqh->actlen));
+       DPRINTFN(5, ("uhci_intr_done: length=%d\n", xfer->actlen));
 
        npoll = upipe->u.intr.npoll;
        for(i = 0; i < npoll; i++) {
@@ -2170,13 +2370,12 @@ uhci_device_intr_done(reqh)
        uhci_free_std_chain(sc, ii->stdstart, 0);
 
        /* XXX Wasteful. */
-       if (reqh->pipe->repeat) {
+       if (xfer->pipe->repeat) {
                uhci_soft_td_t *data, *dataend;
 
                /* This alloc cannot fail since we freed the chain above. */
-               uhci_alloc_std_chain(upipe, sc, reqh->length, 1,
-                                    reqh->flags & USBD_SHORT_XFER_OK,
-                                    &reqh->dmabuf, &data, &dataend);
+               uhci_alloc_std_chain(upipe, sc, xfer->length, 1, xfer->flags,
+                                    &xfer->dmabuf, &data, &dataend);
                dataend->td.td_status |= LE(UHCI_TD_IOC);
 
 #ifdef UHCI_DEBUG
@@ -2193,6 +2392,9 @@ uhci_device_intr_done(reqh)
                callout_handle_init(&ii->timeout_handle);
 #endif
 #ifdef DIAGNOSTIC
+               if (!ii->isdone) {
+                       printf("uhci_device_intr_done: not done, ii=%p\n", ii);
+               }
                ii->isdone = 0;
 #endif
                for (i = 0; i < npoll; i++) {
@@ -2207,15 +2409,15 @@ uhci_device_intr_done(reqh)
 
 /* Deallocate request data structures */
 void
-uhci_device_ctrl_done(reqh)
-       usbd_request_handle reqh;
+uhci_device_ctrl_done(xfer)
+       usbd_xfer_handle xfer;
 {
-       uhci_intr_info_t *ii = reqh->hcpriv;
+       uhci_intr_info_t *ii = xfer->hcpriv;
        uhci_softc_t *sc = ii->sc;
-       struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
+       struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
 
 #ifdef DIAGNOSTIC
-       if (!(reqh->rqflags & URQ_REQUEST))
+       if (!(xfer->rqflags & URQ_REQUEST))
                panic("uhci_ctrl_done: not a request\n");
 #endif
 
@@ -2226,17 +2428,17 @@ uhci_device_ctrl_done(reqh)
        if (upipe->u.ctl.length != 0)
                uhci_free_std_chain(sc, ii->stdstart->link.std, ii->stdend);
 
-       DPRINTFN(5, ("uhci_ctrl_done: length=%d\n", reqh->actlen));
+       DPRINTFN(5, ("uhci_ctrl_done: length=%d\n", xfer->actlen));
 }
 
 /* Deallocate request data structures */
 void
-uhci_device_bulk_done(reqh)
-       usbd_request_handle reqh;
+uhci_device_bulk_done(xfer)
+       usbd_xfer_handle xfer;
 {
-       uhci_intr_info_t *ii = reqh->hcpriv;
+       uhci_intr_info_t *ii = xfer->hcpriv;
        uhci_softc_t *sc = ii->sc;
-       struct uhci_pipe *upipe = (struct uhci_pipe *)reqh->pipe;
+       struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
 
        LIST_REMOVE(ii, list);  /* remove from active list */
 
@@ -2244,7 +2446,7 @@ uhci_device_bulk_done(reqh)
 
        uhci_free_std_chain(sc, ii->stdstart, 0);
 
-       DPRINTFN(5, ("uhci_bulk_done: length=%d\n", reqh->actlen));
+       DPRINTFN(5, ("uhci_bulk_done: length=%d\n", xfer->actlen));
 }
 
 /* Add interrupt QH, called with vflock. */
@@ -2368,7 +2570,8 @@ uhci_open(pipe)
        uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus;
        struct uhci_pipe *upipe = (struct uhci_pipe *)pipe;
        usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc;
-       usbd_status r;
+       usbd_status err;
+       int ival;
 
        DPRINTFN(1, ("uhci_open: pipe=%p, addr=%d, endpt=%d (%d)\n",
                     pipe, pipe->device->address, 
@@ -2392,23 +2595,23 @@ uhci_open(pipe)
                case UE_CONTROL:
                        pipe->methods = &uhci_device_ctrl_methods;
                        upipe->u.ctl.sqh = uhci_alloc_sqh(sc);
-                       if (upipe->u.ctl.sqh == 0)
+                       if (upipe->u.ctl.sqh == NULL)
                                goto bad;
                        upipe->u.ctl.setup = uhci_alloc_std(sc);
-                       if (upipe->u.ctl.setup == 0) {
+                       if (upipe->u.ctl.setup == NULL) {
                                uhci_free_sqh(sc, upipe->u.ctl.sqh);
                                goto bad;
                        }
                        upipe->u.ctl.stat = uhci_alloc_std(sc);
-                       if (upipe->u.ctl.stat == 0) {
+                       if (upipe->u.ctl.stat == NULL) {
                                uhci_free_sqh(sc, upipe->u.ctl.sqh);
                                uhci_free_std(sc, upipe->u.ctl.setup);
                                goto bad;
                        }
-                       r = usb_allocmem(&sc->sc_bus, 
+                       err = usb_allocmem(&sc->sc_bus, 
                                         sizeof(usb_device_request_t), 
                                         0, &upipe->u.ctl.reqdma);
-                       if (r != USBD_NORMAL_COMPLETION) {
+                       if (err) {
                                uhci_free_sqh(sc, upipe->u.ctl.sqh);
                                uhci_free_std(sc, upipe->u.ctl.setup);
                                uhci_free_std(sc, upipe->u.ctl.stat);
@@ -2417,14 +2620,17 @@ uhci_open(pipe)
                        break;
                case UE_INTERRUPT:
                        pipe->methods = &uhci_device_intr_methods;
-                       return (uhci_device_setintr(sc, upipe, ed->bInterval));
+                       ival = pipe->interval;
+                       if (ival == USBD_DEFAULT_INTERVAL)
+                               ival = ed->bInterval;
+                       return (uhci_device_setintr(sc, upipe, ival));
                case UE_ISOCHRONOUS:
                        pipe->methods = &uhci_device_isoc_methods;
                        return (uhci_setup_isoc(pipe));
                case UE_BULK:
                        pipe->methods = &uhci_device_bulk_methods;
                        upipe->u.bulk.sqh = uhci_alloc_sqh(sc);
-                       if (upipe->u.bulk.sqh == 0)
+                       if (upipe->u.bulk.sqh == NULL)
                                goto bad;
                        break;
                }
@@ -2443,8 +2649,8 @@ usb_device_descriptor_t uhci_devd = {
        USB_DEVICE_DESCRIPTOR_SIZE,
        UDESC_DEVICE,           /* type */
        {0x00, 0x01},           /* USB version */
-       UCLASS_HUB,             /* class */
-       USUBCLASS_HUB,          /* subclass */
+       UDCLASS_HUB,            /* class */
+       UDSUBCLASS_HUB,         /* subclass */
        0,                      /* protocol */
        64,                     /* max packet */
        {0},{0},{0x00,0x01},    /* device id */
@@ -2471,8 +2677,8 @@ usb_interface_descriptor_t uhci_ifcd = {
        0,
        0,
        1,
-       UCLASS_HUB,
-       USUBCLASS_HUB,
+       UICLASS_HUB,
+       UISUBCLASS_HUB,
        0,
        0
 };
@@ -2520,37 +2726,42 @@ uhci_str(p, l, s)
  * Simulate a hardware hub by handling all the necessary requests.
  */
 usbd_status
-uhci_root_ctrl_transfer(reqh)
-       usbd_request_handle reqh;
+uhci_root_ctrl_transfer(xfer)
+       usbd_xfer_handle xfer;
 {
-       usbd_status r;
+       usbd_status err;
 
        /* Insert last in queue. */
-       r = usb_insert_transfer(reqh);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = usb_insert_transfer(xfer);
+       if (err)
+               return (err);
 
-       /* Pipe isn't running, start first */
-       return (uhci_root_ctrl_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
+       /* Pipe isn't running (otherwise err would be USBD_INPROG),
+        * start first
+        */
+       return (uhci_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
 }
 
 usbd_status
-uhci_root_ctrl_start(reqh)
-       usbd_request_handle reqh;
+uhci_root_ctrl_start(xfer)
+       usbd_xfer_handle xfer;
 {
-       uhci_softc_t *sc = (uhci_softc_t *)reqh->pipe->device->bus;
+       uhci_softc_t *sc = (uhci_softc_t *)xfer->pipe->device->bus;
        usb_device_request_t *req;
        void *buf = NULL;
        int port, x;
        int s, len, value, index, status, change, l, totlen = 0;
        usb_port_status_t ps;
-       usbd_status r;
+       usbd_status err;
+
+       if (sc->sc_dying)
+               return (USBD_IOERROR);
 
 #ifdef DIAGNOSTIC
-       if (!(reqh->rqflags & URQ_REQUEST))
+       if (!(xfer->rqflags & URQ_REQUEST))
                panic("uhci_root_ctrl_transfer: not a request\n");
 #endif
-       req = &reqh->request;
+       req = &xfer->request;
 
        DPRINTFN(2,("uhci_root_ctrl_control type=0x%02x request=%02x\n", 
                    req->bmRequestType, req->bRequest));
@@ -2560,7 +2771,7 @@ uhci_root_ctrl_start(reqh)
        index = UGETW(req->wIndex);
 
        if (len != 0)
-               buf = KERNADDR(&reqh->dmabuf);
+               buf = KERNADDR(&xfer->dmabuf);
 
 #define C(x,y) ((x) | ((y) << 8))
        switch(C(req->bRequest, req->bmRequestType)) {
@@ -2583,7 +2794,7 @@ uhci_root_ctrl_start(reqh)
                switch(value >> 8) {
                case UDESC_DEVICE:
                        if ((value & 0xff) != 0) {
-                               r = USBD_IOERROR;
+                               err = USBD_IOERROR;
                                goto ret;
                        }
                        totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE);
@@ -2592,7 +2803,7 @@ uhci_root_ctrl_start(reqh)
                        break;
                case UDESC_CONFIG:
                        if ((value & 0xff) != 0) {
-                               r = USBD_IOERROR;
+                               err = USBD_IOERROR;
                                goto ret;
                        }
                        totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE);
@@ -2623,7 +2834,7 @@ uhci_root_ctrl_start(reqh)
                        }
                        break;
                default:
-                       r = USBD_IOERROR;
+                       err = USBD_IOERROR;
                        goto ret;
                }
                break;
@@ -2648,14 +2859,14 @@ uhci_root_ctrl_start(reqh)
                break;
        case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
                if (value >= USB_MAX_DEVICES) {
-                       r = USBD_IOERROR;
+                       err = USBD_IOERROR;
                        goto ret;
                }
                sc->sc_addr = value;
                break;
        case C(UR_SET_CONFIG, UT_WRITE_DEVICE):
                if (value != 0 && value != 1) {
-                       r = USBD_IOERROR;
+                       err = USBD_IOERROR;
                        goto ret;
                }
                sc->sc_conf = value;
@@ -2665,7 +2876,7 @@ uhci_root_ctrl_start(reqh)
        case C(UR_SET_FEATURE, UT_WRITE_DEVICE):
        case C(UR_SET_FEATURE, UT_WRITE_INTERFACE):
        case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT):
-               r = USBD_IOERROR;
+               err = USBD_IOERROR;
                goto ret;
        case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE):
                break;
@@ -2683,7 +2894,7 @@ uhci_root_ctrl_start(reqh)
                else if (index == 2)
                        port = UHCI_PORTSC2;
                else {
-                       r = USBD_IOERROR;
+                       err = USBD_IOERROR;
                        goto ret;
                }
                switch(value) {
@@ -2713,7 +2924,7 @@ uhci_root_ctrl_start(reqh)
                        break;
                case UHF_C_PORT_RESET:
                        sc->sc_isreset = 0;
-                       r = USBD_NORMAL_COMPLETION;
+                       err = USBD_NORMAL_COMPLETION;
                        goto ret;
                case UHF_PORT_CONNECTION:
                case UHF_PORT_OVER_CURRENT:
@@ -2721,7 +2932,7 @@ uhci_root_ctrl_start(reqh)
                case UHF_PORT_LOW_SPEED:
                case UHF_C_PORT_SUSPEND:
                default:
-                       r = USBD_IOERROR;
+                       err = USBD_IOERROR;
                        goto ret;
                }
                break;
@@ -2731,7 +2942,7 @@ uhci_root_ctrl_start(reqh)
                else if (index == 2)
                        port = UHCI_PORTSC2;
                else {
-                       r = USBD_IOERROR;
+                       err = USBD_IOERROR;
                        goto ret;
                }
                if (len > 0) {
@@ -2743,7 +2954,7 @@ uhci_root_ctrl_start(reqh)
                break;
        case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
                if (value != 0) {
-                       r = USBD_IOERROR;
+                       err = USBD_IOERROR;
                        goto ret;
                }
                l = min(len, USB_HUB_DESCRIPTOR_SIZE);
@@ -2752,7 +2963,7 @@ uhci_root_ctrl_start(reqh)
                break;
        case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
                if (len != 4) {
-                       r = USBD_IOERROR;
+                       err = USBD_IOERROR;
                        goto ret;
                }
                memset(buf, 0, len);
@@ -2764,11 +2975,11 @@ uhci_root_ctrl_start(reqh)
                else if (index == 2)
                        port = UHCI_PORTSC2;
                else {
-                       r = USBD_IOERROR;
+                       err = USBD_IOERROR;
                        goto ret;
                }
                if (len != 4) {
-                       r = USBD_IOERROR;
+                       err = USBD_IOERROR;
                        goto ret;
                }
                x = UREAD2(sc, port);
@@ -2799,7 +3010,7 @@ uhci_root_ctrl_start(reqh)
                totlen = l;
                break;
        case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE):
-               r = USBD_IOERROR;
+               err = USBD_IOERROR;
                goto ret;
        case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE):
                break;
@@ -2809,7 +3020,7 @@ uhci_root_ctrl_start(reqh)
                else if (index == 2)
                        port = UHCI_PORTSC2;
                else {
-                       r = USBD_IOERROR;
+                       err = USBD_IOERROR;
                        goto ret;
                }
                switch(value) {
@@ -2844,31 +3055,31 @@ uhci_root_ctrl_start(reqh)
                case UHF_C_PORT_SUSPEND:
                case UHF_C_PORT_RESET:
                default:
-                       r = USBD_IOERROR;
+                       err = USBD_IOERROR;
                        goto ret;
                }
                break;
        default:
-               r = USBD_IOERROR;
+               err = USBD_IOERROR;
                goto ret;
        }
-       reqh->actlen = totlen;
-       r = USBD_NORMAL_COMPLETION;
+       xfer->actlen = totlen;
+       err = USBD_NORMAL_COMPLETION;
  ret:
-       reqh->status = r;
-       reqh->hcpriv = 0;
+       xfer->status = err;
+       xfer->hcpriv = 0;
        s = splusb();
-       usb_transfer_complete(reqh);
+       usb_transfer_complete(xfer);
        splx(s);
        return (USBD_IN_PROGRESS);
 }
 
 /* Abort a root control request. */
 void
-uhci_root_ctrl_abort(reqh)
-       usbd_request_handle reqh;
+uhci_root_ctrl_abort(xfer)
+       usbd_xfer_handle xfer;
 {
-       /* Nothing to do, all transfers are syncronous. */
+       /* Nothing to do, all transfers are synchronous. */
 }
 
 /* Close the root pipe. */
@@ -2876,59 +3087,61 @@ void
 uhci_root_ctrl_close(pipe)
        usbd_pipe_handle pipe;
 {
-       uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus;
-
-       sc->sc_has_timo = 0;
        DPRINTF(("uhci_root_ctrl_close\n"));
 }
 
 /* Abort a root interrupt request. */
 void
-uhci_root_intr_abort(reqh)
-       usbd_request_handle reqh;
+uhci_root_intr_abort(xfer)
+       usbd_xfer_handle xfer;
 {
-       uhci_softc_t *sc = (uhci_softc_t *)reqh->pipe->device->bus;
+       uhci_softc_t *sc = (uhci_softc_t *)xfer->pipe->device->bus;
 
-       usb_untimeout(uhci_timo, reqh, reqh->timo_handle);
-       sc->sc_has_timo = 0;
+       usb_untimeout(uhci_timo, xfer, xfer->timo_handle);
+       sc->sc_has_timo = NULL;
 
-       if (reqh->pipe->intrreqh == reqh) {
+       if (xfer->pipe->intrxfer == xfer) {
                DPRINTF(("uhci_root_intr_abort: remove\n"));
-               reqh->pipe->intrreqh = 0;
+               xfer->pipe->intrxfer = 0;
        }
-       reqh->status = USBD_CANCELLED;
-       usb_transfer_complete(reqh);
+       xfer->status = USBD_CANCELLED;
+       usb_transfer_complete(xfer);
 }
 
 usbd_status
-uhci_root_intr_transfer(reqh)
-       usbd_request_handle reqh;
+uhci_root_intr_transfer(xfer)
+       usbd_xfer_handle xfer;
 {
-       usbd_status r;
+       usbd_status err;
 
        /* Insert last in queue. */
-       r = usb_insert_transfer(reqh);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = usb_insert_transfer(xfer);
+       if (err)
+               return (err);
 
-       /* Pipe isn't running, start first */
-       return (uhci_root_intr_start(SIMPLEQ_FIRST(&reqh->pipe->queue)));
+       /* Pipe isn't running (otherwise err would be USBD_INPROG),
+        * start first
+        */
+       return (uhci_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
 }
 
 /* Start a transfer on the root interrupt pipe */
 usbd_status
-uhci_root_intr_start(reqh)
-       usbd_request_handle reqh;
+uhci_root_intr_start(xfer)
+       usbd_xfer_handle xfer;
 {
-       usbd_pipe_handle pipe = reqh->pipe;
+       usbd_pipe_handle pipe = xfer->pipe;
        uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus;
 
-       DPRINTFN(3, ("uhci_root_intr_transfer: reqh=%p len=%d flags=%d\n",
-                    reqh, reqh->length, reqh->flags));
+       DPRINTFN(3, ("uhci_root_intr_transfer: xfer=%p len=%d flags=%d\n",
+                    xfer, xfer->length, xfer->flags));
+
+       if (sc->sc_dying)
+               return (USBD_IOERROR);
 
-       sc->sc_ival = MS_TO_TICKS(reqh->pipe->endpoint->edesc->bInterval);
-       usb_timeout(uhci_timo, reqh, sc->sc_ival, reqh->timo_handle);
-       sc->sc_has_timo = reqh;
+       sc->sc_ival = MS_TO_TICKS(xfer->pipe->endpoint->edesc->bInterval);
+       usb_timeout(uhci_timo, xfer, sc->sc_ival, xfer->timo_handle);
+       sc->sc_has_timo = xfer;
        return (USBD_IN_PROGRESS);
 }
 
@@ -2939,8 +3152,8 @@ uhci_root_intr_close(pipe)
 {
        uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus;
 
-       usb_untimeout(uhci_timo, pipe->intrreqh, pipe->intrreqh->timo_handle);
-       sc->sc_has_timo = 0;
+       usb_untimeout(uhci_timo, pipe->intrxfer, pipe->intrxfer->timo_handle);
+       sc->sc_has_timo = NULL;
        DPRINTF(("uhci_root_intr_close\n"));
 }
 
index a49c9c3..2213fde 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: uhcireg.h,v 1.2 1999/08/27 09:00:29 fgsch Exp $       */
-/*     $NetBSD: uhcireg.h,v 1.7 1999/08/22 23:19:57 augustss Exp $     */
+/*     $OpenBSD: uhcireg.h,v 1.3 2000/03/26 08:39:46 aaron Exp $       */
+/*     $NetBSD: uhcireg.h,v 1.9 1999/11/20 00:57:09 augustss Exp $     */
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -47,6 +47,7 @@
 #define  PCI_USBREV_MASK       0xff
 #define  PCI_USBREV_PRE_1_0    0x00
 #define  PCI_USBREV_1_0                0x10
+#define  PCI_USBREV_1_1                0x11
 
 #define PCI_LEGSUP             0xc0    /* Legacy Support register */
 #define  PCI_LEGSUP_USBPIRQDEN 0x2000  /* USB PIRQ D Enable */
index 26c6177..3f52610 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: uhcivar.h,v 1.5 1999/11/07 21:30:19 fgsch Exp $       */
-/*     $NetBSD: uhcivar.h,v 1.16 1999/10/13 08:10:56 augustss Exp $    */
+/*     $OpenBSD: uhcivar.h,v 1.6 2000/03/26 08:39:46 aaron Exp $       */
+/*     $NetBSD: uhcivar.h,v 1.23 2000/02/22 16:03:44 augustss Exp $    */
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@ typedef union {
  */
 typedef struct uhci_intr_info {
        struct uhci_softc *sc;
-       usbd_request_handle reqh;
+       usbd_xfer_handle xfer;
        uhci_soft_td_t *stdstart;
        uhci_soft_td_t *stdend;
        LIST_ENTRY(uhci_intr_info) list;
@@ -92,7 +92,7 @@ struct uhci_soft_td {
 };
 /* 
  * Make the size such that it is a multiple of UHCI_TD_ALIGN.  This way
- * we can pack a number of soft TD together and have the real TS well
+ * we can pack a number of soft TD together and have the real TD well
  * aligned.
  * NOTE: Minimum size is 32 bytes.
  */
@@ -116,7 +116,7 @@ struct uhci_soft_qh {
 #define UHCI_SQH_CHUNK 128 /*(PAGE_SIZE / UHCI_QH_SIZE)*/
 
 /*
- * Information about an entry in the virtial frame list.
+ * Information about an entry in the virtual frame list.
  */
 struct uhci_vframe {
        uhci_soft_td_t *htd;            /* pointer to dummy TD */
@@ -140,35 +140,43 @@ typedef struct uhci_softc {
        uhci_soft_qh_t *sc_bulk_start;  /* dummy QH for bulk */
        uhci_soft_qh_t *sc_bulk_end;    /* last bulk transfer */
 
-       uhci_soft_td_t *sc_freetds;
-       uhci_soft_qh_t *sc_freeqhs;
+       uhci_soft_td_t *sc_freetds;     /* TD free list */
+       uhci_soft_qh_t *sc_freeqhs;     /* QH free list */
+
+       SIMPLEQ_HEAD(, usbd_xfer) sc_free_xfers; /* free xfers */
 
        u_int8_t sc_addr;               /* device address */
        u_int8_t sc_conf;               /* device configuration */
 
-       char sc_isreset;
+       u_int8_t sc_saved_sof;
+       u_int16_t sc_saved_frnum;
 
+       char sc_isreset;
        char sc_suspend;
-       usbd_request_handle sc_has_timo;
+       char sc_dying;
 
        LIST_HEAD(, uhci_intr_info) sc_intrhead;
 
        /* Info for the root hub interrupt channel. */
-       int sc_ival;
+       int sc_ival;                    /* time between root hub intrs */
+       usbd_xfer_handle sc_has_timo;   /* root hub interrupt transfer */
 
-       char sc_vflock;
+       char sc_vflock;                 /* for lock virtual frame list */
 #define UHCI_HAS_LOCK 1
 #define UHCI_WANT_LOCK 2
 
-       char sc_vendor[16];
-       int sc_id_vendor;
+       char sc_vendor[16];             /* vendor string for root hub */
+       int sc_id_vendor;               /* vendor ID for root hub */
 
-       void *sc_powerhook;
-       device_ptr_t sc_child;
+       void *sc_powerhook;             /* cookie from power hook */
+       void *sc_shutdownhook;          /* cookie from shutdown hook */
+
+       device_ptr_t sc_child;          /* /dev/usb device */
 } uhci_softc_t;
 
 usbd_status    uhci_init __P((uhci_softc_t *));
 int            uhci_intr __P((void *));
+#if defined(__NetBSD__) || defined(__OpenBSD__)
 int            uhci_detach __P((uhci_softc_t *, int));
 int            uhci_activate __P((device_ptr_t, enum devact));
-
+#endif
index d0bd5ef..0443d21 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: uhid.c,v 1.6 1999/11/07 21:30:19 fgsch Exp $  */
-/*     $NetBSD: uhid.c,v 1.26 1999/10/13 08:10:56 augustss Exp $       */
+/*     $OpenBSD: uhid.c,v 1.7 2000/03/26 08:39:46 aaron Exp $  */
+/*     $NetBSD: uhid.c,v 1.35 2000/03/19 22:23:28 augustss Exp $       */
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -83,6 +83,7 @@ int   uhiddebug = 0;
 
 struct uhid_softc {
        USBBASEDEVICE sc_dev;                   /* base device */
+       usbd_device_handle sc_udev;
        usbd_interface_handle sc_iface; /* interface */
        usbd_pipe_handle sc_intrpipe;   /* interrupt pipe */
        int sc_ep_addr;
@@ -94,8 +95,8 @@ struct uhid_softc {
        u_int8_t sc_oid;
        u_int8_t sc_fid;
 
-       char *sc_ibuf;
-       char *sc_obuf;
+       u_char *sc_ibuf;
+       u_char *sc_obuf;
 
        void *sc_repdesc;
        int sc_repdesc_size;
@@ -146,7 +147,7 @@ static struct cdevsw uhid_cdevsw = {
 };
 #endif
 
-void uhid_intr __P((usbd_request_handle, usbd_private_handle, usbd_status));
+void uhid_intr __P((usbd_xfer_handle, usbd_private_handle, usbd_status));
 
 int uhid_do_read __P((struct uhid_softc *, struct uio *uio, int));
 int uhid_do_write __P((struct uhid_softc *, struct uio *uio, int));
@@ -159,10 +160,10 @@ USB_MATCH(uhid)
        USB_MATCH_START(uhid, uaa);
        usb_interface_descriptor_t *id;
        
-       if (!uaa->iface)
+       if (uaa->iface == NULL)
                return (UMATCH_NONE);
        id = usbd_get_interface_descriptor(uaa->iface);
-       if (!id || id->bInterfaceClass != UCLASS_HID)
+       if (id == NULL || id->bInterfaceClass != UICLASS_HID)
                return (UMATCH_NONE);
        return (UMATCH_IFACECLASS_GENERIC);
 }
@@ -175,9 +176,10 @@ USB_ATTACH(uhid)
        usb_endpoint_descriptor_t *ed;
        int size;
        void *desc;
-       usbd_status r;
+       usbd_status err;
        char devinfo[1024];
-       
+
+       sc->sc_udev = uaa->device;
        sc->sc_iface = iface;
        id = usbd_get_interface_descriptor(iface);
        usbd_devinfo(uaa->device, 0, devinfo);
@@ -186,7 +188,7 @@ USB_ATTACH(uhid)
               devinfo, id->bInterfaceClass, id->bInterfaceSubClass);
 
        ed = usbd_interface2endpoint_descriptor(iface, 0);
-       if (!ed) {
+       if (ed == NULL) {
                printf("%s: could not read endpoint descriptor\n",
                       USBDEVNAME(sc->sc_dev));
                sc->sc_dying = 1;
@@ -212,12 +214,10 @@ USB_ATTACH(uhid)
        sc->sc_ep_addr = ed->bEndpointAddress;
 
        desc = 0;
-       r = usbd_alloc_report_desc(uaa->iface, &desc, &size, M_USBDEV);
-       if (r != USBD_NORMAL_COMPLETION) {
+       err = usbd_alloc_report_desc(uaa->iface, &desc, &size, M_USBDEV);
+       if (err) {
                printf("%s: no report descriptor\n", USBDEVNAME(sc->sc_dev));
                sc->sc_dying = 1;
-               if (desc)
-                       free(desc, M_USBDEV);
                USB_ATTACH_ERROR_RETURN;
        }
        
@@ -230,6 +230,20 @@ USB_ATTACH(uhid)
        sc->sc_repdesc = desc;
        sc->sc_repdesc_size = size;
 
+#ifdef __FreeBSD__
+       {
+               static int global_init_done = 0;
+
+               if (!global_init_done) {
+                       cdevsw_add(&uhid_cdevsw);
+                       global_init_done = 1;
+               }
+       }
+#endif
+
+       usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
+                          USBDEV(sc->sc_dev));
+
        USB_ATTACH_SUCCESS_RETURN;
 }
 
@@ -267,7 +281,7 @@ USB_DETACH(uhid)
 #endif
 
        sc->sc_dying = 1;
-       if (sc->sc_intrpipe)
+       if (sc->sc_intrpipe != NULL)
                usbd_abort_pipe(sc->sc_intrpipe);
 
        if (sc->sc_state & UHID_OPEN) {
@@ -296,20 +310,32 @@ USB_DETACH(uhid)
 
        free(sc->sc_repdesc, M_USBDEV);
 
+       usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
+                          USBDEV(sc->sc_dev));
+
        return (0);
 }
 
 void
-uhid_intr(reqh, addr, status)
-       usbd_request_handle reqh;
+uhid_intr(xfer, addr, status)
+       usbd_xfer_handle xfer;
        usbd_private_handle addr;
        usbd_status status;
 {
        struct uhid_softc *sc = addr;
 
-       DPRINTFN(5, ("uhid_intr: status=%d\n", status));
-       DPRINTFN(5, ("uhid_intr: data = %02x %02x %02x\n",
-                    sc->sc_ibuf[0], sc->sc_ibuf[1], sc->sc_ibuf[2]));
+#ifdef UHID_DEBUG
+       if (uhiddebug > 5) {
+               u_int32_t cc, i;
+
+               usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL);
+               DPRINTF(("uhid_intr: status=%d cc=%d\n", status, cc));
+               DPRINTF(("uhid_intr: data="));
+               for (i = 0; i < cc; i++)
+                       DPRINTF((" %02x", sc->sc_ibuf[i]));
+               DPRINTF(("\n"));
+       }
+#endif
 
        if (status == USBD_CANCELLED)
                return;
@@ -338,7 +364,7 @@ uhidopen(dev, flag, mode, p)
        struct proc *p;
 {
        struct uhid_softc *sc;
-       usbd_status r;
+       usbd_status err;
 
        USB_GET_SC_OPEN(uhid, UHIDUNIT(dev), sc);
 
@@ -360,13 +386,12 @@ uhidopen(dev, flag, mode, p)
        sc->sc_obuf = malloc(sc->sc_osize, M_USBDEV, M_WAITOK);
 
        /* Set up interrupt pipe. */
-       r = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr, 
-                               USBD_SHORT_XFER_OK,
-                               &sc->sc_intrpipe, sc, sc->sc_ibuf, 
-                               sc->sc_isize, uhid_intr);
-       if (r != USBD_NORMAL_COMPLETION) {
+       err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr, 
+           USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc, sc->sc_ibuf,
+           sc->sc_isize, uhid_intr, USBD_DEFAULT_INTERVAL);
+       if (err) {
                DPRINTF(("uhidopen: usbd_open_pipe_intr failed, "
-                        "error=%d\n",r));
+                        "error=%d\n",err));
                free(sc->sc_ibuf, M_USBDEV);
                free(sc->sc_obuf, M_USBDEV);
                sc->sc_state &= ~UHID_OPEN;
@@ -416,15 +441,15 @@ uhid_do_read(sc, uio, flag)
        int error = 0;
        size_t length;
        u_char buffer[UHID_CHUNK];
-       usbd_status r;
+       usbd_status err;
 
        DPRINTFN(1, ("uhidread\n"));
        if (sc->sc_state & UHID_IMMED) {
                DPRINTFN(1, ("uhidread immed\n"));
                
-               r = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT,
+               err = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT,
                                    sc->sc_iid, buffer, sc->sc_isize);
-               if (r != USBD_NORMAL_COMPLETION)
+               if (err)
                        return (EIO);
                return (uiomove(buffer, sc->sc_isize, uio));
        }
@@ -461,7 +486,7 @@ uhid_do_read(sc, uio, flag)
 
                /* Remove a small chunk from the input queue. */
                (void) q_to_b(&sc->sc_q, buffer, length);
-               DPRINTFN(5, ("uhidread: got %d chars\n", length));
+               DPRINTFN(5, ("uhidread: got %lu chars\n", (u_long)length));
 
                /* Copy the data to the user process. */
                if ((error = uiomove(buffer, length, uio)) != 0)
@@ -497,7 +522,7 @@ uhid_do_write(sc, uio, flag)
 {
        int error;
        int size;
-       usbd_status r;
+       usbd_status err;
 
        DPRINTFN(1, ("uhidwrite\n"));
        
@@ -511,15 +536,13 @@ uhid_do_write(sc, uio, flag)
        error = uiomove(sc->sc_obuf, size, uio);
        if (!error) {
                if (sc->sc_oid)
-                       r = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT,
-                                           sc->sc_obuf[0], 
-                                           sc->sc_obuf+1, size-1);
+                       err = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT,
+                           sc->sc_obuf[0], sc->sc_obuf+1, size-1);
                else
-                       r = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT,
-                                           0, sc->sc_obuf, size);
-               if (r != USBD_NORMAL_COMPLETION) {
+                       err = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT,
+                           0, sc->sc_obuf, size);
+               if (err)
                        error = EIO;
-               }
        }
 
        return (error);
@@ -554,7 +577,7 @@ uhid_do_ioctl(sc, cmd, addr, flag, p)
        struct usb_ctl_report_desc *rd;
        struct usb_ctl_report *re;
        int size, id;
-       usbd_status r;
+       usbd_status err;
 
        DPRINTFN(2, ("uhidioctl: cmd=%lx\n", cmd));
 
@@ -575,11 +598,10 @@ uhid_do_ioctl(sc, cmd, addr, flag, p)
 
        case USB_SET_IMMED:
                if (*(int *)addr) {
-                       /* XXX should read into ibuf, but does it matter */
-                       r = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT,
-                                           sc->sc_iid, sc->sc_ibuf, 
-                                           sc->sc_isize);
-                       if (r != USBD_NORMAL_COMPLETION)
+                       /* XXX should read into ibuf, but does it matter? */
+                       err = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT,
+                           sc->sc_iid, sc->sc_ibuf, sc->sc_isize);
+                       if (err)
                                return (EOPNOTSUPP);
 
                        sc->sc_state |=  UHID_IMMED;
@@ -605,9 +627,32 @@ uhid_do_ioctl(sc, cmd, addr, flag, p)
                default:
                        return (EINVAL);
                }
-               r = usbd_get_report(sc->sc_iface, re->report, id, 
-                                   re->data, size);
-               if (r != USBD_NORMAL_COMPLETION)
+               err = usbd_get_report(sc->sc_iface, re->report, id, re->data,
+                   size);
+               if (err)
+                       return (EIO);
+               break;
+       case USB_SET_REPORT:
+               re = (struct usb_ctl_report *)addr;
+               switch (re->report) {
+               case UHID_INPUT_REPORT:
+                       size = sc->sc_isize;
+                       id = sc->sc_iid;
+                       break;
+               case UHID_OUTPUT_REPORT:
+                       size = sc->sc_osize;
+                       id = sc->sc_oid;
+                       break;
+               case UHID_FEATURE_REPORT:
+                       size = sc->sc_fsize;
+                       id = sc->sc_fid;
+                       break;
+               default:
+                       return (EINVAL);
+               }
+               err = usbd_set_report(sc->sc_iface, re->report, id, re->data,
+                   size);
+               if (err)
                        return (EIO);
                break;
 
@@ -667,6 +712,5 @@ uhidpoll(dev, events, p)
 }
 
 #if defined(__FreeBSD__)
-DEV_DRIVER_MODULE(uhid, uhub, uhid_driver, uhid_devclass, 
-                 uhid_cdevsw, usbd_driver_load, 0);
+DRIVER_MODULE(uhid, uhub, uhid_driver, uhid_devclass, usbd_driver_load, 0);
 #endif
index 517d48a..4ba332e 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: uhub.c,v 1.6 1999/11/07 21:30:19 fgsch Exp $  */
-/*     $NetBSD: uhub.c,v 1.32 1999/10/13 08:10:56 augustss Exp $       */
+/*     $OpenBSD: uhub.c,v 1.7 2000/03/26 08:39:46 aaron Exp $  */
+/*     $NetBSD: uhub.c,v 1.40 2000/02/29 21:37:01 augustss Exp $       */
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
 #include <sys/malloc.h>
 #if defined(__NetBSD__) || defined(__OpenBSD__)
 #include <sys/device.h>
+#include <sys/proc.h>
 #elif defined(__FreeBSD__)
 #include <sys/module.h>
 #include <sys/bus.h>
 #include "bus_if.h"
 #endif
-#include <sys/proc.h>
 
 #include <machine/bus.h>
 
@@ -63,9 +63,9 @@
 #include <dev/usb/usbdivar.h>
 
 #ifdef UHUB_DEBUG
-#define DPRINTF(x)     if (usbdebug) logprintf x
-#define DPRINTFN(n,x)  if (usbdebug>(n)) logprintf x
-extern int     usbdebug;
+#define DPRINTF(x)     if (uhubdebug) logprintf x
+#define DPRINTFN(n,x)  if (uhubdebug>(n)) logprintf x
+int    uhubdebug;
 #else
 #define DPRINTF(x)
 #define DPRINTFN(n,x)
@@ -81,15 +81,12 @@ struct uhub_softc {
 
 usbd_status uhub_init_port __P((struct usbd_port *));
 usbd_status uhub_explore __P((usbd_device_handle hub));
-void uhub_intr __P((usbd_request_handle, usbd_private_handle, usbd_status));
+void uhub_intr __P((usbd_xfer_handle, usbd_private_handle, usbd_status));
 
 #if defined(__FreeBSD__)
 static bus_child_detached_t uhub_child_detached;
 #endif
 
-USB_DECLARE_DRIVER_INIT(uhub, 
-                       DEVMETHOD(bus_child_detached, uhub_child_detached));
-
 /* 
  * We need two attachment points:
  * hub to usb and hub to hub
@@ -97,12 +94,17 @@ USB_DECLARE_DRIVER_INIT(uhub,
  */
 
 #if defined(__NetBSD__) || defined(__OpenBSD__)
+USB_DECLARE_DRIVER(uhub);
+
 /* Create the driver instance for the hub connected to hub case */
 struct cfattach uhub_uhub_ca = {
        sizeof(struct uhub_softc), uhub_match, uhub_attach,
        uhub_detach, uhub_activate
 };
 #elif defined(__FreeBSD__)
+USB_DECLARE_DRIVER_INIT(uhub.
+                       DEVMETHOD(bus_child_detached, uhub_child_detached));
+
 /* Create the driver instance for the hub connected to usb case. */
 devclass_t uhubroot_devclass;
 
@@ -131,7 +133,7 @@ USB_MATCH(uhub)
         * The subclass for hubs seems to be 0 for some and 1 for others,
         * so we just ignore the subclass.
         */
-       if (uaa->iface == 0 && dd->bDeviceClass == UCLASS_HUB)
+       if (uaa->iface == NULL && dd->bDeviceClass == UDCLASS_HUB)
                return (UMATCH_DEVCLASS_DEVSUBCLASS);
        return (UMATCH_NONE);
 }
@@ -141,7 +143,7 @@ USB_ATTACH(uhub)
        USB_ATTACH_START(uhub, sc, uaa);
        usbd_device_handle dev = uaa->device;
        char devinfo[1024];
-       usbd_status r;
+       usbd_status err;
        struct usbd_hub *hub;
        usb_device_request_t req;
        usb_hub_descriptor_t hubdesc;
@@ -155,10 +157,10 @@ USB_ATTACH(uhub)
        USB_ATTACH_SETUP;
        printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
 
-       r = usbd_set_config_index(dev, 0, 1);
-       if (r != USBD_NORMAL_COMPLETION) {
+       err = usbd_set_config_index(dev, 0, 1);
+       if (err) {
                DPRINTF(("%s: configuration failed, error=%s\n",
-                        USBDEVNAME(sc->sc_dev), usbd_errstr(r)));
+                        USBDEVNAME(sc->sc_dev), usbd_errstr(err)));
                USB_ATTACH_ERROR_RETURN;
        }
 
@@ -175,15 +177,15 @@ USB_ATTACH(uhub)
        USETW(req.wIndex, 0);
        USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE);
        DPRINTFN(1,("usb_init_hub: getting hub descriptor\n"));
-       r = usbd_do_request(dev, &req, &hubdesc);
+       err = usbd_do_request(dev, &req, &hubdesc);
        nports = hubdesc.bNbrPorts;
-       if (r == USBD_NORMAL_COMPLETION && nports > 7) {
+       if (!err && nports > 7) {
                USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE + (nports+1) / 8);
-               r = usbd_do_request(dev, &req, &hubdesc);
+               err = usbd_do_request(dev, &req, &hubdesc);
        }
-       if (r != USBD_NORMAL_COMPLETION) {
+       if (err) {
                DPRINTF(("%s: getting hub descriptor failed, error=%s\n",
-                        USBDEVNAME(sc->sc_dev), usbd_errstr(r)));
+                        USBDEVNAME(sc->sc_dev), usbd_errstr(err)));
                USB_ATTACH_ERROR_RETURN;
        }
 
@@ -196,7 +198,7 @@ USB_ATTACH(uhub)
 
        hub = malloc(sizeof(*hub) + (nports-1) * sizeof(struct usbd_port),
                     M_USBDEV, M_NOWAIT);
-       if (hub == 0)
+       if (hub == NULL)
                USB_ATTACH_ERROR_RETURN;
        dev->hub = hub;
        dev->hub->hubsoftc = sc;
@@ -209,7 +211,7 @@ USB_ATTACH(uhub)
                 dev->powersrc->parent ? 
                 dev->powersrc->parent->self_powered : 0));
 
-       if (!dev->self_powered && dev->powersrc->parent &&
+       if (!dev->self_powered && dev->powersrc->parent != NULL &&
            !dev->powersrc->parent->self_powered) {
                printf("%s: bus powered hub connected to bus powered hub, "
                       "ignored\n", USBDEVNAME(sc->sc_dev));
@@ -217,13 +219,13 @@ USB_ATTACH(uhub)
        }
 
        /* Set up interrupt pipe. */
-       r = usbd_device2interface_handle(dev, 0, &iface);
-       if (r != USBD_NORMAL_COMPLETION) {
+       err = usbd_device2interface_handle(dev, 0, &iface);
+       if (err) {
                printf("%s: no interface handle\n", USBDEVNAME(sc->sc_dev));
                goto bad;
        }
        ed = usbd_interface2endpoint_descriptor(iface, 0);
-       if (ed == 0) {
+       if (ed == NULL) {
                printf("%s: no endpoint descriptor\n", USBDEVNAME(sc->sc_dev));
                goto bad;
        }
@@ -232,11 +234,10 @@ USB_ATTACH(uhub)
                goto bad;
        }
 
-       r = usbd_open_pipe_intr(iface, ed->bEndpointAddress,USBD_SHORT_XFER_OK,
-                               &sc->sc_ipipe, sc, sc->sc_status, 
-                               sizeof(sc->sc_status),
-                               uhub_intr);
-       if (r != USBD_NORMAL_COMPLETION) {
+       err = usbd_open_pipe_intr(iface, ed->bEndpointAddress,
+           USBD_SHORT_XFER_OK, &sc->sc_ipipe, sc, sc->sc_status,
+           sizeof(sc->sc_status), uhub_intr, USBD_DEFAULT_INTERVAL);
+       if (err) {
                printf("%s: cannot open interrupt pipe\n", 
                       USBDEVNAME(sc->sc_dev));
                goto bad;
@@ -245,15 +246,17 @@ USB_ATTACH(uhub)
        /* Wait with power off for a while. */
        usbd_delay_ms(dev, USB_POWER_DOWN_TIME);
 
+       usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, dev, USBDEV(sc->sc_dev));
+
        for (p = 0; p < nports; p++) {
                struct usbd_port *up = &hub->ports[p];
                up->device = 0;
                up->parent = dev;
                up->portno = p+1;
-               r = uhub_init_port(up);
-               if (r != USBD_NORMAL_COMPLETION)
+               err = uhub_init_port(up);
+               if (err)
                        printf("%s: init of port %d failed\n", 
-                              USBDEVNAME(sc->sc_dev), up->portno);
+                           USBDEVNAME(sc->sc_dev), up->portno);
        }
        sc->sc_running = 1;
 
@@ -271,12 +274,12 @@ uhub_init_port(up)
 {
        int port = up->portno;
        usbd_device_handle dev = up->parent;
-       usbd_status r;
+       usbd_status err;
        u_int16_t pstatus;
 
-       r = usbd_get_port_status(dev, port, &up->status);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = usbd_get_port_status(dev, port, &up->status);
+       if (err)
+               return (err);
        pstatus = UGETW(up->status.wPortStatus);
        DPRINTF(("usbd_init_port: adding hub port=%d status=0x%04x "
                 "change=0x%04x\n",
@@ -287,15 +290,10 @@ uhub_init_port(up)
                /* First let the device go through a good power cycle, */
                usbd_delay_ms(dev, USB_PORT_POWER_DOWN_TIME);
 
-#if 0
-usbd_clear_hub_feature(dev, UHF_C_HUB_OVER_CURRENT);
-usbd_clear_port_feature(dev, port, UHF_C_PORT_OVER_CURRENT);
-#endif
-
                /* then turn the power on. */
-               r = usbd_set_port_feature(dev, port, UHF_PORT_POWER);
-               if (r != USBD_NORMAL_COMPLETION)
-                       return (r);
+               err = usbd_set_port_feature(dev, port, UHF_PORT_POWER);
+               if (err)
+                       return (err);
                DPRINTF(("usb_init_port: turn on port %d power status=0x%04x "
                         "change=0x%04x\n",
                         port, UGETW(up->status.wPortStatus),
@@ -304,9 +302,9 @@ usbd_clear_port_feature(dev, port, UHF_C_PORT_OVER_CURRENT);
                usbd_delay_ms(dev, dev->hub->hubdesc.bPwrOn2PwrGood * 
                                   UHD_PWRON_FACTOR);
                /* Get the port status again. */
-               r = usbd_get_port_status(dev, port, &up->status);
-               if (r != USBD_NORMAL_COMPLETION)
-                       return (r);
+               err = usbd_get_port_status(dev, port, &up->status);
+               if (err)
+                       return (err);
                DPRINTF(("usb_init_port: after power on status=0x%04x "
                         "change=0x%04x\n",
                         UGETW(up->status.wPortStatus),
@@ -339,7 +337,7 @@ uhub_explore(dev)
        usb_hub_descriptor_t *hd = &dev->hub->hubdesc;
        struct uhub_softc *sc = dev->hub->hubsoftc;
        struct usbd_port *up;
-       usbd_status r;
+       usbd_status err;
        int port;
        int change, status;
 
@@ -354,17 +352,16 @@ uhub_explore(dev)
 
        for(port = 1; port <= hd->bNbrPorts; port++) {
                up = &dev->hub->ports[port-1];
-               r = usbd_get_port_status(dev, port, &up->status);
-               if (r != USBD_NORMAL_COMPLETION) {
+               err = usbd_get_port_status(dev, port, &up->status);
+               if (err) {
                        DPRINTF(("uhub_explore: get port status failed, "
-                                "error=%s\n",
-                                usbd_errstr(r)));
+                                "error=%s\n", usbd_errstr(err)));
                        continue;
                }
                status = UGETW(up->status.wPortStatus);
                change = UGETW(up->status.wPortChange);
-               DPRINTFN(5, ("uhub_explore: port %d status 0x%04x 0x%04x\n",
-                            port, status, change));
+               DPRINTFN(3,("uhub_explore: port %d status 0x%04x 0x%04x\n",
+                           port, status, change));
                if (change & UPS_C_PORT_ENABLED) {
                        usbd_clear_port_feature(dev, port, UHF_C_PORT_ENABLE);
                        if (status & UPS_PORT_ENABLED) {
@@ -385,6 +382,8 @@ uhub_explore(dev)
                        }
                }
                if (!(change & UPS_C_CONNECT_STATUS)) {
+                       DPRINTFN(3,("uhub_explore: port=%d !C_CONNECT_"
+                                   "STATUS\n", port));
                        /* No status change, just do recursive explore. */
                        if (up->device && up->device->hub)
                                up->device->hub->explore(up->device);
@@ -402,16 +401,19 @@ uhub_explore(dev)
                 * the disconnect.
                 */
        disco:
-               if (up->device) {
+               if (up->device != NULL) {
                        /* Disconnected */
-                       DPRINTF(("uhub_explore: device %d disappeared "
+                       DPRINTF(("uhub_explore: device addr=%d disappeared "
                                 "on port %d\n", up->device->address, port));
                        usb_disconnect_port(up, USBDEV(sc->sc_dev));
                        usbd_clear_port_feature(dev, port, 
                                                UHF_C_PORT_CONNECTION);
                }
-               if (!(status & UPS_CURRENT_CONNECT_STATUS))
+               if (!(status & UPS_CURRENT_CONNECT_STATUS)) {
+                       DPRINTFN(3,("uhub_explore: port=%d !CURRENT_CONNECT"
+                                   "_STATUS\n", port));
                        continue;
+               }
 
                /* Connected */
                up->restartcnt = 0;
@@ -420,18 +422,20 @@ uhub_explore(dev)
                usbd_delay_ms(dev, USB_PORT_POWERUP_DELAY);
 
                /* Reset port, which implies enabling it. */
-               if (usbd_reset_port(dev, port, &up->status) != 
-                   USBD_NORMAL_COMPLETION)
+               if (usbd_reset_port(dev, port, &up->status)) {
+                       DPRINTF(("uhub_explore: port=%d reset failed\n",
+                                port));
                        continue;
+               }
 
                /* Get device info and set its address. */
-               r = usbd_new_device(USBDEV(sc->sc_dev), dev->bus, 
+               err = usbd_new_device(USBDEV(sc->sc_dev), dev->bus, 
                                    dev->depth + 1, status & UPS_LOW_SPEED, 
                                    port, up);
                /* XXX retry a few times? */
-               if (r != USBD_NORMAL_COMPLETION) {
+               if (err) {
                        DPRINTFN(-1,("uhub_explore: usb_new_device failed, "
-                                    "error=%s\n", usbd_errstr(r)));
+                                    "error=%s\n", usbd_errstr(err)));
                        /* Avoid addressing problems by disabling. */
                        /* usbd_reset_port(dev, port, &up->status); */
 
@@ -460,8 +464,9 @@ uhub_activate(self, act)
        enum devact act;
 {
        struct uhub_softc *sc = (struct uhub_softc *)self;
-       usbd_device_handle devhub = sc->sc_hub;
-       int nports, p, i;
+       struct usbd_hub *hub = sc->sc_hub->hub;
+       usbd_device_handle dev;
+       int nports, port, i;
 
        switch (act) {
        case DVACT_ACTIVATE:
@@ -469,10 +474,12 @@ uhub_activate(self, act)
                break;
 
        case DVACT_DEACTIVATE:
-               nports = devhub->hub->hubdesc.bNbrPorts;
-               for(p = 0; p < nports; p++) {
-                       usbd_device_handle dev = devhub->hub->ports[p].device;
-                       if (dev) {
+               if (hub == NULL) /* malfunctioning hub */
+                       break;
+               nports = hub->hubdesc.bNbrPorts;
+               for(port = 0; port < nports; port++) {
+                       dev = hub->ports[port].device;
+                       if (dev != NULL) {
                                for (i = 0; dev->subdevs[i]; i++)
                                        config_deactivate(dev->subdevs[i]);
                        }
@@ -490,7 +497,7 @@ uhub_activate(self, act)
 USB_DETACH(uhub)
 {
        USB_DETACH_START(uhub, sc);
-       usbd_device_handle dev = sc->sc_hub;
+       struct usbd_hub *hub = sc->sc_hub->hub;
        struct usbd_port *rup;
        int port, nports;
 
@@ -500,25 +507,61 @@ USB_DETACH(uhub)
        DPRINTF(("uhub_detach: sc=%port\n", sc));
 #endif
 
-       if (!dev->hub)          /* Must be partially working */
+       if (hub == NULL)                /* Must be partially working */
                return (0);
 
        usbd_abort_pipe(sc->sc_ipipe);
        usbd_close_pipe(sc->sc_ipipe);
 
-       nports = dev->hub->hubdesc.bNbrPorts;
+       nports = hub->hubdesc.bNbrPorts;
        for(port = 0; port < nports; port++) {
-               rup = &dev->hub->ports[port];
+               rup = &hub->ports[port];
                if (rup->device)
                        usb_disconnect_port(rup, self);
        }
+
+       usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_hub,
+                          USBDEV(sc->sc_dev));
        
-       free(dev->hub, M_USBDEV);
-       dev->hub = 0;
+       free(hub, M_USBDEV);
+       sc->sc_hub->hub = NULL;
 
        return (0);
 }
 
+#if defined(__FreeBSD__)
+/* Called when a device has been detached from it */
+static void
+uhub_child_detached(self, child)
+       device_t self;
+       device_t child;
+{
+       struct uhub_softc *sc = device_get_softc(self);
+       usbd_device_handle devhub = sc->sc_hub;
+       usbd_device_handle dev;
+       int nports;
+       int port;
+       int i;
+
+       if (!devhub->hub)
+               /* should never happen; children are only created after init */
+               panic("hub not fully initialised, but child deleted?");
+
+       nports = devhub->hub->hubdesc.bNbrPorts;
+       for (port = 0; port < nports; port++) {
+               dev = devhub->hub->ports[port].device;
+               if (dev && dev->subdevs) {
+                       for (i = 0; dev->subdevs[i]; i++) {
+                               if (dev->subdevs[i] == child) {
+                                       dev->subdevs[i] = NULL;
+                                       return;
+                               }
+                       }
+               }
+       }
+}
+#endif
+
 /*
  * Hub interrupt.
  * This an indication that some port has changed status.
@@ -526,8 +569,8 @@ USB_DETACH(uhub)
  * to be explored again.
  */
 void
-uhub_intr(reqh, addr, status)
-       usbd_request_handle reqh;
+uhub_intr(xfer, addr, status)
+       usbd_xfer_handle xfer;
        usbd_private_handle addr;
        usbd_status status;
 {
index e23f43d..22a3b37 100644 (file)
@@ -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.
 #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__)
index 1e5ebea..1878d44 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: usb.h,v 1.6 1999/11/07 21:30:19 fgsch Exp $   */
-/*     $NetBSD: usb.h,v 1.38 1999/10/20 21:02:39 augustss Exp $        */
+/*     $OpenBSD: usb.h,v 1.7 2000/03/26 08:39:46 aaron Exp $   */
+/*     $NetBSD: usb.h,v 1.42 2000/03/19 22:23:28 augustss Exp $        */
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -335,54 +335,78 @@ typedef struct {
 #define UPS_C_PORT_RESET               0x0010
 } usb_port_status_t;
 
-#define UCLASS_UNSPEC          0
-#define UCLASS_AUDIO           1
-#define  USUBCLASS_AUDIOCONTROL        1
-#define  USUBCLASS_AUDIOSTREAM 2
-#define  USUBCLASS_MIDISTREAM  3
-#define UCLASS_CDC             2 /* communication */
-#define         USUBCLASS_DIRECT_LINE_CONTROL_MODEL    1
-#define  USUBCLASS_ABSTRACT_CONTROL_MODEL      2
-#define         USUBCLASS_TELEPHONE_CONTROL_MODEL      3
-#define         USUBCLASS_MULTICHANNEL_CONTROL_MODEL   4
-#define         USUBCLASS_CAPI_CONTROLMODEL            5
-#define         USUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6
-#define         USUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7
-#define   UPROTO_CDC_AT                1
-#define UCLASS_HID             3
-#define  USUBCLASS_BOOT                1
-#define UCLASS_PRINTER         7
-#define  USUBCLASS_PRINTER     1
-#define  UPROTO_PRINTER_UNI    1
-#define  UPROTO_PRINTER_BI     2
-#define UCLASS_MASS            8
-#define  USUBCLASS_RBC         1
-#define  USUBCLASS_SFF8020I    2
-#define  USUBCLASS_QIC157      3
-#define  USUBCLASS_UFI         4
-#define  USUBCLASS_SFF8070I    5
-#define  USUBCLASS_SCSI                6
-#define  UPROTO_MASS_CBI_I     0
-#define  UPROTO_MASS_CBI       1
-#define  UPROTO_MASS_BULK      2
-#define  UPROTO_MASS_BULK_P    80
-#define UCLASS_HUB             9
-#define  USUBCLASS_HUB         0
-#define UCLASS_DATA            10
-#define  USUBCLASS_DATA                0
-#define   UPROTO_DATA_ISDNBRI          0x30    /* Physical iface */
-#define   UPROTO_DATA_HDLC             0x31    /* HDLC */
-#define   UPROTO_DATA_TRANSPARENT      0x32    /* Transparent */
-#define   UPROTO_DATA_Q921M            0x50    /* Management for Q921 */
-#define   UPROTO_DATA_Q921             0x51    /* Data for Q921 */
-#define   UPROTO_DATA_Q921TM           0x52    /* TEI multiplexer for Q921 */
-#define   UPROTO_DATA_V42BIS           0x90    /* Data compression */  
-#define   UPROTO_DATA_Q931             0x91    /* Euro-ISDN */
-#define   UPROTO_DATA_V120             0x92    /* V.24 rate adaption */
-#define   UPROTO_DATA_CAPI             0x93    /* CAPI 2.0 commands */
-#define   UPROTO_DATA_HOST_BASED       0xfd    /* Host based driver */
-#define   UPROTO_DATA_PUF              0xfe    /* see Prot. Unit Func. Desc.*/
-#define   UPROTO_DATA_VENDOR           0xff    /* Vendor specific */
+/* Device class codes */
+#define UDCLASS_AUDIO                  0x00
+#define UDCLASS_COMM                   0x02
+#define UDCLASS_HID                    0x00
+#define UDCLASS_HUB                    0x09
+#define        UDSUBCLASS_HUB                  0
+#define UDCLASS_MASS                   0x00
+
+/* Interface class codes */
+#define UICLASS_UNSPEC                 0x00
+
+#define UICLASS_AUDIO                  0x01
+#define        UISUBCLASS_AUDIOCONTROL         1
+#define        UISUBCLASS_AUDIOSTREAM          2
+#define        UISUBCLASS_MIDISTREAM           3
+
+#define UICLASS_CDC                    0x02 /* communication */
+#define        UI_SUBCLASS_DIRECT_LINE_CONTROL_MODEL           1
+#define        UI_SUBCLASS_ABSTRACT_CONTROL_MODEL              2
+#define        UI_SUBCLASS_TELEPHONE_CONTROL_MODEL             3
+#define        UI_SUBCLASS_MULTICHANNEL_CONTROL_MODEL          4
+#define        UI_SUBCLASS_CAPI_CONTROL_MODEL                  5
+#define        UI_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL   6
+#define        UI_SUBCLASS_ATM_NETWORKING_CONTROL_MODEL        7
+#define        UIPROTO_CDC_AT                  1
+
+#define UICLASS_HID                    0x03
+#define        UI_SUBCLASS_BOOT                1
+#define        UIPROTO_BOOT_KEYBOARD           1
+
+#define UICLASS_PHYSICAL               0x05
+
+#define UICLASS_PRINTER                        0x07
+#define UISUBCLASS_PRINTER             1
+#define UIPROTO_PRINTER_UNI            1
+#define UIPROTO_PRINTER_BI             2
+
+#define UICLASS_MASS                   0x08
+#define        UISUBCLASS_RBC                  1
+#define        UISUBCLASS_SFF8020I             2
+#define        UISUBCLASS_QIC157               3
+#define        UISUBCLASS_UFI                  4
+#define        UISUBCLASS_SFF8070I             5
+#define        UISUBCLASS_SCSI                 6
+#define        UIPROTO_MASS_CBI_I              0
+#define        UIPROTO_MASS_CBI                1
+#define        UIPROTO_MASS_BULK               2
+#define        UIPROTO_MASS_BULK_P             80
+
+#define        UICLASS_HUB                     0x09
+#define UISUBCLASS_HUB                 0
+
+#define UICLASS_CDC_DATA               0x0a
+#define UISUBCLASS_DATA                        0
+#define UIPROTO_DATA_ISDNBRI           0x30
+#define        UIPROTO_DATA_HDLC               0x31
+#define UIPROTO_DATA_TRANSPARENT       0x32
+#define UIPROTO_DATA_Q921M             0x50
+#define UIPROTO_DATA_Q921              0x51
+#define UIPROTO_DATA_Q921TM            0x52
+#define UIPROTO_DATA_V42BIS            0x90
+#define UIPROTO_DATA_Q931              0x91
+#define UIPROTO_DATA_V120              0x92
+#define UIPROTO_DATA_CAPI              0x93
+#define UIPROTO_DATA_HOST_BASED                0xfd
+#define UIPROTO_DATA_PUF               0xfe
+#define UIPROTO_DATA_VENDOR            0xff
+
+#define UICLASS_FIRM_UPD               0x0c
+
+#define UICLASS_APPL_SPEC              0xfe
+#define UICLASS_VENDOR                 0xff
 
 
 #define USB_HUB_MAX_DEPTH 5
@@ -476,18 +500,28 @@ struct usb_ctl_report_desc {
        u_char  data[1024];     /* filled data size will vary */
 };
 
+typedef struct { u_int32_t cookie; } usb_event_cookie_t;
+
+#define USB_MAX_DEVNAMES 4
+#define USB_MAX_DEVNAMELEN 16
 struct usb_device_info {
+       u_int8_t        bus;
        u_int8_t        addr;   /* device address */
+       usb_event_cookie_t cookie;
        char            product[USB_MAX_STRING_LEN];
        char            vendor[USB_MAX_STRING_LEN];
        char            release[8];
        u_int16_t       productNo;
        u_int16_t       vendorNo;
+       u_int16_t       releaseNo;
        u_int8_t        class;
+       u_int8_t        subclass;
+       u_int8_t        protocol;
        u_int8_t        config;
        u_int8_t        lowspeed;
        int             power;  /* power consumption in mA, 0 if selfpowered */
        int             nports;
+       char            devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN];
        u_int8_t        ports[16];/* hub only: addresses of devices on ports */
 #define USB_PORT_ENABLED 0xff
 #define USB_PORT_SUSPENDED 0xfe
@@ -504,15 +538,26 @@ struct usb_device_stats {
        u_long  requests[4];    /* indexed by transfer type UE_* */
 };
 
-typedef struct { u_int32_t cookie; } usb_event_cookie_t;
 /* Events that can be read from /dev/usb */
 struct usb_event {
        int                     ue_type;
-#define USB_EVENT_ATTACH 1
-#define USB_EVENT_DETACH 2
-       struct usb_device_info  ue_device;
+#define USB_EVENT_CTRLR_ATTACH 1
+#define USB_EVENT_CTRLR_DETACH 2
+#define USB_EVENT_DEVICE_ATTACH 3
+#define USB_EVENT_DEVICE_DETACH 4
+#define USB_EVENT_DRIVER_ATTACH 5
+#define USB_EVENT_DRIVER_DETACH 6
        struct timespec         ue_time;
-       usb_event_cookie_t      ue_cookie;
+       union {
+               struct {
+                       int                     ue_bus;
+               } ue_ctrlr;
+               struct usb_device_info          ue_device;
+               struct {
+                       usb_event_cookie_t      ue_cookie;
+                       char                    ue_devname[USB_MAX_DEVNAMELEN];
+               } ue_driver;
+       } u;
 };
 
 /* USB controller */
@@ -526,6 +571,7 @@ struct usb_event {
 #define USB_GET_REPORT_DESC    _IOR ('U', 21, struct usb_ctl_report_desc)
 #define USB_SET_IMMED          _IOW ('U', 22, int)
 #define USB_GET_REPORT         _IOWR('U', 23, struct usb_ctl_report)
+#define USB_SET_REPORT         _IOW ('U', 24, struct usb_ctl_report)
 
 /* Generic USB device */
 #define USB_GET_CONFIG         _IOR ('U', 100, int)
index 06be4c7..df3bdf1 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: usb_mem.c,v 1.6 1999/11/07 21:30:19 fgsch Exp $       */
-/*     $NetBSD: usb_mem.c,v 1.15 1999/10/12 11:24:22 augustss Exp $    */
+/*     $OpenBSD: usb_mem.c,v 1.7 2000/03/26 08:39:46 aaron Exp $       */
+/*     $NetBSD: usb_mem.c,v 1.17 1999/12/18 22:47:11 augustss Exp $    */
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -103,7 +103,8 @@ usb_block_allocmem(tag, size, align, dmap)
         usb_dma_block_t *p;
        int s;
 
-       DPRINTFN(5, ("usb_block_allocmem: size=%d align=%d\n", size, align));
+       DPRINTFN(5, ("usb_block_allocmem: size=%lu align=%lu\n",
+                    (u_long)size, (u_long)align));
 
 #ifdef DIAGNOSTIC
        if (!curproc) {
@@ -119,8 +120,8 @@ usb_block_allocmem(tag, size, align, dmap)
                        LIST_REMOVE(p, next);
                        splx(s);
                        *dmap = p;
-                       DPRINTFN(6,("usb_block_allocmem: free list size=%d\n",
-                                   p->size));
+                       DPRINTFN(6,("usb_block_allocmem: free list size=%lu\n",
+                                   (u_long)p->size));
                        return (USBD_NORMAL_COMPLETION);
                }
        }
@@ -135,7 +136,7 @@ usb_block_allocmem(tag, size, align, dmap)
 
        DPRINTFN(6, ("usb_block_allocmem: no free\n"));
        p = malloc(sizeof *p, M_USB, M_NOWAIT);
-       if (p == 0)
+       if (p == NULL)
                return (USBD_NOMEM);
        *dmap = p;
 
@@ -162,7 +163,7 @@ usb_block_allocmem(tag, size, align, dmap)
                                BUS_DMA_NOWAIT);
        if (error)
                goto destroy;
-       return 0;
+       return (USBD_NORMAL_COMPLETION);
 
 destroy:
        bus_dmamap_destroy(tag, p->map);
@@ -203,7 +204,7 @@ usb_block_freemem(p)
 {
        int s;
 
-       DPRINTFN(6, ("usb_block_freemem: size=%d\n", p->size));
+       DPRINTFN(6, ("usb_block_freemem: size=%lu\n", (u_long)p->size));
        s = splusb();
        LIST_INSERT_HEAD(&usb_blk_freelist, p, next);
        splx(s);
@@ -217,7 +218,7 @@ usb_allocmem(bus, size, align, p)
         usb_dma_t *p;
 {
        bus_dma_tag_t tag = bus->dmatag;
-       usbd_status r;
+       usbd_status err;
        struct usb_frag_dma *f;
        usb_dma_block_t *b;
        int i;
@@ -227,12 +228,12 @@ usb_allocmem(bus, size, align, p)
        if (size > USB_MEM_SMALL || align > USB_MEM_SMALL) {
                DPRINTFN(1, ("usb_allocmem: large alloc %d\n", (int)size));
                size = (size + USB_MEM_BLOCK - 1) & ~(USB_MEM_BLOCK - 1);
-               r = usb_block_allocmem(tag, size, align, &p->block);
-               if (r == USBD_NORMAL_COMPLETION) {
+               err = usb_block_allocmem(tag, size, align, &p->block);
+               if (!err) {
                        p->block->fullblock = 1;
                        p->offs = 0;
                }
-               return (r);
+               return (err);
        }
        
        s = splusb();
@@ -240,12 +241,12 @@ usb_allocmem(bus, size, align, p)
        for (f = LIST_FIRST(&usb_frag_freelist); f; f = LIST_NEXT(f, next))
                if (f->block->tag == tag)
                        break;
-       if (!f) {
+       if (f == NULL) {
                DPRINTFN(1, ("usb_allocmem: adding fragments\n"));
-               r = usb_block_allocmem(tag, USB_MEM_BLOCK, USB_MEM_SMALL, &b);
-               if (r != USBD_NORMAL_COMPLETION) {
+               err = usb_block_allocmem(tag, USB_MEM_BLOCK, USB_MEM_SMALL, &b);
+               if (err) {
                        splx(s);
-                       return (r);
+                       return (err);
                }
                b->fullblock = 0;
                for (i = 0; i < USB_MEM_BLOCK; i += USB_MEM_SMALL) {
index 0dca4f7..0e48fd4 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: usb_mem.h,v 1.4 1999/11/07 21:30:19 fgsch Exp $       */
-/*     $NetBSD: usb_mem.h,v 1.10 1999/10/13 18:52:54 augustss Exp $    */
+/*     $OpenBSD: usb_mem.h,v 1.5 2000/03/26 08:39:46 aaron Exp $       */
+/*     $NetBSD: usb_mem.h,v 1.12 2000/03/12 23:10:29 nathanw Exp $     */
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -51,7 +51,7 @@ typedef struct usb_dma_block {
        LIST_ENTRY(usb_dma_block) next;
 } usb_dma_block_t;
 
-#define DMAADDR(dma) ((dma)->block->segs[0].ds_addr + (dma)->offs)
+#define DMAADDR(dma) ((dma)->block->map->dm_segs[0].ds_addr + (dma)->offs)
 #define KERNADDR(dma) ((void *)((dma)->block->kaddr + (dma)->offs))
 
 usbd_status    usb_allocmem __P((usbd_bus_handle,size_t,size_t, usb_dma_t *));
index e5f69af..83a8f6b 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: usb_port.h,v 1.6 1999/11/07 21:30:19 fgsch Exp $      */
-/*     $NetBSD: usb_port.h,v 1.14 1999/10/14 01:18:39 augustss Exp $   */
+/*     $OpenBSD: usb_port.h,v 1.7 2000/03/26 08:39:46 aaron Exp $      */
+/*     $NetBSD: usb_port.h,v 1.21 2000/02/02 07:34:00 augustss Exp $   */
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
 #define UHCI_DEBUG 1
 #define UHUB_DEBUG 1
 #define ULPT_DEBUG 1
+#define UCOM_DEBUG 1
+#define UMODEM_DEBUG 1
 #define UAUDIO_DEBUG 1
+#define AUE_DEBUG 1
+#define CUE_DEBUG 1
+#define KUE_DEBUG 1
 #endif
 
 typedef struct device *device_ptr_t;
 #define USBBASEDEVICE struct device
 #define USBDEV(bdev) (&(bdev))
 #define USBDEVNAME(bdev) ((bdev).dv_xname)
+#define USBDEVUNIT(bdev) ((bdev).dv_unit)
 #define USBDEVPTRNAME(bdevptr) ((bdevptr)->dv_xname)
+#define USBGETSOFTC(d) ((void *)(d))
 
 #define DECLARE_USB_DMA_T \
        struct usb_dma_block; \
@@ -78,7 +85,7 @@ typedef struct device *device_ptr_t;
 
 #define logprintf printf
 
-#define USB_DECLARE_DRIVER_NAME_INIT(_1, dname, _2)  \
+#define USB_DECLARE_DRIVER_(dname)  \
 int __CONCAT(dname,_match) __P((struct device *, struct cfdata *, void *)); \
 void __CONCAT(dname,_attach) __P((struct device *, struct device *, void *)); \
 int __CONCAT(dname,_detach) __P((struct device *, int)); \
@@ -156,8 +163,15 @@ __CONCAT(dname,_detach)(self, flags) \
 #define UHCI_DEBUG 1
 #define UHUB_DEBUG 1
 #define ULPT_DEBUG 1
+#define UCOM_DEBUG 1
+#define UMODEM_DEBUG 1
+#define UAUDIO_DEBUG 1
+#define AUE_DEBUG 1
+#define CUE_DEBUG 1
+#define KUE_DEBUG 1
 #endif
 
+typedef struct device *device_ptr_t;
 #define        memcpy(d, s, l)         bcopy((s),(d),(l))
 #define        memset(d, v, l)         bzero((d),(l))
 #define bswap32(x)             swap32(x)
@@ -166,11 +180,12 @@ __CONCAT(dname,_detach)(self, flags) \
 #define        uhidpoll                uhidselect
 #define        ugenpoll                ugenselect
 
-typedef struct device *device_ptr_t;
 #define USBBASEDEVICE struct device
 #define USBDEV(bdev) (&(bdev))
 #define USBDEVNAME(bdev) ((bdev).dv_xname)
+#define USBDEVUNIT(bdev) ((bdev).dv_unit)
 #define USBDEVPTRNAME(bdevptr) ((bdevptr)->dv_xname)
+#define USBGETSOFTC(d) ((void *)(d))
 
 #define DECLARE_USB_DMA_T \
        struct usb_dma_block; \
@@ -182,8 +197,8 @@ typedef struct device *device_ptr_t;
 #define usb_timeout(f, d, t, h) timeout((f), (d), (t))
 #define usb_untimeout(f, d, h) untimeout((f), (d))
 
-#define USB_DECLARE_DRIVER_NAME_INIT(_1, dname, _2)  \
-int __CONCAT(dname,_match) __P((struct device *, void *, void *)); \
+#define USB_DECLARE_DRIVER(dname)  \
+int __CONCAT(dname,_match)  __P((struct device *, void *, void *)); \
 void __CONCAT(dname,_attach) __P((struct device *, struct device *, void *)); \
 int __CONCAT(dname,_detach) __P((struct device *, int)); \
 int __CONCAT(dname,_activate) __P((struct device *, enum devact)); \
@@ -260,10 +275,13 @@ __CONCAT(dname,_detach)(self, flags) \
 
 #define USBVERBOSE
 
+#define device_ptr_t device_t
 #define USBBASEDEVICE device_t
 #define USBDEV(bdev) (bdev)
 #define USBDEVNAME(bdev) device_get_nameunit(bdev)
+#define USBDEVUNIT(bdev) device_get_unit(bdev)
 #define USBDEVPTRNAME(bdev) device_get_nameunit(bdev)
+#define USBGETSOFTC(bdev) (device_get_softc(bdev))
 
 #define DECLARE_USB_DMA_T typedef void * usb_dma_t
 
@@ -271,23 +289,22 @@ __CONCAT(dname,_detach)(self, flags) \
  */
 #define        memcpy(d, s, l)         bcopy((s),(d),(l))
 #define        memset(d, v, l)         bzero((d),(l))
-#define bswap32(x)             swap32(x)               /* XXX not available in FreeBSD */
-#define kthread_create1
-#define kthread_create
+#define bswap32(x)             swap32(x)
+#define kthread_create1(function, sc, priv, string, name)
+#define kthread_create(create_function, sc)
+#define kthread_exit(err)
 
 #define usb_timeout(f, d, t, h) ((h) = timeout((f), (d), (t)))
 #define usb_untimeout(f, d, h) untimeout((f), (d), (h))
 
-#define clalloc(p, s, x) (clist_alloc_cblocks((p), (s), (x)), 0)
+#define clalloc(p, s, x) (clist_alloc_cblocks((p), (s), (s)), 0)
 #define clfree(p) clist_free_cblocks((p))
 
-#define powerhook_establish(fn, sc) 0
+#define powerhook_establish(fn, sc) (fn)
 #define powerhook_disestablish(hdl)
 #define PWR_RESUME 0
 
-#define config_detach(d, _1) device_delete_child(device_get_parent((d)), (d))
-
-#define USB_DECLARE_DRIVER_NAME_INIT(name, dname, init) \
+#define USB_DECLARE_DRIVER_INIT(dname, init) \
 static device_probe_t __CONCAT(dname,_match); \
 static device_attach_t __CONCAT(dname,_attach); \
 static device_detach_t __CONCAT(dname,_detach); \
@@ -303,10 +320,12 @@ static device_method_t __CONCAT(dname,_methods)[] = { \
 }; \
 \
 static driver_t __CONCAT(dname,_driver) = { \
-        name, \
+       #dname, \
         __CONCAT(dname,_methods), \
         sizeof(struct __CONCAT(dname,_softc)) \
 }
+#define METHODS_NONE                   {0,0}
+#define USB_DECLARE_DRIVER(dname)      USB_DECLARE_DRIVER_INIT(dname, METHODS_NONE)
 
 #define USB_MATCH(dname) \
 static int \
@@ -373,14 +392,3 @@ __CONCAT(dname,_detach)(device_t self)
 #define logprintf              printf
 
 #endif /* __FreeBSD__ */
-
-#define NONE {0,0}
-
-#define USB_DECLARE_DRIVER_NAME(name, dname) \
-       USB_DECLARE_DRIVER_NAME_INIT(#name, dname, NONE )
-#define USB_DECLARE_DRIVER_INIT(dname, init) \
-       USB_DECLARE_DRIVER_NAME_INIT(#dname, dname, init)
-#define USB_DECLARE_DRIVER(dname) \
-       USB_DECLARE_DRIVER_NAME_INIT(#dname, dname, NONE )
-
-#undef NONE
index aa273cd..d607943 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: usb_quirks.c,v 1.2 1999/09/27 18:03:56 fgsch Exp $    */
-/*     $NetBSD: usb_quirks.c,v 1.14 1999/09/15 13:57:09 augustss Exp $ */
+/*     $OpenBSD: usb_quirks.c,v 1.3 2000/03/26 08:39:46 aaron Exp $    */
+/*     $NetBSD: usb_quirks.c,v 1.22 2000/03/16 21:51:24 augustss Exp $ */
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -40,9 +40,6 @@
 
 #include <sys/param.h>
 #include <sys/systm.h>
-#if defined(__FreeBSD__)
-#include <sys/bus.h>
-#endif
  
 #include <dev/usb/usb.h>
 
@@ -58,15 +55,17 @@ struct usbd_quirk_entry {
        u_int16_t idProduct;
        u_int16_t bcdDevice;
        struct usbd_quirks quirks;
-} quirks[] = {
+} usb_quirks[] = {
  { USB_VENDOR_KYE, USB_PRODUCT_KYE_NICHE,          0x100, { UQ_NO_SET_PROTO}},
  { USB_VENDOR_INSIDEOUT,USB_PRODUCT_INSIDEOUT_EDGEPORT4, 
                                                    0x094, { UQ_SWAP_UNICODE}},
  { USB_VENDOR_BTC, USB_PRODUCT_BTC_BTC7932,        0x100, { UQ_NO_STRINGS }},
- { USB_VENDOR_ADS, USB_PRODUCT_ADS_ENET,           0x002, { UQ_NO_STRINGS }},
+ { USB_VENDOR_ADS, USB_PRODUCT_ADS_UBS10BT,        0x002, { UQ_NO_STRINGS }},
  { USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_SERIAL1, 0x101, { UQ_NO_STRINGS }},
  { USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502,            0x0a2, { UQ_BAD_ADC }},
- { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_N48,   0x110, { UQ_MS_REVZ }},
+ { USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ADA70,       0x103, { UQ_BAD_ADC }},
+ { USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ASC495,      0x000, { UQ_BAD_AUDIO }},
+ { USB_VENDOR_QTRONIX, USB_PRODUCT_QTRONIX_980N,    0x110, {UQ_SPUR_BUT_UP}},
  { 0, 0, 0, { 0 } }
 };
 
@@ -78,7 +77,7 @@ usbd_find_quirk(d)
 {
        struct usbd_quirk_entry *t;
 
-       for (t = quirks; t->idVendor != 0; t++) {
+       for (t = usb_quirks; t->idVendor != 0; t++) {
                if (t->idVendor  == UGETW(d->idVendor) &&
                    t->idProduct == UGETW(d->idProduct) &&
                    t->bcdDevice == UGETW(d->bcdDevice))
index f74a645..816791f 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: usb_quirks.h,v 1.2 1999/11/07 21:30:19 fgsch Exp $    */
-/*     $NetBSD: usb_quirks.h,v 1.8 1999/10/11 09:16:39 augustss Exp $  */
+/*     $OpenBSD: usb_quirks.h,v 1.3 2000/03/26 08:39:46 aaron Exp $    */
+/*     $NetBSD: usb_quirks.h,v 1.10 1999/11/18 23:32:31 augustss Exp $ */
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -46,6 +46,8 @@ struct usbd_quirks {
 #define UQ_NO_STRINGS  0x08    /* string descriptors are broken. */
 #define UQ_BAD_ADC     0x10    /* bad audio spec version number. */
 #define UQ_BUS_POWERED 0x20    /* device is bus powered, despite claim */
+#define UQ_BAD_AUDIO   0x40    /* device claims audio class, but isn't */
+#define UQ_SPUR_BUT_UP 0x80    /* spurious mouse button up events */
 };
 
 extern struct usbd_quirks usbd_no_quirk;
index f8dc1ea..1a4cd5a 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: usb_subr.c,v 1.6 1999/11/07 21:30:19 fgsch Exp $      */
-/*     $NetBSD: usb_subr.c,v 1.52 1999/10/13 08:10:58 augustss Exp $   */
+/*     $OpenBSD: usb_subr.c,v 1.7 2000/03/26 08:39:46 aaron Exp $      */
+/*     $NetBSD: usb_subr.c,v 1.67 2000/03/13 23:52:37 soren Exp $      */
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
 #include <sys/malloc.h>
 #if defined(__NetBSD__) || defined(__OpenBSD__)
 #include <sys/device.h>
+#include <sys/select.h>
 #elif defined(__FreeBSD__)
 #include <sys/module.h>
 #include <sys/bus.h>
 #endif
 #include <sys/proc.h>
-#include <sys/select.h>
 
 #include <machine/bus.h>
 
@@ -158,16 +158,16 @@ usbd_get_string_desc(dev, sindex, langid, sdesc)
        usb_string_descriptor_t *sdesc;
 {
        usb_device_request_t req;
-       usbd_status r;
+       usbd_status err;
 
        req.bmRequestType = UT_READ_DEVICE;
        req.bRequest = UR_GET_DESCRIPTOR;
        USETW2(req.wValue, UDESC_STRING, sindex);
        USETW(req.wIndex, langid);
        USETW(req.wLength, 1);  /* only size byte first */
-       r = usbd_do_request(dev, &req, sdesc);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = usbd_do_request(dev, &req, sdesc);
+       if (err)
+               return (err);
        USETW(req.wLength, sdesc->bLength);     /* the whole string */
        return (usbd_do_request(dev, &req, sdesc));
 }
@@ -183,7 +183,7 @@ usbd_get_string(dev, si, buf)
        char *s;
        int i, n;
        u_int16_t c;
-       usbd_status r;
+       usbd_status err;
 
        if (si == 0)
                return (0);
@@ -191,16 +191,16 @@ usbd_get_string(dev, si, buf)
                return (0);
        if (dev->langid == USBD_NOLANG) {
                /* Set up default language */
-               r = usbd_get_string_desc(dev, USB_LANGUAGE_TABLE, 0, &us);
-               if (r != USBD_NORMAL_COMPLETION || us.bLength < 4) {
+               err = usbd_get_string_desc(dev, USB_LANGUAGE_TABLE, 0, &us);
+               if (err || us.bLength < 4) {
                        dev->langid = 0; /* Well, just pick English then */
                } else {
                        /* Pick the first language as the default. */
                        dev->langid = UGETW(us.bString[0]);
                }
        }
-       r = usbd_get_string_desc(dev, si, dev->langid, &us);
-       if (r != USBD_NORMAL_COMPLETION)
+       err = usbd_get_string_desc(dev, si, dev->langid, &us);
+       if (err)
                return (0);
        s = buf;
        n = us.bLength / 2 - 1;
@@ -215,7 +215,7 @@ usbd_get_string(dev, si, buf)
                        *s++ = '?';
        }
        *s++ = 0;
-       return buf;
+       return (buf);
 }
 
 void
@@ -229,7 +229,7 @@ usbd_devinfo_vp(dev, v, p)
        struct usb_knowndev *kdp;
 #endif
 
-       if (!dev) {
+       if (dev == NULL) {
                v[0] = p[0] = '\0';
                return;
        }
@@ -237,7 +237,7 @@ usbd_devinfo_vp(dev, v, p)
        vendor = usbd_get_string(dev, udd->iManufacturer, v);
        product = usbd_get_string(dev, udd->iProduct, p);
 #ifdef USBVERBOSE
-       if (!vendor) {
+       if (vendor == NULL || product == NULL) {
                for(kdp = usb_knowndevs;
                    kdp->vendorname != NULL;
                    kdp++) {
@@ -246,20 +246,20 @@ usbd_devinfo_vp(dev, v, p)
                             (kdp->flags & USB_KNOWNDEV_NOPROD) != 0))
                                break;
                }
-               if (kdp->vendorname == NULL)
-                       vendor = product = NULL;
-               else {
-                       vendor = kdp->vendorname;
+               if (kdp->vendorname != NULL) {
+                       if (!vendor)
+                               vendor = kdp->vendorname;
+                       if (!product)
                        product = (kdp->flags & USB_KNOWNDEV_NOPROD) == 0 ?
-                               kdp->productname : NULL;
+                           kdp->productname : NULL;
                }
        }
 #endif
-       if (vendor)
+       if (vendor != NULL)
                strcpy(v, vendor);
        else
                sprintf(v, "vendor 0x%04x", UGETW(udd->idVendor));
-       if (product)
+       if (product != NULL)
                strcpy(p, product);
        else
                sprintf(p, "product 0x%04x", UGETW(udd->idProduct));
@@ -305,8 +305,10 @@ usb_delay_ms(bus, ms)
        usbd_bus_handle bus;
        u_int ms;
 {
+       extern int cold;
+
        /* Wait at least two clock ticks so we know the time has passed. */
-       if (bus->use_polling)
+       if (bus->use_polling || cold)
                delay((ms+1) * 1000);
        else
                tsleep(&ms, PRIBIO, "usbdly", (ms*hz+999)/1000 + 1);
@@ -328,7 +330,7 @@ usbd_reset_port(dev, port, ps)
        usb_port_status_t *ps;
 {
        usb_device_request_t req;
-       usbd_status r;
+       usbd_status err;
        int n;
        
        req.bmRequestType = UT_WRITE_CLASS_OTHER;
@@ -336,34 +338,35 @@ usbd_reset_port(dev, port, ps)
        USETW(req.wValue, UHF_PORT_RESET);
        USETW(req.wIndex, port);
        USETW(req.wLength, 0);
-       r = usbd_do_request(dev, &req, 0);
+       err = usbd_do_request(dev, &req, 0);
        DPRINTFN(1,("usbd_reset_port: port %d reset done, error=%s\n",
-                   port, usbd_errstr(r)));
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+                   port, usbd_errstr(err)));
+       if (err)
+               return (err);
        n = 10;
        do {
                /* Wait for device to recover from reset. */
                usbd_delay_ms(dev, USB_PORT_RESET_DELAY);
-               r = usbd_get_port_status(dev, port, ps);
-               if (r != USBD_NORMAL_COMPLETION) {
-                       DPRINTF(("usbd_reset_port: get status failed %d\n",r));
-                       return (r);
+               err = usbd_get_port_status(dev, port, ps);
+               if (err) {
+                       DPRINTF(("usbd_reset_port: get status failed %d\n",
+                                err));
+                       return (err);
                }
        } while ((UGETW(ps->wPortChange) & UPS_C_PORT_RESET) == 0 && --n > 0);
        if (n == 0) {
                printf("usbd_reset_port: timeout\n");
                return (USBD_IOERROR);
        }
-       r = usbd_clear_port_feature(dev, port, UHF_C_PORT_RESET);
+       err = usbd_clear_port_feature(dev, port, UHF_C_PORT_RESET);
 #ifdef USB_DEBUG
-       if (r != USBD_NORMAL_COMPLETION)
+       if (err)
                DPRINTF(("usbd_reset_port: clear port feature failed %d\n",r));
 #endif
 
        /* Wait for the device to recover from reset. */
        usbd_delay_ms(dev, USB_PORT_RESET_RECOVERY);
-       return (r);
+       return (err);
 }
 
 usb_interface_descriptor_t *
@@ -397,7 +400,7 @@ usbd_find_idesc(cd, ifaceidx, altidx)
                                return (d);
                }
        }
-       return (0);
+       return (NULL);
 }
 
 usb_endpoint_descriptor_t *
@@ -414,10 +417,10 @@ usbd_find_edesc(cd, ifaceidx, altidx, endptidx)
        int curidx;
 
        d = usbd_find_idesc(cd, ifaceidx, altidx);
-       if (!d)
-               return (0);
+       if (d == NULL)
+               return (NULL);
        if (endptidx >= d->bNumEndpoints) /* quick exit */
-               return (0);
+               return (NULL);
 
        curidx = -1;
        for (p = (char *)d + d->bLength; p < end; ) {
@@ -426,14 +429,14 @@ usbd_find_edesc(cd, ifaceidx, altidx, endptidx)
                        break;
                p += e->bLength;
                if (p <= end && e->bDescriptorType == UDESC_INTERFACE)
-                       return (0);
+                       return (NULL);
                if (p <= end && e->bDescriptorType == UDESC_ENDPOINT) {
                        curidx++;
                        if (curidx == endptidx)
                                return (e);
                }
        }
-       return (0);
+       return (NULL);
 }
 
 usbd_status
@@ -455,15 +458,15 @@ usbd_fill_iface_data(dev, ifaceidx, altidx)
        ifc->index = ifaceidx;
        ifc->altindex = altidx;
        nendpt = ifc->idesc->bNumEndpoints;
-       DPRINTFN(10,("usbd_fill_iface_data: found idesc n=%d\n", nendpt));
+       DPRINTFN(4,("usbd_fill_iface_data: found idesc nendpt=%d\n", nendpt));
        if (nendpt != 0) {
                ifc->endpoints = malloc(nendpt * sizeof(struct usbd_endpoint),
                                        M_USB, M_NOWAIT);
-               if (ifc->endpoints == 0)
+               if (ifc->endpoints == NULL)
                        return (USBD_NOMEM);
        } else
-               ifc->endpoints = 0;
-       ifc->priv = 0;
+               ifc->endpoints = NULL;
+       ifc->priv = NULL;
        p = (char *)ifc->idesc + ifc->idesc->bLength;
        end = (char *)dev->cdesc + UGETW(dev->cdesc->wTotalLength);
 #define ed ((usb_endpoint_descriptor_t *)p)
@@ -477,11 +480,15 @@ usbd_fill_iface_data(dev, ifaceidx, altidx)
                        if (p + ed->bLength <= end && ed->bLength != 0 &&
                            ed->bDescriptorType == UDESC_ENDPOINT)
                                goto found;
-                       if (ed->bDescriptorType == UDESC_INTERFACE ||
-                           ed->bLength == 0)
+                       if (ed->bLength == 0 ||
+                           ed->bDescriptorType == UDESC_INTERFACE)
                                break;
                }
                /* passed end, or bad desc */
+               DPRINTF(("usbd_fill_iface_data: bad descriptor(s): %s\n",
+                        ed->bLength == 0 ? "0 length" :
+                        ed->bDescriptorType == UDESC_INTERFACE ? "iface desc":
+                        "out of data"));
                goto bad;
        found:
                ifc->endpoints[endpt].edesc = ed;
@@ -493,7 +500,8 @@ usbd_fill_iface_data(dev, ifaceidx, altidx)
        return (USBD_NORMAL_COMPLETION);
 
  bad:
-       free(ifc->endpoints, M_USB);
+       if (ifc->endpoints != NULL)
+               free(ifc->endpoints, M_USB);
        return (USBD_INVAL);
 }
 
@@ -530,14 +538,14 @@ usbd_set_config_no(dev, no, msg)
 {
        int index;
        usb_config_descriptor_t cd;
-       usbd_status r;
+       usbd_status err;
 
        DPRINTFN(5,("usbd_set_config_no: %d\n", no));
        /* Figure out what config index to use. */
        for (index = 0; index < dev->ddesc.bNumConfigurations; index++) {
-               r = usbd_get_config_desc(dev, index, &cd);
-               if (r != USBD_NORMAL_COMPLETION)
-                       return (r);
+               err = usbd_get_config_desc(dev, index, &cd);
+               if (err)
+                       return (err);
                if (cd.bConfigurationValue == no)
                        return (usbd_set_config_index(dev, index, msg));
        }
@@ -552,7 +560,7 @@ usbd_set_config_index(dev, index, msg)
 {
        usb_status_t ds;
        usb_config_descriptor_t cd, *cdp;
-       usbd_status r;
+       usbd_status err;
        int ifcidx, nifc, len, selfpowered, power;
 
        DPRINTFN(5,("usbd_set_config_index: dev=%p index=%d\n", dev, index));
@@ -566,26 +574,26 @@ usbd_set_config_index(dev, index, msg)
                        usbd_free_iface_data(dev, ifcidx);
                free(dev->ifaces, M_USB);
                free(dev->cdesc, M_USB);
-               dev->ifaces = 0;
-               dev->cdesc = 0;
+               dev->ifaces = NULL;
+               dev->cdesc = NULL;
                dev->config = 0;
        }
 
        /* Figure out what config number to use. */
-       r = usbd_get_config_desc(dev, index, &cd);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = usbd_get_config_desc(dev, index, &cd);
+       if (err)
+               return (err);
        len = UGETW(cd.wTotalLength);
        cdp = malloc(len, M_USB, M_NOWAIT);
-       if (cdp == 0)
+       if (cdp == NULL)
                return (USBD_NOMEM);
-       r = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp);
-       if (r != USBD_NORMAL_COMPLETION)
+       err = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp);
+       if (err)
                goto bad;
        if (cdp->bDescriptorType != UDESC_CONFIG) {
                DPRINTFN(-1,("usbd_set_config_index: bad desc %d\n",
                             cdp->bDescriptorType));
-               r = USBD_INVAL;
+               err = USBD_INVAL;
                goto bad;
        }
        selfpowered = 0;
@@ -594,13 +602,12 @@ usbd_set_config_index(dev, index, msg)
                /* May be self powered. */
                if (cdp->bmAttributes & UC_BUS_POWERED) {
                        /* Must ask device. */
-                       r = usbd_get_device_status(dev, &ds);
-                       if (r == USBD_NORMAL_COMPLETION && 
-                           (UGETW(ds.wStatus) & UDS_SELF_POWERED))
+                       err = usbd_get_device_status(dev, &ds);
+                       if (!err && (UGETW(ds.wStatus) & UDS_SELF_POWERED))
                                selfpowered = 1;
                        DPRINTF(("usbd_set_config_index: status=0x%04x, "
                                 "error=%s\n",
-                                UGETW(ds.wStatus), usbd_errstr(r)));
+                                UGETW(ds.wStatus), usbd_errstr(err)));
                } else
                        selfpowered = 1;
        }
@@ -609,7 +616,7 @@ usbd_set_config_index(dev, index, msg)
                 dev->address, cdp->bmAttributes, 
                 selfpowered, cdp->bMaxPower * 2));
 #ifdef USB_DEBUG
-       if (!dev->powersrc) {
+       if (dev->powersrc == NULL) {
                DPRINTF(("usbd_set_config_index: No power source?\n"));
                return (USBD_IOERROR);
        }
@@ -623,7 +630,7 @@ usbd_set_config_index(dev, index, msg)
                               USBDEVNAME(dev->bus->bdev), dev->address, 
                               cdp->bConfigurationValue, 
                               power, dev->powersrc->power);
-               r = USBD_NO_POWER;
+               err = USBD_NO_POWER;
                goto bad;
        }
        dev->power = power;
@@ -631,11 +638,11 @@ usbd_set_config_index(dev, index, msg)
 
        DPRINTF(("usbd_set_config_index: set config %d\n",
                 cdp->bConfigurationValue));
-       r = usbd_set_config(dev, cdp->bConfigurationValue);
-       if (r != USBD_NORMAL_COMPLETION) {
+       err = usbd_set_config(dev, cdp->bConfigurationValue);
+       if (err) {
                DPRINTF(("usbd_set_config_index: setting config=%d failed, "
                         "error=%s\n",
-                        cdp->bConfigurationValue, usbd_errstr(r)));
+                        cdp->bConfigurationValue, usbd_errstr(err)));
                goto bad;
        }
        DPRINTF(("usbd_set_config_index: setting new config %d\n",
@@ -643,16 +650,16 @@ usbd_set_config_index(dev, index, msg)
        nifc = cdp->bNumInterface;
        dev->ifaces = malloc(nifc * sizeof(struct usbd_interface), 
                             M_USB, M_NOWAIT);
-       if (dev->ifaces == 0) {
-               r = USBD_NOMEM;
+       if (dev->ifaces == NULL) {
+               err = USBD_NOMEM;
                goto bad;
        }
        DPRINTFN(5,("usbd_set_config_index: dev=%p cdesc=%p\n", dev, cdp));
        dev->cdesc = cdp;
        dev->config = cdp->bConfigurationValue;
        for (ifcidx = 0; ifcidx < nifc; ifcidx++) {
-               r = usbd_fill_iface_data(dev, ifcidx, 0);
-               if (r != USBD_NORMAL_COMPLETION) {
+               err = usbd_fill_iface_data(dev, ifcidx, 0);
+               if (err) {
                        while (--ifcidx >= 0)
                                usbd_free_iface_data(dev, ifcidx);
                        goto bad;
@@ -663,42 +670,44 @@ usbd_set_config_index(dev, index, msg)
 
  bad:
        free(cdp, M_USB);
-       return (r);
+       return (err);
 }
 
 /* XXX add function for alternate settings */
 
 usbd_status
-usbd_setup_pipe(dev, iface, ep, pipe)
+usbd_setup_pipe(dev, iface, ep, ival, pipe)
        usbd_device_handle dev;
        usbd_interface_handle iface; 
        struct usbd_endpoint *ep;
+       int ival;
        usbd_pipe_handle *pipe;
 {
        usbd_pipe_handle p;
-       usbd_status r;
+       usbd_status err;
 
        DPRINTFN(1,("usbd_setup_pipe: dev=%p iface=%p ep=%p pipe=%p\n",
                    dev, iface, ep, pipe));
        p = malloc(dev->bus->pipe_size, M_USB, M_NOWAIT);
-       if (p == 0)
+       if (p == NULL)
                return (USBD_NOMEM);
        p->device = dev;
        p->iface = iface;
        p->endpoint = ep;
        ep->refcnt++;
        p->refcnt = 1;
-       p->intrreqh = 0;
+       p->intrxfer = 0;
        p->running = 0;
        p->repeat = 0;
+       p->interval = ival;
        SIMPLEQ_INIT(&p->queue);
-       r = dev->bus->methods->open_pipe(p);
-       if (r != USBD_NORMAL_COMPLETION) {
+       err = dev->bus->methods->open_pipe(p);
+       if (err) {
                DPRINTFN(-1,("usbd_setup_pipe: endpoint=0x%x failed, error="
                         "%s\n",
-                        ep->edesc->bEndpointAddress, usbd_errstr(r)));
+                        ep->edesc->bEndpointAddress, usbd_errstr(err)));
                free(p, M_USB);
-               return (r);
+               return (err);
        }
        /* Clear any stall and make sure DATA0 toggle will be used next. */
        if (UE_GET_ADDR(ep->edesc->bEndpointAddress) != USB_CONTROL_ENDPOINT)
@@ -739,7 +748,8 @@ usbd_probe_and_attach(parent, dev, port, addr)
 {
        struct usb_attach_arg uaa;
        usb_device_descriptor_t *dd = &dev->ddesc;
-       int r, found, i, confi, nifaces;
+       int found, i, confi, nifaces;
+       usbd_status err;
        device_ptr_t dv;
        usbd_interface_handle ifaces[256]; /* 256 is the absolute max */
 
@@ -770,10 +780,11 @@ usbd_probe_and_attach(parent, dev, port, addr)
        uaa.release = UGETW(dd->bcdDevice);
 
        /* First try with device specific drivers. */
+       DPRINTF(("usbd_probe_and_attach: trying device specific drivers\n"));
        dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch);
-       if (dv) {
+       if (dv != NULL) {
                dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT);
-               if (dev->subdevs == 0)
+               if (dev->subdevs == NULL)
                        return (USBD_NOMEM);
                dev->subdevs[0] = dv;
                dev->subdevs[1] = 0;
@@ -782,16 +793,18 @@ usbd_probe_and_attach(parent, dev, port, addr)
 
        DPRINTF(("usbd_probe_and_attach: no device specific driver found\n"));
 
+       DPRINTF(("usbd_probe_and_attach: looping over %d configurations\n",
+                dd->bNumConfigurations));
        /* Next try with interface drivers. */
        for (confi = 0; confi < dd->bNumConfigurations; confi++) {
                DPRINTFN(1,("usbd_probe_and_attach: trying config idx=%d\n",
                            confi));
-               r = usbd_set_config_index(dev, confi, 1);
-               if (r != USBD_NORMAL_COMPLETION) {
+               err = usbd_set_config_index(dev, confi, 1);
+               if (err) {
 #ifdef USB_DEBUG
                        DPRINTF(("%s: port %d, set config at addr %d failed, "
                                 "error=%s\n", USBDEVPTRNAME(parent), port,
-                                addr, usbd_errstr(r)));
+                                addr, usbd_errstr(err)));
 #else
                        printf("%s: port %d, set config at addr %d failed\n",
                               USBDEVPTRNAME(parent), port, addr);
@@ -800,7 +813,7 @@ usbd_probe_and_attach(parent, dev, port, addr)
                        device_delete_child(parent, bdev);
 #endif
 
-                       return (r);
+                       return (err);
                }
                nifaces = dev->cdesc->bNumInterface;
                uaa.configno = dev->cdesc->bConfigurationValue;
@@ -809,7 +822,7 @@ usbd_probe_and_attach(parent, dev, port, addr)
                uaa.ifaces = ifaces;
                uaa.nifaces = nifaces;
                dev->subdevs = malloc((nifaces+1) * sizeof dv, M_USB,M_NOWAIT);
-               if (dev->subdevs == 0) {
+               if (dev->subdevs == NULL) {
 #if defined(__FreeBSD__)
                        device_delete_child(parent, bdev);
 #endif
@@ -906,12 +919,13 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
 {
        usbd_device_handle dev;
        usb_device_descriptor_t *dd;
-       usbd_status r;
+       usbd_status err;
        int addr;
        int i;
 
        DPRINTF(("usbd_new_device bus=%p depth=%d lowspeed=%d\n",
                 bus, depth, lowspeed));
+
        addr = usbd_getnewaddr(bus);
        if (addr < 0) {
                printf("%s: No free USB addresses, new device ignored.\n", 
@@ -920,7 +934,7 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
        }
 
        dev = malloc(sizeof *dev, M_USB, M_NOWAIT);
-       if (dev == 0)
+       if (dev == NULL)
                return (USBD_NOMEM);
        memset(dev, 0, sizeof(*dev));
 
@@ -946,29 +960,29 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
        dev->langid = USBD_NOLANG;
        dev->cookie.cookie = ++usb_cookie_no;
 
-       /* Establish the the default pipe. */
-       r = usbd_setup_pipe(dev, 0, &dev->def_ep, &dev->default_pipe);
-       if (r != USBD_NORMAL_COMPLETION) {
+       /* Establish the default pipe. */
+       err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
+                             &dev->default_pipe);
+       if (err) {
                usbd_remove_device(dev, up);
-               return (r);
+               return (err);
        }
 
        up->device = dev;
        dd = &dev->ddesc;
        /* Try a few times in case the device is slow (i.e. outside specs.) */
-       for (i = 0; i < 5; i++) {
+       for (i = 0; i < 3; i++) {
                /* Get the first 8 bytes of the device descriptor. */
-               r = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd);
-               if (r == USBD_NORMAL_COMPLETION)
+               err = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd);
+               if (!err)
                        break;
                usbd_delay_ms(dev, 200);
        }
-       if (r != USBD_NORMAL_COMPLETION) {
+       if (err) {
                DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc "
-                             "failed\n",
-                             addr));
+                             "failed\n", addr));
                usbd_remove_device(dev, up);
-               return (r);
+               return (err);
        }
 
        DPRINTF(("usbd_new_device: adding unit addr=%d, rev=%02x, class=%d, "
@@ -994,24 +1008,22 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
        USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize);
 
        /* Get the full device descriptor. */
-       r = usbd_get_device_desc(dev, dd);
-       if (r != USBD_NORMAL_COMPLETION) {
+       err = usbd_reload_device_desc(dev);
+       if (err) {
                DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc "
                              "failed\n", addr));
                usbd_remove_device(dev, up);
-               return (r);
+               return (err);
        }
 
-       /* Figure out what's wrong with this device. */
-       dev->quirks = usbd_find_quirk(dd);
-
        /* Set the address */
-       r = usbd_set_address(dev, addr);
-       if (r != USBD_NORMAL_COMPLETION) {
-               DPRINTFN(-1,("usb_new_device: set address %d failed\n",addr));
-               r = USBD_SET_ADDR_FAILED;
+       err = usbd_set_address(dev, addr);
+       DPRINTFN(5,("usbd_new_device: setting device address=%d\n", addr));
+       if (err) {
+               DPRINTFN(-1,("usb_new_device: set address %d failed\n", addr));
+               err = USBD_SET_ADDR_FAILED;
                usbd_remove_device(dev, up);
-               return (r);
+               return (err);
        }
        /* Allow device time to set new address */
        usbd_delay_ms(dev, USB_SET_ADDRESS_SETTLE);
@@ -1026,16 +1038,34 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
        DPRINTF(("usbd_new_device: new dev (addr %d), dev=%p, parent=%p\n", 
                 addr, dev, parent));
 
-       r = usbd_probe_and_attach(parent, dev, port, addr);
-       if (r != USBD_NORMAL_COMPLETION) {
+       usbd_add_dev_event(USB_EVENT_DEVICE_ATTACH, dev);
+
+       err = usbd_probe_and_attach(parent, dev, port, addr);
+       if (err) {
                usbd_remove_device(dev, up);
-               return (r);
+               return (err);
        }
-  
-       usbd_add_event(USB_EVENT_ATTACH, dev);
+
        return (USBD_NORMAL_COMPLETION);
 }
 
+usbd_status
+usbd_reload_device_desc(dev)
+       usbd_device_handle dev;
+{
+       usbd_status err;
+
+       /* Get the full device descriptor. */
+       err = usbd_get_device_desc(dev, &dev->ddesc);
+       if (err)
+               return (err);
+
+       /* Figure out what's wrong with this device. */
+       dev->quirks = usbd_find_quirk(&dev->ddesc);
+
+       return (USBD_NORMAL_COMPLETION);
+}
+
 void
 usbd_remove_device(dev, up)
        usbd_device_handle dev;
@@ -1043,7 +1073,7 @@ usbd_remove_device(dev, up)
 {
        DPRINTF(("usbd_remove_device: %p\n", dev));
   
-       if (dev->default_pipe)
+       if (dev->default_pipe != NULL)
                usbd_kill_pipe(dev->default_pipe);
        up->device = 0;
        dev->bus->devices[dev->address] = 0;
@@ -1138,17 +1168,35 @@ usbd_fill_deviceinfo(dev, di)
        struct usb_device_info *di;
 {
        struct usbd_port *p;
-       int i, r, s;
+       int i, err, s;
 
-       di->config = dev->config;
+       di->bus = USBDEVUNIT(dev->bus->bdev);
+       di->addr = dev->address;
+       di->cookie = dev->cookie;
        usbd_devinfo_vp(dev, di->vendor, di->product);
        usbd_printBCD(di->release, UGETW(dev->ddesc.bcdDevice));
        di->vendorNo = UGETW(dev->ddesc.idVendor);
        di->productNo = UGETW(dev->ddesc.idProduct);
+       di->releaseNo = UGETW(dev->ddesc.bcdDevice);
        di->class = dev->ddesc.bDeviceClass;
+       di->subclass = dev->ddesc.bDeviceSubClass;
+       di->protocol = dev->ddesc.bDeviceProtocol;
+       di->config = dev->config;
        di->power = dev->self_powered ? 0 : dev->power;
        di->lowspeed = dev->lowspeed;
-       di->addr = dev->address;
+
+       if (dev->subdevs != NULL) {
+               for (i = 0; dev->subdevs[i] && i < USB_MAX_DEVNAMES; i++) {
+                       strncpy(di->devnames[i], USBDEVPTRNAME(dev->subdevs[i]),
+                               USB_MAX_DEVNAMELEN);
+                       di->devnames[i][USB_MAX_DEVNAMELEN-1] = '\0';
+               }
+       } else {
+               i = 0;
+       }
+       for (/* i is set */; i < USB_MAX_DEVNAMES; i++)
+               di->devnames[i][0] = 0;                 /* empty */
+
        if (dev->hub) {
                for (i = 0; 
                     i < sizeof(di->ports) / sizeof(di->ports[0]) &&
@@ -1156,19 +1204,19 @@ usbd_fill_deviceinfo(dev, di)
                     i++) {
                        p = &dev->hub->ports[i];
                        if (p->device)
-                               r = p->device->address;
+                               err = p->device->address;
                        else {
                                s = UGETW(p->status.wPortStatus);
                                if (s & UPS_PORT_ENABLED)
-                                       r = USB_PORT_ENABLED;
+                                       err = USB_PORT_ENABLED;
                                else if (s & UPS_SUSPEND)
-                                       r = USB_PORT_SUSPENDED;
+                                       err = USB_PORT_SUSPENDED;
                                else if (s & UPS_PORT_POWER)
-                                       r = USB_PORT_POWERED;
+                                       err = USB_PORT_POWERED;
                                else
-                                       r = USB_PORT_DISABLED;
+                                       err = USB_PORT_DISABLED;
                        }
-                       di->ports[i] = r;
+                       di->ports[i] = err;
                }
                di->nports = dev->hub->hubdesc.bNbrPorts;
        } else
@@ -1181,17 +1229,17 @@ usb_free_device(dev)
 {
        int ifcidx, nifc;
 
-       if (dev->default_pipe)
+       if (dev->default_pipe != NULL)
                usbd_kill_pipe(dev->default_pipe);
-       if (dev->ifaces) {
+       if (dev->ifaces != NULL) {
                nifc = dev->cdesc->bNumInterface;
                for (ifcidx = 0; ifcidx < nifc; ifcidx++)
                        usbd_free_iface_data(dev, ifcidx);
                free(dev->ifaces, M_USB);
        }
-       if (dev->cdesc)
+       if (dev->cdesc != NULL)
                free(dev->cdesc, M_USB);
-       if (dev->subdevs)
+       if (dev->subdevs != NULL)
                free(dev->subdevs, M_USB);
        free(dev, M_USB);
 }
@@ -1226,36 +1274,33 @@ usb_disconnect_port(up, parent)
                    up, dev, up->portno));
 
 #ifdef DIAGNOSTIC
-       if (!dev) {
+       if (dev == NULL) {
                printf("usb_disconnect_port: no device\n");
                return;
        }
 #endif
 
-       if (!dev->cdesc) {
-               /* Partially attached device, just drop it. */
-               dev->bus->devices[dev->address] = 0;
-               up->device = 0;
-               return;
-       }
-
-       if (dev->subdevs) {
+       if (dev->subdevs != NULL) {
+               DPRINTFN(3,("usb_disconnect_port: disconnect subdevs\n"));
                for (i = 0; dev->subdevs[i]; i++) {
-                       if (!dev->subdevs[i])   /* skip empty elements */
-                               continue;
-
                        printf("%s: at %s", USBDEVPTRNAME(dev->subdevs[i]), 
                               hubname);
                        if (up->portno != 0)
                                printf(" port %d", up->portno);
                        printf(" (addr %d) disconnected\n", dev->address);
+#if defined(__NetBSD__) || defined(__OpenBSD__)
                        config_detach(dev->subdevs[i], DETACH_FORCE);
+#elif defined(__FreeBSD__)
+                       device_delete_child(device_get_parent(dev->subdevs[i]),
+                                           dev->subdevs[i]);
+#endif
+
                }
        }
 
-       usbd_add_event(USB_EVENT_DETACH, dev);
-       dev->bus->devices[dev->address] = 0;
-       up->device = 0;
+       usbd_add_dev_event(USB_EVENT_DEVICE_DETACH, dev);
+       dev->bus->devices[dev->address] = NULL;
+       up->device = NULL;
        usb_free_device(dev);
 }
 
index f37596c..2765d7b 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: usbdi.c,v 1.7 1999/11/07 21:30:20 fgsch Exp $ */
-/*     $NetBSD: usbdi.c,v 1.47 1999/10/13 23:46:10 augustss Exp $      */
+/*     $OpenBSD: usbdi.c,v 1.8 2000/03/26 08:39:46 aaron Exp $ */
+/*     $NetBSD: usbdi.c,v 1.65 2000/03/08 15:34:10 augustss Exp $      */
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
 
 #include <sys/param.h>
 #include <sys/systm.h>
-#include <sys/kernel.h>
 #if defined(__NetBSD__) || defined(__OpenBSD__)
+#include <sys/kernel.h>
 #include <sys/device.h>
 #elif defined(__FreeBSD__)
 #include <sys/module.h>
 #include <sys/bus.h>
 #include <sys/conf.h>
 #include "usb_if.h"
+#if defined(DIAGNOSTIC) && defined(__i386__)
+#include <machine/cpu.h>
+#endif
 #endif
 #include <sys/malloc.h>
 #include <sys/proc.h>
 #include <dev/usb/usbdivar.h>
 #include <dev/usb/usb_mem.h>
 
+#if defined(__FreeBSD__)
+#include "usb_if.h"
+#endif
+
 #ifdef USB_DEBUG
 #define DPRINTF(x)     if (usbdebug) logprintf x
 #define DPRINTFN(n,x)  if (usbdebug>(n)) logprintf x
@@ -71,11 +78,10 @@ extern int usbdebug;
 
 static usbd_status usbd_ar_pipe  __P((usbd_pipe_handle pipe));
 void usbd_do_request_async_cb 
-       __P((usbd_request_handle, usbd_private_handle, usbd_status));
+       __P((usbd_xfer_handle, usbd_private_handle, usbd_status));
 void usbd_start_next __P((usbd_pipe_handle pipe));
-
-static SIMPLEQ_HEAD(, usbd_request) usbd_free_requests =
-       SIMPLEQ_HEAD_INITIALIZER(usbd_free_requests);
+usbd_status usbd_open_pipe_ival
+       __P((usbd_interface_handle, u_int8_t, u_int8_t, usbd_pipe_handle *, int));
 
 static int usbd_nbuses = 0;
 
@@ -88,29 +94,18 @@ usbd_init()
 void
 usbd_finish()
 {
-       usbd_request_handle reqh;
-
-       if (--usbd_nbuses == 0) {
-               /* Last controller is gone, free all requests. */
-               for (;;) {
-                       reqh = SIMPLEQ_FIRST(&usbd_free_requests);
-                       if (reqh == NULL)
-                               break;
-                       SIMPLEQ_REMOVE_HEAD(&usbd_free_requests, reqh, next);
-                       free(reqh, M_USB);
-               }                       
-       }
+       --usbd_nbuses;
 }
 
-static __inline int usbd_reqh_isread __P((usbd_request_handle reqh));
+static __inline int usbd_xfer_isread __P((usbd_xfer_handle xfer));
 static __inline int
-usbd_reqh_isread(reqh)
-       usbd_request_handle reqh;
+usbd_xfer_isread(xfer)
+       usbd_xfer_handle xfer;
 {
-       if (reqh->rqflags & URQ_REQUEST)
-               return (reqh->request.bmRequestType & UT_READ);
+       if (xfer->rqflags & URQ_REQUEST)
+               return (xfer->request.bmRequestType & UT_READ);
        else
-               return (reqh->pipe->endpoint->edesc->bEndpointAddress &
+               return (xfer->pipe->endpoint->edesc->bEndpointAddress &
                        UE_DIR_IN);
 }
 
@@ -121,13 +116,13 @@ void
 usbd_dump_queue(pipe)
        usbd_pipe_handle pipe;
 {
-       usbd_request_handle reqh;
+       usbd_xfer_handle xfer;
 
        printf("usbd_dump_queue: pipe=%p\n", pipe);
-       for (reqh = SIMPLEQ_FIRST(&pipe->queue);
-            reqh;
-            reqh = SIMPLEQ_NEXT(reqh, next)) {
-               printf("  reqh=%p\n", reqh);
+       for (xfer = SIMPLEQ_FIRST(&pipe->queue);
+            xfer;
+            xfer = SIMPLEQ_NEXT(xfer, next)) {
+               printf("  xfer=%p\n", xfer);
        }
 }
 #endif
@@ -139,69 +134,90 @@ usbd_open_pipe(iface, address, flags, pipe)
        u_int8_t flags;
        usbd_pipe_handle *pipe;
 { 
+       return (usbd_open_pipe_ival(iface, address, flags, pipe,
+                                   USBD_DEFAULT_INTERVAL));
+}
+
+usbd_status
+usbd_open_pipe_ival(iface, address, flags, pipe, ival)
+       usbd_interface_handle iface;
+       u_int8_t address;
+       u_int8_t flags;
+       usbd_pipe_handle *pipe;
+       int ival;
+{
        usbd_pipe_handle p;
        struct usbd_endpoint *ep;
-       usbd_status r;
+       usbd_status err;
        int i;
 
+       DPRINTFN(3,("usbd_open_pipe: iface=%p address=0x%x flags=0x%x\n",
+                   iface, address, flags));
+
        for (i = 0; i < iface->idesc->bNumEndpoints; i++) {
                ep = &iface->endpoints[i];
+               if (ep->edesc == NULL)
+                       return (USBD_IOERROR);
                if (ep->edesc->bEndpointAddress == address)
                        goto found;
        }
        return (USBD_BAD_ADDRESS);
  found:
-       if ((flags & USBD_EXCLUSIVE_USE) &&
-           ep->refcnt != 0)
+       if ((flags & USBD_EXCLUSIVE_USE) && ep->refcnt != 0)
                return (USBD_IN_USE);
-       r = usbd_setup_pipe(iface->device, iface, ep, &p);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = usbd_setup_pipe(iface->device, iface, ep, ival, &p);
+       if (err)
+               return (err);
        LIST_INSERT_HEAD(&iface->pipes, p, next);
        *pipe = p;
        return (USBD_NORMAL_COMPLETION);
 }
 
 usbd_status 
-usbd_open_pipe_intr(iface, address, flags, pipe, priv, buffer, length, cb)
+usbd_open_pipe_intr(iface, address, flags, pipe, priv, buffer, len, cb, ival)
        usbd_interface_handle iface;
        u_int8_t address;
        u_int8_t flags;
        usbd_pipe_handle *pipe;
        usbd_private_handle priv;
        void *buffer;
-       u_int32_t length;
+       u_int32_t len;
        usbd_callback cb;
+       int ival;
 {
-       usbd_status r;
-       usbd_request_handle reqh;
+       usbd_status err;
+       usbd_xfer_handle xfer;
        usbd_pipe_handle ipipe;
 
-       r = usbd_open_pipe(iface, address, USBD_EXCLUSIVE_USE, &ipipe);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
-       reqh = usbd_alloc_request(iface->device);
-       if (reqh == 0) {
-               r = USBD_NOMEM;
+       DPRINTFN(3,("usbd_open_pipe_intr: address=0x%x flags=0x%x len=%d\n",
+                   address, flags, len));
+
+       err = usbd_open_pipe_ival(iface, address, USBD_EXCLUSIVE_USE,
+                                 &ipipe, ival);
+       if (err)
+               return (err);
+       xfer = usbd_alloc_xfer(iface->device);
+       if (xfer == NULL) {
+               err = USBD_NOMEM;
                goto bad1;
        }
-       usbd_setup_request(reqh, ipipe, priv, buffer, length, flags,
+       usbd_setup_xfer(xfer, ipipe, priv, buffer, len, flags,
                           USBD_NO_TIMEOUT, cb);
-       ipipe->intrreqh = reqh;
+       ipipe->intrxfer = xfer;
        ipipe->repeat = 1;
-       r = usbd_transfer(reqh);
+       err = usbd_transfer(xfer);
        *pipe = ipipe;
-       if (r != USBD_IN_PROGRESS)
+       if (err != USBD_IN_PROGRESS)
                goto bad2;
        return (USBD_NORMAL_COMPLETION);
 
  bad2:
-       ipipe->intrreqh = 0;
+       ipipe->intrxfer = 0;
        ipipe->repeat = 0;
-       usbd_free_request(reqh);
+       usbd_free_xfer(xfer);
  bad1:
        usbd_close_pipe(ipipe);
-       return r;
+       return (err);
 }
 
 usbd_status
@@ -209,7 +225,7 @@ usbd_close_pipe(pipe)
        usbd_pipe_handle pipe;
 {
 #ifdef DIAGNOSTIC
-       if (pipe == 0) {
+       if (pipe == NULL) {
                printf("usbd_close_pipe: pipe==NULL\n");
                return (USBD_NORMAL_COMPLETION);
        }
@@ -222,185 +238,197 @@ usbd_close_pipe(pipe)
        LIST_REMOVE(pipe, next);
        pipe->endpoint->refcnt--;
        pipe->methods->close(pipe);
-       if (pipe->intrreqh)
-               usbd_free_request(pipe->intrreqh);
+       if (pipe->intrxfer != NULL)
+               usbd_free_xfer(pipe->intrxfer);
        free(pipe, M_USB);
        return (USBD_NORMAL_COMPLETION);
 }
 
 usbd_status
-usbd_transfer(reqh)
-       usbd_request_handle reqh;
+usbd_transfer(xfer)
+       usbd_xfer_handle xfer;
 {
-       usbd_pipe_handle pipe = reqh->pipe;
-       usb_dma_t *dmap = &reqh->dmabuf;
-       usbd_status r;
+       usbd_pipe_handle pipe = xfer->pipe;
+       usb_dma_t *dmap = &xfer->dmabuf;
+       usbd_status err;
        u_int size;
        int s;
 
-       DPRINTFN(5,("usbd_transfer: reqh=%p, flags=%d, pipe=%p, running=%d\n",
-                   reqh, reqh->flags, pipe, pipe->running));
+       DPRINTFN(5,("usbd_transfer: xfer=%p, flags=%d, pipe=%p, running=%d\n",
+                   xfer, xfer->flags, pipe, pipe->running));
 #ifdef USB_DEBUG
        if (usbdebug > 5)
                usbd_dump_queue(pipe);
 #endif
-       reqh->done = 0;
+       xfer->done = 0;
 
-       size = reqh->length;
+       size = xfer->length;
        /* If there is no buffer, allocate one. */
-       if (!(reqh->rqflags & URQ_DEV_DMABUF) && size != 0) {
+       if (!(xfer->rqflags & URQ_DEV_DMABUF) && size != 0) {
                struct usbd_bus *bus = pipe->device->bus;
 
 #ifdef DIAGNOSTIC
-               if (reqh->rqflags & URQ_AUTO_DMABUF)
+               if (xfer->rqflags & URQ_AUTO_DMABUF)
                        printf("usbd_transfer: has old buffer!\n");
 #endif
-               r = bus->methods->allocm(bus, dmap, size);
-               if (r != USBD_NORMAL_COMPLETION)
-                       return (r);
-               reqh->rqflags |= URQ_AUTO_DMABUF;
+               err = bus->methods->allocm(bus, dmap, size);
+               if (err)
+                       return (err);
+               xfer->rqflags |= URQ_AUTO_DMABUF;
        }
 
        /* Copy data if going out. */
-       if (!(reqh->flags & USBD_NO_COPY) && size != 0 && 
-           !usbd_reqh_isread(reqh))
-               memcpy(KERNADDR(dmap), reqh->buffer, size);
+       if (!(xfer->flags & USBD_NO_COPY) && size != 0 && 
+           !usbd_xfer_isread(xfer))
+               memcpy(KERNADDR(dmap), xfer->buffer, size);
 
-       r = pipe->methods->transfer(reqh);
+       err = pipe->methods->transfer(xfer);
 
-       if (r != USBD_IN_PROGRESS && r != USBD_NORMAL_COMPLETION) {
+       if (err != USBD_IN_PROGRESS && err) {
                /* The transfer has not been queued, so free buffer. */
-               if (reqh->rqflags & URQ_AUTO_DMABUF) {
+               if (xfer->rqflags & URQ_AUTO_DMABUF) {
                        struct usbd_bus *bus = pipe->device->bus;
 
-                       bus->methods->freem(bus, &reqh->dmabuf);
-                       reqh->rqflags &= ~URQ_AUTO_DMABUF;
+                       bus->methods->freem(bus, &xfer->dmabuf);
+                       xfer->rqflags &= ~URQ_AUTO_DMABUF;
                }
        }
 
-       if (!(reqh->flags & USBD_SYNCHRONOUS))
-               return (r);
+       if (!(xfer->flags & USBD_SYNCHRONOUS))
+               return (err);
 
        /* Sync transfer, wait for completion. */
-       if (r != USBD_IN_PROGRESS)
-               return (r);
+       if (err != USBD_IN_PROGRESS)
+               return (err);
        s = splusb();
-       if (!reqh->done) {
+       if (!xfer->done) {
                if (pipe->device->bus->use_polling)
                        panic("usbd_transfer: not done\n");
-               tsleep(reqh, PRIBIO, "usbsyn", 0);
+               /* XXX Temporary hack XXX */
+               if (xfer->flags & USBD_NO_TSLEEP) {
+                       int i;
+                       usbd_bus_handle bus = pipe->device->bus;
+                       int to = xfer->timeout * 1000;
+                       for (i = 0; i < to; i += 10) {
+                               delay(10);
+                               bus->methods->do_poll(bus);
+                               if (xfer->done)
+                                       break;
+                       }
+                       if (!xfer->done) {
+                               pipe->methods->abort(xfer);
+                               xfer->status = USBD_TIMEOUT;
+                       }
+               } else
+               /* XXX End hack XXX */
+                       tsleep(xfer, PRIBIO, "usbsyn", 0);
        }
        splx(s);
-       return (reqh->status);
+       return (xfer->status);
 }
 
 /* Like usbd_transfer(), but waits for completion. */
 usbd_status
-usbd_sync_transfer(reqh)
-       usbd_request_handle reqh;
+usbd_sync_transfer(xfer)
+       usbd_xfer_handle xfer;
 {
-       reqh->flags |= USBD_SYNCHRONOUS;
-       return (usbd_transfer(reqh));
+       xfer->flags |= USBD_SYNCHRONOUS;
+       return (usbd_transfer(xfer));
 }
 
 void *
-usbd_alloc_buffer(reqh, size)
-       usbd_request_handle reqh;
+usbd_alloc_buffer(xfer, size)
+       usbd_xfer_handle xfer;
        u_int32_t size;
 {
-       struct usbd_bus *bus = reqh->device->bus;
-       usbd_status r;
+       struct usbd_bus *bus = xfer->device->bus;
+       usbd_status err;
 
-       r = bus->methods->allocm(bus, &reqh->dmabuf, size);
-       if (r != USBD_NORMAL_COMPLETION)
+       err = bus->methods->allocm(bus, &xfer->dmabuf, size);
+       if (err)
                return (0);
-       reqh->rqflags |= URQ_DEV_DMABUF;
-       return (KERNADDR(&reqh->dmabuf));
+       xfer->rqflags |= URQ_DEV_DMABUF;
+       return (KERNADDR(&xfer->dmabuf));
 }
 
 void
-usbd_free_buffer(reqh)
-       usbd_request_handle reqh;
+usbd_free_buffer(xfer)
+       usbd_xfer_handle xfer;
 {
 #ifdef DIAGNOSTIC
-       if (!(reqh->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))) {
+       if (!(xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))) {
                printf("usbd_free_buffer: no buffer\n");
                return;
        }
 #endif
-       reqh->rqflags &= ~(URQ_DEV_DMABUF | URQ_AUTO_DMABUF);
-       reqh->device->bus->methods->freem(reqh->device->bus, &reqh->dmabuf);
+       xfer->rqflags &= ~(URQ_DEV_DMABUF | URQ_AUTO_DMABUF);
+       xfer->device->bus->methods->freem(xfer->device->bus, &xfer->dmabuf);
 }
 
 void *
-usbd_get_buffer(reqh)
-       usbd_request_handle reqh;
+usbd_get_buffer(xfer)
+       usbd_xfer_handle xfer;
 {
-       if (!(reqh->rqflags & URQ_DEV_DMABUF))
+       if (!(xfer->rqflags & URQ_DEV_DMABUF))
                return (0);
-       return (KERNADDR(&reqh->dmabuf));
+       return (KERNADDR(&xfer->dmabuf));
 }
 
-usbd_request_handle 
-usbd_alloc_request(dev)
+usbd_xfer_handle 
+usbd_alloc_xfer(dev)
        usbd_device_handle dev;
 {
-       usbd_request_handle reqh;
-
-       reqh = SIMPLEQ_FIRST(&usbd_free_requests);
-       if (reqh)
-               SIMPLEQ_REMOVE_HEAD(&usbd_free_requests, reqh, next);
-       else
-               reqh = malloc(sizeof(*reqh), M_USB, M_NOWAIT);
-       if (!reqh)
-               return (0);
-       memset(reqh, 0, sizeof *reqh);
-       reqh->device = dev;
-       DPRINTFN(5,("usbd_alloc_request() = %p\n", reqh));
-       return (reqh);
+       usbd_xfer_handle xfer;
+
+       xfer = dev->bus->methods->allocx(dev->bus);
+       if (!xfer)
+               return (NULL);
+       xfer->device = dev;
+       DPRINTFN(5,("usbd_alloc_xfer() = %p\n", xfer));
+       return (xfer);
 }
 
 usbd_status 
-usbd_free_request(reqh)
-       usbd_request_handle reqh;
+usbd_free_xfer(xfer)
+       usbd_xfer_handle xfer;
 {
-       DPRINTFN(5,("usbd_free_request: %p\n", reqh));
-       if (reqh->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))
-               usbd_free_buffer(reqh);
-       SIMPLEQ_INSERT_HEAD(&usbd_free_requests, reqh, next);
+       DPRINTFN(5,("usbd_free_xfer: %p\n", xfer));
+       if (xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))
+               usbd_free_buffer(xfer);
+       xfer->device->bus->methods->freex(xfer->device->bus, xfer);
        return (USBD_NORMAL_COMPLETION);
 }
 
 void
-usbd_setup_request(reqh, pipe, priv, buffer, length, flags, timeout, callback)
-       usbd_request_handle reqh;
+usbd_setup_xfer(xfer, pipe, priv, buffer, length, flags, timeout, callback)
+       usbd_xfer_handle xfer;
        usbd_pipe_handle pipe;
        usbd_private_handle priv;
        void *buffer;
        u_int32_t length;
        u_int16_t flags;
        u_int32_t timeout;
-       void (*callback) __P((usbd_request_handle,
+       void (*callback) __P((usbd_xfer_handle,
                              usbd_private_handle,
                              usbd_status));
 {
-       reqh->pipe = pipe;
-       reqh->priv = priv;
-       reqh->buffer = buffer;
-       reqh->length = length;
-       reqh->actlen = 0;
-       reqh->flags = flags;
-       reqh->timeout = timeout;
-       reqh->status = USBD_NOT_STARTED;
-       reqh->callback = callback;
-       reqh->rqflags &= ~URQ_REQUEST;
-       reqh->nframes = 0;
+       xfer->pipe = pipe;
+       xfer->priv = priv;
+       xfer->buffer = buffer;
+       xfer->length = length;
+       xfer->actlen = 0;
+       xfer->flags = flags;
+       xfer->timeout = timeout;
+       xfer->status = USBD_NOT_STARTED;
+       xfer->callback = callback;
+       xfer->rqflags &= ~URQ_REQUEST;
+       xfer->nframes = 0;
 }
 
 void
-usbd_setup_default_request(reqh, dev, priv, timeout, req, buffer, 
+usbd_setup_default_xfer(xfer, dev, priv, timeout, req, buffer, 
                           length, flags, callback)
-       usbd_request_handle reqh;
+       usbd_xfer_handle xfer;
        usbd_device_handle dev;
        usbd_private_handle priv;
        u_int32_t timeout;
@@ -408,27 +436,27 @@ usbd_setup_default_request(reqh, dev, priv, timeout, req, buffer,
        void *buffer;
        u_int32_t length;
        u_int16_t flags;
-       void (*callback) __P((usbd_request_handle,
+       void (*callback) __P((usbd_xfer_handle,
                              usbd_private_handle,
                              usbd_status));
 {
-       reqh->pipe = dev->default_pipe;
-       reqh->priv = priv;
-       reqh->buffer = buffer;
-       reqh->length = length;
-       reqh->actlen = 0;
-       reqh->flags = flags;
-       reqh->timeout = timeout;
-       reqh->status = USBD_NOT_STARTED;
-       reqh->callback = callback;
-       reqh->request = *req;
-       reqh->rqflags |= URQ_REQUEST;
-       reqh->nframes = 0;
+       xfer->pipe = dev->default_pipe;
+       xfer->priv = priv;
+       xfer->buffer = buffer;
+       xfer->length = length;
+       xfer->actlen = 0;
+       xfer->flags = flags;
+       xfer->timeout = timeout;
+       xfer->status = USBD_NOT_STARTED;
+       xfer->callback = callback;
+       xfer->request = *req;
+       xfer->rqflags |= URQ_REQUEST;
+       xfer->nframes = 0;
 }
 
 void
-usbd_setup_isoc_request(reqh, pipe, priv, frlengths, nframes, flags, callback)
-       usbd_request_handle reqh;
+usbd_setup_isoc_xfer(xfer, pipe, priv, frlengths, nframes, flags, callback)
+       usbd_xfer_handle xfer;
        usbd_pipe_handle pipe;
        usbd_private_handle priv;
        u_int16_t *frlengths;
@@ -436,42 +464,48 @@ usbd_setup_isoc_request(reqh, pipe, priv, frlengths, nframes, flags, callback)
        u_int16_t flags;
        usbd_callback callback;
 {
-       reqh->pipe = pipe;
-       reqh->priv = priv;
-       reqh->buffer = 0;
-       reqh->length = 0;
-       reqh->actlen = 0;
-       reqh->flags = flags;
-       reqh->timeout = USBD_NO_TIMEOUT;
-       reqh->status = USBD_NOT_STARTED;
-       reqh->callback = callback;
-       reqh->rqflags &= ~URQ_REQUEST;
-       reqh->frlengths = frlengths;
-       reqh->nframes = nframes;
+       xfer->pipe = pipe;
+       xfer->priv = priv;
+       xfer->buffer = 0;
+       xfer->length = 0;
+       xfer->actlen = 0;
+       xfer->flags = flags;
+       xfer->timeout = USBD_NO_TIMEOUT;
+       xfer->status = USBD_NOT_STARTED;
+       xfer->callback = callback;
+       xfer->rqflags &= ~URQ_REQUEST;
+       xfer->frlengths = frlengths;
+       xfer->nframes = nframes;
 }
 
 void
-usbd_get_request_status(reqh, priv, buffer, count, status)
-       usbd_request_handle reqh;
+usbd_get_xfer_status(xfer, priv, buffer, count, status)
+       usbd_xfer_handle xfer;
        usbd_private_handle *priv;
        void **buffer;
        u_int32_t *count;
        usbd_status *status;
 {
-       if (priv)
-               *priv = reqh->priv;
-       if (buffer)
-               *buffer = reqh->buffer;
-       if (count)
-               *count = reqh->actlen;
-       if (status)
-               *status = reqh->status;
+       if (priv != NULL)
+               *priv = xfer->priv;
+       if (buffer != NULL)
+               *buffer = xfer->buffer;
+       if (count != NULL)
+               *count = xfer->actlen;
+       if (status != NULL)
+               *status = xfer->status;
 }
 
 usb_config_descriptor_t *
 usbd_get_config_descriptor(dev)
        usbd_device_handle dev;
 {
+#ifdef DIAGNOSTIC
+       if (dev == NULL) {
+               printf("usbd_get_config_descriptor: dev == NULL\n");
+               return (NULL);
+       }
+#endif
        return (dev->cdesc);
 }
 
@@ -479,6 +513,12 @@ usb_interface_descriptor_t *
 usbd_get_interface_descriptor(iface)
        usbd_interface_handle iface;
 {
+#ifdef DIAGNOSTIC
+       if (iface == NULL) {
+               printf("usbd_get_interface_descriptor: dev == NULL\n");
+               return (NULL);
+       }
+#endif
        return (iface->idesc);
 }
 
@@ -503,19 +543,19 @@ usbd_status
 usbd_abort_pipe(pipe)
        usbd_pipe_handle pipe;
 {
-       usbd_status r;
+       usbd_status err;
        int s;
 
 #ifdef DIAGNOSTIC
-       if (pipe == 0) {
+       if (pipe == NULL) {
                printf("usbd_close_pipe: pipe==NULL\n");
                return (USBD_NORMAL_COMPLETION);
        }
 #endif
        s = splusb();
-       r = usbd_ar_pipe(pipe);
+       err = usbd_ar_pipe(pipe);
        splx(s);
-       return (r);
+       return (err);
 }
        
 usbd_status 
@@ -524,7 +564,7 @@ usbd_clear_endpoint_stall(pipe)
 {
        usbd_device_handle dev = pipe->device;
        usb_device_request_t req;
-       usbd_status r;
+       usbd_status err;
 
        DPRINTFN(8, ("usbd_clear_endpoint_stall\n"));
 
@@ -539,15 +579,15 @@ usbd_clear_endpoint_stall(pipe)
        USETW(req.wValue, UF_ENDPOINT_HALT);
        USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
        USETW(req.wLength, 0);
-       r = usbd_do_request(dev, &req, 0);
+       err = usbd_do_request(dev, &req, 0);
 #if 0
 XXX should we do this?
-       if (r == USBD_NORMAL_COMPLETION) {
+       if (!err) {
                pipe->state = USBD_PIPE_ACTIVE;
                /* XXX activate pipe */
        }
 #endif
-       return (r);
+       return (err);
 }
 
 usbd_status 
@@ -556,7 +596,7 @@ usbd_clear_endpoint_stall_async(pipe)
 {
        usbd_device_handle dev = pipe->device;
        usb_device_request_t req;
-       usbd_status r;
+       usbd_status err;
 
        pipe->methods->cleartoggle(pipe);
 
@@ -565,8 +605,16 @@ usbd_clear_endpoint_stall_async(pipe)
        USETW(req.wValue, UF_ENDPOINT_HALT);
        USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
        USETW(req.wLength, 0);
-       r = usbd_do_request_async(dev, &req, 0);
-       return (r);
+       err = usbd_do_request_async(dev, &req, 0);
+       return (err);
+}
+
+void usbd_clear_endpoint_toggle(usbd_pipe_handle pipe); /* XXXXX */
+void
+usbd_clear_endpoint_toggle(pipe)
+       usbd_pipe_handle pipe;
+{
+       pipe->methods->cleartoggle(pipe);
 }
 
 usbd_status 
@@ -583,7 +631,7 @@ usbd_interface_count(dev, count)
        usbd_device_handle dev;
        u_int8_t *count;
 {
-       if (!dev->cdesc)
+       if (dev->cdesc == NULL)
                return (USBD_NOT_CONFIGURED);
        *count = dev->cdesc->bNumInterface;
        return (USBD_NORMAL_COMPLETION);
@@ -604,7 +652,7 @@ usbd_device2interface_handle(dev, ifaceno, iface)
        u_int8_t ifaceno;
        usbd_interface_handle *iface;
 {
-       if (!dev->cdesc)
+       if (dev->cdesc == NULL)
                return (USBD_NOT_CONFIGURED);
        if (ifaceno >= dev->cdesc->bNumInterface)
                return (USBD_INVAL);
@@ -626,7 +674,7 @@ usbd_set_interface(iface, altidx)
        int altidx;
 {
        usb_device_request_t req;
-       usbd_status r;
+       usbd_status err;
 
        if (LIST_FIRST(&iface->pipes) != 0)
                return (USBD_IN_USE);
@@ -636,16 +684,16 @@ usbd_set_interface(iface, altidx)
        iface->endpoints = 0;
        iface->idesc = 0;
 
-       r = usbd_fill_iface_data(iface->device, iface->index, altidx);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = usbd_fill_iface_data(iface->device, iface->index, altidx);
+       if (err)
+               return (err);
 
        req.bmRequestType = UT_WRITE_INTERFACE;
        req.bRequest = UR_SET_INTERFACE;
        USETW(req.wValue, iface->idesc->bAlternateSetting);
        USETW(req.wIndex, iface->idesc->bInterfaceNumber);
        USETW(req.wLength, 0);
-       return usbd_do_request(iface->device, &req, 0);
+       return (usbd_do_request(iface->device, &req, 0));
 }
 
 int
@@ -687,7 +735,7 @@ usbd_get_interface(iface, aiface)
        USETW(req.wValue, 0);
        USETW(req.wIndex, iface->idesc->bInterfaceNumber);
        USETW(req.wLength, 1);
-       return usbd_do_request(iface->device, &req, aiface);
+       return (usbd_do_request(iface->device, &req, aiface));
 }
 
 /*** Internal routines ***/
@@ -697,7 +745,7 @@ static usbd_status
 usbd_ar_pipe(pipe)
        usbd_pipe_handle pipe;
 {
-       usbd_request_handle reqh;
+       usbd_xfer_handle xfer;
 
        SPLUSBCHECK;
 
@@ -707,11 +755,11 @@ usbd_ar_pipe(pipe)
                usbd_dump_queue(pipe);
 #endif
        pipe->repeat = 0;
-       while ((reqh = SIMPLEQ_FIRST(&pipe->queue))) {
-               DPRINTFN(2,("usbd_ar_pipe: pipe=%p reqh=%p (methods=%p)\n", 
-                           pipe, reqh, pipe->methods));
+       while ((xfer = SIMPLEQ_FIRST(&pipe->queue)) != NULL) {
+               DPRINTFN(2,("usbd_ar_pipe: pipe=%p xfer=%p (methods=%p)\n", 
+                           pipe, xfer, pipe->methods));
                /* Make the HC abort it (and invoke the callback). */
-               pipe->methods->abort(reqh);
+               pipe->methods->abort(xfer);
                /* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */
        }
        return (USBD_NORMAL_COMPLETION);
@@ -719,22 +767,22 @@ usbd_ar_pipe(pipe)
 
 /* Called at splusb() */
 void
-usb_transfer_complete(reqh)
-       usbd_request_handle reqh;
+usb_transfer_complete(xfer)
+       usbd_xfer_handle xfer;
 {
-       usbd_pipe_handle pipe = reqh->pipe;
-       usb_dma_t *dmap = &reqh->dmabuf;
+       usbd_pipe_handle pipe = xfer->pipe;
+       usb_dma_t *dmap = &xfer->dmabuf;
        int repeat = pipe->repeat;
        int polling;
 
        SPLUSBCHECK;
 
-       DPRINTFN(5, ("usb_transfer_complete: pipe=%p reqh=%p status=%d actlen=%d\n",
-                    pipe, reqh, reqh->status, reqh->actlen));
+       DPRINTFN(5, ("usb_transfer_complete: pipe=%p xfer=%p status=%d actlen=%d\n",
+                    pipe, xfer, xfer->status, xfer->actlen));
 
 #ifdef DIAGNOSTIC
-       if (!pipe) {
-               printf("usbd_transfer_cb: pipe==0, reqh=%p\n", reqh);
+       if (pipe == NULL) {
+               printf("usbd_transfer_cb: pipe==0, xfer=%p\n", xfer);
                return;
        }
 #endif
@@ -743,63 +791,71 @@ usb_transfer_complete(reqh)
        if (polling)
                pipe->running = 0;
 
-       if (!(reqh->flags & USBD_NO_COPY) && reqh->actlen != 0 &&
-           usbd_reqh_isread(reqh)) {
+       if (!(xfer->flags & USBD_NO_COPY) && xfer->actlen != 0 &&
+           usbd_xfer_isread(xfer)) {
 #ifdef DIAGNOSTIC
-               if (reqh->actlen > reqh->length) {
+               if (xfer->actlen > xfer->length) {
                        printf("usb_transfer_complete: actlen > len %d > %d\n",
-                              reqh->actlen, reqh->length);
-                       reqh->actlen = reqh->length;
+                              xfer->actlen, xfer->length);
+                       xfer->actlen = xfer->length;
                }
 #endif
-               memcpy(reqh->buffer, KERNADDR(dmap), reqh->actlen);
+               memcpy(xfer->buffer, KERNADDR(dmap), xfer->actlen);
        }
 
        /* if we allocated the buffer in usbd_transfer() we free it here. */
-       if (reqh->rqflags & URQ_AUTO_DMABUF) {
+       if (xfer->rqflags & URQ_AUTO_DMABUF) {
                if (!repeat) {
                        struct usbd_bus *bus = pipe->device->bus;
                        bus->methods->freem(bus, dmap);
-                       reqh->rqflags &= ~URQ_AUTO_DMABUF;
+                       xfer->rqflags &= ~URQ_AUTO_DMABUF;
                }
        }
 
-       if (pipe->methods->done)
-               pipe->methods->done(reqh);
-
        if (!repeat) {
                /* Remove request from queue. */
 #ifdef DIAGNOSTIC
-               if (reqh != SIMPLEQ_FIRST(&pipe->queue))
+               if (xfer != SIMPLEQ_FIRST(&pipe->queue))
                        printf("usb_transfer_complete: bad dequeue %p != %p\n",
-                              reqh, SIMPLEQ_FIRST(&pipe->queue));
+                              xfer, SIMPLEQ_FIRST(&pipe->queue));
 #endif
-               SIMPLEQ_REMOVE_HEAD(&pipe->queue, reqh, next);
+               SIMPLEQ_REMOVE_HEAD(&pipe->queue, xfer, next);
        }
+       DPRINTFN(5,("usb_transfer_complete: repeat=%d new head=%p\n",
+                   repeat, SIMPLEQ_FIRST(&pipe->queue)));
 
        /* Count completed transfers. */
        ++pipe->device->bus->stats.requests
                [pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE];
 
-       reqh->done = 1;
-       if (reqh->status == USBD_NORMAL_COMPLETION &&
-           reqh->actlen < reqh->length &&
-           !(reqh->flags & USBD_SHORT_XFER_OK)) {
+       xfer->done = 1;
+       if (xfer->status && xfer->actlen < xfer->length &&
+           !(xfer->flags & USBD_SHORT_XFER_OK)) {
                DPRINTFN(-1, ("usbd_transfer_cb: short xfer %d<%d (bytes)\n",
-                             reqh->actlen, reqh->length));
-               reqh->status = USBD_SHORT_XFER;
+                             xfer->actlen, xfer->length));
+               xfer->status = USBD_SHORT_XFER;
        }
 
-       if (reqh->callback)
-               reqh->callback(reqh, reqh->priv, reqh->status);
+       if (xfer->callback)
+               xfer->callback(xfer, xfer->priv, xfer->status);
+
+#ifdef DIAGNOSTIC
+       if (pipe->methods->done != NULL)
+               pipe->methods->done(xfer);
+       else
+               printf("usb_transfer_complete: pipe->methods->done == NULL\n");
+#else
+       pipe->methods->done(xfer);
+#endif
 
-       if ((reqh->flags & USBD_SYNCHRONOUS) && !polling)
-               wakeup(reqh);
+       if ((xfer->flags & USBD_SYNCHRONOUS) && !polling)
+               wakeup(xfer);
 
        if (!repeat) {
                /* XXX should we stop the queue on all errors? */
-               if (reqh->status == USBD_CANCELLED ||
-                   reqh->status == USBD_TIMEOUT)
+               if ((xfer->status == USBD_CANCELLED ||
+                   xfer->status == USBD_TIMEOUT) &&
+                  pipe->iface != NULL)                 /* not control pipe */
                        pipe->running = 0;
                else
                        usbd_start_next(pipe);
@@ -807,25 +863,25 @@ usb_transfer_complete(reqh)
 }
 
 usbd_status
-usb_insert_transfer(reqh)
-       usbd_request_handle reqh;
+usb_insert_transfer(xfer)
+       usbd_xfer_handle xfer;
 {
-       usbd_pipe_handle pipe = reqh->pipe;
-       usbd_status r;
+       usbd_pipe_handle pipe = xfer->pipe;
+       usbd_status err;
        int s;
 
        DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d timeout=%d\n", 
-                   pipe, pipe->running, reqh->timeout));
+                   pipe, pipe->running, xfer->timeout));
        s = splusb();
-       SIMPLEQ_INSERT_TAIL(&pipe->queue, reqh, next);
+       SIMPLEQ_INSERT_TAIL(&pipe->queue, xfer, next);
        if (pipe->running)
-               r = USBD_IN_PROGRESS;
+               err = USBD_IN_PROGRESS;
        else {
                pipe->running = 1;
-               r = USBD_NORMAL_COMPLETION;
+               err = USBD_NORMAL_COMPLETION;
        }
        splx(s);
-       return (r);
+       return (err);
 }
 
 /* Called at splusb() */
@@ -833,33 +889,31 @@ void
 usbd_start_next(pipe)
        usbd_pipe_handle pipe;
 {
-       usbd_request_handle reqh;
-       usbd_status r;
+       usbd_xfer_handle xfer;
+       usbd_status err;
 
        SPLUSBCHECK;
 
-       DPRINTFN(10, ("usbd_start_next: pipe=%p\n", pipe));
-       
 #ifdef DIAGNOSTIC
-       if (!pipe) {
-               printf("usbd_start_next: pipe == 0\n");
+       if (pipe == NULL) {
+               printf("usbd_start_next: pipe == NULL\n");
                return;
        }
-       if (!pipe->methods || !pipe->methods->start) {
-               printf("usbd_start_next:  no start method\n");
+       if (pipe->methods == NULL || pipe->methods->start == NULL) {
+               printf("usbd_start_next: pipe=%p no start method\n", pipe);
                return;
        }
 #endif
 
        /* Get next request in queue. */
-       reqh = SIMPLEQ_FIRST(&pipe->queue);
-       DPRINTFN(5, ("usbd_start_next: pipe=%p start reqh=%p\n", pipe, reqh));
-       if (!reqh)
+       xfer = SIMPLEQ_FIRST(&pipe->queue);
+       DPRINTFN(5, ("usbd_start_next: pipe=%p, xfer=%p\n", pipe, xfer));
+       if (xfer == NULL) {
                pipe->running = 0;
-       else {
-               r = pipe->methods->start(reqh);
-               if (r != USBD_IN_PROGRESS) {
-                       printf("usbd_start_next: error=%d\n", r);
+       else {
+               err = pipe->methods->start(xfer);
+               if (err != USBD_IN_PROGRESS) {
+                       printf("usbd_start_next: error=%d\n", err);
                        pipe->running = 0;
                        /* XXX do what? */
                }
@@ -883,35 +937,39 @@ usbd_do_request_flags(dev, req, data, flags, actlen)
        u_int16_t flags;
        int *actlen;
 {
-       usbd_request_handle reqh;
-       usbd_status r;
+       usbd_xfer_handle xfer;
+       usbd_status err;
 
 #ifdef DIAGNOSTIC
+#if defined(__i386__) && defined(__FreeBSD__)
+       KASSERT(intr_nesting_level == 0,
+               ("usbd_do_request: in interrupt context"));
+#endif
        if (dev->bus->intr_context) {
                printf("usbd_do_request: not in process context\n");
                return (USBD_INVAL);
        }
 #endif
 
-       reqh = usbd_alloc_request(dev);
-       if (reqh == 0)
+       xfer = usbd_alloc_xfer(dev);
+       if (xfer == NULL)
                return (USBD_NOMEM);
-       usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT, req,
+       usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, req,
                                   data, UGETW(req->wLength), flags, 0);
-       r = usbd_sync_transfer(reqh);
+       err = usbd_sync_transfer(xfer);
 #if defined(USB_DEBUG) || defined(DIAGNOSTIC)
-       if (reqh->actlen > reqh->length)
+       if (xfer->actlen > xfer->length)
                DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
                         "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
-                        dev->address, reqh->request.bmRequestType,
-                        reqh->request.bRequest, UGETW(reqh->request.wValue),
-                        UGETW(reqh->request.wIndex), 
-                        UGETW(reqh->request.wLength), 
-                        reqh->length, reqh->actlen));
+                        dev->address, xfer->request.bmRequestType,
+                        xfer->request.bRequest, UGETW(xfer->request.wValue),
+                        UGETW(xfer->request.wIndex), 
+                        UGETW(xfer->request.wLength), 
+                        xfer->length, xfer->actlen));
 #endif
-       if (actlen)
-               *actlen = reqh->actlen;
-       if (r == USBD_STALLED) {
+       if (actlen != NULL)
+               *actlen = xfer->actlen;
+       if (err == USBD_STALLED) {
                /* 
                 * The control endpoint has stalled.  Control endpoints
                 * should not halt, but some may do so anyway so clear
@@ -920,18 +978,18 @@ usbd_do_request_flags(dev, req, data, flags, actlen)
                usb_device_request_t treq;
                usb_status_t status;
                u_int16_t s;
-               usbd_status nr;
+               usbd_status nerr;
 
                treq.bmRequestType = UT_READ_ENDPOINT;
                treq.bRequest = UR_GET_STATUS;
                USETW(treq.wValue, 0);
                USETW(treq.wIndex, 0);
                USETW(treq.wLength, sizeof(usb_status_t));
-               usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT,
+               usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT,
                                           &treq, &status,sizeof(usb_status_t),
                                           0, 0);
-               nr = usbd_sync_transfer(reqh);
-               if (nr != USBD_NORMAL_COMPLETION)
+               nerr = usbd_sync_transfer(xfer);
+               if (nerr)
                        goto bad;
                s = UGETW(status.wStatus);
                DPRINTF(("usbd_do_request: status = 0x%04x\n", s));
@@ -942,36 +1000,36 @@ usbd_do_request_flags(dev, req, data, flags, actlen)
                USETW(treq.wValue, UF_ENDPOINT_HALT);
                USETW(treq.wIndex, 0);
                USETW(treq.wLength, 0);
-               usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT,
+               usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT,
                                           &treq, &status, 0, 0, 0);
-               nr = usbd_sync_transfer(reqh);
-               if (nr != USBD_NORMAL_COMPLETION)
+               nerr = usbd_sync_transfer(xfer);
+               if (nerr)
                        goto bad;
        }
 
  bad:
-       usbd_free_request(reqh);
-       return (r);
+       usbd_free_xfer(xfer);
+       return (err);
 }
 
 void
-usbd_do_request_async_cb(reqh, priv, status)
-       usbd_request_handle reqh;
+usbd_do_request_async_cb(xfer, priv, status)
+       usbd_xfer_handle xfer;
        usbd_private_handle priv;
        usbd_status status;
 {
 #if defined(USB_DEBUG) || defined(DIAGNOSTIC)
-       if (reqh->actlen > reqh->length)
+       if (xfer->actlen > xfer->length)
                DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
                         "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
-                        reqh->pipe->device->address, 
-                        reqh->request.bmRequestType,
-                        reqh->request.bRequest, UGETW(reqh->request.wValue),
-                        UGETW(reqh->request.wIndex), 
-                        UGETW(reqh->request.wLength), 
-                        reqh->length, reqh->actlen));
+                        xfer->pipe->device->address, 
+                        xfer->request.bmRequestType,
+                        xfer->request.bRequest, UGETW(xfer->request.wValue),
+                        UGETW(xfer->request.wIndex), 
+                        UGETW(xfer->request.wLength), 
+                        xfer->length, xfer->actlen));
 #endif
-       usbd_free_request(reqh);
+       usbd_free_xfer(xfer);
 }
 
 /*
@@ -984,19 +1042,19 @@ usbd_do_request_async(dev, req, data)
        usb_device_request_t *req;
        void *data;
 {
-       usbd_request_handle reqh;
-       usbd_status r;
+       usbd_xfer_handle xfer;
+       usbd_status err;
 
-       reqh = usbd_alloc_request(dev);
-       if (reqh == 0)
+       xfer = usbd_alloc_xfer(dev);
+       if (xfer == NULL)
                return (USBD_NOMEM);
-       usbd_setup_default_request(reqh, dev, 0, USBD_DEFAULT_TIMEOUT, req, data, 
+       usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, req, data, 
                                   UGETW(req->wLength), 0, 
                                   usbd_do_request_async_cb);
-       r = usbd_transfer(reqh);
-       if (r != USBD_IN_PROGRESS) {
-               usbd_free_request(reqh);
-               return (r);
+       err = usbd_transfer(xfer);
+       if (err != USBD_IN_PROGRESS) {
+               usbd_free_xfer(xfer);
+               return (err);
        }
        return (USBD_NORMAL_COMPLETION);
 }
@@ -1021,14 +1079,14 @@ usbd_dopoll(iface)
 }
 
 void
-usbd_set_polling(iface, on)
-       usbd_interface_handle iface;
+usbd_set_polling(dev, on)
+       usbd_device_handle dev;
        int on;
 {
        if (on)
-               iface->device->bus->use_polling++;
+               dev->bus->use_polling++;
        else
-               iface->device->bus->use_polling--;
+               dev->bus->use_polling--;
 }
 
 
@@ -1048,6 +1106,21 @@ usbd_get_endpoint_descriptor(iface, address)
        return (0);
 }
 
+/*
+ * usbd_ratecheck() can limit the number of error messages that occurs.
+ * When a device is unplugged it may take up to 0.25s for the hub driver
+ * to notice it.  If the driver continuously tries to do I/O operations
+ * this can generate a large number of messages.
+ */
+int
+usbd_ratecheck(last)
+       struct timeval *last;
+{
+       struct timeval errinterval = { 0, 250000 }; /* 0.25s */
+
+       return (ratecheck(last, &errinterval));
+}
+
 #if defined(__FreeBSD__)
 int
 usbd_driver_load(module_t mod, int what, void *arg)
index 7efe8ac..29f969c 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: usbdi.h,v 1.6 1999/11/07 21:30:20 fgsch Exp $ */
-/*     $NetBSD: usbdi.h,v 1.31 1999/10/13 08:10:58 augustss Exp $      */
+/*     $OpenBSD: usbdi.h,v 1.7 2000/03/26 08:39:46 aaron Exp $ */
+/*     $NetBSD: usbdi.h,v 1.31 2000/03/02 12:37:51 augustss Exp $      */
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -42,7 +42,7 @@ typedef struct usbd_bus               *usbd_bus_handle;
 typedef struct usbd_device     *usbd_device_handle;
 typedef struct usbd_interface  *usbd_interface_handle;
 typedef struct usbd_pipe       *usbd_pipe_handle;
-typedef struct usbd_request    *usbd_request_handle;
+typedef struct usbd_xfer       *usbd_xfer_handle;
 typedef void                   *usbd_private_handle;
 
 typedef enum {         /* keep in sync with usbd_status_msgs */ 
@@ -70,18 +70,23 @@ typedef enum {              /* keep in sync with usbd_status_msgs */
        USBD_ERROR_MAX,         /* must be last */
 } usbd_status;
 
-typedef int usbd_lock_token;
-
-typedef void (*usbd_callback) __P((usbd_request_handle, usbd_private_handle,
+typedef void (*usbd_callback) __P((usbd_xfer_handle, usbd_private_handle,
                                   usbd_status));
 
 /* Open flags */
 #define USBD_EXCLUSIVE_USE     0x01
 
+/* Use default (specified by ep. desc.) interval on interrupt pipe */
+#define USBD_DEFAULT_INTERVAL  (-1)
+
 /* Request flags */
 #define USBD_NO_COPY           0x01    /* do not copy data to DMA buffer */
 #define USBD_SYNCHRONOUS       0x02    /* wait for completion */
 /* in usb.h #define USBD_SHORT_XFER_OK 0x04*/  /* allow short reads */
+#define USBD_FORCE_SHORT_XFER  0x08    /* force last short packet on write */
+
+/* XXX Temporary hack XXX */
+#define USBD_NO_TSLEEP         0x80    /* XXX use busy wait */
 
 #define USBD_NO_TIMEOUT 0
 #define USBD_DEFAULT_TIMEOUT 5000 /* ms = 5 s */
@@ -94,25 +99,25 @@ usbd_status usbd_open_pipe
        __P((usbd_interface_handle iface, u_int8_t address,
             u_int8_t flags, usbd_pipe_handle *pipe));
 usbd_status usbd_close_pipe    __P((usbd_pipe_handle pipe));
-usbd_status usbd_transfer      __P((usbd_request_handle req));
-usbd_request_handle usbd_alloc_request __P((usbd_device_handle));
-usbd_status usbd_free_request  __P((usbd_request_handle reqh));
-void usbd_setup_request        
-       __P((usbd_request_handle reqh, usbd_pipe_handle pipe,
+usbd_status usbd_transfer      __P((usbd_xfer_handle req));
+usbd_xfer_handle usbd_alloc_xfer       __P((usbd_device_handle));
+usbd_status usbd_free_xfer     __P((usbd_xfer_handle xfer));
+void usbd_setup_xfer
+       __P((usbd_xfer_handle xfer, usbd_pipe_handle pipe,
             usbd_private_handle priv, void *buffer,
             u_int32_t length, u_int16_t flags, u_int32_t timeout,
             usbd_callback));
-void usbd_setup_default_request
-       __P((usbd_request_handle reqh, usbd_device_handle dev,
+void usbd_setup_default_xfer
+       __P((usbd_xfer_handle xfer, usbd_device_handle dev,
             usbd_private_handle priv, u_int32_t timeout,
             usb_device_request_t *req,  void *buffer,
             u_int32_t length, u_int16_t flags, usbd_callback));
-void usbd_setup_isoc_request   
-       __P((usbd_request_handle reqh, usbd_pipe_handle pipe,
+void usbd_setup_isoc_xfer
+       __P((usbd_xfer_handle xfer, usbd_pipe_handle pipe,
             usbd_private_handle priv, u_int16_t *frlengths,
             u_int32_t nframes, u_int16_t flags, usbd_callback));
-void usbd_get_request_status
-       __P((usbd_request_handle reqh, usbd_private_handle *priv,
+void usbd_get_xfer_status
+       __P((usbd_xfer_handle xfer, usbd_private_handle *priv,
             void **buffer, u_int32_t *count, usbd_status *status));
 usb_endpoint_descriptor_t *usbd_interface2endpoint_descriptor
        __P((usbd_interface_handle iface, u_int8_t address));
@@ -129,15 +134,15 @@ usbd_status usbd_device2interface_handle
        __P((usbd_device_handle dev, u_int8_t ifaceno, usbd_interface_handle *iface));
 
 usbd_device_handle usbd_pipe2device_handle __P((usbd_pipe_handle));
-void *usbd_alloc_buffer __P((usbd_request_handle req, u_int32_t size));
-void usbd_free_buffer __P((usbd_request_handle req));
-void *usbd_get_buffer __P((usbd_request_handle reqh));
-usbd_status usbd_sync_transfer __P((usbd_request_handle req));
+void *usbd_alloc_buffer __P((usbd_xfer_handle req, u_int32_t size));
+void usbd_free_buffer __P((usbd_xfer_handle req));
+void *usbd_get_buffer __P((usbd_xfer_handle xfer));
+usbd_status usbd_sync_transfer __P((usbd_xfer_handle req));
 usbd_status usbd_open_pipe_intr
        __P((usbd_interface_handle iface, u_int8_t address,
             u_int8_t flags, usbd_pipe_handle *pipe,
             usbd_private_handle priv, void *buffer,
-            u_int32_t length, usbd_callback));
+            u_int32_t length, usbd_callback, int));
 usbd_status usbd_do_request 
        __P((usbd_device_handle pipe, usb_device_request_t *req, void *data));
 usbd_status usbd_do_request_async
@@ -166,11 +171,21 @@ usb_endpoint_descriptor_t *usbd_find_edesc
             int endptidx));
 
 void usbd_dopoll __P((usbd_interface_handle));
-void usbd_set_polling __P((usbd_interface_handle iface, int on));
+void usbd_set_polling __P((usbd_device_handle iface, int on));
 
 const char *usbd_errstr __P((usbd_status err));
 
-void usbd_add_event __P((int, usbd_device_handle));
+void usbd_add_dev_event __P((int, usbd_device_handle));
+void usbd_add_drv_event __P((int, usbd_device_handle, device_ptr_t));
+
+void usbd_devinfo __P((usbd_device_handle, int, char *));
+struct usbd_quirks *usbd_get_quirks __P((usbd_device_handle));
+usb_endpoint_descriptor_t *usbd_get_endpoint_descriptor
+       __P((usbd_interface_handle iface, u_int8_t address));
+
+usbd_status usbd_reload_device_desc __P((usbd_device_handle));
+
+int usbd_ratecheck __P((struct timeval *last));
 
 /* NetBSD attachment information */
 
@@ -231,17 +246,19 @@ struct usb_attach_arg {
 
 #endif
 
-void usbd_devinfo __P((usbd_device_handle, int, char *));
-struct usbd_quirks *usbd_get_quirks __P((usbd_device_handle));
-usb_endpoint_descriptor_t *usbd_get_endpoint_descriptor
-       __P((usbd_interface_handle iface, u_int8_t address));
-
 #if defined(__FreeBSD__)
 int usbd_driver_load    __P((module_t mod, int what, void *arg));
 #endif
 
+/*
+ * XXX
+ * splusb MUST be the lowest level interrupt so that within USB callbacks
+ * the level can be raised the appropriate level.
+ * XXX Should probably use a softsplusb.
+ */
 /* XXX */
 #define splusb splbio
+#define splhardusb splbio
 #define IPL_USB IPL_BIO
 /* XXX */
 
index 52a55f0..152e81d 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: usbdi_util.c,v 1.5 1999/11/07 21:30:20 fgsch Exp $    */
-/*     $NetBSD: usbdi_util.c,v 1.22 1999/10/13 08:10:59 augustss Exp $ */
+/*     $OpenBSD: usbdi_util.c,v 1.6 2000/03/26 08:39:46 aaron Exp $    */
+/*     $NetBSD: usbdi_util.c,v 1.28 2000/02/22 11:25:06 augustss Exp $ */
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -42,9 +42,8 @@
 #include <sys/systm.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
-#include <sys/proc.h>
-#include <sys/device.h>
 #if defined(__NetBSD__) || defined(__OpenBSD__)
+#include <sys/proc.h>
 #include <sys/device.h>
 #elif defined(__FreeBSD__)
 #include <sys/bus.h>
@@ -74,6 +73,9 @@ usbd_get_desc(dev, type, index, len, desc)
 {
        usb_device_request_t req;
 
+       DPRINTFN(3,("usbd_get_desc: type=%d, index=%d, len=%d\n",
+                   type, index, len));
+
        req.bmRequestType = UT_READ_DEVICE;
        req.bRequest = UR_GET_DESCRIPTOR;
        USETW2(req.wValue, type, index);
@@ -83,21 +85,22 @@ usbd_get_desc(dev, type, index, len, desc)
 }
 
 usbd_status
-usbd_get_config_desc(dev, conf, d)
+usbd_get_config_desc(dev, confidx, d)
        usbd_device_handle dev;
-       int conf;
+       int confidx;
        usb_config_descriptor_t *d;
 {
-       usbd_status r;
+       usbd_status err;
 
-       DPRINTFN(3,("usbd_get_config_desc: conf=%d\n", conf));
-       r = usbd_get_desc(dev, UDESC_CONFIG, conf, 
-                         USB_CONFIG_DESCRIPTOR_SIZE, d);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       DPRINTFN(3,("usbd_get_config_desc: confidx=%d\n", confidx));
+       err = usbd_get_desc(dev, UDESC_CONFIG, confidx,
+                           USB_CONFIG_DESCRIPTOR_SIZE, d);
+       if (err)
+               return (err);
        if (d->bDescriptorType != UDESC_CONFIG) {
-               DPRINTFN(-1,("usbd_get_config_desc: conf %d, bad desc %d\n",
-                            conf, d->bDescriptorType));
+               DPRINTFN(-1,("usbd_get_config_desc: confidx=%d, bad desc ",
+                            "len=%d type=%d\n",
+                            confidx, d->bLength, d->bDescriptorType));
                return (USBD_INVAL);
        }
        return (USBD_NORMAL_COMPLETION);
@@ -254,17 +257,15 @@ usbd_set_protocol(iface, report)
        usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface);
        usbd_device_handle dev;
        usb_device_request_t req;
-       usbd_status r;
+       usbd_status err;
 
        DPRINTFN(4, ("usbd_set_protocol: iface=%p, report=%d, endpt=%d\n",
                     iface, report, id->bInterfaceNumber));
-       if (!id)
+       if (id == NULL)
                return (USBD_IOERROR);
-       r = usbd_interface2device_handle(iface, &dev);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
-       if (!id)
-               return (USBD_INVAL);
+       err = usbd_interface2device_handle(iface, &dev);
+       if (err)
+               return (err);
        req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
        req.bRequest = UR_SET_PROTOCOL;
        USETW(req.wValue, report);
@@ -284,16 +285,14 @@ usbd_set_report(iface, type, id, data, len)
        usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
        usbd_device_handle dev;
        usb_device_request_t req;
-       usbd_status r;
+       usbd_status err;
 
        DPRINTFN(4, ("usbd_set_report: len=%d\n", len));
-       if (!ifd)
+       if (ifd == NULL)
                return (USBD_IOERROR);
-       r = usbd_interface2device_handle(iface, &dev);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
-       if (!ifd)
-               return (USBD_INVAL);
+       err = usbd_interface2device_handle(iface, &dev);
+       if (err)
+               return (err);
        req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
        req.bRequest = UR_SET_REPORT;
        USETW2(req.wValue, type, id);
@@ -313,16 +312,14 @@ usbd_set_report_async(iface, type, id, data, len)
        usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
        usbd_device_handle dev;
        usb_device_request_t req;
-       usbd_status r;
+       usbd_status err;
 
        DPRINTFN(4, ("usbd_set_report_async: len=%d\n", len));
-       if (!ifd)
+       if (ifd == NULL)
                return (USBD_IOERROR);
-       r = usbd_interface2device_handle(iface, &dev);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
-       if (!ifd)
-               return (USBD_INVAL);
+       err = usbd_interface2device_handle(iface, &dev);
+       if (err)
+               return (err);
        req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
        req.bRequest = UR_SET_REPORT;
        USETW2(req.wValue, type, id);
@@ -342,16 +339,14 @@ usbd_get_report(iface, type, id, data, len)
        usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
        usbd_device_handle dev;
        usb_device_request_t req;
-       usbd_status r;
+       usbd_status err;
 
-       DPRINTFN(4, ("usbd_set_report: len=%d\n", len));
-       if (!id)
+       DPRINTFN(4, ("usbd_get_report: len=%d\n", len));
+       if (ifd == NULL)
                return (USBD_IOERROR);
-       r = usbd_interface2device_handle(iface, &dev);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
-       if (!ifd)
-               return (USBD_INVAL);
+       err = usbd_interface2device_handle(iface, &dev);
+       if (err)
+               return (err);
        req.bmRequestType = UT_READ_CLASS_INTERFACE;
        req.bRequest = UR_GET_REPORT;
        USETW2(req.wValue, type, id);
@@ -369,16 +364,14 @@ usbd_set_idle(iface, duration, id)
        usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
        usbd_device_handle dev;
        usb_device_request_t req;
-       usbd_status r;
+       usbd_status err;
 
        DPRINTFN(4, ("usbd_set_idle: %d %d\n", duration, id));
-       if (!ifd)
+       if (ifd == NULL)
                return (USBD_IOERROR);
-       r = usbd_interface2device_handle(iface, &dev);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
-       if (!ifd)
-               return (USBD_INVAL);
+       err = usbd_interface2device_handle(iface, &dev);
+       if (err)
+               return (err);
        req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
        req.bRequest = UR_SET_IDLE;
        USETW2(req.wValue, duration, id);
@@ -414,12 +407,12 @@ usbd_get_hid_descriptor(ifc)
        usb_config_descriptor_t *cdesc;
        usb_hid_descriptor_t *hd;
        char *p, *end;
-       usbd_status r;
+       usbd_status err;
 
-       if (!idesc)
+       if (idesc == NULL)
                return (0);
-       r = usbd_interface2device_handle(ifc, &dev);
-       if (r != USBD_NORMAL_COMPLETION)
+       err = usbd_interface2device_handle(ifc, &dev);
+       if (err)
                return (0);
        cdesc = usbd_get_config_descriptor(dev);
 
@@ -451,27 +444,27 @@ usbd_alloc_report_desc(ifc, descp, sizep, mem)
        usb_interface_descriptor_t *id;
        usb_hid_descriptor_t *hid;
        usbd_device_handle dev;
-       usbd_status r;
+       usbd_status err;
 
-       r = usbd_interface2device_handle(ifc, &dev);
-       if (r != USBD_NORMAL_COMPLETION)
-               return (r);
+       err = usbd_interface2device_handle(ifc, &dev);
+       if (err)
+               return (err);
        id = usbd_get_interface_descriptor(ifc);
-       if (!id)
+       if (id == NULL)
                return (USBD_INVAL);
        hid = usbd_get_hid_descriptor(ifc);
-       if (!hid)
+       if (hid == NULL)
                return (USBD_IOERROR);
        *sizep = UGETW(hid->descrs[0].wDescriptorLength);
        *descp = malloc(*sizep, mem, M_NOWAIT);
-       if (!*descp)
+       if (*descp == NULL)
                return (USBD_NOMEM);
        /* XXX should not use 0 Report ID */
-       r = usbd_get_report_descriptor(dev, id->bInterfaceNumber, 0, 
+       err = usbd_get_report_descriptor(dev, id->bInterfaceNumber, 0, 
                                       *sizep, *descp);
-       if (r != USBD_NORMAL_COMPLETION) {
+       if (err) {
                free(*descp, mem);
-               return (r);
+               return (err);
        }
        return (USBD_NORMAL_COMPLETION);
 }
@@ -491,20 +484,20 @@ usbd_get_config(dev, conf)
        return (usbd_do_request(dev, &req, conf));
 }
 
-static void usbd_bulk_transfer_cb __P((usbd_request_handle reqh, 
+static void usbd_bulk_transfer_cb __P((usbd_xfer_handle xfer,
                usbd_private_handle priv, usbd_status status));
 static void
-usbd_bulk_transfer_cb(reqh, priv, status)
-       usbd_request_handle reqh;
+usbd_bulk_transfer_cb(xfer, priv, status)
+       usbd_xfer_handle xfer;
        usbd_private_handle priv;
        usbd_status status;
 {
-       wakeup(reqh);
+       wakeup(xfer);
 }
 
 usbd_status
-usbd_bulk_transfer(reqh, pipe, flags, timeout, buf, size, lbl)
-       usbd_request_handle reqh;
+usbd_bulk_transfer(xfer, pipe, flags, timeout, buf, size, lbl)
+       usbd_xfer_handle xfer;
        usbd_pipe_handle pipe;
        u_int16_t flags;
        u_int32_t timeout;
@@ -512,32 +505,32 @@ usbd_bulk_transfer(reqh, pipe, flags, timeout, buf, size, lbl)
        u_int32_t *size;
        char *lbl;
 {
-       usbd_status r;
+       usbd_status err;
        int s, error;
 
-       usbd_setup_request(reqh, pipe, 0, buf, *size,
-                          flags, timeout, usbd_bulk_transfer_cb);
+       usbd_setup_xfer(xfer, pipe, 0, buf, *size,
+                       flags, timeout, usbd_bulk_transfer_cb);
        DPRINTFN(1, ("usbd_bulk_transfer: start transfer %d bytes\n", *size));
        s = splusb();           /* don't want callback until tsleep() */
-       r = usbd_transfer(reqh);
-       if (r != USBD_IN_PROGRESS) {
+       err = usbd_transfer(xfer);
+       if (err != USBD_IN_PROGRESS) {
                splx(s);
-               return (r);
+               return (err);
        }
-       error = tsleep((caddr_t)reqh, PZERO | PCATCH, lbl, 0);
+       error = tsleep((caddr_t)xfer, PZERO | PCATCH, lbl, 0);
        splx(s);
        if (error) {
                DPRINTF(("usbd_bulk_transfer: tsleep=%d\n", error));
                usbd_abort_pipe(pipe);
                return (USBD_INTERRUPTED);
        }
-       usbd_get_request_status(reqh, 0, 0, size, &r);
+       usbd_get_xfer_status(xfer, NULL, NULL, size, &err);
        DPRINTFN(1,("usbd_bulk_transfer: transferred %d\n", *size));
-       if (r != USBD_NORMAL_COMPLETION) {
-               DPRINTF(("usbd_bulk_transfer: error=%d\n", r));
+       if (err != USBD_NORMAL_COMPLETION) {
+               DPRINTF(("usbd_bulk_transfer: error=%d\n", err));
                usbd_clear_endpoint_stall(pipe);
        }
-       return (r);
+       return (err);
 }
 
 void
index e3c055e..098316b 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: usbdi_util.h,v 1.3 1999/09/27 18:03:56 fgsch Exp $    */
-/*     $NetBSD: usbdi_util.h,v 1.17 1999/09/05 19:32:19 augustss Exp $ */
+/*     $OpenBSD: usbdi_util.h,v 1.4 2000/03/26 08:39:46 aaron Exp $    */
+/*     $NetBSD: usbdi_util.h,v 1.19 1999/11/18 23:32:37 augustss Exp $ */
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -90,7 +90,7 @@ usbd_status usbd_set_config_index
        __P((usbd_device_handle dev, int index, int msg));
 
 usbd_status usbd_bulk_transfer
-       __P((usbd_request_handle reqh, usbd_pipe_handle pipe, u_int16_t flags,
+       __P((usbd_xfer_handle xfer, usbd_pipe_handle pipe, u_int16_t flags,
             u_int32_t timeout, void *buf, u_int32_t *size, char *lbl));
 
 void usb_detach_wait __P((device_ptr_t));
index 9fd4931..ad013be 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: usbdivar.h,v 1.6 1999/11/07 21:30:20 fgsch Exp $      */
-/*     $NetBSD: usbdivar.h,v 1.38 1999/10/25 10:51:46 augustss Exp $   */
+/*     $OpenBSD: usbdivar.h,v 1.7 2000/03/26 08:39:46 aaron Exp $      */
+/*     $NetBSD: usbdivar.h,v 1.47 2000/02/22 11:30:56 augustss Exp $   */
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -41,7 +41,7 @@
 /* From usb_mem.h */
 DECLARE_USB_DMA_T;
 
-struct usbd_request;
+struct usbd_xfer;
 struct usbd_pipe;
 
 struct usbd_endpoint {
@@ -51,19 +51,23 @@ struct usbd_endpoint {
 
 struct usbd_bus_methods {
        usbd_status           (*open_pipe)__P((struct usbd_pipe *pipe));
+       void                  (*soft_intr)__P((struct usbd_bus *));
        void                  (*do_poll)__P((struct usbd_bus *));
        usbd_status           (*allocm)__P((struct usbd_bus *, usb_dma_t *,
                                            u_int32_t bufsize));
        void                  (*freem)__P((struct usbd_bus *, usb_dma_t *));
+       struct usbd_xfer *    (*allocx)__P((struct usbd_bus *));
+       void                  (*freex)__P((struct usbd_bus *,
+                                          struct usbd_xfer *));
 };
 
 struct usbd_pipe_methods {
-       usbd_status           (*transfer)__P((usbd_request_handle reqh));
-       usbd_status           (*start)__P((usbd_request_handle reqh));
-       void                  (*abort)__P((usbd_request_handle reqh));
+       usbd_status           (*transfer)__P((usbd_xfer_handle xfer));
+       usbd_status           (*start)__P((usbd_xfer_handle xfer));
+       void                  (*abort)__P((usbd_xfer_handle xfer));
        void                  (*close)__P((usbd_pipe_handle pipe));
        void                  (*cleartoggle)__P((usbd_pipe_handle pipe));
-       void                  (*done)__P((usbd_request_handle reqh));
+       void                  (*done)__P((usbd_xfer_handle xfer));
 };
 
 struct usbd_port {
@@ -101,31 +105,38 @@ struct usbd_bus {
        struct usb_device_stats stats;
        int                     intr_context;
        u_int                   no_intrs;
+       int                     usbrev; /* USB revision */
+#define USBREV_UNKNOWN 0
+#define USBREV_PRE_1_0 1
+#define USBREV_1_0     2
+#define USBREV_1_1     3
+#define USBREV_STR { "unknown", "pre 1.0", "1.0", "1.1" }
+
 #if defined(__NetBSD__) || defined(__OpenBSD__)
        bus_dma_tag_t           dmatag; /* DMA tag */
 #endif
 };
 
 struct usbd_device {
-       struct usbd_bus        *bus;
-       struct usbd_pipe       *default_pipe;
-       u_int8_t                address;
-       u_int8_t                depth;
-       u_int8_t                lowspeed;
-       u_int16_t               power;
-       u_int8_t                self_powered;
-       int                     config;
-       int                     langid; /* language to use for strings */
+       struct usbd_bus        *bus;            /* our controller */
+       struct usbd_pipe       *default_pipe;   /* pipe 0 */
+       u_int8_t                address;        /* device address */
+       u_int8_t                config;         /* current configuration # */
+       u_int8_t                depth;          /* distance from root hub */
+       u_int8_t                lowspeed;       /* lowspeed flag */
+       u_int8_t                self_powered;   /* flag for self powered */
+       u_int16_t               power;          /* mA the device uses */
+       int16_t                 langid;         /* language for strings */
 #define USBD_NOLANG (-1)
-       usb_event_cookie_t      cookie; /* unique connection id */
-       struct usbd_port       *powersrc;
-       struct usbd_endpoint    def_ep; /* for pipe 0 */
-       usb_endpoint_descriptor_t def_ep_desc; /* for pipe 0 */
-       struct usbd_interface  *ifaces;
-       usb_device_descriptor_t ddesc;
-       usb_config_descriptor_t *cdesc; /* full config descr */
-       struct usbd_quirks     *quirks;
-       struct usbd_hub        *hub; /* only if this is a hub */
+       usb_event_cookie_t      cookie;         /* unique connection id */
+       struct usbd_port       *powersrc;       /* upstream hub port, or 0 */
+       struct usbd_endpoint    def_ep;         /* for pipe 0 */
+       usb_endpoint_descriptor_t def_ep_desc;  /* for pipe 0 */
+       struct usbd_interface  *ifaces;         /* array of all interfaces */
+       usb_device_descriptor_t ddesc;          /* device descriptor */
+       usb_config_descriptor_t *cdesc;         /* full config descr */
+       struct usbd_quirks     *quirks;         /* device quirks, always set */
+       struct usbd_hub        *hub;            /* only if this is a hub */
        device_ptr_t           *subdevs;        /* sub-devices, 0 terminated */
 };
 
@@ -145,17 +156,18 @@ struct usbd_pipe {
        struct usbd_endpoint   *endpoint;
        int                     refcnt;
        char                    running;
-       SIMPLEQ_HEAD(, usbd_request) queue;
+       SIMPLEQ_HEAD(, usbd_xfer) queue;
        LIST_ENTRY(usbd_pipe)   next;
 
-       usbd_request_handle     intrreqh; /* used for repeating requests */
+       usbd_xfer_handle        intrxfer; /* used for repeating requests */
        char                    repeat;
+       int                     interval;
 
        /* Filled by HC driver. */
        struct usbd_pipe_methods *methods;
 };
 
-struct usbd_request {
+struct usbd_xfer {
        struct usbd_pipe       *pipe;
        void                   *priv;
        void                   *buffer;
@@ -183,10 +195,10 @@ struct usbd_request {
 #define URQ_AUTO_DMABUF        0x10
 #define URQ_DEV_DMABUF 0x20
 
-       SIMPLEQ_ENTRY(usbd_request) next;
+       SIMPLEQ_ENTRY(usbd_xfer) next;
 
        void                   *hcpriv; /* private use by the HC driver */
-       int                     hcprivint; /* ditto */
+       int                     hcprivint;
 
 #if defined(__FreeBSD__)
        struct callout_handle  timo_handle;
@@ -204,7 +216,7 @@ usbd_status usbd_reset_port __P((usbd_device_handle dev,
                                     int port, usb_port_status_t *ps));
 usbd_status    usbd_setup_pipe __P((usbd_device_handle dev,
                                     usbd_interface_handle iface,
-                                    struct usbd_endpoint *,
+                                    struct usbd_endpoint *, int,
                                     usbd_pipe_handle *pipe));
 usbd_status    usbd_new_device __P((device_ptr_t parent, 
                                     usbd_bus_handle bus, int depth,
@@ -217,13 +229,13 @@ usbd_status       usbd_fill_iface_data __P((usbd_device_handle dev,
                                          int i, int a));
 void           usb_free_device __P((usbd_device_handle));
 
-usbd_status    usb_insert_transfer __P((usbd_request_handle reqh));
-void           usb_transfer_complete __P((usbd_request_handle reqh));
+usbd_status    usb_insert_transfer __P((usbd_xfer_handle xfer));
+void           usb_transfer_complete __P((usbd_xfer_handle xfer));
 void           usb_disconnect_port __P((struct usbd_port *up, device_ptr_t));
 
 /* Routines from usb.c */
-int            usb_bus_count __P((void));
 void           usb_needs_explore __P((usbd_bus_handle));
+void           usb_schedsoftintr __P((struct usbd_bus *));
 
 #ifdef DIAGNOSTIC
 #define SPLUSBCHECK \
@@ -231,6 +243,7 @@ void                usb_needs_explore __P((usbd_bus_handle));
             extern int cold; \
              if (!cold && _s != _su) printf("SPLUSBCHECK failed 0x%x!=0x%x, %s:%d\n", \
                                   _s, _su, __FILE__, __LINE__); \
+             splx(_s); \
         } while (0)
 #else
 #define SPLUSBCHECK