Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/usb Two major changes:



details:   https://anonhg.NetBSD.org/src/rev/46a88dd0fb36
branches:  trunk
changeset: 484080:46a88dd0fb36
user:      augustss <augustss%NetBSD.org@localhost>
date:      Fri Mar 24 22:57:58 2000 +0000

description:
Two major changes:

  Make each xfer have its own intr_info.  This is necessary if we want
to queue multiple xfers on an endpoint.  This should get rid of the
(mostly harmless) DIAGNOSTICs about intr_infos (not) being done.

  Change (again!) how xfers are aborted.  Aborting a TD is a nightmare
on the braindead UHCI controller.  (Unless you stop the HC, thereby
losing isoc traffic.)  Hopefully I got it right this time.

diffstat:

 sys/dev/usb/uhci.c    |  729 ++++++++++++++++++++++++++++++++-----------------
 sys/dev/usb/uhcivar.h |   16 +-
 2 files changed, 480 insertions(+), 265 deletions(-)

diffs (truncated from 1372 to 300 lines):

diff -r fd46c98b7ed4 -r 46a88dd0fb36 sys/dev/usb/uhci.c
--- a/sys/dev/usb/uhci.c        Fri Mar 24 22:55:13 2000 +0000
+++ b/sys/dev/usb/uhci.c        Fri Mar 24 22:57:58 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uhci.c,v 1.91 2000/03/24 22:03:31 augustss Exp $       */
+/*     $NetBSD: uhci.c,v 1.92 2000/03/24 22:57:58 augustss Exp $       */
 /*     $FreeBSD: src/sys/dev/usb/uhci.c,v 1.33 1999/11/17 22:33:41 n_hibma Exp $       */
 
 /*
@@ -93,6 +93,7 @@
 #endif
 
 #ifdef UHCI_DEBUG
+uhci_softc_t *thesc;
 #define DPRINTF(x)     if (uhcidebug) printf x
 #define DPRINTFN(n,x)  if (uhcidebug>(n)) printf x
 int uhcidebug = 0;
@@ -117,8 +118,12 @@
 
 struct uhci_pipe {
        struct usbd_pipe pipe;
-       uhci_intr_info_t *iinfo;
        int nexttoggle;
+
+       u_char aborting;
+       usbd_xfer_handle abortstart, abortend;
+       usb_callout_t abort_timeout;
+
        /* Info needed for different pipe kinds. */
        union {
                /* Control pipe */
@@ -147,12 +152,6 @@
        } u;
 };
 
-/* 
- * The uhci_intr_info free list can be global since they contain
- * no dma specific data.  The other free lists do.
- */
-LIST_HEAD(, uhci_intr_info) uhci_ii_free;
-
 static void            uhci_busreset __P((uhci_softc_t *));
 static void            uhci_shutdown __P((void *v));
 static void            uhci_power __P((int, void *));
@@ -161,8 +160,6 @@
 static void            uhci_free_std __P((uhci_softc_t *, uhci_soft_td_t *));
 static uhci_soft_qh_t *uhci_alloc_sqh __P((uhci_softc_t *));
 static void            uhci_free_sqh __P((uhci_softc_t *, uhci_soft_qh_t *));
-static uhci_intr_info_t *uhci_alloc_intr_info __P((uhci_softc_t *));
-static void            uhci_free_intr_info __P((uhci_intr_info_t *ii));
 #if 0
 static void            uhci_enter_ctl_q __P((uhci_softc_t *, uhci_soft_qh_t *,
                                      uhci_intr_info_t *));
@@ -180,12 +177,15 @@
 static void            uhci_check_intr __P((uhci_softc_t *,
                            uhci_intr_info_t *));
 static void            uhci_idone __P((uhci_intr_info_t *));
+
 static void            uhci_abort_xfer __P((usbd_xfer_handle,
                            usbd_status status));
 static void            uhci_abort_xfer_end __P((void *v));
+static void            uhci_abort_unlink_qh __P((struct uhci_pipe *));
+static void            uhci_abort_relink_qh __P((struct uhci_pipe *));
+static void            uhci_cancel_abort __P((usbd_pipe_handle));
+
 static void            uhci_timeout __P((void *));
