2 Internal library implementation for PCI Bus module.
4 Copyright (c) 2006 - 2009, Intel Corporation
5 All rights reserved. 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.
19 Retrieve the PCI Card device BAR information via PciIo interface.
21 @param PciIoDevice PCI Card device instance.
26 IN PCI_IO_DEVICE
*PciIoDevice
31 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
36 // Read PciBar information from the bar register
38 if (!gFullEnumeration
) {
41 &(PciIoDevice
->PciIo
),
43 PCI_CARD_MEMORY_BASE_0
,
48 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BaseAddress
= (UINT64
) (Address
);
49 (PciIoDevice
->PciBar
)[P2C_MEM_1
].Length
= 0x2000000;
50 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BarType
= PciBarTypeMem32
;
54 &(PciIoDevice
->PciIo
),
56 PCI_CARD_MEMORY_BASE_1
,
60 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BaseAddress
= (UINT64
) (Address
);
61 (PciIoDevice
->PciBar
)[P2C_MEM_2
].Length
= 0x2000000;
62 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BarType
= PciBarTypePMem32
;
66 &(PciIoDevice
->PciIo
),
68 PCI_CARD_IO_BASE_0_LOWER
,
72 (PciIoDevice
->PciBar
)[P2C_IO_1
].BaseAddress
= (UINT64
) (Address
);
73 (PciIoDevice
->PciBar
)[P2C_IO_1
].Length
= 0x100;
74 (PciIoDevice
->PciBar
)[P2C_IO_1
].BarType
= PciBarTypeIo16
;
78 &(PciIoDevice
->PciIo
),
80 PCI_CARD_IO_BASE_1_LOWER
,
84 (PciIoDevice
->PciBar
)[P2C_IO_2
].BaseAddress
= (UINT64
) (Address
);
85 (PciIoDevice
->PciBar
)[P2C_IO_2
].Length
= 0x100;
86 (PciIoDevice
->PciBar
)[P2C_IO_2
].BarType
= PciBarTypeIo16
;
90 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
91 GetResourcePaddingForHpb (PciIoDevice
);
96 Remove rejected pci device from specific root bridge
99 @param RootBridgeHandle Specific parent root bridge handle.
100 @param Bridge Bridge device instance.
104 RemoveRejectedPciDevices (
105 IN EFI_HANDLE RootBridgeHandle
,
106 IN PCI_IO_DEVICE
*Bridge
110 LIST_ENTRY
*CurrentLink
;
111 LIST_ENTRY
*LastLink
;
113 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
117 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
119 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
121 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
123 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
125 // Remove rejected devices recusively
127 RemoveRejectedPciDevices (RootBridgeHandle
, Temp
);
130 // Skip rejection for all PPBs, while detect rejection for others
132 if (IsPciDeviceRejected (Temp
)) {
135 // For P2C, remove all devices on it
137 if (!IsListEmpty (&Temp
->ChildList
)) {
138 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Temp
);
142 // Finally remove itself
144 LastLink
= CurrentLink
->BackLink
;
145 RemoveEntryList (CurrentLink
);
146 FreePciDevice (Temp
);
148 CurrentLink
= LastLink
;
152 CurrentLink
= CurrentLink
->ForwardLink
;
157 Submits the I/O and memory resource requirements for the specified PCI Host Bridge.
159 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
161 @retval EFI_SUCCESS Successfully finished resource allocation.
162 @retval EFI_NOT_FOUND Cannot get root bridge instance.
163 @retval EFI_OUT_OF_RESOURCES Platform failed to program the resources if no hot plug supported.
164 @retval other Some error occurred when allocating resources for the PCI Host Bridge.
166 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
170 PciHostBridgeResourceAllocator (
171 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
174 PCI_IO_DEVICE
*RootBridgeDev
;
175 EFI_HANDLE RootBridgeHandle
;
184 UINT64 Mem32ResStatus
;
185 UINT64 PMem32ResStatus
;
186 UINT64 Mem64ResStatus
;
187 UINT64 PMem64ResStatus
;
188 UINT64 MaxOptionRomSize
;
189 PCI_RESOURCE_NODE
*IoBridge
;
190 PCI_RESOURCE_NODE
*Mem32Bridge
;
191 PCI_RESOURCE_NODE
*PMem32Bridge
;
192 PCI_RESOURCE_NODE
*Mem64Bridge
;
193 PCI_RESOURCE_NODE
*PMem64Bridge
;
194 PCI_RESOURCE_NODE IoPool
;
195 PCI_RESOURCE_NODE Mem32Pool
;
196 PCI_RESOURCE_NODE PMem32Pool
;
197 PCI_RESOURCE_NODE Mem64Pool
;
198 PCI_RESOURCE_NODE PMem64Pool
;
200 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData
;
201 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData
;
209 // It may try several times if the resource allocation fails
213 // Initialize resource pool
215 InitializeResourcePool (&IoPool
, PciBarTypeIo16
);
216 InitializeResourcePool (&Mem32Pool
, PciBarTypeMem32
);
217 InitializeResourcePool (&PMem32Pool
, PciBarTypePMem32
);
218 InitializeResourcePool (&Mem64Pool
, PciBarTypeMem64
);
219 InitializeResourcePool (&PMem64Pool
, PciBarTypePMem64
);
221 RootBridgeDev
= NULL
;
222 RootBridgeHandle
= 0;
224 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
226 // Get Root Bridge Device by handle
228 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
230 if (RootBridgeDev
== NULL
) {
231 return EFI_NOT_FOUND
;
235 // Create the entire system resource map from the information collected by
236 // enumerator. Several resource tree was created
239 IoBridge
= CreateResourceNode (
248 Mem32Bridge
= CreateResourceNode (
257 PMem32Bridge
= CreateResourceNode (
266 Mem64Bridge
= CreateResourceNode (
275 PMem64Bridge
= CreateResourceNode (
285 // Create resourcemap by going through all the devices subject to this root bridge
297 // Get the max ROM size that the root bridge can process
299 RootBridgeDev
->RomSize
= Mem32Bridge
->Length
;
302 // Skip to enlarge the resource request during realloction
306 // Get Max Option Rom size for current root bridge
308 MaxOptionRomSize
= GetMaxOptionRomSize (RootBridgeDev
);
311 // Enlarger the mem32 resource to accomdate the option rom
312 // if the mem32 resource is not enough to hold the rom
314 if (MaxOptionRomSize
> Mem32Bridge
->Length
) {
316 Mem32Bridge
->Length
= MaxOptionRomSize
;
317 RootBridgeDev
->RomSize
= MaxOptionRomSize
;
320 // Alignment should be adjusted as well
322 if (Mem32Bridge
->Alignment
< MaxOptionRomSize
- 1) {
323 Mem32Bridge
->Alignment
= MaxOptionRomSize
- 1;
329 // Based on the all the resource tree, contruct ACPI resource node to
330 // submit the resource aperture to pci host bridge protocol
332 Status
= ConstructAcpiResourceRequestor (
343 // Insert these resource nodes into the database
345 InsertResourceNode (&IoPool
, IoBridge
);
346 InsertResourceNode (&Mem32Pool
, Mem32Bridge
);
347 InsertResourceNode (&PMem32Pool
, PMem32Bridge
);
348 InsertResourceNode (&Mem64Pool
, Mem64Bridge
);
349 InsertResourceNode (&PMem64Pool
, PMem64Bridge
);
351 if (Status
== EFI_SUCCESS
) {
353 // Submit the resource requirement
355 Status
= PciResAlloc
->SubmitResources (
357 RootBridgeDev
->Handle
,
363 // Free acpi resource node
365 if (AcpiConfig
!= NULL
) {
366 FreePool (AcpiConfig
);
369 if (EFI_ERROR (Status
)) {
371 // Destroy all the resource tree
373 DestroyResourceTree (&IoPool
);
374 DestroyResourceTree (&Mem32Pool
);
375 DestroyResourceTree (&PMem32Pool
);
376 DestroyResourceTree (&Mem64Pool
);
377 DestroyResourceTree (&PMem64Pool
);
386 // Notify platform to start to program the resource
388 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeAllocateResources
);
389 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
391 // If Hot Plug is not supported
393 if (EFI_ERROR (Status
)) {
395 // Allocation failed, then return
397 return EFI_OUT_OF_RESOURCES
;
400 // Allocation succeed.
401 // Get host bridge handle for status report, and then skip the main while
403 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
409 // If Hot Plug is supported
411 if (!EFI_ERROR (Status
)) {
413 // Allocation succeed, then continue the following
419 // If the resource allocation is unsuccessful, free resources on bridge
422 RootBridgeDev
= NULL
;
423 RootBridgeHandle
= 0;
425 IoResStatus
= EFI_RESOURCE_SATISFIED
;
426 Mem32ResStatus
= EFI_RESOURCE_SATISFIED
;
427 PMem32ResStatus
= EFI_RESOURCE_SATISFIED
;
428 Mem64ResStatus
= EFI_RESOURCE_SATISFIED
;
429 PMem64ResStatus
= EFI_RESOURCE_SATISFIED
;
431 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
433 // Get RootBridg Device by handle
435 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
436 if (RootBridgeDev
== NULL
) {
437 return EFI_NOT_FOUND
;
441 // Get host bridge handle for status report
443 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
446 // Get acpi resource node for all the resource types
450 Status
= PciResAlloc
->GetProposedResources (
452 RootBridgeDev
->Handle
,
456 if (EFI_ERROR (Status
)) {
460 if (AcpiConfig
!= NULL
) {
462 // Adjust resource allocation policy for each RB
464 GetResourceAllocationStatus (
472 FreePool (AcpiConfig
);
480 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
483 // It is very difficult to follow the spec here
484 // Device path , Bar index can not be get here
486 ZeroMem (&AllocFailExtendedData
, sizeof (AllocFailExtendedData
));
488 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
490 EFI_IO_BUS_PCI
| EFI_IOB_EC_RESOURCE_CONFLICT
,
491 (VOID
*) &AllocFailExtendedData
,
492 sizeof (AllocFailExtendedData
)
495 Status
= PciHostBridgeAdjustAllocation (
509 // Destroy all the resource tree
511 DestroyResourceTree (&IoPool
);
512 DestroyResourceTree (&Mem32Pool
);
513 DestroyResourceTree (&PMem32Pool
);
514 DestroyResourceTree (&Mem64Pool
);
515 DestroyResourceTree (&PMem64Pool
);
517 NotifyPhase (PciResAlloc
, EfiPciHostBridgeFreeResources
);
519 if (EFI_ERROR (Status
)) {
531 // Raise the EFI_IOB_PCI_RES_ALLOC status code
533 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
535 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_RES_ALLOC
,
536 (VOID
*) &HandleExtendedData
,
537 sizeof (HandleExtendedData
)
541 // Notify pci bus driver starts to program the resource
543 NotifyPhase (PciResAlloc
, EfiPciHostBridgeSetResources
);
545 RootBridgeDev
= NULL
;
547 RootBridgeHandle
= 0;
549 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
551 // Get RootBridg Device by handle
553 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
555 if (RootBridgeDev
== NULL
) {
556 return EFI_NOT_FOUND
;
560 // Get acpi resource node for all the resource types
563 Status
= PciResAlloc
->GetProposedResources (
565 RootBridgeDev
->Handle
,
569 if (EFI_ERROR (Status
)) {
574 // Get the resource base by interpreting acpi resource node
587 // Process option rom for this root bridge
589 ProcessOptionRom (RootBridgeDev
, Mem32Base
, RootBridgeDev
->RomSize
);
592 // Create the entire system resource map from the information collected by
593 // enumerator. Several resource tree was created
610 // Program IO resources
618 // Program Mem32 resources
626 // Program PMem32 resources
634 // Program Mem64 resources
642 // Program PMem64 resources
649 FreePool (AcpiConfig
);
653 // Destroy all the resource tree
655 DestroyResourceTree (&IoPool
);
656 DestroyResourceTree (&Mem32Pool
);
657 DestroyResourceTree (&PMem32Pool
);
658 DestroyResourceTree (&Mem64Pool
);
659 DestroyResourceTree (&PMem64Pool
);
662 // Notify the resource allocation phase is to end
664 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndResourceAllocation
);
670 Scan pci bus and assign bus number to the given PCI bus system.
672 @param Bridge Bridge device instance.
673 @param StartBusNumber start point.
674 @param SubBusNumber Point to sub bus number.
675 @param PaddedBusRange Customized bus number.
677 @retval EFI_SUCCESS Successfully scanned and assigned bus number.
678 @retval other Some error occurred when scanning pci bus.
680 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
685 IN PCI_IO_DEVICE
*Bridge
,
686 IN UINT8 StartBusNumber
,
687 OUT UINT8
*SubBusNumber
,
688 OUT UINT8
*PaddedBusRange
699 PCI_IO_DEVICE
*PciDevice
;
703 EFI_HPC_PADDING_ATTRIBUTES Attributes
;
704 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
706 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
709 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
713 Attributes
= (EFI_HPC_PADDING_ATTRIBUTES
) 0;
719 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
720 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
723 // Check to see whether a pci device is present
725 Status
= PciDevicePresent (
733 if (EFI_ERROR (Status
)) {
736 // Skip sub functions, this is not a multi function device
744 DEBUG((EFI_D_ERROR
, "Found DEV(%02d,%02d,%02d)\n", StartBusNumber
, Device
, Func
));
746 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
748 // Get the PCI device information
750 Status
= PciSearchDevice (
759 ASSERT (!EFI_ERROR (Status
));
761 PciAddress
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0);
763 if (!IS_PCI_BRIDGE (&Pci
)) {
765 // PCI bridges will be called later
766 // Here just need for PCI device or PCI to cardbus controller
767 // EfiPciBeforeChildBusEnumeration for PCI Device Node
769 PreprocessController (
771 PciDevice
->BusNumber
,
772 PciDevice
->DeviceNumber
,
773 PciDevice
->FunctionNumber
,
774 EfiPciBeforeChildBusEnumeration
779 // For Pci Hotplug controller devcie only
781 if (gPciHotPlugInit
!= NULL
) {
783 // Check if it is a Hotplug PCI controller
785 if (IsRootPciHotPlugController (PciDevice
->DevicePath
, &HpIndex
)) {
787 if (!gPciRootHpcData
[HpIndex
].Initialized
) {
789 Status
= CreateEventForHpc (HpIndex
, &Event
);
791 ASSERT (!EFI_ERROR (Status
));
793 Status
= gPciHotPlugInit
->InitializeRootHpc (
795 gPciRootHpcPool
[HpIndex
].HpcDevicePath
,
801 PreprocessController (
803 PciDevice
->BusNumber
,
804 PciDevice
->DeviceNumber
,
805 PciDevice
->FunctionNumber
,
806 EfiPciBeforeChildBusEnumeration
813 if (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
)) {
817 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
819 // If Hot Plug is not supported,
820 // get the bridge information
822 Status
= PciSearchDevice (
831 if (EFI_ERROR (Status
)) {
836 // If Hot Plug is supported,
837 // Get the bridge information
840 if (gPciHotPlugInit
!= NULL
) {
842 if (IsRootPciHotPlugBus (PciDevice
->DevicePath
, &HpIndex
)) {
845 // If it is initialized, get the padded bus range
847 Status
= gPciHotPlugInit
->GetResourcePadding (
849 gPciRootHpcPool
[HpIndex
].HpbDevicePath
,
852 (VOID
**) &Descriptors
,
856 if (EFI_ERROR (Status
)) {
861 Status
= PciGetBusRange (
868 FreePool (Descriptors
);
870 if (EFI_ERROR (Status
)) {
880 // Add feature to support customized secondary bus number
882 if (*SubBusNumber
== 0) {
883 *SubBusNumber
= *PaddedBusRange
;
888 SecondBus
= *SubBusNumber
;
890 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
891 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET
);
893 Status
= PciRootBridgeIoWrite (
904 // If it is PPB, resursively search down this bridge
906 if (IS_PCI_BRIDGE (&Pci
)) {
909 // Temporarily initialize SubBusNumber to maximum bus number to ensure the
910 // PCI configuration transaction to go through any PPB
913 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET
);
914 Status
= PciRootBridgeIoWrite (
924 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
926 PreprocessController (
928 PciDevice
->BusNumber
,
929 PciDevice
->DeviceNumber
,
930 PciDevice
->FunctionNumber
,
931 EfiPciBeforeChildBusEnumeration
934 DEBUG((EFI_D_ERROR
, "Scan PPB(%02d,%02d,%02d)\n", PciDevice
->BusNumber
, PciDevice
->DeviceNumber
,PciDevice
->FunctionNumber
));
935 Status
= PciScanBus (
941 if (EFI_ERROR (Status
)) {
946 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
) && BusPadding
) {
948 // Ensure the device is enabled and initialized
950 if ((Attributes
== EfiPaddingPciRootBridge
) &&
951 (State
& EFI_HPC_STATE_ENABLED
) != 0 &&
952 (State
& EFI_HPC_STATE_INITIALIZED
) != 0) {
953 *PaddedBusRange
= (UINT8
) ((UINT8
) (BusRange
) +*PaddedBusRange
);
955 *SubBusNumber
= (UINT8
) ((UINT8
) (BusRange
) +*SubBusNumber
);
960 // Set the current maximum bus number under the PPB
962 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET
);
964 Status
= PciRootBridgeIoWrite (
974 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
977 // Skip sub functions, this is not a multi function device
989 Process Option Rom on the specified root bridge.
991 @param Bridge Pci root bridge device instance.
993 @retval EFI_SUCCESS Success process.
994 @retval other Some error occurred when processing Option Rom on the root bridge.
998 PciRootBridgeP2CProcess (
999 IN PCI_IO_DEVICE
*Bridge
1002 LIST_ENTRY
*CurrentLink
;
1003 PCI_IO_DEVICE
*Temp
;
1004 EFI_HPC_STATE State
;
1008 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1010 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
1012 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1014 if (IS_CARDBUS_BRIDGE (&Temp
->Pci
)) {
1016 if (gPciHotPlugInit
!= NULL
&& Temp
->Allocated
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1019 // Raise the EFI_IOB_PCI_HPC_INIT status code
1021 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1023 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_HPC_INIT
,
1027 PciAddress
= EFI_PCI_ADDRESS (Temp
->BusNumber
, Temp
->DeviceNumber
, Temp
->FunctionNumber
, 0);
1028 Status
= gPciHotPlugInit
->InitializeRootHpc (
1036 if (!EFI_ERROR (Status
)) {
1037 Status
= PciBridgeEnumerator (Temp
);
1039 if (EFI_ERROR (Status
)) {
1044 CurrentLink
= CurrentLink
->ForwardLink
;
1050 if (!IsListEmpty (&Temp
->ChildList
)) {
1051 Status
= PciRootBridgeP2CProcess (Temp
);
1054 CurrentLink
= CurrentLink
->ForwardLink
;
1061 Process Option Rom on the specified host bridge.
1063 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
1065 @retval EFI_SUCCESS Success process.
1066 @retval EFI_NOT_FOUND Can not find the root bridge instance.
1067 @retval other Some error occurred when processing Option Rom on the host bridge.
1071 PciHostBridgeP2CProcess (
1072 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1075 EFI_HANDLE RootBridgeHandle
;
1076 PCI_IO_DEVICE
*RootBridgeDev
;
1079 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1083 RootBridgeHandle
= NULL
;
1085 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1088 // Get RootBridg Device by handle
1090 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
1092 if (RootBridgeDev
== NULL
) {
1093 return EFI_NOT_FOUND
;
1096 Status
= PciRootBridgeP2CProcess (RootBridgeDev
);
1097 if (EFI_ERROR (Status
)) {
1107 This function is used to enumerate the entire host bridge
1108 in a given platform.
1110 @param PciResAlloc A pointer to the PCI Host Resource Allocation protocol.
1112 @retval EFI_SUCCESS Successfully enumerated the host bridge.
1113 @retval EFI_OUT_OF_RESOURCES No enough memory available.
1114 @retval other Some error occurred when enumerating the host bridge.
1118 PciHostBridgeEnumerator (
1119 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1122 EFI_HANDLE RootBridgeHandle
;
1123 PCI_IO_DEVICE
*RootBridgeDev
;
1125 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1127 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1128 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration
;
1129 UINT8 StartBusNumber
;
1130 LIST_ENTRY RootBridgeList
;
1133 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1134 InitializeHotPlugSupport ();
1137 InitializeListHead (&RootBridgeList
);
1140 // Notify the bus allocation phase is about to start
1142 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1144 DEBUG((EFI_D_ERROR
, "PCI Bus First Scanning\n"));
1145 RootBridgeHandle
= NULL
;
1146 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1149 // if a root bridge instance is found, create root bridge device for it
1152 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1154 if (RootBridgeDev
== NULL
) {
1155 return EFI_OUT_OF_RESOURCES
;
1159 // Enumerate all the buses under this root bridge
1161 Status
= PciRootBridgeEnumerator (
1166 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1167 InsertTailList (&RootBridgeList
, &(RootBridgeDev
->Link
));
1169 DestroyRootBridge (RootBridgeDev
);
1171 if (EFI_ERROR (Status
)) {
1177 // Notify the bus allocation phase is finished for the first time
1179 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1181 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1183 // Reset all assigned PCI bus number in all PPB
1185 RootBridgeHandle
= NULL
;
1186 Link
= GetFirstNode (&RootBridgeList
);
1187 while ((PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) &&
1188 (!IsNull (&RootBridgeList
, Link
))) {
1189 RootBridgeDev
= PCI_IO_DEVICE_FROM_LINK (Link
);
1191 // Get the Bus information
1193 Status
= PciResAlloc
->StartBusEnumeration (
1196 (VOID
**) &Configuration
1198 if (EFI_ERROR (Status
)) {
1203 // Get the bus number to start with
1205 StartBusNumber
= (UINT8
) (Configuration
->AddrRangeMin
);
1207 ResetAllPpbBusNumber (
1212 FreePool (Configuration
);
1213 Link
= GetNextNode (&RootBridgeList
, Link
);
1214 DestroyRootBridge (RootBridgeDev
);
1218 // Wait for all HPC initialized
1220 Status
= AllRootHPCInitialized (STALL_1_SECOND
* 15);
1222 if (EFI_ERROR (Status
)) {
1227 // Notify the bus allocation phase is about to start for the 2nd time
1229 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1231 DEBUG((EFI_D_ERROR
, "PCI Bus Second Scanning\n"));
1232 RootBridgeHandle
= NULL
;
1233 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1236 // if a root bridge instance is found, create root bridge device for it
1238 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1240 if (RootBridgeDev
== NULL
) {
1241 return EFI_OUT_OF_RESOURCES
;
1245 // Enumerate all the buses under this root bridge
1247 Status
= PciRootBridgeEnumerator (
1252 DestroyRootBridge (RootBridgeDev
);
1253 if (EFI_ERROR (Status
)) {
1259 // Notify the bus allocation phase is to end for the 2nd time
1261 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1265 // Notify the resource allocation phase is to start
1267 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginResourceAllocation
);
1269 RootBridgeHandle
= NULL
;
1270 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1273 // if a root bridge instance is found, create root bridge device for it
1275 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1277 if (RootBridgeDev
== NULL
) {
1278 return EFI_OUT_OF_RESOURCES
;
1281 Status
= StartManagingRootBridge (RootBridgeDev
);
1283 if (EFI_ERROR (Status
)) {
1287 PciRootBridgeIo
= RootBridgeDev
->PciRootBridgeIo
;
1288 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
1290 if (EFI_ERROR (Status
)) {
1294 Status
= PciGetBusRange (&Descriptors
, &MinBus
, NULL
, NULL
);
1296 if (EFI_ERROR (Status
)) {
1301 // Determine root bridge attribute by calling interface of Pcihostbridge
1304 DetermineRootBridgeAttributes (
1310 // Collect all the resource information under this root bridge
1311 // A database that records all the information about pci device subject to this
1312 // root bridge will then be created
1314 Status
= PciPciDeviceInfoCollector (
1319 if (EFI_ERROR (Status
)) {
1323 InsertRootBridge (RootBridgeDev
);
1326 // Record the hostbridge handle
1328 AddHostBridgeEnumerator (RootBridgeDev
->PciRootBridgeIo
->ParentHandle
);
1335 Read PCI device configuration register by specified address.
1337 This function check the incompatiblilites on PCI device. Return the register
1340 @param PciRootBridgeIo PCI root bridge io protocol instance.
1341 @param PciIo PCI IO protocol instance.
1342 @param PciDeviceInfo PCI device information.
1343 @param Width Signifies the width of the memory operations.
1344 @param Address The address within the PCI configuration space for the PCI controller.
1345 @param Buffer For read operations, the destination buffer to store the results. For
1346 write operations, the source buffer to write data from.
1348 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
1349 @retval EFI_UNSUPPORTED Width is invalid for this PCI root bridge.
1350 @retval other Some error occurred when reading PCI device configuration space
1351 or checking incompatibility.
1356 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
1357 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
1358 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
1366 EFI_PCI_REGISTER_ACCESS_DATA
*PciRegisterAccessData
;
1367 UINT64 AccessAddress
;
1372 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
1373 ASSERT (Buffer
!= NULL
);
1375 if ((PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT
) != 0) {
1377 // Check access compatibility at first time
1379 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_READ
, Address
& 0xff, Width
, &PciRegisterAccessData
);
1381 if (Status
== EFI_SUCCESS
) {
1383 // There exists incompatibility on this operation
1385 AccessWidth
= Width
;
1387 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
1388 AccessWidth
= PciRegisterAccessData
->Width
;
1391 AccessAddress
= Address
& ~((1 << AccessWidth
) - 1);
1395 Pointer
= (UINT8
*) &TempBuffer
;
1399 if (PciRootBridgeIo
!= NULL
) {
1400 Status
= PciRootBridgeIo
->Pci
.Read (
1402 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) AccessWidth
,
1407 } else if (PciIo
!= NULL
) {
1408 Status
= PciIo
->Pci
.Read (
1410 (EFI_PCI_IO_PROTOCOL_WIDTH
) AccessWidth
,
1411 (UINT32
) AccessAddress
,
1417 if (Status
!= EFI_SUCCESS
) {
1421 Stride
= (UINTN
)1 << AccessWidth
;
1422 AccessAddress
+= Stride
;
1423 if (AccessAddress
>= (Address
+ LShiftU64 (1ULL, (UINTN
)Width
))) {
1425 // If all datas have been read, exit
1432 if ((AccessAddress
& 0xff) < PciRegisterAccessData
->EndOffset
) {
1434 // If current offset doesn't reach the end
1440 // Continue checking access incompatibility
1442 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_READ
, AccessAddress
& 0xff, AccessWidth
, &PciRegisterAccessData
);
1443 if (Status
== EFI_SUCCESS
) {
1444 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
1445 AccessWidth
= PciRegisterAccessData
->Width
;
1451 case EfiPciWidthUint8
:
1452 * (UINT8
*) Buffer
= (UINT8
) TempBuffer
;
1454 case EfiPciWidthUint16
:
1455 * (UINT16
*) Buffer
= (UINT16
) TempBuffer
;
1457 case EfiPciWidthUint32
:
1458 * (UINT32
*) Buffer
= (UINT32
) TempBuffer
;
1461 return EFI_UNSUPPORTED
;
1468 // AccessWidth incompatible check not supportted
1469 // or, there doesn't exist incompatibility on this operation
1471 if (PciRootBridgeIo
!= NULL
) {
1472 Status
= PciRootBridgeIo
->Pci
.Read (
1474 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
1481 Status
= PciIo
->Pci
.Read (
1483 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
1494 Update register value by checking PCI device incompatibility.
1496 This function check register value incompatibilites on PCI device. Return the register
1499 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
1500 @param AccessType Access type, READ or WRITE.
1501 @param Width Signifies the width of the memory operations.
1502 @param Address The address within the PCI configuration space.
1503 @param Buffer Store the register data.
1505 @retval EFI_SUCCESS The data has been updated.
1506 @retval EFI_UNSUPPORTED Width is invalid for this PCI root bridge.
1507 @retval other Some error occurred when checking incompatibility.
1512 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
1513 IN UINT64 AccessType
,
1520 EFI_PCI_REGISTER_VALUE_DATA
*PciRegisterData
;
1525 ASSERT (Buffer
!= NULL
);
1528 // Check register value incompatibility
1530 Status
= PciRegisterUpdateCheck (PciDeviceInfo
, AccessType
, Address
& 0xff, &PciRegisterData
);
1531 if (Status
== EFI_SUCCESS
) {
1533 AndValue
= ((UINT32
) PciRegisterData
->AndValue
) >> (((UINT8
) Address
& 0x3) * 8);
1534 OrValue
= ((UINT32
) PciRegisterData
->OrValue
) >> (((UINT8
) Address
& 0x3) * 8);
1536 TempValue
= * (UINT32
*) Buffer
;
1537 if (PciRegisterData
->AndValue
!= VALUE_NOCARE
) {
1538 TempValue
&= AndValue
;
1540 if (PciRegisterData
->OrValue
!= VALUE_NOCARE
) {
1541 TempValue
|= OrValue
;
1545 case EfiPciWidthUint8
:
1546 *(UINT8
*)Buffer
= (UINT8
) TempValue
;
1549 case EfiPciWidthUint16
:
1550 *(UINT16
*)Buffer
= (UINT16
) TempValue
;
1552 case EfiPciWidthUint32
:
1553 *(UINT32
*)Buffer
= TempValue
;
1557 return EFI_UNSUPPORTED
;
1565 Write PCI device configuration register by specified address.
1567 This function check the incompatiblilites on PCI device, and write date
1570 @param PciRootBridgeIo PCI root bridge io instance.
1571 @param PciIo PCI IO protocol instance.
1572 @param PciDeviceInfo PCI device information.
1573 @param Width Signifies the width of the memory operations.
1574 @param Address The address within the PCI configuration space for the PCI controller.
1575 @param Buffer For read operations, the destination buffer to store the results. For
1576 write operations, the source buffer to write data from.
1578 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
1579 @retval other Some error occurred when writing PCI device information
1580 or checking incompatibility.
1585 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
1586 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
1587 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
1595 EFI_PCI_REGISTER_ACCESS_DATA
*PciRegisterAccessData
;
1596 UINT64 AccessAddress
;
1602 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
1603 ASSERT (Buffer
!= NULL
);
1605 if ((PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT
) != 0) {
1607 // Check access compatibility at first time
1609 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_WRITE
, Address
& 0xff, Width
, &PciRegisterAccessData
);
1611 if (Status
== EFI_SUCCESS
) {
1613 // There exists incompatibility on this operation
1615 AccessWidth
= Width
;
1617 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
1618 AccessWidth
= PciRegisterAccessData
->Width
;
1621 AccessAddress
= Address
& ~((1 << AccessWidth
) - 1);
1624 Pointer
= (UINT8
*) &Buffer
;
1625 Data
= * (UINT64
*) Buffer
;
1629 if (AccessWidth
> Width
) {
1631 // If actual access width is larger than orignal one, additional data need to be read back firstly
1633 Status
= ReadConfigData (PciRootBridgeIo
, PciIo
, PciDeviceInfo
, AccessWidth
, AccessAddress
, &Data
);
1634 if (Status
!= EFI_SUCCESS
) {
1639 // Check data read incompatibility
1641 UpdateConfigData (PciDeviceInfo
, PCI_REGISTER_READ
, AccessWidth
, AccessAddress
& 0xff, &Data
);
1643 Shift
= (UINTN
)(Address
- AccessAddress
) * 8;
1645 case EfiPciWidthUint8
:
1646 Data
= (* (UINT8
*) Buffer
) << Shift
| (Data
& ~(0xff << Shift
));
1649 case EfiPciWidthUint16
:
1650 Data
= (* (UINT16
*) Buffer
) << Shift
| (Data
& ~(0xffff << Shift
));
1655 // Check data write incompatibility
1657 UpdateConfigData (PciDeviceInfo
, PCI_REGISTER_WRITE
, AccessWidth
, MultU64x32 (AccessAddress
, 0xff), &Data
);
1660 if (PciRootBridgeIo
!= NULL
) {
1661 Status
= PciRootBridgeIo
->Pci
.Write (
1663 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) AccessWidth
,
1669 Status
= PciIo
->Pci
.Write (
1671 (EFI_PCI_IO_PROTOCOL_WIDTH
) AccessWidth
,
1672 (UINT32
) AccessAddress
,
1678 if (Status
!= EFI_SUCCESS
) {
1682 Data
= RShiftU64 (Data
, ((1 << AccessWidth
) * 8));
1684 Stride
= (UINTN
)1 << AccessWidth
;
1685 AccessAddress
+= Stride
;
1686 if (AccessAddress
>= (Address
+ LShiftU64 (1ULL, (UINTN
)Width
))) {
1688 // If all datas have been written, exit
1695 if ((AccessAddress
& 0xff) < PciRegisterAccessData
->EndOffset
) {
1697 // If current offset doesn't reach the end
1703 // Continue checking access incompatibility
1705 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_WRITE
, AccessAddress
& 0xff, AccessWidth
, &PciRegisterAccessData
);
1706 if (Status
== EFI_SUCCESS
) {
1707 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
1708 AccessWidth
= PciRegisterAccessData
->Width
;
1718 // AccessWidth incompatible check not supportted
1719 // or, there doesn't exist incompatibility on this operation
1721 if (PciRootBridgeIo
!= NULL
) {
1722 Status
= PciRootBridgeIo
->Pci
.Write (
1724 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
1730 Status
= PciIo
->Pci
.Write (
1732 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
1743 Abstract PCI device device information.
1745 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1746 @param PciIo A pointer to EFI_PCI_PROTOCOL.
1747 @param Pci PCI device configuration space.
1748 @param Address The address within the PCI configuration space for the PCI controller.
1749 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
1751 @retval EFI_SUCCESS Pci device device information has been abstracted.
1752 @retval EFI_NOT_FOUND Cannot found the specified PCI device.
1753 @retval other Some error occurred when reading PCI device information.
1757 GetPciDeviceDeviceInfo (
1758 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
1759 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
1760 IN PCI_TYPE00
*Pci
, OPTIONAL
1761 IN UINT64 Address
, OPTIONAL
1762 OUT EFI_PCI_DEVICE_INFO
*PciDeviceInfo
1767 UINT32 PciConfigData
;
1768 PCI_IO_DEVICE
*PciIoDevice
;
1770 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
1771 ASSERT (PciDeviceInfo
!= NULL
);
1773 if (PciIo
!= NULL
) {
1774 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
1777 // Get pointer to PCI_TYPE00 from PciIoDevice
1779 Pci
= &PciIoDevice
->Pci
;
1784 // While PCI_TYPE00 hasn't been gotten, read PCI device device information directly
1786 PciAddress
= Address
& 0xffffffffffffff00ULL
;
1787 Status
= PciRootBridgeIo
->Pci
.Read (
1795 if (EFI_ERROR (Status
)) {
1799 if ((PciConfigData
& 0xffff) == 0xffff) {
1800 return EFI_NOT_FOUND
;
1803 PciDeviceInfo
->VendorID
= PciConfigData
& 0xffff;
1804 PciDeviceInfo
->DeviceID
= PciConfigData
>> 16;
1806 Status
= PciRootBridgeIo
->Pci
.Read (
1813 if (EFI_ERROR (Status
)) {
1817 PciDeviceInfo
->RevisionID
= PciConfigData
& 0xf;
1819 Status
= PciRootBridgeIo
->Pci
.Read (
1827 if (EFI_ERROR (Status
)) {
1831 PciDeviceInfo
->SubsystemVendorID
= PciConfigData
& 0xffff;
1832 PciDeviceInfo
->SubsystemID
= PciConfigData
>> 16;
1835 PciDeviceInfo
->VendorID
= Pci
->Hdr
.VendorId
;
1836 PciDeviceInfo
->DeviceID
= Pci
->Hdr
.DeviceId
;
1837 PciDeviceInfo
->RevisionID
= Pci
->Hdr
.RevisionID
;
1838 PciDeviceInfo
->SubsystemVendorID
= Pci
->Device
.SubsystemVendorID
;
1839 PciDeviceInfo
->SubsystemID
= Pci
->Device
.SubsystemID
;
1846 Read PCI configuration space with incompatibility check.
1848 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1849 @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL.
1850 @param Pci A pointer to PCI_TYPE00.
1851 @param Width Signifies the width of the memory operations.
1852 @param Address The address within the PCI configuration space for the PCI controller.
1853 @param Count The number of unit to be read.
1854 @param Buffer For read operations, the destination buffer to store the results. For
1855 write operations, the source buffer to write data from.
1857 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
1858 @retval EFI_UNSUPPORTED Buffer is NULL.
1859 @retval other Some error occurred when reading PCI configuration space.
1863 PciIncompatibilityCheckRead (
1864 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
1865 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
1866 IN PCI_TYPE00
*Pci
, OPTIONAL
1874 EFI_PCI_DEVICE_INFO PciDeviceInfo
;
1877 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
1878 if (Buffer
== NULL
) {
1879 return EFI_UNSUPPORTED
;
1883 // get PCI device device information
1885 Status
= GetPciDeviceDeviceInfo (PciRootBridgeIo
, PciIo
, Pci
, Address
, &PciDeviceInfo
);
1886 if (Status
!= EFI_SUCCESS
) {
1890 Stride
= 1 << Width
;
1892 for (; Count
> 0; Count
--, Address
+= Stride
, Buffer
= (UINT8
*)Buffer
+ Stride
) {
1895 // read configuration register
1897 Status
= ReadConfigData (PciRootBridgeIo
, PciIo
, &PciDeviceInfo
, (UINT64
) Width
, Address
, Buffer
);
1899 if (Status
!= EFI_SUCCESS
) {
1904 // update the data read from configuration register
1906 if ((PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT
) != 0) {
1907 UpdateConfigData (&PciDeviceInfo
, PCI_REGISTER_READ
, Width
, Address
& 0xff, Buffer
);
1915 Write PCI configuration space with incompatibility check.
1917 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1918 @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL.
1919 @param Pci A pointer to PCI_TYPE00.
1920 @param Width Signifies the width of the memory operations.
1921 @param Address The address within the PCI configuration space for the PCI controller.
1922 @param Count The number of unit to be write.
1923 @param Buffer For read operations, the destination buffer to store the results. For
1924 write operations, the source buffer to write data from.
1926 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
1927 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
1928 valid for the PCI configuration header of the PCI controller.
1930 @retval other Some error occurred when writing PCI configuration space.
1934 PciIncompatibilityCheckWrite (
1935 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
1936 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
1937 IN PCI_TYPE00
*Pci
, OPTIONAL
1945 EFI_PCI_DEVICE_INFO PciDeviceInfo
;
1949 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
1950 if (Buffer
== NULL
) {
1951 return EFI_UNSUPPORTED
;
1955 // Get PCI device device information
1957 Status
= GetPciDeviceDeviceInfo (PciRootBridgeIo
, PciIo
, Pci
, Address
, &PciDeviceInfo
);
1958 if (Status
!= EFI_SUCCESS
) {
1962 Stride
= 1 << Width
;
1964 for (; Count
> 0; Count
--, Address
+= Stride
, Buffer
= (UINT8
*) Buffer
+ Stride
) {
1969 case EfiPciWidthUint8
:
1970 Data
= * (UINT8
*) Buffer
;
1972 case EfiPciWidthUint16
:
1973 Data
= * (UINT16
*) Buffer
;
1976 case EfiPciWidthUint32
:
1977 Data
= * (UINT32
*) Buffer
;
1981 return EFI_UNSUPPORTED
;
1985 // Update the data writen into configuration register
1987 if ((PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT
) != 0) {
1988 UpdateConfigData (&PciDeviceInfo
, PCI_REGISTER_WRITE
, Width
, Address
& 0xff, &Data
);
1992 // Write configuration register
1994 Status
= WriteConfigData (PciRootBridgeIo
, PciIo
, &PciDeviceInfo
, Width
, Address
, &Data
);
1996 if (Status
!= EFI_SUCCESS
) {
2005 Read PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2007 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2008 @param Pci A pointer to PCI_TYPE00.
2009 @param Width Signifies the width of the memory operations.
2010 @param Address The address within the PCI configuration space for the PCI controller.
2011 @param Count The number of unit to be read.
2012 @param Buffer For read operations, the destination buffer to store the results. For
2013 write operations, the source buffer to write data from.
2015 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2016 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2017 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
2021 PciRootBridgeIoRead (
2022 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
2023 IN PCI_TYPE00
*Pci
, OPTIONAL
2024 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
2032 if ((PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_READ_SUPPORT
) != 0) {
2034 // If PCI incompatibility check enabled
2036 Status
= PciIncompatibilityCheckRead (
2045 if (Status
== EFI_UNSUPPORTED
) {
2046 return EFI_INVALID_PARAMETER
;
2051 return PciRootBridgeIo
->Pci
.Read (
2062 Write PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2064 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2065 @param Pci A pointer to PCI_TYPE00.
2066 @param Width Signifies the width of the memory operations.
2067 @param Address The address within the PCI configuration space for the PCI controller.
2068 @param Count The number of unit to be read.
2069 @param Buffer For read operations, the destination buffer to store the results. For
2070 write operations, the source buffer to write data from.
2072 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2073 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2074 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
2078 PciRootBridgeIoWrite (
2079 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
2081 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
2089 if ((PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_WRITE_SUPPORT
) != 0) {
2091 // If PCI incompatibility check enabled
2093 Status
= PciIncompatibilityCheckWrite (
2102 if (Status
== EFI_UNSUPPORTED
) {
2103 return EFI_INVALID_PARAMETER
;
2109 return PciRootBridgeIo
->Pci
.Write (
2120 Read PCI configuration space through EFI_PCI_IO_PROTOCOL.
2122 @param PciIo A pointer to the EFI_PCI_O_PROTOCOL.
2123 @param Width Signifies the width of the memory operations.
2124 @param Address The address within the PCI configuration space for the PCI controller.
2125 @param Count The number of unit to be read.
2126 @param Buffer For read operations, the destination buffer to store the results. For
2127 write operations, the source buffer to write data from.
2129 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
2130 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
2131 valid for the PCI configuration header of the PCI controller.
2132 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2133 @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
2138 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2139 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
2145 if ((PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_READ_SUPPORT
) != 0) {
2147 // If PCI incompatibility check enabled
2149 return PciIncompatibilityCheckRead (
2159 return PciIo
->Pci
.Read (
2170 Write PCI configuration space through EFI_PCI_IO_PROTOCOL.
2172 If PCI incompatibility check is enabled, do incompatibility check.
2174 @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
2175 @param Width Signifies the width of the memory operations.
2176 @param Offset The offset within the PCI configuration space for the PCI controller.
2177 @param Count The number of PCI configuration operations to perform.
2178 @param Buffer For read operations, the destination buffer to store the results. For write
2179 operations, the source buffer to write data from.
2181 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
2182 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
2183 valid for the PCI configuration header of the PCI controller.
2184 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2185 @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
2190 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2191 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
2197 if ((PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_WRITE_SUPPORT
) != 0) {
2199 // If PCI incompatibility check enabled
2201 return PciIncompatibilityCheckWrite (
2212 return PciIo
->Pci
.Write (