Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/usb Add a flag, USBD_FORCE_SHORT_XFER, to transfers....



details:   https://anonhg.NetBSD.org/src/rev/08df8820f319
branches:  trunk
changeset: 480592:08df8820f319
user:      augustss <augustss%NetBSD.org@localhost>
date:      Sun Jan 16 13:12:05 2000 +0000

description:
Add a flag, USBD_FORCE_SHORT_XFER, to transfers.  Using this flag will
force the last packet of a transfer to be smaller than the maximum
packet size.  The only time this matters is if the transfer size is
a multiple of the maximum packet size, in which case a 0 length packet
is sent last.
Some weird devices require this behaviour to determine the end of
a transfer.

diffstat:

 sys/dev/usb/ohci.c  |  125 ++++++++++++++++++++++++++++++++++++++++++++-------
 sys/dev/usb/uhci.c  |   50 ++++++++++----------
 sys/dev/usb/usbdi.h |    6 ++-
 3 files changed, 137 insertions(+), 44 deletions(-)

diffs (truncated from 369 to 300 lines):

diff -r 641a258e3963 -r 08df8820f319 sys/dev/usb/ohci.c
--- a/sys/dev/usb/ohci.c        Sun Jan 16 13:05:48 2000 +0000
+++ b/sys/dev/usb/ohci.c        Sun Jan 16 13:12:05 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ohci.c,v 1.60 2000/01/16 10:35:24 augustss Exp $       */
+/*     $NetBSD: ohci.c,v 1.61 2000/01/16 13:12:06 augustss Exp $       */
 /*     $FreeBSD: src/sys/dev/usb/ohci.c,v 1.22 1999/11/17 22:33:40 n_hibma Exp $       */
 
 /*
@@ -123,7 +123,7 @@
                            ohci_soft_td_t *, ohci_soft_td_t *));
 #endif
 static usbd_status     ohci_alloc_std_chain __P((struct ohci_pipe *,
-                           ohci_softc_t *, int, int, int, usb_dma_t *, 
+                           ohci_softc_t *, int, int, u_int16_t, usb_dma_t *, 
                            ohci_soft_td_t *, ohci_soft_td_t **));
 
 static void            ohci_shutdown __P((void *v));
@@ -441,28 +441,32 @@
 }
 
 usbd_status
-ohci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
-       struct ohci_pipe *upipe;
+ohci_alloc_std_chain(opipe, sc, len, rd, flags, dma, sp, ep)
+       struct ohci_pipe *opipe;
        ohci_softc_t *sc;
-       int len, rd, shortok;
+       int len, rd;
+       u_int16_t flags;
        usb_dma_t *dma;
        ohci_soft_td_t *sp, **ep;
 {
        ohci_soft_td_t *next, *cur;
        ohci_physaddr_t dataphys, dataphysend;
-       u_int32_t intr;
+       u_int32_t intr, tdflags;
        int curlen;
 
        DPRINTFN(len < 4096,("ohci_alloc_std_chain: start len=%d\n", len));
        cur = sp;
        dataphys = DMAADDR(dma);
        dataphysend = OHCI_PAGE(dataphys + len - 1);
+       tdflags = 
+           (rd ? OHCI_TD_IN : OHCI_TD_OUT) | 
+           OHCI_TD_NOCC | OHCI_TD_TOGGLE_CARRY | 
+           (flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0);
+
        for (;;) {
                next = ohci_alloc_std(sc);
-               if (next == 0) {
-                       /* XXX free chain */
-                       return (USBD_NOMEM);
-               }
+               if (next == 0)
+                       goto nomem;
 
                /* The OHCI hardware can handle at most one page crossing. */
                if (OHCI_PAGE(dataphys) == dataphysend ||
@@ -481,10 +485,7 @@
                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 = LE(tdflags | intr);
                cur->td.td_cbp = LE(dataphys);
                cur->nexttd = next;
                cur->td.td_nexttd = LE(next->physaddr);
@@ -499,10 +500,31 @@
                dataphys += curlen;
                cur = next;
        }
