2 PCI eunmeration implementation on entire PCI bus system for PCI Bus module.
4 Copyright (c) 2006 - 2013, 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
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.
18 This routine is used to enumerate entire pci bus system
21 @param Controller Parent controller handle.
23 @retval EFI_SUCCESS PCI enumeration finished successfully.
24 @retval other Some error occurred when enumerating the pci bus system.
29 IN EFI_HANDLE Controller
33 EFI_HANDLE HostBridgeHandle
;
35 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
;
36 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
39 // If PCI bus has already done the full enumeration, never do it again
41 if (!gFullEnumeration
) {
42 return PciEnumeratorLight (Controller
);
46 // Get the rootbridge Io protocol to find the host bridge handle
48 Status
= gBS
->OpenProtocol (
50 &gEfiPciRootBridgeIoProtocolGuid
,
51 (VOID
**) &PciRootBridgeIo
,
52 gPciBusDriverBinding
.DriverBindingHandle
,
54 EFI_OPEN_PROTOCOL_GET_PROTOCOL
57 if (EFI_ERROR (Status
)) {
62 // Get the host bridge handle
64 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
67 // Get the pci host bridge resource allocation protocol
69 Status
= gBS
->OpenProtocol (
71 &gEfiPciHostBridgeResourceAllocationProtocolGuid
,
72 (VOID
**) &PciResAlloc
,
73 gPciBusDriverBinding
.DriverBindingHandle
,
75 EFI_OPEN_PROTOCOL_GET_PROTOCOL
78 if (EFI_ERROR (Status
)) {
83 // Notify the pci bus enumeration is about to begin
85 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginEnumeration
);
87 if (EFI_ERROR (Status
)) {
92 // Start the bus allocation phase
94 Status
= PciHostBridgeEnumerator (PciResAlloc
);
96 if (EFI_ERROR (Status
)) {
101 // Submit the resource request
103 Status
= PciHostBridgeResourceAllocator (PciResAlloc
);
105 if (EFI_ERROR (Status
)) {
110 // Notify the pci bus enumeration is about to complete
112 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndEnumeration
);
114 if (EFI_ERROR (Status
)) {
121 Status
= PciHostBridgeP2CProcess (PciResAlloc
);
123 if (EFI_ERROR (Status
)) {
128 // Process attributes for devices on this host bridge
130 Status
= PciHostBridgeDeviceAttribute (PciResAlloc
);
131 if (EFI_ERROR (Status
)) {
135 gFullEnumeration
= FALSE
;
138 Status
= gBS
->InstallProtocolInterface (
140 &gEfiPciEnumerationCompleteProtocolGuid
,
141 EFI_NATIVE_INTERFACE
,
144 if (EFI_ERROR (Status
)) {
152 Enumerate PCI root bridge.
154 @param PciResAlloc Pointer to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
155 @param RootBridgeDev Instance of root bridge device.
157 @retval EFI_SUCCESS Successfully enumerated root bridge.
158 @retval other Failed to enumerate root bridge.
162 PciRootBridgeEnumerator (
163 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
,
164 IN PCI_IO_DEVICE
*RootBridgeDev
168 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration
;
169 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration1
;
170 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration2
;
171 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration3
;
173 UINT8 StartBusNumber
;
174 UINT8 PaddedBusRange
;
175 EFI_HANDLE RootBridgeHandle
;
185 // Get the root bridge handle
187 RootBridgeHandle
= RootBridgeDev
->Handle
;
189 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
191 EFI_IO_BUS_PCI
| EFI_IOB_PCI_BUS_ENUM
,
192 RootBridgeDev
->DevicePath
196 // Get the Bus information
198 Status
= PciResAlloc
->StartBusEnumeration (
201 (VOID
**) &Configuration
204 if (EFI_ERROR (Status
)) {
208 if (Configuration
== NULL
|| Configuration
->Desc
== ACPI_END_TAG_DESCRIPTOR
) {
209 return EFI_INVALID_PARAMETER
;
211 RootBridgeDev
->BusNumberRanges
= Configuration
;
214 // Sort the descriptors in ascending order
216 for (Configuration1
= Configuration
; Configuration1
->Desc
!= ACPI_END_TAG_DESCRIPTOR
; Configuration1
++) {
217 Configuration2
= Configuration1
;
218 for (Configuration3
= Configuration1
+ 1; Configuration3
->Desc
!= ACPI_END_TAG_DESCRIPTOR
; Configuration3
++) {
219 if (Configuration2
->AddrRangeMin
> Configuration3
->AddrRangeMin
) {
220 Configuration2
= Configuration3
;
224 // All other fields other than AddrRangeMin and AddrLen are ignored in a descriptor,
225 // so only need to swap these two fields.
227 if (Configuration2
!= Configuration1
) {
228 AddrRangeMin
= Configuration1
->AddrRangeMin
;
229 Configuration1
->AddrRangeMin
= Configuration2
->AddrRangeMin
;
230 Configuration2
->AddrRangeMin
= AddrRangeMin
;
232 AddrLen
= Configuration1
->AddrLen
;
233 Configuration1
->AddrLen
= Configuration2
->AddrLen
;
234 Configuration2
->AddrLen
= AddrLen
;
239 // Get the bus number to start with
241 StartBusNumber
= (UINT8
) (Configuration
->AddrRangeMin
);
244 // Initialize the subordinate bus number
246 SubBusNumber
= StartBusNumber
;
249 // Reset all assigned PCI bus number
251 ResetAllPpbBusNumber (
259 Status
= PciScanBus (
266 if (EFI_ERROR (Status
)) {
272 // Assign max bus number scanned
275 Status
= PciAllocateBusNumber (RootBridgeDev
, SubBusNumber
, PaddedBusRange
, &SubBusNumber
);
276 if (EFI_ERROR (Status
)) {
281 // Find the bus range which contains the higest bus number, then returns the number of buses
282 // that should be decoded.
284 while (Configuration
->AddrRangeMin
+ Configuration
->AddrLen
- 1 < SubBusNumber
) {
287 AddrLen
= Configuration
->AddrLen
;
288 Configuration
->AddrLen
= SubBusNumber
- Configuration
->AddrRangeMin
+ 1;
291 // Save the Desc field of the next descriptor. Mark the next descriptor as an END descriptor.
294 Desc
= Configuration
->Desc
;
295 Configuration
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
300 Status
= PciResAlloc
->SetBusNumbers (
303 RootBridgeDev
->BusNumberRanges
307 // Restore changed fields
309 Configuration
->Desc
= Desc
;
310 (Configuration
- 1)->AddrLen
= AddrLen
;
316 This routine is used to process all PCI devices' Option Rom
317 on a certain root bridge.
319 @param Bridge Given parent's root bridge.
320 @param RomBase Base address of ROM driver loaded from.
321 @param MaxLength Maximum rom size.
326 IN PCI_IO_DEVICE
*Bridge
,
331 LIST_ENTRY
*CurrentLink
;
335 // Go through bridges to reach all devices
337 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
338 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
339 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
340 if (!IsListEmpty (&Temp
->ChildList
)) {
343 // Go further to process the option rom under this bridge
345 ProcessOptionRom (Temp
, RomBase
, MaxLength
);
348 if (Temp
->RomSize
!= 0 && Temp
->RomSize
<= MaxLength
) {
351 // Load and process the option rom
353 LoadOpRomImage (Temp
, RomBase
);
356 CurrentLink
= CurrentLink
->ForwardLink
;
361 This routine is used to assign bus number to the given PCI bus system
363 @param Bridge Parent root bridge instance.
364 @param StartBusNumber Number of beginning.
365 @param SubBusNumber The number of sub bus.
367 @retval EFI_SUCCESS Successfully assigned bus number.
368 @retval EFI_DEVICE_ERROR Failed to assign bus number.
373 IN PCI_IO_DEVICE
*Bridge
,
374 IN UINT8 StartBusNumber
,
375 OUT UINT8
*SubBusNumber
386 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
388 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
393 *SubBusNumber
= StartBusNumber
;
396 // First check to see whether the parent is ppb
398 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
399 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
402 // Check to see whether a pci device is present
404 Status
= PciDevicePresent (
412 if (!EFI_ERROR (Status
) &&
413 (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
))) {
416 // Reserved one bus for cardbus bridge
418 Status
= PciAllocateBusNumber (Bridge
, *SubBusNumber
, 1, SubBusNumber
);
419 if (EFI_ERROR (Status
)) {
422 SecondBus
= *SubBusNumber
;
424 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
426 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
428 Status
= PciRootBridgeIo
->Pci
.Write (
437 // Initialize SubBusNumber to SecondBus
439 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
440 Status
= PciRootBridgeIo
->Pci
.Write (
448 // If it is PPB, resursively search down this bridge
450 if (IS_PCI_BRIDGE (&Pci
)) {
453 Status
= PciRootBridgeIo
->Pci
.Write (
461 Status
= PciAssignBusNumber (
467 if (EFI_ERROR (Status
)) {
468 return EFI_DEVICE_ERROR
;
473 // Set the current maximum bus number under the PPB
475 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
477 Status
= PciRootBridgeIo
->Pci
.Write (
487 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
490 // Skip sub functions, this is not a multi function device
501 This routine is used to determine the root bridge attribute by interfacing
502 the host bridge resource allocation protocol.
504 @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
505 @param RootBridgeDev Root bridge instance
507 @retval EFI_SUCCESS Successfully got root bridge's attribute.
508 @retval other Failed to get attribute.
512 DetermineRootBridgeAttributes (
513 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
,
514 IN PCI_IO_DEVICE
*RootBridgeDev
519 EFI_HANDLE RootBridgeHandle
;
522 RootBridgeHandle
= RootBridgeDev
->Handle
;
525 // Get root bridge attribute by calling into pci host bridge resource allocation protocol
527 Status
= PciResAlloc
->GetAllocAttributes (
533 if (EFI_ERROR (Status
)) {
538 // Here is the point where PCI bus driver calls HOST bridge allocation protocol
539 // Currently we hardcoded for ea815
541 if ((Attributes
& EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
) != 0) {
542 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED
;
545 if ((Attributes
& EFI_PCI_HOST_BRIDGE_MEM64_DECODE
) != 0) {
546 RootBridgeDev
->Decodes
|= EFI_BRIDGE_MEM64_DECODE_SUPPORTED
;
547 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED
;
550 RootBridgeDev
->Decodes
|= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
;
551 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
552 RootBridgeDev
->Decodes
|= EFI_BRIDGE_IO16_DECODE_SUPPORTED
;
558 Get Max Option Rom size on specified bridge.
560 @param Bridge Given bridge device instance.
562 @return Max size of option rom needed.
566 GetMaxOptionRomSize (
567 IN PCI_IO_DEVICE
*Bridge
570 LIST_ENTRY
*CurrentLink
;
572 UINT64 MaxOptionRomSize
;
573 UINT64 TempOptionRomSize
;
575 MaxOptionRomSize
= 0;
578 // Go through bridges to reach all devices
580 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
581 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
582 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
583 if (!IsListEmpty (&Temp
->ChildList
)) {
586 // Get max option rom size under this bridge
588 TempOptionRomSize
= GetMaxOptionRomSize (Temp
);
591 // Compare with the option rom size of the bridge
592 // Get the larger one
594 if (Temp
->RomSize
> TempOptionRomSize
) {
595 TempOptionRomSize
= Temp
->RomSize
;
601 // For devices get the rom size directly
603 TempOptionRomSize
= Temp
->RomSize
;
607 // Get the largest rom size on this bridge
609 if (TempOptionRomSize
> MaxOptionRomSize
) {
610 MaxOptionRomSize
= TempOptionRomSize
;
613 CurrentLink
= CurrentLink
->ForwardLink
;
616 return MaxOptionRomSize
;
620 Process attributes of devices on this host bridge
622 @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
624 @retval EFI_SUCCESS Successfully process attribute.
625 @retval EFI_NOT_FOUND Can not find the specific root bridge device.
626 @retval other Failed to determine the root bridge device's attribute.
630 PciHostBridgeDeviceAttribute (
631 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
634 EFI_HANDLE RootBridgeHandle
;
635 PCI_IO_DEVICE
*RootBridgeDev
;
638 RootBridgeHandle
= NULL
;
640 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
643 // Get RootBridg Device by handle
645 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
647 if (RootBridgeDev
== NULL
) {
648 return EFI_NOT_FOUND
;
652 // Set the attributes for devcies behind the Root Bridge
654 Status
= DetermineDeviceAttribute (RootBridgeDev
);
655 if (EFI_ERROR (Status
)) {
665 Get resource allocation status from the ACPI resource descriptor.
667 @param AcpiConfig Point to Acpi configuration table.
668 @param IoResStatus Return the status of I/O resource.
669 @param Mem32ResStatus Return the status of 32-bit Memory resource.
670 @param PMem32ResStatus Return the status of 32-bit Prefetchable Memory resource.
671 @param Mem64ResStatus Return the status of 64-bit Memory resource.
672 @param PMem64ResStatus Return the status of 64-bit Prefetchable Memory resource.
676 GetResourceAllocationStatus (
678 OUT UINT64
*IoResStatus
,
679 OUT UINT64
*Mem32ResStatus
,
680 OUT UINT64
*PMem32ResStatus
,
681 OUT UINT64
*Mem64ResStatus
,
682 OUT UINT64
*PMem64ResStatus
687 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*ACPIAddressDesc
;
689 Temp
= (UINT8
*) AcpiConfig
;
691 while (*Temp
== ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
693 ACPIAddressDesc
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Temp
;
694 ResStatus
= ACPIAddressDesc
->AddrTranslationOffset
;
696 switch (ACPIAddressDesc
->ResType
) {
698 if (ACPIAddressDesc
->AddrSpaceGranularity
== 32) {
699 if (ACPIAddressDesc
->SpecificFlag
== 0x06) {
703 *PMem32ResStatus
= ResStatus
;
708 *Mem32ResStatus
= ResStatus
;
712 if (ACPIAddressDesc
->AddrSpaceGranularity
== 64) {
713 if (ACPIAddressDesc
->SpecificFlag
== 0x06) {
717 *PMem64ResStatus
= ResStatus
;
722 *Mem64ResStatus
= ResStatus
;
732 *IoResStatus
= ResStatus
;
739 Temp
+= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
744 Remove a PCI device from device pool and mark its bar.
746 @param PciDevice Instance of Pci device.
748 @retval EFI_SUCCESS Successfully remove the PCI device.
749 @retval EFI_ABORTED Pci device is a root bridge or a PCI-PCI bridge.
754 IN PCI_IO_DEVICE
*PciDevice
757 PCI_IO_DEVICE
*Bridge
;
759 LIST_ENTRY
*CurrentLink
;
762 // Remove the padding resource from a bridge
764 if ( IS_PCI_BRIDGE(&PciDevice
->Pci
) &&
765 PciDevice
->ResourcePaddingDescriptors
!= NULL
) {
766 FreePool (PciDevice
->ResourcePaddingDescriptors
);
767 PciDevice
->ResourcePaddingDescriptors
= NULL
;
774 if (IS_PCI_BRIDGE (&PciDevice
->Pci
) || (PciDevice
->Parent
== NULL
)) {
778 if (IS_CARDBUS_BRIDGE (&PciDevice
->Pci
)) {
780 // Get the root bridge device
783 while (Bridge
->Parent
!= NULL
) {
784 Bridge
= Bridge
->Parent
;
787 RemoveAllPciDeviceOnBridge (Bridge
->Handle
, PciDevice
);
792 InitializeP2C (PciDevice
);
798 Bridge
= PciDevice
->Parent
;
799 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
800 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
801 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
802 if (Temp
== PciDevice
) {
803 InitializePciDevice (Temp
);
804 RemoveEntryList (CurrentLink
);
808 CurrentLink
= CurrentLink
->ForwardLink
;
815 Determine whethter a PCI device can be rejected.
817 @param PciResNode Pointer to Pci resource node instance.
819 @retval TRUE The PCI device can be rejected.
820 @retval TRUE The PCI device cannot be rejected.
825 IN PCI_RESOURCE_NODE
*PciResNode
830 Temp
= PciResNode
->PciDev
;
833 // Ensure the device is present
840 // PPB and RB should go ahead
842 if (IS_PCI_BRIDGE (&Temp
->Pci
) || (Temp
->Parent
== NULL
)) {
847 // Skip device on Bus0
849 if ((Temp
->Parent
!= NULL
) && (Temp
->BusNumber
== 0)) {
856 if (IS_PCI_VGA (&Temp
->Pci
)) {
864 Compare two resource nodes and get the larger resource consumer.
866 @param PciResNode1 resource node 1 want to be compared
867 @param PciResNode2 resource node 2 want to be compared
869 @return Larger resource node.
873 GetLargerConsumerDevice (
874 IN PCI_RESOURCE_NODE
*PciResNode1
,
875 IN PCI_RESOURCE_NODE
*PciResNode2
878 if (PciResNode2
== NULL
) {
882 if ((IS_PCI_BRIDGE(&(PciResNode2
->PciDev
->Pci
)) || (PciResNode2
->PciDev
->Parent
== NULL
)) \
883 && (PciResNode2
->ResourceUsage
!= PciResUsagePadding
) )
888 if (PciResNode1
== NULL
) {
892 if ((PciResNode1
->Length
) > (PciResNode2
->Length
)) {
901 Get the max resource consumer in the host resource pool.
903 @param ResPool Pointer to resource pool node.
905 @return The max resource consumer in the host resource pool.
909 GetMaxResourceConsumerDevice (
910 IN PCI_RESOURCE_NODE
*ResPool
913 PCI_RESOURCE_NODE
*Temp
;
914 LIST_ENTRY
*CurrentLink
;
915 PCI_RESOURCE_NODE
*PciResNode
;
916 PCI_RESOURCE_NODE
*PPBResNode
;
920 CurrentLink
= ResPool
->ChildList
.ForwardLink
;
921 while (CurrentLink
!= NULL
&& CurrentLink
!= &ResPool
->ChildList
) {
923 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
925 if (!IsRejectiveDevice (Temp
)) {
926 CurrentLink
= CurrentLink
->ForwardLink
;
930 if ((IS_PCI_BRIDGE (&(Temp
->PciDev
->Pci
)) || (Temp
->PciDev
->Parent
== NULL
)) \
931 && (Temp
->ResourceUsage
!= PciResUsagePadding
))
933 PPBResNode
= GetMaxResourceConsumerDevice (Temp
);
934 PciResNode
= GetLargerConsumerDevice (PciResNode
, PPBResNode
);
936 PciResNode
= GetLargerConsumerDevice (PciResNode
, Temp
);
939 CurrentLink
= CurrentLink
->ForwardLink
;
946 Adjust host bridge allocation so as to reduce resource requirement
948 @param IoPool Pointer to instance of I/O resource Node.
949 @param Mem32Pool Pointer to instance of 32-bit memory resource Node.
950 @param PMem32Pool Pointer to instance of 32-bit Prefetchable memory resource node.
951 @param Mem64Pool Pointer to instance of 64-bit memory resource node.
952 @param PMem64Pool Pointer to instance of 64-bit Prefetchable memory resource node.
953 @param IoResStatus Status of I/O resource Node.
954 @param Mem32ResStatus Status of 32-bit memory resource Node.
955 @param PMem32ResStatus Status of 32-bit Prefetchable memory resource node.
956 @param Mem64ResStatus Status of 64-bit memory resource node.
957 @param PMem64ResStatus Status of 64-bit Prefetchable memory resource node.
959 @retval EFI_SUCCESS Successfully adjusted resoruce on host bridge.
960 @retval EFI_ABORTED Host bridge hasn't this resource type or no resource be adjusted.
964 PciHostBridgeAdjustAllocation (
965 IN PCI_RESOURCE_NODE
*IoPool
,
966 IN PCI_RESOURCE_NODE
*Mem32Pool
,
967 IN PCI_RESOURCE_NODE
*PMem32Pool
,
968 IN PCI_RESOURCE_NODE
*Mem64Pool
,
969 IN PCI_RESOURCE_NODE
*PMem64Pool
,
970 IN UINT64 IoResStatus
,
971 IN UINT64 Mem32ResStatus
,
972 IN UINT64 PMem32ResStatus
,
973 IN UINT64 Mem64ResStatus
,
974 IN UINT64 PMem64ResStatus
977 BOOLEAN AllocationAjusted
;
978 PCI_RESOURCE_NODE
*PciResNode
;
979 PCI_RESOURCE_NODE
*ResPool
[5];
980 PCI_IO_DEVICE
*RemovedPciDev
[5];
982 UINTN RemovedPciDevNum
;
986 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData
;
989 ZeroMem (RemovedPciDev
, 5 * sizeof (PCI_IO_DEVICE
*));
990 RemovedPciDevNum
= 0;
993 ResPool
[1] = Mem32Pool
;
994 ResPool
[2] = PMem32Pool
;
995 ResPool
[3] = Mem64Pool
;
996 ResPool
[4] = PMem64Pool
;
998 ResStatus
[0] = IoResStatus
;
999 ResStatus
[1] = Mem32ResStatus
;
1000 ResStatus
[2] = PMem32ResStatus
;
1001 ResStatus
[3] = Mem64ResStatus
;
1002 ResStatus
[4] = PMem64ResStatus
;
1004 AllocationAjusted
= FALSE
;
1006 for (ResType
= 0; ResType
< 5; ResType
++) {
1008 if (ResStatus
[ResType
] == EFI_RESOURCE_SATISFIED
) {
1012 if (ResStatus
[ResType
] == EFI_RESOURCE_NOT_SATISFIED
) {
1014 // Host bridge hasn't this resource type
1020 // Hostbridge hasn't enough resource
1022 PciResNode
= GetMaxResourceConsumerDevice (ResPool
[ResType
]);
1023 if (PciResNode
== NULL
) {
1028 // Check if the device has been removed before
1030 for (DevIndex
= 0; DevIndex
< RemovedPciDevNum
; DevIndex
++) {
1031 if (PciResNode
->PciDev
== RemovedPciDev
[DevIndex
]) {
1036 if (DevIndex
!= RemovedPciDevNum
) {
1041 // Remove the device if it isn't in the array
1043 Status
= RejectPciDevice (PciResNode
->PciDev
);
1044 if (Status
== EFI_SUCCESS
) {
1047 "PciBus: [%02x|%02x|%02x] was rejected due to resource confliction.\n",
1048 PciResNode
->PciDev
->BusNumber
, PciResNode
->PciDev
->DeviceNumber
, PciResNode
->PciDev
->FunctionNumber
1052 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
1055 // Have no way to get ReqRes, AllocRes & Bar here
1057 ZeroMem (&AllocFailExtendedData
, sizeof (AllocFailExtendedData
));
1058 AllocFailExtendedData
.DevicePathSize
= (UINT16
) sizeof (EFI_DEVICE_PATH_PROTOCOL
);
1059 AllocFailExtendedData
.DevicePath
= (UINT8
*) PciResNode
->PciDev
->DevicePath
;
1060 AllocFailExtendedData
.Bar
= PciResNode
->Bar
;
1062 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
1064 EFI_IO_BUS_PCI
| EFI_IOB_EC_RESOURCE_CONFLICT
,
1065 (VOID
*) &AllocFailExtendedData
,
1066 sizeof (AllocFailExtendedData
)
1070 // Add it to the array and indicate at least a device has been rejected
1072 RemovedPciDev
[RemovedPciDevNum
++] = PciResNode
->PciDev
;
1073 AllocationAjusted
= TRUE
;
1080 if (AllocationAjusted
) {
1088 Summary requests for all resource type, and contruct ACPI resource
1091 @param Bridge detecting bridge
1092 @param IoNode Pointer to instance of I/O resource Node
1093 @param Mem32Node Pointer to instance of 32-bit memory resource Node
1094 @param PMem32Node Pointer to instance of 32-bit Pmemory resource node
1095 @param Mem64Node Pointer to instance of 64-bit memory resource node
1096 @param PMem64Node Pointer to instance of 64-bit Pmemory resource node
1097 @param Config Output buffer holding new constructed APCI resource requestor
1099 @retval EFI_SUCCESS Successfully constructed ACPI resource.
1100 @retval EFI_OUT_OF_RESOURCES No memory availabe.
1104 ConstructAcpiResourceRequestor (
1105 IN PCI_IO_DEVICE
*Bridge
,
1106 IN PCI_RESOURCE_NODE
*IoNode
,
1107 IN PCI_RESOURCE_NODE
*Mem32Node
,
1108 IN PCI_RESOURCE_NODE
*PMem32Node
,
1109 IN PCI_RESOURCE_NODE
*Mem64Node
,
1110 IN PCI_RESOURCE_NODE
*PMem64Node
,
1116 UINT8
*Configuration
;
1117 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1118 EFI_ACPI_END_TAG_DESCRIPTOR
*PtrEnd
;
1126 // if there is io request, add to the io aperture
1128 if (ResourceRequestExisted (IoNode
)) {
1134 // if there is mem32 request, add to the mem32 aperture
1136 if (ResourceRequestExisted (Mem32Node
)) {
1142 // if there is pmem32 request, add to the pmem32 aperture
1144 if (ResourceRequestExisted (PMem32Node
)) {
1150 // if there is mem64 request, add to the mem64 aperture
1152 if (ResourceRequestExisted (Mem64Node
)) {
1158 // if there is pmem64 request, add to the pmem64 aperture
1160 if (ResourceRequestExisted (PMem64Node
)) {
1165 if (NumConfig
!= 0) {
1168 // If there is at least one type of resource request,
1169 // allocate a acpi resource node
1171 Configuration
= AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * NumConfig
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1172 if (Configuration
== NULL
) {
1173 return EFI_OUT_OF_RESOURCES
;
1176 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
;
1179 // Deal with io aperture
1181 if ((Aperture
& 0x01) != 0) {
1182 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1183 Ptr
->Len
= (UINT16
) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3);
1187 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
1191 Ptr
->SpecificFlag
= 1;
1192 Ptr
->AddrLen
= IoNode
->Length
;
1193 Ptr
->AddrRangeMax
= IoNode
->Alignment
;
1198 // Deal with mem32 aperture
1200 if ((Aperture
& 0x02) != 0) {
1201 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1202 Ptr
->Len
= (UINT16
) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3);
1206 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1210 Ptr
->SpecificFlag
= 0;
1214 Ptr
->AddrSpaceGranularity
= 32;
1215 Ptr
->AddrLen
= Mem32Node
->Length
;
1216 Ptr
->AddrRangeMax
= Mem32Node
->Alignment
;
1222 // Deal with Pmem32 aperture
1224 if ((Aperture
& 0x04) != 0) {
1225 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1226 Ptr
->Len
= (UINT16
) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3);
1230 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1234 Ptr
->SpecificFlag
= 0x6;
1238 Ptr
->AddrSpaceGranularity
= 32;
1239 Ptr
->AddrLen
= PMem32Node
->Length
;
1240 Ptr
->AddrRangeMax
= PMem32Node
->Alignment
;
1245 // Deal with mem64 aperture
1247 if ((Aperture
& 0x08) != 0) {
1248 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1249 Ptr
->Len
= (UINT16
) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3);
1253 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1257 Ptr
->SpecificFlag
= 0;
1261 Ptr
->AddrSpaceGranularity
= 64;
1262 Ptr
->AddrLen
= Mem64Node
->Length
;
1263 Ptr
->AddrRangeMax
= Mem64Node
->Alignment
;
1268 // Deal with Pmem64 aperture
1270 if ((Aperture
& 0x10) != 0) {
1271 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1272 Ptr
->Len
= (UINT16
) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3);
1276 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1280 Ptr
->SpecificFlag
= 0x06;
1284 Ptr
->AddrSpaceGranularity
= 64;
1285 Ptr
->AddrLen
= PMem64Node
->Length
;
1286 Ptr
->AddrRangeMax
= PMem64Node
->Alignment
;
1294 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) Ptr
;
1296 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1297 PtrEnd
->Checksum
= 0;
1302 // If there is no resource request
1304 Configuration
= AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1305 if (Configuration
== NULL
) {
1306 return EFI_OUT_OF_RESOURCES
;
1309 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) (Configuration
);
1310 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1312 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (Ptr
+ 1);
1313 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1314 PtrEnd
->Checksum
= 0;
1317 *Config
= Configuration
;
1323 Get resource base from an acpi configuration descriptor.
1325 @param Config An acpi configuration descriptor.
1326 @param IoBase Output of I/O resource base address.
1327 @param Mem32Base Output of 32-bit memory base address.
1328 @param PMem32Base Output of 32-bit prefetchable memory base address.
1329 @param Mem64Base Output of 64-bit memory base address.
1330 @param PMem64Base Output of 64-bit prefetchable memory base address.
1337 OUT UINT64
*Mem32Base
,
1338 OUT UINT64
*PMem32Base
,
1339 OUT UINT64
*Mem64Base
,
1340 OUT UINT64
*PMem64Base
1344 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1347 ASSERT (Config
!= NULL
);
1349 *IoBase
= 0xFFFFFFFFFFFFFFFFULL
;
1350 *Mem32Base
= 0xFFFFFFFFFFFFFFFFULL
;
1351 *PMem32Base
= 0xFFFFFFFFFFFFFFFFULL
;
1352 *Mem64Base
= 0xFFFFFFFFFFFFFFFFULL
;
1353 *PMem64Base
= 0xFFFFFFFFFFFFFFFFULL
;
1355 Temp
= (UINT8
*) Config
;
1357 while (*Temp
== ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
1359 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Temp
;
1360 ResStatus
= Ptr
->AddrTranslationOffset
;
1362 if (ResStatus
== EFI_RESOURCE_SATISFIED
) {
1364 switch (Ptr
->ResType
) {
1367 // Memory type aperture
1372 // Check to see the granularity
1374 if (Ptr
->AddrSpaceGranularity
== 32) {
1375 if ((Ptr
->SpecificFlag
& 0x06) != 0) {
1376 *PMem32Base
= Ptr
->AddrRangeMin
;
1378 *Mem32Base
= Ptr
->AddrRangeMin
;
1382 if (Ptr
->AddrSpaceGranularity
== 64) {
1383 if ((Ptr
->SpecificFlag
& 0x06) != 0) {
1384 *PMem64Base
= Ptr
->AddrRangeMin
;
1386 *Mem64Base
= Ptr
->AddrRangeMin
;
1396 *IoBase
= Ptr
->AddrRangeMin
;
1410 Temp
+= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
1415 Enumerate pci bridge, allocate resource and determine attribute
1416 for devices on this bridge.
1418 @param BridgeDev Pointer to instance of bridge device.
1420 @retval EFI_SUCCESS Successfully enumerated PCI bridge.
1421 @retval other Failed to enumerate.
1425 PciBridgeEnumerator (
1426 IN PCI_IO_DEVICE
*BridgeDev
1430 UINT8 StartBusNumber
;
1431 EFI_PCI_IO_PROTOCOL
*PciIo
;
1436 PciIo
= &(BridgeDev
->PciIo
);
1437 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x19, 1, &StartBusNumber
);
1439 if (EFI_ERROR (Status
)) {
1443 Status
= PciAssignBusNumber (
1449 if (EFI_ERROR (Status
)) {
1453 Status
= PciPciDeviceInfoCollector (BridgeDev
, StartBusNumber
);
1455 if (EFI_ERROR (Status
)) {
1459 Status
= PciBridgeResourceAllocator (BridgeDev
);
1461 if (EFI_ERROR (Status
)) {
1465 Status
= DetermineDeviceAttribute (BridgeDev
);
1467 if (EFI_ERROR (Status
)) {
1476 Allocate all kinds of resource for PCI bridge.
1478 @param Bridge Pointer to bridge instance.
1480 @retval EFI_SUCCESS Successfully allocated resource for PCI bridge.
1481 @retval other Failed to allocate resource for bridge.
1485 PciBridgeResourceAllocator (
1486 IN PCI_IO_DEVICE
*Bridge
1489 PCI_RESOURCE_NODE
*IoBridge
;
1490 PCI_RESOURCE_NODE
*Mem32Bridge
;
1491 PCI_RESOURCE_NODE
*PMem32Bridge
;
1492 PCI_RESOURCE_NODE
*Mem64Bridge
;
1493 PCI_RESOURCE_NODE
*PMem64Bridge
;
1501 IoBridge
= CreateResourceNode (
1504 Bridge
->BridgeIoAlignment
,
1510 Mem32Bridge
= CreateResourceNode (
1519 PMem32Bridge
= CreateResourceNode (
1528 Mem64Bridge
= CreateResourceNode (
1537 PMem64Bridge
= CreateResourceNode (
1547 // Create resourcemap by going through all the devices subject to this root bridge
1558 Status
= GetResourceBaseFromBridge (
1567 if (EFI_ERROR (Status
)) {
1572 // Program IO resources
1580 // Program Mem32 resources
1588 // Program PMem32 resources
1596 // Program Mem64 resources
1604 // Program PMem64 resources
1611 DestroyResourceTree (IoBridge
);
1612 DestroyResourceTree (Mem32Bridge
);
1613 DestroyResourceTree (PMem32Bridge
);
1614 DestroyResourceTree (PMem64Bridge
);
1615 DestroyResourceTree (Mem64Bridge
);
1617 gBS
->FreePool (IoBridge
);
1618 gBS
->FreePool (Mem32Bridge
);
1619 gBS
->FreePool (PMem32Bridge
);
1620 gBS
->FreePool (PMem64Bridge
);
1621 gBS
->FreePool (Mem64Bridge
);
1627 Get resource base address for a pci bridge device.
1629 @param Bridge Given Pci driver instance.
1630 @param IoBase Output for base address of I/O type resource.
1631 @param Mem32Base Output for base address of 32-bit memory type resource.
1632 @param PMem32Base Ooutput for base address of 32-bit Pmemory type resource.
1633 @param Mem64Base Output for base address of 64-bit memory type resource.
1634 @param PMem64Base Output for base address of 64-bit Pmemory type resource.
1636 @retval EFI_SUCCESS Successfully got resource base address.
1637 @retval EFI_OUT_OF_RESOURCES PCI bridge is not available.
1641 GetResourceBaseFromBridge (
1642 IN PCI_IO_DEVICE
*Bridge
,
1644 OUT UINT64
*Mem32Base
,
1645 OUT UINT64
*PMem32Base
,
1646 OUT UINT64
*Mem64Base
,
1647 OUT UINT64
*PMem64Base
1650 if (!Bridge
->Allocated
) {
1651 return EFI_OUT_OF_RESOURCES
;
1655 *Mem32Base
= gAllOne
;
1656 *PMem32Base
= gAllOne
;
1657 *Mem64Base
= gAllOne
;
1658 *PMem64Base
= gAllOne
;
1660 if (IS_PCI_BRIDGE (&Bridge
->Pci
)) {
1662 if (Bridge
->PciBar
[PPB_IO_RANGE
].Length
> 0) {
1663 *IoBase
= Bridge
->PciBar
[PPB_IO_RANGE
].BaseAddress
;
1666 if (Bridge
->PciBar
[PPB_MEM32_RANGE
].Length
> 0) {
1667 *Mem32Base
= Bridge
->PciBar
[PPB_MEM32_RANGE
].BaseAddress
;
1670 if (Bridge
->PciBar
[PPB_PMEM32_RANGE
].Length
> 0) {
1671 *PMem32Base
= Bridge
->PciBar
[PPB_PMEM32_RANGE
].BaseAddress
;
1674 if (Bridge
->PciBar
[PPB_PMEM64_RANGE
].Length
> 0) {
1675 *PMem64Base
= Bridge
->PciBar
[PPB_PMEM64_RANGE
].BaseAddress
;
1677 *PMem64Base
= gAllOne
;
1682 if (IS_CARDBUS_BRIDGE (&Bridge
->Pci
)) {
1683 if (Bridge
->PciBar
[P2C_IO_1
].Length
> 0) {
1684 *IoBase
= Bridge
->PciBar
[P2C_IO_1
].BaseAddress
;
1686 if (Bridge
->PciBar
[P2C_IO_2
].Length
> 0) {
1687 *IoBase
= Bridge
->PciBar
[P2C_IO_2
].BaseAddress
;
1691 if (Bridge
->PciBar
[P2C_MEM_1
].Length
> 0) {
1692 if (Bridge
->PciBar
[P2C_MEM_1
].BarType
== PciBarTypePMem32
) {
1693 *PMem32Base
= Bridge
->PciBar
[P2C_MEM_1
].BaseAddress
;
1696 if (Bridge
->PciBar
[P2C_MEM_1
].BarType
== PciBarTypeMem32
) {
1697 *Mem32Base
= Bridge
->PciBar
[P2C_MEM_1
].BaseAddress
;
1701 if (Bridge
->PciBar
[P2C_MEM_2
].Length
> 0) {
1702 if (Bridge
->PciBar
[P2C_MEM_2
].BarType
== PciBarTypePMem32
) {
1703 *PMem32Base
= Bridge
->PciBar
[P2C_MEM_2
].BaseAddress
;
1706 if (Bridge
->PciBar
[P2C_MEM_2
].BarType
== PciBarTypeMem32
) {
1707 *Mem32Base
= Bridge
->PciBar
[P2C_MEM_2
].BaseAddress
;
1716 These are the notifications from the PCI bus driver that it is about to enter a certain
1717 phase of the PCI enumeration process.
1719 This member function can be used to notify the host bridge driver to perform specific actions,
1720 including any chipset-specific initialization, so that the chipset is ready to enter the next phase.
1721 Eight notification points are defined at this time. See belows:
1722 EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apertures and internal data
1723 structures. The PCI enumerator should issue this notification
1724 before starting a fresh enumeration process. Enumeration cannot
1725 be restarted after sending any other notification such as
1726 EfiPciHostBridgeBeginBusAllocation.
1727 EfiPciHostBridgeBeginBusAllocation The bus allocation phase is about to begin. No specific action is
1728 required here. This notification can be used to perform any
1729 chipset-specific programming.
1730 EfiPciHostBridgeEndBusAllocation The bus allocation and bus programming phase is complete. No
1731 specific action is required here. This notification can be used to
1732 perform any chipset-specific programming.
1733 EfiPciHostBridgeBeginResourceAllocation
1734 The resource allocation phase is about to begin. No specific
1735 action is required here. This notification can be used to perform
1736 any chipset-specific programming.
1737 EfiPciHostBridgeAllocateResources Allocates resources per previously submitted requests for all the PCI
1738 root bridges. These resource settings are returned on the next call to
1739 GetProposedResources(). Before calling NotifyPhase() with a Phase of
1740 EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible
1741 for gathering I/O and memory requests for
1742 all the PCI root bridges and submitting these requests using
1743 SubmitResources(). This function pads the resource amount
1744 to suit the root bridge hardware, takes care of dependencies between
1745 the PCI root bridges, and calls the Global Coherency Domain (GCD)
1746 with the allocation request. In the case of padding, the allocated range
1747 could be bigger than what was requested.
1748 EfiPciHostBridgeSetResources Programs the host bridge hardware to decode previously allocated
1749 resources (proposed resources) for all the PCI root bridges. After the
1750 hardware is programmed, reassigning resources will not be supported.
1751 The bus settings are not affected.
1752 EfiPciHostBridgeFreeResources Deallocates resources that were previously allocated for all the PCI
1753 root bridges and resets the I/O and memory apertures to their initial
1754 state. The bus settings are not affected. If the request to allocate
1755 resources fails, the PCI enumerator can use this notification to
1756 deallocate previous resources, adjust the requests, and retry
1758 EfiPciHostBridgeEndResourceAllocation The resource allocation phase is completed. No specific action is
1759 required here. This notification can be used to perform any chipsetspecific
1762 @param[in] PciResAlloc The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
1763 @param[in] Phase The phase during enumeration
1765 @retval EFI_NOT_READY This phase cannot be entered at this time. For example, this error
1766 is valid for a Phase of EfiPciHostBridgeAllocateResources if
1767 SubmitResources() has not been called for one or more
1768 PCI root bridges before this call
1769 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. This error is valid
1770 for a Phase of EfiPciHostBridgeSetResources.
1771 @retval EFI_INVALID_PARAMETER Invalid phase parameter
1772 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1773 This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the
1774 previously submitted resource requests cannot be fulfilled or
1775 were only partially fulfilled.
1776 @retval EFI_SUCCESS The notification was accepted without any errors.
1781 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
,
1782 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
1785 EFI_HANDLE HostBridgeHandle
;
1786 EFI_HANDLE RootBridgeHandle
;
1787 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1790 HostBridgeHandle
= NULL
;
1791 RootBridgeHandle
= NULL
;
1792 if (gPciPlatformProtocol
!= NULL
) {
1794 // Get Host Bridge Handle.
1796 PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
);
1799 // Get the rootbridge Io protocol to find the host bridge handle
1801 Status
= gBS
->HandleProtocol (
1803 &gEfiPciRootBridgeIoProtocolGuid
,
1804 (VOID
**) &PciRootBridgeIo
1807 if (EFI_ERROR (Status
)) {
1808 return EFI_NOT_FOUND
;
1811 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
1814 // Call PlatformPci::PlatformNotify() if the protocol is present.
1816 gPciPlatformProtocol
->PlatformNotify (
1817 gPciPlatformProtocol
,
1822 } else if (gPciOverrideProtocol
!= NULL
){
1824 // Get Host Bridge Handle.
1826 PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
);
1829 // Get the rootbridge Io protocol to find the host bridge handle
1831 Status
= gBS
->HandleProtocol (
1833 &gEfiPciRootBridgeIoProtocolGuid
,
1834 (VOID
**) &PciRootBridgeIo
1837 if (EFI_ERROR (Status
)) {
1838 return EFI_NOT_FOUND
;
1841 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
1844 // Call PlatformPci::PhaseNotify() if the protocol is present.
1846 gPciOverrideProtocol
->PlatformNotify (
1847 gPciOverrideProtocol
,
1854 Status
= PciResAlloc
->NotifyPhase (
1859 if (gPciPlatformProtocol
!= NULL
) {
1861 // Call PlatformPci::PlatformNotify() if the protocol is present.
1863 gPciPlatformProtocol
->PlatformNotify (
1864 gPciPlatformProtocol
,
1870 } else if (gPciOverrideProtocol
!= NULL
) {
1872 // Call PlatformPci::PhaseNotify() if the protocol is present.
1874 gPciOverrideProtocol
->PlatformNotify (
1875 gPciOverrideProtocol
,
1886 Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
1887 stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
1888 PCI controllers before enumeration.
1890 This function is called during the PCI enumeration process. No specific action is expected from this
1891 member function. It allows the host bridge driver to preinitialize individual PCI controllers before
1894 @param Bridge Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
1895 @param Bus The bus number of the pci device.
1896 @param Device The device number of the pci device.
1897 @param Func The function number of the pci device.
1898 @param Phase The phase of the PCI device enumeration.
1900 @retval EFI_SUCCESS The requested parameters were returned.
1901 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
1902 @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined in
1903 EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
1904 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. The PCI enumerator should
1905 not enumerate this device, including its child devices if it is a PCI-to-PCI
1910 PreprocessController (
1911 IN PCI_IO_DEVICE
*Bridge
,
1915 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1918 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS RootBridgePciAddress
;
1919 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
;
1920 EFI_HANDLE RootBridgeHandle
;
1921 EFI_HANDLE HostBridgeHandle
;
1925 // Get the host bridge handle
1927 HostBridgeHandle
= Bridge
->PciRootBridgeIo
->ParentHandle
;
1930 // Get the pci host bridge resource allocation protocol
1932 Status
= gBS
->OpenProtocol (
1934 &gEfiPciHostBridgeResourceAllocationProtocolGuid
,
1935 (VOID
**) &PciResAlloc
,
1938 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1941 if (EFI_ERROR (Status
)) {
1942 return EFI_UNSUPPORTED
;
1946 // Get Root Brige Handle
1948 while (Bridge
->Parent
!= NULL
) {
1949 Bridge
= Bridge
->Parent
;
1952 RootBridgeHandle
= Bridge
->Handle
;
1954 RootBridgePciAddress
.Register
= 0;
1955 RootBridgePciAddress
.Function
= Func
;
1956 RootBridgePciAddress
.Device
= Device
;
1957 RootBridgePciAddress
.Bus
= Bus
;
1958 RootBridgePciAddress
.ExtendedRegister
= 0;
1960 if (gPciPlatformProtocol
!= NULL
) {
1962 // Call PlatformPci::PrepController() if the protocol is present.
1964 gPciPlatformProtocol
->PlatformPrepController (
1965 gPciPlatformProtocol
,
1968 RootBridgePciAddress
,
1972 } else if (gPciOverrideProtocol
!= NULL
) {
1974 // Call PlatformPci::PrepController() if the protocol is present.
1976 gPciOverrideProtocol
->PlatformPrepController (
1977 gPciOverrideProtocol
,
1980 RootBridgePciAddress
,
1986 Status
= PciResAlloc
->PreprocessController (
1989 RootBridgePciAddress
,
1993 if (gPciPlatformProtocol
!= NULL
) {
1995 // Call PlatformPci::PrepController() if the protocol is present.
1997 gPciPlatformProtocol
->PlatformPrepController (
1998 gPciPlatformProtocol
,
2001 RootBridgePciAddress
,
2005 } else if (gPciOverrideProtocol
!= NULL
) {
2007 // Call PlatformPci::PrepController() if the protocol is present.
2009 gPciOverrideProtocol
->PlatformPrepController (
2010 gPciOverrideProtocol
,
2013 RootBridgePciAddress
,
2023 This function allows the PCI bus driver to be notified to act as requested when a hot-plug event has
2024 happened on the hot-plug controller. Currently, the operations include add operation and remove operation..
2026 @param This A pointer to the hot plug request protocol.
2027 @param Operation The operation the PCI bus driver is requested to make.
2028 @param Controller The handle of the hot-plug controller.
2029 @param RemainingDevicePath The remaining device path for the PCI-like hot-plug device.
2030 @param NumberOfChildren The number of child handles.
2031 For a add operation, it is an output parameter.
2032 For a remove operation, it's an input parameter.
2033 @param ChildHandleBuffer The buffer which contains the child handles.
2035 @retval EFI_INVALID_PARAMETER Operation is not a legal value.
2036 Controller is NULL or not a valid handle.
2037 NumberOfChildren is NULL.
2038 ChildHandleBuffer is NULL while Operation is add.
2039 @retval EFI_OUT_OF_RESOURCES There are no enough resources to start the devices.
2040 @retval EFI_NOT_FOUND Can not find bridge according to controller handle.
2041 @retval EFI_SUCCESS The handles for the specified device have been created or destroyed
2042 as requested, and for an add operation, the new handles are
2043 returned in ChildHandleBuffer.
2047 PciHotPlugRequestNotify (
2048 IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL
* This
,
2049 IN EFI_PCI_HOTPLUG_OPERATION Operation
,
2050 IN EFI_HANDLE Controller
,
2051 IN EFI_DEVICE_PATH_PROTOCOL
* RemainingDevicePath OPTIONAL
,
2052 IN OUT UINT8
*NumberOfChildren
,
2053 IN OUT EFI_HANDLE
* ChildHandleBuffer
2056 PCI_IO_DEVICE
*Bridge
;
2057 PCI_IO_DEVICE
*Temp
;
2058 EFI_PCI_IO_PROTOCOL
*PciIo
;
2060 EFI_HANDLE RootBridgeHandle
;
2064 // Check input parameter validity
2066 if ((Controller
== NULL
) || (NumberOfChildren
== NULL
)){
2067 return EFI_INVALID_PARAMETER
;
2070 if ((Operation
!= EfiPciHotPlugRequestAdd
) && (Operation
!= EfiPciHotplugRequestRemove
)) {
2071 return EFI_INVALID_PARAMETER
;
2074 if (Operation
== EfiPciHotPlugRequestAdd
){
2075 if (ChildHandleBuffer
== NULL
) {
2076 return EFI_INVALID_PARAMETER
;
2078 } else if ((Operation
== EfiPciHotplugRequestRemove
) && (*NumberOfChildren
!= 0)) {
2079 if (ChildHandleBuffer
== NULL
) {
2080 return EFI_INVALID_PARAMETER
;
2084 Status
= gBS
->OpenProtocol (
2086 &gEfiPciIoProtocolGuid
,
2088 gPciBusDriverBinding
.DriverBindingHandle
,
2090 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2093 if (EFI_ERROR (Status
)) {
2094 return EFI_NOT_FOUND
;
2097 Bridge
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
2100 // Get root bridge handle
2103 while (Temp
->Parent
!= NULL
) {
2104 Temp
= Temp
->Parent
;
2107 RootBridgeHandle
= Temp
->Handle
;
2109 if (Operation
== EfiPciHotPlugRequestAdd
) {
2111 // Report Status Code to indicate hot plug happens
2113 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
2115 (EFI_IO_BUS_PCI
| EFI_IOB_PC_HOTPLUG
),
2119 if (NumberOfChildren
!= NULL
) {
2120 *NumberOfChildren
= 0;
2123 if (IsListEmpty (&Bridge
->ChildList
)) {
2125 Status
= PciBridgeEnumerator (Bridge
);
2127 if (EFI_ERROR (Status
)) {
2132 Status
= StartPciDevicesOnBridge (
2135 RemainingDevicePath
,
2143 if (Operation
== EfiPciHotplugRequestRemove
) {
2145 if (*NumberOfChildren
== 0) {
2147 // Remove all devices on the bridge
2149 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Bridge
);
2154 for (Index
= 0; Index
< *NumberOfChildren
; Index
++) {
2156 // De register all the pci device
2158 Status
= DeRegisterPciDevice (RootBridgeHandle
, ChildHandleBuffer
[Index
]);
2160 if (EFI_ERROR (Status
)) {
2175 Search hostbridge according to given handle
2177 @param RootBridgeHandle Host bridge handle.
2179 @retval TRUE Found host bridge handle.
2180 @retval FALSE Not found hot bridge handle.
2184 SearchHostBridgeHandle (
2185 IN EFI_HANDLE RootBridgeHandle
2188 EFI_HANDLE HostBridgeHandle
;
2189 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2194 // Get the rootbridge Io protocol to find the host bridge handle
2196 Status
= gBS
->OpenProtocol (
2198 &gEfiPciRootBridgeIoProtocolGuid
,
2199 (VOID
**) &PciRootBridgeIo
,
2200 gPciBusDriverBinding
.DriverBindingHandle
,
2202 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2205 if (EFI_ERROR (Status
)) {
2209 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
2210 for (Index
= 0; Index
< gPciHostBridgeNumber
; Index
++) {
2211 if (HostBridgeHandle
== gPciHostBrigeHandles
[Index
]) {
2220 Add host bridge handle to global variable for enumerating.
2222 @param HostBridgeHandle Host bridge handle.
2224 @retval EFI_SUCCESS Successfully added host bridge.
2225 @retval EFI_ABORTED Host bridge is NULL, or given host bridge
2226 has been in host bridge list.
2230 AddHostBridgeEnumerator (
2231 IN EFI_HANDLE HostBridgeHandle
2236 if (HostBridgeHandle
== NULL
) {
2240 for (Index
= 0; Index
< gPciHostBridgeNumber
; Index
++) {
2241 if (HostBridgeHandle
== gPciHostBrigeHandles
[Index
]) {
2246 if (Index
< PCI_MAX_HOST_BRIDGE_NUM
) {
2247 gPciHostBrigeHandles
[Index
] = HostBridgeHandle
;
2248 gPciHostBridgeNumber
++;