-static void            uhci_lock_frames __P((uhci_softc_t *));
-static void            uhci_unlock_frames __P((uhci_softc_t *));
 static void            uhci_add_ctrl __P((uhci_softc_t *, uhci_soft_qh_t *));
 static void            uhci_add_bulk __P((uhci_softc_t *, uhci_soft_qh_t *));
 static void            uhci_remove_ctrl __P((uhci_softc_t *,uhci_soft_qh_t *));
@@ -244,16 +244,17 @@
 
 static usbd_status     uhci_device_request __P((usbd_xfer_handle xfer));
 
-static void            uhci_add_intr __P((uhci_softc_t *, int,
-                           uhci_soft_qh_t *));
-static void            uhci_remove_intr __P((uhci_softc_t *, int,
-                           uhci_soft_qh_t *));
+static void            uhci_add_intr __P((uhci_softc_t *, uhci_soft_qh_t *));
+static void            uhci_remove_intr __P((uhci_softc_t*, uhci_soft_qh_t*));
 static usbd_status     uhci_device_setintr __P((uhci_softc_t *sc, 
                            struct uhci_pipe *pipe, int ival));
 
 static void            uhci_device_clear_toggle __P((usbd_pipe_handle pipe));
 static void            uhci_noop __P((usbd_pipe_handle pipe));
 
+static __inline__ uhci_soft_qh_t *uhci_find_prev_qh
+    __P((uhci_soft_qh_t *, uhci_soft_qh_t *));
+
 #ifdef UHCI_DEBUG
 static void            uhci_dumpregs __P((uhci_softc_t *));
 static void            uhci_dump_qhs __P((uhci_soft_qh_t *));
@@ -342,6 +343,28 @@
        uhci_device_isoc_done,
 };
 
+#define uhci_add_intr_info(sc, ii) \
+       LIST_INSERT_HEAD(&(sc)->sc_intrhead, (ii), list);
+#define uhci_del_intr_info(ii) \
+       LIST_REMOVE((ii), list)
+
+static __inline__ uhci_soft_qh_t *
+uhci_find_prev_qh(pqh, sqh)
+       uhci_soft_qh_t *pqh, *sqh;
+{
+       DPRINTFN(15,("uhci_find_prev_qh: pqh=%p sqh=%p\n", pqh, sqh));
+
+       for (; pqh->hlink != sqh; pqh = pqh->hlink) {
+#if defined(DIAGNOSTIC) || defined(UHCI_DEBUG)         
+               if (le32toh(pqh->qh.qh_hlink) & UHCI_PTR_T) {
+                       printf("uhci_find_qh: QH not found\n");
+                       return (NULL);
+               }
+#endif
+       }
+       return (pqh);
+}
+
 void
 uhci_busreset(sc)
        uhci_softc_t *sc;
@@ -363,6 +386,8 @@
        DPRINTFN(1,("uhci_init: start\n"));
 
 #ifdef UHCI_DEBUG
+       thesc = sc;
+
        if (uhcidebug > 2)
                uhci_dumpregs(sc);
 #endif
@@ -436,10 +461,11 @@
        sc->sc_bus.methods = &uhci_bus_methods;
        sc->sc_bus.pipe_size = sizeof(struct uhci_pipe);
 
+#if defined(__NetBSD__) || defined(__OpenBSD__)
        sc->sc_suspend = PWR_RESUME;
        sc->sc_powerhook = powerhook_establish(uhci_power, sc);
-
        sc->sc_shutdownhook = shutdownhook_establish(uhci_shutdown, sc);
+#endif
 
        DPRINTFN(1,("uhci_init: enabling\n"));
        UWRITE2(sc, UHCI_INTR, UHCI_INTR_TOCRCIE | UHCI_INTR_RIE | 
@@ -486,8 +512,10 @@
        if (rv != 0)
                return (rv);
 
+#if defined(__NetBSD__) || defined(__OpenBSD__)
        powerhook_disestablish(sc->sc_powerhook);
        shutdownhook_disestablish(sc->sc_shutdownhook);
+#endif
 
        /* Free all xfers associated with this HC. */
        for (;;) {
@@ -533,9 +561,14 @@
        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);
+               xfer = malloc(sizeof(struct uhci_xfer), M_USB, M_NOWAIT);
+       if (xfer != NULL) {
+               memset(xfer, 0, sizeof (struct uhci_xfer));
+               UXFER(xfer)->iinfo.sc = sc;
+#ifdef DIAGNOSTIC
+               UXFER(xfer)->iinfo.isdone = 1;
+#endif
+       }
        return (xfer);
 }
 
