Hi, The following diff makes the trb iteration code easier to read and understand. I don't know why it needed to be done the other way around.
General agreement and support from stsp@. Paul Index: dev/usb/xhci.c =================================================================== RCS file: /cvs/src/sys/dev/usb/xhci.c,v retrieving revision 1.77 diff -u -p -u -p -r1.77 xhci.c --- dev/usb/xhci.c 8 Sep 2017 10:25:19 -0000 1.77 +++ dev/usb/xhci.c 6 Nov 2017 11:58:01 -0000 @@ -2763,17 +2768,18 @@ xhci_device_isoc_start(struct usbd_xfer paddr = DMAADDR(&xfer->dmabuf, offs); /* Chain more TRBs if needed. */ - for (i = ntrb - 1; i > 0; i--) { - len = xfer->frlengths[ntrb - i]; + for (i = 1; i < ntrb; i++) { + int last = (i == ntrb - 1); + len = xfer->frlengths[i]; KASSERT(len <= UGETW(ed->wMaxPacketSize)); /* Next (or Last) TRB. */ - trb = xhci_xfer_get_trb(sc, xfer, &toggle, (i == 1)); + trb = xhci_xfer_get_trb(sc, xfer, &toggle, last); flags = XHCI_TRB_TYPE_NORMAL | toggle; if (usbd_xfer_isread(xfer)) flags |= XHCI_TRB_ISP; - flags |= (i == 1) ? XHCI_TRB_IOC : XHCI_TRB_CHAIN; + flags |= last ? XHCI_TRB_IOC : XHCI_TRB_CHAIN; trb->trb_paddr = htole64(paddr); trb->trb_status = htole32(