Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/usb Use device speed in setup.



details:   https://anonhg.NetBSD.org/src/rev/820003dea3a6
branches:  trunk
changeset: 517853:820003dea3a6
user:      augustss <augustss%NetBSD.org@localhost>
date:      Tue Nov 20 13:49:07 2001 +0000

description:
Use device speed in setup.
Simplify async list handling.

diffstat:

 sys/dev/usb/ehci.c |  303 +++++++++++++++++++++++++++++-----------------------
 1 files changed, 167 insertions(+), 136 deletions(-)

diffs (truncated from 562 to 300 lines):

diff -r d713c3683d58 -r 820003dea3a6 sys/dev/usb/ehci.c
--- a/sys/dev/usb/ehci.c        Tue Nov 20 13:48:03 2001 +0000
+++ b/sys/dev/usb/ehci.c        Tue Nov 20 13:49:07 2001 +0000
@@ -1,4 +1,11 @@
-/*     $NetBSD: ehci.c,v 1.10 2001/11/19 02:57:16 augustss Exp $       */
+/* TODO
+Add intrinfo.
+USB 2 reset is 50 ms?
+Frame lengths of control and bulk are 64, 512?
+Indicator light bit.
+Check 7.1.7.3
+*/
+/*     $NetBSD: ehci.c,v 1.11 2001/11/20 13:49:07 augustss Exp $       */
 
 /*
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -47,7 +54,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.10 2001/11/19 02:57:16 augustss Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.11 2001/11/20 13:49:07 augustss Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -110,6 +117,8 @@
 Static usbd_status     ehci_open(usbd_pipe_handle);
 Static void            ehci_poll(struct usbd_bus *);
 Static void            ehci_softintr(void *);
+Static int             ehci_intr1(ehci_softc_t *);
+
 
 Static usbd_status     ehci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t);
 Static void            ehci_freem(struct usbd_bus *, usb_dma_t *);
@@ -168,12 +177,10 @@
 Static ehci_soft_qtd_t  *ehci_alloc_sqtd(ehci_softc_t *);
 Static void            ehci_free_sqtd(ehci_softc_t *, ehci_soft_qtd_t *);
 
-Static void            ehci_hash_add_qtd(ehci_softc_t *, ehci_soft_qtd_t *);
-Static void            ehci_hash_rem_qtd(ehci_softc_t *, ehci_soft_qtd_t *);
-Static ehci_soft_qtd_t  *ehci_hash_find_qtd(ehci_softc_t *, ehci_physaddr_t);
 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 *,
                                    ehci_soft_qh_t *);
+Static void            ehci_sync_hc(ehci_softc_t *);
 
 Static void            ehci_close_pipe(usbd_pipe_handle, ehci_soft_qh_t *);
 Static void            ehci_abort_xfer(usbd_xfer_handle, usbd_status);
@@ -188,6 +195,8 @@
 Static void            ehci_dump_sqh(ehci_soft_qh_t *);
 #endif
 
+#define EHCI_NULL htole32(EHCI_LINK_TERMINATE)
+
 #define EHCI_INTR_ENDPT 1
 
 Static struct usbd_bus_methods ehci_bus_methods = {
@@ -260,6 +269,7 @@
        u_int32_t version, sparams, cparams, hcr;
        u_int i;
        usbd_status err;
+       ehci_soft_qh_t *sqh;
 
        DPRINTF(("ehci_init: start\n"));
 #ifdef EHCI_DEBUG
@@ -296,9 +306,6 @@
        
        sc->sc_bus.usbrev = USBREV_2_0;
 
-       for (i = 0; i < EHCI_HASH_SIZE; i++)
-               LIST_INIT(&sc->sc_hash_qtds[i]);
-
        /* Reset the controller */
        DPRINTF(("%s: resetting\n", USBDEVNAME(sc->sc_bus.bdev)));
        EOWRITE4(sc, EHCI_USBCMD, 0);   /* Halt controller */
@@ -337,48 +344,34 @@
 
        sc->sc_eintrs = EHCI_NORMAL_INTRS;
 
