From nobody Mon Nov 02 03:02:54 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4jHxMy6mY2z6yVj0 for ; Mon, 02 Nov 2026 03:02:54 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 4jHxMy4ss2z4SgC for ; Mon, 02 Nov 2026 03:02:54 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1793588574; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=o4CjmKVqqT1JN5qn5BV2UIW8h6AIMWMTT/lJ4ErRIMw=; b=FR/pMJF3eKe/UHGNQS5JWibDnafLO2n0WLvIHiWrf0GliaMSSc3Pf1XgEUUcTPnrfXnvn2 hrFvbAyVaUaENNpVbwm2CKO1AiuRtuMhOfUTl0IHHL2UE/B/R8luyE5YCFqvUtqqUSlQUO 1VvoSENXNSpnNPRtnB/FseHyxN33vE0VucTuAJjk5QaLqjRrdsLmRVf6grEXjeALqNH/uC pQy8OM3FrbwUwIqNldbUIiysKYoehszAVDYcmWzdTdvByJ3odE0PvpP/KgfTAwnszDWDcn v85sZ1w0iaPC9q6ZJ2HAh6czrgjyv9UkyDoCjrhI+QX5NuwvtwH0baVeCgqslw== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1793588574; b=GnjwPXS5YdLtoGjTAOL6/vKFfZLgojwY4X9iTrNjNOG+yr9xi3dohfMM/QbbUlYuTtRU++ ka18bNRyzq9CjaxCNL61v8vxEhiAvu0fnZhjL3Kd9+nu3A9HNo6zi1rkX47VaBJ+ey04Lc 7gYb6XFqxaOim0ddmDJFy0ilB72IIv7HDvyq/iAMv92ZHnUdmmE7NUAIokt9/n5JR4ccK0 W5cOsjSWtMrENIeDi9E9G34BoL1zeVWDm0VVmbewDvKoDCZMOnqehnMZTblj62diOdbImw kZGhJ8PWL5T8MC/GycwD02HEtJDbXz3OGbH+nNgt06GcyQrS5IxHVNAhchCmsw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1793588574; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=o4CjmKVqqT1JN5qn5BV2UIW8h6AIMWMTT/lJ4ErRIMw=; b=F5tS1QXtM/+t+WJO1NrDskJZcNFtG/dDQoyCmMbHL9heRJ8vhn9kBDcTEH/216buPN+9MI x5PGnYFjSfGieUKumiwkHlVEdExyLrNUdzGE3wcNF4kgKP24CxPsnqomrLDbi5++ijZ840 8Q32GApW2C/Xtnz7sOINjzY8SCkgn/1PLmW8KJBaz8LD32M8L1ppPvwCnTtuFb4wpvpUkv K5Fbm6wkzXZcu9x7PgWHzG1cpBrtuqmH1Vn3CmGrFJzs6hbAbl6jZEvz9LRyFKDpafUSuJ WlOhfY4jHdsaI93zzcJS+bWeeQIkNzfJfy1r/Pvk4NPVPd5AZ7wguYRPHUJ+MQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4jHxMy4X03zRPK for ; Mon, 02 Nov 2026 03:02:54 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3b6a3 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 02 Nov 2026 03:02:54 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: ShengYi Hung Subject: git: 20b19982545e - main - usb: support SSP and SSPx2 xHCI List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: Commit messages for all branches of the src repository List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: aokblast X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 20b19982545eb96160a20d0224f4b074f5fcb9af Auto-Submitted: auto-generated Date: Mon, 02 Nov 2026 03:02:54 +0000 Message-Id: <6ae7fd5e.3b6a3.38ca4f83@gitrepo.freebsd.org> The branch main has been updated by aokblast: URL: https://cgit.FreeBSD.org/src/commit/?id=20b19982545eb96160a20d0224f4b074f5fcb9af commit 20b19982545eb96160a20d0224f4b074f5fcb9af Author: ShengYi Hung AuthorDate: 2025-09-01 14:54:11 +0000 Commit: ShengYi Hung CommitDate: 2026-11-02 03:02:11 +0000 usb: support SSP and SSPx2 xHCI Only the default PSI IDs are supported, other controllers fall back to USB 3.0. Record the speed IDs the controller has: the root hub BOS lists those, and a link without one uses the closest lower ID. Per xHCI 6.2.2, take the parent hub slot ID and port number of SS and SSP devices from the closest higher-rank hub. Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D52347 --- sys/dev/usb/controller/xhci.c | 305 ++++++++++++++++++++++++++++++++++----- sys/dev/usb/controller/xhci.h | 14 ++ sys/dev/usb/controller/xhcireg.h | 12 ++ 3 files changed, 294 insertions(+), 37 deletions(-) diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c index acc6eee525b0..3f3ab299647b 100644 --- a/sys/dev/usb/controller/xhci.c +++ b/sys/dev/usb/controller/xhci.c @@ -485,6 +485,60 @@ xhci_reset_controller(struct xhci_softc *sc) return (0); } +static bool +xhci_parse_protocol(struct xhci_softc *sc, uint32_t eecp, uint32_t eec) +{ + enum usb_revision rev; + uint32_t val; + uint16_t psiv; + uint8_t minor; + uint8_t psic; + uint8_t i; + + minor = XHCI_XECP_MINOR(eec); + psic = XHCI_XECP_PSIC_GET(XREAD4(sc, capa, eecp + 0x08)); + psiv = XHCI_PSIV_BIT(XHCI_PS_SPEED_SS); + rev = USB_REV_3_0; + + if (psic == 0) { + /* + * The port revision only tells which speeds the port may + * have, so be careful about what we claim for the bus. + */ + if (minor >= 0x10) { + psiv |= XHCI_PSIV_BIT(XHCI_PS_SPEED_SS_PLUS_GEN2); + rev = USB_REV_3_1; + } + if (minor >= 0x20) { + psiv |= XHCI_PSIV_BIT(XHCI_PS_SPEED_SS_PLUS_GEN1_x2) | + XHCI_PSIV_BIT(XHCI_PS_SPEED_SS_PLUS_GEN2_x2); + } + } + + for (i = 0; i != psic; i++) { + val = XREAD4(sc, capa, eecp + 0x10 + i * 4); + val &= ~(XHCI_XECP_PSI_RSVD | XHCI_XECP_PSI_LP); + switch (val) { + case 0x00050134: /* 4: 5 Gbps Gen1x1 */ + break; + case 0x000a0135: /* 5: 10 Gbps Gen2x1 */ + case 0x000a0136: /* 6: 10 Gbps Gen1x2 (5G/lane x 2) */ + rev = MAX(rev, USB_REV_3_1); + break; + case 0x00140137: /* 7: 20 Gbps Gen2x2 (10G/lane x 2) */ + rev = USB_REV_3_2; + break; + default: + return (false); + } + psiv |= XHCI_PSIV_BIT(XHCI_XECP_PSIV_GET(val)); + } + + sc->sc_ss_psiv |= psiv; + sc->sc_bus.usbrev = MAX(sc->sc_bus.usbrev, rev); + return (true); +} + usb_error_t xhci_init(struct xhci_softc *sc, device_t self, uint8_t dma32) { @@ -497,6 +551,7 @@ xhci_init(struct xhci_softc *sc, device_t self, uint8_t dma32) /* set the bus revision */ sc->sc_bus.usbrev = USB_REV_3_0; + sc->sc_ss_psiv = XHCI_PSIV_BIT(XHCI_PS_SPEED_SS); /* set up the bus struct */ sc->sc_bus.methods = &xhci_bus_methods; @@ -642,6 +697,7 @@ xhci_get_xecp(struct xhci_softc *sc) uint32_t eec; uint32_t eecp; bool first = true; + bool default_psi = true; hccp1 = XREAD4(sc, capa, XHCI_HCCPARAMS1); @@ -686,6 +742,9 @@ xhci_get_xecp(struct xhci_softc *sc) break; case XHCI_ID_PROTOCOLS: printf("PROTO"); + if (XHCI_XECP_MAJOR(eec) == 0x03 && + !xhci_parse_protocol(sc, eecp, eec)) + default_psi = false; break; case XHCI_ID_POWER_MGMT: printf("POWER"); @@ -714,6 +773,13 @@ xhci_get_xecp(struct xhci_softc *sc) first = false; } printf(">\n"); + + if (!default_psi) { + device_printf(sc->sc_bus.parent, + "xECP: not support non-default mapping, fallback to usb 3.0\n"); + sc->sc_bus.usbrev = USB_REV_3_0; + sc->sc_ss_psiv = XHCI_PSIV_BIT(XHCI_PS_SPEED_SS); + } } static void @@ -2531,6 +2597,9 @@ xhci_configure_endpoint(struct usb_device *udev, switch (udev->speed) { case USB_SPEED_SUPER: + case USB_SPEED_SUPER_PLUS: + case USB_SPEED_SUPER_PLUS_X2: + case USB_SPEED_SUPER_PLUS_GEN2_X2: if (mult > 3) mult = 3; temp |= XHCI_EPCTX_0_MULT_SET(mult - 1); @@ -2650,6 +2719,67 @@ xhci_configure_endpoint_by_xfer(struct usb_xfer *xfer) xfer->max_frame_size, xfer->endpoint->ep_mode)); } +static uint8_t +xhci_ss_psiv(struct xhci_softc *sc, enum usb_dev_speed speed) +{ + switch (speed) { + case USB_SPEED_SUPER_PLUS_GEN2_X2: + if (sc->sc_ss_psiv & + XHCI_PSIV_BIT(XHCI_PS_SPEED_SS_PLUS_GEN2_x2)) + return (XHCI_PS_SPEED_SS_PLUS_GEN2_x2); + /* FALLTHROUGH */ + case USB_SPEED_SUPER_PLUS: + if (sc->sc_ss_psiv & XHCI_PSIV_BIT(XHCI_PS_SPEED_SS_PLUS_GEN2)) + return (XHCI_PS_SPEED_SS_PLUS_GEN2); + /* FALLTHROUGH */ + case USB_SPEED_SUPER_PLUS_X2: + if (sc->sc_ss_psiv & + XHCI_PSIV_BIT(XHCI_PS_SPEED_SS_PLUS_GEN1_x2)) + return (XHCI_PS_SPEED_SS_PLUS_GEN1_x2); + /* FALLTHROUGH */ + default: + return (XHCI_PS_SPEED_SS); + } +} + +static enum usb_dev_speed +xhci_ss_highest(struct xhci_softc *sc) +{ + switch (xhci_ss_psiv(sc, USB_SPEED_SUPER_PLUS_GEN2_X2)) { + case XHCI_PS_SPEED_SS_PLUS_GEN2_x2: + return (USB_SPEED_SUPER_PLUS_GEN2_X2); + case XHCI_PS_SPEED_SS_PLUS_GEN2: + return (USB_SPEED_SUPER_PLUS); + case XHCI_PS_SPEED_SS_PLUS_GEN1_x2: + return (USB_SPEED_SUPER_PLUS_X2); + default: + return (USB_SPEED_SUPER); + } +} + +static struct usb_device * +xhci_ss_parent_hub(struct xhci_softc *sc, struct usb_device *udev, + uint8_t *port_no) +{ + struct usb_device *adev = udev; + struct usb_device *hubdev = udev->parent_hub; + + if (udev->speed >= xhci_ss_highest(sc)) + return (NULL); + + for (; hubdev != NULL && hubdev->parent_hub != NULL; + hubdev = hubdev->parent_hub) { + if (hubdev->hub->ports[adev->port_index].ss_speed_unknown) + return (NULL); + if (hubdev->speed > udev->speed) { + *port_no = adev->port_no; + return (hubdev); + } + adev = hubdev; + } + return (NULL); +} + static usb_error_t xhci_configure_device(struct usb_device *udev) { @@ -2664,6 +2794,7 @@ xhci_configure_device(struct usb_device *udev) uint8_t is_hub; uint8_t index; uint8_t depth; + uint8_t port_no; index = udev->controller_slot_id; @@ -2737,13 +2868,12 @@ xhci_configure_device(struct usb_device *udev) } break; default: - temp |= XHCI_SCTX_0_SPEED_SET(4); + temp |= XHCI_SCTX_0_SPEED_SET(xhci_ss_psiv(sc, udev->speed)); break; } is_hub = sc->sc_hw.devs[index].nports != 0 && - (udev->speed == USB_SPEED_SUPER || - udev->speed == USB_SPEED_HIGH); + (udev->speed >= USB_SPEED_HIGH); if (is_hub) temp |= XHCI_SCTX_0_HUB_SET(1); @@ -2779,6 +2909,23 @@ xhci_configure_device(struct usb_device *udev) udev->hs_port_no); } break; + case USB_SPEED_SUPER: + case USB_SPEED_SUPER_PLUS: + case USB_SPEED_SUPER_PLUS_X2: + case USB_SPEED_SUPER_PLUS_GEN2_X2: + /* + * Per xHCI 1.2 ยง6.2.2 the parent hub slot ID and port number + * of a SS/SSP device identify the hub which isolates it, that + * is the closest higher rank hub. They must be zero if there + * is none. The root hub has no slot and never qualifies. + */ + hubdev = xhci_ss_parent_hub(sc, udev, &port_no); + if (hubdev != NULL) { + temp |= XHCI_SCTX_2_TT_HUB_SID_SET( + hubdev->controller_slot_id); + temp |= XHCI_SCTX_2_TT_PORT_NUM_SET(port_no); + } + break; default: break; } @@ -3277,39 +3424,95 @@ struct usb_device_descriptor xhci_devd = .bNumConfigurations = 1, /* # of configurations */ }; +/* The capabilities every root HUB BOS descriptor starts with */ +#define XHCI_BOSD_COMMON(desc, ncaps) \ + .bosd = { \ + .bLength = sizeof(desc.bosd), \ + .bDescriptorType = UDESC_BOS, \ + HSETW(.wTotalLength, sizeof(desc)), \ + .bNumDeviceCaps = (ncaps), \ + }, \ + .usb2extd = { \ + .bLength = sizeof(desc.usb2extd), \ + .bDescriptorType = UDESC_DEVICE_CAPABILITY, \ + .bDevCapabilityType = 2, \ + .bmAttributes[0] = 2, \ + }, \ + .usbdcd = { \ + .bLength = sizeof(desc.usbdcd), \ + .bDescriptorType = UDESC_DEVICE_CAPABILITY, \ + .bDevCapabilityType = 3, \ + .bmAttributes = 0, /* XXX */ \ + HSETW(.wSpeedsSupported, 0x000C), \ + .bFunctionalitySupport = 8, \ + .bU1DevExitLat = 255, /* dummy - not used */ \ + .wU2DevExitLat = { 0x00, 0x08 }, \ + }, \ + .cidd = { \ + .bLength = sizeof(desc.cidd), \ + .bDescriptorType = UDESC_DEVICE_CAPABILITY, \ + .bDevCapabilityType = 4, \ + .bReserved = 0, \ + .bContainerID = 0, /* XXX */ \ + } + static const -struct xhci_bos_desc xhci_bosd = { - .bosd = { - .bLength = sizeof(xhci_bosd.bosd), - .bDescriptorType = UDESC_BOS, - HSETW(.wTotalLength, sizeof(xhci_bosd)), - .bNumDeviceCaps = 3, - }, - .usb2extd = { - .bLength = sizeof(xhci_bosd.usb2extd), - .bDescriptorType = 1, - .bDevCapabilityType = 2, - .bmAttributes[0] = 2, - }, - .usbdcd = { - .bLength = sizeof(xhci_bosd.usbdcd), +struct xhci_bos_desc xhci_30_bosd = { + XHCI_BOSD_COMMON(xhci_30_bosd, 3), +}; + +static const +struct xhci_ssp_bos_desc xhci_ssp_bosd = { + XHCI_BOSD_COMMON(xhci_ssp_bosd, 4), + .ssplus = { .bDescriptorType = UDESC_DEVICE_CAPABILITY, - .bDevCapabilityType = 3, - .bmAttributes = 0, /* XXX */ - HSETW(.wSpeedsSupported, 0x000C), - .bFunctionalitySupport = 8, - .bU1DevExitLat = 255, /* dummy - not used */ - .wU2DevExitLat = { 0x00, 0x08 }, - }, - .cidd = { - .bLength = sizeof(xhci_bosd.cidd), - .bDescriptorType = 1, - .bDevCapabilityType = 4, + .bDevCapabilityType = USB_DEVCAP_SUPERSPEED_PLUS, .bReserved = 0, - .bContainerID = 0, /* XXX */ + .wFunctionalitySupport = {0x04, 0x11}, /* SSID 4, Rx: 1, Tx: 1 */ + .wReserved = {0}, + }, + .caps = { + /* The speed is per lane */ + [0] = {0x34, 0x00, 0x05, 0x00}, /* 4: 5 Gbps Gen1x1, Rx */ + [1] = {0xb4, 0x00, 0x05, 0x00}, /* 4: 5 Gbps Gen1x1, Tx */ + [2] = {0x35, 0x40, 0x0a, 0x00}, /* 5: 10 Gbps Gen2x1, Rx */ + [3] = {0xb5, 0x40, 0x0a, 0x00}, /* 5: 10 Gbps Gen2x1, Tx */ + [4] = {0x36, 0x40, 0x05, 0x00}, /* 6: 5 Gbps Gen1x2, Rx */ + [5] = {0xb6, 0x40, 0x05, 0x00}, /* 6: 5 Gbps Gen1x2, Tx */ + [6] = {0x37, 0x40, 0x0a, 0x00}, /* 7: 10 Gbps Gen2x2, Rx */ + [7] = {0xb7, 0x40, 0x0a, 0x00}, /* 7: 10 Gbps Gen2x2, Tx */ }, }; +static uint16_t +xhci_ssp_bos_build(struct xhci_softc *sc) +{ + struct xhci_ssp_bos_desc *bos = &sc->sc_hub_desc.ssp_bos; + uint16_t len; + uint8_t i; + uint8_t n; + + *bos = xhci_ssp_bosd; + + for (i = n = 0; i != nitems(bos->caps); i += 2) { + if ((sc->sc_ss_psiv & XHCI_PSIV_BIT(USB_DEVCAP_SSPLUS_SSID_GET( + UGETDW(xhci_ssp_bosd.caps[i])))) == 0) + continue; + memcpy(bos->caps[n], xhci_ssp_bosd.caps[i], + 2 * sizeof(bos->caps[0])); + n += 2; + } + + len = offsetof(struct xhci_ssp_bos_desc, caps) + + n * sizeof(bos->caps[0]); + USETW(bos->bosd.wTotalLength, len); + bos->ssplus.bLength = sizeof(bos->ssplus) + n * sizeof(bos->caps[0]); + USETDW(bos->ssplus.bmAttributes, USB_DEVCAP_SSPLUS_SSAC_SET(n - 1) | + USB_DEVCAP_SSPLUS_SSIC_SET((n / 2) - 1)); + + return (len); +} + static const struct xhci_config_desc xhci_confd = { .confd = { @@ -3404,8 +3607,18 @@ xhci_roothub_exec(struct usb_device *udev, err = USB_ERR_IOERROR; goto done; } + sc->sc_hub_desc.devd = xhci_devd; + switch (sc->sc_bus.usbrev) { + case USB_REV_3_2: + USETW(sc->sc_hub_desc.devd.bcdUSB, 0x0320); + break; + case USB_REV_3_1: + USETW(sc->sc_hub_desc.devd.bcdUSB, 0x0310); + break; + default: + break; + } len = sizeof(xhci_devd); - ptr = (const void *)&xhci_devd; break; case UDESC_BOS: @@ -3413,8 +3626,12 @@ xhci_roothub_exec(struct usb_device *udev, err = USB_ERR_IOERROR; goto done; } - len = sizeof(xhci_bosd); - ptr = (const void *)&xhci_bosd; + if (sc->sc_bus.usbrev < USB_REV_3_1) { + len = sizeof(xhci_30_bosd); + ptr = (const void *)&xhci_30_bosd; + } else { + len = xhci_ssp_bos_build(sc); + } break; case UDESC_CONFIG: @@ -3609,8 +3826,9 @@ xhci_roothub_exec(struct usb_device *udev, case C(UR_GET_STATUS, UT_READ_CLASS_OTHER): DPRINTFN(9, "UR_GET_STATUS i=%d\n", index); - if ((index < 1) || - (index > sc->sc_noport)) { + if ((index < 1) || (index > sc->sc_noport) || + (value != 0 && value != 2) || + (value == 2 && sc->sc_bus.usbrev < USB_REV_3_1)) { err = USB_ERR_IOERROR; goto done; } @@ -3650,6 +3868,18 @@ xhci_roothub_exec(struct usb_device *udev, #endif USETW(sc->sc_hub_desc.ps.wPortStatus, i); + if (value == 2) { + /* + * Only the default mapping gets here, where the speed + * ID tells the lane count, which is zero based. + */ + i = XHCI_PS_SPEED_GET(v); + j = (i == XHCI_PS_SPEED_SS_PLUS_GEN1_x2 || + i == XHCI_PS_SPEED_SS_PLUS_GEN2_x2) ? 1 : 0; + USETDW(sc->sc_hub_desc.ext_ps.dwExtPortStatus, + i | (i << 4) | (j << 8) | (j << 12)); + } + i = 0; if (v & XHCI_PS_CSC) i |= UPS_C_CONNECT_STATUS; @@ -3667,7 +3897,8 @@ xhci_roothub_exec(struct usb_device *udev, i |= UPS_C_PORT_CONFIG_ERROR; USETW(sc->sc_hub_desc.ps.wPortChange, i); - len = sizeof(sc->sc_hub_desc.ps); + len = (value == 2) ? sizeof(sc->sc_hub_desc.ext_ps) : + sizeof(sc->sc_hub_desc.ps); break; case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE): @@ -4441,7 +4672,7 @@ xhci_device_state_change(struct usb_device *udev) DPRINTF("\n"); if (usb_get_device_state(udev) == USB_STATE_CONFIGURED) { - err = uhub_query_info(udev, &sc->sc_hw.devs[index].nports, + err = uhub_query_info(udev, &sc->sc_hw.devs[index].nports, &sc->sc_hw.devs[index].tt); if (err != 0) sc->sc_hw.devs[index].nports = 0; diff --git a/sys/dev/usb/controller/xhci.h b/sys/dev/usb/controller/xhci.h index c2e6cde8ad77..9a84243eb8f5 100644 --- a/sys/dev/usb/controller/xhci.h +++ b/sys/dev/usb/controller/xhci.h @@ -478,10 +478,22 @@ struct xhci_bos_desc { struct usb_devcap_container_id_descriptor cidd; } __packed; +struct xhci_ssp_bos_desc { + struct usb_bos_descriptor bosd; + struct usb_devcap_usb2ext_descriptor usb2extd; + struct usb_devcap_ss_descriptor usbdcd; + struct usb_devcap_container_id_descriptor cidd; + struct usb_devcap_ss_plus_descriptor_header ssplus; + uDWord caps[8]; +} __packed; + union xhci_hub_desc { struct usb_status stat; struct usb_port_status ps; struct usb_hub_ss_descriptor hubd; + struct usb_ext_status ext_ps; + struct usb_device_descriptor devd; + struct xhci_ssp_bos_desc ssp_bos; uint8_t temp[128]; }; @@ -548,6 +560,8 @@ struct xhci_softc { uint8_t sc_command_ccs; /* number of XHCI device slots */ uint8_t sc_noslot; + /* Enhanced SuperSpeed speed IDs of the controller, see XHCI_PSIV_BIT */ + uint16_t sc_ss_psiv; /* number of ports on root HUB */ uint8_t sc_noport; /* root HUB device configuration */ diff --git a/sys/dev/usb/controller/xhcireg.h b/sys/dev/usb/controller/xhcireg.h index c4f62586a0d0..ac6c7393ab49 100644 --- a/sys/dev/usb/controller/xhcireg.h +++ b/sys/dev/usb/controller/xhcireg.h @@ -127,6 +127,9 @@ #define XHCI_PS_SPEED_LOW 0x2 /* Low Speed USB */ #define XHCI_PS_SPEED_HIGH 0x3 /* High Speed USB */ #define XHCI_PS_SPEED_SS 0x4 /* Super Speed USB */ +#define XHCI_PS_SPEED_SS_PLUS_GEN2 0x5 /* Super Speed Plus Gen2x1 */ +#define XHCI_PS_SPEED_SS_PLUS_GEN1_x2 0x6 /* Super Speed Plus Gen1x2 */ +#define XHCI_PS_SPEED_SS_PLUS_GEN2_x2 0x7 /* Super Speed Plus Gen2x2 */ #define XHCI_PS_PIC_GET(x) (((x) >> 14) & 0x3) /* RW - port indicator */ #define XHCI_PS_PIC_SET(x) (((x) & 0x3) << 14) /* RW - port indicator */ #define XHCI_PS_LWS 0x00010000 /* RW - port link state write strobe */ @@ -195,9 +198,18 @@ /* XHCI legacy support */ #define XHCI_XECP_ID(x) ((x) & 0xFF) #define XHCI_XECP_NEXT(x) (((x) >> 8) & 0xFF) +#define XHCI_XECP_MAJOR(x) (((x) >> 24) & 0xFF) +#define XHCI_XECP_MINOR(x) (((x) >> 16) & 0xFF) #define XHCI_XECP_BIOS_SEM 0x0002 #define XHCI_XECP_OS_SEM 0x0003 +/* Support protocol */ +#define XHCI_XECP_PSIC_GET(x) (((x) >> 28) & 0x0F) +#define XHCI_XECP_PSI_RSVD 0x00003E00 +#define XHCI_XECP_PSI_LP 0x0000C000 +#define XHCI_XECP_PSIV_GET(x) ((x) & 0x0F) +#define XHCI_PSIV_BIT(x) (1U << (x)) + /* XHCI capability ID's */ #define XHCI_ID_USB_LEGACY 0x0001 #define XHCI_ID_PROTOCOLS 0x0002