+       if ((flags & USBD_FORCE_SHORT_XFER) &&
+           len % UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize) == 0) {
+               /* Force a 0 length transfer at the end. */
+               next = ohci_alloc_std(sc);
+               if (next == 0)
+                       goto nomem;
+
+               cur->td.td_flags = LE(tdflags | OHCI_TD_SET_DI(1));
+               cur->td.td_cbp = 0; /* indicate 0 length packet */
+               cur->nexttd = next;
+               cur->td.td_nexttd = LE(next->physaddr);
+               cur->td.td_be = LE(dataphys - 1);
+               cur->len = 0;
+               cur->flags = 0;
+               cur = next;
+               DPRINTFN(2,("ohci_alloc_std_chain: add 0 xfer\n"));
+       }
        cur->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
        *ep = next;
 
        return (USBD_NORMAL_COMPLETION);
+
+ nomem:
+       /* XXX free chain */
+       return (USBD_NOMEM);
 }
 
 #if 0
@@ -1706,6 +1728,7 @@
        DPRINTFN(1,("ohci_abort_xfer: stop ed=%p\n", sed));
        sed->ed.ed_flags |= LE(OHCI_ED_SKIP); /* force hardware skip */
 
+#if 1
        if (xfer->device->bus->intr_context) {
                /* We have no process context, so we can't use tsleep(). */
                timeout(ohci_abort_xfer_end, xfer, hz / USB_FRAMES_PER_SECOND);
@@ -1717,6 +1740,10 @@
                usb_delay_ms(opipe->pipe.device->bus, 1);
                ohci_abort_xfer_end(xfer);
        }
+#else
+       delay(1000);
+       ohci_abort_xfer_end(xfer);
+#endif
 }
 
 void
@@ -2361,8 +2388,7 @@
 
        /* Allocate a chain of new TDs (including a new tail). */
        data = opipe->tail.td;
-       err = ohci_alloc_std_chain(opipe, sc, len, isread, 
-                 xfer->flags & USBD_SHORT_XFER_OK,
+       err = ohci_alloc_std_chain(opipe, sc, len, isread, xfer->flags,
                  &xfer->dmabuf, data, &tail);
        if (err)
                return (err);
@@ -2678,7 +2704,71 @@
 ohci_device_isoc_enter(xfer)
        usbd_xfer_handle xfer;
 {
-       printf("ohci_device_isoc_enter: not implemented\n");
+       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;
+       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
@@ -2693,7 +2783,6 @@
 ohci_device_isoc_abort(xfer)
        usbd_xfer_handle xfer;
 {
-       printf("ohci_device_isoc_abort: not implemented\n");
 }
 
 void
diff -r 641a258e3963 -r 08df8820f319 sys/dev/usb/uhci.c
--- a/sys/dev/usb/uhci.c        Sun Jan 16 13:05:48 2000 +0000
+++ b/sys/dev/usb/uhci.c        Sun Jan 16 13:12:05 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uhci.c,v 1.72 2000/01/16 10:27:51 augustss Exp $       */
+/*     $NetBSD: uhci.c,v 1.73 2000/01/16 13:12:05 augustss Exp $       */
 /*     $FreeBSD: src/sys/dev/usb/uhci.c,v 1.33 1999/11/17 22:33:41 n_hibma Exp $       */
 
 /*
@@ -168,7 +168,7 @@
 static void            uhci_free_std_chain __P((uhci_softc_t *, 
                                         uhci_soft_td_t *, uhci_soft_td_t *));
 static usbd_status     uhci_alloc_std_chain __P((struct uhci_pipe *,
-                           uhci_softc_t *, int, int, int, usb_dma_t *, 
+                           uhci_softc_t *, int, int, u_int16_t, usb_dma_t *, 
                            uhci_soft_td_t **, uhci_soft_td_t **));
 static void            uhci_timo __P((void *));
 static void            uhci_waitintr __P((uhci_softc_t *,
@@ -1375,10 +1375,11 @@
 }
 
 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;
 {
@@ -1390,20 +1391,22 @@
        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;
@@ -1414,7 +1417,7 @@
        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);
@@ -1433,7 +1436,8 @@
                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;
@@ -1510,9 +1514,8 @@
        upipe->u.bulk.isread = isread;
        upipe->u.bulk.length = len;
 
-       err = uhci_alloc_std_chain(upipe, sc, len, isread, 
-                                xfer->flags & USBD_SHORT_XFER_OK,



Home | Main Index | Thread Index | Old Index