+/**\r
+ Calculate the offset of the xHCI Supported Protocol Capability.\r
+\r
+ @param Xhc The XHCI Instance.\r
+ @param MajorVersion The USB Major Version in xHCI Support Protocol Capability Field\r
+\r
+ @return The offset of xHCI Supported Protocol capability register.\r
+\r
+**/\r
+UINT32\r
+XhcGetSupportedProtocolCapabilityAddr (\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
+ IN UINT8 MajorVersion\r
+ )\r
+{\r
+ UINT32 ExtCapOffset;\r
+ UINT8 NextExtCapReg;\r
+ UINT32 Data;\r
+ UINT32 NameString;\r
+ XHC_SUPPORTED_PROTOCOL_DW0 UsbSupportDw0;\r
+\r
+ if (Xhc == NULL) {\r
+ return 0;\r
+ }\r
+\r
+ ExtCapOffset = 0;\r
+\r
+ do {\r
+ //\r
+ // Check if the extended capability register's capability id is USB Legacy Support.\r
+ //\r
+ Data = XhcReadExtCapReg (Xhc, ExtCapOffset);\r
+ UsbSupportDw0.Dword = Data;\r
+ if ((Data & 0xFF) == XHC_CAP_USB_SUPPORTED_PROTOCOL) {\r
+ if (UsbSupportDw0.Data.RevMajor == MajorVersion) {\r
+ NameString = XhcReadExtCapReg (Xhc, ExtCapOffset + XHC_SUPPORTED_PROTOCOL_NAME_STRING_OFFSET);\r
+ if (NameString == XHC_SUPPORTED_PROTOCOL_NAME_STRING_VALUE) {\r
+ //\r
+ // Ensure Name String field is xHCI supported protocols in xHCI Supported Protocol Capability Offset 04h\r
+ //\r
+ return ExtCapOffset;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // If not, then traverse all of the ext capability registers till finding out it.\r
+ //\r
+ NextExtCapReg = (UINT8)((Data >> 8) & 0xFF);\r
+ ExtCapOffset += (NextExtCapReg << 2);\r
+ } while (NextExtCapReg != 0);\r
+\r
+ return 0xFFFFFFFF;\r
+}\r
+\r
+/**\r
+ Find PortSpeed value match Protocol Speed ID Value (PSIV).\r
+\r
+ @param Xhc The XHCI Instance.\r
+ @param ExtCapOffset The USB Major Version in xHCI Support Protocol Capability Field\r
+ @param PortSpeed The Port Speed Field in USB PortSc register\r
+\r
+ @return The Protocol Speed ID (PSI) from xHCI Supported Protocol capability register.\r
+\r
+**/\r
+UINT32\r
+XhciPsivGetPsid (\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
+ IN UINT32 ExtCapOffset,\r
+ IN UINT8 PortSpeed\r
+ )\r
+{\r
+ XHC_SUPPORTED_PROTOCOL_DW2 PortId;\r
+ XHC_SUPPORTED_PROTOCOL_PROTOCOL_SPEED_ID Reg;\r
+ UINT32 Count;\r
+\r
+ if ((Xhc == NULL) || (ExtCapOffset == 0xFFFFFFFF)) {\r
+ return 0;\r
+ }\r
+\r
+ //\r
+ // According to XHCI 1.1 spec November 2017,\r
+ // Section 7.2 xHCI Supported Protocol Capability\r
+ // 1. Get the PSIC(Protocol Speed ID Count) value.\r
+ // 2. The PSID register boundary should be Base address + PSIC * 0x04\r
+ //\r
+ PortId.Dword = XhcReadExtCapReg (Xhc, ExtCapOffset + XHC_SUPPORTED_PROTOCOL_DW2_OFFSET);\r
+\r
+ for (Count = 0; Count < PortId.Data.Psic; Count++) {\r
+ Reg.Dword = XhcReadExtCapReg (Xhc, ExtCapOffset + XHC_SUPPORTED_PROTOCOL_PSI_OFFSET + (Count << 2));\r
+ if (Reg.Data.Psiv == PortSpeed) {\r
+ return Reg.Dword;\r
+ }\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+/**\r
+ Find PortSpeed value match case in XHCI Supported Protocol Capability\r
+\r
+ @param Xhc The XHCI Instance.\r
+ @param PortSpeed The Port Speed Field in USB PortSc register\r
+\r
+ @return The USB Port Speed.\r
+\r
+**/\r
+UINT16\r
+XhcCheckUsbPortSpeedUsedPsic (\r
+ IN USB_XHCI_INSTANCE *Xhc,\r
+ IN UINT8 PortSpeed\r
+ )\r
+{\r
+ XHC_SUPPORTED_PROTOCOL_PROTOCOL_SPEED_ID SpField;\r
+ UINT16 UsbSpeedIdMap;\r
+\r
+ if (Xhc == NULL) {\r
+ return 0;\r
+ }\r
+\r
+ SpField.Dword = 0;\r
+ UsbSpeedIdMap = 0;\r
+\r
+ //\r
+ // Check xHCI Supported Protocol Capability, find the PSIV field to match\r
+ // PortSpeed definition when the Major Revision is 03h.\r
+ //\r
+ if (Xhc->Usb3SupOffset != 0xFFFFFFFF) {\r
+ SpField.Dword = XhciPsivGetPsid (Xhc, Xhc->Usb3SupOffset, PortSpeed);\r
+ if (SpField.Dword != 0) {\r
+ //\r
+ // Found the corresponding PORTSC value in PSIV field of USB3 offset.\r
+ //\r
+ UsbSpeedIdMap = USB_PORT_STAT_SUPER_SPEED;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Check xHCI Supported Protocol Capability, find the PSIV field to match\r
+ // PortSpeed definition when the Major Revision is 02h.\r
+ //\r
+ if ((UsbSpeedIdMap == 0) && (Xhc->Usb2SupOffset != 0xFFFFFFFF)) {\r
+ SpField.Dword = XhciPsivGetPsid (Xhc, Xhc->Usb2SupOffset, PortSpeed);\r
+ if (SpField.Dword != 0) {\r
+ //\r
+ // Found the corresponding PORTSC value in PSIV field of USB2 offset.\r
+ //\r
+ if (SpField.Data.Psie == 2) {\r
+ //\r
+ // According to XHCI 1.1 spec November 2017,\r
+ // Section 7.2.1 the Protocol Speed ID Exponent (PSIE) field definition,\r
+ // PSIE value shall be applied to Protocol Speed ID Mantissa when calculating, value 2 shall represent bit rate in Mb/s\r
+ //\r
+ if (SpField.Data.Psim == XHC_SUPPORTED_PROTOCOL_USB2_HIGH_SPEED_PSIM) {\r
+ //\r
+ // PSIM shows as default High-speed protocol, apply to High-speed mapping\r
+ //\r
+ UsbSpeedIdMap = USB_PORT_STAT_HIGH_SPEED;\r
+ }\r
+ } else if (SpField.Data.Psie == 1) {\r
+ //\r
+ // According to XHCI 1.1 spec November 2017,\r
+ // Section 7.2.1 the Protocol Speed ID Exponent (PSIE) field definition,\r
+ // PSIE value shall be applied to Protocol Speed ID Mantissa when calculating, value 1 shall represent bit rate in Kb/s\r
+ //\r
+ if (SpField.Data.Psim == XHC_SUPPORTED_PROTOCOL_USB2_LOW_SPEED_PSIM) {\r
+ //\r
+ // PSIM shows as default Low-speed protocol, apply to Low-speed mapping\r
+ //\r
+ UsbSpeedIdMap = USB_PORT_STAT_LOW_SPEED;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ return UsbSpeedIdMap;\r
+}\r
+\r