-       /* Allocate dummy QH that starts the bulk list. */
-       sc->sc_bulk_head = ehci_alloc_sqh(sc);
-       if (sc->sc_bulk_head == NULL) {
+       /* Allocate dummy QH that starts the async list. */
+       sqh = ehci_alloc_sqh(sc);
+       if (sqh == NULL) {
                err = USBD_NOMEM;
                goto bad1;
        }
-       memset(&sc->sc_bulk_head->qh, 0, sizeof(ehci_qtd_t));
-       sc->sc_bulk_head->qh.qh_curqtd = htole32(EHCI_LINK_TERMINATE);
-       sc->sc_bulk_head->qh.qh_qtd.qtd_status =
+       /* Fill the QH */
+       sqh->qh.qh_endp =
+           htole32(EHCI_QH_SET_EPS(EHCI_QH_SPEED_HIGH) | EHCI_QH_HRECL);
+       sqh->qh.qh_link =
+           htole32(sqh->physaddr | EHCI_LINK_QH);
+       sqh->qh.qh_curqtd = EHCI_NULL;
+       sqh->next = NULL;
+       /* Fill the overlay qTD */
+       sqh->qh.qh_qtd.qtd_next = EHCI_NULL;
+       sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL;
+       sqh->qh.qh_qtd.qtd_status =
            htole32(EHCI_QTD_SET_STATUS(EHCI_QTD_HALTED));
-       sc->sc_bulk_head->qh.qh_link =
-           htole32(EHCI_LINK_TERMINATE); /* XXX no bw reclaimation */
-       sc->sc_bulk_head->next = NULL;
+       sqh->sqtd = NULL;
 #ifdef EHCI_DEBUG
        if (ehcidebug) {
-               ehci_dump_sqh(sc->sc_bulk_head);
-       }
-#endif
-
-       /* Allocate dummy QH that starts the control list. */
-       sc->sc_ctrl_head = ehci_alloc_sqh(sc);
-       if (sc->sc_ctrl_head == NULL) {
-               err = USBD_NOMEM;
-               goto bad2;
-       }
-       memset(&sc->sc_ctrl_head->qh, 0, sizeof(ehci_qtd_t));
-       sc->sc_ctrl_head->qh.qh_curqtd = htole32(EHCI_LINK_TERMINATE);
-       sc->sc_ctrl_head->qh.qh_qtd.qtd_status =
-           htole32(EHCI_QTD_SET_STATUS(EHCI_QTD_HALTED));
-       sc->sc_ctrl_head->qh.qh_endp = htole32(EHCI_QH_HRECL);
-       sc->sc_ctrl_head->qh.qh_link =
-           htole32(sc->sc_bulk_head->physaddr | EHCI_LINK_QH);
-       sc->sc_ctrl_head = sc->sc_bulk_head;
-#ifdef EHCI_DEBUG
-       if (ehcidebug) {
-               ehci_dump_sqh(sc->sc_ctrl_head);
+               ehci_dump_sqh(sc->sc_async_head);
        }
 #endif
 
        /* Point to async list */
-       EOWRITE4(sc, EHCI_ASYNCLISTADDR,
-                sc->sc_ctrl_head->physaddr | EHCI_LINK_QH);
+       sc->sc_async_head = sqh;
+       EOWRITE4(sc, EHCI_ASYNCLISTADDR, sqh->physaddr | EHCI_LINK_QH);
 
        usb_callout_init(sc->sc_tmo_pcd);
 
@@ -413,17 +406,15 @@
 
 #if 0
  bad3:
-       ehci_free_sqh(sc, sc->sc_bulk_head);
+       ehci_free_sqh(sc, sc->sc_ctrl_head);
+ bad2:
+       ehci_free_sqtd(sc, sc->sc_bulk_head->sqtd);
 #endif
- bad2:
-       ehci_free_sqh(sc, sc->sc_ctrl_head);
  bad1:
        usb_freemem(&sc->sc_bus, &sc->sc_fldma);
        return (err);
 }
 
-Static int ehci_intr1(ehci_softc_t *);
-
 int
 ehci_intr(void *v)
 {
@@ -472,7 +463,7 @@
        sc->sc_bus.no_intrs++;
        if (eintrs & EHCI_STS_IAA) {
                DPRINTF(("ehci_intr1: door bell\n"));
-               wakeup(&sc->sc_bulk_head);
+               wakeup(&sc->sc_async_head);
                eintrs &= ~EHCI_STS_INT;
        }
        if (eintrs & EHCI_STS_INT) {
@@ -859,7 +850,6 @@
        u_int8_t xfertype = ed->bmAttributes & UE_XFERTYPE;
        struct ehci_pipe *epipe = (struct ehci_pipe *)pipe;
        ehci_soft_qh_t *sqh;
-       ehci_soft_qtd_t *sqtd;
        usbd_status err;
 #if 0
        ehci_soft_itd_t *sitd;
@@ -887,7 +877,12 @@
                return (USBD_NORMAL_COMPLETION);
        }
 
-       speed = EHCI_QH_SPEED_HIGH; /* XXX */
+       switch (dev->speed) {
+       case USB_SPEED_LOW:  speed = EHCI_QH_SPEED_LOW;  break;
+       case USB_SPEED_FULL: speed = EHCI_QH_SPEED_FULL; break;
+       case USB_SPEED_HIGH: speed = EHCI_QH_SPEED_HIGH; break;
+       default: panic("ehci_open: bad device speed %d\n", dev->speed);
+       }
        naks = 8;               /* XXX */
        sqh = ehci_alloc_sqh(sc);
        if (sqh == NULL)
@@ -905,39 +900,33 @@
                );
        sqh->qh.qh_endphub = htole32(
                EHCI_QH_SET_MULT(1)
+               /* XXX TT stuff */
+               /* XXX interrupt mask */
                );
