Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/usb Set up control xfers.



details:   https://anonhg.NetBSD.org/src/rev/a508ee482920
branches:  trunk
changeset: 517893:a508ee482920
user:      augustss <augustss%NetBSD.org@localhost>
date:      Wed Nov 21 02:44:30 2001 +0000

description:
Set up control xfers.
Handle xfer timeouts.
Better debug messages.

diffstat:

 sys/dev/usb/ehci.c    |  471 +++++++++++++++++++++++++++++++++++++++++++++----
 sys/dev/usb/ehcireg.h |   17 +-
 sys/dev/usb/ehcivar.h |    9 +-
 3 files changed, 448 insertions(+), 49 deletions(-)

diffs (truncated from 804 to 300 lines):

diff -r 4b73daa68a93 -r a508ee482920 sys/dev/usb/ehci.c
--- a/sys/dev/usb/ehci.c        Wed Nov 21 02:41:18 2001 +0000
+++ b/sys/dev/usb/ehci.c        Wed Nov 21 02:44:30 2001 +0000
@@ -1,8 +1,7 @@
 /* TODO
 Add intrinfo.
-Indicator light bit.
 */
-/*     $NetBSD: ehci.c,v 1.14 2001/11/20 16:25:35 augustss Exp $       */
+/*     $NetBSD: ehci.c,v 1.15 2001/11/21 02:44:30 augustss Exp $       */
 
 /*
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -51,7 +50,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.14 2001/11/20 16:25:35 augustss Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.15 2001/11/21 02:44:30 augustss Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -78,7 +77,9 @@
 #define DPRINTF(x)     if (ehcidebug) printf x
 #define DPRINTFN(n,x)  if (ehcidebug>(n)) printf x
 int ehcidebug = 0;
+#ifndef __NetBSD__
 #define bitmask_snprintf(q,f,b,l) snprintf((b), (l), "%b", (q), (f))
+#endif
 #else
 #define DPRINTF(x)
 #define DPRINTFN(n,x)
@@ -99,12 +100,14 @@
                        ehci_soft_qtd_t *setup, *data, *stat;
                } ctl;
                /* Interrupt pipe */
+               /* XXX */
                /* Bulk pipe */
                struct {
                        u_int length;
                        int isread;
                } bulk;
                /* Iso pipe */
+               /* XXX */
        } u;
 };
 
@@ -115,7 +118,9 @@
 Static void            ehci_poll(struct usbd_bus *);
 Static void            ehci_softintr(void *);
 Static int             ehci_intr1(ehci_softc_t *);
-
+Static void            ehci_waitintr(ehci_softc_t *, usbd_xfer_handle);
+Static void            ehci_timeout(void *);
+Static void            ehci_timeout_task(void *);
 
 Static usbd_status     ehci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t);
 Static void            ehci_freem(struct usbd_bus *, usb_dma_t *);
@@ -173,6 +178,11 @@
 
 Static ehci_soft_qtd_t  *ehci_alloc_sqtd(ehci_softc_t *);
 Static void            ehci_free_sqtd(ehci_softc_t *, ehci_soft_qtd_t *);
+Static usbd_status     ehci_alloc_std_chain(struct ehci_pipe *,
+                           ehci_softc_t *, int, int, usbd_xfer_handle,
+                           ehci_soft_qtd_t **, ehci_soft_qtd_t **);
+
+Static usbd_status     ehci_device_request(usbd_xfer_handle xfer);
 
 Static void            ehci_add_qh(ehci_soft_qh_t *, ehci_soft_qh_t *);
 Static void            ehci_rem_qh(ehci_softc_t *, ehci_soft_qh_t *,
@@ -186,12 +196,15 @@
 Static void            ehci_dumpregs(ehci_softc_t *);
 Static void            ehci_dump(void);
 Static ehci_softc_t    *theehci;
-Static void            ehci_dump_link(ehci_link_t);
+Static void            ehci_dump_link(ehci_link_t, int);
+Static void            ehci_dump_sqtds(ehci_soft_qtd_t *);
 Static void            ehci_dump_sqtd(ehci_soft_qtd_t *);
 Static void            ehci_dump_qtd(ehci_qtd_t *);
 Static void            ehci_dump_sqh(ehci_soft_qh_t *);
 #endif
 
+#define MS_TO_TICKS(ms) ((ms) * hz / 1000)
+
 #define EHCI_NULL htole32(EHCI_LINK_TERMINATE)
 
 #define EHCI_INTR_ENDPT 1
@@ -260,6 +273,8 @@
        ehci_device_isoc_done,
 };
 
