]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
MdeModulePkg: Fixed extra 1 SR-IOV reserved bus
[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
9060e3ec 1109\r
1110 PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
1111 SecondBus = 0;\r
1112 Register = 0;\r
1113 State = 0;\r
1436aea4 1114 Attributes = (EFI_HPC_PADDING_ATTRIBUTES)0;\r
9060e3ec 1115 BusRange = 0;\r
1116 BusPadding = FALSE;\r
1117 PciDevice = NULL;\r
1118 PciAddress = 0;\r
1119\r
1120 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
1121 TempReservedBusNum = 0;\r
1122 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
9060e3ec 1123 //\r
1124 // Check to see whether a pci device is present\r
1125 //\r
1126 Status = PciDevicePresent (\r
1436aea4
MK
1127 PciRootBridgeIo,\r
1128 &Pci,\r
1129 StartBusNumber,\r
1130 Device,\r
1131 Func\r
1132 );\r
9060e3ec 1133\r
1436aea4 1134 if (EFI_ERROR (Status) && (Func == 0)) {\r
25a26646
JS
1135 //\r
1136 // go to next device if there is no Function 0\r
1137 //\r
1138 break;\r
1139 }\r
1140\r
9060e3ec 1141 if (EFI_ERROR (Status)) {\r
9060e3ec 1142 continue;\r
1143 }\r
1144\r
d4048391 1145 //\r
1146 // Get the PCI device information\r
1147 //\r
1148 Status = PciSearchDevice (\r
1436aea4
MK
1149 Bridge,\r
1150 &Pci,\r
1151 StartBusNumber,\r
1152 Device,\r
1153 Func,\r
1154 &PciDevice\r
1155 );\r
9060e3ec 1156\r
995d8b85
JY
1157 if (EFI_ERROR (Status)) {\r
1158 continue;\r
1159 }\r
9060e3ec 1160\r
d4048391 1161 PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);\r
9060e3ec 1162\r
d4048391 1163 if (!IS_PCI_BRIDGE (&Pci)) {\r
1164 //\r
1165 // PCI bridges will be called later\r
1166 // Here just need for PCI device or PCI to cardbus controller\r
1167 // EfiPciBeforeChildBusEnumeration for PCI Device Node\r
1168 //\r
1169 PreprocessController (\r
1436aea4
MK
1170 PciDevice,\r
1171 PciDevice->BusNumber,\r
1172 PciDevice->DeviceNumber,\r
1173 PciDevice->FunctionNumber,\r
1174 EfiPciBeforeChildBusEnumeration\r
1175 );\r
d4048391 1176 }\r
9060e3ec 1177\r
d4048391 1178 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
9060e3ec 1179 //\r
1180 // For Pci Hotplug controller devcie only\r
1181 //\r
1182 if (gPciHotPlugInit != NULL) {\r
1183 //\r
1184 // Check if it is a Hotplug PCI controller\r
1185 //\r
1186 if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) {\r
55565b08 1187 gPciRootHpcData[HpIndex].Found = TRUE;\r
9060e3ec 1188\r
1189 if (!gPciRootHpcData[HpIndex].Initialized) {\r
9060e3ec 1190 Status = CreateEventForHpc (HpIndex, &Event);\r
1191\r
1192 ASSERT (!EFI_ERROR (Status));\r
1193\r
1194 Status = gPciHotPlugInit->InitializeRootHpc (\r
1195 gPciHotPlugInit,\r
1196 gPciRootHpcPool[HpIndex].HpcDevicePath,\r
1197 PciAddress,\r
1198 Event,\r
1199 &State\r
1200 );\r
1201\r
1202 PreprocessController (\r
1203 PciDevice,\r
1204 PciDevice->BusNumber,\r
1205 PciDevice->DeviceNumber,\r
1206 PciDevice->FunctionNumber,\r
1207 EfiPciBeforeChildBusEnumeration\r
1436aea4 1208 );\r
9060e3ec 1209 }\r
1210 }\r
1211 }\r
1212 }\r
1213\r
1214 if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {\r
1215 //\r
1216 // For PPB\r
1217 //\r
2603fce1 1218 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
9060e3ec 1219 //\r
1220 // If Hot Plug is supported,\r
1221 // Get the bridge information\r
1222 //\r
1223 BusPadding = FALSE;\r
1224 if (gPciHotPlugInit != NULL) {\r
cbbccf3c 1225 if (IsPciHotPlugBus (PciDevice)) {\r
9060e3ec 1226 //\r
1227 // If it is initialized, get the padded bus range\r
1228 //\r
1229 Status = gPciHotPlugInit->GetResourcePadding (\r
1230 gPciHotPlugInit,\r
cbbccf3c 1231 PciDevice->DevicePath,\r
9060e3ec 1232 PciAddress,\r
1233 &State,\r
1436aea4 1234 (VOID **)&Descriptors,\r
9060e3ec 1235 &Attributes\r
1236 );\r
1237\r
1238 if (EFI_ERROR (Status)) {\r
1239 return Status;\r
1240 }\r
1241\r
1436aea4 1242 BusRange = 0;\r
fff2623c 1243 NextDescriptors = Descriptors;\r
1436aea4
MK
1244 Status = PciGetBusRange (\r
1245 &NextDescriptors,\r
1246 NULL,\r
1247 NULL,\r
1248 &BusRange\r
1249 );\r
9060e3ec 1250\r
1251 FreePool (Descriptors);\r
1252\r
ada38584
RN
1253 if (!EFI_ERROR (Status)) {\r
1254 BusPadding = TRUE;\r
1255 } else if (Status != EFI_NOT_FOUND) {\r
1256 //\r
1257 // EFI_NOT_FOUND is not a real error. It indicates no bus number padding requested.\r
1258 //\r
1259 return Status;\r
2e94e412 1260 }\r
9060e3ec 1261 }\r
1262 }\r
1263 }\r
1264\r
306bbe82 1265 Status = PciAllocateBusNumber (Bridge, *SubBusNumber, 1, SubBusNumber);\r
1266 if (EFI_ERROR (Status)) {\r
1267 return Status;\r
9060e3ec 1268 }\r
1436aea4 1269\r
9060e3ec 1270 SecondBus = *SubBusNumber;\r
1271\r
1436aea4
MK
1272 Register = (UINT16)((SecondBus << 8) | (UINT16)StartBusNumber);\r
1273 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET);\r
9060e3ec 1274\r
1275 Status = PciRootBridgeIo->Pci.Write (\r
1276 PciRootBridgeIo,\r
1277 EfiPciWidthUint16,\r
1278 Address,\r
1279 1,\r
1280 &Register\r
1281 );\r
1282\r
9060e3ec 1283 //\r
1284 // If it is PPB, resursively search down this bridge\r
1285 //\r
1286 if (IS_PCI_BRIDGE (&Pci)) {\r
9060e3ec 1287 //\r
1288 // Temporarily initialize SubBusNumber to maximum bus number to ensure the\r
1289 // PCI configuration transaction to go through any PPB\r
1290 //\r
1436aea4
MK
1291 Register = PciGetMaxBusNumber (Bridge);\r
1292 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);\r
1293 Status = PciRootBridgeIo->Pci.Write (\r
1294 PciRootBridgeIo,\r
1295 EfiPciWidthUint8,\r
1296 Address,\r
1297 1,\r
1298 &Register\r
1299 );\r
9060e3ec 1300\r
1301 //\r
1302 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige\r
1303 //\r
1304 PreprocessController (\r
1305 PciDevice,\r
1306 PciDevice->BusNumber,\r
1307 PciDevice->DeviceNumber,\r
1308 PciDevice->FunctionNumber,\r
1309 EfiPciBeforeChildBusEnumeration\r
1310 );\r
1311\r
9060e3ec 1312 Status = PciScanBus (\r
1436aea4
MK
1313 PciDevice,\r
1314 SecondBus,\r
1315 SubBusNumber,\r
1316 PaddedBusRange\r
1317 );\r
9060e3ec 1318 if (EFI_ERROR (Status)) {\r
1319 return Status;\r
1320 }\r
1321 }\r
1322\r
1323 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport) && BusPadding) {\r
1324 //\r
1325 // Ensure the device is enabled and initialized\r
1326 //\r
1327 if ((Attributes == EfiPaddingPciRootBridge) &&\r
1436aea4
MK
1328 ((State & EFI_HPC_STATE_ENABLED) != 0) &&\r
1329 ((State & EFI_HPC_STATE_INITIALIZED) != 0))\r
1330 {\r
1331 *PaddedBusRange = (UINT8)((UINT8)(BusRange) + *PaddedBusRange);\r
9060e3ec 1332 } else {\r
c7e7613e
RN
1333 //\r
1334 // Reserve the larger one between the actual occupied bus number and padded bus number\r
1335 //\r
1436aea4 1336 Status = PciAllocateBusNumber (PciDevice, SecondBus, (UINT8)(BusRange), &PaddedSubBus);\r
306bbe82 1337 if (EFI_ERROR (Status)) {\r
1338 return Status;\r
1339 }\r
1436aea4 1340\r
c7e7613e 1341 *SubBusNumber = MAX (PaddedSubBus, *SubBusNumber);\r
9060e3ec 1342 }\r
1343 }\r
1344\r
1345 //\r
1346 // Set the current maximum bus number under the PPB\r
1347 //\r
1348 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);\r
1349\r
1350 Status = PciRootBridgeIo->Pci.Write (\r
1351 PciRootBridgeIo,\r
1352 EfiPciWidthUint8,\r
1353 Address,\r
1354 1,\r
1355 SubBusNumber\r
1356 );\r
1436aea4 1357 } else {\r
9060e3ec 1358 //\r
1359 // It is device. Check PCI IOV for Bus reservation\r
9060e3ec 1360 // Go through each function, just reserve the MAX ReservedBusNum for one device\r
1361 //\r
1436aea4 1362 if (PcdGetBool (PcdSrIovSupport) && (PciDevice->SrIovCapabilityOffset != 0)) {\r
9060e3ec 1363 if (TempReservedBusNum < PciDevice->ReservedBusNum) {\r
1436aea4 1364 Status = PciAllocateBusNumber (PciDevice, *SubBusNumber, (UINT8)(PciDevice->ReservedBusNum - TempReservedBusNum), SubBusNumber);\r
306bbe82 1365 if (EFI_ERROR (Status)) {\r
1366 return Status;\r
1367 }\r
1436aea4 1368\r
9060e3ec 1369 TempReservedBusNum = PciDevice->ReservedBusNum;\r
1370\r
1371 if (Func == 0) {\r
87000d77 1372 DEBUG ((DEBUG_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x\n", *SubBusNumber));\r
9060e3ec 1373 } else {\r
87000d77 1374 DEBUG ((DEBUG_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x (Update)\n", *SubBusNumber));\r
9060e3ec 1375 }\r
1376 }\r
1377 }\r
1378 }\r
1379\r
1436aea4 1380 if ((Func == 0) && !IS_PCI_MULTI_FUNC (&Pci)) {\r
9060e3ec 1381 //\r
1382 // Skip sub functions, this is not a multi function device\r
1383 //\r
1384\r
1385 Func = PCI_MAX_FUNC;\r
1386 }\r
1387 }\r
1388 }\r
1389\r
1390 return EFI_SUCCESS;\r
1391}\r
1392\r
1393/**\r
1394 Process Option Rom on the specified root bridge.\r
1395\r
1396 @param Bridge Pci root bridge device instance.\r
1397\r
1398 @retval EFI_SUCCESS Success process.\r
1399 @retval other Some error occurred when processing Option Rom on the root bridge.\r
1400\r
1401**/\r
1402EFI_STATUS\r
1403PciRootBridgeP2CProcess (\r
1436aea4 1404 IN PCI_IO_DEVICE *Bridge\r
9060e3ec 1405 )\r
1406{\r
1436aea4
MK
1407 LIST_ENTRY *CurrentLink;\r
1408 PCI_IO_DEVICE *Temp;\r
1409 EFI_HPC_STATE State;\r
1410 UINT64 PciAddress;\r
1411 EFI_STATUS Status;\r
9060e3ec 1412\r
1413 CurrentLink = Bridge->ChildList.ForwardLink;\r
1414\r
1415 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
9060e3ec 1416 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
1417\r
1418 if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {\r
1436aea4 1419 if ((gPciHotPlugInit != NULL) && Temp->Allocated && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
9060e3ec 1420 //\r
1421 // Raise the EFI_IOB_PCI_HPC_INIT status code\r
1422 //\r
1423 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1424 EFI_PROGRESS_CODE,\r
fe91c992 1425 EFI_IO_BUS_PCI | EFI_IOB_PCI_HPC_INIT,\r
9060e3ec 1426 Temp->DevicePath\r
1427 );\r
1428\r
1429 PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);\r
1436aea4
MK
1430 Status = gPciHotPlugInit->InitializeRootHpc (\r
1431 gPciHotPlugInit,\r
1432 Temp->DevicePath,\r
1433 PciAddress,\r
1434 NULL,\r
1435 &State\r
1436 );\r
9060e3ec 1437\r
1438 if (!EFI_ERROR (Status)) {\r
1439 Status = PciBridgeEnumerator (Temp);\r
1440\r
1441 if (EFI_ERROR (Status)) {\r
1442 return Status;\r
1443 }\r
1444 }\r
1445\r
1446 CurrentLink = CurrentLink->ForwardLink;\r
1447 continue;\r
9060e3ec 1448 }\r
1449 }\r
1450\r
1451 if (!IsListEmpty (&Temp->ChildList)) {\r
1452 Status = PciRootBridgeP2CProcess (Temp);\r
1453 }\r
1454\r
1455 CurrentLink = CurrentLink->ForwardLink;\r
1456 }\r
1457\r
1458 return EFI_SUCCESS;\r
1459}\r
1460\r
1461/**\r
1462 Process Option Rom on the specified host bridge.\r
1463\r
1464 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.\r
1465\r
1466 @retval EFI_SUCCESS Success process.\r
1467 @retval EFI_NOT_FOUND Can not find the root bridge instance.\r
1468 @retval other Some error occurred when processing Option Rom on the host bridge.\r
1469\r
1470**/\r
1471EFI_STATUS\r
1472PciHostBridgeP2CProcess (\r
1436aea4 1473 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
9060e3ec 1474 )\r
1475{\r
1436aea4
MK
1476 EFI_HANDLE RootBridgeHandle;\r
1477 PCI_IO_DEVICE *RootBridgeDev;\r
1478 EFI_STATUS Status;\r
9060e3ec 1479\r
1480 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1481 return EFI_SUCCESS;\r
1482 }\r
1483\r
1484 RootBridgeHandle = NULL;\r
1485\r
1486 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
9060e3ec 1487 //\r
1488 // Get RootBridg Device by handle\r
1489 //\r
1490 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);\r
1491\r
1492 if (RootBridgeDev == NULL) {\r
1493 return EFI_NOT_FOUND;\r
1494 }\r
1495\r
1496 Status = PciRootBridgeP2CProcess (RootBridgeDev);\r
1497 if (EFI_ERROR (Status)) {\r
1498 return Status;\r
1499 }\r
9060e3ec 1500 }\r
1501\r
1502 return EFI_SUCCESS;\r
1503}\r
1504\r
1505/**\r
1506 This function is used to enumerate the entire host bridge\r
1507 in a given platform.\r
1508\r
1509 @param PciResAlloc A pointer to the PCI Host Resource Allocation protocol.\r
1510\r
1511 @retval EFI_SUCCESS Successfully enumerated the host bridge.\r
1512 @retval EFI_OUT_OF_RESOURCES No enough memory available.\r
1513 @retval other Some error occurred when enumerating the host bridge.\r
1514\r
1515**/\r
1516EFI_STATUS\r
1517PciHostBridgeEnumerator (\r
1518 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc\r
1519 )\r
1520{\r
1436aea4
MK
1521 EFI_HANDLE RootBridgeHandle;\r
1522 PCI_IO_DEVICE *RootBridgeDev;\r
1523 EFI_STATUS Status;\r
1524 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
1525 UINT16 MinBus;\r
1526 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
1527 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;\r
1528 UINT8 StartBusNumber;\r
1529 LIST_ENTRY RootBridgeList;\r
1530 LIST_ENTRY *Link;\r
bd067178 1531 EFI_STATUS RootBridgeEnumerationStatus;\r
9060e3ec 1532\r
1533 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
1534 InitializeHotPlugSupport ();\r
1535 }\r
1536\r
1537 InitializeListHead (&RootBridgeList);\r
1538\r
1539 //\r
1540 // Notify the bus allocation phase is about to start\r
1541 //\r
ea8d98fa
OM
1542 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
1543\r
1544 if (EFI_ERROR (Status)) {\r
1545 return Status;\r
1546 }\r
9060e3ec 1547\r
1436aea4 1548 DEBUG ((DEBUG_INFO, "PCI Bus First Scanning\n"));\r
bd067178
FN
1549 RootBridgeHandle = NULL;\r
1550 RootBridgeEnumerationStatus = EFI_SUCCESS;\r
9060e3ec 1551 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
9060e3ec 1552 //\r
1553 // if a root bridge instance is found, create root bridge device for it\r
1554 //\r
1555\r
1556 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1557\r
1558 if (RootBridgeDev == NULL) {\r
1559 return EFI_OUT_OF_RESOURCES;\r
1560 }\r
1561\r
1562 //\r
1563 // Enumerate all the buses under this root bridge\r
1564 //\r
1565 Status = PciRootBridgeEnumerator (\r
1436aea4
MK
1566 PciResAlloc,\r
1567 RootBridgeDev\r
1568 );\r
9060e3ec 1569\r
1436aea4 1570 if ((gPciHotPlugInit != NULL) && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
9060e3ec 1571 InsertTailList (&RootBridgeList, &(RootBridgeDev->Link));\r
1572 } else {\r
1573 DestroyRootBridge (RootBridgeDev);\r
1574 }\r
1436aea4 1575\r
9060e3ec 1576 if (EFI_ERROR (Status)) {\r
bd067178 1577 RootBridgeEnumerationStatus = Status;\r
9060e3ec 1578 }\r
1579 }\r
1580\r
1581 //\r
1582 // Notify the bus allocation phase is finished for the first time\r
1583 //\r
1584 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
1585\r
bd067178
FN
1586 if (EFI_ERROR (RootBridgeEnumerationStatus)) {\r
1587 return RootBridgeEnumerationStatus;\r
1588 }\r
1589\r
1436aea4 1590 if ((gPciHotPlugInit != NULL) && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
9060e3ec 1591 //\r
1592 // Reset all assigned PCI bus number in all PPB\r
1593 //\r
1594 RootBridgeHandle = NULL;\r
1436aea4 1595 Link = GetFirstNode (&RootBridgeList);\r
9060e3ec 1596 while ((PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) &&\r
1436aea4
MK
1597 (!IsNull (&RootBridgeList, Link)))\r
1598 {\r
9060e3ec 1599 RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (Link);\r
1600 //\r
1601 // Get the Bus information\r
1602 //\r
1603 Status = PciResAlloc->StartBusEnumeration (\r
1604 PciResAlloc,\r
1605 RootBridgeHandle,\r
1436aea4 1606 (VOID **)&Configuration\r
9060e3ec 1607 );\r
1608 if (EFI_ERROR (Status)) {\r
1609 return Status;\r
1610 }\r
1611\r
1612 //\r
1613 // Get the bus number to start with\r
1614 //\r
1436aea4 1615 StartBusNumber = (UINT8)(Configuration->AddrRangeMin);\r
9060e3ec 1616\r
1617 ResetAllPpbBusNumber (\r
1618 RootBridgeDev,\r
1619 StartBusNumber\r
1436aea4 1620 );\r
9060e3ec 1621\r
1622 FreePool (Configuration);\r
8063b47b 1623 Link = RemoveEntryList (Link);\r
9060e3ec 1624 DestroyRootBridge (RootBridgeDev);\r
1625 }\r
1626\r
1627 //\r
1628 // Wait for all HPC initialized\r
1629 //\r
1630 Status = AllRootHPCInitialized (STALL_1_SECOND * 15);\r
1631\r
1632 if (EFI_ERROR (Status)) {\r
87000d77 1633 DEBUG ((DEBUG_ERROR, "Some root HPC failed to initialize\n"));\r
9060e3ec 1634 return Status;\r
1635 }\r
1636\r
1637 //\r
1638 // Notify the bus allocation phase is about to start for the 2nd time\r
1639 //\r
ea8d98fa
OM
1640 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);\r
1641\r
1642 if (EFI_ERROR (Status)) {\r
1643 return Status;\r
1644 }\r
9060e3ec 1645\r
1436aea4 1646 DEBUG ((DEBUG_INFO, "PCI Bus Second Scanning\n"));\r
9060e3ec 1647 RootBridgeHandle = NULL;\r
1648 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
9060e3ec 1649 //\r
1650 // if a root bridge instance is found, create root bridge device for it\r
1651 //\r
1652 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1653\r
1654 if (RootBridgeDev == NULL) {\r
1655 return EFI_OUT_OF_RESOURCES;\r
1656 }\r
1657\r
1658 //\r
1659 // Enumerate all the buses under this root bridge\r
1660 //\r
1661 Status = PciRootBridgeEnumerator (\r
1436aea4
MK
1662 PciResAlloc,\r
1663 RootBridgeDev\r
1664 );\r
9060e3ec 1665\r
1666 DestroyRootBridge (RootBridgeDev);\r
1667 if (EFI_ERROR (Status)) {\r
bd067178 1668 RootBridgeEnumerationStatus = Status;\r
9060e3ec 1669 }\r
1670 }\r
1671\r
1672 //\r
1673 // Notify the bus allocation phase is to end for the 2nd time\r
1674 //\r
1675 NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);\r
bd067178
FN
1676\r
1677 if (EFI_ERROR (RootBridgeEnumerationStatus)) {\r
1678 return RootBridgeEnumerationStatus;\r
1679 }\r
9060e3ec 1680 }\r
1681\r
1682 //\r
1683 // Notify the resource allocation phase is to start\r
1684 //\r
ea8d98fa
OM
1685 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);\r
1686\r
1687 if (EFI_ERROR (Status)) {\r
1688 return Status;\r
1689 }\r
9060e3ec 1690\r
1691 RootBridgeHandle = NULL;\r
1692 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {\r
9060e3ec 1693 //\r
1694 // if a root bridge instance is found, create root bridge device for it\r
1695 //\r
1696 RootBridgeDev = CreateRootBridge (RootBridgeHandle);\r
1697\r
1698 if (RootBridgeDev == NULL) {\r
1699 return EFI_OUT_OF_RESOURCES;\r
1700 }\r
1701\r
1702 Status = StartManagingRootBridge (RootBridgeDev);\r
1703\r
1704 if (EFI_ERROR (Status)) {\r
1705 return Status;\r
1706 }\r
1707\r
1708 PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;\r
1436aea4 1709 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **)&Descriptors);\r
9060e3ec 1710\r
1711 if (EFI_ERROR (Status)) {\r
1712 return Status;\r
1713 }\r
1714\r
1715 Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);\r
1716\r
1717 if (EFI_ERROR (Status)) {\r
1718 return Status;\r
1719 }\r
1720\r
1721 //\r
1722 // Determine root bridge attribute by calling interface of Pcihostbridge\r
1723 // protocol\r
1724 //\r
1725 DetermineRootBridgeAttributes (\r
1726 PciResAlloc,\r
1727 RootBridgeDev\r
1728 );\r
1729\r
1730 //\r
1731 // Collect all the resource information under this root bridge\r
1732 // A database that records all the information about pci device subject to this\r
1733 // root bridge will then be created\r
1734 //\r
1735 Status = PciPciDeviceInfoCollector (\r
1436aea4
MK
1736 RootBridgeDev,\r
1737 (UINT8)MinBus\r
1738 );\r
9060e3ec 1739\r
1740 if (EFI_ERROR (Status)) {\r
1741 return Status;\r
1742 }\r
1743\r
1744 InsertRootBridge (RootBridgeDev);\r
1745\r
1746 //\r
1747 // Record the hostbridge handle\r
1748 //\r
1749 AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);\r
1750 }\r
1751\r
1752 return EFI_SUCCESS;\r
1753}\r
0785c619
LH
1754\r
1755/**\r
1756 This function is used to program the Resizable BAR Register.\r
1757\r
1758 @param PciIoDevice A pointer to the PCI_IO_DEVICE.\r
1759 @param ResizableBarOp PciResizableBarMax: Set BAR to max size\r
1760 PciResizableBarMin: set BAR to min size.\r
1761\r
1762 @retval EFI_SUCCESS Successfully enumerated the host bridge.\r
1763 @retval other Some error occurred when enumerating the host bridge.\r
1764\r
1765**/\r
1766EFI_STATUS\r
1767PciProgramResizableBar (\r
1768 IN PCI_IO_DEVICE *PciIoDevice,\r
1769 IN PCI_RESIZABLE_BAR_OPERATION ResizableBarOp\r
1770 )\r
1771{\r
1436aea4
MK
1772 EFI_PCI_IO_PROTOCOL *PciIo;\r
1773 UINT64 Capabilities;\r
1774 UINT32 Index;\r
1775 UINT32 Offset;\r
1776 INTN Bit;\r
1777 UINTN ResizableBarNumber;\r
1778 EFI_STATUS Status;\r
1779 PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY Entries[PCI_MAX_BAR];\r
0785c619
LH
1780\r
1781 ASSERT (PciIoDevice->ResizableBarOffset != 0);\r
1782\r
1436aea4
MK
1783 DEBUG ((\r
1784 DEBUG_INFO,\r
1785 " Programs Resizable BAR register, offset: 0x%08x, number: %d\n",\r
1786 PciIoDevice->ResizableBarOffset,\r
1787 PciIoDevice->ResizableBarNumber\r
1788 ));\r
0785c619
LH
1789\r
1790 ResizableBarNumber = MIN (PciIoDevice->ResizableBarNumber, PCI_MAX_BAR);\r
1436aea4
MK
1791 PciIo = &PciIoDevice->PciIo;\r
1792 Status = PciIo->Pci.Read (\r
1793 PciIo,\r
1794 EfiPciIoWidthUint8,\r
1795 PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER),\r
1796 sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY) * ResizableBarNumber,\r
1797 (VOID *)(&Entries)\r
1798 );\r
0785c619
LH
1799 ASSERT_EFI_ERROR (Status);\r
1800\r
1801 for (Index = 0; Index < ResizableBarNumber; Index++) {\r
0785c619
LH
1802 //\r
1803 // When the bit of Capabilities Set, indicates that the Function supports\r
1804 // operating with the BAR sized to (2^Bit) MB.\r
1805 // Example:\r
1806 // Bit 0 is set: supports operating with the BAR sized to 1 MB\r
1807 // Bit 1 is set: supports operating with the BAR sized to 2 MB\r
1808 // Bit n is set: supports operating with the BAR sized to (2^n) MB\r
1809 //\r
1436aea4
MK
1810 Capabilities = LShiftU64 (Entries[Index].ResizableBarControl.Bits.BarSizeCapability, 28)\r
1811 | Entries[Index].ResizableBarCapability.Bits.BarSizeCapability;\r
0785c619
LH
1812\r
1813 if (ResizableBarOp == PciResizableBarMax) {\r
1436aea4 1814 Bit = HighBitSet64 (Capabilities);\r
0785c619 1815 } else {\r
4c79f9bc 1816 ASSERT (ResizableBarOp == PciResizableBarMin);\r
1436aea4 1817 Bit = LowBitSet64 (Capabilities);\r
0785c619
LH
1818 }\r
1819\r
1820 ASSERT (Bit >= 0);\r
1821\r
1822 Offset = PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER)\r
1436aea4
MK
1823 + Index * sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY)\r
1824 + OFFSET_OF (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY, ResizableBarControl);\r
0785c619 1825\r
1436aea4 1826 Entries[Index].ResizableBarControl.Bits.BarSize = (UINT32)Bit;\r
0785c619
LH
1827 DEBUG ((\r
1828 DEBUG_INFO,\r
1829 " Resizable Bar: Offset = 0x%x, Bar Size Capability = 0x%016lx, New Bar Size = 0x%lx\n",\r
1830 OFFSET_OF (PCI_TYPE00, Device.Bar[Entries[Index].ResizableBarControl.Bits.BarIndex]),\r
1436aea4
MK
1831 Capabilities,\r
1832 LShiftU64 (SIZE_1MB, Bit)\r
0785c619
LH
1833 ));\r
1834 PciIo->Pci.Write (\r
1436aea4
MK
1835 PciIo,\r
1836 EfiPciIoWidthUint32,\r
1837 Offset,\r
1838 1,\r
1839 &Entries[Index].ResizableBarControl.Uint32\r
1840 );\r
0785c619
LH
1841 }\r
1842\r
1843 return EFI_SUCCESS;\r
1844}\r