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