]> git.proxmox.com Git - mirror_edk2.git/blame - ArmVirtPkg/Library/ArmVirtPciHostBridgeUtilityLib/ArmVirtPciHostBridgeUtilityLib.c
ArmVirtPkg: Add PCIe host bridge utility lib for ArmVirtPkg
[mirror_edk2.git] / ArmVirtPkg / Library / ArmVirtPciHostBridgeUtilityLib / ArmVirtPciHostBridgeUtilityLib.c
CommitLineData
5959879e
SM
1/** @file\r
2 PCI Host Bridge utility functions for ArmVirt.\r
3\r
4 Copyright (c) 2021, Arm Limited. All rights reserved.<BR>\r
5\r
6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
7\r
8**/\r
9\r
10#include <IndustryStandard/Acpi10.h>\r
11#include <IndustryStandard/Pci.h>\r
12#include <Library/BaseMemoryLib.h>\r
13#include <Library/DebugLib.h>\r
14#include <Library/DevicePathLib.h>\r
15#include <Library/MemoryAllocationLib.h>\r
16#include <Library/PciHostBridgeLib.h>\r
17#include <Library/PciHostBridgeUtilityLib.h>\r
18#include <Library/PciLib.h>\r
19\r
20#pragma pack(1)\r
21typedef struct {\r
22 ACPI_HID_DEVICE_PATH AcpiDevicePath;\r
23 EFI_DEVICE_PATH_PROTOCOL EndDevicePath;\r
24} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;\r
25#pragma pack ()\r
26\r
27GLOBAL_REMOVE_IF_UNREFERENCED\r
28CHAR16 *mPciHostBridgeAcpiAddressSpaceTypeStr[] = {\r
29 L"Mem",\r
30 L"I/O",\r
31 L"Bus"\r
32};\r
33\r
34STATIC CONST EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath = {\r
35 {\r
36 {\r
37 ACPI_DEVICE_PATH,\r
38 ACPI_DP,\r
39 {\r
40 (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),\r
41 (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8)\r
42 }\r
43 },\r
44 EISA_PNP_ID (0x0A03), // HID\r
45 0 // UID\r
46 },\r
47\r
48 {\r
49 END_DEVICE_PATH_TYPE,\r
50 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
51 {\r
52 END_DEVICE_PATH_LENGTH,\r
53 0\r
54 }\r
55 }\r
56};\r
57\r
58\r
59GLOBAL_REMOVE_IF_UNREFERENCED\r
60CHAR16 *mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = {\r
61 L"Mem", L"I/O", L"Bus"\r
62};\r
63\r
64STATIC PCI_ROOT_BRIDGE mRootBridge;\r
65\r
66/**\r
67 Utility function to return all the root bridge instances in an array.\r
68\r
69 @param [out] Count The number of root bridge instances.\r
70 @param [in] Attributes Initial attributes.\r
71 @param [in] AllocationAttributes Allocation attributes.\r
72 @param [in] DmaAbove4G DMA above 4GB memory.\r
73 @param [in] NoExtendedConfigSpace No Extended Config Space.\r
74 @param [in] BusMin Minimum Bus number, inclusive.\r
75 @param [in] BusMax Maximum Bus number, inclusive.\r
76 @param [in] Io IO aperture.\r
77 @param [in] Mem MMIO aperture.\r
78 @param [in] MemAbove4G MMIO aperture above 4G.\r
79 @param [in] PMem Prefetchable MMIO aperture.\r
80 @param [in] PMemAbove4G Prefetchable MMIO aperture above 4G.\r
81\r
82 @return All the root bridge instances in an array.\r
83**/\r
84PCI_ROOT_BRIDGE *\r
85EFIAPI\r
86PciHostBridgeUtilityGetRootBridges (\r
87 OUT UINTN *Count,\r
88 IN UINT64 Attributes,\r
89 IN UINT64 AllocationAttributes,\r
90 IN BOOLEAN DmaAbove4G,\r
91 IN BOOLEAN NoExtendedConfigSpace,\r
92 IN UINTN BusMin,\r
93 IN UINTN BusMax,\r
94 IN PCI_ROOT_BRIDGE_APERTURE *Io,\r
95 IN PCI_ROOT_BRIDGE_APERTURE *Mem,\r
96 IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,\r
97 IN PCI_ROOT_BRIDGE_APERTURE *PMem,\r
98 IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G\r
99 )\r
100{\r
101 if ((Count == NULL) ||\r
102 (Io == NULL) ||\r
103 (Mem == NULL) ||\r
104 (MemAbove4G == NULL) ||\r
105 (PMem == NULL) ||\r
106 (PMemAbove4G == NULL)) {\r
107 return NULL;\r
108 }\r
109\r
110\r
111 *Count = 1;\r
112\r
113 mRootBridge.Segment = 0;\r
114 mRootBridge.Supports = Attributes;\r
115 mRootBridge.Attributes = Attributes;\r
116\r
117 mRootBridge.DmaAbove4G = DmaAbove4G;\r
118 mRootBridge.NoExtendedConfigSpace = NoExtendedConfigSpace;\r
119 mRootBridge.ResourceAssigned = FALSE;\r
120\r
121 mRootBridge.AllocationAttributes = AllocationAttributes;\r
122\r
123 mRootBridge.Bus.Base = BusMin;\r
124 mRootBridge.Bus.Limit = BusMax;\r
125 mRootBridge.Io.Base = Io->Base;\r
126 mRootBridge.Io.Limit = Io->Limit;\r
127 mRootBridge.Mem.Base = Mem->Base;\r
128 mRootBridge.Mem.Limit = Mem->Limit;\r
129 mRootBridge.MemAbove4G.Base = MemAbove4G->Base;\r
130 mRootBridge.MemAbove4G.Limit = MemAbove4G->Limit;\r
131 mRootBridge.PMem.Base = PMem->Base;\r
132 mRootBridge.PMem.Limit = PMem->Limit;\r
133 mRootBridge.PMemAbove4G.Base = PMemAbove4G->Base;\r
134 mRootBridge.PMemAbove4G.Limit = PMemAbove4G->Limit;\r
135\r
136 mRootBridge.DevicePath =\r
137 (EFI_DEVICE_PATH_PROTOCOL*)&mEfiPciRootBridgeDevicePath;\r
138\r
139 return &mRootBridge;\r
140}\r
141\r
142/**\r
143 Utility function to free root bridge instances array from\r
144 PciHostBridgeUtilityGetRootBridges().\r
145\r
146 @param[in] Bridges The root bridge instances array.\r
147 @param[in] Count The count of the array.\r
148**/\r
149VOID\r
150EFIAPI\r
151PciHostBridgeUtilityFreeRootBridges (\r
152 IN PCI_ROOT_BRIDGE *Bridges,\r
153 IN UINTN Count\r
154 )\r
155{\r
156 // Nothing to do here.\r
157}\r
158\r
159/**\r
160 Utility function to inform the platform that the resource conflict happens.\r
161\r
162 @param[in] Configuration Pointer to PCI I/O and PCI memory resource\r
163 descriptors. The Configuration contains the\r
164 resources for all the root bridges. The resource\r
165 for each root bridge is terminated with END\r
166 descriptor and an additional END is appended\r
167 indicating the end of the entire resources. The\r
168 resource descriptor field values follow the\r
169 description in\r
170 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
171 .SubmitResources().\r
172**/\r
173VOID\r
174EFIAPI\r
175PciHostBridgeUtilityResourceConflict (\r
176 IN VOID *Configuration\r
177 )\r
178{\r
179 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
180 UINTN RootBridgeIndex;\r
181 DEBUG ((DEBUG_ERROR, "PciHostBridge: Resource conflict happens!\n"));\r
182\r
183 RootBridgeIndex = 0;\r
184 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR*)Configuration;\r
185 while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
186 DEBUG ((DEBUG_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));\r
187 for (; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {\r
188 ASSERT (Descriptor->ResType <\r
189 ARRAY_SIZE (mPciHostBridgeAcpiAddressSpaceTypeStr)\r
190 );\r
191 DEBUG ((\r
192 DEBUG_ERROR,\r
193 " %s: Length/Alignment = 0x%lx / 0x%lx\n",\r
194 mPciHostBridgeAcpiAddressSpaceTypeStr[Descriptor->ResType],\r
195 Descriptor->AddrLen,\r
196 Descriptor->AddrRangeMax\r
197 ));\r
198 if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
199 DEBUG ((\r
200 DEBUG_ERROR,\r
201 " Granularity/SpecificFlag = %ld / %02x%s\n",\r
202 Descriptor->AddrSpaceGranularity,\r
203 Descriptor->SpecificFlag,\r
204 ((Descriptor->SpecificFlag &\r
205 EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE\r
206 ) != 0) ? L" (Prefetchable)" : L""\r
207 ));\r
208 }\r
209 }\r
210 //\r
211 // Skip the END descriptor for root bridge\r
212 //\r
213 ASSERT (Descriptor->Desc == ACPI_END_TAG_DESCRIPTOR);\r
214 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR*)(\r
215 (EFI_ACPI_END_TAG_DESCRIPTOR*)Descriptor + 1\r
216 );\r
217 }\r
218}\r