Hello,

I'll post xhci patches for HEAD.


x-addrendian.diff
        + Fix endian issue of device address.
x-linktrb2.diff
        + Put Link TRB always at the end of ring.
          Should fix ctrl xfer problem on Intel xHC.


Thanks,
--
t-hash
--- sys/dev/usb/xhci.c.orig     2016-07-18 07:07:53.000000000 +0900
+++ sys/dev/usb/xhci.c  2016-08-07 14:17:46.000000000 +0900
@@ -2229,7 +2246,7 @@ xhci_new_device(device_t parent, struct 
 
                cp = xhci_slot_get_dcv(sc, xs, XHCI_DCI_SLOT);
                //hexdump("slot context", cp, sc->sc_ctxsz);
-               uint8_t addr = XHCI_SCTX_3_DEV_ADDR_GET(cp[3]);
+               uint8_t addr = XHCI_SCTX_3_DEV_ADDR_GET(le32toh(cp[3]));
                DPRINTFN(4, "device address %u", addr, 0, 0, 0);
                /* XXX ensure we know when the hardware does something
                   we can't yet cope with */
--- sys/dev/usb/xhci.c.orig     2016-07-18 07:07:53.000000000 +0900
+++ sys/dev/usb/xhci.c  2016-08-09 17:37:40.000000000 +0900
@@ -2374,58 +2397,63 @@ xhci_ring_put(struct xhci_softc * const 
         * The code should write the 'cycle' bit on the link trb AFTER
         * adding the other trb.
         */
-       if (ri + ntrbs >= (xr->xr_ntrb - 1)) {
-               parameter = xhci_ring_trbp(xr, 0);
-               status = 0;
-               control = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_LINK) |
-                   XHCI_TRB_3_TC_BIT | (cs ? XHCI_TRB_3_CYCLE_BIT : 0);
-               xhci_trb_put(&xr->xr_trb[ri], parameter, status, control);
-               usb_syncmem(&xr->xr_dma, XHCI_TRB_SIZE * ri, XHCI_TRB_SIZE * 1,
-                   BUS_DMASYNC_PREWRITE);
-               xr->xr_cookies[ri] = NULL;
-               xr->xr_ep = 0;
-               xr->xr_cs ^= 1;
-               ri = xr->xr_ep;
-               cs = xr->xr_cs;
-       }
-
-       ri++;
-
-       /* Write any subsequent TRB first */
-       for (i = 1; i < ntrbs; i++) {
-               parameter = trbs[i].trb_0;
-               status = trbs[i].trb_2;
-               control = trbs[i].trb_3;
+       u_int firstep = xr->xr_ep;
+       u_int firstcs = xr->xr_cs;
 
-               if (cs) {
-                       control |= XHCI_TRB_3_CYCLE_BIT;
+       for (i = 0; i < ntrbs; ) {
+               u_int oldri = ri;
+               u_int oldcs = cs;
+
+               if (ri >= (xr->xr_ntrb - 1)) {
+                       /* Put Link TD at the end of ring */
+                       parameter = xhci_ring_trbp(xr, 0);
+                       status = 0;
+                       control = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_LINK) |
+                           XHCI_TRB_3_TC_BIT;
+                       xr->xr_cookies[ri] = NULL;
+                       xr->xr_ep = 0;
+                       xr->xr_cs ^= 1;
+                       ri = xr->xr_ep;
+                       cs = xr->xr_cs;
                } else {
-                       control &= ~XHCI_TRB_3_CYCLE_BIT;
+                       parameter = trbs[i].trb_0;
+                       status = trbs[i].trb_2;
+                       control = trbs[i].trb_3;
+
+                       xr->xr_cookies[ri] = cookie;
+                       ri++;
+                       i++;
                }
-
-               xhci_trb_put(&xr->xr_trb[ri], parameter, status, control);
-               usb_syncmem(&xr->xr_dma, XHCI_TRB_SIZE * ri, XHCI_TRB_SIZE * 1,
-                   BUS_DMASYNC_PREWRITE);
-               xr->xr_cookies[ri] = cookie;
-               ri++;
+               /*
+                * If this is a first TRB, mark it invalid to prevent
+                * xHC from running it immediately.
+                */
+               if (oldri == firstep) {
+                       if (oldcs) {
+                               control &= ~XHCI_TRB_3_CYCLE_BIT;
+                       } else {
+                               control |= XHCI_TRB_3_CYCLE_BIT;
+                       }
+               } else {
+                       if (oldcs) {
+                               control |= XHCI_TRB_3_CYCLE_BIT;
+                       } else {
+                               control &= ~XHCI_TRB_3_CYCLE_BIT;
+                       }
+               }
+               xhci_trb_put(&xr->xr_trb[oldri], parameter, status, control);
+               usb_syncmem(&xr->xr_dma, XHCI_TRB_SIZE * oldri,
+                   XHCI_TRB_SIZE * 1, BUS_DMASYNC_PREWRITE);
        }
 
-       /* Write the first TRB last */
-       i = 0;
-       parameter = trbs[i].trb_0;
-       status = trbs[i].trb_2;
-       control = trbs[i].trb_3;
-
-       if (xr->xr_cs) {
-               control |= XHCI_TRB_3_CYCLE_BIT;
+       /* Now invert cycle bit of first TRB */
+       if (firstcs) {
+               xr->xr_trb[firstep].trb_3 |= htole32(XHCI_TRB_3_CYCLE_BIT);
        } else {
-               control &= ~XHCI_TRB_3_CYCLE_BIT;
+               xr->xr_trb[firstep].trb_3 &= ~htole32(XHCI_TRB_3_CYCLE_BIT);
        }
-
-       xhci_trb_put(&xr->xr_trb[xr->xr_ep], parameter, status, control);
-       usb_syncmem(&xr->xr_dma, XHCI_TRB_SIZE * xr->xr_ep, XHCI_TRB_SIZE * 1,
-           BUS_DMASYNC_PREWRITE);
-       xr->xr_cookies[xr->xr_ep] = cookie;
+       usb_syncmem(&xr->xr_dma, XHCI_TRB_SIZE * firstep,
+           XHCI_TRB_SIZE * 1, BUS_DMASYNC_PREWRITE);
 
        xr->xr_ep = ri;
        xr->xr_cs = cs;

Reply via email to