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