Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/usb Make control transfer of over 8K possible by usi...
details: https://anonhg.NetBSD.org/src/rev/b581ecfc704c
branches: trunk
changeset: 483858:b581ecfc704c
user: augustss <augustss%NetBSD.org@localhost>
date: Sun Mar 19 22:24:57 2000 +0000
description:
Make control transfer of over 8K possible by using a chain of TDs.
diffstat:
sys/dev/usb/ohci.c | 89 ++++++++++++++++++++++++--------------------------
sys/dev/usb/ohcireg.h | 4 +-
2 files changed, 45 insertions(+), 48 deletions(-)
diffs (232 lines):
diff -r 35251321a992 -r b581ecfc704c sys/dev/usb/ohci.c
--- a/sys/dev/usb/ohci.c Sun Mar 19 22:23:28 2000 +0000
+++ b/sys/dev/usb/ohci.c Sun Mar 19 22:24:57 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ohci.c,v 1.76 2000/03/16 12:40:51 tsutsui Exp $ */
+/* $NetBSD: ohci.c,v 1.77 2000/03/19 22:24:57 augustss Exp $ */
/* $FreeBSD: src/sys/dev/usb/ohci.c,v 1.22 1999/11/17 22:33:40 n_hibma Exp $ */
/*
@@ -127,7 +127,7 @@
ohci_soft_td_t *, ohci_soft_td_t *));
#endif
static usbd_status ohci_alloc_std_chain __P((struct ohci_pipe *,
- ohci_softc_t *, int, int, u_int16_t, usb_dma_t *,
+ ohci_softc_t *, int, int, usbd_xfer_handle,
ohci_soft_td_t *, ohci_soft_td_t **));
static void ohci_shutdown __P((void *v));
@@ -468,18 +468,19 @@
}
usbd_status
-ohci_alloc_std_chain(opipe, sc, alen, rd, flags, dma, sp, ep)
+ohci_alloc_std_chain(opipe, sc, alen, rd, xfer, sp, ep)
struct ohci_pipe *opipe;
ohci_softc_t *sc;
int alen, rd;
- u_int16_t flags;
- usb_dma_t *dma;
+ usbd_xfer_handle xfer;
ohci_soft_td_t *sp, **ep;
{
ohci_soft_td_t *next, *cur;
ohci_physaddr_t dataphys, dataphysend;
- u_int32_t intr, tdflags;
+ u_int32_t tdflags;
int len, curlen;
+ usb_dma_t *dma = &xfer->dmabuf;
+ u_int16_t flags = xfer->flags;
DPRINTFN(alen < 4096,("ohci_alloc_std_chain: start len=%d\n", alen));
@@ -487,10 +488,10 @@
cur = sp;
dataphys = DMAADDR(dma);
dataphysend = OHCI_PAGE(dataphys + len - 1);
- tdflags =
+ tdflags = htole32(
(rd ? OHCI_TD_IN : OHCI_TD_OUT) |
- OHCI_TD_NOCC | OHCI_TD_TOGGLE_CARRY |
- (flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0);
+ (flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0) |
+ OHCI_TD_NOCC | OHCI_TD_TOGGLE_CARRY | OHCI_TD_NOINTR);
for (;;) {
next = ohci_alloc_std(sc);
@@ -513,14 +514,14 @@
len, curlen));
len -= curlen;
- intr = len == 0 ? OHCI_TD_SET_DI(1) : OHCI_TD_NOINTR;
- cur->td.td_flags = htole32(tdflags | intr);
+ cur->td.td_flags = tdflags;
cur->td.td_cbp = htole32(dataphys);
cur->nexttd = next;
cur->td.td_nexttd = htole32(next->physaddr);
cur->td.td_be = htole32(dataphys + curlen - 1);
cur->len = curlen;
cur->flags = OHCI_ADD_LEN;
+ cur->xfer = xfer;
DPRINTFN(10,("ohci_alloc_std_chain: cbp=0x%08x be=0x%08x\n",
dataphys, dataphys + curlen - 1));
if (len == 0)
@@ -533,24 +534,22 @@
alen % UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize) == 0) {
/* Force a 0 length transfer at the end. */
- cur->td.td_flags = htole32(tdflags | OHCI_TD_NOINTR);
cur = next;
-
next = ohci_alloc_std(sc);
if (next == NULL)
goto nomem;
- cur->td.td_flags = htole32(tdflags | OHCI_TD_SET_DI(1));
+ cur->td.td_flags = tdflags;
cur->td.td_cbp = 0; /* indicate 0 length packet */
cur->nexttd = next;
cur->td.td_nexttd = htole32(next->physaddr);
cur->td.td_be = ~0;
cur->len = 0;
cur->flags = 0;
+ cur->xfer = xfer;
DPRINTFN(2,("ohci_alloc_std_chain: add 0 xfer\n"));
}
- cur->flags |= OHCI_CALL_DONE;
- *ep = next;
+ *ep = cur;
return (USBD_NORMAL_COMPLETION);
@@ -1399,7 +1398,7 @@
usbd_device_handle dev = opipe->pipe.device;
ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
int addr = dev->address;
- ohci_soft_td_t *setup, *data = 0, *stat, *next, *tail;
+ ohci_soft_td_t *setup, *stat, *next, *tail;
ohci_soft_ed_t *sed;
int isread;
int len;
@@ -1433,36 +1432,26 @@
/* Update device address and length since they may have changed. */
/* XXX This only needs to be done once, but it's too early in open. */
+ /* XXXX Should not touch ED here! */
sed->ed.ed_flags = htole32(
(le32toh(sed->ed.ed_flags) & ~(OHCI_ED_ADDRMASK | OHCI_ED_MAXPMASK)) |
OHCI_ED_SET_FA(addr) |
OHCI_ED_SET_MAXP(UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize)));
+ next = stat;
+
/* Set up data transaction */
if (len != 0) {
- data = ohci_alloc_std(sc);
- if (data == NULL) {
- err = USBD_NOMEM;
+ ohci_soft_td_t *std = stat;
+
+ err = ohci_alloc_std_chain(opipe, sc, len, isread, xfer,
+ std, &stat);
+ stat = stat->nexttd; /* point at free TD */
+ if (err)
goto bad3;
- }
- data->td.td_flags = htole32(
- (isread ? OHCI_TD_IN : OHCI_TD_OUT) | OHCI_TD_NOCC |
- OHCI_TD_TOGGLE_1 | OHCI_TD_NOINTR |
- (xfer->flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0));
- data->td.td_cbp = htole32(DMAADDR(&xfer->dmabuf));
- data->nexttd = stat;
- data->td.td_nexttd = htole32(stat->physaddr);
- data->td.td_be = htole32(le32toh(data->td.td_cbp) + len - 1);
- data->len = len;
- data->xfer = xfer;
- data->flags = OHCI_ADD_LEN;
-
- next = data;
- stat->flags = OHCI_CALL_DONE;
- } else {
- next = stat;
- /* XXX ADD_LEN? */
- stat->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
+ /* Start toggle at 1 and then use the carried toggle. */
+ std->td.td_flags &= htole32(~OHCI_TD_TOGGLE_MASK);
+ std->td.td_flags |= htole32(OHCI_TD_TOGGLE_1);
}
memcpy(KERNADDR(&opipe->u.ctl.reqdma), req, sizeof *req);
@@ -1473,18 +1462,19 @@
setup->nexttd = next;
setup->td.td_nexttd = htole32(next->physaddr);
setup->td.td_be = htole32(le32toh(setup->td.td_cbp) + sizeof *req - 1);
- setup->len = 0; /* XXX The number of byte we count */
+ setup->len = 0;
setup->xfer = xfer;
setup->flags = 0;
xfer->hcpriv = setup;
stat->td.td_flags = htole32(
- (isread ? OHCI_TD_OUT : OHCI_TD_IN) | OHCI_TD_NOCC |
- OHCI_TD_TOGGLE_1 | OHCI_TD_SET_DI(1));
+ (isread ? OHCI_TD_OUT : OHCI_TD_IN) |
+ OHCI_TD_NOCC | OHCI_TD_TOGGLE_1 | OHCI_TD_SET_DI(1));
stat->td.td_cbp = 0;
stat->nexttd = tail;
stat->td.td_nexttd = htole32(tail->physaddr);
stat->td.td_be = 0;
+ stat->flags = OHCI_CALL_DONE;
stat->len = 0;
stat->xfer = xfer;
@@ -1507,9 +1497,9 @@
}
splx(s);
-#ifdef OHCI_DEBUG
- if (ohcidebug > 5) {
- usb_delay_ms(&sc->sc_bus, 5);
+#if 0
+ if (ohcidebug > 10) {
+ delay(10000);
DPRINTF(("ohci_device_request: status=%x\n",
OREAD4(sc, OHCI_COMMAND_STATUS)));
ohci_dump_ed(sed);
@@ -2509,8 +2499,13 @@
/* Allocate a chain of new TDs (including a new tail). */
data = opipe->tail.td;
- err = ohci_alloc_std_chain(opipe, sc, len, isread, xfer->flags,
- &xfer->dmabuf, data, &tail);
+ err = ohci_alloc_std_chain(opipe, sc, len, isread, xfer,
+ data, &tail);
+ /* We want interrupt at the end of the transfer. */
+ tail->td.td_flags &= htole32(~OHCI_TD_INTR_MASK);
+ tail->td.td_flags |= htole32(OHCI_TD_SET_DI(1));
+ tail->flags |= OHCI_CALL_DONE;
+ tail = tail->nexttd; /* point at sentinel */
if (err)
return (err);
diff -r 35251321a992 -r b581ecfc704c sys/dev/usb/ohcireg.h
--- a/sys/dev/usb/ohcireg.h Sun Mar 19 22:23:28 2000 +0000
+++ b/sys/dev/usb/ohcireg.h Sun Mar 19 22:24:57 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ohcireg.h,v 1.14 2000/01/31 22:35:14 augustss Exp $ */
+/* $NetBSD: ohcireg.h,v 1.15 2000/03/19 22:24:58 augustss Exp $ */
/* $FreeBSD: src/sys/dev/usb/ohcireg.h,v 1.8 1999/11/17 22:33:40 n_hibma Exp $ */
@@ -185,9 +185,11 @@
#define OHCI_TD_GET_DI(x) (((x) >> 21) & 7) /* Delay Interrupt */
#define OHCI_TD_SET_DI(x) ((x) << 21)
#define OHCI_TD_NOINTR 0x00e00000
+#define OHCI_TD_INTR_MASK 0x00e00000
#define OHCI_TD_TOGGLE_CARRY 0x00000000
#define OHCI_TD_TOGGLE_0 0x02000000
#define OHCI_TD_TOGGLE_1 0x03000000
+#define OHCI_TD_TOGGLE_MASK 0x03000000
#define OHCI_TD_GET_EC(x) (((x) >> 26) & 3) /* Error Count */
#define OHCI_TD_GET_CC(x) ((x) >> 28) /* Condition Code */
#define OHCI_TD_NOCC 0xf0000000
Home |
Main Index |
Thread Index |
Old Index