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