The branch main has been updated by thj:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=405cfeef615f5493b49b6ab4619fa29dfe37fd7d

commit 405cfeef615f5493b49b6ab4619fa29dfe37fd7d
Author:     Tom Jones <t...@freebsd.org>
AuthorDate: 2025-07-14 08:07:20 +0000
Commit:     Tom Jones <t...@freebsd.org>
CommitDate: 2025-09-02 09:37:08 +0000

    xhci: Parse and print extended capabilities
    
    Parse out and display xhci controller extended capabilities. This gives
    us a mechanism to pick these up when the controller attaches. The print
    helps users and developer know the availability of features in the wild.
    
    This change will let developers know from dmesg that a controller
    supports USB debugging.
    
    Reviewed by:    aokblast
    Sponsored by:   The FreeBSD Foundation
    Differential Revision: https://reviews.freebsd.org/D51255
---
 sys/dev/usb/controller/xhci.c    | 85 ++++++++++++++++++++++++++++++++++++++++
 sys/dev/usb/controller/xhcireg.h |  5 +++
 2 files changed, 90 insertions(+)

diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c
index 5be592512196..788b2b718062 100644
--- a/sys/dev/usb/controller/xhci.c
+++ b/sys/dev/usb/controller/xhci.c
@@ -156,6 +156,7 @@ struct xhci_std_temp {
 
 static void    xhci_do_poll(struct usb_bus *);
 static void    xhci_device_done(struct usb_xfer *, usb_error_t);
+static void    xhci_get_xecp(struct xhci_softc *);
 static void    xhci_root_intr(struct xhci_softc *);
 static void    xhci_free_device_ext(struct usb_device *);
 static struct xhci_endpoint_ext *xhci_get_endpoint_ext(struct usb_device *,
@@ -566,6 +567,8 @@ xhci_init(struct xhci_softc *sc, device_t self, uint8_t 
dma32)
        device_printf(self, "%d bytes context size, %d-bit DMA\n",
            sc->sc_ctx_is_64_byte ? 64 : 32, (int)sc->sc_bus.dma_bits);
 
+       xhci_get_xecp(sc);
+
        /* enable 64Kbyte control endpoint quirk */
        sc->sc_bus.control_ep_quirk = (xhcictlquirk ? 1 : 0);
 
@@ -653,6 +656,88 @@ xhci_uninit(struct xhci_softc *sc)
        sx_destroy(&sc->sc_cmd_sx);
 }
 
+static void
+xhci_get_xecp(struct xhci_softc *sc)
+{
+
+       uint32_t hccp1;
+       uint32_t eec;
+       uint32_t eecp;
+       bool first = true;
+
+       hccp1 = XREAD4(sc, capa, XHCI_HCSPARAMS0);
+
+       if (XHCI_HCS0_XECP(hccp1) == 0)  {
+               device_printf(sc->sc_bus.parent,
+                   "xECP: no capabilities found\n");
+               return;
+       }
+
+       /*
+        * Parse the xECP Capabilities table and print known caps.
+        * Implemented, vendor and reserved xECP Capabilities values are
+        * documented in Table 7.2 of eXtensible Host Controller Interface for
+        * Universal Serial Bus (xHCI) Rev 1.2b 2023.
+        */
+       device_printf(sc->sc_bus.parent, "xECP capabilities <");
+
+       eec = -1;
+       for (eecp = XHCI_HCS0_XECP(hccp1) << 2;
+            eecp != 0 && XHCI_XECP_NEXT(eec) != 0;
+            eecp += XHCI_XECP_NEXT(eec) << 2) {
+               eec = XREAD4(sc, capa, eecp);
+
+               uint8_t xecpid = XHCI_XECP_ID(eec);
+
+               if ((xecpid >= 11 && xecpid <= 16) ||
+                   (xecpid >= 19 && xecpid <= 191)) {
+                       if (!first)
+                               printf(",");
+                       printf("RES(%x)", xecpid);
+               } else if (xecpid > 191) {
+                       if (!first)
+                               printf(",");
+                       printf("VEND(%x)", xecpid);
+               } else {
+                       if (!first)
+                               printf(",");
+                       switch (xecpid)
+                       {
+                       case XHCI_ID_USB_LEGACY:
+                               printf("LEGACY");
+                               break;
+                       case XHCI_ID_PROTOCOLS:
+                               printf("PROTO");
+                               break;
+                       case XHCI_ID_POWER_MGMT:
+                               printf("POWER");
+                               break;
+                       case XHCI_ID_VIRTUALIZATION:
+                               printf("VIRT");
+                               break;
+                       case XHCI_ID_MSG_IRQ:
+                               printf("MSG IRQ");
+                               break;
+                       case XHCI_ID_USB_LOCAL_MEM:
+                               printf("LOCAL MEM");
+                               break;
+                       case XHCI_ID_USB_DEBUG:
+                               printf("DEBUG");
+                               break;
+                       case XHCI_ID_EXT_MSI:
+                               printf("EXT MSI");
+                               break;
+                       case XHCI_ID_USB3_TUN:
+                               printf("TUN");
+                               break;
+
+                       }
+               }
+               first = false;
+       }
+       printf(">\n");
+}
+
 static void
 xhci_set_hw_power_sleep(struct usb_bus *bus, uint32_t state)
 {
diff --git a/sys/dev/usb/controller/xhcireg.h b/sys/dev/usb/controller/xhcireg.h
index 9d0b6e2f4b4b..821897155544 100644
--- a/sys/dev/usb/controller/xhcireg.h
+++ b/sys/dev/usb/controller/xhcireg.h
@@ -205,6 +205,11 @@
 #define        XHCI_ID_VIRTUALIZATION  0x0004
 #define        XHCI_ID_MSG_IRQ         0x0005
 #define        XHCI_ID_USB_LOCAL_MEM   0x0006
+/* values 7-9 are reserved */
+#define        XHCI_ID_USB_DEBUG       0x000a
+/* values 11-16 are reserved */
+#define        XHCI_ID_EXT_MSI         0x0011
+#define        XHCI_ID_USB3_TUN        0x0012
 
 /* XHCI register R/W wrappers */
 #define        XREAD1(sc, what, a) \

Reply via email to