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