]> git.proxmox.com Git - mirror_edk2.git/blobdiff - DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
DynamicTablesPkg: AcpiSsdtPcieLibArm: Added function to reserve ECAM space
[mirror_edk2.git] / DynamicTablesPkg / Library / Acpi / Arm / AcpiSsdtPcieLibArm / SsdtPcieGenerator.c
index a34018151f2d41ae808fec5ea9f257904a68d2b5..dd75fc27e60e92919804dc195143aed99d9336bf 100644 (file)
 #include <Library/AcpiHelperLib.h>\r
 #include <Library/TableHelperLib.h>\r
 #include <Library/AmlLib/AmlLib.h>\r
+#include <Library/SsdtPcieSupportLib.h>\r
 #include <Protocol/ConfigurationManagerProtocol.h>\r
 \r
 #include "SsdtPcieGenerator.h"\r
 \r
+#define PCI_MAX_DEVICE_COUNT_PER_BUS       32\r
+#define PCI_MAX_FUNCTION_COUNT_PER_DEVICE  8\r
+\r
 /** ARM standard SSDT Pcie Table Generator.\r
 \r
 Requirements:\r
@@ -280,86 +284,6 @@ GeneratePciDeviceInfo (
   return Status;\r
 }\r
 \r
-/** Generate Pci slots devices.\r
-\r
-  PCI Firmware Specification - Revision 3.3,\r
-  s4.8 "Generic ACPI PCI Slot Description" requests to describe the PCI slot\r
-  used. It should be possible to enumerate them, but this is additional\r
-  information.\r
-\r
-  @param [in]  MappingTable  The mapping table structure.\r
-  @param [in, out]  PciNode     Pci node to amend.\r
-\r
-  @retval EFI_SUCCESS            Success.\r
-  @retval EFI_INVALID_PARAMETER  Invalid parameter.\r
-  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-GeneratePciSlots (\r
-  IN      CONST MAPPING_TABLE           *MappingTable,\r
-  IN  OUT       AML_OBJECT_NODE_HANDLE  PciNode\r
-  )\r
-{\r
-  EFI_STATUS              Status;\r
-  UINT32                  Index;\r
-  UINT32                  LastIndex;\r
-  UINT32                  DeviceId;\r
-  CHAR8                   AslName[AML_NAME_SEG_SIZE + 1];\r
-  AML_OBJECT_NODE_HANDLE  DeviceNode;\r
-\r
-  ASSERT (MappingTable != NULL);\r
-  ASSERT (PciNode != NULL);\r
-\r
-  // Generic device name is "Dxx".\r
-  CopyMem (AslName, "Dxx_", AML_NAME_SEG_SIZE + 1);\r
-\r
-  LastIndex = MappingTable->LastIndex;\r
-\r
-  // There are at most 32 devices on a Pci bus.\r
-  if (LastIndex >= 32) {\r
-    ASSERT (0);\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  for (Index = 0; Index < LastIndex; Index++) {\r
-    DeviceId                       = MappingTable->Table[Index];\r
-    AslName[AML_NAME_SEG_SIZE - 3] = AsciiFromHex (DeviceId & 0xF);\r
-    AslName[AML_NAME_SEG_SIZE - 2] = AsciiFromHex ((DeviceId >> 4) & 0xF);\r
-\r
-    // ASL:\r
-    // Device (Dxx) {\r
-    //   Name (_ADR, <address value>)\r
-    // }\r
-    Status = AmlCodeGenDevice (AslName, PciNode, &DeviceNode);\r
-    if (EFI_ERROR (Status)) {\r
-      ASSERT (0);\r
-      return Status;\r
-    }\r
-\r
-    /* ACPI 6.4 specification, Table 6.2: "ADR Object Address Encodings"\r
-       High word-Device #, Low word-Function #. (for example, device 3,\r
-       function 2 is 0x00030002). To refer to all the functions on a device #,\r
-       use a function number of FFFF).\r
-    */\r
-    Status = AmlCodeGenNameInteger (\r
-               "_ADR",\r
-               (DeviceId << 16) | 0xFFFF,\r
-               DeviceNode,\r
-               NULL\r
-               );\r
-    if (EFI_ERROR (Status)) {\r
-      ASSERT (0);\r
-      return Status;\r
-    }\r
-\r
-    // _SUN object is not generated as we don't know which slot will be used.\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
 /** Generate a _PRT object (Pci Routing Table) for the Pci device.\r
 \r
   Cf. ACPI 6.4 specification, s6.2.13 "_PRT (PCI Routing Table)"\r
@@ -449,7 +373,7 @@ GeneratePrt (
     if ((Index > 0)   &&\r
         (IrqMapInfo->IntcInterrupt.Interrupt >= 32)   &&\r
         (IrqMapInfo->IntcInterrupt.Interrupt < 1020)  &&\r
-        ((IrqMapInfo->IntcInterrupt.Flags & 0x3) != BIT0))\r
+        ((IrqMapInfo->IntcInterrupt.Flags & 0xB) != 0))\r
     {\r
       Status = EFI_INVALID_PARAMETER;\r
       ASSERT_EFI_ERROR (Status);\r
@@ -495,7 +419,7 @@ GeneratePrt (
   PrtNode = NULL;\r
 \r
   // Generate the Pci slots once all the device have been added.\r
-  Status = GeneratePciSlots (&Generator->DeviceTable, PciNode);\r
+  Status = GeneratePciSlots (PciInfo, &Generator->DeviceTable, PciNode);\r
   if (EFI_ERROR (Status)) {\r
     ASSERT (0);\r
     goto exit_handler;\r
@@ -540,6 +464,7 @@ GeneratePciCrs (
   UINT32                       RefCount;\r
   CM_ARM_PCI_ADDRESS_MAP_INFO  *AddrMapInfo;\r
   AML_OBJECT_NODE_HANDLE       CrsNode;\r
+  BOOLEAN                      IsPosDecode;\r
 \r
   ASSERT (Generator != NULL);\r
   ASSERT (CfgMgrProtocol != NULL);\r
@@ -609,6 +534,11 @@ GeneratePciCrs (
     }\r
 \r
     Translation = (AddrMapInfo->CpuAddress != AddrMapInfo->PciAddress);\r
+    if (AddrMapInfo->CpuAddress >= AddrMapInfo->PciAddress) {\r
+      IsPosDecode = TRUE;\r
+    } else {\r
+      IsPosDecode = FALSE;\r
+    }\r
 \r
     switch (AddrMapInfo->SpaceCode) {\r
       case PCI_SS_IO:\r
@@ -616,12 +546,12 @@ GeneratePciCrs (
                    FALSE,\r
                    TRUE,\r
                    TRUE,\r
-                   TRUE,\r
+                   IsPosDecode,\r
                    3,\r
                    0,\r
                    AddrMapInfo->PciAddress,\r
                    AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1,\r
-                   Translation ? AddrMapInfo->CpuAddress : 0,\r
+                   Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0,\r
                    AddrMapInfo->AddressSize,\r
                    0,\r
                    NULL,\r
@@ -635,7 +565,7 @@ GeneratePciCrs (
       case PCI_SS_M32:\r
         Status = AmlCodeGenRdDWordMemory (\r
                    FALSE,\r
-                   TRUE,\r
+                   IsPosDecode,\r
                    TRUE,\r
                    TRUE,\r
                    TRUE,\r
@@ -643,7 +573,7 @@ GeneratePciCrs (
                    0,\r
                    AddrMapInfo->PciAddress,\r
                    AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1,\r
-                   Translation ? AddrMapInfo->CpuAddress : 0,\r
+                   Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0,\r
                    AddrMapInfo->AddressSize,\r
                    0,\r
                    NULL,\r
@@ -657,7 +587,7 @@ GeneratePciCrs (
       case PCI_SS_M64:\r
         Status = AmlCodeGenRdQWordMemory (\r
                    FALSE,\r
-                   TRUE,\r
+                   IsPosDecode,\r
                    TRUE,\r
                    TRUE,\r
                    TRUE,\r
@@ -665,7 +595,7 @@ GeneratePciCrs (
                    0,\r
                    AddrMapInfo->PciAddress,\r
                    AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1,\r
-                   Translation ? AddrMapInfo->CpuAddress : 0,\r
+                   Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0,\r
                    AddrMapInfo->AddressSize,\r
                    0,\r
                    NULL,\r
@@ -689,84 +619,125 @@ GeneratePciCrs (
   return Status;\r
 }\r
 \r
-/** Add an _OSC template method to the PciNode.\r
+/** Generate a RES0 device node to reserve PNP motherboard resources\r
+  for a given PCI node.\r
 \r
-  The _OSC method is provided as an AML blob. The blob is\r
-  parsed and attached at the end of the PciNode list of variable elements.\r
-\r
-  @param [in, out]  PciNode     Pci node to amend.\r
+  @param [in]   PciNode       Parent PCI node handle of the generated\r
+                              resource object.\r
+  @param [out]  CrsNode       CRS node of the AML tree to populate.\r
 \r
   @retval EFI_SUCCESS             The function completed successfully.\r
-  @retval EFI_INVALID_PARAMETER   Invalid parameter.\r
+  @retval EFI_INVALID_PARAMETER   Invalid input parameter.\r
   @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.\r
 **/\r
 STATIC\r
 EFI_STATUS\r
 EFIAPI\r
