diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c index 8dd7a8fbb7..461b2cd9b5 100644 --- a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c +++ b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c @@ -405,7 +405,7 @@ XhcGetRootHubPortStatus ( // Section 7.2 xHCI Support Protocol Capability // if (PortSpeed > 0) { - PortStatus->PortStatus = XhcCheckUsbPortSpeedUsedPsic (Xhc, PortSpeed); + PortStatus->PortStatus = XhcCheckUsbPortSpeedUsedPsic (Xhc, PortSpeed, PortNumber); // If no match found in ext cap reg, fall back to PORTSC if (PortStatus->PortStatus == 0) { // diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c b/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c index 2b4a4b2444..5700fc5fb8 100644 --- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c +++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c @@ -636,6 +636,7 @@ XhcGetSupportedProtocolCapabilityAddr ( @param Xhc The XHCI Instance. @param ExtCapOffset The USB Major Version in xHCI Support Protocol Capability Field @param PortSpeed The Port Speed Field in USB PortSc register + @param PortNumber The Port Number (0-indexed) @return The Protocol Speed ID (PSI) from xHCI Supported Protocol capability register. @@ -644,12 +645,15 @@ UINT32 XhciPsivGetPsid ( IN USB_XHCI_INSTANCE *Xhc, IN UINT32 ExtCapOffset, - IN UINT8 PortSpeed + IN UINT8 PortSpeed, + IN UINT8 PortNumber ) { XHC_SUPPORTED_PROTOCOL_DW2 PortId; XHC_SUPPORTED_PROTOCOL_PROTOCOL_SPEED_ID Reg; UINT32 Count; + UINT32 MinPortIndex; + UINT32 MaxPortIndex; if ((Xhc == NULL) || (ExtCapOffset == 0xFFFFFFFF)) { return 0; @@ -663,6 +667,23 @@ XhciPsivGetPsid ( // PortId.Dword = XhcReadExtCapReg (Xhc, ExtCapOffset + XHC_SUPPORTED_PROTOCOL_DW2_OFFSET); + // + // According to XHCI 1.1 spec November 2017, valid values + // for CompPortOffset are 1 to CompPortCount - 1. + // + // PortNumber is zero-indexed, so subtract 1. + // + if ((PortId.Data.CompPortOffset == 0) || (PortId.Data.CompPortCount == 0)) { + return 0; + } + + MinPortIndex = PortId.Data.CompPortOffset - 1; + MaxPortIndex = MinPortIndex + PortId.Data.CompPortCount - 1; + + if ((PortNumber < MinPortIndex) || (PortNumber > MaxPortIndex)) { + return 0; + } + for (Count = 0; Count < PortId.Data.Psic; Count++) { Reg.Dword = XhcReadExtCapReg (Xhc, ExtCapOffset + XHC_SUPPORTED_PROTOCOL_PSI_OFFSET + (Count << 2)); if (Reg.Data.Psiv == PortSpeed) { @@ -676,8 +697,9 @@ XhciPsivGetPsid ( /** Find PortSpeed value match case in XHCI Supported Protocol Capability - @param Xhc The XHCI Instance. - @param PortSpeed The Port Speed Field in USB PortSc register + @param Xhc The XHCI Instance. + @param PortSpeed The Port Speed Field in USB PortSc register + @param PortNumber The Port Number (0-indexed) @return The USB Port Speed. @@ -685,7 +707,8 @@ XhciPsivGetPsid ( UINT16 XhcCheckUsbPortSpeedUsedPsic ( IN USB_XHCI_INSTANCE *Xhc, - IN UINT8 PortSpeed + IN UINT8 PortSpeed, + IN UINT8 PortNumber ) { XHC_SUPPORTED_PROTOCOL_PROTOCOL_SPEED_ID SpField; @@ -703,7 +726,7 @@ XhcCheckUsbPortSpeedUsedPsic ( // PortSpeed definition when the Major Revision is 03h. // if (Xhc->Usb3SupOffset != 0xFFFFFFFF) { - SpField.Dword = XhciPsivGetPsid (Xhc, Xhc->Usb3SupOffset, PortSpeed); + SpField.Dword = XhciPsivGetPsid (Xhc, Xhc->Usb3SupOffset, PortSpeed, PortNumber); if (SpField.Dword != 0) { // // Found the corresponding PORTSC value in PSIV field of USB3 offset. @@ -717,7 +740,7 @@ XhcCheckUsbPortSpeedUsedPsic ( // PortSpeed definition when the Major Revision is 02h. // if ((UsbSpeedIdMap == 0) && (Xhc->Usb2SupOffset != 0xFFFFFFFF)) { - SpField.Dword = XhciPsivGetPsid (Xhc, Xhc->Usb2SupOffset, PortSpeed); + SpField.Dword = XhciPsivGetPsid (Xhc, Xhc->Usb2SupOffset, PortSpeed, PortNumber); if (SpField.Dword != 0) { // // Found the corresponding PORTSC value in PSIV field of USB2 offset. diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.h b/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.h index 5fe2ba4f0e..63bcae8974 100644 --- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.h +++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.h @@ -621,10 +621,11 @@ XhcGetSupportedProtocolCapabilityAddr ( ); /** - Find SpeedField value match with Port Speed ID value. + Find PortSpeed value match case in XHCI Supported Protocol Capability - @param Xhc The XHCI Instance. - @param Speed The Port Speed filed in USB PortSc register + @param Xhc The XHCI Instance. + @param PortSpeed The Port Speed Field in USB PortSc register + @param PortNumber The Port Number (0-indexed) @return The USB Port Speed. @@ -632,7 +633,8 @@ XhcGetSupportedProtocolCapabilityAddr ( UINT16 XhcCheckUsbPortSpeedUsedPsic ( IN USB_XHCI_INSTANCE *Xhc, - IN UINT8 Speed + IN UINT8 PortSpeed, + IN UINT8 PortNumber ); #endif