summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/usb/ohci.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c
index a7db2d5..5a5ae49 100644
--- a/sys/dev/usb/ohci.c
+++ b/sys/dev/usb/ohci.c
@@ -501,9 +501,8 @@ ohci_alloc_std_chain(struct ohci_pipe *opipe, ohci_softc_t *sc,
len = alen;
cur = sp;
-
dataphys = DMAADDR(dma, 0);
- dataphysend = OHCI_PAGE(dataphys + len - 1);
+ dataphysend = OHCI_PAGE(DMAADDR(dma, len - 1));
tdflags = htole32(
(rd ? OHCI_TD_IN : OHCI_TD_OUT) |
(flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0) |
@@ -518,8 +517,8 @@ ohci_alloc_std_chain(struct ohci_pipe *opipe, ohci_softc_t *sc,
/* The OHCI hardware can handle at most one page crossing. */
#if defined(__NetBSD__) || defined(__OpenBSD__)
- if (OHCI_PAGE(dataphys) == OHCI_PAGE(dataphysend) ||
- OHCI_PAGE(dataphys) + OHCI_PAGE_SIZE == OHCI_PAGE(dataphysend))
+ if (OHCI_PAGE(dataphys) == dataphysend ||
+ OHCI_PAGE(dataphys) + OHCI_PAGE_SIZE == dataphysend)
#elif defined(__FreeBSD__)
/* XXX This is pretty broken: Because we do not allocate
* a contiguous buffer (contiguous in physical pages) we
@@ -527,7 +526,7 @@ ohci_alloc_std_chain(struct ohci_pipe *opipe, ohci_softc_t *sc,
* So check whether the start and end of the buffer are on
* the same page.
*/
- if (OHCI_PAGE(dataphys) == OHCI_PAGE(dataphysend))
+ if (OHCI_PAGE(dataphys) == dataphysend)
#endif
{
/* we can handle it in this TD */
@@ -544,6 +543,8 @@ ohci_alloc_std_chain(struct ohci_pipe *opipe, ohci_softc_t *sc,
/* must use multiple TDs, fill as much as possible. */
curlen = 2 * OHCI_PAGE_SIZE -
OHCI_PAGE_MASK(dataphys);
+ if (curlen > len) /* may have fit in one page */
+ curlen = len;
#elif defined(__FreeBSD__)
/* See comment above (XXX) */
curlen = OHCI_PAGE_SIZE -
@@ -568,6 +569,9 @@ ohci_alloc_std_chain(struct ohci_pipe *opipe, ohci_softc_t *sc,
dataphys, dataphys + curlen - 1));
if (len == 0)
break;
+ if (len < 0)
+ panic("Length went negative: %d curlen %d dma %p offset %08x", len, curlen, *dma, (int)offset);
+
DPRINTFN(10,("ohci_alloc_std_chain: extend chain\n"));
offset += curlen;
cur = next;
OpenPOWER on IntegriCloud