]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
MdeModulePkg/XhciDxe: Add access xHCI Extended Capabilities Pointer
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / XhciDxe / XhciReg.c
index 80be3311d49c1758117e6f32155e7d5bec1b4a44..2b4a4b2444e5a39f3e4255293c9ce154abc2da5e 100644 (file)
@@ -575,6 +575,184 @@ XhcGetCapabilityAddr (
   return 0xFFFFFFFF;\r
 }\r
 \r
+/**\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
 /**\r
   Whether the XHCI host controller is halted.\r
 \r