@@ -697,7 +730,7 @@
 void
 uhci_dump()
 {
-       uhci_softc_t *sc = uhci;
+       uhci_softc_t *sc = thesc;
 
        uhci_dumpregs(sc);
        printf("intrs=%d\n", sc->sc_bus.no_intrs);
@@ -758,6 +791,39 @@
                        break;
        }
 }
+
+void uhci_dump_ii(uhci_intr_info_t *ii);
+void
+uhci_dump_ii(ii)
+       uhci_intr_info_t *ii;
+{
+       usbd_pipe_handle pipe = ii->xfer->pipe;
+       usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc;
+       usbd_device_handle dev = pipe->device;
+       
+       printf("ii %p: done=%d xfer=%p dev=%p vid=0x%04x pid=0x%04x addr=%d pipe=%p ep=0x%02x attr=0x%02x\n", 
+              ii, ii->isdone, ii->xfer, dev, 
+              UGETW(dev->ddesc.idVendor), 
+              UGETW(dev->ddesc.idProduct),
+              dev->address, pipe,
+              ed->bEndpointAddress, ed->bmAttributes);
+}
+
+void uhci_dump_iis(struct uhci_softc *);
+void
+uhci_dump_iis(sc)
+       struct uhci_softc *sc;
+{
+       uhci_intr_info_t *ii;
+
+       printf("intr_info list:\n");
+       for (ii = LIST_FIRST(&sc->sc_intrhead); ii; ii = LIST_NEXT(ii, list))
+               uhci_dump_ii(ii);
+}
+
+void iidump(void);
+void iidump() { uhci_dump_iis(thesc); }
+
 #endif
 
 /*
@@ -791,7 +857,6 @@
        xfer->actlen = 1;
        xfer->status = USBD_NORMAL_COMPLETION;
        s = splusb();
-       xfer->hcpriv = 0;
        xfer->device->bus->intr_context++;
        usb_transfer_complete(xfer);
        xfer->device->bus->intr_context--;
@@ -810,65 +875,6 @@
 {
 }
 
-void
-uhci_lock_frames(sc)
-       uhci_softc_t *sc;
-{
-       int s = splusb();
-
-       while (sc->sc_vflock & UHCI_HAS_LOCK) {
-               sc->sc_vflock |= UHCI_WANT_LOCK;
-               tsleep(&sc->sc_vflock, PRIBIO, "uhcqhl", 0);
-       }
-       sc->sc_vflock = UHCI_HAS_LOCK;
-       splx(s);
-}
-
-void
-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);
-       splx(s);
-}
-
-/*
- * Allocate an interrupt information struct.  A free list is kept
- * for fast allocation.
- */
-uhci_intr_info_t *
-uhci_alloc_intr_info(sc)
-       uhci_softc_t *sc;
-{
-       uhci_intr_info_t *ii;
-
-       ii = LIST_FIRST(&uhci_ii_free);
-       if (ii)
-               LIST_REMOVE(ii, list);
-       else {
-               ii = malloc(sizeof(uhci_intr_info_t), M_USBHC, M_NOWAIT);
-       }
-       ii->sc = sc;
-       usb_callout_init(ii->timeout_handle);
-
-       return ii;
-}
-
-void
-uhci_free_intr_info(ii)
-       uhci_intr_info_t *ii;
-{
-#if defined(__NetBSD__) && defined(DIAGNOSTIC)
-       if (callout_pending(&ii->timeout_handle))
-               panic("uhci_free_intr_info: pending callout");
-#endif
-       LIST_INSERT_HEAD(&uhci_ii_free, ii, list); /* and put on free list */
-}
-
 /* Add control QH, called at splusb(). */
 void
 uhci_add_ctrl(sc, sqh)
@@ -899,15 +905,7 @@
        SPLUSBCHECK;
 
        DPRINTFN(10, ("uhci_remove_ctrl: sqh=%p\n", sqh));



Home | Main Index | Thread Index | Old Index