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