]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciBusDxe / PciLib.c
CommitLineData
9060e3ec 1/** @file\r
2 Internal library implementation for PCI Bus module.\r
3\r
bd067178 4Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.<BR>\r
25a26646 5(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r
9d510e61 6SPDX-License-Identifier: BSD-2-Clause-Patent\r
9060e3ec 7\r
8**/\r
9\r
10#include "PciBus.h"\r
11\r
8db6a82c 12GLOBAL_REMOVE_IF_UNREFERENCED\r
1436aea4 13CHAR16 *mBarTypeStr[] = {\r
8db6a82c
RN
14 L"Unknow",\r
15 L" Io16",\r
16 L" Io32",\r
17 L" Mem32",\r
18 L"PMem32",\r
19 L" Mem64",\r
20 L"PMem64",\r
0176af14 21 L" OpRom",\r
8db6a82c
RN
22 L" Io",\r
23 L" Mem",\r
24 L"Unknow"\r
1436aea4 25};\r
9060e3ec 26\r
03ac238b
RN
27/**\r
28 Retrieve the max bus number that is assigned to the Root Bridge hierarchy.\r
29 It can support the case that there are multiple bus ranges.\r
30\r
31 @param Bridge Bridge device instance.\r
32\r
33 @retval The max bus number that is assigned to this Root Bridge hierarchy.\r
34\r
35**/\r
36UINT16\r
37PciGetMaxBusNumber (\r
1436aea4 38 IN PCI_IO_DEVICE *Bridge\r
03ac238b
RN
39 )\r
40{\r
41 PCI_IO_DEVICE *RootBridge;\r
42 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BusNumberRanges;\r
43 UINT64 MaxNumberInRange;\r
44\r
45 //\r
46 // Get PCI Root Bridge device\r
47 //\r
48 RootBridge = Bridge;\r
49 while (RootBridge->Parent != NULL) {\r
50 RootBridge = RootBridge->Parent;\r
51 }\r
1436aea4 52\r
03ac238b
RN
53 MaxNumberInRange = 0;\r
54 //\r
55 // Iterate the bus number ranges to get max PCI bus number\r
56 //\r
57 BusNumberRanges = RootBridge->BusNumberRanges;\r
58 while (BusNumberRanges->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
59 MaxNumberInRange = BusNumberRanges->AddrRangeMin + BusNumberRanges->AddrLen - 1;\r
60 BusNumberRanges++;\r
61 }\r
1436aea4
MK
62\r
63 return (UINT16)MaxNumberInRange;\r
03ac238b
RN
64}\r
65\r
9060e3ec 66/**\r
67 Retrieve the PCI Card device BAR information via PciIo interface.\r
68\r
69 @param PciIoDevice PCI Card device instance.\r
70\r
71**/\r
72VOID\r
73GetBackPcCardBar (\r
1436aea4 74 IN PCI_IO_DEVICE *PciIoDevice\r
9060e3ec 75 )\r
76{\r
77 UINT32 Address;\r
78\r
79 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
80 return;\r
81 }\r
82\r
83 //\r
84 // Read PciBar information from the bar register\r
85 //\r
86 if (!gFullEnumeration) {\r
87 Address = 0;\r
88 PciIoDevice->PciIo.Pci.Read (\r
89 &(PciIoDevice->PciIo),\r
90 EfiPciIoWidthUint32,\r
91 PCI_CARD_MEMORY_BASE_0,\r
92 1,\r
93 &Address\r
94 );\r
95\r
1436aea4
MK
96 (PciIoDevice->PciBar)[P2C_MEM_1].BaseAddress = (UINT64)(Address);\r
97 (PciIoDevice->PciBar)[P2C_MEM_1].Length = 0x2000000;\r
98 (PciIoDevice->PciBar)[P2C_MEM_1].BarType = PciBarTypeMem32;\r
9060e3ec 99\r
100 Address = 0;\r
101 PciIoDevice->PciIo.Pci.Read (\r
102 &(PciIoDevice->PciIo),\r
103 EfiPciIoWidthUint32,\r
104 PCI_CARD_MEMORY_BASE_1,\r
105 1,\r
106 &Address\r
107 );\r
1436aea4
MK
108 (PciIoDevice->PciBar)[P2C_MEM_2].BaseAddress = (UINT64)(Address);\r
109 (PciIoDevice->PciBar)[P2C_MEM_2].Length = 0x2000000;\r
110 (PciIoDevice->PciBar)[P2C_MEM_2].BarType = PciBarTypePMem32;\r
9060e3ec 111\r
112 Address = 0;\r
113 PciIoDevice->PciIo.Pci.Read (\r
114 &(PciIoDevice->PciIo),\r
115 EfiPciIoWidthUint32,\r
116 PCI_CARD_IO_BASE_0_LOWER,\r
117 1,\r
118 &Address\r
119 );\r
1436aea4 120 (PciIoDevice->PciBar)[P2C_IO_1].BaseAddress = (UINT64)(Address);\r
9060e3ec 121 (PciIoDevice->PciBar)[P2C_IO_1].Length = 0x100;\r
122 (PciIoDevice->PciBar)[P2C_IO_1].BarType = PciBarTypeIo16;\r
123\r
124 Address = 0;\r
125 PciIoDevice->PciIo.Pci.Read (\r
126 &(PciIoDevice->PciIo),\r
127 EfiPciIoWidthUint32,\r
128 PCI_CARD_IO_BASE_1_LOWER,\r
129 1,\r
130 &Address\r
131 );\r
1436aea4 132 (PciIoDevice->PciBar)[P2C_IO_2].BaseAddress = (UINT64)(Address);\r
9060e3ec 133 (PciIoDevice->PciBar)[P2C_IO_2].Length = 0x100;\r
134 (PciIoDevice->PciBar)[P2C_IO_2].BarType = PciBarTypeIo16;\r
9060e3ec 135 }\r
136\r
1436aea4 137 if ((gPciHotPlugInit != NULL) && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
9060e3ec 138 GetResourcePaddingForHpb (PciIoDevice);\r
139 }\r
140}\r
141\r
142/**\r
143 Remove rejected pci device from specific root bridge\r
144 handle.\r
145\r
146 @param RootBridgeHandle Specific parent root bridge handle.\r
147 @param Bridge Bridge device instance.\r
148\r
149**/\r
150VOID\r
151RemoveRejectedPciDevices (\r
1436aea4
MK
152 IN EFI_HANDLE RootBridgeHandle,\r
153 IN PCI_IO_DEVICE *Bridge\r
9060e3ec 154 )\r
155{\r
1436aea4
MK
156 PCI_IO_DEVICE *Temp;\r
157 LIST_ENTRY *CurrentLink;\r
158 LIST_ENTRY *LastLink;\r
9060e3ec 159\r
160 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
161 return;\r
162 }\r
163\r
164 CurrentLink = Bridge->ChildList.ForwardLink;\r
165\r
166 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
9060e3ec 167 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
168\r
169 if (IS_PCI_BRIDGE (&Temp->Pci)) {\r
170 //\r
171 // Remove rejected devices recusively\r
172 //\r
173 RemoveRejectedPciDevices (RootBridgeHandle, Temp);\r
174 } else {\r
175 //\r
176 // Skip rejection for all PPBs, while detect rejection for others\r
177 //\r
178 if (IsPciDeviceRejected (Temp)) {\r
9060e3ec 179 //\r
180 // For P2C, remove all devices on it\r
181 //\r
182 if (!IsListEmpty (&Temp->ChildList)) {\r
183 RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp);\r
184 }\r
185\r
186 //\r
187 // Finally remove itself\r
188 //\r
189 LastLink = CurrentLink->BackLink;\r
190 RemoveEntryList (CurrentLink);\r
191 FreePciDevice (Temp);\r
192\r
193 CurrentLink = LastLink;\r
194 }\r
195 }\r
196\r
197 CurrentLink = CurrentLink->ForwardLink;\r
198 }\r
199}\r
200\r
8db6a82c
RN
201/**\r
202 Dump the resourc map of the bridge device.\r
203\r
204 @param[in] BridgeResource Resource descriptor of the bridge device.\r
205**/\r
206VOID\r
207DumpBridgeResource (\r
1436aea4 208 IN PCI_RESOURCE_NODE *BridgeResource\r
8db6a82c
RN
209 )\r
210{\r
1436aea4
MK
211 LIST_ENTRY *Link;\r
212 PCI_RESOURCE_NODE *Resource;\r
213 PCI_BAR *Bar;\r
8db6a82c
RN
214\r
215 if ((BridgeResource != NULL) && (BridgeResource->Length != 0)) {\r
216 DEBUG ((\r
1436aea4
MK
217 DEBUG_INFO,\r
218 "Type = %s; Base = 0x%lx;\tLength = 0x%lx;\tAlignment = 0x%lx\n",\r
8db6a82c
RN
219 mBarTypeStr[MIN (BridgeResource->ResType, PciBarTypeMaxType)],\r
220 BridgeResource->PciDev->PciBar[BridgeResource->Bar].BaseAddress,\r
1436aea4
MK
221 BridgeResource->Length,\r
222 BridgeResource->Alignment\r
8db6a82c 223 ));\r
f67bd32d 224 for ( Link = GetFirstNode (&BridgeResource->ChildList)\r
1436aea4
MK
225 ; !IsNull (&BridgeResource->ChildList, Link)\r
226 ; Link = GetNextNode (&BridgeResource->ChildList, Link)\r
227 )\r
228 {\r
8db6a82c
RN
229 Resource = RESOURCE_NODE_FROM_LINK (Link);\r
230 if (Resource->ResourceUsage == PciResUsageTypical) {\r
231 Bar = Resource->Virtual ? Resource->PciDev->VfPciBar : Resource->PciDev->PciBar;\r
232 DEBUG ((\r
1436aea4
MK
233 DEBUG_INFO,\r
234 " Base = 0x%lx;\tLength = 0x%lx;\tAlignment = 0x%lx;\tOwner = %s [%02x|%02x|%02x:",\r
235 Bar[Resource->Bar].BaseAddress,\r
236 Resource->Length,\r
237 Resource->Alignment,\r
8db6a82c
RN
238 IS_PCI_BRIDGE (&Resource->PciDev->Pci) ? L"PPB" :\r
239 IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci) ? L"P2C" :\r
1436aea4
MK
240 L"PCI",\r
241 Resource->PciDev->BusNumber,\r
242 Resource->PciDev->DeviceNumber,\r
f67bd32d 243 Resource->PciDev->FunctionNumber\r
8db6a82c
RN
244 ));\r
245\r
246 if ((!IS_PCI_BRIDGE (&Resource->PciDev->Pci) && !IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci)) ||\r
247 (IS_PCI_BRIDGE (&Resource->PciDev->Pci) && (Resource->Bar < PPB_IO_RANGE)) ||\r
248 (IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci) && (Resource->Bar < P2C_MEM_1))\r
1436aea4
MK
249 )\r
250 {\r
8db6a82c
RN
251 //\r
252 // The resource requirement comes from the device itself.\r
253 //\r
87000d77 254 DEBUG ((DEBUG_INFO, "%02x]", Bar[Resource->Bar].Offset));\r
8db6a82c
RN
255 } else {\r
256 //\r
257 // The resource requirement comes from the subordinate devices.\r
258 //\r
87000d77 259 DEBUG ((DEBUG_INFO, "**]"));\r
8db6a82c
RN
260 }\r
261 } else {\r
87000d77 262 DEBUG ((DEBUG_INFO, " Base = Padding;\tLength = 0x%lx;\tAlignment = 0x%lx", Resource->Length, Resource->Alignment));\r
8db6a82c 263 }\r
1436aea4 264\r
f67bd32d 265 if (BridgeResource->ResType != Resource->ResType) {\r
87000d77 266 DEBUG ((DEBUG_INFO, "; Type = %s", mBarTypeStr[MIN (Resource->ResType, PciBarTypeMaxType)]));\r
f67bd32d 267 }\r
1436aea4 268\r
87000d77 269 DEBUG ((DEBUG_INFO, "\n"));\r
8db6a82c
RN
270 }\r
271 }\r
272}\r
273\r
274/**\r
275 Find the corresponding resource node for the Device in child list of BridgeResource.\r
d1102dba 276\r
f67bd32d
RN
277 @param[in] Device Pointer to PCI_IO_DEVICE.\r
278 @param[in] BridgeResource Pointer to PCI_RESOURCE_NODE.\r
279 @param[out] DeviceResources Pointer to a buffer to receive resources for the Device.\r
d1102dba 280\r
f67bd32d 281 @return Count of the resource descriptors returned.\r
8db6a82c 282**/\r
f67bd32d 283UINTN\r
8db6a82c 284FindResourceNode (\r
1436aea4
MK
285 IN PCI_IO_DEVICE *Device,\r
286 IN PCI_RESOURCE_NODE *BridgeResource,\r
287 OUT PCI_RESOURCE_NODE **DeviceResources OPTIONAL\r
8db6a82c
RN
288 )\r
289{\r
1436aea4
MK
290 LIST_ENTRY *Link;\r
291 PCI_RESOURCE_NODE *Resource;\r
292 UINTN Count;\r
8db6a82c 293\r
f67bd32d 294 Count = 0;\r
8db6a82c 295 for ( Link = BridgeResource->ChildList.ForwardLink\r
1436aea4
MK
296 ; Link != &BridgeResource->ChildList\r
297 ; Link = Link->ForwardLink\r
298 )\r
299 {\r
8db6a82c
RN
300 Resource = RESOURCE_NODE_FROM_LINK (Link);\r
301 if (Resource->PciDev == Device) {\r
f67bd32d
RN
302 if (DeviceResources != NULL) {\r
303 DeviceResources[Count] = Resource;\r
304 }\r
1436aea4 305\r
f67bd32d 306 Count++;\r
8db6a82c
RN
307 }\r
308 }\r
309\r
f67bd32d 310 return Count;\r
8db6a82c
RN
311}\r
312\r
313/**\r
314 Dump the resource map of all the devices under Bridge.\r
d1102dba 315\r
f67bd32d
RN
316 @param[in] Bridge Bridge device instance.\r
317 @param[in] Resources Resource descriptors for the bridge device.\r
318 @param[in] ResourceCount Count of resource descriptors.\r
8db6a82c
RN
319**/\r
320VOID\r
321DumpResourceMap (\r
1436aea4
MK
322 IN PCI_IO_DEVICE *Bridge,\r
323 IN PCI_RESOURCE_NODE **Resources,\r
324 IN UINTN ResourceCount\r
8db6a82c
RN
325 )\r
326{\r
1436aea4
MK
327 EFI_STATUS Status;\r
328 LIST_ENTRY *Link;\r
329 PCI_IO_DEVICE *Device;\r
330 UINTN Index;\r
331 CHAR16 *Str;\r
332 PCI_RESOURCE_NODE **ChildResources;\r
333 UINTN ChildResourceCount;\r
8db6a82c 334\r
87000d77 335 DEBUG ((DEBUG_INFO, "PciBus: Resource Map for "));\r
8db6a82c
RN
336\r
337 Status = gBS->OpenProtocol (\r
338 Bridge->Handle,\r
339 &gEfiPciRootBridgeIoProtocolGuid,\r
340 NULL,\r
341 NULL,\r
342 NULL,\r
343 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
344 );\r
345 if (EFI_ERROR (Status)) {\r
346 DEBUG ((\r
1436aea4
MK
347 DEBUG_INFO,\r
348 "Bridge [%02x|%02x|%02x]\n",\r
349 Bridge->BusNumber,\r
350 Bridge->DeviceNumber,\r
351 Bridge->FunctionNumber\r
8db6a82c
RN
352 ));\r
353 } else {\r
863986b3
RN
354 Str = ConvertDevicePathToText (\r
355 DevicePathFromHandle (Bridge->Handle),\r
356 FALSE,\r
357 FALSE\r
358 );\r
87000d77 359 DEBUG ((DEBUG_INFO, "Root Bridge %s\n", Str != NULL ? Str : L""));\r
8db6a82c
RN
360 if (Str != NULL) {\r
361 FreePool (Str);\r
362 }\r
363 }\r
364\r
f67bd32d
RN
365 for (Index = 0; Index < ResourceCount; Index++) {\r
366 DumpBridgeResource (Resources[Index]);\r
367 }\r
1436aea4 368\r
87000d77 369 DEBUG ((DEBUG_INFO, "\n"));\r
8db6a82c
RN
370\r
371 for ( Link = Bridge->ChildList.ForwardLink\r
1436aea4
MK
372 ; Link != &Bridge->ChildList\r
373 ; Link = Link->ForwardLink\r
374 )\r
375 {\r
8db6a82c
RN
376 Device = PCI_IO_DEVICE_FROM_LINK (Link);\r
377 if (IS_PCI_BRIDGE (&Device->Pci)) {\r
f67bd32d
RN
378 ChildResourceCount = 0;\r
379 for (Index = 0; Index < ResourceCount; Index++) {\r
380 ChildResourceCount += FindResourceNode (Device, Resources[Index], NULL);\r
381 }\r
1436aea4 382\r
f67bd32d
RN
383 ChildResources = AllocatePool (sizeof (PCI_RESOURCE_NODE *) * ChildResourceCount);\r
384 ASSERT (ChildResources != NULL);\r
385 ChildResourceCount = 0;\r
386 for (Index = 0; Index < ResourceCount; Index++) {\r
387 ChildResourceCount += FindResourceNode (Device, Resources[Index], &ChildResources[ChildResourceCount]);\r
388 }\r
389\r
390 DumpResourceMap (Device, ChildResources, ChildResourceCount);\r
391 FreePool (ChildResources);\r
8db6a82c
RN
392 }\r
393 }\r
394}\r
395\r
0785c619
LH
396/**\r
397 Adjust the Devices' BAR size to minimum value if it support Resizeable BAR capability.\r
398\r
399 @param RootBridgeDev Pointer to instance of PCI_IO_DEVICE..\r
400\r
401 @return TRUE if BAR size is adjusted.\r
402\r
403**/\r
404BOOLEAN\r
405AdjustPciDeviceBarSize (\r
1436aea4 406 IN PCI_IO_DEVICE *RootBridgeDev\r
0785c619
LH
407 )\r
408{\r
1436aea4
MK
409 PCI_IO_DEVICE *PciIoDevice;\r
410 LIST_ENTRY *CurrentLink;\r
411 BOOLEAN Adjusted;\r
412 UINTN Offset;\r
413 UINTN BarIndex;\r
0785c619
LH
414\r
415 Adjusted = FALSE;\r
416 CurrentLink = RootBridgeDev->ChildList.ForwardLink;\r
417\r
418 while (CurrentLink != NULL && CurrentLink != &RootBridgeDev->ChildList) {\r
419 PciIoDevice = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
420\r
421 if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {\r
422 if (AdjustPciDeviceBarSize (PciIoDevice)) {\r
423 Adjusted = TRUE;\r
424 }\r
425 } else {\r
426 if (PciIoDevice->ResizableBarOffset != 0) {\r
427 DEBUG ((\r
428 DEBUG_ERROR,\r
429 "PciBus: [%02x|%02x|%02x] Adjust Pci Device Bar Size\n",\r
1436aea4
MK
430 PciIoDevice->BusNumber,\r
431 PciIoDevice->DeviceNumber,\r
432 PciIoDevice->FunctionNumber\r
0785c619
LH
433 ));\r
434 PciProgramResizableBar (PciIoDevice, PciResizableBarMin);\r
435 //\r
436 // Start to parse the bars\r
437 //\r
438 for (Offset = 0x10, BarIndex = 0; Offset <= 0x24 && BarIndex < PCI_MAX_BAR; BarIndex++) {\r
439 Offset = PciParseBar (PciIoDevice, Offset, BarIndex);\r
440 }\r
1436aea4 441\r
0785c619 442 Adjusted = TRUE;\r
1436aea4
MK
443 DEBUG_CODE (\r
444 DumpPciBars (PciIoDevice);\r
445 );\r
0785c619
LH
446 }\r
447 }\r
448\r
449 CurrentLink = CurrentLink->ForwardLink;\r
450 }\r
451\r
452 return Adjusted;\r
453}\r
454\r
9060e3ec 455/**\r
456 Submits the I/O and memory resource requirements for the specified PCI Host Bridge.\r
457\r
458 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
459\r
460 @retval EFI_SUCCESS Successfully finished resource allocation.\r
461 @retval EFI_NOT_FOUND Cannot get root bridge instance.\r
462 @retval EFI_OUT_OF_RESOURCES Platform failed to program the resources if no hot plug supported.\r
463 @retval other Some error occurred when allocating resources for the PCI Host Bridge.\r
464\r
465 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.\r
466\r
467**/\r
468EFI_STATUS\r
469PciHostBridgeResourceAllocator (\r
1436aea4 470 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
9060e3ec 471 )\r
472{\r
473 PCI_IO_DEVICE *RootBridgeDev;\r
474 EFI_HANDLE RootBridgeHandle;\r
475 VOID *AcpiConfig;\r
476 EFI_STATUS Status;\r
477 UINT64 IoBase;\r
478 UINT64 Mem32Base;\r
479 UINT64 PMem32Base;\r
480 UINT64 Mem64Base;\r
481 UINT64 PMem64Base;\r
482 UINT64 IoResStatus;\r
483 UINT64 Mem32ResStatus;\r
484 UINT64 PMem32ResStatus;\r
485 UINT64 Mem64ResStatus;\r
486 UINT64 PMem64ResStatus;\r
1f6785c4 487 UINT32 MaxOptionRomSize;\r
9060e3ec 488 PCI_RESOURCE_NODE *IoBridge;\r
489 PCI_RESOURCE_NODE *Mem32Bridge;\r
490 PCI_RESOURCE_NODE *PMem32Bridge;\r
491 PCI_RESOURCE_NODE *Mem64Bridge;\r
492 PCI_RESOURCE_NODE *PMem64Bridge;\r
493 PCI_RESOURCE_NODE IoPool;\r
494 PCI_RESOURCE_NODE Mem32Pool;\r
495 PCI_RESOURCE_NODE PMem32Pool;\r
496 PCI_RESOURCE_NODE Mem64Pool;\r
497 PCI_RESOURCE_NODE PMem64Pool;\r
9060e3ec 498 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData;\r
499 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData;\r
0785c619
LH
500 BOOLEAN ResizableBarNeedAdjust;\r
501 BOOLEAN ResizableBarAdjusted;\r
502\r
503 ResizableBarNeedAdjust = PcdGetBool (PcdPcieResizableBarSupport);\r
9060e3ec 504\r
9060e3ec 505 //\r
506 // It may try several times if the resource allocation fails\r
507 //\r
508 while (TRUE) {\r
509 //\r
510 // Initialize resource pool\r
511 //\r
512 InitializeResourcePool (&IoPool, PciBarTypeIo16);\r
513 InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);\r
514 InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);\r
515 InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);\r
516 InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);\r
517\r
1436aea4
MK
518 RootBridgeDev = NULL;\r
519 RootBridgeHandle = 0;\r
9060e3ec 520\r
521 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
522 //\r
523 // Get Root Bridge Device by handle\r
524 //\r
525 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
526\r
527 if (RootBridgeDev == NULL) {\r
528 return EFI_NOT_FOUND;\r
529 }\r
530\r
531 //\r
532 // Create the entire system resource map from the information collected by\r
533 // enumerator. Several resource tree was created\r
534 //\r
535\r
1ef26783 536 //\r
ed356b9e 537 // If non-standard PCI Bridge I/O window alignment is supported,\r
1ef26783 538 // set I/O aligment to minimum possible alignment for root bridge.\r
539 //\r
9060e3ec 540 IoBridge = CreateResourceNode (\r
541 RootBridgeDev,\r
542 0,\r
1436aea4 543 FeaturePcdGet (PcdPciBridgeIoAlignmentProbe) ? 0x1FF : 0xFFF,\r
8db6a82c 544 RB_IO_RANGE,\r
9060e3ec 545 PciBarTypeIo16,\r
546 PciResUsageTypical\r
547 );\r
548\r
549 Mem32Bridge = CreateResourceNode (\r
550 RootBridgeDev,\r
551 0,\r
552 0xFFFFF,\r
8db6a82c 553 RB_MEM32_RANGE,\r
9060e3ec 554 PciBarTypeMem32,\r
555 PciResUsageTypical\r
556 );\r
557\r
558 PMem32Bridge = CreateResourceNode (\r
559 RootBridgeDev,\r
560 0,\r
561 0xFFFFF,\r
8db6a82c 562 RB_PMEM32_RANGE,\r
9060e3ec 563 PciBarTypePMem32,\r
564 PciResUsageTypical\r
565 );\r
566\r
567 Mem64Bridge = CreateResourceNode (\r
568 RootBridgeDev,\r
569 0,\r
570 0xFFFFF,\r
8db6a82c 571 RB_MEM64_RANGE,\r
9060e3ec 572 PciBarTypeMem64,\r
573 PciResUsageTypical\r
574 );\r
575\r
576 PMem64Bridge = CreateResourceNode (\r
577 RootBridgeDev,\r
578 0,\r
579 0xFFFFF,\r
8db6a82c 580 RB_PMEM64_RANGE,\r
9060e3ec 581 PciBarTypePMem64,\r
582 PciResUsageTypical\r
583 );\r
584\r
0176af14
RN
585 //\r
586 // Get the max ROM size that the root bridge can process\r
587 // Insert to resource map so that there will be dedicate MEM32 resource range for Option ROM.\r
588 // All devices' Option ROM share the same MEM32 resource.\r
589 //\r
590 MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);\r
736c436e
RN
591 if (MaxOptionRomSize != 0) {\r
592 RootBridgeDev->PciBar[0].BarType = PciBarTypeOpRom;\r
593 RootBridgeDev->PciBar[0].Length = MaxOptionRomSize;\r
594 RootBridgeDev->PciBar[0].Alignment = MaxOptionRomSize - 1;\r
595 GetResourceFromDevice (RootBridgeDev, IoBridge, Mem32Bridge, PMem32Bridge, Mem64Bridge, PMem64Bridge);\r
596 }\r
0176af14 597\r
9060e3ec 598 //\r
599 // Create resourcemap by going through all the devices subject to this root bridge\r
600 //\r
601 CreateResourceMap (\r
602 RootBridgeDev,\r
603 IoBridge,\r
604 Mem32Bridge,\r
605 PMem32Bridge,\r
606 Mem64Bridge,\r
607 PMem64Bridge\r
608 );\r
609\r
9060e3ec 610 //\r
2048c585 611 // Based on the all the resource tree, construct ACPI resource node to\r
9060e3ec 612 // submit the resource aperture to pci host bridge protocol\r
613 //\r
614 Status = ConstructAcpiResourceRequestor (\r
615 RootBridgeDev,\r
616 IoBridge,\r
617 Mem32Bridge,\r
618 PMem32Bridge,\r
619 Mem64Bridge,\r
620 PMem64Bridge,\r
621 &AcpiConfig\r
622 );\r
623\r
624 //\r
625 // Insert these resource nodes into the database\r
626 //\r
627 InsertResourceNode (&IoPool, IoBridge);\r
628 InsertResourceNode (&Mem32Pool, Mem32Bridge);\r
629 InsertResourceNode (&PMem32Pool, PMem32Bridge);\r
630 InsertResourceNode (&Mem64Pool, Mem64Bridge);\r
631 InsertResourceNode (&PMem64Pool, PMem64Bridge);\r
632\r
633 if (Status == EFI_SUCCESS) {\r
634 //\r
635 // Submit the resource requirement\r
636 //\r
637 Status = PciResAlloc->SubmitResources (\r
638 PciResAlloc,\r
639 RootBridgeDev->Handle,\r
640 AcpiConfig\r
641 );\r
724f26a9
RN
642 //\r
643 // If SubmitResources returns error, PciBus isn't able to start.\r
644 // It's a fatal error so assertion is added.\r
645 //\r
87000d77 646 DEBUG ((DEBUG_INFO, "PciBus: HostBridge->SubmitResources() - %r\n", Status));\r
724f26a9 647 ASSERT_EFI_ERROR (Status);\r
9060e3ec 648 }\r
649\r
650 //\r
651 // Free acpi resource node\r
652 //\r
653 if (AcpiConfig != NULL) {\r
654 FreePool (AcpiConfig);\r
655 }\r
656\r
657 if (EFI_ERROR (Status)) {\r
658 //\r
659 // Destroy all the resource tree\r
660 //\r
661 DestroyResourceTree (&IoPool);\r
662 DestroyResourceTree (&Mem32Pool);\r
663 DestroyResourceTree (&PMem32Pool);\r
664 DestroyResourceTree (&Mem64Pool);\r
665 DestroyResourceTree (&PMem64Pool);\r
666 return Status;\r
667 }\r
668 }\r
1436aea4 669\r
9060e3ec 670 //\r
671 // End while, at least one Root Bridge should be found.\r
672 //\r
673 ASSERT (RootBridgeDev != NULL);\r
674\r
675 //\r
676 // Notify platform to start to program the resource\r
677 //\r
678 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);\r
87000d77 679 DEBUG ((DEBUG_INFO, "PciBus: HostBridge->NotifyPhase(AllocateResources) - %r\n", Status));\r
9060e3ec 680 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
681 //\r
682 // If Hot Plug is not supported\r
683 //\r
684 if (EFI_ERROR (Status)) {\r
685 //\r
686 // Allocation failed, then return\r
687 //\r
688 return EFI_OUT_OF_RESOURCES;\r
689 }\r
1436aea4 690\r
9060e3ec 691 //\r
692 // Allocation succeed.\r
693 // Get host bridge handle for status report, and then skip the main while\r
694 //\r
695 HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;\r
696\r
697 break;\r
9060e3ec 698 } else {\r
699 //\r
700 // If Hot Plug is supported\r
701 //\r
702 if (!EFI_ERROR (Status)) {\r
703 //\r
704 // Allocation succeed, then continue the following\r
705 //\r
706 break;\r
707 }\r
708\r
709 //\r
710 // If the resource allocation is unsuccessful, free resources on bridge\r
711 //\r
712\r
1436aea4
MK
713 RootBridgeDev = NULL;\r
714 RootBridgeHandle = 0;\r
9060e3ec 715\r
1436aea4
MK
716 IoResStatus = EFI_RESOURCE_SATISFIED;\r
717 Mem32ResStatus = EFI_RESOURCE_SATISFIED;\r
718 PMem32ResStatus = EFI_RESOURCE_SATISFIED;\r
719 Mem64ResStatus = EFI_RESOURCE_SATISFIED;\r
720 PMem64ResStatus = EFI_RESOURCE_SATISFIED;\r
9060e3ec 721\r
722 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
723 //\r
724 // Get RootBridg Device by handle\r
725 //\r
726 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
727 if (RootBridgeDev == NULL) {\r
728 return EFI_NOT_FOUND;\r
729 }\r
730\r
731 //\r
732 // Get host bridge handle for status report\r
733 //\r
734 HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;\r
735\r
736 //\r
737 // Get acpi resource node for all the resource types\r
738 //\r
739 AcpiConfig = NULL;\r
740\r
741 Status = PciResAlloc->GetProposedResources (\r
742 PciResAlloc,\r
743 RootBridgeDev->Handle,\r
744 &AcpiConfig\r
745 );\r
746\r
747 if (EFI_ERROR (Status)) {\r
748 return Status;\r
749 }\r
750\r
751 if (AcpiConfig != NULL) {\r
752 //\r
753 // Adjust resource allocation policy for each RB\r
754 //\r
755 GetResourceAllocationStatus (\r
756 AcpiConfig,\r
757 &IoResStatus,\r
758 &Mem32ResStatus,\r
759 &PMem32ResStatus,\r
760 &Mem64ResStatus,\r
761 &PMem64ResStatus\r
762 );\r
763 FreePool (AcpiConfig);\r
764 }\r
765 }\r
1436aea4 766\r
9060e3ec 767 //\r
768 // End while\r
769 //\r
770\r
771 //\r
772 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code\r
773 //\r
774 //\r
775 // It is very difficult to follow the spec here\r
776 // Device path , Bar index can not be get here\r
777 //\r
778 ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));\r
779\r
780 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
1436aea4
MK
781 EFI_PROGRESS_CODE,\r
782 EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,\r
783 (VOID *)&AllocFailExtendedData,\r
784 sizeof (AllocFailExtendedData)\r
785 );\r
9060e3ec 786\r
1436aea4
MK
787 //\r
788 // When resource conflict happens, adjust the BAR size first.\r
789 // Only when adjusting BAR size doesn't help or BAR size cannot be adjusted,\r
790 // reject the device who requests largest resource that causes conflict.\r
791 //\r
0785c619
LH
792 ResizableBarAdjusted = FALSE;\r
793 if (ResizableBarNeedAdjust) {\r
1436aea4 794 ResizableBarAdjusted = AdjustPciDeviceBarSize (RootBridgeDev);\r
0785c619
LH
795 ResizableBarNeedAdjust = FALSE;\r
796 }\r
1436aea4 797\r
0785c619
LH
798 if (!ResizableBarAdjusted) {\r
799 Status = PciHostBridgeAdjustAllocation (\r
1436aea4
MK
800 &IoPool,\r
801 &Mem32Pool,\r
802 &PMem32Pool,\r
803 &Mem64Pool,\r
804 &PMem64Pool,\r
805 IoResStatus,\r
806 Mem32ResStatus,\r
807 PMem32ResStatus,\r
808 Mem64ResStatus,\r
809 PMem64ResStatus\r
810 );\r
0785c619 811 }\r
1436aea4 812\r
9060e3ec 813 //\r
814 // Destroy all the resource tree\r
815 //\r
816 DestroyResourceTree (&IoPool);\r
817 DestroyResourceTree (&Mem32Pool);\r
818 DestroyResourceTree (&PMem32Pool);\r
819 DestroyResourceTree (&Mem64Pool);\r
820 DestroyResourceTree (&PMem64Pool);\r
821\r
822 NotifyPhase (PciResAlloc, EfiPciHostBridgeFreeResources);\r
823\r
824 if (EFI_ERROR (Status)) {\r
825 return Status;\r
826 }\r
9060e3ec 827 }\r
828 }\r
1436aea4 829\r
9060e3ec 830 //\r
831 // End main while\r
832 //\r
833\r
834 //\r
835 // Raise the EFI_IOB_PCI_RES_ALLOC status code\r
836 //\r
837 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
1436aea4
MK
838 EFI_PROGRESS_CODE,\r
839 EFI_IO_BUS_PCI | EFI_IOB_PCI_RES_ALLOC,\r
840 (VOID *)&HandleExtendedData,\r
841 sizeof (HandleExtendedData)\r
842 );\r
9060e3ec 843\r
844 //\r
845 // Notify pci bus driver starts to program the resource\r
846 //\r
ea8d98fa
OM
847 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);\r
848\r
849 if (EFI_ERROR (Status)) {\r
850 return Status;\r
851 }\r
9060e3ec 852\r
1436aea4 853 RootBridgeDev = NULL;\r
9060e3ec 854\r
1436aea4 855 RootBridgeHandle = 0;\r
9060e3ec 856\r
857 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
858 //\r
859 // Get RootBridg Device by handle\r
860 //\r
861 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
862\r
863 if (RootBridgeDev == NULL) {\r
864 return EFI_NOT_FOUND;\r
865 }\r
866\r
867 //\r
868 // Get acpi resource node for all the resource types\r
869 //\r
870 AcpiConfig = NULL;\r
1436aea4
MK
871 Status = PciResAlloc->GetProposedResources (\r
872 PciResAlloc,\r
873 RootBridgeDev->Handle,\r
874 &AcpiConfig\r
875 );\r
9060e3ec 876\r
877 if (EFI_ERROR (Status)) {\r
878 return Status;\r
879 }\r
880\r
881 //\r
882 // Get the resource base by interpreting acpi resource node\r
883 //\r
884 //\r
885 GetResourceBase (\r
886 AcpiConfig,\r
887 &IoBase,\r
888 &Mem32Base,\r
889 &PMem32Base,\r
890 &Mem64Base,\r
891 &PMem64Base\r
892 );\r
893\r
9060e3ec 894 //\r
895 // Create the entire system resource map from the information collected by\r
896 // enumerator. Several resource tree was created\r
897 //\r
f67bd32d
RN
898 FindResourceNode (RootBridgeDev, &IoPool, &IoBridge);\r
899 FindResourceNode (RootBridgeDev, &Mem32Pool, &Mem32Bridge);\r
900 FindResourceNode (RootBridgeDev, &PMem32Pool, &PMem32Bridge);\r
901 FindResourceNode (RootBridgeDev, &Mem64Pool, &Mem64Bridge);\r
902 FindResourceNode (RootBridgeDev, &PMem64Pool, &PMem64Bridge);\r
9060e3ec 903\r
9995c2e5
RN
904 ASSERT (IoBridge != NULL);\r
905 ASSERT (Mem32Bridge != NULL);\r
906 ASSERT (PMem32Bridge != NULL);\r
907 ASSERT (Mem64Bridge != NULL);\r
908 ASSERT (PMem64Bridge != NULL);\r
909\r
9060e3ec 910 //\r
911 // Program IO resources\r
912 //\r
913 ProgramResource (\r
914 IoBase,\r
915 IoBridge\r
916 );\r
917\r
918 //\r
919 // Program Mem32 resources\r
920 //\r
921 ProgramResource (\r
922 Mem32Base,\r
923 Mem32Bridge\r
924 );\r
925\r
926 //\r
927 // Program PMem32 resources\r
928 //\r
929 ProgramResource (\r
930 PMem32Base,\r
931 PMem32Bridge\r
932 );\r
933\r
934 //\r
935 // Program Mem64 resources\r
936 //\r
937 ProgramResource (\r
938 Mem64Base,\r
939 Mem64Bridge\r
940 );\r
941\r
942 //\r
943 // Program PMem64 resources\r
944 //\r
945 ProgramResource (\r
946 PMem64Base,\r
947 PMem64Bridge\r
948 );\r
949\r
0176af14
RN
950 //\r
951 // Process Option ROM for this root bridge after all BARs are programmed.\r
952 // The PPB's MEM32 RANGE BAR is re-programmed to the Option ROM BAR Base in order to\r
953 // shadow the Option ROM of the devices under the PPB.\r
954 // After the shadow, Option ROM BAR decoding is turned off and the PPB's MEM32 RANGE\r
955 // BAR is restored back to the original value.\r
956 // The original value is programmed by ProgramResource() above.\r
957 //\r
958 DEBUG ((\r
1436aea4
MK
959 DEBUG_INFO,\r
960 "Process Option ROM: BAR Base/Length = %lx/%lx\n",\r
961 RootBridgeDev->PciBar[0].BaseAddress,\r
962 RootBridgeDev->PciBar[0].Length\r
0176af14
RN
963 ));\r
964 ProcessOptionRom (RootBridgeDev, RootBridgeDev->PciBar[0].BaseAddress, RootBridgeDev->PciBar[0].Length);\r
965\r
1436aea4
MK
966 IoBridge->PciDev->PciBar[IoBridge->Bar].BaseAddress = IoBase;\r
967 Mem32Bridge->PciDev->PciBar[Mem32Bridge->Bar].BaseAddress = Mem32Base;\r
8db6a82c 968 PMem32Bridge->PciDev->PciBar[PMem32Bridge->Bar].BaseAddress = PMem32Base;\r
1436aea4 969 Mem64Bridge->PciDev->PciBar[Mem64Bridge->Bar].BaseAddress = Mem64Base;\r
8db6a82c
RN
970 PMem64Bridge->PciDev->PciBar[PMem64Bridge->Bar].BaseAddress = PMem64Base;\r
971\r
972 //\r
973 // Dump the resource map for current root bridge\r
974 //\r
975 DEBUG_CODE (\r
f67bd32d
RN
976 PCI_RESOURCE_NODE *Resources[5];\r
977 Resources[0] = IoBridge;\r
978 Resources[1] = Mem32Bridge;\r
979 Resources[2] = PMem32Bridge;\r
980 Resources[3] = Mem64Bridge;\r
981 Resources[4] = PMem64Bridge;\r
0781e85f 982 DumpResourceMap (RootBridgeDev, Resources, ARRAY_SIZE (Resources));\r
1436aea4 983 );\r
8db6a82c 984\r
9060e3ec 985 FreePool (AcpiConfig);\r
986 }\r
987\r
988 //\r
989 // Destroy all the resource tree\r
990 //\r
991 DestroyResourceTree (&IoPool);\r
992 DestroyResourceTree (&Mem32Pool);\r
993 DestroyResourceTree (&PMem32Pool);\r
994 DestroyResourceTree (&Mem64Pool);\r
995 DestroyResourceTree (&PMem64Pool);\r
996\r
997 //\r
998 // Notify the resource allocation phase is to end\r
999 //\r
ea8d98fa 1000 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);\r
9060e3ec 1001\r
ea8d98fa 1002 return Status;\r
9060e3ec 1003}\r
1004\r
306bbe82 1005/**\r
1006 Allocate NumberOfBuses buses and return the next available PCI bus number.\r
1007\r
1008 @param Bridge Bridge device instance.\r
1009 @param StartBusNumber Current available PCI bus number.\r
1010 @param NumberOfBuses Number of buses enumerated below the StartBusNumber.\r
1011 @param NextBusNumber Next available PCI bus number.\r
1012\r
1013 @retval EFI_SUCCESS Available bus number resource is enough. Next available PCI bus number\r
1014 is returned in NextBusNumber.\r
1015 @retval EFI_OUT_OF_RESOURCES Available bus number resource is not enough for allocation.\r
1016\r
1017**/\r
1018EFI_STATUS\r
1019PciAllocateBusNumber (\r
1436aea4
MK
1020 IN PCI_IO_DEVICE *Bridge,\r
1021 IN UINT8 StartBusNumber,\r
1022 IN UINT8 NumberOfBuses,\r
1023 OUT UINT8 *NextBusNumber\r
306bbe82 1024 )\r
1025{\r
1026 PCI_IO_DEVICE *RootBridge;\r
1027 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BusNumberRanges;\r
1028 UINT8 NextNumber;\r
1029 UINT64 MaxNumberInRange;\r
1030\r
1031 //\r
1032 // Get PCI Root Bridge device\r
1033 //\r
1034 RootBridge = Bridge;\r
1035 while (RootBridge->Parent != NULL) {\r
1036 RootBridge = RootBridge->Parent;\r
1037 }\r
1038\r
1039 //\r
1040 // Get next available PCI bus number\r
1041 //\r
1042 BusNumberRanges = RootBridge->BusNumberRanges;\r
1043 while (BusNumberRanges->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
1044 MaxNumberInRange = BusNumberRanges->AddrRangeMin + BusNumberRanges->AddrLen - 1;\r
1436aea4 1045 if ((StartBusNumber >= BusNumberRanges->AddrRangeMin) && (StartBusNumber <= MaxNumberInRange)) {\r
50bdaa05 1046 NextNumber = (UINT8)(StartBusNumber + NumberOfBuses);\r
306bbe82 1047 while (NextNumber > MaxNumberInRange) {\r
1048 ++BusNumberRanges;\r
1049 if (BusNumberRanges->Desc == ACPI_END_TAG_DESCRIPTOR) {\r
1050 return EFI_OUT_OF_RESOURCES;\r
1051 }\r
1436aea4
MK
1052\r
1053 NextNumber = (UINT8)(NextNumber + (BusNumberRanges->AddrRangeMin - (MaxNumberInRange + 1)));\r
306bbe82 1054 MaxNumberInRange = BusNumberRanges->AddrRangeMin + BusNumberRanges->AddrLen - 1;\r
1055 }\r
1436aea4 1056\r
306bbe82 1057 *NextBusNumber = NextNumber;\r
1058 return EFI_SUCCESS;\r
1059 }\r
1436aea4 1060\r
306bbe82 1061 BusNumberRanges++;\r
1062 }\r
1436aea4 1063\r
306bbe82 1064 return EFI_OUT_OF_RESOURCES;\r
1065}\r
1066\r
9060e3ec 1067/**\r
1068 Scan pci bus and assign bus number to the given PCI bus system.\r
1069\r
1070 @param Bridge Bridge device instance.\r
1071 @param StartBusNumber start point.\r
1072 @param SubBusNumber Point to sub bus number.\r
1073 @param PaddedBusRange Customized bus number.\r
1074\r
1075 @retval EFI_SUCCESS Successfully scanned and assigned bus number.\r
1076 @retval other Some error occurred when scanning pci bus.\r
1077\r
1078 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.\r
1079\r
1080**/\r
1081EFI_STATUS\r
1082PciScanBus (\r
1436aea4
MK
1083 IN PCI_IO_DEVICE *Bridge,\r
1084 IN UINT8 StartBusNumber,\r
1085 OUT UINT8 *SubBusNumber,\r
1086 OUT UINT8 *PaddedBusRange\r
9060e3ec 1087 )\r
1088{\r
1436aea4
MK
1089 EFI_STATUS Status;\r
1090 PCI_TYPE00 Pci;\r
1091 UINT8 Device;\r
1092 UINT8 Func;\r
1093 UINT64 Address;\r
1094 UINT8 SecondBus;\r
1095 UINT8 PaddedSubBus;\r
1096 UINT16 Register;\r
1097 UINTN HpIndex;\r
1098 PCI_IO_DEVICE *PciDevice;\r
1099 EFI_EVENT Event;\r
1100 EFI_HPC_STATE State;\r
1101 UINT64 PciAddress;\r
1102 EFI_HPC_PADDING_ATTRIBUTES Attributes;\r
1103 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
1104 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *NextDescriptors;\r
1105 UINT16 BusRange;\r
1106 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1107 BOOLEAN BusPadding;\r
1108 UINT32 TempReservedBusNum;\r
8fc06b6e 1109 BOOLEAN IsAriEnabled;\r
9060e3ec 1110\r
1111 PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
1112 SecondBus = 0;\r
1113 Register = 0;\r
1114 State = 0;\r
1436aea4 1115 Attributes = (EFI_HPC_PADDING_ATTRIBUTES)0;\r
9060e3ec 1116 BusRange = 0;\r
1117 BusPadding = FALSE;\r
1118 PciDevice = NULL;\r
1119 PciAddress = 0;\r
8fc06b6e 1120 IsAriEnabled = FALSE;\r
9060e3ec 1121\r
1122 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
8fc06b6e
FN
1123 if (!IsAriEnabled) {\r
1124 TempReservedBusNum = 0;\r
1125 }\r
1126\r
9060e3ec 1127 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
9060e3ec 1128 //\r
1129 // Check to see whether a pci device is present\r
1130 //\r
1131 Status = PciDevicePresent (\r
1436aea4
MK
1132 PciRootBridgeIo,\r
1133 &Pci,\r
1134 StartBusNumber,\r
1135 Device,\r
1136 Func\r
1137 );\r
9060e3ec 1138\r
1436aea4 1139 if (EFI_ERROR (Status) && (Func == 0)) {\r
25a26646
JS
1140 //\r
1141 // go to next device if there is no Function 0\r
1142 //\r
1143 break;\r
1144 }\r
1145\r
9060e3ec 1146 if (EFI_ERROR (Status)) {\r
9060e3ec 1147 continue;\r
1148 }\r
1149\r
d4048391 1150 //\r
1151 // Get the PCI device information\r
1152 //\r
1153 Status = PciSearchDevice (\r
1436aea4
MK
1154 Bridge,\r
1155 &Pci,\r
1156 StartBusNumber,\r
1157 Device,\r
1158 Func,\r
1159 &PciDevice\r
1160 );\r
9060e3ec 1161\r
995d8b85
JY
1162 if (EFI_ERROR (Status)) {\r
1163 continue;\r
1164 }\r
9060e3ec 1165\r
8fc06b6e
FN
1166 //\r
1167 // Per Pcie spec ARI Extended Capability\r
1168 // This capability must be implemented by each function in an ARI device.\r
1169 // It is not applicable to a Root Port, a Switch Downstream Port, an RCiEP, or a Root Complex Event Collector\r
1170 //\r
1171 if (((Device == 0) && (Func == 0)) && (PciDevice->IsAriEnabled)) {\r
1172 IsAriEnabled = TRUE;\r
1173 }\r
1174\r
1175 if (PciDevice->IsAriEnabled != IsAriEnabled) {\r
1176 DEBUG ((\r
1177 DEBUG_ERROR,\r
1178 "ERROR: %02x:%02x:%02x device ARI Feature(%x) is not consistent with others Function\n",\r
1179 StartBusNumber,\r
1180 Device,\r
1181 Func,\r
1182 PciDevice->IsAriEnabled\r
1183 ));\r
1184 return EFI_DEVICE_ERROR;\r
1185 }\r
1186\r
d4048391 1187 PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);\r
9060e3ec 1188\r
d4048391 1189 if (!IS_PCI_BRIDGE (&Pci)) {\r
1190 //\r
1191 // PCI bridges will be called later\r
1192 // Here just need for PCI device or PCI to cardbus controller\r
1193 // EfiPciBeforeChildBusEnumeration for PCI Device Node\r
1194 //\r
1195 PreprocessController (\r
1436aea4
MK
1196 PciDevice,\r
1197 PciDevice->BusNumber,\r
1198 PciDevice->DeviceNumber,\r
1199 PciDevice->FunctionNumber,\r
1200 EfiPciBeforeChildBusEnumeration\r
1201 );\r
d4048391 1202 }\r
9060e3ec 1203\r
d4048391 1204 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
9060e3ec 1205 //\r
1206 // For Pci Hotplug controller devcie only\r
1207 //\r
1208 if (gPciHotPlugInit != NULL) {\r
1209 //\r
1210 // Check if it is a Hotplug PCI controller\r
1211 //\r
1212 if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) {\r
55565b08 1213 gPciRootHpcData[HpIndex].Found = TRUE;\r
9060e3ec 1214\r
1215 if (!gPciRootHpcData[HpIndex].Initialized) {\r
9060e3ec 1216 Status = CreateEventForHpc (HpIndex, &Event);\r
1217\r
1218 ASSERT (!EFI_ERROR (Status));\r
1219\r
1220 Status = gPciHotPlugInit->InitializeRootHpc (\r
1221 gPciHotPlugInit,\r
1222 gPciRootHpcPool[HpIndex].HpcDevicePath,\r
1223 PciAddress,\r
1224 Event,\r
1225 &State\r
1226 );\r
1227\r
1228 PreprocessController (\r
1229 PciDevice,\r
1230 PciDevice->BusNumber,\r
1231 PciDevice->DeviceNumber,\r
1232 PciDevice->FunctionNumber,\r
1233 EfiPciBeforeChildBusEnumeration\r
1436aea4 1234 );\r
9060e3ec 1235 }\r
1236 }\r
1237 }\r
1238 }\r
1239\r
1240 if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {\r
1241 //\r
1242 // For PPB\r
1243 //\r
2603fce1 1244 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
9060e3ec 1245 //\r
1246 // If Hot Plug is supported,\r
1247 // Get the bridge information\r
1248 //\r
1249 BusPadding = FALSE;\r
1250 if (gPciHotPlugInit != NULL) {\r
cbbccf3c 1251 if (IsPciHotPlugBus (PciDevice)) {\r
9060e3ec 1252 //\r
1253 // If it is initialized, get the padded bus range\r
1254 //\r
1255 Status = gPciHotPlugInit->GetResourcePadding (\r
1256 gPciHotPlugInit,\r
cbbccf3c 1257 PciDevice->DevicePath,\r
9060e3ec 1258 PciAddress,\r
1259 &State,\r
1436aea4 1260 (VOID **)&Descriptors,\r
9060e3ec 1261 &Attributes\r
1262 );\r
1263\r
1264 if (EFI_ERROR (Status)) {\r
1265 return Status;\r
1266 }\r
1267\r
1436aea4 1268 BusRange = 0;\r
fff2623c 1269 NextDescriptors = Descriptors;\r
1436aea4
MK
1270 Status = PciGetBusRange (\r
1271 &NextDescriptors,\r
1272 NULL,\r
1273 NULL,\r
1274 &BusRange\r
1275 );\r
9060e3ec 1276\r
1277 FreePool (Descriptors);\r
1278\r
ada38584
RN
1279 if (!EFI_ERROR (Status)) {\r
1280 BusPadding = TRUE;\r
1281 } else if (Status != EFI_NOT_FOUND) {\r
1282 //\r
1283 // EFI_NOT_FOUND is not a real error. It indicates no bus number padding requested.\r
1284 //\r
1285 return Status;\r
2e94e412 1286 }\r
9060e3ec 1287 }\r
1288 }\r
1289 }\r
1290\r
306bbe82 1291 Status = PciAllocateBusNumber (Bridge, *SubBusNumber, 1, SubBusNumber);\r
1292 if (EFI_ERROR (Status)) {\r
1293 return Status;\r
9060e3ec 1294 }\r
1436aea4 1295\r
9060e3ec 1296 SecondBus = *SubBusNumber;\r
1297\r
1436aea4
MK
1298 Register = (UINT16)((SecondBus << 8) | (UINT16)StartBusNumber);\r
1299 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET);\r
9060e3ec 1300\r
1301 Status = PciRootBridgeIo->Pci.Write (\r
1302 PciRootBridgeIo,\r
1303 EfiPciWidthUint16,\r
1304 Address,\r
1305 1,\r
1306 &Register\r
1307 );\r
1308\r
9060e3ec 1309 //\r
1310 // If it is PPB, resursively search down this bridge\r
1311 //\r
1312 if (IS_PCI_BRIDGE (&Pci)) {\r
9060e3ec 1313 //\r
1314 // Temporarily initialize SubBusNumber to maximum bus number to ensure the\r
1315 // PCI configuration transaction to go through any PPB\r
1316 //\r
1436aea4
MK
1317 Register = PciGetMaxBusNumber (Bridge);\r
1318 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);\r
1319 Status = PciRootBridgeIo->Pci.Write (\r
1320 PciRootBridgeIo,\r
1321 EfiPciWidthUint8,\r
1322 Address,\r
1323 1,\r
1324 &Register\r
1325 );\r
9060e3ec 1326\r
1327 //\r
1328 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige\r
1329 //\r
1330 PreprocessController (\r
1331 PciDevice,\r
1332 PciDevice->BusNumber,\r
1333 PciDevice->DeviceNumber,\r
1334 PciDevice->FunctionNumber,\r
1335 EfiPciBeforeChildBusEnumeration\r
1336 );\r
1337\r
9060e3ec 1338 Status = PciScanBus (\r
1436aea4
MK
1339 PciDevice,\r
1340 SecondBus,\r
1341 SubBusNumber,\r
1342 PaddedBusRange\r
1343 );\r
9060e3ec 1344 if (EFI_ERROR (Status)) {\r
1345 return Status;\r
1346 }\r
1347 }\r
1348\r
1349 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport) && BusPadding) {\r
1350 //\r
1351 // Ensure the device is enabled and initialized\r
1352 //\r
1353 if ((Attributes == EfiPaddingPciRootBridge) &&\r
1436aea4
MK
1354 ((State & EFI_HPC_STATE_ENABLED) != 0) &&\r
1355 ((State & EFI_HPC_STATE_INITIALIZED) != 0))\r
1356 {\r
1357 *PaddedBusRange = (UINT8)((UINT8)(BusRange) + *PaddedBusRange);\r
9060e3ec 1358 } else {\r
c7e7613e
RN
1359 //\r
1360 // Reserve the larger one between the actual occupied bus number and padded bus number\r
1361 //\r
1436aea4 1362 Status = PciAllocateBusNumber (PciDevice, SecondBus, (UINT8)(BusRange), &PaddedSubBus);\r
306bbe82 1363 if (EFI_ERROR (Status)) {\r
1364 return Status;\r
1365 }\r
1436aea4 1366\r
c7e7613e 1367 *SubBusNumber = MAX (PaddedSubBus, *SubBusNumber);\r
9060e3ec 1368 }\r
1369 }\r
1370\r
1371 //\r
1372 // Set the current maximum bus number under the PPB\r
1373 //\r
1374 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);\r
1375\r
1376 Status = PciRootBridgeIo->Pci.Write (\r
1377 PciRootBridgeIo,\r
1378 EfiPciWidthUint8,\r
1379 Address,\r
1380 1,\r
1381 SubBusNumber\r
1382 );\r
1436aea4 1383 } else {\r
9060e3ec 1384 //\r
1385 // It is device. Check PCI IOV for Bus reservation\r
9060e3ec 1386 // Go through each function, just reserve the MAX ReservedBusNum for one device\r
1387 //\r
1436aea4 1388 if (PcdGetBool (PcdSrIovSupport) && (PciDevice->SrIovCapabilityOffset != 0)) {\r
9060e3ec 1389 if (TempReservedBusNum < PciDevice->ReservedBusNum) {\r
1436aea4 1390 Status = PciAllocateBusNumber (PciDevice, *SubBusNumber, (UINT8)(PciDevice->ReservedBusNum - TempReservedBusNum), SubBusNumber);\r
306bbe82 1391 if (EFI_ERROR (Status)) {\r
1392 return Status;\r
1393 }\r
1436aea4 1394\r
9060e3ec 1395 TempReservedBusNum = PciDevice->ReservedBusNum;\r
1396\r
1397 if (Func == 0) {\r
87000d77 1398 DEBUG ((DEBUG_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x\n", *SubBusNumber));\r
9060e3ec 1399 } else {\r
87000d77 1400 DEBUG ((DEBUG_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x (Update)\n", *SubBusNumber));\r
9060e3ec 1401 }\r
1402 }\r
1403 }\r
1404 }\r
1405\r
1436aea4 1406 if ((Func == 0) && !IS_PCI_MULTI_FUNC (&Pci)) {\r
9060e3ec 1407 //\r
1408 // Skip sub functions, this is not a multi function device\r
1409 //\r
1410\r
1411 Func = PCI_MAX_FUNC;\r
1412 }\r
1413 }\r
1414 }\r
1415\r
1416 return EFI_SUCCESS;\r
1417}\r
1418\r
1419/**\r
1420 Process Option Rom on the specified root bridge.\r
1421\r
1422 @param Bridge Pci root bridge device instance.\r
1423\r
1424 @retval EFI_SUCCESS Success process.\r
1425 @retval other Some error occurred when processing Option Rom on the root bridge.\r
1426\r
1427**/\r
1428EFI_STATUS\r
1429PciRootBridgeP2CProcess (\r
1436aea4 1430 IN PCI_IO_DEVICE *Bridge\r
9060e3ec 1431 )\r
1432{\r
1436aea4
MK
1433 LIST_ENTRY *CurrentLink;\r
1434 PCI_IO_DEVICE *Temp;\r
1435 EFI_HPC_STATE State;\r
1436 UINT64 PciAddress;\r
1437 EFI_STATUS Status;\r
9060e3ec 1438\r
1439 CurrentLink = Bridge->ChildList.ForwardLink;\r
1440\r
1441 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
9060e3ec 1442 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
1443\r
1444 if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {\r
1436aea4 1445 if ((gPciHotPlugInit != NULL) && Temp->Allocated && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
9060e3ec 1446 //\r
1447 // Raise the EFI_IOB_PCI_HPC_INIT status code\r
1448 //\r
1449 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1450 EFI_PROGRESS_CODE,\r
fe91c992 1451 EFI_IO_BUS_PCI | EFI_IOB_PCI_HPC_INIT,\r
9060e3ec 1452 Temp->DevicePath\r
1453 );\r
1454\r
1455 PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);\r
1436aea4
MK
1456 Status = gPciHotPlugInit->InitializeRootHpc (\r
1457 gPciHotPlugInit,\r
1458 Temp->DevicePath,\r
1459 PciAddress,\r
1460 NULL,\r
1461 &State\r
1462 );\r
9060e3ec 1463\r
1464 if (!EFI_ERROR (Status)) {\r
1465 Status = PciBridgeEnumerator (Temp);\r
1466\r
1467 if (EFI_ERROR (Status)) {\r
1468 return Status;\r
1469 }\r
1470 }\r
1471\r
1472 CurrentLink = CurrentLink->ForwardLink;\r
1473 continue;\r
9060e3ec 1474 }\r
1475 }\r
1476\r
1477 if (!IsListEmpty (&Temp->ChildList)) {\r
1478 Status = PciRootBridgeP2CProcess (Temp);\r
1479 }\r
1480\r
1481 CurrentLink = CurrentLink->ForwardLink;\r
1482 }\r
1483\r
1484 return EFI_SUCCESS;\r
1485}\r
1486\r
1487/**\r
1488 Process Option Rom on the specified host bridge.\r
1489\r
1490 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
1491\r
1492 @retval EFI_SUCCESS Success process.\r
1493 @retval EFI_NOT_FOUND Can not find the root bridge instance.\r
1494 @retval other Some error occurred when processing Option Rom on the host bridge.\r
1495\r
1496**/\r
1497EFI_STATUS\r
1498PciHostBridgeP2CProcess (\r
1436aea4 1499 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
9060e3ec 1500 )\r
1501{\r
1436aea4
MK
1502 EFI_HANDLE RootBridgeHandle;\r
1503 PCI_IO_DEVICE *RootBridgeDev;\r
1504 EFI_STATUS Status;\r
9060e3ec 1505\r
1506 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1507 return EFI_SUCCESS;\r
1508 }\r
1509\r
1510 RootBridgeHandle = NULL;\r
1511\r
1512 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
9060e3ec 1513 //\r
1514 // Get RootBridg Device by handle\r
1515 //\r
1516 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
1517\r
1518 if (RootBridgeDev == NULL) {\r
1519 return EFI_NOT_FOUND;\r
1520 }\r
1521\r
1522 Status = PciRootBridgeP2CProcess (RootBridgeDev);\r
1523 if (EFI_ERROR (Status)) {\r
1524 return Status;\r
1525 }\r
9060e3ec 1526 }\r
1527\r
1528 return EFI_SUCCESS;\r
1529}\r
1530\r
1531/**\r
1532 This function is used to enumerate the entire host bridge\r
1533 in a given platform.\r
1534\r
1535 @param PciResAlloc A pointer to the PCI Host Resource Allocation protocol.\r
1536\r
1537 @retval EFI_SUCCESS Successfully enumerated the host bridge.\r
1538 @retval EFI_OUT_OF_RESOURCES No enough memory available.\r
1539 @retval other Some error occurred when enumerating the host bridge.\r
1540\r
1541**/\r
1542EFI_STATUS\r
1543PciHostBridgeEnumerator (\r
1544 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
1545 )\r
1546{\r
1436aea4
MK
1547 EFI_HANDLE RootBridgeHandle;\r
1548 PCI_IO_DEVICE *RootBridgeDev;\r
1549 EFI_STATUS Status;\r
1550 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1551 UINT16 MinBus;\r
1552 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
1553 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;\r
1554 UINT8 StartBusNumber;\r
1555 LIST_ENTRY RootBridgeList;\r
1556 LIST_ENTRY *Link;\r
bd067178 1557 EFI_STATUS RootBridgeEnumerationStatus;\r
9060e3ec 1558\r
1559 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1560 InitializeHotPlugSupport ();\r
1561 }\r
1562\r
1563 InitializeListHead (&RootBridgeList);\r
1564\r
1565 //\r
1566 // Notify the bus allocation phase is about to start\r
1567 //\r
ea8d98fa
OM
1568 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
1569\r
1570 if (EFI_ERROR (Status)) {\r
1571 return Status;\r
1572 }\r
9060e3ec 1573\r
1436aea4 1574 DEBUG ((DEBUG_INFO, "PCI Bus First Scanning\n"));\r
bd067178
FN
1575 RootBridgeHandle = NULL;\r
1576 RootBridgeEnumerationStatus = EFI_SUCCESS;\r
9060e3ec 1577 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
9060e3ec 1578 //\r
1579 // if a root bridge instance is found, create root bridge device for it\r
1580 //\r
1581\r
1582 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1583\r
1584 if (RootBridgeDev == NULL) {\r
1585 return EFI_OUT_OF_RESOURCES;\r
1586 }\r
1587\r
1588 //\r
1589 // Enumerate all the buses under this root bridge\r
1590 //\r
1591 Status = PciRootBridgeEnumerator (\r
1436aea4
MK
1592 PciResAlloc,\r
1593 RootBridgeDev\r
1594 );\r
9060e3ec 1595\r
1436aea4 1596 if ((gPciHotPlugInit != NULL) && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
9060e3ec 1597 InsertTailList (&RootBridgeList, &(RootBridgeDev->Link));\r
1598 } else {\r
1599 DestroyRootBridge (RootBridgeDev);\r
1600 }\r
1436aea4 1601\r
9060e3ec 1602 if (EFI_ERROR (Status)) {\r
bd067178 1603 RootBridgeEnumerationStatus = Status;\r
9060e3ec 1604 }\r
1605 }\r
1606\r
1607 //\r
1608 // Notify the bus allocation phase is finished for the first time\r
1609 //\r
1610 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
1611\r
bd067178
FN
1612 if (EFI_ERROR (RootBridgeEnumerationStatus)) {\r
1613 return RootBridgeEnumerationStatus;\r
1614 }\r
1615\r
1436aea4 1616 if ((gPciHotPlugInit != NULL) && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
9060e3ec 1617 //\r
1618 // Reset all assigned PCI bus number in all PPB\r
1619 //\r
1620 RootBridgeHandle = NULL;\r
1436aea4 1621 Link = GetFirstNode (&RootBridgeList);\r
9060e3ec 1622 while ((PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) &&\r
1436aea4
MK
1623 (!IsNull (&RootBridgeList, Link)))\r
1624 {\r
9060e3ec 1625 RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (Link);\r
1626 //\r
1627 // Get the Bus information\r
1628 //\r
1629 Status = PciResAlloc->StartBusEnumeration (\r
1630 PciResAlloc,\r
1631 RootBridgeHandle,\r
1436aea4 1632 (VOID **)&Configuration\r
9060e3ec 1633 );\r
1634 if (EFI_ERROR (Status)) {\r
1635 return Status;\r
1636 }\r
1637\r
1638 //\r
1639 // Get the bus number to start with\r
1640 //\r
1436aea4 1641 StartBusNumber = (UINT8)(Configuration->AddrRangeMin);\r
9060e3ec 1642\r
1643 ResetAllPpbBusNumber (\r
1644 RootBridgeDev,\r
1645 StartBusNumber\r
1436aea4 1646 );\r
9060e3ec 1647\r
1648 FreePool (Configuration);\r
8063b47b 1649 Link = RemoveEntryList (Link);\r
9060e3ec 1650 DestroyRootBridge (RootBridgeDev);\r
1651 }\r
1652\r
1653 //\r
1654 // Wait for all HPC initialized\r
1655 //\r
1656 Status = AllRootHPCInitialized (STALL_1_SECOND * 15);\r
1657\r
1658 if (EFI_ERROR (Status)) {\r
87000d77 1659 DEBUG ((DEBUG_ERROR, "Some root HPC failed to initialize\n"));\r
9060e3ec 1660 return Status;\r
1661 }\r
1662\r
1663 //\r
1664 // Notify the bus allocation phase is about to start for the 2nd time\r
1665 //\r
ea8d98fa
OM
1666 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
1667\r
1668 if (EFI_ERROR (Status)) {\r
1669 return Status;\r
1670 }\r
9060e3ec 1671\r
1436aea4 1672 DEBUG ((DEBUG_INFO, "PCI Bus Second Scanning\n"));\r
9060e3ec 1673 RootBridgeHandle = NULL;\r
1674 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
9060e3ec 1675 //\r
1676 // if a root bridge instance is found, create root bridge device for it\r
1677 //\r
1678 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1679\r
1680 if (RootBridgeDev == NULL) {\r
1681 return EFI_OUT_OF_RESOURCES;\r
1682 }\r
1683\r
1684 //\r
1685 // Enumerate all the buses under this root bridge\r
1686 //\r
1687 Status = PciRootBridgeEnumerator (\r
1436aea4
MK
1688 PciResAlloc,\r
1689 RootBridgeDev\r
1690 );\r
9060e3ec 1691\r
1692 DestroyRootBridge (RootBridgeDev);\r
1693 if (EFI_ERROR (Status)) {\r
bd067178 1694 RootBridgeEnumerationStatus = Status;\r
9060e3ec 1695 }\r
1696 }\r
1697\r
1698 //\r
1699 // Notify the bus allocation phase is to end for the 2nd time\r
1700 //\r
1701 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
bd067178
FN
1702\r
1703 if (EFI_ERROR (RootBridgeEnumerationStatus)) {\r
1704 return RootBridgeEnumerationStatus;\r
1705 }\r
9060e3ec 1706 }\r
1707\r
1708 //\r
1709 // Notify the resource allocation phase is to start\r
1710 //\r
ea8d98fa
OM
1711 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);\r
1712\r
1713 if (EFI_ERROR (Status)) {\r
1714 return Status;\r
1715 }\r
9060e3ec 1716\r
1717 RootBridgeHandle = NULL;\r
1718 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
9060e3ec 1719 //\r
1720 // if a root bridge instance is found, create root bridge device for it\r
1721 //\r
1722 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1723\r
1724 if (RootBridgeDev == NULL) {\r
1725 return EFI_OUT_OF_RESOURCES;\r
1726 }\r
1727\r
1728 Status = StartManagingRootBridge (RootBridgeDev);\r
1729\r
1730 if (EFI_ERROR (Status)) {\r
1731 return Status;\r
1732 }\r
1733\r
1734 PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;\r
1436aea4 1735 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **)&Descriptors);\r
9060e3ec 1736\r
1737 if (EFI_ERROR (Status)) {\r
1738 return Status;\r
1739 }\r
1740\r
1741 Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);\r
1742\r
1743 if (EFI_ERROR (Status)) {\r
1744 return Status;\r
1745 }\r
1746\r
1747 //\r
1748 // Determine root bridge attribute by calling interface of Pcihostbridge\r
1749 // protocol\r
1750 //\r
1751 DetermineRootBridgeAttributes (\r
1752 PciResAlloc,\r
1753 RootBridgeDev\r
1754 );\r
1755\r
1756 //\r
1757 // Collect all the resource information under this root bridge\r
1758 // A database that records all the information about pci device subject to this\r
1759 // root bridge will then be created\r
1760 //\r
1761 Status = PciPciDeviceInfoCollector (\r
1436aea4
MK
1762 RootBridgeDev,\r
1763 (UINT8)MinBus\r
1764 );\r
9060e3ec 1765\r
1766 if (EFI_ERROR (Status)) {\r
1767 return Status;\r
1768 }\r
1769\r
1770 InsertRootBridge (RootBridgeDev);\r
1771\r
1772 //\r
1773 // Record the hostbridge handle\r
1774 //\r
1775 AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);\r
1776 }\r
1777\r
1778 return EFI_SUCCESS;\r
1779}\r
0785c619
LH
1780\r
1781/**\r
1782 This function is used to program the Resizable BAR Register.\r
1783\r
1784 @param PciIoDevice A pointer to the PCI_IO_DEVICE.\r
1785 @param ResizableBarOp PciResizableBarMax: Set BAR to max size\r
1786 PciResizableBarMin: set BAR to min size.\r
1787\r
1788 @retval EFI_SUCCESS Successfully enumerated the host bridge.\r
1789 @retval other Some error occurred when enumerating the host bridge.\r
1790\r
1791**/\r
1792EFI_STATUS\r
1793PciProgramResizableBar (\r
1794 IN PCI_IO_DEVICE *PciIoDevice,\r
1795 IN PCI_RESIZABLE_BAR_OPERATION ResizableBarOp\r
1796 )\r
1797{\r
1436aea4
MK
1798 EFI_PCI_IO_PROTOCOL *PciIo;\r
1799 UINT64 Capabilities;\r
1800 UINT32 Index;\r
1801 UINT32 Offset;\r
1802 INTN Bit;\r
1803 UINTN ResizableBarNumber;\r
1804 EFI_STATUS Status;\r
1805 PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY Entries[PCI_MAX_BAR];\r
0785c619
LH
1806\r
1807 ASSERT (PciIoDevice->ResizableBarOffset != 0);\r
1808\r
1436aea4
MK
1809 DEBUG ((\r
1810 DEBUG_INFO,\r
1811 " Programs Resizable BAR register, offset: 0x%08x, number: %d\n",\r
1812 PciIoDevice->ResizableBarOffset,\r
1813 PciIoDevice->ResizableBarNumber\r
1814 ));\r
0785c619
LH
1815\r
1816 ResizableBarNumber = MIN (PciIoDevice->ResizableBarNumber, PCI_MAX_BAR);\r
1436aea4
MK
1817 PciIo = &PciIoDevice->PciIo;\r
1818 Status = PciIo->Pci.Read (\r
1819 PciIo,\r
1820 EfiPciIoWidthUint8,\r
1821 PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER),\r
1822 sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY) * ResizableBarNumber,\r
1823 (VOID *)(&Entries)\r
1824 );\r
0785c619
LH
1825 ASSERT_EFI_ERROR (Status);\r
1826\r
1827 for (Index = 0; Index < ResizableBarNumber; Index++) {\r
0785c619
LH
1828 //\r
1829 // When the bit of Capabilities Set, indicates that the Function supports\r
1830 // operating with the BAR sized to (2^Bit) MB.\r
1831 // Example:\r
1832 // Bit 0 is set: supports operating with the BAR sized to 1 MB\r
1833 // Bit 1 is set: supports operating with the BAR sized to 2 MB\r
1834 // Bit n is set: supports operating with the BAR sized to (2^n) MB\r
1835 //\r
1436aea4
MK
1836 Capabilities = LShiftU64 (Entries[Index].ResizableBarControl.Bits.BarSizeCapability, 28)\r
1837 | Entries[Index].ResizableBarCapability.Bits.BarSizeCapability;\r
0785c619
LH
1838\r
1839 if (ResizableBarOp == PciResizableBarMax) {\r
1436aea4 1840 Bit = HighBitSet64 (Capabilities);\r
0785c619 1841 } else {\r
4c79f9bc 1842 ASSERT (ResizableBarOp == PciResizableBarMin);\r
1436aea4 1843 Bit = LowBitSet64 (Capabilities);\r
0785c619
LH
1844 }\r
1845\r
1846 ASSERT (Bit >= 0);\r
1847\r
1848 Offset = PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER)\r
1436aea4
MK
1849 + Index * sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY)\r
1850 + OFFSET_OF (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY, ResizableBarControl);\r
0785c619 1851\r
1436aea4 1852 Entries[Index].ResizableBarControl.Bits.BarSize = (UINT32)Bit;\r
0785c619
LH
1853 DEBUG ((\r
1854 DEBUG_INFO,\r
1855 " Resizable Bar: Offset = 0x%x, Bar Size Capability = 0x%016lx, New Bar Size = 0x%lx\n",\r
1856 OFFSET_OF (PCI_TYPE00, Device.Bar[Entries[Index].ResizableBarControl.Bits.BarIndex]),\r
1436aea4
MK
1857 Capabilities,\r
1858 LShiftU64 (SIZE_1MB, Bit)\r
0785c619
LH
1859 ));\r
1860 PciIo->Pci.Write (\r
1436aea4
MK
1861 PciIo,\r
1862 EfiPciIoWidthUint32,\r
1863 Offset,\r
1864 1,\r
1865 &Entries[Index].ResizableBarControl.Uint32\r
1866 );\r
0785c619
LH
1867 }\r
1868\r
1869 return EFI_SUCCESS;\r
1870}\r