-       sqh->qh.qh_curqtd = htole32(EHCI_LINK_TERMINATE);
+       sqh->qh.qh_curqtd = EHCI_NULL;
+       /* Fill the overlay qTD */
+       sqh->qh.qh_qtd.qtd_next = EHCI_NULL;
+       sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL;
+       sqh->qh.qh_qtd.qtd_status =
+           htole32(EHCI_QTD_SET_STATUS(EHCI_QTD_HALTED));
 
        epipe->sqh = sqh;
-#if 0
-       if (xfertype == UE_CONTROL || xfertype == UE_BULK) {
-               sqtd = ehci_alloc_sqtd(sc);
-               if (sqtd == NULL) {
-                       ehci_free_sqtd(sc, sqtd);
-                       goto bad1;
-               }
-               epipe->tail.qtd = sqtd;
-               tdphys = sqtd->physaddr;
-       } else
-               sqtd = NULL;
-#endif
 
        switch (xfertype) {
        case UE_CONTROL:
-               pipe->methods = &ehci_device_ctrl_methods;
-               err = usb_allocmem(&sc->sc_bus, 
-                                  sizeof(usb_device_request_t), 
+               err = usb_allocmem(&sc->sc_bus, sizeof(usb_device_request_t), 
                                   0, &epipe->u.ctl.reqdma);
                if (err)
-                       goto bad;
+                       goto bad1;
+               pipe->methods = &ehci_device_ctrl_methods;
                s = splusb();
-               ehci_add_qh(sqh, sc->sc_ctrl_head);
+               ehci_add_qh(sqh, sc->sc_async_head);
                splx(s);
                break;
        case UE_BULK:
                pipe->methods = &ehci_device_bulk_methods;
                s = splusb();
-               ehci_add_qh(sqh, sc->sc_bulk_head);
+               ehci_add_qh(sqh, sc->sc_async_head);
                splx(s);
                break;
        default:
@@ -945,12 +934,8 @@
        }
        return (USBD_NORMAL_COMPLETION);
 
- bad:
-       if (sqtd != NULL)
-               ehci_free_sqtd(sc, sqtd);
-/*bad1:*/
-       if (sqh != NULL)
-               ehci_free_sqh(sc, sqh);
+ bad1:
+       ehci_free_sqh(sc, sqh);
  bad0:
        return (USBD_NOMEM);
 }
@@ -983,7 +968,6 @@
 ehci_rem_qh(ehci_softc_t *sc, ehci_soft_qh_t *sqh, ehci_soft_qh_t *head)
 {
        ehci_soft_qh_t *p; 
-       int s;
 
        SPLUSBCHECK;
        /* XXX */
@@ -994,17 +978,25 @@
        p->next = sqh->next;
        p->qh.qh_link = sqh->qh.qh_link;
 
-       /*
-        * Now we must ensure that the HC has released all references to the
-        * QH.  We do this by asking for a Async Advance Doorbell interrupt
-        * and then we wait for the interrupt.
-        * To make this easier we first obtain exclusive use ofthe doorbell.
-        */
+       ehci_sync_hc(sc);
+}
+
+/*
+ * Ensure that the HC has released all references to the QH.  We do this
+ * by asking for a Async Advance Doorbell interrupt and then we wait for
+ * the interrupt.
+ * To make this easier we first obtain exclusive use of the doorbell.
+ */
+void
+ehci_sync_hc(ehci_softc_t *sc)
+{
+       int s;
+
        lockmgr(&sc->sc_doorbell_lock, LK_EXCLUSIVE, NULL); /* get doorbell */
        s = splhardusb();
        /* ask for doorbell */
        EOWRITE4(sc, EHCI_USBCMD, EOREAD4(sc, EHCI_USBCMD) | EHCI_CMD_IAAD);
-       tsleep(&sc->sc_bulk_head, PZERO, "ehcidi", 0); /* wait for doorbell */
+       tsleep(&sc->sc_async_head, PZERO, "ehcidi", 0); /* wait for doorbell */



Home | Main Index | Thread Index | Old Index