Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/nick-nhusb]: src/sys/dev/usb Various improvements from t-hash (updated b...



details:   https://anonhg.NetBSD.org/src/rev/fbd3c866ca26
branches:  nick-nhusb
changeset: 804383:fbd3c866ca26
user:      skrll <skrll%NetBSD.org@localhost>
date:      Sun Sep 13 09:27:54 2015 +0000

description:
Various improvements from t-hash (updated by me)

    + Improve xhci_configure_endpoint().
        + Split off maxburst and interval calculation.
            + Start interval calculation with 10, not 11.
            + Put correct maxburst value.
        + Split off constructing endpoint context.
    + Improve xhci_event_transfer()
        + Remove case of unlikely completion codes I added.
    + Clear xr_cookies too when xhci_set_dequeue() clears xr_trb.
    + Return USBD_NO_ADDR if xhci_address_device fails with
      XHCI_TRB_ERROR_NO_SLOTS.
    + Add aprint_debug xhci capability registers.
    + Add & update comments.

I checked HCCPARAMS1 against version 1.1 of the XHCI specification.  Not
sure of previous version formats

diffstat:

 sys/dev/usb/xhci.c    |  448 +++++++++++++++++++++++++++++--------------------
 sys/dev/usb/xhcireg.h |  253 +++++++++++++++------------
 2 files changed, 402 insertions(+), 299 deletions(-)

diffs (truncated from 984 to 300 lines):

diff -r 92c97113b707 -r fbd3c866ca26 sys/dev/usb/xhci.c
--- a/sys/dev/usb/xhci.c        Sun Sep 13 06:50:09 2015 +0000
+++ b/sys/dev/usb/xhci.c        Sun Sep 13 09:27:54 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: xhci.c,v 1.28.2.36 2015/09/13 06:50:09 skrll Exp $     */
+/*     $NetBSD: xhci.c,v 1.28.2.37 2015/09/13 09:27:54 skrll Exp $     */
 
 /*
  * Copyright (c) 2013 Jonathan A. Kollasch
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.28.2.36 2015/09/13 06:50:09 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.28.2.37 2015/09/13 09:27:54 skrll Exp $");
 
 #include "opt_usb.h"
 
@@ -613,12 +613,46 @@
 #endif
 }
 
+#define XHCI_HCCPREV1_BITS     \
+       "\177\020"      /* New bitmask */                       \
+       "f\020\020XECP\0"                                       \
+       "f\014\4MAXPSA\0"                                       \
+       "b\013CFC\0"                                            \
+       "b\012SEC\0"                                            \
+       "b\011SBD\0"                                            \
+       "b\010FSE\0"                                            \
+       "b\7NSS\0"                                              \
+       "b\6LTC\0"                                              \
+       "b\5LHRC\0"                                             \
+       "b\4PIND\0"                                             \
+       "b\3PPC\0"                                              \
+       "b\2CZC\0"                                              \
+       "b\1BNC\0"                                              \
+       "b\0AC64\0"                                             \
+       "\0"
+#define XHCI_HCCV1_x_BITS      \
+       "\177\020"      /* New bitmask */                       \
+       "f\020\020XECP\0"                                       \
+       "f\014\4MAXPSA\0"                                       \
+       "b\013CFC\0"                                            \
+       "b\012SEC\0"                                            \
+       "b\011SPC\0"                                            \
+       "b\010PAE\0"                                            \
+       "b\7NSS\0"                                              \
+       "b\6LTC\0"                                              \
+       "b\5LHRC\0"                                             \
+       "b\4PIND\0"                                             \
+       "b\3PPC\0"                                              \
+       "b\2CSZ\0"                                              \
+       "b\1BNC\0"                                              \
+       "b\0AC64\0"                                             \
+       "\0"
 
 int
 xhci_init(struct xhci_softc *sc)
 {
        bus_size_t bsz;
-       uint32_t cap, hcs1, hcs2, hcc, dboff, rtsoff;
+       uint32_t cap, hcs1, hcs2, hcs3, hcc, dboff, rtsoff;
        uint32_t ecp, ecr;
        uint32_t usbcmd, usbsts, pagesize, config;
        int i;
@@ -635,7 +669,8 @@
        caplength = XHCI_CAP_CAPLENGTH(cap);
        hciversion = XHCI_CAP_HCIVERSION(cap);
 
-       if ((hciversion < 0x0096) || (hciversion > 0x0100)) {
+       if (hciversion < XHCI_HCIVERSION_0_96 ||
+           hciversion > XHCI_HCIVERSION_1_0) {
                aprint_normal_dev(sc->sc_dev,
                    "xHCI version %x.%x not known to be supported\n",
                    (hciversion >> 8) & 0xff, (hciversion >> 0) & 0xff);
@@ -655,15 +690,22 @@
        sc->sc_maxintrs = XHCI_HCS1_MAXINTRS(hcs1);
        sc->sc_maxports = XHCI_HCS1_MAXPORTS(hcs1);
        hcs2 = xhci_cap_read_4(sc, XHCI_HCSPARAMS2);
-       (void)xhci_cap_read_4(sc, XHCI_HCSPARAMS3);
+       hcs3 = xhci_cap_read_4(sc, XHCI_HCSPARAMS3);
+       aprint_debug_dev(sc->sc_dev,
+           "hcs1=%"PRIx32" hcs2=%"PRIx32" hcs3=%"PRIx32"\n", hcs1, hcs2, hcs3);
+
        hcc = xhci_cap_read_4(sc, XHCI_HCCPARAMS);
-
        sc->sc_ac64 = XHCI_HCC_AC64(hcc);
        sc->sc_ctxsz = XHCI_HCC_CSZ(hcc) ? 64 : 32;
-       aprint_debug_dev(sc->sc_dev, "ac64 %d ctxsz %d\n", sc->sc_ac64,
-           sc->sc_ctxsz);
-
+
+       char sbuf[128];
+       if (hciversion < XHCI_HCIVERSION_1_0)
+               snprintb(sbuf, sizeof(sbuf), XHCI_HCCPREV1_BITS, hcc);
+       else
+               snprintb(sbuf, sizeof sbuf, XHCI_HCCV1_x_BITS, hcc);
+       aprint_debug_dev(sc->sc_dev, "hcc=%s\n", sbuf);
        aprint_debug_dev(sc->sc_dev, "xECP %x\n", XHCI_HCC_XECP(hcc) * 4);
+
        ecp = XHCI_HCC_XECP(hcc) * 4;
        while (ecp != 0) {
                ecr = xhci_read_4(sc, ecp);
@@ -1072,8 +1114,8 @@
 
        XHCIHIST_FUNC(); XHCIHIST_CALLED();
 
-       /* 6.2.2 */
        /*
+        * 6.2.2, Table 57-60, 6.2.2.1, 6.2.2.2
         * tthubslot:
         *   This is the slot ID of parent HS hub
         *   if LS/FS device is connected && connected through HS hub.
@@ -1093,7 +1135,6 @@
             dev->ud_myhub->ud_speed == USB_SPEED_HIGH) &&
            (speed == USB_SPEED_LOW || speed == USB_SPEED_FULL)) {
                ttportnum = dev->ud_myhsport->up_portno;
-               /* XXX addr == slot ? */
                tthubslot = dev->ud_myhsport->up_parent->ud_addr;
        } else {
                ttportnum = 0;
@@ -1156,11 +1197,174 @@
        cp[3] |= htole32(0);
 }
 
+static uint32_t
+xhci_get_maxburst(struct usbd_pipe *pipe)
+{
+       usb_endpoint_descriptor_t * const ed = pipe->up_endpoint->ue_edesc;
+       usbd_desc_iter_t iter;
+       const usb_cdc_descriptor_t *cdcd;
+       const usb_endpoint_ss_comp_descriptor_t * esscd = NULL;
+       uint32_t maxb = 0;
+       uint8_t ep;
+
+       cdcd = (const usb_cdc_descriptor_t *)usb_find_desc(
+           pipe->up_dev, UDESC_INTERFACE, USBD_CDCSUBTYPE_ANY);
+       usb_desc_iter_init(pipe->up_dev, &iter);
+       iter.cur = (const void *)cdcd;
+
+       /* find endpoint_ss_comp desc for ep of this pipe */
+       for (ep = 0;;) {
+               cdcd = (const usb_cdc_descriptor_t *)usb_desc_iter_next(&iter);
+               if (cdcd == NULL)
+                       break;
+               if (ep == 0 && cdcd->bDescriptorType == UDESC_ENDPOINT) {
+                       ep = ((const usb_endpoint_descriptor_t *)cdcd)->
+                           bEndpointAddress;
+                       if (UE_GET_ADDR(ep) ==
+                           UE_GET_ADDR(ed->bEndpointAddress)) {
+                               cdcd = (const usb_cdc_descriptor_t *)
+                                   usb_desc_iter_next(&iter);
+                               break;
+                       }
+                       ep = 0;
+               }
+       }
+       if (cdcd != NULL && cdcd->bDescriptorType == UDESC_ENDPOINT_SS_COMP) {
+               esscd = (const usb_endpoint_ss_comp_descriptor_t *)cdcd;
+               maxb = esscd->bMaxBurst;
+       }
+
+       return maxb;
+}
+
 /*
- * called
- *  from xhci_open
- *  from usbd_setup_pipe_flags
- *  from usbd_open_pipe_ival
+ * Convert endpoint bInterval value to endpoint context interval value
+ * for Interrupt pipe.
+ * xHCI 6.2.3.6 Table 65, USB 2.0 9.6.6
+ */
+static uint32_t
+xhci_bival2ival(uint32_t ival, int speed)
+{
+       if (speed == USB_SPEED_LOW || speed == USB_SPEED_FULL) {
+               int i;
+
+               /*
+                * round ival down to "the nearest base 2 multiple of
+                * bInterval * 8".
+                * bInterval is at most 255 as its type is uByte.
+                * 255(ms) = 2040(x 125us) < 2^11, so start with 10.
+                */
+               for (i = 10; i > 0; i--) {
+                       if ((ival * 8) >= (1 << i))
+                               break;
+               }
+               ival = i;
+       } else {
+               /* Interval = bInterval-1 for SS/HS */
+               ival--;
+       }
+
+       return ival;
+}
+
+/*
+ * 4.8.2, 6.2.3.2
+ * construct common endpoint parameters
+ */
+static void
+xhci_setup_endp_ctx(struct usbd_pipe *pipe, uint32_t *cp)
+{
+       struct xhci_slot * const xs = pipe->up_dev->ud_hcpriv;
+       usb_endpoint_descriptor_t * const ed = pipe->up_endpoint->ue_edesc;
+       const u_int dci = xhci_ep_get_dci(ed);
+       const uint8_t xfertype = UE_GET_XFERTYPE(ed->bmAttributes);
+       uint32_t mps = UGETW(ed->wMaxPacketSize);
+       uint32_t maxb = 0;
+       int speed = pipe->up_dev->ud_speed;
+       uint32_t ival = ed->bInterval;
+
+       cp[0] = htole32(
+           XHCI_EPCTX_0_EPSTATE_SET(0) |
+           XHCI_EPCTX_0_MULT_SET(0) |  /* always 0 except SS iscoh */
+           XHCI_EPCTX_0_MAXP_STREAMS_SET(0) |
+           XHCI_EPCTX_0_LSA_SET(0) |
+           XHCI_EPCTX_0_MAX_ESIT_PAYLOAD_HI_SET(0)
+           );
+       cp[1] = htole32(
+           XHCI_EPCTX_1_EPTYPE_SET(xhci_ep_get_type(ed)) |
+           XHCI_EPCTX_1_HID_SET(0) |
+           XHCI_EPCTX_1_MAXB_SET(0)
+           );
+       if (xfertype != UE_ISOCHRONOUS)
+               cp[1] |= htole32(XHCI_EPCTX_1_CERR_SET(3));
+
+       /* 6.2.3.4,  4.8.2.4 */
+       if (USB_IS_SS(speed)) {
+               /* UBS 3.1  9.6.6 */
+               cp[1] |= htole32(XHCI_EPCTX_1_MAXP_SIZE_SET(mps));
+               /* UBS 3.1  9.6.7 */
+               maxb = xhci_get_maxburst(pipe);
+               cp[1] |= htole32(XHCI_EPCTX_1_MAXB_SET(maxb));
+       } else {
+               /* UBS 2.0  9.6.6 */
+               cp[1] |= htole32(XHCI_EPCTX_1_MAXP_SIZE_SET(UE_GET_SIZE(mps)));
+
+               /* 6.2.3.4 */
+               if (speed == USB_SPEED_HIGH &&
+                  (xfertype == UE_ISOCHRONOUS || xfertype == UE_INTERRUPT)) {
+                       maxb = UE_GET_TRANS(mps);
+               } else {
+                       /* LS/FS or HS CTRL or HS BULK */
+                       maxb = 0;
+               }
+               cp[1] |= htole32(XHCI_EPCTX_1_MAXB_SET(maxb));
+       }
+
+       if (xfertype == UE_CONTROL)
+               cp[4] = htole32(XHCI_EPCTX_4_AVG_TRB_LEN_SET(8)); /* 6.2.3 */
+       else if (USB_IS_SS(speed))
+               cp[4] = htole32(XHCI_EPCTX_4_AVG_TRB_LEN_SET(mps));
+       else
+               cp[4] = htole32(XHCI_EPCTX_4_AVG_TRB_LEN_SET(UE_GET_SIZE(mps)));
+
+       switch (xfertype) {
+       case UE_CONTROL:
+               break;
+       case UE_BULK:
+               /* XXX Set MaxPStreams, HID, and LSA if streams enabled */
+               break;
+       case UE_INTERRUPT:
+               if (pipe->up_interval != USBD_DEFAULT_INTERVAL)
+                       ival = pipe->up_interval;
+
+               ival = xhci_bival2ival(ival, speed);
+               cp[0] |= htole32(XHCI_EPCTX_0_IVAL_SET(ival));
+               break;
+       case UE_ISOCHRONOUS:
+               if (pipe->up_interval != USBD_DEFAULT_INTERVAL)
+                       ival = pipe->up_interval;
+
+               /* xHCI 6.2.3.6 Table 65, USB 2.0 9.6.6 */
+               if (speed == USB_SPEED_FULL)
+                       ival += 3; /* 1ms -> 125us */
+               ival--;
+               cp[0] |= htole32(XHCI_EPCTX_0_IVAL_SET(ival));
+
+               if (USB_IS_SS(speed)) {
+                       /* XXX if LEC = 1, set ESIT instead */
+                       cp[0] |= htole32(XHCI_EPCTX_0_MULT_SET(0));
+               }
+               break;
+       default:
+               break;
+       }
+       *(uint64_t *)(&cp[2]) = htole64(
+           xhci_ring_trbp(&xs->xs_ep[dci].xe_tr, 0) |
+           XHCI_EPCTX_2_DCS_SET(1));
+}
+
+/*
+ * Construct input contexts and issue TRB
  */
 static usbd_status



Home | Main Index | Thread Index | Old Index