]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.c
MdeModulePkg/AtaAtapiPassThru: Revert patch to disable Bus Master
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciBusDxe / PciHotPlugSupport.c
index 257874b8b03ed43b7dfada351dac65263d53ceaa..73bcd32788d1c2ffb5a7f540e2df7b0693df8602 100644 (file)
@@ -300,7 +300,7 @@ IsSHPC (
   Offset = 0;\r
   Status = LocateCapabilityRegBlock (\r
             PciIoDevice,\r
-            EFI_PCI_CAPABILITY_ID_HOTPLUG,\r
+            EFI_PCI_CAPABILITY_ID_SHPC,\r
             &Offset,\r
             NULL\r
             );\r
@@ -316,6 +316,94 @@ IsSHPC (
   return FALSE;\r
 }\r
 \r
+/**\r
+  Check whether PciIoDevice supports PCIe hotplug.\r
+\r
+  This is equivalent to the following condition:\r
+  - the device is either a PCIe switch downstream port or a root port,\r
+  - and the device has the SlotImplemented bit set in its PCIe capability\r
+    register,\r
+  - and the device has the HotPlugCapable bit set in its slot capabilities\r
+    register.\r
+\r
+  @param[in] PciIoDevice  The device being checked.\r
+\r
+  @retval TRUE   PciIoDevice is a PCIe port that accepts a hotplugged device.\r
+  @retval FALSE  Otherwise.\r
+\r
+**/\r
+BOOLEAN\r
+SupportsPcieHotplug (\r
+  IN PCI_IO_DEVICE                      *PciIoDevice\r
+  )\r
+{\r
+  UINT32                       Offset;\r
+  EFI_STATUS                   Status;\r
+  PCI_REG_PCIE_CAPABILITY      Capability;\r
+  PCI_REG_PCIE_SLOT_CAPABILITY SlotCapability;\r
+\r
+  if (PciIoDevice == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Read the PCI Express Capabilities Register\r
+  //\r
+  if (!PciIoDevice->IsPciExp) {\r
+    return FALSE;\r
+  }\r
+  Offset = PciIoDevice->PciExpressCapabilityOffset +\r
+           OFFSET_OF (PCI_CAPABILITY_PCIEXP, Capability);\r
+  Status = PciIoDevice->PciIo.Pci.Read (\r
+                                    &PciIoDevice->PciIo,\r
+                                    EfiPciIoWidthUint16,\r
+                                    Offset,\r
+                                    1,\r
+                                    &Capability\r
+                                    );\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Check the contents of the register\r
+  //\r
+  switch (Capability.Bits.DevicePortType) {\r
+  case PCIE_DEVICE_PORT_TYPE_ROOT_PORT:\r
+  case PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT:\r
+    break;\r
+  default:\r
+    return FALSE;\r
+  }\r
+  if (!Capability.Bits.SlotImplemented) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Read the Slot Capabilities Register\r
+  //\r
+  Offset = PciIoDevice->PciExpressCapabilityOffset +\r
+           OFFSET_OF (PCI_CAPABILITY_PCIEXP, SlotCapability);\r
+  Status = PciIoDevice->PciIo.Pci.Read (\r
+                                    &PciIoDevice->PciIo,\r
+                                    EfiPciIoWidthUint32,\r
+                                    Offset,\r
+                                    1,\r
+                                    &SlotCapability\r
+                                    );\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Check the contents of the register\r
+  //\r
+  if (SlotCapability.Bits.HotPlugCapable) {\r
+    return TRUE;\r
+  }\r
+  return FALSE;\r
+}\r
+\r
 /**\r
   Get resource padding if the specified PCI bridge is a hot plug bus.\r
 \r
@@ -382,6 +470,14 @@ IsPciHotPlugBus (
     return TRUE;\r
   }\r
 \r
+  if (SupportsPcieHotplug (PciIoDevice)) {\r
+    //\r
+    // If the PPB is a PCIe root complex port or a switch downstream port, and\r
+    // implements a hot-plug capable slot, then also return TRUE.\r
+    //\r
+    return TRUE;\r
+  }\r
+\r
   //\r
   // Otherwise, see if it is a Root HPC\r
   //\r