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
);
382 // End while, at least one Root Bridge should be found.
384 ASSERT (RootBridgeDev
!= NULL
);
387 // Notify platform to start to program the resource
389 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeAllocateResources
);
390 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
392 // If Hot Plug is not supported
394 if (EFI_ERROR (Status
)) {
396 // Allocation failed, then return
398 return EFI_OUT_OF_RESOURCES
;
401 // Allocation succeed.
402 // Get host bridge handle for status report, and then skip the main while
404 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
410 // If Hot Plug is supported
412 if (!EFI_ERROR (Status
)) {
414 // Allocation succeed, then continue the following
420 // If the resource allocation is unsuccessful, free resources on bridge
423 RootBridgeDev
= NULL
;
424 RootBridgeHandle
= 0;
426 IoResStatus
= EFI_RESOURCE_SATISFIED
;
427 Mem32ResStatus
= EFI_RESOURCE_SATISFIED
;
428 PMem32ResStatus
= EFI_RESOURCE_SATISFIED
;
429 Mem64ResStatus
= EFI_RESOURCE_SATISFIED
;
430 PMem64ResStatus
= EFI_RESOURCE_SATISFIED
;
432 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
434 // Get RootBridg Device by handle
436 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
437 if (RootBridgeDev
== NULL
) {
438 return EFI_NOT_FOUND
;
442 // Get host bridge handle for status report
444 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
447 // Get acpi resource node for all the resource types
451 Status
= PciResAlloc
->GetProposedResources (
453 RootBridgeDev
->Handle
,
457 if (EFI_ERROR (Status
)) {
461 if (AcpiConfig
!= NULL
) {
463 // Adjust resource allocation policy for each RB
465 GetResourceAllocationStatus (
473 FreePool (AcpiConfig
);
481 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
484 // It is very difficult to follow the spec here
485 // Device path , Bar index can not be get here
487 ZeroMem (&AllocFailExtendedData
, sizeof (AllocFailExtendedData
));
489 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
491 EFI_IO_BUS_PCI
| EFI_IOB_EC_RESOURCE_CONFLICT
,
492 (VOID
*) &AllocFailExtendedData
,
493 sizeof (AllocFailExtendedData
)
496 Status
= PciHostBridgeAdjustAllocation (
510 // Destroy all the resource tree
512 DestroyResourceTree (&IoPool
);
513 DestroyResourceTree (&Mem32Pool
);
514 DestroyResourceTree (&PMem32Pool
);
515 DestroyResourceTree (&Mem64Pool
);
516 DestroyResourceTree (&PMem64Pool
);
518 NotifyPhase (PciResAlloc
, EfiPciHostBridgeFreeResources
);
520 if (EFI_ERROR (Status
)) {
532 // Raise the EFI_IOB_PCI_RES_ALLOC status code
534 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
536 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_RES_ALLOC
,
537 (VOID
*) &HandleExtendedData
,
538 sizeof (HandleExtendedData
)
542 // Notify pci bus driver starts to program the resource
544 NotifyPhase (PciResAlloc
, EfiPciHostBridgeSetResources
);
546 RootBridgeDev
= NULL
;
548 RootBridgeHandle
= 0;
550 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
552 // Get RootBridg Device by handle
554 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
556 if (RootBridgeDev
== NULL
) {
557 return EFI_NOT_FOUND
;
561 // Get acpi resource node for all the resource types
564 Status
= PciResAlloc
->GetProposedResources (
566 RootBridgeDev
->Handle
,
570 if (EFI_ERROR (Status
)) {
575 // Get the resource base by interpreting acpi resource node
588 // Process option rom for this root bridge
590 ProcessOptionRom (RootBridgeDev
, Mem32Base
, RootBridgeDev
->RomSize
);
593 // Create the entire system resource map from the information collected by
594 // enumerator. Several resource tree was created
611 // Program IO resources
619 // Program Mem32 resources
627 // Program PMem32 resources
635 // Program Mem64 resources
643 // Program PMem64 resources
650 FreePool (AcpiConfig
);
654 // Destroy all the resource tree
656 DestroyResourceTree (&IoPool
);
657 DestroyResourceTree (&Mem32Pool
);
658 DestroyResourceTree (&PMem32Pool
);
659 DestroyResourceTree (&Mem64Pool
);
660 DestroyResourceTree (&PMem64Pool
);
663 // Notify the resource allocation phase is to end
665 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndResourceAllocation
);
671 Scan pci bus and assign bus number to the given PCI bus system.
673 @param Bridge Bridge device instance.
674 @param StartBusNumber start point.
675 @param SubBusNumber Point to sub bus number.
676 @param PaddedBusRange Customized bus number.
678 @retval EFI_SUCCESS Successfully scanned and assigned bus number.
679 @retval other Some error occurred when scanning pci bus.
681 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
686 IN PCI_IO_DEVICE
*Bridge
,
687 IN UINT8 StartBusNumber
,
688 OUT UINT8
*SubBusNumber
,
689 OUT UINT8
*PaddedBusRange
700 PCI_IO_DEVICE
*PciDevice
;
704 EFI_HPC_PADDING_ATTRIBUTES Attributes
;
705 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
707 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
710 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
714 Attributes
= (EFI_HPC_PADDING_ATTRIBUTES
) 0;
720 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
721 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
724 // Check to see whether a pci device is present
726 Status
= PciDevicePresent (
734 if (EFI_ERROR (Status
)) {
737 // Skip sub functions, this is not a multi function device
745 DEBUG((EFI_D_ERROR
, "Found DEV(%02d,%02d,%02d)\n", StartBusNumber
, Device
, Func
));
747 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
749 // Get the PCI device information
751 Status
= PciSearchDevice (
760 ASSERT (!EFI_ERROR (Status
));
762 PciAddress
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0);
764 if (!IS_PCI_BRIDGE (&Pci
)) {
766 // PCI bridges will be called later
767 // Here just need for PCI device or PCI to cardbus controller
768 // EfiPciBeforeChildBusEnumeration for PCI Device Node
770 PreprocessController (
772 PciDevice
->BusNumber
,
773 PciDevice
->DeviceNumber
,
774 PciDevice
->FunctionNumber
,
775 EfiPciBeforeChildBusEnumeration
780 // For Pci Hotplug controller devcie only
782 if (gPciHotPlugInit
!= NULL
) {
784 // Check if it is a Hotplug PCI controller
786 if (IsRootPciHotPlugController (PciDevice
->DevicePath
, &HpIndex
)) {
788 if (!gPciRootHpcData
[HpIndex
].Initialized
) {
790 Status
= CreateEventForHpc (HpIndex
, &Event
);
792 ASSERT (!EFI_ERROR (Status
));
794 Status
= gPciHotPlugInit
->InitializeRootHpc (
796 gPciRootHpcPool
[HpIndex
].HpcDevicePath
,
802 PreprocessController (
804 PciDevice
->BusNumber
,
805 PciDevice
->DeviceNumber
,
806 PciDevice
->FunctionNumber
,
807 EfiPciBeforeChildBusEnumeration
814 if (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
)) {
818 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
820 // If Hot Plug is not supported,
821 // get the bridge information
823 Status
= PciSearchDevice (
832 if (EFI_ERROR (Status
)) {
837 // If Hot Plug is supported,
838 // Get the bridge information
841 if (gPciHotPlugInit
!= NULL
) {
843 if (IsRootPciHotPlugBus (PciDevice
->DevicePath
, &HpIndex
)) {
846 // If it is initialized, get the padded bus range
848 Status
= gPciHotPlugInit
->GetResourcePadding (
850 gPciRootHpcPool
[HpIndex
].HpbDevicePath
,
853 (VOID
**) &Descriptors
,
857 if (EFI_ERROR (Status
)) {
862 Status
= PciGetBusRange (
869 FreePool (Descriptors
);
871 if (EFI_ERROR (Status
)) {
881 // Add feature to support customized secondary bus number
883 if (*SubBusNumber
== 0) {
884 *SubBusNumber
= *PaddedBusRange
;
889 SecondBus
= *SubBusNumber
;
891 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
892 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET
);
894 Status
= PciRootBridgeIoWrite (
905 // If it is PPB, resursively search down this bridge
907 if (IS_PCI_BRIDGE (&Pci
)) {
910 // Temporarily initialize SubBusNumber to maximum bus number to ensure the
911 // PCI configuration transaction to go through any PPB
914 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET
);
915 Status
= PciRootBridgeIoWrite (
925 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
927 PreprocessController (
929 PciDevice
->BusNumber
,
930 PciDevice
->DeviceNumber
,
931 PciDevice
->FunctionNumber
,
932 EfiPciBeforeChildBusEnumeration
935 DEBUG((EFI_D_ERROR
, "Scan PPB(%02d,%02d,%02d)\n", PciDevice
->BusNumber
, PciDevice
->DeviceNumber
,PciDevice
->FunctionNumber
));
936 Status
= PciScanBus (
942 if (EFI_ERROR (Status
)) {
947 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
) && BusPadding
) {
949 // Ensure the device is enabled and initialized
951 if ((Attributes
== EfiPaddingPciRootBridge
) &&
952 (State
& EFI_HPC_STATE_ENABLED
) != 0 &&
953 (State
& EFI_HPC_STATE_INITIALIZED
) != 0) {
954 *PaddedBusRange
= (UINT8
) ((UINT8
) (BusRange
) +*PaddedBusRange
);
956 *SubBusNumber
= (UINT8
) ((UINT8
) (BusRange
) +*SubBusNumber
);
961 // Set the current maximum bus number under the PPB
963 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET
);
965 Status
= PciRootBridgeIoWrite (
975 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
978 // Skip sub functions, this is not a multi function device
990 Process Option Rom on the specified root bridge.
992 @param Bridge Pci root bridge device instance.
994 @retval EFI_SUCCESS Success process.
995 @retval other Some error occurred when processing Option Rom on the root bridge.
999 PciRootBridgeP2CProcess (
1000 IN PCI_IO_DEVICE
*Bridge
1003 LIST_ENTRY
*CurrentLink
;
1004 PCI_IO_DEVICE
*Temp
;
1005 EFI_HPC_STATE State
;
1009 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1011 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
1013 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1015 if (IS_CARDBUS_BRIDGE (&Temp
->Pci
)) {
1017 if (gPciHotPlugInit
!= NULL
&& Temp
->Allocated
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1020 // Raise the EFI_IOB_PCI_HPC_INIT status code
1022 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1024 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_HPC_INIT
,
1028 PciAddress
= EFI_PCI_ADDRESS (Temp
->BusNumber
, Temp
->DeviceNumber
, Temp
->FunctionNumber
, 0);
1029 Status
= gPciHotPlugInit
->InitializeRootHpc (
1037 if (!EFI_ERROR (Status
)) {
1038 Status
= PciBridgeEnumerator (Temp
);
1040 if (EFI_ERROR (Status
)) {
1045 CurrentLink
= CurrentLink
->ForwardLink
;
1051 if (!IsListEmpty (&Temp
->ChildList
)) {
1052 Status
= PciRootBridgeP2CProcess (Temp
);
1055 CurrentLink
= CurrentLink
->ForwardLink
;
1062 Process Option Rom on the specified host bridge.
1064 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
1066 @retval EFI_SUCCESS Success process.
1067 @retval EFI_NOT_FOUND Can not find the root bridge instance.
1068 @retval other Some error occurred when processing Option Rom on the host bridge.
1072 PciHostBridgeP2CProcess (
1073 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1076 EFI_HANDLE RootBridgeHandle
;
1077 PCI_IO_DEVICE
*RootBridgeDev
;
1080 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1084 RootBridgeHandle
= NULL
;
1086 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1089 // Get RootBridg Device by handle
1091 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
1093 if (RootBridgeDev
== NULL
) {
1094 return EFI_NOT_FOUND
;
1097 Status
= PciRootBridgeP2CProcess (RootBridgeDev
);
1098 if (EFI_ERROR (Status
)) {
1108 This function is used to enumerate the entire host bridge
1109 in a given platform.
1111 @param PciResAlloc A pointer to the PCI Host Resource Allocation protocol.
1113 @retval EFI_SUCCESS Successfully enumerated the host bridge.
1114 @retval EFI_OUT_OF_RESOURCES No enough memory available.
1115 @retval other Some error occurred when enumerating the host bridge.
1119 PciHostBridgeEnumerator (
1120 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1123 EFI_HANDLE RootBridgeHandle
;
1124 PCI_IO_DEVICE
*RootBridgeDev
;
1126 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1128 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1129 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration
;
1130 UINT8 StartBusNumber
;
1131 LIST_ENTRY RootBridgeList
;
1134 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1135 InitializeHotPlugSupport ();
1138 InitializeListHead (&RootBridgeList
);
1141 // Notify the bus allocation phase is about to start
1143 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1145 DEBUG((EFI_D_ERROR
, "PCI Bus First Scanning\n"));
1146 RootBridgeHandle
= NULL
;
1147 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1150 // if a root bridge instance is found, create root bridge device for it
1153 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1155 if (RootBridgeDev
== NULL
) {
1156 return EFI_OUT_OF_RESOURCES
;
1160 // Enumerate all the buses under this root bridge
1162 Status
= PciRootBridgeEnumerator (
1167 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1168 InsertTailList (&RootBridgeList
, &(RootBridgeDev
->Link
));
1170 DestroyRootBridge (RootBridgeDev
);
1172 if (EFI_ERROR (Status
)) {
1178 // Notify the bus allocation phase is finished for the first time
1180 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1182 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1184 // Reset all assigned PCI bus number in all PPB
1186 RootBridgeHandle
= NULL
;
1187 Link
= GetFirstNode (&RootBridgeList
);
1188 while ((PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) &&
1189 (!IsNull (&RootBridgeList
, Link
))) {
1190 RootBridgeDev
= PCI_IO_DEVICE_FROM_LINK (Link
);
1192 // Get the Bus information
1194 Status
= PciResAlloc
->StartBusEnumeration (
1197 (VOID
**) &Configuration
1199 if (EFI_ERROR (Status
)) {
1204 // Get the bus number to start with
1206 StartBusNumber
= (UINT8
) (Configuration
->AddrRangeMin
);
1208 ResetAllPpbBusNumber (
1213 FreePool (Configuration
);
1214 Link
= GetNextNode (&RootBridgeList
, Link
);
1215 DestroyRootBridge (RootBridgeDev
);
1219 // Wait for all HPC initialized
1221 Status
= AllRootHPCInitialized (STALL_1_SECOND
* 15);
1223 if (EFI_ERROR (Status
)) {
1228 // Notify the bus allocation phase is about to start for the 2nd time
1230 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1232 DEBUG((EFI_D_ERROR
, "PCI Bus Second Scanning\n"));
1233 RootBridgeHandle
= NULL
;
1234 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1237 // if a root bridge instance is found, create root bridge device for it
1239 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1241 if (RootBridgeDev
== NULL
) {
1242 return EFI_OUT_OF_RESOURCES
;
1246 // Enumerate all the buses under this root bridge
1248 Status
= PciRootBridgeEnumerator (
1253 DestroyRootBridge (RootBridgeDev
);
1254 if (EFI_ERROR (Status
)) {
1260 // Notify the bus allocation phase is to end for the 2nd time
1262 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1266 // Notify the resource allocation phase is to start
1268 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginResourceAllocation
);
1270 RootBridgeHandle
= NULL
;
1271 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1274 // if a root bridge instance is found, create root bridge device for it
1276 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1278 if (RootBridgeDev
== NULL
) {
1279 return EFI_OUT_OF_RESOURCES
;
1282 Status
= StartManagingRootBridge (RootBridgeDev
);
1284 if (EFI_ERROR (Status
)) {
1288 PciRootBridgeIo
= RootBridgeDev
->PciRootBridgeIo
;
1289 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
1291 if (EFI_ERROR (Status
)) {
1295 Status
= PciGetBusRange (&Descriptors
, &MinBus
, NULL
, NULL
);
1297 if (EFI_ERROR (Status
)) {
1302 // Determine root bridge attribute by calling interface of Pcihostbridge
1305 DetermineRootBridgeAttributes (
1311 // Collect all the resource information under this root bridge
1312 // A database that records all the information about pci device subject to this
1313 // root bridge will then be created
1315 Status
= PciPciDeviceInfoCollector (
1320 if (EFI_ERROR (Status
)) {
1324 InsertRootBridge (RootBridgeDev
);
1327 // Record the hostbridge handle
1329 AddHostBridgeEnumerator (RootBridgeDev
->PciRootBridgeIo
->ParentHandle
);
1336 Read PCI device configuration register by specified address.
1338 This function check the incompatiblilites on PCI device. Return the register
1341 @param PciRootBridgeIo PCI root bridge io protocol instance.
1342 @param PciIo PCI IO protocol instance.
1343 @param PciDeviceInfo PCI device information.
1344 @param Width Signifies the width of the memory operations.
1345 @param Offset The offset within the PCI configuration space for the PCI controller.
1346 @param Buffer For read operations, the destination buffer to store the results. For
1347 write operations, the source buffer to write data from.
1349 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
1350 @retval EFI_UNSUPPORTED Width is invalid for this PCI root bridge.
1351 @retval other Some error occurred when reading PCI device configuration space
1352 or checking incompatibility.
1357 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
1358 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
1359 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
1367 EFI_PCI_REGISTER_ACCESS_DATA
*PciRegisterAccessData
;
1368 UINT64 AccessAddress
;
1373 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
1374 ASSERT (Buffer
!= NULL
);
1376 if ((PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT
) != 0) {
1378 // Check access compatibility at first time
1380 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_READ
, Offset
& 0xff, Width
, &PciRegisterAccessData
);
1382 if (Status
== EFI_SUCCESS
) {
1384 // There exists incompatibility on this operation
1386 AccessWidth
= Width
;
1388 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
1389 AccessWidth
= PciRegisterAccessData
->Width
;
1392 AccessAddress
= Offset
& ~((1 << AccessWidth
) - 1);
1396 Pointer
= (UINT8
*) &TempBuffer
;
1400 if (PciRootBridgeIo
!= NULL
) {
1401 Status
= PciRootBridgeIo
->Pci
.Read (
1403 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) AccessWidth
,
1408 } else if (PciIo
!= NULL
) {
1409 Status
= PciIo
->Pci
.Read (
1411 (EFI_PCI_IO_PROTOCOL_WIDTH
) AccessWidth
,
1412 (UINT32
) AccessAddress
,
1418 if (Status
!= EFI_SUCCESS
) {
1422 Stride
= (UINTN
)1 << AccessWidth
;
1423 AccessAddress
+= Stride
;
1424 if (AccessAddress
>= (Offset
+ LShiftU64 (1ULL, (UINTN
)Width
))) {
1426 // If all datas have been read, exit
1433 if ((AccessAddress
& 0xff) < PciRegisterAccessData
->EndOffset
) {
1435 // If current offset doesn't reach the end
1441 // Continue checking access incompatibility
1443 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_READ
, AccessAddress
& 0xff, AccessWidth
, &PciRegisterAccessData
);
1444 if (Status
== EFI_SUCCESS
) {
1445 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
1446 AccessWidth
= PciRegisterAccessData
->Width
;
1452 case EfiPciWidthUint8
:
1453 * (UINT8
*) Buffer
= (UINT8
) TempBuffer
;
1455 case EfiPciWidthUint16
:
1456 * (UINT16
*) Buffer
= (UINT16
) TempBuffer
;
1458 case EfiPciWidthUint32
:
1459 * (UINT32
*) Buffer
= (UINT32
) TempBuffer
;
1462 return EFI_UNSUPPORTED
;
1469 // AccessWidth incompatible check not supportted
1470 // or, there doesn't exist incompatibility on this operation
1472 if (PciRootBridgeIo
!= NULL
) {
1473 Status
= PciRootBridgeIo
->Pci
.Read (
1475 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
1482 Status
= PciIo
->Pci
.Read (
1484 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
1495 Update register value by checking PCI device incompatibility.
1497 This function check register value incompatibilites on PCI device. Return the register
1500 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
1501 @param AccessType Access type, READ or WRITE.
1502 @param Width Signifies the width of the memory operations.
1503 @param Offset The offset within the PCI configuration space.
1504 @param Buffer Store the register data.
1506 @retval EFI_SUCCESS The data has been updated.
1507 @retval EFI_UNSUPPORTED Width is invalid for this PCI root bridge.
1508 @retval other Some error occurred when checking incompatibility.
1513 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
1514 IN UINT64 AccessType
,
1521 EFI_PCI_REGISTER_VALUE_DATA
*PciRegisterData
;
1526 ASSERT (Buffer
!= NULL
);
1529 // Check register value incompatibility
1531 Status
= PciRegisterUpdateCheck (PciDeviceInfo
, AccessType
, Offset
& 0xff, &PciRegisterData
);
1532 if (Status
== EFI_SUCCESS
) {
1534 AndValue
= ((UINT32
) PciRegisterData
->AndValue
) >> (((UINT8
) Offset
& 0x3) * 8);
1535 OrValue
= ((UINT32
) PciRegisterData
->OrValue
) >> (((UINT8
) Offset
& 0x3) * 8);
1537 TempValue
= * (UINT32
*) Buffer
;
1538 if (PciRegisterData
->AndValue
!= VALUE_NOCARE
) {
1539 TempValue
&= AndValue
;
1541 if (PciRegisterData
->OrValue
!= VALUE_NOCARE
) {
1542 TempValue
|= OrValue
;
1546 case EfiPciWidthUint8
:
1547 *(UINT8
*)Buffer
= (UINT8
) TempValue
;
1550 case EfiPciWidthUint16
:
1551 *(UINT16
*)Buffer
= (UINT16
) TempValue
;
1553 case EfiPciWidthUint32
:
1554 *(UINT32
*)Buffer
= TempValue
;
1558 return EFI_UNSUPPORTED
;
1566 Write PCI device configuration register by specified address.
1568 This function check the incompatiblilites on PCI device, and write date
1571 @param PciRootBridgeIo PCI root bridge io instance.
1572 @param PciIo PCI IO protocol instance.
1573 @param PciDeviceInfo PCI device information.
1574 @param Width Signifies the width of the memory operations.
1575 @param Offset The offset within the PCI configuration space for the PCI controller.
1576 @param Buffer For read operations, the destination buffer to store the results. For
1577 write operations, the source buffer to write data from.
1579 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
1580 @retval other Some error occurred when writing PCI device information
1581 or checking incompatibility.
1586 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
1587 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
1588 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
1596 EFI_PCI_REGISTER_ACCESS_DATA
*PciRegisterAccessData
;
1597 UINT64 AccessAddress
;
1603 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
1604 ASSERT (Buffer
!= NULL
);
1606 if ((PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT
) != 0) {
1608 // Check access compatibility at first time
1610 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_WRITE
, Offset
& 0xff, Width
, &PciRegisterAccessData
);
1612 if (Status
== EFI_SUCCESS
) {
1614 // There exists incompatibility on this operation
1616 AccessWidth
= Width
;
1618 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
1619 AccessWidth
= PciRegisterAccessData
->Width
;
1622 AccessAddress
= Offset
& ~((1 << AccessWidth
) - 1);
1625 Pointer
= (UINT8
*) &Buffer
;
1626 Data
= * (UINT64
*) Buffer
;
1630 if (AccessWidth
> Width
) {
1632 // If actual access width is larger than orignal one, additional data need to be read back firstly
1634 Status
= ReadConfigData (PciRootBridgeIo
, PciIo
, PciDeviceInfo
, AccessWidth
, AccessAddress
, &Data
);
1635 if (Status
!= EFI_SUCCESS
) {
1640 // Check data read incompatibility
1642 UpdateConfigData (PciDeviceInfo
, PCI_REGISTER_READ
, AccessWidth
, AccessAddress
& 0xff, &Data
);
1644 Shift
= (UINTN
)(Offset
- AccessAddress
) * 8;
1646 case EfiPciWidthUint8
:
1647 Data
= (* (UINT8
*) Buffer
) << Shift
| (Data
& ~(0xff << Shift
));
1650 case EfiPciWidthUint16
:
1651 Data
= (* (UINT16
*) Buffer
) << Shift
| (Data
& ~(0xffff << Shift
));
1656 // Check data write incompatibility
1658 UpdateConfigData (PciDeviceInfo
, PCI_REGISTER_WRITE
, AccessWidth
, MultU64x32 (AccessAddress
, 0xff), &Data
);
1661 if (PciRootBridgeIo
!= NULL
) {
1662 Status
= PciRootBridgeIo
->Pci
.Write (
1664 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) AccessWidth
,
1670 Status
= PciIo
->Pci
.Write (
1672 (EFI_PCI_IO_PROTOCOL_WIDTH
) AccessWidth
,
1673 (UINT32
) AccessAddress
,
1679 if (Status
!= EFI_SUCCESS
) {
1683 Data
= RShiftU64 (Data
, ((1 << AccessWidth
) * 8));
1685 Stride
= (UINTN
)1 << AccessWidth
;
1686 AccessAddress
+= Stride
;
1687 if (AccessAddress
>= (Offset
+ LShiftU64 (1ULL, (UINTN
)Width
))) {
1689 // If all datas have been written, exit
1696 if ((AccessAddress
& 0xff) < PciRegisterAccessData
->EndOffset
) {
1698 // If current offset doesn't reach the end
1704 // Continue checking access incompatibility
1706 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_WRITE
, AccessAddress
& 0xff, AccessWidth
, &PciRegisterAccessData
);
1707 if (Status
== EFI_SUCCESS
) {
1708 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
1709 AccessWidth
= PciRegisterAccessData
->Width
;
1719 // AccessWidth incompatible check not supportted
1720 // or, there doesn't exist incompatibility on this operation
1722 if (PciRootBridgeIo
!= NULL
) {
1723 Status
= PciRootBridgeIo
->Pci
.Write (
1725 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
1731 Status
= PciIo
->Pci
.Write (
1733 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
1744 Abstract PCI device device information.
1746 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1747 @param PciIo A pointer to EFI_PCI_PROTOCOL.
1748 @param Pci PCI device configuration space.
1749 @param Offset The offset within the PCI configuration space for the PCI controller.
1750 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
1752 @retval EFI_SUCCESS Pci device device information has been abstracted.
1753 @retval EFI_NOT_FOUND Cannot found the specified PCI device.
1754 @retval other Some error occurred when reading PCI device information.
1758 GetPciDeviceDeviceInfo (
1759 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
1760 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
1761 IN PCI_TYPE00
*Pci
, OPTIONAL
1762 IN UINT64 Offset
, OPTIONAL
1763 OUT EFI_PCI_DEVICE_INFO
*PciDeviceInfo
1768 UINT32 PciConfigData
;
1769 PCI_IO_DEVICE
*PciIoDevice
;
1771 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
1772 ASSERT (PciDeviceInfo
!= NULL
);
1774 if (PciIo
!= NULL
) {
1775 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
1778 // Get pointer to PCI_TYPE00 from PciIoDevice
1780 Pci
= &PciIoDevice
->Pci
;
1785 // While PCI_TYPE00 hasn't been gotten, read PCI device device information directly
1787 PciAddress
= Offset
& 0xffffffffffffff00ULL
;
1788 Status
= PciRootBridgeIo
->Pci
.Read (
1796 if (EFI_ERROR (Status
)) {
1800 if ((PciConfigData
& 0xffff) == 0xffff) {
1801 return EFI_NOT_FOUND
;
1804 PciDeviceInfo
->VendorID
= PciConfigData
& 0xffff;
1805 PciDeviceInfo
->DeviceID
= PciConfigData
>> 16;
1807 Status
= PciRootBridgeIo
->Pci
.Read (
1814 if (EFI_ERROR (Status
)) {
1818 PciDeviceInfo
->RevisionID
= PciConfigData
& 0xf;
1820 Status
= PciRootBridgeIo
->Pci
.Read (
1828 if (EFI_ERROR (Status
)) {
1832 PciDeviceInfo
->SubsystemVendorID
= PciConfigData
& 0xffff;
1833 PciDeviceInfo
->SubsystemID
= PciConfigData
>> 16;
1836 PciDeviceInfo
->VendorID
= Pci
->Hdr
.VendorId
;
1837 PciDeviceInfo
->DeviceID
= Pci
->Hdr
.DeviceId
;
1838 PciDeviceInfo
->RevisionID
= Pci
->Hdr
.RevisionID
;
1839 PciDeviceInfo
->SubsystemVendorID
= Pci
->Device
.SubsystemVendorID
;
1840 PciDeviceInfo
->SubsystemID
= Pci
->Device
.SubsystemID
;
1847 Read PCI configuration space with incompatibility check.
1849 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1850 @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL.
1851 @param Pci A pointer to PCI_TYPE00.
1852 @param Width Signifies the width of the memory operations.
1853 @param Offset The offset within the PCI configuration space for the PCI controller.
1854 @param Count The number of unit to be read.
1855 @param Buffer For read operations, the destination buffer to store the results. For
1856 write operations, the source buffer to write data from.
1858 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
1859 @retval EFI_UNSUPPORTED Buffer is NULL.
1860 @retval other Some error occurred when reading PCI configuration space.
1864 PciIncompatibilityCheckRead (
1865 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
1866 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
1867 IN PCI_TYPE00
*Pci
, OPTIONAL
1875 EFI_PCI_DEVICE_INFO PciDeviceInfo
;
1878 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
1879 if (Buffer
== NULL
) {
1880 return EFI_UNSUPPORTED
;
1884 // get PCI device device information
1886 Status
= GetPciDeviceDeviceInfo (PciRootBridgeIo
, PciIo
, Pci
, Offset
, &PciDeviceInfo
);
1887 if (Status
!= EFI_SUCCESS
) {
1891 Stride
= 1 << Width
;
1893 for (; Count
> 0; Count
--, Offset
+= Stride
, Buffer
= (UINT8
*)Buffer
+ Stride
) {
1896 // read configuration register
1898 Status
= ReadConfigData (PciRootBridgeIo
, PciIo
, &PciDeviceInfo
, (UINT64
) Width
, Offset
, Buffer
);
1900 if (Status
!= EFI_SUCCESS
) {
1905 // update the data read from configuration register
1907 if ((PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT
) != 0) {
1908 UpdateConfigData (&PciDeviceInfo
, PCI_REGISTER_READ
, Width
, Offset
& 0xff, Buffer
);
1916 Write PCI configuration space with incompatibility check.
1918 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1919 @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL.
1920 @param Pci A pointer to PCI_TYPE00.
1921 @param Width Signifies the width of the memory operations.
1922 @param Offset The offset within the PCI configuration space for the PCI controller.
1923 @param Count The number of unit to be write.
1924 @param Buffer For read operations, the destination buffer to store the results. For
1925 write operations, the source buffer to write data from.
1927 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
1928 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
1929 valid for the PCI configuration header of the PCI controller.
1931 @retval other Some error occurred when writing PCI configuration space.
1935 PciIncompatibilityCheckWrite (
1936 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
1937 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
1938 IN PCI_TYPE00
*Pci
, OPTIONAL
1946 EFI_PCI_DEVICE_INFO PciDeviceInfo
;
1950 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
1951 if (Buffer
== NULL
) {
1952 return EFI_UNSUPPORTED
;
1956 // Get PCI device device information
1958 Status
= GetPciDeviceDeviceInfo (PciRootBridgeIo
, PciIo
, Pci
, Offset
, &PciDeviceInfo
);
1959 if (Status
!= EFI_SUCCESS
) {
1963 Stride
= 1 << Width
;
1965 for (; Count
> 0; Count
--, Offset
+= Stride
, Buffer
= (UINT8
*) Buffer
+ Stride
) {
1970 case EfiPciWidthUint8
:
1971 Data
= * (UINT8
*) Buffer
;
1973 case EfiPciWidthUint16
:
1974 Data
= * (UINT16
*) Buffer
;
1977 case EfiPciWidthUint32
:
1978 Data
= * (UINT32
*) Buffer
;
1982 return EFI_UNSUPPORTED
;
1986 // Update the data writen into configuration register
1988 if ((PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT
) != 0) {
1989 UpdateConfigData (&PciDeviceInfo
, PCI_REGISTER_WRITE
, Width
, Offset
& 0xff, &Data
);
1993 // Write configuration register
1995 Status
= WriteConfigData (PciRootBridgeIo
, PciIo
, &PciDeviceInfo
, Width
, Offset
, &Data
);
1997 if (Status
!= EFI_SUCCESS
) {
2006 Read PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2008 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2009 @param Pci A pointer to PCI_TYPE00.
2010 @param Width Signifies the width of the memory operations.
2011 @param Offset The offset within the PCI configuration space for the PCI controller.
2012 @param Count The number of unit to be read.
2013 @param Buffer For read operations, the destination buffer to store the results. For
2014 write operations, the source buffer to write data from.
2016 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2017 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2018 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
2022 PciRootBridgeIoRead (
2023 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
2024 IN PCI_TYPE00
*Pci
, OPTIONAL
2025 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
2033 if ((PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_READ_SUPPORT
) != 0) {
2035 // If PCI incompatibility check enabled
2037 Status
= PciIncompatibilityCheckRead (
2046 if (Status
== EFI_UNSUPPORTED
) {
2047 return EFI_INVALID_PARAMETER
;
2052 return PciRootBridgeIo
->Pci
.Read (
2063 Write PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2065 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2066 @param Pci A pointer to PCI_TYPE00.
2067 @param Width Signifies the width of the memory operations.
2068 @param Offset The offset within the PCI configuration space for the PCI controller.
2069 @param Count The number of unit to be read.
2070 @param Buffer For read operations, the destination buffer to store the results. For
2071 write operations, the source buffer to write data from.
2073 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2074 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2075 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
2079 PciRootBridgeIoWrite (
2080 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
2082 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
2090 if ((PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_WRITE_SUPPORT
) != 0) {
2092 // If PCI incompatibility check enabled
2094 Status
= PciIncompatibilityCheckWrite (
2103 if (Status
== EFI_UNSUPPORTED
) {
2104 return EFI_INVALID_PARAMETER
;
2110 return PciRootBridgeIo
->Pci
.Write (
2121 Read PCI configuration space through EFI_PCI_IO_PROTOCOL.
2123 @param PciIo A pointer to the EFI_PCI_O_PROTOCOL.
2124 @param Width Signifies the width of the memory operations.
2125 @param Offset The offset within the PCI configuration space for the PCI controller.
2126 @param Count The number of unit to be read.
2127 @param Buffer For read operations, the destination buffer to store the results. For
2128 write operations, the source buffer to write data from.
2130 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
2131 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
2132 valid for the PCI configuration header of the PCI controller.
2133 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2134 @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
2139 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2140 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
2146 if ((PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_READ_SUPPORT
) != 0) {
2148 // If PCI incompatibility check enabled
2150 return PciIncompatibilityCheckRead (
2160 return PciIo
->Pci
.Read (
2171 Write PCI configuration space through EFI_PCI_IO_PROTOCOL.
2173 If PCI incompatibility check is enabled, do incompatibility check.
2175 @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
2176 @param Width Signifies the width of the memory operations.
2177 @param Offset The offset within the PCI configuration space for the PCI controller.
2178 @param Count The number of PCI configuration operations to perform.
2179 @param Buffer For read operations, the destination buffer to store the results. For write
2180 operations, the source buffer to write data from.
2182 @retval EFI_SUCCESS The data was read from or written to the PCI controller.
2183 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
2184 valid for the PCI configuration header of the PCI controller.
2185 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2186 @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
2191 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2192 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
2198 if ((PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_WRITE_SUPPORT
) != 0) {
2200 // If PCI incompatibility check enabled
2202 return PciIncompatibilityCheckWrite (
2213 return PciIo
->Pci
.Write (