#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
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
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
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
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
}\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
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
case PCI_SS_M32:\r
Status = AmlCodeGenRdDWordMemory (\r
FALSE,\r
- TRUE,\r
+ IsPosDecode,\r
TRUE,\r
TRUE,\r
TRUE,\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
case PCI_SS_M64:\r
Status = AmlCodeGenRdQWordMemory (\r
FALSE,\r
- TRUE,\r
+ IsPosDecode,\r
TRUE,\r
TRUE,\r
TRUE,\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
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
\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
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