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