]> git.proxmox.com Git - mirror_edk2.git/blame - ArmVirtPkg/PciHostBridgeDxe/PciHostBridge.c
BaseTools/GenFv: Account for rebase of FV section containing VTF file
[mirror_edk2.git] / ArmVirtPkg / PciHostBridgeDxe / PciHostBridge.c
CommitLineData
9595e3cd
LE
1/** @file\r
2 Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation\r
3\r
4Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials are\r
6licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
d1c561f9 13**/\r
9595e3cd
LE
14\r
15#include "PciHostBridge.h"\r
16\r
17//\r
18// Hard code: Root Bridge Number within the host bridge\r
19// Root Bridge's attribute\r
20// Root Bridge's device path\r
21// Root Bridge's resource aperture\r
22//\r
23UINTN RootBridgeNumber[1] = { 1 };\r
24\r
25UINT64 RootBridgeAttribute[1][1] = { { EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM } };\r
26\r
27EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath[1][1] = {\r
28 {\r
29 {\r
30 {\r
31 {\r
32 ACPI_DEVICE_PATH,\r
33 ACPI_DP,\r
34 {\r
35 (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),\r
36 (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)\r
37 }\r
38 },\r
39 EISA_PNP_ID(0x0A03),\r
40 0\r
41 },\r
d1c561f9 42\r
9595e3cd
LE
43 {\r
44 END_DEVICE_PATH_TYPE,\r
45 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
46 {\r
47 END_DEVICE_PATH_LENGTH,\r
48 0\r
49 }\r
50 }\r
51 }\r
52 }\r
53};\r
54\r
aca7e8b6 55STATIC PCI_ROOT_BRIDGE_RESOURCE_APERTURE mResAperture[1][1];\r
9595e3cd
LE
56\r
57EFI_HANDLE mDriverImageHandle;\r
58\r
59PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = {\r
60 PCI_HOST_BRIDGE_SIGNATURE, // Signature\r
61 NULL, // HostBridgeHandle\r
62 0, // RootBridgeNumber\r
63 {NULL, NULL}, // Head\r
64 FALSE, // ResourceSubiteed\r
65 TRUE, // CanRestarted\r
66 {\r
67 NotifyPhase,\r
68 GetNextRootBridge,\r
69 GetAttributes,\r
70 StartBusEnumeration,\r
71 SetBusNumbers,\r
72 SubmitResources,\r
73 GetProposedResources,\r
74 PreprocessController\r
75 }\r
76};\r
77\r
78//\r
79// Implementation\r
80//\r
81\r
cd2178bb
AB
82STATIC\r
83VOID\r
84SetLinuxPciProbeOnlyProperty (\r
85 IN FDT_CLIENT_PROTOCOL *FdtClient\r
86 )\r
87{\r
88 INT32 Node;\r
89 UINT32 Tmp;\r
90 EFI_STATUS Status;\r
91\r
92 if (!FeaturePcdGet (PcdPureAcpiBoot)) {\r
93 //\r
94 // Set the /chosen/linux,pci-probe-only property to 1, so that the PCI\r
95 // setup we will perform in the firmware is honored by the Linux OS,\r
96 // rather than torn down and done from scratch. This is generally a more\r
97 // sensible approach, and aligns with what ACPI based OSes do typically.\r
98 //\r
99 // In case we are exposing an emulated VGA PCI device to the guest, which\r
100 // may subsequently get exposed via the Graphics Output protocol and\r
101 // driven as an efifb by Linux, we need this setting to prevent the\r
102 // framebuffer from becoming unresponsive.\r
103 //\r
104 Status = FdtClient->GetOrInsertChosenNode (FdtClient, &Node);\r
105\r
106 if (!EFI_ERROR (Status)) {\r
107 Tmp = SwapBytes32 (1);\r
108 Status = FdtClient->SetNodeProperty (FdtClient, Node,\r
109 "linux,pci-probe-only", &Tmp, sizeof (Tmp));\r
110 }\r
111 if (EFI_ERROR (Status)) {\r
112 DEBUG ((EFI_D_WARN,\r
113 "Failed to set /chosen/linux,pci-probe-only property\n"));\r
114 }\r
115 }\r
116}\r
117\r
118//\r
119// We expect the "ranges" property of "pci-host-ecam-generic" to consist of\r
120// records like this.\r
121//\r
122#pragma pack (1)\r
123typedef struct {\r
124 UINT32 Type;\r
125 UINT64 ChildBase;\r
126 UINT64 CpuBase;\r
127 UINT64 Size;\r
128} DTB_PCI_HOST_RANGE_RECORD;\r
129#pragma pack ()\r
130\r
131#define DTB_PCI_HOST_RANGE_RELOCATABLE BIT31\r
132#define DTB_PCI_HOST_RANGE_PREFETCHABLE BIT30\r
133#define DTB_PCI_HOST_RANGE_ALIASED BIT29\r
134#define DTB_PCI_HOST_RANGE_MMIO32 BIT25\r
135#define DTB_PCI_HOST_RANGE_MMIO64 (BIT25 | BIT24)\r
136#define DTB_PCI_HOST_RANGE_IO BIT24\r
137#define DTB_PCI_HOST_RANGE_TYPEMASK (BIT31 | BIT30 | BIT29 | BIT25 | BIT24)\r
138\r
139STATIC\r
140EFI_STATUS\r
141ProcessPciHost (\r
142 OUT UINT64 *IoBase,\r
143 OUT UINT64 *IoSize,\r
144 OUT UINT64 *IoTranslation,\r
145 OUT UINT64 *MmioBase,\r
146 OUT UINT64 *MmioSize,\r
147 OUT UINT64 *MmioTranslation,\r
148 OUT UINT32 *BusMin,\r
149 OUT UINT32 *BusMax\r
150 )\r
151{\r
152 FDT_CLIENT_PROTOCOL *FdtClient;\r
153 INT32 Node;\r
154 UINT64 ConfigBase, ConfigSize;\r
155 CONST VOID *Prop;\r
156 UINT32 Len;\r
157 UINT32 RecordIdx;\r
158 EFI_STATUS Status;\r
159\r
160 //\r
161 // The following output arguments are initialized only in\r
162 // order to suppress '-Werror=maybe-uninitialized' warnings\r
163 // *incorrectly* emitted by some gcc versions.\r
164 //\r
165 *IoBase = 0;\r
166 *IoTranslation = 0;\r
167 *MmioBase = 0;\r
168 *MmioTranslation = 0;\r
169 *BusMin = 0;\r
170 *BusMax = 0;\r
171\r
172 //\r
173 // *IoSize and *MmioSize are initialized to zero because the logic below\r
174 // requires it. However, since they are also affected by the issue reported\r
175 // above, they are initialized early.\r
176 //\r
177 *IoSize = 0;\r
178 *MmioSize = 0;\r
179\r
180 Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,\r
181 (VOID **)&FdtClient);\r
182 ASSERT_EFI_ERROR (Status);\r
183\r
184 Status = FdtClient->FindCompatibleNode (FdtClient, "pci-host-ecam-generic",\r
185 &Node);\r
186 if (EFI_ERROR (Status)) {\r
187 DEBUG ((EFI_D_INFO,\r
188 "%a: No 'pci-host-ecam-generic' compatible DT node found\n",\r
189 __FUNCTION__));\r
190 return EFI_NOT_FOUND;\r
191 }\r
192\r
193 DEBUG_CODE (\r
194 INT32 Tmp;\r
195\r
196 //\r
197 // A DT can legally describe multiple PCI host bridges, but we are not\r
198 // equipped to deal with that. So assert that there is only one.\r
199 //\r
200 Status = FdtClient->FindNextCompatibleNode (FdtClient,\r
201 "pci-host-ecam-generic", Node, &Tmp);\r
202 ASSERT (Status == EFI_NOT_FOUND);\r
203 );\r
204\r
205 Status = FdtClient->GetNodeProperty (FdtClient, Node, "reg", &Prop, &Len);\r
206 if (EFI_ERROR (Status) || Len != 2 * sizeof (UINT64)) {\r
207 DEBUG ((EFI_D_ERROR, "%a: 'reg' property not found or invalid\n",\r
208 __FUNCTION__));\r
209 return EFI_PROTOCOL_ERROR;\r
210 }\r
211\r
212 //\r
213 // Fetch the ECAM window.\r
214 //\r
215 ConfigBase = SwapBytes64 (((CONST UINT64 *)Prop)[0]);\r
216 ConfigSize = SwapBytes64 (((CONST UINT64 *)Prop)[1]);\r
217\r
218 //\r
219 // Fetch the bus range (note: inclusive).\r
220 //\r
221 Status = FdtClient->GetNodeProperty (FdtClient, Node, "bus-range", &Prop,\r
222 &Len);\r
223 if (EFI_ERROR (Status) || Len != 2 * sizeof (UINT32)) {\r
224 DEBUG ((EFI_D_ERROR, "%a: 'bus-range' not found or invalid\n",\r
225 __FUNCTION__));\r
226 return EFI_PROTOCOL_ERROR;\r
227 }\r
228 *BusMin = SwapBytes32 (((CONST UINT32 *)Prop)[0]);\r
229 *BusMax = SwapBytes32 (((CONST UINT32 *)Prop)[1]);\r
230\r
231 //\r
232 // Sanity check: the config space must accommodate all 4K register bytes of\r
233 // all 8 functions of all 32 devices of all buses.\r
234 //\r
235 if (*BusMax < *BusMin || *BusMax - *BusMin == MAX_UINT32 ||\r
236 DivU64x32 (ConfigSize, SIZE_4KB * 8 * 32) < *BusMax - *BusMin + 1) {\r
237 DEBUG ((EFI_D_ERROR, "%a: invalid 'bus-range' and/or 'reg'\n",\r
238 __FUNCTION__));\r
239 return EFI_PROTOCOL_ERROR;\r
240 }\r
241\r
242 //\r
243 // Iterate over "ranges".\r
244 //\r
245 Status = FdtClient->GetNodeProperty (FdtClient, Node, "ranges", &Prop, &Len);\r
246 if (EFI_ERROR (Status) || Len == 0 ||\r
247 Len % sizeof (DTB_PCI_HOST_RANGE_RECORD) != 0) {\r
248 DEBUG ((EFI_D_ERROR, "%a: 'ranges' not found or invalid\n", __FUNCTION__));\r
249 return EFI_PROTOCOL_ERROR;\r
250 }\r
251\r
252 for (RecordIdx = 0; RecordIdx < Len / sizeof (DTB_PCI_HOST_RANGE_RECORD);\r
253 ++RecordIdx) {\r
254 CONST DTB_PCI_HOST_RANGE_RECORD *Record;\r
255\r
256 Record = (CONST DTB_PCI_HOST_RANGE_RECORD *)Prop + RecordIdx;\r
257 switch (SwapBytes32 (Record->Type) & DTB_PCI_HOST_RANGE_TYPEMASK) {\r
258 case DTB_PCI_HOST_RANGE_IO:\r
259 *IoBase = SwapBytes64 (Record->ChildBase);\r
260 *IoSize = SwapBytes64 (Record->Size);\r
261 *IoTranslation = SwapBytes64 (Record->CpuBase) - *IoBase;\r
262 break;\r
263\r
264 case DTB_PCI_HOST_RANGE_MMIO32:\r
265 *MmioBase = SwapBytes64 (Record->ChildBase);\r
266 *MmioSize = SwapBytes64 (Record->Size);\r
267 *MmioTranslation = SwapBytes64 (Record->CpuBase) - *MmioBase;\r
268\r
269 if (*MmioBase > MAX_UINT32 || *MmioSize > MAX_UINT32 ||\r
270 *MmioBase + *MmioSize > SIZE_4GB) {\r
271 DEBUG ((EFI_D_ERROR, "%a: MMIO32 space invalid\n", __FUNCTION__));\r
272 return EFI_PROTOCOL_ERROR;\r
273 }\r
274\r
275 if (*MmioTranslation != 0) {\r
276 DEBUG ((EFI_D_ERROR, "%a: unsupported nonzero MMIO32 translation "\r
277 "0x%Lx\n", __FUNCTION__, *MmioTranslation));\r
278 return EFI_UNSUPPORTED;\r
279 }\r
280\r
281 break;\r
282 }\r
283 }\r
284 if (*IoSize == 0 || *MmioSize == 0) {\r
285 DEBUG ((EFI_D_ERROR, "%a: %a space empty\n", __FUNCTION__,\r
286 (*IoSize == 0) ? "IO" : "MMIO32"));\r
287 return EFI_PROTOCOL_ERROR;\r
288 }\r
289\r
290 //\r
291 // The dynamic PCD PcdPciExpressBaseAddress should have already been set,\r
292 // and should match the value we found in the DT node.\r
293 //\r
294 ASSERT (PcdGet64 (PcdPciExpressBaseAddress) == ConfigBase);\r
295\r
296 SetLinuxPciProbeOnlyProperty (FdtClient);\r
297\r
298 DEBUG ((EFI_D_INFO, "%a: Config[0x%Lx+0x%Lx) Bus[0x%x..0x%x] "\r
299 "Io[0x%Lx+0x%Lx)@0x%Lx Mem[0x%Lx+0x%Lx)@0x%Lx\n", __FUNCTION__, ConfigBase,\r
300 ConfigSize, *BusMin, *BusMax, *IoBase, *IoSize, *IoTranslation, *MmioBase,\r
301 *MmioSize, *MmioTranslation));\r
302 return EFI_SUCCESS;\r
303}\r
304\r
305\r
9595e3cd
LE
306/**\r
307 Entry point of this driver\r
308\r
309 @param ImageHandle Handle of driver image\r
310 @param SystemTable Point to EFI_SYSTEM_TABLE\r
311\r
120a25c2 312 @retval EFI_ABORTED PCI host bridge not present\r
9595e3cd
LE
313 @retval EFI_OUT_OF_RESOURCES Can not allocate memory resource\r
314 @retval EFI_DEVICE_ERROR Can not install the protocol instance\r
315 @retval EFI_SUCCESS Success to initialize the Pci host bridge.\r
316**/\r
317EFI_STATUS\r
318EFIAPI\r
319InitializePciHostBridge (\r
320 IN EFI_HANDLE ImageHandle,\r
321 IN EFI_SYSTEM_TABLE *SystemTable\r
322 )\r
323{\r
f9a8be42 324 UINT64 MmioAttributes;\r
9595e3cd
LE
325 EFI_STATUS Status;\r
326 UINTN Loop1;\r
327 UINTN Loop2;\r
328 PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
329 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
cd2178bb
AB
330 UINT64 IoBase, IoSize, IoTranslation;\r
331 UINT64 MmioBase, MmioSize, MmioTranslation;\r
332 UINT32 BusMin, BusMax;\r
d1c561f9 333\r
120a25c2
LE
334 if (PcdGet64 (PcdPciExpressBaseAddress) == 0) {\r
335 DEBUG ((EFI_D_INFO, "%a: PCI host bridge not present\n", __FUNCTION__));\r
336 return EFI_ABORTED;\r
337 }\r
338\r
cd2178bb
AB
339 Status = ProcessPciHost (&IoBase, &IoSize, &IoTranslation, &MmioBase,\r
340 &MmioSize, &MmioTranslation, &BusMin, &BusMax);\r
341 if (EFI_ERROR (Status)) {\r
342 return Status;\r
343 }\r
344\r
9595e3cd 345 mDriverImageHandle = ImageHandle;\r
d1c561f9 346\r
cd2178bb
AB
347 mResAperture[0][0].BusBase = BusMin;\r
348 mResAperture[0][0].BusLimit = BusMax;\r
aca7e8b6 349\r
cd2178bb
AB
350 mResAperture[0][0].MemBase = MmioBase;\r
351 mResAperture[0][0].MemLimit = MmioBase + MmioSize - 1;\r
aca7e8b6 352\r
cd2178bb
AB
353 mResAperture[0][0].IoBase = IoBase;\r
354 mResAperture[0][0].IoLimit = IoBase + IoSize - 1;\r
355 mResAperture[0][0].IoTranslation = IoTranslation;\r
aca7e8b6 356\r
807c26d3
LE
357 //\r
358 // Add IO and MMIO memory space, so that resources can be allocated in the\r
359 // EfiPciHostBridgeAllocateResources phase.\r
360 //\r
361 Status = gDS->AddIoSpace (\r
362 EfiGcdIoTypeIo,\r
cd2178bb
AB
363 IoBase,\r
364 IoSize\r
807c26d3
LE
365 );\r
366 ASSERT_EFI_ERROR (Status);\r
367\r
f9a8be42
LE
368 MmioAttributes = FeaturePcdGet (PcdKludgeMapPciMmioAsCached) ?\r
369 EFI_MEMORY_WB : EFI_MEMORY_UC;\r
370\r
807c26d3
LE
371 Status = gDS->AddMemorySpace (\r
372 EfiGcdMemoryTypeMemoryMappedIo,\r
cd2178bb
AB
373 MmioBase,\r
374 MmioSize,\r
f9a8be42 375 MmioAttributes\r
807c26d3
LE
376 );\r
377 if (EFI_ERROR (Status)) {\r
378 DEBUG ((EFI_D_ERROR, "%a: AddMemorySpace: %r\n", __FUNCTION__, Status));\r
379 return Status;\r
380 }\r
381\r
f9a8be42 382 Status = gDS->SetMemorySpaceAttributes (\r
cd2178bb
AB
383 MmioBase,\r
384 MmioSize,\r
f9a8be42
LE
385 MmioAttributes\r
386 );\r
387 if (EFI_ERROR (Status)) {\r
388 DEBUG ((EFI_D_ERROR, "%a: SetMemorySpaceAttributes: %r\n", __FUNCTION__,\r
389 Status));\r
390 return Status;\r
391 }\r
392\r
9595e3cd
LE
393 //\r
394 // Create Host Bridge Device Handle\r
395 //\r
396 for (Loop1 = 0; Loop1 < HOST_BRIDGE_NUMBER; Loop1++) {\r
397 HostBridge = AllocateCopyPool (sizeof(PCI_HOST_BRIDGE_INSTANCE), &mPciHostBridgeInstanceTemplate);\r
398 if (HostBridge == NULL) {\r
399 return EFI_OUT_OF_RESOURCES;\r
400 }\r
d1c561f9 401\r
9595e3cd
LE
402 HostBridge->RootBridgeNumber = RootBridgeNumber[Loop1];\r
403 InitializeListHead (&HostBridge->Head);\r
404\r
405 Status = gBS->InstallMultipleProtocolInterfaces (\r
d1c561f9 406 &HostBridge->HostBridgeHandle,\r
9595e3cd
LE
407 &gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc,\r
408 NULL\r
409 );\r
410 if (EFI_ERROR (Status)) {\r
411 FreePool (HostBridge);\r
412 return EFI_DEVICE_ERROR;\r
413 }\r
d1c561f9 414\r
9595e3cd
LE
415 //\r
416 // Create Root Bridge Device Handle in this Host Bridge\r
417 //\r
d1c561f9 418\r
9595e3cd
LE
419 for (Loop2 = 0; Loop2 < HostBridge->RootBridgeNumber; Loop2++) {\r
420 PrivateData = AllocateZeroPool (sizeof(PCI_ROOT_BRIDGE_INSTANCE));\r
421 if (PrivateData == NULL) {\r
422 return EFI_OUT_OF_RESOURCES;\r
423 }\r
424\r
425 PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE;\r
426 PrivateData->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath[Loop1][Loop2];\r
427\r
428 RootBridgeConstructor (\r
d1c561f9
OM
429 &PrivateData->Io,\r
430 HostBridge->HostBridgeHandle,\r
431 RootBridgeAttribute[Loop1][Loop2],\r
9595e3cd
LE
432 &mResAperture[Loop1][Loop2]\r
433 );\r
d1c561f9 434\r
9595e3cd 435 Status = gBS->InstallMultipleProtocolInterfaces(\r
d1c561f9 436 &PrivateData->Handle,\r
9595e3cd
LE
437 &gEfiDevicePathProtocolGuid, PrivateData->DevicePath,\r
438 &gEfiPciRootBridgeIoProtocolGuid, &PrivateData->Io,\r
439 NULL\r
440 );\r
441 if (EFI_ERROR (Status)) {\r
442 FreePool(PrivateData);\r
443 return EFI_DEVICE_ERROR;\r
444 }\r
d1c561f9 445\r
9595e3cd
LE
446 InsertTailList (&HostBridge->Head, &PrivateData->Link);\r
447 }\r
d1c561f9 448 }\r
9595e3cd
LE
449\r
450 return EFI_SUCCESS;\r
451}\r
452\r
453\r
454/**\r
455 These are the notifications from the PCI bus driver that it is about to enter a certain\r
456 phase of the PCI enumeration process.\r
457\r
458 This member function can be used to notify the host bridge driver to perform specific actions,\r
459 including any chipset-specific initialization, so that the chipset is ready to enter the next phase.\r
460 Eight notification points are defined at this time. See belows:\r
461 EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apertures and internal data\r
462 structures. The PCI enumerator should issue this notification\r
463 before starting a fresh enumeration process. Enumeration cannot\r
464 be restarted after sending any other notification such as\r
465 EfiPciHostBridgeBeginBusAllocation.\r
466 EfiPciHostBridgeBeginBusAllocation The bus allocation phase is about to begin. No specific action is\r
467 required here. This notification can be used to perform any\r
468 chipset-specific programming.\r
469 EfiPciHostBridgeEndBusAllocation The bus allocation and bus programming phase is complete. No\r
470 specific action is required here. This notification can be used to\r
471 perform any chipset-specific programming.\r
472 EfiPciHostBridgeBeginResourceAllocation\r
473 The resource allocation phase is about to begin. No specific\r
474 action is required here. This notification can be used to perform\r
475 any chipset-specific programming.\r
476 EfiPciHostBridgeAllocateResources Allocates resources per previously submitted requests for all the PCI\r
477 root bridges. These resource settings are returned on the next call to\r
478 GetProposedResources(). Before calling NotifyPhase() with a Phase of\r
479 EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible\r
480 for gathering I/O and memory requests for\r
481 all the PCI root bridges and submitting these requests using\r
482 SubmitResources(). This function pads the resource amount\r
483 to suit the root bridge hardware, takes care of dependencies between\r
484 the PCI root bridges, and calls the Global Coherency Domain (GCD)\r
485 with the allocation request. In the case of padding, the allocated range\r
486 could be bigger than what was requested.\r
487 EfiPciHostBridgeSetResources Programs the host bridge hardware to decode previously allocated\r
488 resources (proposed resources) for all the PCI root bridges. After the\r
489 hardware is programmed, reassigning resources will not be supported.\r
490 The bus settings are not affected.\r
491 EfiPciHostBridgeFreeResources Deallocates resources that were previously allocated for all the PCI\r
492 root bridges and resets the I/O and memory apertures to their initial\r
493 state. The bus settings are not affected. If the request to allocate\r
494 resources fails, the PCI enumerator can use this notification to\r
495 deallocate previous resources, adjust the requests, and retry\r
496 allocation.\r
497 EfiPciHostBridgeEndResourceAllocation The resource allocation phase is completed. No specific action is\r
498 required here. This notification can be used to perform any chipsetspecific\r
499 programming.\r
500\r
501 @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
502 @param[in] Phase The phase during enumeration\r
503\r
504 @retval EFI_NOT_READY This phase cannot be entered at this time. For example, this error\r
505 is valid for a Phase of EfiPciHostBridgeAllocateResources if\r
506 SubmitResources() has not been called for one or more\r
507 PCI root bridges before this call\r
508 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. This error is valid\r
509 for a Phase of EfiPciHostBridgeSetResources.\r
510 @retval EFI_INVALID_PARAMETER Invalid phase parameter\r
511 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
512 This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the\r
513 previously submitted resource requests cannot be fulfilled or\r
514 were only partially fulfilled.\r
515 @retval EFI_SUCCESS The notification was accepted without any errors.\r
516\r
517**/\r
518EFI_STATUS\r
519EFIAPI\r
520NotifyPhase(\r
521 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
522 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase\r
523 )\r
524{\r
525 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;\r
526 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
527 PCI_RESOURCE_TYPE Index;\r
528 LIST_ENTRY *List;\r
529 EFI_PHYSICAL_ADDRESS BaseAddress;\r
530 UINT64 AddrLen;\r
531 UINTN BitsOfAlignment;\r
532 EFI_STATUS Status;\r
533 EFI_STATUS ReturnStatus;\r
d1c561f9 534\r
9595e3cd 535 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);\r
d1c561f9 536\r
9595e3cd
LE
537 switch (Phase) {\r
538\r
539 case EfiPciHostBridgeBeginEnumeration:\r
540 if (HostBridgeInstance->CanRestarted) {\r
541 //\r
d1c561f9 542 // Reset the Each Root Bridge\r
9595e3cd
LE
543 //\r
544 List = HostBridgeInstance->Head.ForwardLink;\r
d1c561f9 545\r
9595e3cd
LE
546 while (List != &HostBridgeInstance->Head) {\r
547 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
548 for (Index = TypeIo; Index < TypeMax; Index++) {\r
549 RootBridgeInstance->ResAllocNode[Index].Type = Index;\r
550 RootBridgeInstance->ResAllocNode[Index].Base = 0;\r
551 RootBridgeInstance->ResAllocNode[Index].Length = 0;\r
552 RootBridgeInstance->ResAllocNode[Index].Status = ResNone;\r
553 }\r
d1c561f9 554\r
9595e3cd
LE
555 List = List->ForwardLink;\r
556 }\r
d1c561f9 557\r
9595e3cd
LE
558 HostBridgeInstance->ResourceSubmited = FALSE;\r
559 HostBridgeInstance->CanRestarted = TRUE;\r
560 } else {\r
561 //\r
562 // Can not restart\r
d1c561f9 563 //\r
9595e3cd 564 return EFI_NOT_READY;\r
d1c561f9 565 }\r
9595e3cd
LE
566 break;\r
567\r
568 case EfiPciHostBridgeEndEnumeration:\r
569 break;\r
570\r
571 case EfiPciHostBridgeBeginBusAllocation:\r
572 //\r
573 // No specific action is required here, can perform any chipset specific programing\r
574 //\r
575 HostBridgeInstance->CanRestarted = FALSE;\r
576 break;\r
577\r
578 case EfiPciHostBridgeEndBusAllocation:\r
579 //\r
580 // No specific action is required here, can perform any chipset specific programing\r
581 //\r
582 //HostBridgeInstance->CanRestarted = FALSE;\r
583 break;\r
584\r
585 case EfiPciHostBridgeBeginResourceAllocation:\r
586 //\r
587 // No specific action is required here, can perform any chipset specific programing\r
588 //\r
589 //HostBridgeInstance->CanRestarted = FALSE;\r
590 break;\r
591\r
592 case EfiPciHostBridgeAllocateResources:\r
593 ReturnStatus = EFI_SUCCESS;\r
594 if (HostBridgeInstance->ResourceSubmited) {\r
595 //\r
d1c561f9 596 // Take care of the resource dependencies between the root bridges\r
9595e3cd
LE
597 //\r
598 List = HostBridgeInstance->Head.ForwardLink;\r
599\r
600 while (List != &HostBridgeInstance->Head) {\r
601 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
602 for (Index = TypeIo; Index < TypeBus; Index++) {\r
603 if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {\r
d1c561f9 604\r
9595e3cd 605 AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;\r
d1c561f9 606\r
9595e3cd
LE
607 //\r
608 // Get the number of '1' in Alignment.\r
609 //\r
610 BitsOfAlignment = (UINTN) (HighBitSet64 (RootBridgeInstance->ResAllocNode[Index].Alignment) + 1);\r
d1c561f9 611\r
9595e3cd
LE
612 switch (Index) {\r
613\r
d1c561f9 614 case TypeIo:\r
9595e3cd
LE
615 //\r
616 // It is impossible for this chipset to align 0xFFFF for IO16\r
617 // So clear it\r
618 //\r
619 if (BitsOfAlignment >= 16) {\r
620 BitsOfAlignment = 0;\r
621 }\r
d1c561f9 622\r
ef8dba7d 623 BaseAddress = mResAperture[0][0].IoLimit;\r
9595e3cd 624 Status = gDS->AllocateIoSpace (\r
ef8dba7d 625 EfiGcdAllocateMaxAddressSearchTopDown,\r
d1c561f9 626 EfiGcdIoTypeIo,\r
9595e3cd
LE
627 BitsOfAlignment,\r
628 AddrLen,\r
629 &BaseAddress,\r
630 mDriverImageHandle,\r
631 NULL\r
632 );\r
d1c561f9 633\r
9595e3cd
LE
634 if (!EFI_ERROR (Status)) {\r
635 RootBridgeInstance->ResAllocNode[Index].Base = (UINTN)BaseAddress;\r
d1c561f9 636 RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated;\r
9595e3cd 637 } else {\r
d1c561f9 638 ReturnStatus = Status;\r
9595e3cd
LE
639 if (Status != EFI_OUT_OF_RESOURCES) {\r
640 RootBridgeInstance->ResAllocNode[Index].Length = 0;\r
641 }\r
642 }\r
643\r
644 break;\r
645\r
646\r
647 case TypeMem32:\r
648 //\r
649 // It is impossible for this chipset to align 0xFFFFFFFF for Mem32\r
d1c561f9 650 // So clear it\r
9595e3cd 651 //\r
d1c561f9 652\r
9595e3cd
LE
653 if (BitsOfAlignment >= 32) {\r
654 BitsOfAlignment = 0;\r
655 }\r
d1c561f9 656\r
b9a44dca 657 BaseAddress = mResAperture[0][0].MemLimit;\r
9595e3cd 658 Status = gDS->AllocateMemorySpace (\r
b9a44dca 659 EfiGcdAllocateMaxAddressSearchTopDown,\r
d1c561f9 660 EfiGcdMemoryTypeMemoryMappedIo,\r
9595e3cd
LE
661 BitsOfAlignment,\r
662 AddrLen,\r
663 &BaseAddress,\r
664 mDriverImageHandle,\r
665 NULL\r
666 );\r
d1c561f9 667\r
9595e3cd
LE
668 if (!EFI_ERROR (Status)) {\r
669 // We were able to allocate the PCI memory\r
670 RootBridgeInstance->ResAllocNode[Index].Base = (UINTN)BaseAddress;\r
671 RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated;\r
d1c561f9 672\r
9595e3cd
LE
673 } else {\r
674 // Not able to allocate enough PCI memory\r
d1c561f9
OM
675 ReturnStatus = Status;\r
676\r
9595e3cd
LE
677 if (Status != EFI_OUT_OF_RESOURCES) {\r
678 RootBridgeInstance->ResAllocNode[Index].Length = 0;\r
d1c561f9 679 }\r
9595e3cd
LE
680 ASSERT (FALSE);\r
681 }\r
682 break;\r
d1c561f9
OM
683\r
684 case TypePMem32:\r
685 case TypeMem64:\r
9595e3cd
LE
686 case TypePMem64:\r
687 ReturnStatus = EFI_ABORTED;\r
d1c561f9 688 break;\r
9595e3cd
LE
689 default:\r
690 ASSERT (FALSE);\r
691 break;\r
692 }; //end switch\r
693 }\r
694 }\r
d1c561f9 695\r
9595e3cd
LE
696 List = List->ForwardLink;\r
697 }\r
d1c561f9 698\r
9595e3cd 699 return ReturnStatus;\r
9595e3cd
LE
700 } else {\r
701 return EFI_NOT_READY;\r
702 }\r
9595e3cd
LE
703\r
704 case EfiPciHostBridgeSetResources:\r
705 break;\r
706\r
707 case EfiPciHostBridgeFreeResources:\r
708 ReturnStatus = EFI_SUCCESS;\r
709 List = HostBridgeInstance->Head.ForwardLink;\r
710 while (List != &HostBridgeInstance->Head) {\r
711 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
712 for (Index = TypeIo; Index < TypeBus; Index++) {\r
713 if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) {\r
714 AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;\r
715 BaseAddress = RootBridgeInstance->ResAllocNode[Index].Base;\r
716 switch (Index) {\r
717\r
d1c561f9
OM
718 case TypeIo:\r
719 Status = gDS->FreeIoSpace (BaseAddress, AddrLen);\r
9595e3cd
LE
720 if (EFI_ERROR (Status)) {\r
721 ReturnStatus = Status;\r
722 }\r
723 break;\r
724\r
725 case TypeMem32:\r
726 Status = gDS->FreeMemorySpace (BaseAddress, AddrLen);\r
727 if (EFI_ERROR (Status)) {\r
728 ReturnStatus = Status;\r
729 }\r
730 break;\r
731\r
732 case TypePMem32:\r
733 break;\r
734\r
735 case TypeMem64:\r
736 break;\r
737\r
738 case TypePMem64:\r
d1c561f9 739 break;\r
9595e3cd
LE
740\r
741 default:\r
742 ASSERT (FALSE);\r
743 break;\r
744\r
745 }; //end switch\r
746 RootBridgeInstance->ResAllocNode[Index].Type = Index;\r
747 RootBridgeInstance->ResAllocNode[Index].Base = 0;\r
748 RootBridgeInstance->ResAllocNode[Index].Length = 0;\r
749 RootBridgeInstance->ResAllocNode[Index].Status = ResNone;\r
750 }\r
751 }\r
d1c561f9 752\r
9595e3cd
LE
753 List = List->ForwardLink;\r
754 }\r
d1c561f9 755\r
9595e3cd 756 HostBridgeInstance->ResourceSubmited = FALSE;\r
d1c561f9 757 HostBridgeInstance->CanRestarted = TRUE;\r
9595e3cd
LE
758 return ReturnStatus;\r
759\r
760 case EfiPciHostBridgeEndResourceAllocation:\r
761 HostBridgeInstance->CanRestarted = FALSE;\r
762 break;\r
763\r
764 default:\r
765 return EFI_INVALID_PARAMETER;\r
766 }\r
d1c561f9
OM
767\r
768 return EFI_SUCCESS;\r
9595e3cd
LE
769}\r
770\r
771/**\r
772 Return the device handle of the next PCI root bridge that is associated with this Host Bridge.\r
773\r
774 This function is called multiple times to retrieve the device handles of all the PCI root bridges that\r
775 are associated with this PCI host bridge. Each PCI host bridge is associated with one or more PCI\r
776 root bridges. On each call, the handle that was returned by the previous call is passed into the\r
777 interface, and on output the interface returns the device handle of the next PCI root bridge. The\r
778 caller can use the handle to obtain the instance of the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL\r
779 for that root bridge. When there are no more PCI root bridges to report, the interface returns\r
780 EFI_NOT_FOUND. A PCI enumerator must enumerate the PCI root bridges in the order that they\r
781 are returned by this function.\r
782 For D945 implementation, there is only one root bridge in PCI host bridge.\r
783\r
784 @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
785 @param[in, out] RootBridgeHandle Returns the device handle of the next PCI root bridge.\r
d1c561f9 786\r
9595e3cd 787 @retval EFI_SUCCESS If parameter RootBridgeHandle = NULL, then return the first Rootbridge handle of the\r
d1c561f9 788 specific Host bridge and return EFI_SUCCESS.\r
9595e3cd
LE
789 @retval EFI_NOT_FOUND Can not find the any more root bridge in specific host bridge.\r
790 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not an EFI_HANDLE that was\r
791 returned on a previous call to GetNextRootBridge().\r
792**/\r
793EFI_STATUS\r
794EFIAPI\r
795GetNextRootBridge(\r
796 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
797 IN OUT EFI_HANDLE *RootBridgeHandle\r
798 )\r
799{\r
d1c561f9
OM
800 BOOLEAN NoRootBridge;\r
801 LIST_ENTRY *List;\r
9595e3cd
LE
802 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;\r
803 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
d1c561f9 804\r
9595e3cd
LE
805 NoRootBridge = TRUE;\r
806 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);\r
807 List = HostBridgeInstance->Head.ForwardLink;\r
d1c561f9
OM
808\r
809\r
9595e3cd
LE
810 while (List != &HostBridgeInstance->Head) {\r
811 NoRootBridge = FALSE;\r
812 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
813 if (*RootBridgeHandle == NULL) {\r
814 //\r
815 // Return the first Root Bridge Handle of the Host Bridge\r
816 //\r
817 *RootBridgeHandle = RootBridgeInstance->Handle;\r
818 return EFI_SUCCESS;\r
819 } else {\r
820 if (*RootBridgeHandle == RootBridgeInstance->Handle) {\r
821 //\r
822 // Get next if have\r
823 //\r
824 List = List->ForwardLink;\r
825 if (List!=&HostBridgeInstance->Head) {\r
826 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
827 *RootBridgeHandle = RootBridgeInstance->Handle;\r
d1c561f9 828 return EFI_SUCCESS;\r
9595e3cd
LE
829 } else {\r
830 return EFI_NOT_FOUND;\r
831 }\r
832 }\r
833 }\r
d1c561f9 834\r
9595e3cd
LE
835 List = List->ForwardLink;\r
836 } //end while\r
d1c561f9 837\r
9595e3cd
LE
838 if (NoRootBridge) {\r
839 return EFI_NOT_FOUND;\r
840 } else {\r
841 return EFI_INVALID_PARAMETER;\r
842 }\r
843}\r
844\r
845/**\r
846 Returns the allocation attributes of a PCI root bridge.\r
847\r
848 The function returns the allocation attributes of a specific PCI root bridge. The attributes can vary\r
849 from one PCI root bridge to another. These attributes are different from the decode-related\r
850 attributes that are returned by the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.GetAttributes() member function. The\r
851 RootBridgeHandle parameter is used to specify the instance of the PCI root bridge. The device\r
852 handles of all the root bridges that are associated with this host bridge must be obtained by calling\r
853 GetNextRootBridge(). The attributes are static in the sense that they do not change during or\r
854 after the enumeration process. The hardware may provide mechanisms to change the attributes on\r
d1c561f9 855 the fly, but such changes must be completed before EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is\r
9595e3cd
LE
856 installed. The permitted values of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTES are defined in\r
857 "Related Definitions" below. The caller uses these attributes to combine multiple resource requests.\r
d1c561f9
OM
858 For example, if the flag EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM is set, the PCI bus enumerator needs to\r
859 include requests for the prefetchable memory in the nonprefetchable memory pool and not request any\r
9595e3cd
LE
860 prefetchable memory.\r
861 Attribute Description\r
862 ------------------------------------ ----------------------------------------------------------------------\r
863 EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM If this bit is set, then the PCI root bridge does not support separate\r
864 windows for nonprefetchable and prefetchable memory. A PCI bus\r
865 driver needs to include requests for prefetchable memory in the\r
866 nonprefetchable memory pool.\r
867\r
868 EFI_PCI_HOST_BRIDGE_MEM64_DECODE If this bit is set, then the PCI root bridge supports 64-bit memory\r
869 windows. If this bit is not set, the PCI bus driver needs to include\r
870 requests for a 64-bit memory address in the corresponding 32-bit\r
871 memory pool.\r
872\r
873 @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
874 @param[in] RootBridgeHandle The device handle of the PCI root bridge in which the caller is interested. Type\r
875 EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification.\r
876 @param[out] Attributes The pointer to attribte of root bridge, it is output parameter\r
d1c561f9 877\r
9595e3cd
LE
878 @retval EFI_INVALID_PARAMETER Attribute pointer is NULL\r
879 @retval EFI_INVALID_PARAMETER RootBridgehandle is invalid.\r
880 @retval EFI_SUCCESS Success to get attribute of interested root bridge.\r
881\r
882**/\r
883EFI_STATUS\r
884EFIAPI\r
885GetAttributes(\r
886 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
887 IN EFI_HANDLE RootBridgeHandle,\r
888 OUT UINT64 *Attributes\r
889 )\r
890{\r
d1c561f9 891 LIST_ENTRY *List;\r
9595e3cd
LE
892 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;\r
893 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
d1c561f9 894\r
9595e3cd
LE
895 if (Attributes == NULL) {\r
896 return EFI_INVALID_PARAMETER;\r
897 }\r
d1c561f9 898\r
9595e3cd
LE
899 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);\r
900 List = HostBridgeInstance->Head.ForwardLink;\r
d1c561f9 901\r
9595e3cd
LE
902 while (List != &HostBridgeInstance->Head) {\r
903 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
904 if (RootBridgeHandle == RootBridgeInstance->Handle) {\r
905 *Attributes = RootBridgeInstance->RootBridgeAttrib;\r
906 return EFI_SUCCESS;\r
907 }\r
908 List = List->ForwardLink;\r
909 }\r
d1c561f9 910\r
9595e3cd 911 //\r
d1c561f9 912 // RootBridgeHandle is not an EFI_HANDLE\r
9595e3cd
LE
913 // that was returned on a previous call to GetNextRootBridge()\r
914 //\r
915 return EFI_INVALID_PARAMETER;\r
916}\r
917\r
918/**\r
919 Sets up the specified PCI root bridge for the bus enumeration process.\r
920\r
921 This member function sets up the root bridge for bus enumeration and returns the PCI bus range\r
922 over which the search should be performed in ACPI 2.0 resource descriptor format.\r
923\r
924 @param[in] This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.\r
925 @param[in] RootBridgeHandle The PCI Root Bridge to be set up.\r
926 @param[out] Configuration Pointer to the pointer to the PCI bus resource descriptor.\r
d1c561f9 927\r
9595e3cd
LE
928 @retval EFI_INVALID_PARAMETER Invalid Root bridge's handle\r
929 @retval EFI_OUT_OF_RESOURCES Fail to allocate ACPI resource descriptor tag.\r
930 @retval EFI_SUCCESS Sucess to allocate ACPI resource descriptor.\r
931\r
932**/\r
933EFI_STATUS\r
934EFIAPI\r
935StartBusEnumeration(\r
936 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
937 IN EFI_HANDLE RootBridgeHandle,\r
938 OUT VOID **Configuration\r
939 )\r
940{\r
d1c561f9 941 LIST_ENTRY *List;\r
9595e3cd
LE
942 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;\r
943 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
944 VOID *Buffer;\r
945 UINT8 *Temp;\r
946 UINT64 BusStart;\r
947 UINT64 BusEnd;\r
d1c561f9 948\r
9595e3cd
LE
949 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);\r
950 List = HostBridgeInstance->Head.ForwardLink;\r
d1c561f9 951\r
9595e3cd
LE
952 while (List != &HostBridgeInstance->Head) {\r
953 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
954 if (RootBridgeHandle == RootBridgeInstance->Handle) {\r
955 //\r
956 // Set up the Root Bridge for Bus Enumeration\r
957 //\r
958 BusStart = RootBridgeInstance->BusBase;\r
959 BusEnd = RootBridgeInstance->BusLimit;\r
960 //\r
961 // Program the Hardware(if needed) if error return EFI_DEVICE_ERROR\r
962 //\r
d1c561f9 963\r
9595e3cd
LE
964 Buffer = AllocatePool (sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof(EFI_ACPI_END_TAG_DESCRIPTOR));\r
965 if (Buffer == NULL) {\r
966 return EFI_OUT_OF_RESOURCES;\r
967 }\r
d1c561f9 968\r
9595e3cd 969 Temp = (UINT8 *)Buffer;\r
d1c561f9 970\r
9595e3cd
LE
971 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Desc = 0x8A;\r
972 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Len = 0x2B;\r
973 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->ResType = 2;\r
d1c561f9 974 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->GenFlag = 0;\r
9595e3cd
LE
975 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->SpecificFlag = 0;\r
976 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrSpaceGranularity = 0;\r
977 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMin = BusStart;\r
978 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMax = 0;\r
d1c561f9 979 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrTranslationOffset = 0;\r
9595e3cd 980 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrLen = BusEnd - BusStart + 1;\r
d1c561f9 981\r
9595e3cd 982 Temp = Temp + sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
d1c561f9 983 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;\r
9595e3cd 984 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;\r
d1c561f9
OM
985\r
986 *Configuration = Buffer;\r
9595e3cd
LE
987 return EFI_SUCCESS;\r
988 }\r
989 List = List->ForwardLink;\r
990 }\r
d1c561f9 991\r
9595e3cd
LE
992 return EFI_INVALID_PARAMETER;\r
993}\r
994\r
995/**\r
996 Programs the PCI root bridge hardware so that it decodes the specified PCI bus range.\r
997\r
998 This member function programs the specified PCI root bridge to decode the bus range that is\r
999 specified by the input parameter Configuration.\r
1000 The bus range information is specified in terms of the ACPI 2.0 resource descriptor format.\r
1001\r
1002 @param[in] This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance\r
1003 @param[in] RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed\r
1004 @param[in] Configuration The pointer to the PCI bus resource descriptor\r
d1c561f9 1005\r
9595e3cd
LE
1006 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.\r
1007 @retval EFI_INVALID_PARAMETER Configuration is NULL.\r
1008 @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI 2.0 resource descriptor.\r
1009 @retval EFI_INVALID_PARAMETER Configuration does not include a valid ACPI 2.0 bus resource descriptor.\r
d1c561f9 1010 @retval EFI_INVALID_PARAMETER Configuration includes valid ACPI 2.0 resource descriptors other than\r
9595e3cd
LE
1011 bus descriptors.\r
1012 @retval EFI_INVALID_PARAMETER Configuration contains one or more invalid ACPI resource descriptors.\r
1013 @retval EFI_INVALID_PARAMETER "Address Range Minimum" is invalid for this root bridge.\r
1014 @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this root bridge.\r
1015 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.\r
1016 @retval EFI_SUCCESS The bus range for the PCI root bridge was programmed.\r
1017\r
1018**/\r
1019EFI_STATUS\r
1020EFIAPI\r
1021SetBusNumbers(\r
1022 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
1023 IN EFI_HANDLE RootBridgeHandle,\r
1024 IN VOID *Configuration\r
1025 )\r
1026{\r
d1c561f9 1027 LIST_ENTRY *List;\r
9595e3cd
LE
1028 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;\r
1029 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
1030 UINT8 *Ptr;\r
1031 UINTN BusStart;\r
1032 UINTN BusEnd;\r
1033 UINTN BusLen;\r
d1c561f9 1034\r
9595e3cd
LE
1035 if (Configuration == NULL) {\r
1036 return EFI_INVALID_PARAMETER;\r
1037 }\r
d1c561f9 1038\r
9595e3cd 1039 Ptr = Configuration;\r
d1c561f9 1040\r
9595e3cd
LE
1041 //\r
1042 // Check the Configuration is valid\r
1043 //\r
1044 if(*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
1045 return EFI_INVALID_PARAMETER;\r
1046 }\r
d1c561f9 1047\r
9595e3cd
LE
1048 if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType != 2) {\r
1049 return EFI_INVALID_PARAMETER;\r
1050 }\r
1051\r
1052 Ptr += sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
1053 if (*Ptr != ACPI_END_TAG_DESCRIPTOR) {\r
1054 return EFI_INVALID_PARAMETER;\r
1055 }\r
d1c561f9 1056\r
9595e3cd
LE
1057 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);\r
1058 List = HostBridgeInstance->Head.ForwardLink;\r
d1c561f9 1059\r
9595e3cd 1060 Ptr = Configuration;\r
d1c561f9 1061\r
9595e3cd
LE
1062 while (List != &HostBridgeInstance->Head) {\r
1063 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
1064 if (RootBridgeHandle == RootBridgeInstance->Handle) {\r
1065 BusStart = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMin;\r
1066 BusLen = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrLen;\r
1067 BusEnd = BusStart + BusLen - 1;\r
d1c561f9 1068\r
9595e3cd
LE
1069 if (BusStart > BusEnd) {\r
1070 return EFI_INVALID_PARAMETER;\r
1071 }\r
d1c561f9 1072\r
9595e3cd
LE
1073 if ((BusStart < RootBridgeInstance->BusBase) || (BusEnd > RootBridgeInstance->BusLimit)) {\r
1074 return EFI_INVALID_PARAMETER;\r
1075 }\r
d1c561f9 1076\r
9595e3cd
LE
1077 //\r
1078 // Update the Bus Range\r
1079 //\r
1080 RootBridgeInstance->ResAllocNode[TypeBus].Base = BusStart;\r
1081 RootBridgeInstance->ResAllocNode[TypeBus].Length = BusLen;\r
1082 RootBridgeInstance->ResAllocNode[TypeBus].Status = ResAllocated;\r
d1c561f9 1083\r
9595e3cd
LE
1084 //\r
1085 // Program the Root Bridge Hardware\r
1086 //\r
d1c561f9 1087\r
9595e3cd
LE
1088 return EFI_SUCCESS;\r
1089 }\r
d1c561f9 1090\r
9595e3cd
LE
1091 List = List->ForwardLink;\r
1092 }\r
d1c561f9 1093\r
9595e3cd
LE
1094 return EFI_INVALID_PARAMETER;\r
1095}\r
1096\r
1097\r
1098/**\r
1099 Submits the I/O and memory resource requirements for the specified PCI root bridge.\r
1100\r
1101 This function is used to submit all the I/O and memory resources that are required by the specified\r
1102 PCI root bridge. The input parameter Configuration is used to specify the following:\r
1103 - The various types of resources that are required\r
1104 - The associated lengths in terms of ACPI 2.0 resource descriptor format\r
1105\r
1106 @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.\r
1107 @param[in] RootBridgeHandle The PCI root bridge whose I/O and memory resource requirements are being submitted.\r
1108 @param[in] Configuration The pointer to the PCI I/O and PCI memory resource descriptor.\r
d1c561f9 1109\r
9595e3cd
LE
1110 @retval EFI_SUCCESS The I/O and memory resource requests for a PCI root bridge were accepted.\r
1111 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.\r
1112 @retval EFI_INVALID_PARAMETER Configuration is NULL.\r
1113 @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI 2.0 resource descriptor.\r
d1c561f9
OM
1114 @retval EFI_INVALID_PARAMETER Configuration includes requests for one or more resource types that are\r
1115 not supported by this PCI root bridge. This error will happen if the caller\r
9595e3cd
LE
1116 did not combine resources according to Attributes that were returned by\r
1117 GetAllocAttributes().\r
1118 @retval EFI_INVALID_PARAMETER Address Range Maximum" is invalid.\r
1119 @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this PCI root bridge.\r
1120 @retval EFI_INVALID_PARAMETER "Address Space Granularity" is invalid for this PCI root bridge.\r
1121\r
1122**/\r
1123EFI_STATUS\r
1124EFIAPI\r
1125SubmitResources(\r
1126 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
1127 IN EFI_HANDLE RootBridgeHandle,\r
1128 IN VOID *Configuration\r
1129 )\r
1130{\r
d1c561f9 1131 LIST_ENTRY *List;\r
9595e3cd
LE
1132 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;\r
1133 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
1134 UINT8 *Temp;\r
1135 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
1136 UINT64 AddrLen;\r
1137 UINT64 Alignment;\r
d1c561f9 1138\r
9595e3cd
LE
1139 //\r
1140 // Check the input parameter: Configuration\r
1141 //\r
1142 if (Configuration == NULL) {\r
1143 return EFI_INVALID_PARAMETER;\r
1144 }\r
d1c561f9 1145\r
9595e3cd
LE
1146 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);\r
1147 List = HostBridgeInstance->Head.ForwardLink;\r
d1c561f9 1148\r
9595e3cd 1149 Temp = (UINT8 *)Configuration;\r
d1c561f9 1150 while ( *Temp == 0x8A) {\r
9595e3cd
LE
1151 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;\r
1152 }\r
1153 if (*Temp != 0x79) {\r
1154 return EFI_INVALID_PARAMETER;\r
1155 }\r
d1c561f9 1156\r
9595e3cd
LE
1157 Temp = (UINT8 *)Configuration;\r
1158 while (List != &HostBridgeInstance->Head) {\r
1159 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
1160 if (RootBridgeHandle == RootBridgeInstance->Handle) {\r
1a1d6376
LE
1161 for (;\r
1162 *Temp == 0x8A;\r
1163 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR)\r
1164 ) {\r
9595e3cd
LE
1165 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ;\r
1166\r
1167 //\r
1168 // Check Address Length\r
1169 //\r
1a1d6376
LE
1170 if (Ptr->AddrLen == 0) {\r
1171 HostBridgeInstance->ResourceSubmited = TRUE;\r
1172 continue;\r
1173 }\r
9595e3cd
LE
1174 if (Ptr->AddrLen > 0xffffffff) {\r
1175 return EFI_INVALID_PARAMETER;\r
1176 }\r
1177\r
1178 //\r
1179 // Check address range alignment\r
1180 //\r
1181 if (Ptr->AddrRangeMax >= 0xffffffff || Ptr->AddrRangeMax != (GetPowerOfTwo64 (Ptr->AddrRangeMax + 1) - 1)) {\r
1182 return EFI_INVALID_PARAMETER;\r
1183 }\r
d1c561f9 1184\r
9595e3cd
LE
1185 switch (Ptr->ResType) {\r
1186\r
1187 case 0:\r
d1c561f9 1188\r
9595e3cd
LE
1189 //\r
1190 // Check invalid Address Sapce Granularity\r
1191 //\r
1192 if (Ptr->AddrSpaceGranularity != 32) {\r
1193 return EFI_INVALID_PARAMETER;\r
1194 }\r
d1c561f9 1195\r
9595e3cd
LE
1196 //\r
1197 // check the memory resource request is supported by PCI root bridge\r
1198 //\r
1199 if (RootBridgeInstance->RootBridgeAttrib == EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM &&\r
1200 Ptr->SpecificFlag == 0x06) {\r
1201 return EFI_INVALID_PARAMETER;\r
1202 }\r
d1c561f9 1203\r
9595e3cd
LE
1204 AddrLen = Ptr->AddrLen;\r
1205 Alignment = Ptr->AddrRangeMax;\r
1206 if (Ptr->AddrSpaceGranularity == 32) {\r
1207 if (Ptr->SpecificFlag == 0x06) {\r
1208 //\r
1209 // Apply from GCD\r
1210 //\r
1211 RootBridgeInstance->ResAllocNode[TypePMem32].Status = ResSubmitted;\r
1212 } else {\r
1213 RootBridgeInstance->ResAllocNode[TypeMem32].Length = AddrLen;\r
1214 RootBridgeInstance->ResAllocNode[TypeMem32].Alignment = Alignment;\r
d1c561f9 1215 RootBridgeInstance->ResAllocNode[TypeMem32].Status = ResRequested;\r
9595e3cd
LE
1216 HostBridgeInstance->ResourceSubmited = TRUE;\r
1217 }\r
1218 }\r
1219\r
1220 if (Ptr->AddrSpaceGranularity == 64) {\r
1221 if (Ptr->SpecificFlag == 0x06) {\r
1222 RootBridgeInstance->ResAllocNode[TypePMem64].Status = ResSubmitted;\r
1223 } else {\r
1224 RootBridgeInstance->ResAllocNode[TypeMem64].Status = ResSubmitted;\r
1225 }\r
1226 }\r
1227 break;\r
1228\r
1229 case 1:\r
1230 AddrLen = (UINTN) Ptr->AddrLen;\r
1231 Alignment = (UINTN) Ptr->AddrRangeMax;\r
1232 RootBridgeInstance->ResAllocNode[TypeIo].Length = AddrLen;\r
1233 RootBridgeInstance->ResAllocNode[TypeIo].Alignment = Alignment;\r
1234 RootBridgeInstance->ResAllocNode[TypeIo].Status = ResRequested;\r
d1c561f9 1235 HostBridgeInstance->ResourceSubmited = TRUE;\r
9595e3cd
LE
1236 break;\r
1237\r
1238 default:\r
1239 break;\r
1240 };\r
d1c561f9
OM
1241 }\r
1242\r
9595e3cd
LE
1243 return EFI_SUCCESS;\r
1244 }\r
d1c561f9 1245\r
9595e3cd
LE
1246 List = List->ForwardLink;\r
1247 }\r
d1c561f9 1248\r
9595e3cd
LE
1249 return EFI_INVALID_PARAMETER;\r
1250}\r
1251\r
1252/**\r
1253 Returns the proposed resource settings for the specified PCI root bridge.\r
1254\r
1255 This member function returns the proposed resource settings for the specified PCI root bridge. The\r
1256 proposed resource settings are prepared when NotifyPhase() is called with a Phase of\r
1257 EfiPciHostBridgeAllocateResources. The output parameter Configuration\r
1258 specifies the following:\r
1259 - The various types of resources, excluding bus resources, that are allocated\r
1260 - The associated lengths in terms of ACPI 2.0 resource descriptor format\r
1261\r
1262 @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.\r
1263 @param[in] RootBridgeHandle The PCI root bridge handle. Type EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification.\r
1264 @param[out] Configuration The pointer to the pointer to the PCI I/O and memory resource descriptor.\r
d1c561f9 1265\r
9595e3cd
LE
1266 @retval EFI_SUCCESS The requested parameters were returned.\r
1267 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.\r
1268 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.\r
1269 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
1270\r
1271**/\r
1272EFI_STATUS\r
1273EFIAPI\r
1274GetProposedResources(\r
1275 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
1276 IN EFI_HANDLE RootBridgeHandle,\r
1277 OUT VOID **Configuration\r
1278 )\r
1279{\r
d1c561f9 1280 LIST_ENTRY *List;\r
9595e3cd
LE
1281 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;\r
1282 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
1283 UINTN Index;\r
d1c561f9
OM
1284 UINTN Number;\r
1285 VOID *Buffer;\r
9595e3cd
LE
1286 UINT8 *Temp;\r
1287 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
1288 UINT64 ResStatus;\r
d1c561f9 1289\r
9595e3cd
LE
1290 Buffer = NULL;\r
1291 Number = 0;\r
1292 //\r
1293 // Get the Host Bridge Instance from the resource allocation protocol\r
1294 //\r
1295 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);\r
1296 List = HostBridgeInstance->Head.ForwardLink;\r
d1c561f9 1297\r
9595e3cd
LE
1298 //\r
1299 // Enumerate the root bridges in this host bridge\r
1300 //\r
1301 while (List != &HostBridgeInstance->Head) {\r
1302 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
1303 if (RootBridgeHandle == RootBridgeInstance->Handle) {\r
1304 for (Index = 0; Index < TypeBus; Index ++) {\r
1305 if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {\r
1306 Number ++;\r
d1c561f9 1307 }\r
9595e3cd 1308 }\r
d1c561f9 1309\r
9595e3cd 1310 if (Number == 0) {\r
e5ceb6c9
LE
1311 EFI_ACPI_END_TAG_DESCRIPTOR *End;\r
1312\r
1313 End = AllocateZeroPool (sizeof *End);\r
1314 if (End == NULL) {\r
1315 return EFI_OUT_OF_RESOURCES;\r
1316 }\r
1317 End->Desc = ACPI_END_TAG_DESCRIPTOR;\r
1318 *Configuration = End;\r
1319 return EFI_SUCCESS;\r
9595e3cd
LE
1320 }\r
1321\r
1322 Buffer = AllocateZeroPool (Number * sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof(EFI_ACPI_END_TAG_DESCRIPTOR));\r
1323 if (Buffer == NULL) {\r
1324 return EFI_OUT_OF_RESOURCES;\r
1325 }\r
d1c561f9 1326\r
9595e3cd
LE
1327 Temp = Buffer;\r
1328 for (Index = 0; Index < TypeBus; Index ++) {\r
1329 if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {\r
1330 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ;\r
1331 ResStatus = RootBridgeInstance->ResAllocNode[Index].Status;\r
d1c561f9 1332\r
9595e3cd
LE
1333 switch (Index) {\r
1334\r
1335 case TypeIo:\r
1336 //\r
1337 // Io\r
1338 //\r
1339 Ptr->Desc = 0x8A;\r
1340 Ptr->Len = 0x2B;\r
1341 Ptr->ResType = 1;\r
d1c561f9 1342 Ptr->GenFlag = 0;\r
9595e3cd
LE
1343 Ptr->SpecificFlag = 0;\r
1344 Ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;\r
1345 Ptr->AddrRangeMax = 0;\r
1346 Ptr->AddrTranslationOffset = \\r
1347 (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;\r
1348 Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;\r
1349 break;\r
1350\r
1351 case TypeMem32:\r
1352 //\r
1353 // Memory 32\r
d1c561f9 1354 //\r
9595e3cd
LE
1355 Ptr->Desc = 0x8A;\r
1356 Ptr->Len = 0x2B;\r
1357 Ptr->ResType = 0;\r
d1c561f9 1358 Ptr->GenFlag = 0;\r
9595e3cd
LE
1359 Ptr->SpecificFlag = 0;\r
1360 Ptr->AddrSpaceGranularity = 32;\r
1361 Ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;\r
1362 Ptr->AddrRangeMax = 0;\r
1363 Ptr->AddrTranslationOffset = \\r
d1c561f9 1364 (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;\r
9595e3cd
LE
1365 Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;\r
1366 break;\r
1367\r
1368 case TypePMem32:\r
1369 //\r
1370 // Prefetch memory 32\r
1371 //\r
1372 Ptr->Desc = 0x8A;\r
1373 Ptr->Len = 0x2B;\r
1374 Ptr->ResType = 0;\r
d1c561f9 1375 Ptr->GenFlag = 0;\r
9595e3cd
LE
1376 Ptr->SpecificFlag = 6;\r
1377 Ptr->AddrSpaceGranularity = 32;\r
1378 Ptr->AddrRangeMin = 0;\r
1379 Ptr->AddrRangeMax = 0;\r
d1c561f9 1380 Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;\r
9595e3cd
LE
1381 Ptr->AddrLen = 0;\r
1382 break;\r
1383\r
1384 case TypeMem64:\r
1385 //\r
1386 // Memory 64\r
1387 //\r
1388 Ptr->Desc = 0x8A;\r
1389 Ptr->Len = 0x2B;\r
1390 Ptr->ResType = 0;\r
d1c561f9 1391 Ptr->GenFlag = 0;\r
9595e3cd
LE
1392 Ptr->SpecificFlag = 0;\r
1393 Ptr->AddrSpaceGranularity = 64;\r
1394 Ptr->AddrRangeMin = 0;\r
1395 Ptr->AddrRangeMax = 0;\r
d1c561f9 1396 Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;\r
9595e3cd
LE
1397 Ptr->AddrLen = 0;\r
1398 break;\r
1399\r
1400 case TypePMem64:\r
1401 //\r
1402 // Prefetch memory 64\r
1403 //\r
1404 Ptr->Desc = 0x8A;\r
1405 Ptr->Len = 0x2B;\r
1406 Ptr->ResType = 0;\r
d1c561f9 1407 Ptr->GenFlag = 0;\r
9595e3cd
LE
1408 Ptr->SpecificFlag = 6;\r
1409 Ptr->AddrSpaceGranularity = 64;\r
1410 Ptr->AddrRangeMin = 0;\r
1411 Ptr->AddrRangeMax = 0;\r
d1c561f9 1412 Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;\r
9595e3cd
LE
1413 Ptr->AddrLen = 0;\r
1414 break;\r
1415 };\r
d1c561f9 1416\r
9595e3cd 1417 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
d1c561f9 1418 }\r
9595e3cd 1419 }\r
d1c561f9
OM
1420\r
1421 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;\r
9595e3cd 1422 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;\r
d1c561f9
OM
1423\r
1424 *Configuration = Buffer;\r
1425\r
9595e3cd
LE
1426 return EFI_SUCCESS;\r
1427 }\r
d1c561f9 1428\r
9595e3cd
LE
1429 List = List->ForwardLink;\r
1430 }\r
d1c561f9 1431\r
9595e3cd
LE
1432 return EFI_INVALID_PARAMETER;\r
1433}\r
1434\r
1435/**\r
1436 Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various\r
1437 stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual\r
1438 PCI controllers before enumeration.\r
1439\r
1440 This function is called during the PCI enumeration process. No specific action is expected from this\r
1441 member function. It allows the host bridge driver to preinitialize individual PCI controllers before\r
1442 enumeration.\r
1443\r
1444 @param This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.\r
1445 @param RootBridgeHandle The associated PCI root bridge handle. Type EFI_HANDLE is defined in\r
1446 InstallProtocolInterface() in the UEFI 2.0 Specification.\r
1447 @param PciAddress The address of the PCI device on the PCI bus. This address can be passed to the\r
1448 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL member functions to access the PCI\r
1449 configuration space of the device. See Table 12-1 in the UEFI 2.0 Specification for\r
1450 the definition of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS.\r
d1c561f9
OM
1451 @param Phase The phase of the PCI device enumeration.\r
1452\r
9595e3cd
LE
1453 @retval EFI_SUCCESS The requested parameters were returned.\r
1454 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.\r
1455 @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined in\r
1456 EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.\r
1457 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. The PCI enumerator should\r
1458 not enumerate this device, including its child devices if it is a PCI-to-PCI\r
1459 bridge.\r
1460\r
1461**/\r
1462EFI_STATUS\r
1463EFIAPI\r
1464PreprocessController (\r
1465 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,\r
1466 IN EFI_HANDLE RootBridgeHandle,\r
1467 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,\r
1468 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase\r
1469 )\r
1470{\r
1471 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;\r
1472 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;\r
d1c561f9 1473 LIST_ENTRY *List;\r
9595e3cd
LE
1474\r
1475 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);\r
1476 List = HostBridgeInstance->Head.ForwardLink;\r
1477\r
1478 //\r
1479 // Enumerate the root bridges in this host bridge\r
1480 //\r
1481 while (List != &HostBridgeInstance->Head) {\r
1482 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);\r
1483 if (RootBridgeHandle == RootBridgeInstance->Handle) {\r
1484 break;\r
1485 }\r
1486 List = List->ForwardLink;\r
1487 }\r
1488 if (List == &HostBridgeInstance->Head) {\r
1489 return EFI_INVALID_PARAMETER;\r
1490 }\r
1491\r
1492 if ((UINT32)Phase > EfiPciBeforeResourceCollection) {\r
1493 return EFI_INVALID_PARAMETER;\r
1494 }\r
1495\r
1496 return EFI_SUCCESS;\r
1497}\r