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 framework for doing isoc transfers. The act...



details:   https://anonhg.NetBSD.org/src/rev/e80d07831c29
branches:  trunk
changeset: 480581:e80d07831c29
user:      augustss <augustss%NetBSD.org@localhost>
date:      Sun Jan 16 10:35:24 2000 +0000

description:
Add framework for doing isoc transfers.  The actual scheduling code
is still missing.

diffstat:

 sys/dev/usb/ohci.c    |  236 ++++++++++++++++++++++++++++++++++++++++++-------
 sys/dev/usb/ohcireg.h |   29 +++++-
 sys/dev/usb/ohcivar.h |   12 ++-
 3 files changed, 238 insertions(+), 39 deletions(-)

diffs (truncated from 573 to 300 lines):

diff -r 7c7730a14f92 -r e80d07831c29 sys/dev/usb/ohci.c
--- a/sys/dev/usb/ohci.c        Sun Jan 16 10:27:51 2000 +0000
+++ b/sys/dev/usb/ohci.c        Sun Jan 16 10:35:24 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ohci.c,v 1.59 2000/01/16 10:27:51 augustss Exp $       */
+/*     $NetBSD: ohci.c,v 1.60 2000/01/16 10:35:24 augustss Exp $       */
 /*     $FreeBSD: src/sys/dev/usb/ohci.c,v 1.22 1999/11/17 22:33:40 n_hibma Exp $       */
 
 /*
@@ -115,6 +115,9 @@
 static ohci_soft_td_t  *ohci_alloc_std __P((ohci_softc_t *));
 static void            ohci_free_std __P((ohci_softc_t *, ohci_soft_td_t *));
 
+static ohci_soft_itd_t *ohci_alloc_sitd __P((ohci_softc_t *));
+static void            ohci_free_sitd __P((ohci_softc_t *,ohci_soft_itd_t *));
+
 #if 0
 static void            ohci_free_std_chain __P((ohci_softc_t *, 
                            ohci_soft_td_t *, ohci_soft_td_t *));
@@ -143,6 +146,9 @@
 static ohci_soft_td_t  *ohci_hash_find_td __P((ohci_softc_t *,
                            ohci_physaddr_t));
 
+static usbd_status     ohci_setup_isoc __P((usbd_pipe_handle pipe));
+static void            ohci_device_isoc_enter __P((usbd_xfer_handle));
+
 static usbd_status     ohci_allocm __P((struct usbd_bus *, usb_dma_t *,
                            u_int32_t));
 static void            ohci_freem __P((struct usbd_bus *, usb_dma_t *));
@@ -176,13 +182,11 @@
 static void            ohci_device_intr_close __P((usbd_pipe_handle));
 static void            ohci_device_intr_done  __P((usbd_xfer_handle));
 
-#if 0
 static usbd_status     ohci_device_isoc_transfer __P((usbd_xfer_handle));
 static usbd_status     ohci_device_isoc_start __P((usbd_xfer_handle));
 static void            ohci_device_isoc_abort __P((usbd_xfer_handle));
 static void            ohci_device_isoc_close __P((usbd_pipe_handle));
 static void            ohci_device_isoc_done  __P((usbd_xfer_handle));
-#endif
 
 static usbd_status     ohci_device_setintr __P((ohci_softc_t *sc, 
                            struct ohci_pipe *pipe, int ival));
@@ -222,7 +226,10 @@
 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 */
@@ -243,7 +250,7 @@
                } bulk;
                /* Iso pipe */
                struct iso {
-                       int xxxxx;
+                       int next, inuse;
                } iso;
        } u;
 };
@@ -302,7 +309,6 @@
        ohci_device_bulk_done,
 };
 
-#if 0
 static struct usbd_pipe_methods ohci_device_isoc_methods = {
        ohci_device_isoc_transfer,
        ohci_device_isoc_start,
@@ -311,7 +317,6 @@
        ohci_noop,
        ohci_device_isoc_done,
 };
-#endif
 
 #if defined(__NetBSD__) || defined(__OpenBSD__)
 int
@@ -516,15 +521,53 @@
 }
 #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 err;
-       int rev;
        int i;
-       u_int32_t s, ctl, ival, hcr, fm, per;
+       u_int32_t s, ctl, ival, hcr, fm, per, rev;
 
        DPRINTF(("ohci_init: start\n"));
 #if defined(__OpenBSD__)
@@ -557,6 +600,7 @@
 
        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 == NULL) {
                err = USBD_NOMEM;
@@ -564,6 +608,7 @@
        }
        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 == NULL) {
                err = USBD_NOMEM;
@@ -571,6 +616,14 @@
        }
        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);
@@ -578,16 +631,17 @@
                        while (--i >= 0)
                                ohci_free_sed(sc, sc->sc_eds[i]);
                        err = USBD_NOMEM;
-                       goto bad3;
+                       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
@@ -650,14 +704,14 @@
        if (hcr) {
                printf("%s: reset timeout\n", USBDEVNAME(sc->sc_bus.bdev));
                err = USBD_IOERROR;
-               goto bad3;
+               goto bad5;
        }
 #ifdef OHCI_DEBUG
        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));
@@ -704,6 +758,11 @@
 
        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:
@@ -1060,7 +1119,7 @@
        xfer->hcpriv = NULL;
 
        if (xfer->pipe->repeat) {
-               data = opipe->tail;
+               data = opipe->tail.td;
                tail = ohci_alloc_std(sc); /* XXX should reuse TD */
                if (tail == NULL) {
                        xfer->status = USBD_NOMEM;
@@ -1085,7 +1144,7 @@
 
                ohci_hash_add_td(sc, data);
                sed->ed.ed_tailp = LE(tail->physaddr);
-               opipe->tail = tail;
+               opipe->tail.td = tail;
        }
 }
 
@@ -1215,7 +1274,7 @@
                    UGETW(req->wIndex), len, addr, 
                    opipe->pipe.endpoint->edesc->bEndpointAddress));
 
-       setup = opipe->tail;
+       setup = opipe->tail.td;
        stat = ohci_alloc_std(sc);
        if (stat == NULL) {
                err = USBD_NOMEM;
@@ -1303,7 +1362,7 @@
                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 (xfer->timeout && !sc->sc_bus.use_polling) {
                 usb_timeout(ohci_timeout, xfer,
@@ -1487,8 +1546,12 @@
        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;
+       ohci_soft_itd_t *sitd;
+       ohci_physaddr_t tdphys;
+       u_int32_t fmt;
        usbd_status err;
        int s;
 
@@ -1509,22 +1572,35 @@
                sed = ohci_alloc_sed(sc);
                if (sed == NULL)
                        goto bad0;
-               std = ohci_alloc_std(sc);
-               if (std == NULL)
-                       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 | 



Home | Main Index | Thread Index | Old Index