+int ehcidisable = 0;
+
 usbd_status
 ehci_init(ehci_softc_t *sc)
 {
@@ -268,6 +283,9 @@
        usbd_status err;
        ehci_soft_qh_t *sqh;
 
+       if (ehcidisable)
+               return (USBD_INVAL);
+
        DPRINTF(("ehci_init: start\n"));
 #ifdef EHCI_DEBUG
        theehci = sc;
@@ -402,10 +420,8 @@
        return (USBD_NORMAL_COMPLETION);
 
 #if 0
- bad3:
-       ehci_free_sqh(sc, sc->sc_ctrl_head);
  bad2:
-       ehci_free_sqtd(sc, sc->sc_bulk_head->sqtd);
+       ehci_free_sqh(sc, sc->sc_async_head);
 #endif
  bad1:
        usb_freemem(&sc->sc_bus, &sc->sc_fldma);
@@ -417,6 +433,9 @@
 {
        ehci_softc_t *sc = v;
 
+       if (sc == NULL || sc->sc_dying || ehcidisable)
+               return (0);
+
        /* If we get an interrupt while polling, then just ignore it. */
        if (sc->sc_bus.use_polling) {
 #ifdef DIAGNOSTIC
@@ -524,7 +543,7 @@
 ehci_pcd(ehci_softc_t *sc, usbd_xfer_handle xfer)
 {
        usbd_pipe_handle pipe;
-       struct ehci_pipe *opipe;
+       struct ehci_pipe *epipe;
        u_char *p;
        int i, m;
 
@@ -534,7 +553,7 @@
        }
 
        pipe = xfer->pipe;
-       opipe = (struct ehci_pipe *)pipe;
+       epipe = (struct ehci_pipe *)pipe;
 
        p = KERNADDR(&xfer->dmabuf);
        m = min(sc->sc_noport, xfer->length * 8 - 1);
@@ -557,6 +576,42 @@
        //ehci_softc_t *sc = v;
 }
 
+/*
+ * Wait here until controller claims to have an interrupt.
+ * Then call ohci_intr and return.  Use timeout to avoid waiting
+ * too long.
+ */
+void
+ehci_waitintr(ehci_softc_t *sc, usbd_xfer_handle xfer)
+{
+       int timo = xfer->timeout;
+       int usecs;
+       u_int32_t intrs;
+
+       xfer->status = USBD_IN_PROGRESS;
+       for (usecs = timo * 1000000 / hz; usecs > 0; usecs -= 1000) {
+               usb_delay_ms(&sc->sc_bus, 1);
+               intrs = EHCI_STS_INTRS(EOREAD4(sc, EHCI_USBSTS)) &
+                       sc->sc_eintrs;
+               DPRINTFN(15,("ehci_waitintr: 0x%04x\n", intrs));
+#ifdef OHCI_DEBUG
+               if (ehcidebug > 15)
+                       ehci_dumpregs(sc);
+#endif
+               if (intrs) {
+                       ehci_intr1(sc);
+                       if (xfer->status != USBD_IN_PROGRESS)
+                               return;
+               }
+       }
+
+       /* Timeout */
+       DPRINTF(("ehci_waitintr: timeout\n"));
+       xfer->status = USBD_TIMEOUT;
+       usb_transfer_complete(xfer);
+       /* XXX should free TD */
+}
+
 void
 ehci_poll(struct usbd_bus *bus)
 {
@@ -593,6 +648,8 @@
        if (sc->sc_shutdownhook != NULL)
                shutdownhook_disestablish(sc->sc_shutdownhook);
 
+       usb_delay_ms(&sc->sc_bus, 1000); /* XXX let stray task complete */
+
        /* XXX free other data structures XXX */
 
        return (rv);
@@ -732,9 +789,9 @@
        if (xfer != NULL)
                SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, xfer, next);
        else
-               xfer = malloc(sizeof(*xfer), M_USB, M_NOWAIT);
+               xfer = malloc(sizeof(struct ehci_xfer), M_USB, M_NOWAIT);
        if (xfer != NULL)
-               memset(xfer, 0, sizeof *xfer);
+               memset(xfer, 0, sizeof (struct ehci_xfer));
        return (xfer);
 }
 
@@ -749,10 +806,11 @@
 Static void
 ehci_device_clear_toggle(usbd_pipe_handle pipe)
 {
+       struct ehci_pipe *epipe = (struct ehci_pipe *)pipe;
+
+       printf("ehci_device_clear_toggle: epipe=%p\n", epipe);
 #if 0
 OOO
-       struct ehci_pipe *epipe = (struct ehci_pipe *)pipe;
-
        epipe->sed->ed.ed_headp &= htole32(~EHCI_TOGGLECARRY);
 #endif
 }
@@ -771,6 +829,11 @@
               EOREAD4(sc, EHCI_USBCMD),
               EOREAD4(sc, EHCI_USBSTS),
               EOREAD4(sc, EHCI_USBINTR));
