Module Name: src Committed By: skrll Date: Mon Apr 4 07:43:12 UTC 2016
Modified Files: src/sys/dev/usb [nick-nhusb]: ehci.c ehcivar.h ohci.c uhci.c Log Message: Rework {alloc,reset}_*_chain functions to perform all of TD setup in reset chain. The initial motivation for this was to fix ZLP. To generate a diff of this commit: cvs rdiff -u -r1.234.2.95 -r1.234.2.96 src/sys/dev/usb/ehci.c cvs rdiff -u -r1.42.14.24 -r1.42.14.25 src/sys/dev/usb/ehcivar.h cvs rdiff -u -r1.254.2.69 -r1.254.2.70 src/sys/dev/usb/ohci.c cvs rdiff -u -r1.264.4.69 -r1.264.4.70 src/sys/dev/usb/uhci.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/usb/ehci.c diff -u src/sys/dev/usb/ehci.c:1.234.2.95 src/sys/dev/usb/ehci.c:1.234.2.96 --- src/sys/dev/usb/ehci.c:1.234.2.95 Sat Mar 26 11:42:44 2016 +++ src/sys/dev/usb/ehci.c Mon Apr 4 07:43:12 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: ehci.c,v 1.234.2.95 2016/03/26 11:42:44 skrll Exp $ */ +/* $NetBSD: ehci.c,v 1.234.2.96 2016/04/04 07:43:12 skrll Exp $ */ /* * Copyright (c) 2004-2012 The NetBSD Foundation, Inc. @@ -53,7 +53,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.234.2.95 2016/03/26 11:42:44 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.234.2.96 2016/04/04 07:43:12 skrll Exp $"); #include "ohci.h" #include "uhci.h" @@ -235,12 +235,13 @@ Static void ehci_free_sqh(ehci_softc_t 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_sqtd_chain(ehci_softc_t *, struct usbd_xfer *, - int, int, ehci_soft_qtd_t **, ehci_soft_qtd_t **); +Static usbd_status ehci_alloc_sqtd_chain(ehci_softc_t *, + struct usbd_xfer *, int, int, ehci_soft_qtd_t **); Static void ehci_free_sqtds(ehci_softc_t *, struct ehci_xfer *); Static void ehci_reset_sqtd_chain(ehci_softc_t *, struct usbd_xfer *, int, int, int *, ehci_soft_qtd_t **); +Static void ehci_append_sqtd(ehci_soft_qtd_t *, ehci_soft_qtd_t *); Static ehci_soft_itd_t *ehci_alloc_itd(ehci_softc_t *); Static ehci_soft_sitd_t * @@ -2823,130 +2824,38 @@ ehci_free_sqtd(ehci_softc_t *sc, ehci_so Static usbd_status ehci_alloc_sqtd_chain(ehci_softc_t *sc, struct usbd_xfer *xfer, - int alen, int rd, ehci_soft_qtd_t **sp, ehci_soft_qtd_t **ep) + int alen, int rd, ehci_soft_qtd_t **sp) { struct ehci_xfer *exfer = EHCI_XFER2EXFER(xfer); - ehci_soft_qtd_t *next, *cur; - ehci_physaddr_t nextphys; - uint32_t qtdstatus; - int len, curlen, mps; - int i, tog; - int pages, pageoffs; - size_t curoffs; - vaddr_t va, va_offs; - usb_dma_t *dma = &xfer->ux_dmabuf; uint16_t flags = xfer->ux_flags; - paddr_t a; EHCIHIST_FUNC(); EHCIHIST_CALLED(); - DPRINTF("start len=%d", alen, 0, 0, 0); ASSERT_SLEEPABLE(); KASSERT(sp); - KASSERT(alen != 0 || (flags & USBD_FORCE_SHORT_XFER)); - - len = alen; - qtdstatus = EHCI_QTD_ACTIVE | - EHCI_QTD_SET_PID(rd ? EHCI_QTD_PID_IN : EHCI_QTD_PID_OUT) | - EHCI_QTD_SET_CERR(3) - ; + KASSERT(alen != 0 || (!rd && (flags & USBD_FORCE_SHORT_XFER))); - size_t nsqtd = (flags & USBD_FORCE_SHORT_XFER) ? 1 : 0; - nsqtd += ((len + EHCI_QTD_MAXTRANSFER - 1) / EHCI_QTD_MAXTRANSFER); + size_t nsqtd = (!rd && (flags & USBD_FORCE_SHORT_XFER)) ? 1 : 0; + nsqtd += ((alen + EHCI_PAGE_SIZE - 1) / EHCI_PAGE_SIZE); exfer->ex_sqtds = kmem_zalloc(sizeof(ehci_soft_qtd_t *) * nsqtd, KM_SLEEP); exfer->ex_nsqtd = nsqtd; - mps = UGETW(xfer->ux_pipe->up_endpoint->ue_edesc->wMaxPacketSize); - cur = ehci_alloc_sqtd(sc); - *sp = cur; - if (cur == NULL) - goto nomem; - - curoffs = 0; - for (size_t j = 0;;) { - KASSERT(j < nsqtd); - exfer->ex_sqtds[j++] = cur; - - /* The EHCI hardware can handle at most 5 pages. */ - va = (vaddr_t)KERNADDR(dma, curoffs); - va_offs = EHCI_PAGE_OFFSET(va); - if (len - curoffs < EHCI_QTD_MAXTRANSFER - va_offs) { - /* we can handle it in this QTD */ - curlen = len - curoffs; - } else { - /* must use multiple TDs, fill as much as possible. */ - curlen = EHCI_QTD_MAXTRANSFER - va_offs; + DPRINTF("xfer %p len %d nsqtd %d flags %x", xfer, alen, nsqtd, flags); - /* the length must be a multiple of the max size */ - curlen -= curlen % mps; - DPRINTF("multiple QTDs, curlen=%d", curlen, 0, 0, 0); - KASSERT(curlen != 0); - } - DPRINTF("len=%d curlen=%d curoffs=%zu", len, curlen, curoffs, - 0); - - /* - * Allocate another transfer if there's more data left, - * or if force last short transfer flag is set and we're - * allocating a multiple of the max packet size. - */ - - if (curoffs + curlen != len || - ((curlen % mps) == 0 && !rd && curlen != 0 && - (flags & USBD_FORCE_SHORT_XFER))) { - next = ehci_alloc_sqtd(sc); - if (next == NULL) - goto nomem; - nextphys = htole32(next->physaddr); - } else { - next = NULL; - nextphys = EHCI_NULL; - } - - /* Find number of pages we'll be using, insert dma addresses */ - pages = EHCI_NPAGES(curlen); - KASSERT(pages <= EHCI_QTD_NBUFFERS); - pageoffs = EHCI_PAGE(curoffs); - for (i = 0; i < pages; i++) { - a = DMAADDR(dma, pageoffs + i * EHCI_PAGE_SIZE); - cur->qtd.qtd_buffer[i] = htole32(EHCI_PAGE(a)); - /* Cast up to avoid compiler warnings */ - cur->qtd.qtd_buffer_hi[i] = htole32((uint64_t)a >> 32); - } + for (size_t j = 0; j < exfer->ex_nsqtd;) { + ehci_soft_qtd_t *cur = ehci_alloc_sqtd(sc); + if (cur == NULL) + goto nomem; + exfer->ex_sqtds[j++] = cur; - /* First buffer pointer requires a page offset to start at */ - cur->qtd.qtd_buffer[0] |= htole32(va_offs); - cur->qtd.qtd_next = cur->qtd.qtd_altnext = nextphys; - cur->qtd.qtd_status = htole32(qtdstatus); - cur->nextqtd = next; cur->xfer = xfer; - cur->bufoff = curoffs; - cur->tdlen = curlen; cur->len = 0; - DPRINTF("cbp=0x%08zx end=0x%08zx", curoffs, curoffs + curlen, - 0, 0); - - /* - * adjust the toggle based on the number of packets in this - * qtd - */ - if (((curlen + mps - 1) / mps) & 1) { - tog ^= 1; - qtdstatus ^= EHCI_QTD_TOGGLE_MASK; - } - if (next == NULL) - break; - DPRINTF("extend chain", 0, 0, 0, 0); - if (len) - curoffs += curlen; - cur = next; } - if (ep) - *ep = cur; - DPRINTF("return sqtd=%p sqtdend=%p", *sp, cur, 0, 0); + *sp = exfer->ex_sqtds[0]; + DPRINTF("return sqtd=%p", *sp, 0, 0, 0); return USBD_NORMAL_COMPLETION; @@ -2976,92 +2885,132 @@ ehci_free_sqtds(ehci_softc_t *sc, struct } Static void +ehci_append_sqtd(ehci_soft_qtd_t *sqtd, ehci_soft_qtd_t *prev) +{ + if (prev) { + prev->nextqtd = sqtd; + prev->qtd.qtd_next = htole32(sqtd->physaddr); + prev->qtd.qtd_altnext = prev->qtd.qtd_next; + usb_syncmem(&prev->dma, prev->offs, sizeof(prev->qtd), + BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); + } +} + +Static void ehci_reset_sqtd_chain(ehci_softc_t *sc, struct usbd_xfer *xfer, int length, int isread, int *toggle, ehci_soft_qtd_t **lsqtd) { struct ehci_xfer *exfer = EHCI_XFER2EXFER(xfer); + usb_dma_t *dma = &xfer->ux_dmabuf; + uint16_t flags = xfer->ux_flags; ehci_soft_qtd_t *sqtd, *prev; int tog = *toggle; int mps = UGETW(xfer->ux_pipe->up_endpoint->ue_edesc->wMaxPacketSize); int len = length; - size_t i; EHCIHIST_FUNC(); EHCIHIST_CALLED(); - DPRINTF("xfer=%p len %d isread %d toggle %d", xfer, len, isread, - *toggle); + DPRINTF("xfer=%p len %d isread %d toggle %d", xfer, len, isread, tog); DPRINTF(" VA %p", KERNADDR(&xfer->ux_dmabuf, 0), 0, 0, 0); + KASSERT(length != 0 || (!isread && (flags & USBD_FORCE_SHORT_XFER))); + + const uint32_t qtdstatus = EHCI_QTD_ACTIVE | + EHCI_QTD_SET_PID(isread ? EHCI_QTD_PID_IN : EHCI_QTD_PID_OUT) | + EHCI_QTD_SET_CERR(3) + ; + sqtd = prev = NULL; - for (i = 0; i < exfer->ex_nsqtd; i++, prev = sqtd) { - sqtd = exfer->ex_sqtds[i]; - vaddr_t va = (vaddr_t)KERNADDR(&xfer->ux_dmabuf, sqtd->bufoff); - sqtd->len = sqtd->tdlen; - if (len < sqtd->len) { - sqtd->len = len; - } - - DPRINTF("sqtd[%d]=%p prev %p len %d", i, sqtd, prev, sqtd->len); - DPRINTF(" va %p bufoff %d pa %p", va, sqtd->bufoff, - DMAADDR(&xfer->ux_dmabuf, sqtd->bufoff), 0); - - if (prev) { - prev->nextqtd = sqtd; - prev->qtd.qtd_next = htole32(sqtd->physaddr); - prev->qtd.qtd_altnext = prev->qtd.qtd_next; + size_t curoffs = 0; + size_t j = 0; + for (; len != 0 && j < exfer->ex_nsqtd; prev = sqtd) { + sqtd = exfer->ex_sqtds[j++]; + DPRINTF("sqtd[%d]=%p prev %p", j, sqtd, prev, 0); + + /* + * The EHCI hardware can handle at most 5 pages and they do + * not have to be contiguous + */ + vaddr_t va = (vaddr_t)KERNADDR(dma, curoffs); + vaddr_t va_offs = EHCI_PAGE_OFFSET(va); + size_t curlen = len; + if (curlen >= EHCI_QTD_MAXTRANSFER - va_offs) { + /* must use multiple TDs, fill as much as possible. */ + curlen = EHCI_QTD_MAXTRANSFER - va_offs; + + /* the length must be a multiple of the max size */ + curlen -= curlen % mps; } - usb_syncmem(&sqtd->dma, - sqtd->offs + offsetof(ehci_qtd_t, qtd_status), - sizeof(sqtd->qtd.qtd_status), - BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); - usb_syncmem(&sqtd->dma, - sqtd->offs + offsetof(ehci_qtd_t, qtd_buffer), - sizeof(sqtd->qtd.qtd_buffer[0]), - BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); + KASSERT(curlen != 0); + DPRINTF(" len=%d curlen=%d curoffs=%zu", len, curlen, + curoffs, 0); - sqtd->qtd.qtd_buffer[0] &= ~htole32(EHCI_PAGE_MASK); - sqtd->qtd.qtd_buffer[0] |= htole32(EHCI_PAGE_OFFSET(va)); - /* Reset ... */ - sqtd->qtd.qtd_status &= ~htole32( - EHCI_QTD_STATUS_MASK | - EHCI_QTD_PID_MASK | - EHCI_QTD_CERR_MASK | - EHCI_QTD_C_PAGE_MASK | - EHCI_QTD_BYTES_MASK | - EHCI_QTD_TOGGLE_MASK); - sqtd->qtd.qtd_status |= htole32( - EHCI_QTD_ACTIVE | - EHCI_QTD_SET_PID(isread ? EHCI_QTD_PID_IN : EHCI_QTD_PID_OUT) | - EHCI_QTD_SET_BYTES(sqtd->len) | - EHCI_QTD_SET_CERR(3) | + /* Fill the qTD */ + sqtd->qtd.qtd_next = sqtd->qtd.qtd_altnext = EHCI_NULL; + sqtd->qtd.qtd_status = htole32( + qtdstatus | + EHCI_QTD_SET_BYTES(curlen) | EHCI_QTD_SET_TOGGLE(tog)); - usb_syncmem(&sqtd->dma, - sqtd->offs + offsetof(ehci_qtd_t, qtd_status), - sizeof(sqtd->qtd.qtd_status), - BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); - usb_syncmem(&sqtd->dma, - sqtd->offs + offsetof(ehci_qtd_t, qtd_buffer), - sizeof(sqtd->qtd.qtd_buffer[0]), + /* Find number of pages we'll be using, insert dma addresses */ + size_t pages = EHCI_NPAGES(curlen); + KASSERT(pages <= EHCI_QTD_NBUFFERS); + size_t pageoffs = EHCI_PAGE(curoffs); + for (size_t i = 0; i < pages; i++) { + paddr_t a = DMAADDR(dma, + pageoffs + i * EHCI_PAGE_SIZE); + sqtd->qtd.qtd_buffer[i] = htole32(EHCI_PAGE(a)); + /* Cast up to avoid compiler warnings */ + sqtd->qtd.qtd_buffer_hi[i] = htole32((uint64_t)a >> 32); + DPRINTF(" buffer[%d/%d] 0x%08x 0x%08x", i, pages, + le32toh(sqtd->qtd.qtd_buffer_hi[i]), + le32toh(sqtd->qtd.qtd_buffer[i])); + } + /* First buffer pointer requires a page offset to start at */ + sqtd->qtd.qtd_buffer[0] |= htole32(va_offs); + + usb_syncmem(&sqtd->dma, sqtd->offs, sizeof(sqtd->qtd), BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); - if (((sqtd->len + mps - 1) / mps) & 1) { + sqtd->len = curlen; + + DPRINTF(" va %p pa %p len %d", va, + DMAADDR(&xfer->ux_dmabuf, curoffs), curlen, 0); + + ehci_append_sqtd(sqtd, prev); + + if (((curlen + mps - 1) / mps) & 1) { tog ^= 1; } - len -= sqtd->len; - if (len == 0) - break; + curoffs += curlen; + len -= curlen; } - KASSERTMSG(len == 0, "xfer %p olen %d len %d mps %d ex_nsqtd %zu i %zu", - xfer, length, len, mps, exfer->ex_nsqtd, i); + KASSERTMSG(len == 0, "xfer %p olen %d len %d mps %d ex_nsqtd %zu j %zu", + xfer, length, len, mps, exfer->ex_nsqtd, j); - if (i < exfer->ex_nsqtd) { - /* - * The full allocation chain wasn't used, so we need to - * terminate it. - */ + if (!isread && + (flags & USBD_FORCE_SHORT_XFER) && + length % mps == 0) { + /* Force a 0 length transfer at the end. */ + + KASSERTMSG(j < exfer->ex_nsqtd, "j=%zu nsqtd=%zu", j, + exfer->ex_nsqtd); + prev = sqtd; + sqtd = exfer->ex_sqtds[j++]; + memset(&sqtd->qtd, 0, sizeof(sqtd->qtd)); sqtd->qtd.qtd_next = sqtd->qtd.qtd_altnext = EHCI_NULL; + sqtd->qtd.qtd_status = htole32( + qtdstatus | + EHCI_QTD_SET_BYTES(0) | + EHCI_QTD_SET_TOGGLE(tog)); + + usb_syncmem(&sqtd->dma, sqtd->offs, sizeof(sqtd->qtd), + BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); + + ehci_append_sqtd(sqtd, prev); + tog ^= 1; } + *lsqtd = sqtd; *toggle = tog; } @@ -3531,9 +3480,8 @@ ehci_device_ctrl_init(struct usbd_xfer * next = status; /* Set up data transaction */ if (len != 0) { - ehci_soft_qtd_t *end; err = ehci_alloc_sqtd_chain(sc, xfer, len, isread, - &exfer->ex_data, &end); + &exfer->ex_data); if (err) goto bad3; next = exfer->ex_data; @@ -3550,7 +3498,7 @@ ehci_device_ctrl_init(struct usbd_xfer * setup->qtd.qtd_next = setup->qtd.qtd_altnext = htole32(next->physaddr); setup->nextqtd = next; setup->xfer = xfer; - setup->tdlen = setup->len = sizeof(*req); + setup->len = sizeof(*req); status->qtd.qtd_status = htole32( EHCI_QTD_SET_PID(isread ? EHCI_QTD_PID_OUT : EHCI_QTD_PID_IN) | @@ -3562,7 +3510,7 @@ ehci_device_ctrl_init(struct usbd_xfer * status->qtd.qtd_next = status->qtd.qtd_altnext = EHCI_NULL; status->nextqtd = NULL; status->xfer = xfer; - status->tdlen = status->len = 0; + status->len = 0; return 0; bad3: @@ -3848,7 +3796,7 @@ ehci_device_bulk_init(struct usbd_xfer * exfer->ex_type = EX_BULK; exfer->ex_nsqtd = 0; err = ehci_alloc_sqtd_chain(sc, xfer, len, isread, - &exfer->ex_sqtdstart, &exfer->ex_sqtdend); + &exfer->ex_sqtdstart); return err; } @@ -4063,7 +4011,7 @@ ehci_device_intr_init(struct usbd_xfer * exfer->ex_type = EX_INTR; exfer->ex_nsqtd = 0; err = ehci_alloc_sqtd_chain(sc, xfer, len, isread, - &exfer->ex_sqtdstart, &exfer->ex_sqtdend); + &exfer->ex_sqtdstart); return err; } @@ -4134,6 +4082,7 @@ ehci_device_intr_start(struct usbd_xfer /* Take lock to protect nexttoggle */ mutex_enter(&sc->sc_lock); + ehci_reset_sqtd_chain(sc, xfer, len, isread, &epipe->nexttoggle, &end); end->qtd.qtd_status |= htole32(EHCI_QTD_IOC); Index: src/sys/dev/usb/ehcivar.h diff -u src/sys/dev/usb/ehcivar.h:1.42.14.24 src/sys/dev/usb/ehcivar.h:1.42.14.25 --- src/sys/dev/usb/ehcivar.h:1.42.14.24 Sat Mar 26 11:42:44 2016 +++ src/sys/dev/usb/ehcivar.h Mon Apr 4 07:43:12 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: ehcivar.h,v 1.42.14.24 2016/03/26 11:42:44 skrll Exp $ */ +/* $NetBSD: ehcivar.h,v 1.42.14.25 2016/04/04 07:43:12 skrll Exp $ */ /* * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -41,9 +41,7 @@ typedef struct ehci_soft_qtd { usb_dma_t dma; /* qTD's DMA infos */ int offs; /* qTD's offset in usb_dma_t */ struct usbd_xfer *xfer; /* xfer back pointer */ - size_t bufoff; /* Offset into xfer buffer */ uint16_t len; - uint16_t tdlen; } ehci_soft_qtd_t; #define EHCI_SQTD_ALIGN MAX(EHCI_QTD_ALIGN, CACHE_LINE_SIZE) #define EHCI_SQTD_SIZE ((sizeof(struct ehci_soft_qtd) + EHCI_SQTD_ALIGN - 1) & -EHCI_SQTD_ALIGN) Index: src/sys/dev/usb/ohci.c diff -u src/sys/dev/usb/ohci.c:1.254.2.69 src/sys/dev/usb/ohci.c:1.254.2.70 --- src/sys/dev/usb/ohci.c:1.254.2.69 Fri Apr 1 15:13:45 2016 +++ src/sys/dev/usb/ohci.c Mon Apr 4 07:43:12 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: ohci.c,v 1.254.2.69 2016/04/01 15:13:45 skrll Exp $ */ +/* $NetBSD: ohci.c,v 1.254.2.70 2016/04/04 07:43:12 skrll Exp $ */ /* * Copyright (c) 1998, 2004, 2005, 2012 The NetBSD Foundation, Inc. @@ -41,7 +41,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.254.2.69 2016/04/01 15:13:45 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.254.2.70 2016/04/04 07:43:12 skrll Exp $"); #include "opt_usb.h" @@ -517,105 +517,37 @@ ohci_free_std(ohci_softc_t *sc, ohci_sof } Static usbd_status -ohci_alloc_std_chain(ohci_softc_t *sc, struct usbd_xfer *xfer, int alen, int rd) +ohci_alloc_std_chain(ohci_softc_t *sc, struct usbd_xfer *xfer, int length, int rd) { struct ohci_xfer *ox = OHCI_XFER2OXFER(xfer); - struct usbd_pipe *pipe = xfer->ux_pipe; - ohci_soft_td_t *next, *cur; - ohci_physaddr_t dataphys, dataphysend; - int len = alen; - int curlen; - usb_dma_t *dma = &xfer->ux_dmabuf; uint16_t flags = xfer->ux_flags; OHCIHIST_FUNC(); OHCIHIST_CALLED(); DPRINTFN(8, "addr=%d endpt=%d len=%d speed=%d", - pipe->up_dev->ud_addr, - UE_GET_ADDR(pipe->up_endpoint->ue_edesc->bEndpointAddress), - alen, pipe->up_dev->ud_speed); + xfer->ux_pipe->up_dev->ud_addr, + UE_GET_ADDR(xfer->ux_pipe->up_endpoint->ue_edesc->bEndpointAddress), + length, xfer->ux_pipe->up_dev->ud_speed); ASSERT_SLEEPABLE(); + KASSERT(length != 0 || (!rd && (flags & USBD_FORCE_SHORT_XFER))); - size_t nstd = (flags & USBD_FORCE_SHORT_XFER) ? 1 : 0; - nstd += ((len + OHCI_PAGE_SIZE - 1) / OHCI_PAGE_SIZE); + size_t nstd = (!rd && (flags & USBD_FORCE_SHORT_XFER)) ? 1 : 0; + nstd += ((length + OHCI_PAGE_SIZE - 1) / OHCI_PAGE_SIZE); ox->ox_stds = kmem_zalloc(sizeof(ohci_soft_td_t *) * nstd, KM_SLEEP); ox->ox_nstd = nstd; - int mps = UGETW(pipe->up_endpoint->ue_edesc->wMaxPacketSize); - DPRINTFN(8, "xfer %p nstd %d mps %d", xfer, nstd, mps, 0); + DPRINTFN(8, "xfer %p nstd %d", xfer, nstd, 0, 0); - len = alen; - cur = ohci_alloc_std(sc); - if (cur == NULL) - goto nomem; - - dataphys = DMAADDR(dma, 0); - dataphysend = OHCI_PAGE(dataphys + len - 1); - const uint32_t tdflags = HTOO32( - (rd ? OHCI_TD_IN : OHCI_TD_OUT) | - OHCI_TD_NOCC | OHCI_TD_TOGGLE_CARRY | OHCI_TD_NOINTR); - - for (size_t j = 0;;) { - ox->ox_stds[j++] = cur; - next = ohci_alloc_std(sc); - if (next == NULL) + for (size_t j = 0; j < ox->ox_nstd;) { + ohci_soft_td_t *cur = ohci_alloc_std(sc); + if (cur == NULL) goto nomem; - /* The OHCI hardware can handle at most one page crossing. */ - if (OHCI_PAGE(dataphys) == dataphysend || - OHCI_PAGE(dataphys) + OHCI_PAGE_SIZE == dataphysend) { - /* we can handle it in this TD */ - curlen = len; - } else { - /* must use multiple TDs, fill as much as possible. */ - curlen = 2 * OHCI_PAGE_SIZE - - (dataphys & (OHCI_PAGE_SIZE - 1)); - /* the length must be a multiple of the max size */ - curlen -= curlen % mps; - KASSERT(curlen != 0); - } - DPRINTFN(4, "dataphys=0x%08x dataphysend=0x%08x " - "len=%d curlen=%d", dataphys, dataphysend, len, curlen); - len -= curlen; - - cur->td.td_flags = tdflags; - cur->td.td_cbp = HTOO32(dataphys); - cur->td.td_nexttd = HTOO32(next->physaddr); - cur->td.td_be = HTOO32(dataphys + curlen - 1); - cur->nexttd = next; - cur->len = curlen; - cur->flags = OHCI_ADD_LEN; + ox->ox_stds[j++] = cur; cur->xfer = xfer; - - DPRINTFN(10, "cbp=0x%08x be=0x%08x", dataphys, - dataphys + curlen - 1, 0, 0); - if (len == 0) - break; - DPRINTFN(10, "extend chain", 0, 0, 0, 0); - dataphys += curlen; - cur = next; - } - if (!rd && (flags & USBD_FORCE_SHORT_XFER) && - alen % mps == 0) { - /* Force a 0 length transfer at the end. */ - - cur = next; - next = ohci_alloc_std(sc); - if (next == NULL) - goto nomem; - - cur->td.td_flags = tdflags; - cur->td.td_cbp = 0; /* indicate 0 length packet */ - cur->td.td_nexttd = HTOO32(next->physaddr); - cur->td.td_be = ~0; - cur->nexttd = next; - cur->len = 0; cur->flags = 0; - cur->xfer = xfer; - - DPRINTFN(2, "add 0 xfer", 0, 0, 0, 0); } return USBD_NORMAL_COMPLETION; @@ -648,7 +580,6 @@ ohci_reset_std_chain(ohci_softc_t *sc, s { struct ohci_xfer *ox = OHCI_XFER2OXFER(xfer); ohci_soft_td_t *next, *cur; - ohci_physaddr_t dataphys, dataphysend; int len, curlen; usb_dma_t *dma = &xfer->ux_dmabuf; uint16_t flags = xfer->ux_flags; @@ -667,44 +598,52 @@ ohci_reset_std_chain(ohci_softc_t *sc, s int mps = UGETW(xfer->ux_pipe->up_endpoint->ue_edesc->wMaxPacketSize); + /* + * Assign next for the len == 0 case where we don't go through the + * main loop. + */ len = alen; - cur = sp; + cur = next = sp; - dataphys = DMAADDR(dma, 0); - dataphysend = OHCI_PAGE(dataphys + len - 1); usb_syncmem(dma, 0, len, rd ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); const uint32_t tdflags = HTOO32( (rd ? OHCI_TD_IN : OHCI_TD_OUT) | OHCI_TD_NOCC | OHCI_TD_TOGGLE_CARRY | OHCI_TD_NOINTR); - for (size_t j = 1;;) { + size_t curoffs = 0; + for (size_t j = 1; len != 0;) { if (j == ox->ox_nstd) next = NULL; else next = ox->ox_stds[j++]; KASSERT(next != cur); - /* The OHCI hardware can handle at most one page crossing. */ - if (OHCI_PAGE(dataphys) == dataphysend || - OHCI_PAGE(dataphys) + OHCI_PAGE_SIZE == dataphysend) { - /* we can handle it in this TD */ - curlen = len; - } else { + curlen = 0; + ohci_physaddr_t sdataphys = DMAADDR(dma, curoffs); + ohci_physaddr_t edataphys = DMAADDR(dma, curoffs + len - 1); + + ohci_physaddr_t sphyspg = OHCI_PAGE(sdataphys); + ohci_physaddr_t ephyspg = OHCI_PAGE(edataphys); + /* + * The OHCI hardware can handle at most one page + * crossing per TD + */ + curlen = len; + if (!(sphyspg == ephyspg || sphyspg + 1 == ephyspg)) { /* must use multiple TDs, fill as much as possible. */ curlen = 2 * OHCI_PAGE_SIZE - - (dataphys & (OHCI_PAGE_SIZE - 1)); + (sdataphys & (OHCI_PAGE_SIZE - 1)); /* the length must be a multiple of the max size */ curlen -= curlen % mps; - KASSERT(curlen != 0); } - DPRINTFN(4, "dataphys=0x%08x dataphysend=0x%08x " - "len=%d curlen=%d", dataphys, dataphysend, len, curlen); - len -= curlen; + KASSERT(curlen != 0); + DPRINTFN(4, "sdataphys=0x%08x edataphys=0x%08x " + "len=%d curlen=%d", sdataphys, edataphys, len, curlen); cur->td.td_flags = tdflags; - cur->td.td_cbp = HTOO32(dataphys); - cur->td.td_be = HTOO32(dataphys + curlen - 1); + cur->td.td_cbp = HTOO32(sdataphys); + cur->td.td_be = HTOO32(edataphys); cur->td.td_nexttd = (next != NULL) ? HTOO32(next->physaddr) : 0; cur->nexttd = next; cur->len = curlen; @@ -714,14 +653,15 @@ ohci_reset_std_chain(ohci_softc_t *sc, s usb_syncmem(&cur->dma, cur->offs, sizeof(cur->td), BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); - DPRINTFN(10, "cbp=0x%08x be=0x%08x", dataphys, - dataphys + curlen - 1, 0, 0); - if (len == 0) - break; - KASSERT(next != NULL); - DPRINTFN(10, "extend chain", 0, 0, 0, 0); - dataphys += curlen; - cur = next; + + curoffs += curlen; + len -= curlen; + + if (len != 0) { + KASSERT(next != NULL); + DPRINTFN(10, "extend chain", 0, 0, 0, 0); + cur = next; + } } cur->td.td_flags |= (xfer->ux_flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0); @@ -736,7 +676,7 @@ ohci_reset_std_chain(ohci_softc_t *sc, s cur->td.td_flags = tdflags; cur->td.td_cbp = 0; /* indicate 0 length packet */ - cur->td.td_nexttd = HTOO32(next->physaddr); + cur->td.td_nexttd = 0; cur->td.td_be = ~0; cur->nexttd = NULL; cur->len = 0; Index: src/sys/dev/usb/uhci.c diff -u src/sys/dev/usb/uhci.c:1.264.4.69 src/sys/dev/usb/uhci.c:1.264.4.70 --- src/sys/dev/usb/uhci.c:1.264.4.69 Fri Mar 25 17:44:00 2016 +++ src/sys/dev/usb/uhci.c Mon Apr 4 07:43:12 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: uhci.c,v 1.264.4.69 2016/03/25 17:44:00 skrll Exp $ */ +/* $NetBSD: uhci.c,v 1.264.4.70 2016/04/04 07:43:12 skrll Exp $ */ /* * Copyright (c) 1998, 2004, 2011, 2012 The NetBSD Foundation, Inc. @@ -42,7 +42,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uhci.c,v 1.264.4.69 2016/03/25 17:44:00 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uhci.c,v 1.264.4.70 2016/04/04 07:43:12 skrll Exp $"); #include "opt_usb.h" @@ -179,7 +179,7 @@ Static void uhci_exit_ctl_q(uhci_softc_ Static void uhci_free_std_chain(uhci_softc_t *, uhci_soft_td_t *, uhci_soft_td_t *); Static usbd_status uhci_alloc_std_chain(uhci_softc_t *, struct usbd_xfer *, - int, int, uhci_soft_td_t **, uhci_soft_td_t **); + int, int, uhci_soft_td_t **); Static void uhci_free_stds(uhci_softc_t *, struct uhci_xfer *); Static void uhci_reset_std_chain(uhci_softc_t *, struct usbd_xfer *, @@ -2011,95 +2011,53 @@ uhci_free_std_chain(uhci_softc_t *sc, uh } usbd_status -uhci_alloc_std_chain(uhci_softc_t *sc, struct usbd_xfer *xfer, int alen, - int rd, uhci_soft_td_t **sp, uhci_soft_td_t **ep) +uhci_alloc_std_chain(uhci_softc_t *sc, struct usbd_xfer *xfer, int len, + int rd, uhci_soft_td_t **sp) { - uhci_soft_td_t *p, *lastp; - uhci_physaddr_t lastlink; - int i, l, maxp; - int len; - uint32_t status; struct uhci_xfer *uxfer = UHCI_XFER2UXFER(xfer); - int addr = xfer->ux_pipe->up_dev->ud_addr; - int endpt = xfer->ux_pipe->up_endpoint->ue_edesc->bEndpointAddress; - usb_dma_t *dma = &xfer->ux_dmabuf; uint16_t flags = xfer->ux_flags; + uhci_soft_td_t *p; UHCIHIST_FUNC(); UHCIHIST_CALLED(); DPRINTFN(8, "xfer=%p pipe=%p", xfer, xfer->ux_pipe, 0, 0); - DPRINTFN(8, "addr=%d endpt=%d len=%d speed=%d", - addr, UE_GET_ADDR(endpt), alen, xfer->ux_pipe->up_dev->ud_speed); ASSERT_SLEEPABLE(); KASSERT(sp); - len = alen; - maxp = UGETW(xfer->ux_pipe->up_endpoint->ue_edesc->wMaxPacketSize); + int maxp = UGETW(xfer->ux_pipe->up_endpoint->ue_edesc->wMaxPacketSize); if (maxp == 0) { printf("%s: maxp=0\n", __func__); return USBD_INVAL; } size_t ntd = (len + maxp - 1) / maxp; - if ((flags & USBD_FORCE_SHORT_XFER) && len % maxp == 0) + if (!rd && (flags & USBD_FORCE_SHORT_XFER)) { ntd++; + } DPRINTFN(10, "maxp=%d ntd=%d", maxp, ntd, 0, 0); uxfer->ux_stds = NULL; uxfer->ux_nstd = ntd; + p = NULL; if (ntd == 0) { *sp = NULL; - if (ep) - *ep = NULL; DPRINTF("ntd=0", 0, 0, 0, 0); return USBD_NORMAL_COMPLETION; } uxfer->ux_stds = kmem_alloc(sizeof(uhci_soft_td_t *) * ntd, KM_SLEEP); - lastp = NULL; ntd--; - status = UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(3) | UHCI_TD_ACTIVE); - if (xfer->ux_pipe->up_dev->ud_speed == USB_SPEED_LOW) - status |= UHCI_TD_LS; - if (flags & USBD_SHORT_XFER_OK) - status |= UHCI_TD_SPD; - for (i = ntd; i >= 0; i--) { + for (int i = ntd; i >= 0; i--) { p = uhci_alloc_std(sc); if (p == NULL) { - uhci_free_std_chain(sc, lastp, NULL); + uhci_free_stds(sc, uxfer); return USBD_NOMEM; } uxfer->ux_stds[i] = p; - if (i == ntd) { - /* last TD */ - l = len % maxp; - if (l == 0 && !(flags & USBD_FORCE_SHORT_XFER)) - l = maxp; - if (ep) - *ep = p; - lastlink = UHCI_PTR_T; - } else { - l = maxp; - lastlink = p->physaddr; - } - p->link.std = lastp; - p->td.td_link = htole32(lastlink | UHCI_PTR_VF | UHCI_PTR_TD); - p->td.td_status = htole32(status); - p->td.td_token = htole32( - (rd ? UHCI_TD_PID_IN : UHCI_TD_PID_OUT) | - UHCI_TD_SET_MAXLEN(l) | - UHCI_TD_SET_ENDPT(UE_GET_ADDR(endpt)) | - UHCI_TD_SET_DEVADDR(addr) - ); - p->td.td_buffer = htole32(DMAADDR(dma, i * maxp)); - DPRINTF("std %p link 0x%08x status 0x%08x token 0x%08x", - p, le32toh(p->td.td_link), le32toh(p->td.td_status), - le32toh(p->td.td_token)); - - lastp = p; } - *sp = lastp; + + *sp = uxfer->ux_stds[0]; return USBD_NORMAL_COMPLETION; } @@ -2147,11 +2105,14 @@ uhci_reset_std_chain(uhci_softc_t *sc, s DPRINTFN(8, "xfer=%p len %d isread %d toggle %d", xfer, len, isread, *toggle); - KASSERT(len != 0 || (flags & USBD_FORCE_SHORT_XFER)); + KASSERT(len != 0 || (!isread && (flags & USBD_FORCE_SHORT_XFER))); maxp = UGETW(pipe->up_endpoint->ue_edesc->wMaxPacketSize); KASSERT(maxp != 0); + int addr = xfer->ux_pipe->up_dev->ud_addr; + int endpt = xfer->ux_pipe->up_endpoint->ue_edesc->bEndpointAddress; + status = UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(3) | UHCI_TD_ACTIVE); if (pipe->up_dev->ud_speed == USB_SPEED_LOW) status |= UHCI_TD_LS; @@ -2159,15 +2120,12 @@ uhci_reset_std_chain(uhci_softc_t *sc, s status |= UHCI_TD_SPD; usb_syncmem(dma, 0, len, isread ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); - std = prev = NULL; - for (i = 0; i < uxfer->ux_nstd; i++, prev = std) { + for (i = 0; len != 0 && i < uxfer->ux_nstd; i++, prev = std) { int l = len; std = uxfer->ux_stds[i]; if (l > maxp) l = maxp; - if (l == 0 && !(flags & USBD_FORCE_SHORT_XFER)) - break; if (prev) { prev->link.std = std; @@ -2178,53 +2136,62 @@ uhci_reset_std_chain(uhci_softc_t *sc, s BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); } - int addr __diagused = xfer->ux_pipe->up_dev->ud_addr; - int endpt __diagused = xfer->ux_pipe->up_endpoint->ue_edesc->bEndpointAddress; - KASSERTMSG(UHCI_TD_GET_ENDPT(le32toh(std->td.td_token)) == UE_GET_ADDR(endpt), - "%" __PRIuBIT " vs %d (0x%08x) in %p", - UHCI_TD_GET_ENDPT(le32toh(std->td.td_token)), - UE_GET_ADDR(endpt), le32toh(std->td.td_token), std); - KASSERTMSG(UHCI_TD_GET_DEVADDR(le32toh(std->td.td_token)) == addr, - "%" __PRIuBIT " vs %d (0x%08x) in %p", - UHCI_TD_GET_DEVADDR(le32toh(std->td.td_token)), addr, - le32toh(std->td.td_token), std); - usb_syncmem(&std->dma, std->offs, sizeof(std->td), BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); + std->td.td_link = htole32(UHCI_PTR_T | UHCI_PTR_VF | UHCI_PTR_TD); std->td.td_status = htole32(status); - std->td.td_token &= ~htole32( - UHCI_TD_PID_MASK | - UHCI_TD_DT_MASK | - UHCI_TD_MAXLEN_MASK - ); - std->td.td_token |= htole32( + std->td.td_token = htole32( + UHCI_TD_SET_ENDPT(UE_GET_ADDR(endpt)) | + UHCI_TD_SET_DEVADDR(addr) | UHCI_TD_SET_PID(isread ? UHCI_TD_PID_IN : UHCI_TD_PID_OUT) | UHCI_TD_SET_DT(tog) | UHCI_TD_SET_MAXLEN(l) ); - std->td.td_link &= ~htole32(UHCI_PTR_T); + std->td.td_buffer = htole32(DMAADDR(dma, i * maxp)); + + std->link.std = NULL; usb_syncmem(&std->dma, std->offs, sizeof(std->td), BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); tog ^= 1; len -= l; - if (len == 0) - break; } KASSERTMSG(len == 0, "xfer %p alen %d len %d mps %d ux_nqtd %zu i %zu", xfer, length, len, maxp, uxfer->ux_nstd, i); - if (i < uxfer->ux_nstd) { - /* - * The full allocation chain wasn't used, so we need to - * terminate it. - */ - std->link.std = NULL; - std->td.td_link = htole32(UHCI_PTR_T); + if (!isread && + (flags & USBD_FORCE_SHORT_XFER) && + length % maxp == 0) { + /* Force a 0 length transfer at the end. */ + KASSERTMSG(i < uxfer->ux_nstd, "i=%zu nstd=%zu", i, + uxfer->ux_nstd); + std = uxfer->ux_stds[i++]; + + std->td.td_link = htole32(UHCI_PTR_T | UHCI_PTR_VF | UHCI_PTR_TD); + std->td.td_status = htole32(status); + std->td.td_token = htole32( + UHCI_TD_SET_ENDPT(UE_GET_ADDR(endpt)) | + UHCI_TD_SET_DEVADDR(addr) | + UHCI_TD_SET_PID(UHCI_TD_PID_OUT) | + UHCI_TD_SET_DT(tog) | + UHCI_TD_SET_MAXLEN(0) + ); + std->td.td_buffer = 0; usb_syncmem(&std->dma, std->offs, sizeof(std->td), BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); + + std->link.std = NULL; + if (prev) { + prev->link.std = std; + prev->td.td_link = htole32( + std->physaddr | UHCI_PTR_VF | UHCI_PTR_TD + ); + usb_syncmem(&prev->dma, prev->offs, sizeof(prev->td), + BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); + } + tog ^= 1; } *lstd = std; *toggle = tog; @@ -2263,8 +2230,7 @@ uhci_device_bulk_init(struct usbd_xfer * KASSERT(!(xfer->ux_rqflags & URQ_REQUEST)); uxfer->ux_type = UX_BULK; - err = uhci_alloc_std_chain(sc, xfer, len, isread, &uxfer->ux_stdstart, - &uxfer->ux_stdend); + err = uhci_alloc_std_chain(sc, xfer, len, isread, &uxfer->ux_stdstart); if (err) return err; @@ -2525,68 +2491,30 @@ uhci_device_ctrl_init(struct usbd_xfer * usb_device_request_t *req = &xfer->ux_request; struct usbd_device *dev = upipe->pipe.up_dev; uhci_softc_t *sc = dev->ud_bus->ub_hcpriv; - int addr = dev->ud_addr; int endpt = upipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; - uhci_soft_td_t *setup, *data, *stat, *next, *dataend; + uhci_soft_td_t *data; int len; - uint32_t ls; usbd_status err; int isread; UHCIHIST_FUNC(); UHCIHIST_CALLED(); - DPRINTFN(3, "len=%d, addr=%d, endpt=%d", xfer->ux_bufsize, - dev->ud_addr, endpt, 0); + DPRINTFN(3, "xfer=%p len=%d, addr=%d, endpt=%d", xfer, xfer->ux_bufsize, + dev->ud_addr, endpt); - ls = dev->ud_speed == USB_SPEED_LOW ? UHCI_TD_LS : 0; isread = req->bmRequestType & UT_READ; len = xfer->ux_bufsize; uxfer->ux_type = UX_CTRL; - setup = upipe->ctrl.setup; - stat = upipe->ctrl.stat; - /* Set up data transaction */ if (len != 0) { - err = uhci_alloc_std_chain(sc, xfer, len, isread, &data, - &dataend); + err = uhci_alloc_std_chain(sc, xfer, len, isread, &data); if (err) return err; - next = data; - dataend->link.std = stat; - dataend->td.td_link = htole32(stat->physaddr | UHCI_PTR_TD); - } else { - next = stat; - } - - setup->link.std = next; - setup->td.td_link = htole32(next->physaddr | UHCI_PTR_TD); - setup->td.td_status = htole32(UHCI_TD_SET_ERRCNT(3) | ls | - UHCI_TD_ACTIVE); - setup->td.td_token = htole32(UHCI_TD_SETUP(sizeof(*req), endpt, addr)); - setup->td.td_buffer = htole32(DMAADDR(&upipe->ctrl.reqdma, 0)); - - stat->link.std = NULL; - stat->td.td_link = htole32(UHCI_PTR_T); - stat->td.td_status = htole32(UHCI_TD_SET_ERRCNT(3) | ls | - UHCI_TD_ACTIVE | UHCI_TD_IOC); - stat->td.td_token = - htole32(isread ? UHCI_TD_OUT(0, endpt, addr, 1) : - UHCI_TD_IN (0, endpt, addr, 1)); - stat->td.td_buffer = htole32(0); - - DPRINTFN(10, "--- dump start ---", 0, 0, 0, 0); -#ifdef UHCI_DEBUG - if (uhcidebug >= 10) { - DPRINTFN(10, "before transfer", 0, 0, 0, 0); - uhci_dump_tds(setup); } -#endif - DPRINTFN(10, "--- dump end ---", 0, 0, 0, 0); - /* Set up interrupt info. */ - uxfer->ux_setup = setup; + uxfer->ux_setup = upipe->ctrl.setup; + uxfer->ux_stat = upipe->ctrl.stat; uxfer->ux_data = data; - uxfer->ux_stat = stat; return 0; } @@ -2637,7 +2565,6 @@ uhci_device_ctrl_start(struct usbd_xfer uhci_soft_td_t *setup, *stat, *next, *dataend; uhci_soft_qh_t *sqh; int len; - uint32_t ls; int isread; UHCIHIST_FUNC(); UHCIHIST_CALLED(); @@ -2654,7 +2581,6 @@ uhci_device_ctrl_start(struct usbd_xfer DPRINTFN(3, "len=%d, addr=%d, endpt=%d", UGETW(req->wLength), dev->ud_addr, endpt, 0); - ls = dev->ud_speed == USB_SPEED_LOW ? UHCI_TD_LS : 0; isread = req->bmRequestType & UT_READ; len = UGETW(req->wLength); @@ -2683,22 +2609,23 @@ uhci_device_ctrl_start(struct usbd_xfer next = stat; } - setup->link.std = next; - setup->td.td_link = htole32(next->physaddr | UHCI_PTR_TD); - setup->td.td_status |= htole32( + const uint32_t status = UHCI_TD_ZERO_ACTLEN( UHCI_TD_SET_ERRCNT(3) | - ls | - UHCI_TD_ACTIVE + UHCI_TD_ACTIVE | + (dev->ud_speed == USB_SPEED_LOW ? UHCI_TD_LS : 0) ); - setup->td.td_token &= ~htole32(UHCI_TD_MAXLEN_MASK); - setup->td.td_token |= htole32(UHCI_TD_SET_MAXLEN(sizeof(*req))); + setup->link.std = next; + setup->td.td_link = htole32(next->physaddr | UHCI_PTR_TD); + setup->td.td_status = htole32(status); + setup->td.td_token = htole32(UHCI_TD_SETUP(sizeof(*req), endpt, addr)); + setup->td.td_buffer = htole32(DMAADDR(&upipe->ctrl.reqdma, 0)); + usb_syncmem(&setup->dma, setup->offs, sizeof(setup->td), BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); stat->link.std = NULL; stat->td.td_link = htole32(UHCI_PTR_T); - stat->td.td_status = htole32(UHCI_TD_SET_ERRCNT(3) | ls | - UHCI_TD_ACTIVE | UHCI_TD_IOC); + stat->td.td_status = htole32(status | UHCI_TD_IOC); stat->td.td_token = htole32(isread ? UHCI_TD_OUT(0, endpt, addr, 1) : UHCI_TD_IN (0, endpt, addr, 1)); @@ -2795,8 +2722,7 @@ uhci_device_intr_init(struct usbd_xfer * ux->ux_type = UX_INTR; ux->ux_nstd = 0; - err = uhci_alloc_std_chain(sc, xfer, len, isread, - &ux->ux_stdstart, &ux->ux_stdend); + err = uhci_alloc_std_chain(sc, xfer, len, isread, &ux->ux_stdstart); return err; }