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