+       printf("frindex=0x08x ctrdsegm=0x%08x periodic=0x%08x async=0x%08x\n",
+              EOREAD4(sc, EHCI_FRINDEX),
+              EOREAD4(sc, EHCI_CTRLDSSEGMENT),
+              EOREAD4(sc, EHCI_PERIODICLISTBASE),
+              EOREAD4(sc, EHCI_ASYNCLISTADDR));
        for (i = 1; i <= sc->sc_noport; i++)
                printf("port %d status=0x%08x\n", i, 
                       EOREAD4(sc, EHCI_PORTSC(i)));
@@ -783,19 +846,30 @@
 }
 
 void
-ehci_dump_link(ehci_link_t link)
+ehci_dump_link(ehci_link_t link, int type)
 {
-       printf("0x%08x<", link);
-       switch (EHCI_LINK_TYPE(link)) {
-       case EHCI_LINK_ITD: printf("ITD"); break;
-       case EHCI_LINK_QH: printf("QH"); break;
-       case EHCI_LINK_SITD: printf("SITD"); break;
-       case EHCI_LINK_FSTN: printf("FSTN"); break;
+       link = le32toh(link);
+       printf("0x%08x", link);
+       if (link & EHCI_LINK_TERMINATE)
+               printf("<T>");
+       else {
+               printf("<");
+               if (type) {
+                       switch (EHCI_LINK_TYPE(link)) {
+                       case EHCI_LINK_ITD: printf("ITD"); break;
+                       case EHCI_LINK_QH: printf("QH"); break;
+                       case EHCI_LINK_SITD: printf("SITD"); break;
+                       case EHCI_LINK_FSTN: printf("FSTN"); break;
+               }
+               printf(">");
        }
-       if (link & EHCI_LINK_TERMINATE)
-               printf(",T>");
-       else
-               printf(">");
+}
+
+void
+ehci_dump_sqtds(ehci_soft_qtd_t *sqtd)
+{
+       for (; sqtd; sqtd = sqtd->nextqtd)
+               ehci_dump_sqtd(sqtd);
 }
 
 void
@@ -809,29 +883,48 @@
 ehci_dump_qtd(ehci_qtd_t *qtd)
 {
        u_int32_t s;
+       char sbuf[128];
 
-       printf("  next="); ehci_dump_link(qtd->qtd_next);
-       printf(" altnext="); ehci_dump_link(qtd->qtd_altnext);
+       printf("  next="); ehci_dump_link(qtd->qtd_next, 0);
+       printf(" altnext="); ehci_dump_link(qtd->qtd_altnext, 0);
        printf("\n");
-       s = qtd->qtd_status;
+       s = le32toh(qtd->qtd_status);
+       bitmask_snprintf(EHCI_QTD_GET_STATUS(s),
+                        "\20\10ACTIVE\7HALTED\6BUFERR\5BABBLE\4XACTERR"
+                        "\3MISSED\2SPLIT\1PING", sbuf, sizeof(sbuf));
        printf("  status=0x%08x: toggle=%d bytes=0x%x ioc=%d c_page=0x%x\n",
               s, EHCI_QTD_GET_TOGGLE(s), EHCI_QTD_GET_BYTES(s),
               EHCI_QTD_GET_IOC(s), EHCI_QTD_GET_C_PAGE(s));
-       printf("    cerr=%d pid=%d stat=0x%02x\n", EHCI_QTD_GET_CERR(s),
-              EHCI_QTD_GET_PID(s), EHCI_QTD_GET_STATUS(s));
+       printf("    cerr=%d pid=%d stat=0x%s\n", EHCI_QTD_GET_CERR(s),



Home | Main Index | Thread Index | Old Index