-AddOscMethod (\r
-  IN  OUT   AML_OBJECT_NODE_HANDLE  PciNode\r
+GenerateMotherboardDevice (\r
+  IN  AML_OBJECT_NODE_HANDLE  PciNode,\r
+  OUT AML_OBJECT_NODE_HANDLE  *CrsNode\r
   )\r
 {\r
-  EFI_STATUS                   Status;\r
-  EFI_STATUS                   Status1;\r
-  EFI_ACPI_DESCRIPTION_HEADER  *SsdtPcieOscTemplate;\r
-  AML_ROOT_NODE_HANDLE         OscTemplateRoot;\r
-  AML_OBJECT_NODE_HANDLE       OscNode;\r
+  EFI_STATUS              Status;\r
+  UINT32                  EisaId;\r
+  AML_OBJECT_NODE_HANDLE  ResNode;\r
 \r
-  ASSERT (PciNode != NULL);\r
+  if (CrsNode == NULL) {\r
+    ASSERT (0);\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
 \r
-  // Parse the Ssdt Pci Osc Template.\r
-  SsdtPcieOscTemplate = (EFI_ACPI_DESCRIPTION_HEADER *)\r
-                        ssdtpcieosctemplate_aml_code;\r
+  // ASL: Device (RES0) {}\r
+  Status = AmlCodeGenDevice ("RES0", PciNode, &ResNode);\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT (0);\r
+    return Status;\r
+  }\r
 \r
-  OscNode         = NULL;\r
-  OscTemplateRoot = NULL;\r
-  Status          = AmlParseDefinitionBlock (\r
-                      SsdtPcieOscTemplate,\r
-                      &OscTemplateRoot\r
-                      );\r
+  // ASL: Name (_HID, EISAID ("PNP0C02"))\r
+  Status = AmlGetEisaIdFromString ("PNP0C02", &EisaId); /* PNP Motherboard Resources */\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((\r
-      DEBUG_ERROR,\r
-      "ERROR: SSDT-PCI-OSC: Failed to parse SSDT PCI OSC Template."\r
-      " Status = %r\n",\r
-      Status\r
-      ));\r
+    ASSERT (0);\r
     return Status;\r
   }\r
 \r
-  Status = AmlFindNode (OscTemplateRoot, "\\_OSC", &OscNode);\r
+  Status = AmlCodeGenNameInteger ("_HID", EisaId, ResNode, NULL);\r
   if (EFI_ERROR (Status)) {\r
-    goto error_handler;\r
+    ASSERT (0);\r
+    return Status;\r
   }\r
 \r
-  Status = AmlDetachNode (OscNode);\r
+  // ASL: Name (_CRS, ResourceTemplate () {})\r
+  Status = AmlCodeGenNameResourceTemplate ("_CRS", ResNode, CrsNode);\r
   if (EFI_ERROR (Status)) {\r
-    goto error_handler;\r
+    ASSERT (0);\r
+    return Status;\r
   }\r
 \r
-  Status = AmlAttachNode (PciNode, OscNode);\r
+  return Status;\r
+}\r
+\r
+/** Reserves ECAM space for PCI config space\r
+\r
+  @param [in]       Generator       The SSDT Pci generator.\r
+  @param [in]       CfgMgrProtocol  Pointer to the Configuration Manager\r
+                                    Protocol interface.\r
+  @param [in]       PciInfo         Pci device information.\r
+  @param [in, out]  PciNode         RootNode of the AML tree to populate.\r
+\r
+  @retval EFI_SUCCESS             The function completed successfully.\r
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.\r
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+ReserveEcamSpace (\r
+  IN            ACPI_PCI_GENERATOR                            *Generator,\r
+  IN      CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol,\r
+  IN      CONST CM_ARM_PCI_CONFIG_SPACE_INFO                  *PciInfo,\r
+  IN  OUT       AML_OBJECT_NODE_HANDLE                        PciNode\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  AML_OBJECT_NODE_HANDLE  CrsNode;\r
+  UINT64                  AddressMinimum;\r
+  UINT64                  AddressMaximum;\r
+\r
+  Status = GenerateMotherboardDevice (PciNode, &CrsNode);\r
   if (EFI_ERROR (Status)) {\r
-    // Free the detached node.\r
-    AmlDeleteTree (OscNode);\r
-    goto error_handler;\r
+    ASSERT (0);\r
+    return Status;\r
   }\r
 \r
-error_handler:\r
-  // Cleanup\r
-  Status1 = AmlDeleteTree (OscTemplateRoot);\r
-  if (EFI_ERROR (Status1)) {\r
-    DEBUG ((\r
-      DEBUG_ERROR,\r
-      "ERROR: SSDT-PCI-OSC: Failed to cleanup AML tree."\r
-      " Status = %r\n",\r
-      Status1\r
-      ));\r
-    // If Status was success but we failed to delete the AML Tree\r
-    // return Status1 else return the original error code, i.e. Status.\r
-    if (!EFI_ERROR (Status)) {\r
-      return Status1;\r
-    }\r
+  AddressMinimum = PciInfo->BaseAddress + (PciInfo->StartBusNumber *\r
+                                           PCI_MAX_DEVICE_COUNT_PER_BUS * PCI_MAX_FUNCTION_COUNT_PER_DEVICE * SIZE_4KB);\r
+  AddressMaximum = PciInfo->BaseAddress + ((PciInfo->EndBusNumber + 1) *\r
+                                           PCI_MAX_DEVICE_COUNT_PER_BUS * PCI_MAX_FUNCTION_COUNT_PER_DEVICE * SIZE_4KB) - 1;\r
+\r
+  Status = AmlCodeGenRdQWordMemory (\r
+             FALSE,\r
+             TRUE,\r
+             TRUE,\r
+             TRUE,\r
+             FALSE,  // non-cacheable\r
+             TRUE,\r
+             0,\r
+             AddressMinimum,\r
+             AddressMaximum,\r
+             0,  // no translation\r
+             AddressMaximum - AddressMinimum + 1,\r
+             0,\r
+             NULL,\r
+             0,\r
+             TRUE,\r
+             CrsNode,\r
+             NULL\r
+             );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT (0);\r
+    return Status;\r
   }\r
 \r
   return Status;\r
@@ -818,7 +789,10 @@ GeneratePciDevice (
 \r
   // Write the name of the PCI device.\r
   CopyMem (AslName, "PCIx", AML_NAME_SEG_SIZE + 1);\r
-  AslName[AML_NAME_SEG_SIZE - 1] = AsciiFromHex (Uid);\r
+  AslName[AML_NAME_SEG_SIZE - 1] = AsciiFromHex (Uid & 0xF);\r
+  if (Uid > 0xF) {\r
+    AslName[AML_NAME_SEG_SIZE - 2] = AsciiFromHex ((Uid >> 4) & 0xF);\r
+  }\r
 \r
   // ASL: Device (PCIx) {}\r
   Status = AmlCodeGenDevice (AslName, ScopeNode, &PciNode);\r
@@ -855,9 +829,17 @@ GeneratePciDevice (
     return Status;\r
   }\r
 \r
+  // Add the PNP Motherboard Resources Device to reserve ECAM space\r
+  Status = ReserveEcamSpace (Generator, CfgMgrProtocol, PciInfo, PciNode);\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT (0);\r
+    return Status;\r
+  }\r
+\r
   // Add the template _OSC method.\r
-  Status = AddOscMethod (PciNode);\r
+  Status = AddOscMethod (PciInfo, PciNode);\r
   ASSERT_EFI_ERROR (Status);\r
+\r
   return Status;\r
 }\r
 \r