3 PCI Bus Driver Lib file
4 It abstracts some functions that can be different
5 between light PCI bus driver and full PCI bus driver
7 Copyright (c) 2006 - 2008, Intel Corporation
8 All rights reserved. This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_HOTPLUG_REQUEST_PROTOCOL gPciHotPlugRequest
= {
21 PciHotPlugRequestNotify
25 Install protocol gEfiPciHotPlugRequestProtocolGuid
26 @param Status return status of protocol installation.
29 InstallHotPlugRequestProtocol (
35 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
40 *Status
= gBS
->InstallProtocolInterface (
42 &gEfiPciHotPlugRequestProtocolGuid
,
49 Retrieve the BAR information via PciIo interface.
51 @param PciIoDevice Pci device instance.
55 IN PCI_IO_DEVICE
*PciIoDevice
60 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
65 // Read PciBar information from the bar register
67 if (!gFullEnumeration
) {
71 &(PciIoDevice
->PciIo
),
78 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BaseAddress
= (UINT64
) (Address
);
79 (PciIoDevice
->PciBar
)[P2C_MEM_1
].Length
= 0x2000000;
80 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BarType
= PciBarTypeMem32
;
84 &(PciIoDevice
->PciIo
),
90 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BaseAddress
= (UINT64
) (Address
);
91 (PciIoDevice
->PciBar
)[P2C_MEM_2
].Length
= 0x2000000;
92 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BarType
= PciBarTypePMem32
;
96 &(PciIoDevice
->PciIo
),
102 (PciIoDevice
->PciBar
)[P2C_IO_1
].BaseAddress
= (UINT64
) (Address
);
103 (PciIoDevice
->PciBar
)[P2C_IO_1
].Length
= 0x100;
104 (PciIoDevice
->PciBar
)[P2C_IO_1
].BarType
= PciBarTypeIo16
;
108 &(PciIoDevice
->PciIo
),
114 (PciIoDevice
->PciBar
)[P2C_IO_2
].BaseAddress
= (UINT64
) (Address
);
115 (PciIoDevice
->PciBar
)[P2C_IO_2
].Length
= 0x100;
116 (PciIoDevice
->PciBar
)[P2C_IO_2
].BarType
= PciBarTypeIo16
;
120 if (gPciHotPlugInit
!= NULL
) {
121 GetResourcePaddingForHpb (PciIoDevice
);
126 Remove rejected pci device from specific root bridge
129 @param RootBridgeHandle specific parent root bridge handle.
130 @param Bridge Bridge device instance.
132 @retval EFI_SUCCESS Success operation.
135 RemoveRejectedPciDevices (
136 EFI_HANDLE RootBridgeHandle
,
137 IN PCI_IO_DEVICE
*Bridge
141 LIST_ENTRY
*CurrentLink
;
142 LIST_ENTRY
*LastLink
;
144 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
148 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
150 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
152 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
154 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
156 // Remove rejected devices recusively
158 RemoveRejectedPciDevices (RootBridgeHandle
, Temp
);
161 // Skip rejection for all PPBs, while detect rejection for others
163 if (IsPciDeviceRejected (Temp
)) {
166 // For P2C, remove all devices on it
169 if (!IsListEmpty (&Temp
->ChildList
)) {
170 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Temp
);
174 // Finally remove itself
177 LastLink
= CurrentLink
->BackLink
;
178 RemoveEntryList (CurrentLink
);
179 FreePciDevice (Temp
);
181 CurrentLink
= LastLink
;
185 CurrentLink
= CurrentLink
->ForwardLink
;
192 Wrapper function for allocating resource for pci host bridge.
194 @param PciResAlloc Point to protocol instance EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
198 PciHostBridgeResourceAllocator (
199 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
202 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
203 return PciHostBridgeResourceAllocator_WithHotPlugDeviceSupport (
207 return PciHostBridgeResourceAllocator_WithoutHotPlugDeviceSupport (
214 Submits the I/O and memory resource requirements for the specified PCI Root Bridge.
216 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
218 @retval EFI_SUCCESS Success.
221 PciHostBridgeResourceAllocator_WithoutHotPlugDeviceSupport (
222 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
225 PCI_IO_DEVICE
*RootBridgeDev
;
226 EFI_HANDLE RootBridgeHandle
;
234 UINT64 MaxOptionRomSize
;
235 PCI_RESOURCE_NODE
*IoBridge
;
236 PCI_RESOURCE_NODE
*Mem32Bridge
;
237 PCI_RESOURCE_NODE
*PMem32Bridge
;
238 PCI_RESOURCE_NODE
*Mem64Bridge
;
239 PCI_RESOURCE_NODE
*PMem64Bridge
;
240 PCI_RESOURCE_NODE IoPool
;
241 PCI_RESOURCE_NODE Mem32Pool
;
242 PCI_RESOURCE_NODE PMem32Pool
;
243 PCI_RESOURCE_NODE Mem64Pool
;
244 PCI_RESOURCE_NODE PMem64Pool
;
245 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD ExtendedData
;
248 // Initialize resource pool
251 InitializeResourcePool (&IoPool
, PciBarTypeIo16
);
252 InitializeResourcePool (&Mem32Pool
, PciBarTypeMem32
);
253 InitializeResourcePool (&PMem32Pool
, PciBarTypePMem32
);
254 InitializeResourcePool (&Mem64Pool
, PciBarTypeMem64
);
255 InitializeResourcePool (&PMem64Pool
, PciBarTypePMem64
);
257 RootBridgeDev
= NULL
;
258 RootBridgeHandle
= 0;
260 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
262 // Get RootBridg Device by handle
264 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
266 if (RootBridgeDev
== NULL
) {
267 return EFI_NOT_FOUND
;
271 // Get host bridge handle for status report
273 ExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
276 // Create the entire system resource map from the information collected by
277 // enumerator. Several resource tree was created
280 IoBridge
= CreateResourceNode (
289 Mem32Bridge
= CreateResourceNode (
298 PMem32Bridge
= CreateResourceNode (
307 Mem64Bridge
= CreateResourceNode (
316 PMem64Bridge
= CreateResourceNode (
326 // Create resourcemap by going through all the devices subject to this root bridge
328 Status
= CreateResourceMap (
338 // Get the max ROM size that the root bridge can process
340 RootBridgeDev
->RomSize
= Mem32Bridge
->Length
;
343 // Get Max Option Rom size for current root bridge
345 MaxOptionRomSize
= GetMaxOptionRomSize (RootBridgeDev
);
348 // Enlarger the mem32 resource to accomdate the option rom
349 // if the mem32 resource is not enough to hold the rom
351 if (MaxOptionRomSize
> Mem32Bridge
->Length
) {
353 Mem32Bridge
->Length
= MaxOptionRomSize
;
354 RootBridgeDev
->RomSize
= MaxOptionRomSize
;
357 // Alignment should be adjusted as well
359 if (Mem32Bridge
->Alignment
< MaxOptionRomSize
- 1) {
360 Mem32Bridge
->Alignment
= MaxOptionRomSize
- 1;
365 // Based on the all the resource tree, contruct ACPI resource node to
366 // submit the resource aperture to pci host bridge protocol
368 Status
= ConstructAcpiResourceRequestor (
379 // Insert these resource nodes into the database
381 InsertResourceNode (&IoPool
, IoBridge
);
382 InsertResourceNode (&Mem32Pool
, Mem32Bridge
);
383 InsertResourceNode (&PMem32Pool
, PMem32Bridge
);
384 InsertResourceNode (&Mem64Pool
, Mem64Bridge
);
385 InsertResourceNode (&PMem64Pool
, PMem64Bridge
);
387 if (Status
== EFI_SUCCESS
) {
389 // Submit the resource requirement
391 Status
= PciResAlloc
->SubmitResources (
393 RootBridgeDev
->Handle
,
398 // Free acpi resource node
400 if (AcpiConfig
!= NULL
) {
401 FreePool (AcpiConfig
);
404 if (EFI_ERROR (Status
)) {
406 // Destroy all the resource tree
408 DestroyResourceTree (&IoPool
);
409 DestroyResourceTree (&Mem32Pool
);
410 DestroyResourceTree (&PMem32Pool
);
411 DestroyResourceTree (&Mem64Pool
);
412 DestroyResourceTree (&PMem64Pool
);
421 // Notify pci bus driver starts to program the resource
423 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeAllocateResources
);
425 if (EFI_ERROR (Status
)) {
427 // Allocation failed, then return
429 return EFI_OUT_OF_RESOURCES
;
432 // Raise the EFI_IOB_PCI_RES_ALLOC status code
434 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
436 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_RES_ALLOC
,
437 (VOID
*) &ExtendedData
,
438 sizeof (ExtendedData
)
442 // Notify pci bus driver starts to program the resource
444 NotifyPhase (PciResAlloc
, EfiPciHostBridgeSetResources
);
446 RootBridgeDev
= NULL
;
448 RootBridgeHandle
= 0;
450 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
452 // Get RootBridg Device by handle
454 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
456 if (RootBridgeDev
== NULL
) {
457 return EFI_NOT_FOUND
;
461 // Get acpi resource node for all the resource types
464 Status
= PciResAlloc
->GetProposedResources (
466 RootBridgeDev
->Handle
,
469 if (EFI_ERROR (Status
)) {
474 // Get the resource base by interpreting acpi resource node
487 // Process option rom for this root bridge
489 Status
= ProcessOptionRom (RootBridgeDev
, Mem32Base
, RootBridgeDev
->RomSize
);
492 // Create the entire system resource map from the information collected by
493 // enumerator. Several resource tree was created
495 Status
= GetResourceMap (
509 if (EFI_ERROR (Status
)) {
514 // Program IO resources
522 // Program Mem32 resources
530 // Program PMem32 resources
538 // Program Mem64 resources
546 // Program PMem64 resources
553 FreePool (AcpiConfig
);
557 // Destroy all the resource tree
559 DestroyResourceTree (&IoPool
);
560 DestroyResourceTree (&Mem32Pool
);
561 DestroyResourceTree (&PMem32Pool
);
562 DestroyResourceTree (&Mem64Pool
);
563 DestroyResourceTree (&PMem64Pool
);
566 // Notify the resource allocation phase is to end
568 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndResourceAllocation
);
574 Submits the I/O and memory resource requirements for the specified PCI Root Bridge.
576 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
578 @retval EFI_SUCCESS Success.
581 PciHostBridgeResourceAllocator_WithHotPlugDeviceSupport (
582 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
585 PCI_IO_DEVICE
*RootBridgeDev
;
586 EFI_HANDLE RootBridgeHandle
;
595 UINT64 Mem32ResStatus
;
596 UINT64 PMem32ResStatus
;
597 UINT64 Mem64ResStatus
;
598 UINT64 PMem64ResStatus
;
599 UINT64 MaxOptionRomSize
;
600 PCI_RESOURCE_NODE
*IoBridge
;
601 PCI_RESOURCE_NODE
*Mem32Bridge
;
602 PCI_RESOURCE_NODE
*PMem32Bridge
;
603 PCI_RESOURCE_NODE
*Mem64Bridge
;
604 PCI_RESOURCE_NODE
*PMem64Bridge
;
605 PCI_RESOURCE_NODE IoPool
;
606 PCI_RESOURCE_NODE Mem32Pool
;
607 PCI_RESOURCE_NODE PMem32Pool
;
608 PCI_RESOURCE_NODE Mem64Pool
;
609 PCI_RESOURCE_NODE PMem64Pool
;
611 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData
;
612 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData
;
620 // It will try several times if the resource allocation fails
625 // Initialize resource pool
627 InitializeResourcePool (&IoPool
, PciBarTypeIo16
);
628 InitializeResourcePool (&Mem32Pool
, PciBarTypeMem32
);
629 InitializeResourcePool (&PMem32Pool
, PciBarTypePMem32
);
630 InitializeResourcePool (&Mem64Pool
, PciBarTypeMem64
);
631 InitializeResourcePool (&PMem64Pool
, PciBarTypePMem64
);
633 RootBridgeDev
= NULL
;
634 RootBridgeHandle
= 0;
636 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
639 // Get RootBridg Device by handle
641 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
643 if (RootBridgeDev
== NULL
) {
644 return EFI_NOT_FOUND
;
648 // Create the entire system resource map from the information collected by
649 // enumerator. Several resource tree was created
652 IoBridge
= CreateResourceNode (
661 Mem32Bridge
= CreateResourceNode (
670 PMem32Bridge
= CreateResourceNode (
679 Mem64Bridge
= CreateResourceNode (
688 PMem64Bridge
= CreateResourceNode (
698 // Create resourcemap by going through all the devices subject to this root bridge
700 Status
= CreateResourceMap (
710 // Get the max ROM size that the root bridge can process
712 RootBridgeDev
->RomSize
= Mem32Bridge
->Length
;
715 // Skip to enlarge the resource request during realloction
719 // Get Max Option Rom size for current root bridge
721 MaxOptionRomSize
= GetMaxOptionRomSize (RootBridgeDev
);
724 // Enlarger the mem32 resource to accomdate the option rom
725 // if the mem32 resource is not enough to hold the rom
727 if (MaxOptionRomSize
> Mem32Bridge
->Length
) {
729 Mem32Bridge
->Length
= MaxOptionRomSize
;
730 RootBridgeDev
->RomSize
= MaxOptionRomSize
;
733 // Alignment should be adjusted as well
735 if (Mem32Bridge
->Alignment
< MaxOptionRomSize
- 1) {
736 Mem32Bridge
->Alignment
= MaxOptionRomSize
- 1;
742 // Based on the all the resource tree, contruct ACPI resource node to
743 // submit the resource aperture to pci host bridge protocol
745 Status
= ConstructAcpiResourceRequestor (
756 // Insert these resource nodes into the database
758 InsertResourceNode (&IoPool
, IoBridge
);
759 InsertResourceNode (&Mem32Pool
, Mem32Bridge
);
760 InsertResourceNode (&PMem32Pool
, PMem32Bridge
);
761 InsertResourceNode (&Mem64Pool
, Mem64Bridge
);
762 InsertResourceNode (&PMem64Pool
, PMem64Bridge
);
764 if (Status
== EFI_SUCCESS
) {
766 // Submit the resource requirement
768 Status
= PciResAlloc
->SubmitResources (
770 RootBridgeDev
->Handle
,
776 // Free acpi resource node
778 if (AcpiConfig
!= NULL
) {
779 FreePool (AcpiConfig
);
782 if (EFI_ERROR (Status
)) {
784 // Destroy all the resource tree
786 DestroyResourceTree (&IoPool
);
787 DestroyResourceTree (&Mem32Pool
);
788 DestroyResourceTree (&PMem32Pool
);
789 DestroyResourceTree (&Mem64Pool
);
790 DestroyResourceTree (&PMem64Pool
);
796 // Notify pci bus driver starts to program the resource
799 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeAllocateResources
);
801 if (!EFI_ERROR (Status
)) {
803 // Allocation succeed, then continue the following
809 // If the resource allocation is unsuccessful, free resources on bridge
812 RootBridgeDev
= NULL
;
813 RootBridgeHandle
= 0;
815 IoResStatus
= EFI_RESOURCE_SATISFIED
;
816 Mem32ResStatus
= EFI_RESOURCE_SATISFIED
;
817 PMem32ResStatus
= EFI_RESOURCE_SATISFIED
;
818 Mem64ResStatus
= EFI_RESOURCE_SATISFIED
;
819 PMem64ResStatus
= EFI_RESOURCE_SATISFIED
;
821 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
823 // Get RootBridg Device by handle
825 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
826 if (RootBridgeDev
== NULL
) {
827 return EFI_NOT_FOUND
;
831 // Get host bridge handle for status report
833 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
836 // Get acpi resource node for all the resource types
840 Status
= PciResAlloc
->GetProposedResources (
842 RootBridgeDev
->Handle
,
846 if (EFI_ERROR (Status
)) {
850 if (AcpiConfig
!= NULL
) {
852 // Adjust resource allocation policy for each RB
854 GetResourceAllocationStatus (
862 FreePool (AcpiConfig
);
870 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
873 // It is very difficult to follow the spec here
874 // Device path , Bar index can not be get here
876 ZeroMem (&AllocFailExtendedData
, sizeof (AllocFailExtendedData
));
878 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
880 EFI_IO_BUS_PCI
| EFI_IOB_EC_RESOURCE_CONFLICT
,
881 (VOID
*) &AllocFailExtendedData
,
882 sizeof (AllocFailExtendedData
)
885 Status
= PciHostBridgeAdjustAllocation (
899 // Destroy all the resource tree
901 DestroyResourceTree (&IoPool
);
902 DestroyResourceTree (&Mem32Pool
);
903 DestroyResourceTree (&PMem32Pool
);
904 DestroyResourceTree (&Mem64Pool
);
905 DestroyResourceTree (&PMem64Pool
);
907 NotifyPhase (PciResAlloc
, EfiPciHostBridgeFreeResources
);
909 if (EFI_ERROR (Status
)) {
921 // Raise the EFI_IOB_PCI_RES_ALLOC status code
923 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
925 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_RES_ALLOC
,
926 (VOID
*) &HandleExtendedData
,
927 sizeof (HandleExtendedData
)
931 // Notify pci bus driver starts to program the resource
933 NotifyPhase (PciResAlloc
, EfiPciHostBridgeSetResources
);
935 RootBridgeDev
= NULL
;
937 RootBridgeHandle
= 0;
939 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
942 // Get RootBridg Device by handle
944 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
946 if (RootBridgeDev
== NULL
) {
947 return EFI_NOT_FOUND
;
951 // Get acpi resource node for all the resource types
954 Status
= PciResAlloc
->GetProposedResources (
956 RootBridgeDev
->Handle
,
960 if (EFI_ERROR (Status
)) {
965 // Get the resource base by interpreting acpi resource node
978 // Process option rom for this root bridge
980 Status
= ProcessOptionRom (RootBridgeDev
, Mem32Base
, RootBridgeDev
->RomSize
);
983 // Create the entire system resource map from the information collected by
984 // enumerator. Several resource tree was created
986 Status
= GetResourceMap (
1000 if (EFI_ERROR (Status
)) {
1005 // Program IO resources
1013 // Program Mem32 resources
1021 // Program PMem32 resources
1029 // Program Mem64 resources
1037 // Program PMem64 resources
1044 FreePool (AcpiConfig
);
1048 // Destroy all the resource tree
1050 DestroyResourceTree (&IoPool
);
1051 DestroyResourceTree (&Mem32Pool
);
1052 DestroyResourceTree (&PMem32Pool
);
1053 DestroyResourceTree (&Mem64Pool
);
1054 DestroyResourceTree (&PMem64Pool
);
1057 // Notify the resource allocation phase is to end
1059 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndResourceAllocation
);
1065 Wapper function of scanning pci bus and assign bus number to the given PCI bus system
1066 Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
1068 @param Bridge Bridge device instance.
1069 @param StartBusNumber start point.
1070 @param SubBusNumber Point to sub bus number.
1071 @param PaddedBusRange Customized bus number.
1073 @retval EFI_SUCCESS Success.
1074 @retval EFI_DEVICE_ERROR Fail to scan bus.
1078 IN PCI_IO_DEVICE
*Bridge
,
1079 IN UINT8 StartBusNumber
,
1080 OUT UINT8
*SubBusNumber
,
1081 OUT UINT8
*PaddedBusRange
1084 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1085 return PciScanBus_WithHotPlugDeviceSupport (
1092 return PciScanBus_WithoutHotPlugDeviceSupport (
1102 Wapper function of scanning pci bus and assign bus number to the given PCI bus system
1103 Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
1105 @param Bridge Bridge device instance.
1106 @param StartBusNumber start point.
1107 @param SubBusNumber Point to sub bus number.
1108 @param PaddedBusRange Customized bus number.
1110 @retval EFI_SUCCESS Success.
1111 @retval EFI_DEVICE_ERROR Fail to scan bus.
1114 PciScanBus_WithoutHotPlugDeviceSupport (
1115 IN PCI_IO_DEVICE
*Bridge
,
1116 IN UINT8 StartBusNumber
,
1117 OUT UINT8
*SubBusNumber
,
1118 OUT UINT8
*PaddedBusRange
1128 PCI_IO_DEVICE
*PciDevice
;
1129 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1131 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
1135 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
1136 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
1139 // Check to see whether a pci device is present
1141 Status
= PciDevicePresent (
1149 if (!EFI_ERROR (Status
)) {
1150 DEBUG((EFI_D_ERROR
, "Found DEV(%02d,%02d,%02d)\n", StartBusNumber
, Device
, Func
));
1152 if (IS_PCI_BRIDGE (&Pci
) ||
1153 IS_CARDBUS_BRIDGE (&Pci
)) {
1156 // Get the bridge information
1158 Status
= PciSearchDevice (
1167 if (EFI_ERROR (Status
)) {
1172 // Add feature to support customized secondary bus number
1174 if (*SubBusNumber
== 0) {
1175 *SubBusNumber
= *PaddedBusRange
;
1176 *PaddedBusRange
= 0;
1181 SecondBus
= (*SubBusNumber
);
1183 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
1185 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
1187 Status
= PciRootBridgeIoWrite (
1197 // Initialize SubBusNumber to SecondBus
1199 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1200 Status
= PciRootBridgeIoWrite (
1209 // If it is PPB, resursively search down this bridge
1211 if (IS_PCI_BRIDGE (&Pci
)) {
1213 // Temporarily initialize SubBusNumber to maximum bus number to ensure the
1214 // PCI configuration transaction to go through any PPB
1216 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1218 Status
= PciRootBridgeIoWrite (
1227 PreprocessController (
1229 PciDevice
->BusNumber
,
1230 PciDevice
->DeviceNumber
,
1231 PciDevice
->FunctionNumber
,
1232 EfiPciBeforeChildBusEnumeration
1235 DEBUG((EFI_D_ERROR
, "Scan PPB(%02d,%02d,%02d)\n", PciDevice
->BusNumber
, PciDevice
->DeviceNumber
,PciDevice
->FunctionNumber
));
1236 Status
= PciScanBus (
1238 (UINT8
) (SecondBus
),
1243 if (EFI_ERROR (Status
)) {
1244 return EFI_DEVICE_ERROR
;
1249 // Set the current maximum bus number under the PPB
1252 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1254 Status
= PciRootBridgeIoWrite (
1265 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
1268 // Skip sub functions, this is not a multi function device
1271 Func
= PCI_MAX_FUNC
;
1280 Wapper function of scanning pci bus and assign bus number to the given PCI bus system
1281 Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
1283 @param Bridge Bridge device instance.
1284 @param StartBusNumber start point.
1285 @param SubBusNumber Point to sub bus number.
1286 @param PaddedBusRange Customized bus number.
1288 @retval EFI_SUCCESS Success.
1289 @retval EFI_DEVICE_ERROR Fail to scan bus.
1292 PciScanBus_WithHotPlugDeviceSupport (
1293 IN PCI_IO_DEVICE
*Bridge
,
1294 IN UINT8 StartBusNumber
,
1295 OUT UINT8
*SubBusNumber
,
1296 OUT UINT8
*PaddedBusRange
1307 PCI_IO_DEVICE
*PciDevice
;
1309 EFI_HPC_STATE State
;
1311 EFI_HPC_PADDING_ATTRIBUTES Attributes
;
1312 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1314 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1317 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
1321 Attributes
= (EFI_HPC_PADDING_ATTRIBUTES
) 0;
1324 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
1325 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
1328 // Check to see whether a pci device is present
1330 Status
= PciDevicePresent (
1338 if (EFI_ERROR (Status
)) {
1341 // Skip sub functions, this is not a multi function device
1343 Func
= PCI_MAX_FUNC
;
1349 DEBUG((EFI_D_ERROR
, "Found DEV(%02d,%02d,%02d)\n", StartBusNumber
, Device
, Func
));
1352 // Get the PCI device information
1354 Status
= PciSearchDevice (
1363 ASSERT (!EFI_ERROR (Status
));
1365 PciAddress
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0);
1367 if (!IS_PCI_BRIDGE (&Pci
)) {
1369 // PCI bridges will be called later
1370 // Here just need for PCI device or PCI to cardbus controller
1371 // EfiPciBeforeChildBusEnumeration for PCI Device Node
1373 PreprocessController (
1375 PciDevice
->BusNumber
,
1376 PciDevice
->DeviceNumber
,
1377 PciDevice
->FunctionNumber
,
1378 EfiPciBeforeChildBusEnumeration
1383 // For Pci Hotplug controller devcie only
1385 if (gPciHotPlugInit
!= NULL
) {
1387 // Check if it is a Hotplug PCI controller
1389 if (IsRootPciHotPlugController (PciDevice
->DevicePath
, &HpIndex
)) {
1391 if (!gPciRootHpcData
[HpIndex
].Initialized
) {
1393 Status
= CreateEventForHpc (HpIndex
, &Event
);
1395 ASSERT (!EFI_ERROR (Status
));
1397 Status
= gPciHotPlugInit
->InitializeRootHpc (
1399 gPciRootHpcPool
[HpIndex
].HpcDevicePath
,
1405 PreprocessController (
1407 PciDevice
->BusNumber
,
1408 PciDevice
->DeviceNumber
,
1409 PciDevice
->FunctionNumber
,
1410 EfiPciBeforeChildBusEnumeration
1416 if (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
)) {
1419 // Get the bridge information
1422 if (gPciHotPlugInit
!= NULL
) {
1424 if (IsRootPciHotPlugBus (PciDevice
->DevicePath
, &HpIndex
)) {
1427 // If it is initialized, get the padded bus range
1429 Status
= gPciHotPlugInit
->GetResourcePadding (
1431 gPciRootHpcPool
[HpIndex
].HpbDevicePath
,
1434 (VOID
**) &Descriptors
,
1438 if (EFI_ERROR (Status
)) {
1443 Status
= PciGetBusRange (
1450 gBS
->FreePool (Descriptors
);
1452 if (EFI_ERROR (Status
)) {
1461 // Add feature to support customized secondary bus number
1463 if (*SubBusNumber
== 0) {
1464 *SubBusNumber
= *PaddedBusRange
;
1465 *PaddedBusRange
= 0;
1469 SecondBus
= *SubBusNumber
;
1471 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
1472 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
1474 Status
= PciRootBridgeIoWrite (
1485 // If it is PPB, resursively search down this bridge
1487 if (IS_PCI_BRIDGE (&Pci
)) {
1490 // Initialize SubBusNumber to Maximum bus number
1493 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1494 Status
= PciRootBridgeIoWrite (
1504 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
1506 PreprocessController (
1508 PciDevice
->BusNumber
,
1509 PciDevice
->DeviceNumber
,
1510 PciDevice
->FunctionNumber
,
1511 EfiPciBeforeChildBusEnumeration
1514 DEBUG((EFI_D_ERROR
, "Scan PPB(%02d,%02d,%02d)\n", PciDevice
->BusNumber
, PciDevice
->DeviceNumber
,PciDevice
->FunctionNumber
));
1515 Status
= PciScanBus (
1517 (UINT8
) (SecondBus
),
1522 if (EFI_ERROR (Status
)) {
1523 return EFI_DEVICE_ERROR
;
1529 // Ensure the device is enabled and initialized
1531 if ((Attributes
== EfiPaddingPciRootBridge
) &&
1532 (State
& EFI_HPC_STATE_ENABLED
) != 0 &&
1533 (State
& EFI_HPC_STATE_INITIALIZED
) != 0) {
1534 *PaddedBusRange
= (UINT8
) ((UINT8
) (BusRange
) +*PaddedBusRange
);
1536 *SubBusNumber
= (UINT8
) ((UINT8
) (BusRange
) +*SubBusNumber
);
1541 // Set the current maximum bus number under the PPB
1543 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1545 Status
= PciRootBridgeIoWrite (
1555 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
1558 // Skip sub functions, this is not a multi function device
1560 Func
= PCI_MAX_FUNC
;
1570 Process Option Rom on this host bridge.
1572 @param Bridge Pci bridge device instance.
1574 @retval EFI_SUCCESS Success.
1577 PciRootBridgeP2CProcess (
1578 IN PCI_IO_DEVICE
*Bridge
1581 LIST_ENTRY
*CurrentLink
;
1582 PCI_IO_DEVICE
*Temp
;
1583 EFI_HPC_STATE State
;
1587 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1589 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
1591 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1593 if (IS_CARDBUS_BRIDGE (&Temp
->Pci
)) {
1595 if (gPciHotPlugInit
!= NULL
&& Temp
->Allocated
) {
1598 // Raise the EFI_IOB_PCI_HPC_INIT status code
1600 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1602 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_HPC_INIT
,
1606 PciAddress
= EFI_PCI_ADDRESS (Temp
->BusNumber
, Temp
->DeviceNumber
, Temp
->FunctionNumber
, 0);
1607 Status
= gPciHotPlugInit
->InitializeRootHpc (
1615 if (!EFI_ERROR (Status
)) {
1616 Status
= PciBridgeEnumerator (Temp
);
1618 if (EFI_ERROR (Status
)) {
1623 CurrentLink
= CurrentLink
->ForwardLink
;
1629 if (!IsListEmpty (&Temp
->ChildList
)) {
1630 Status
= PciRootBridgeP2CProcess (Temp
);
1633 CurrentLink
= CurrentLink
->ForwardLink
;
1640 Process Option Rom on this host bridge.
1642 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
1644 @retval EFI_NOT_FOUND Can not find the root bridge instance.
1645 @retval EFI_SUCCESS Success process.
1648 PciHostBridgeP2CProcess (
1649 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1652 EFI_HANDLE RootBridgeHandle
;
1653 PCI_IO_DEVICE
*RootBridgeDev
;
1656 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1660 RootBridgeHandle
= NULL
;
1662 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1665 // Get RootBridg Device by handle
1667 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
1669 if (RootBridgeDev
== NULL
) {
1670 return EFI_NOT_FOUND
;
1673 Status
= PciRootBridgeP2CProcess (RootBridgeDev
);
1675 if (EFI_ERROR (Status
)) {
1685 This function is used to enumerate the entire host bridge
1686 in a given platform.
1688 @param PciResAlloc A pointer to the resource allocate protocol.
1690 @retval EFI_OUT_OF_RESOURCES no enough resource.
1691 @retval EFI_SUCCESS Success.
1695 PciHostBridgeEnumerator (
1696 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1699 EFI_HANDLE RootBridgeHandle
;
1700 PCI_IO_DEVICE
*RootBridgeDev
;
1702 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1704 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1705 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration
;
1706 UINT8 StartBusNumber
;
1707 LIST_ENTRY RootBridgeList
;
1710 InitializeHotPlugSupport ();
1712 InitializeListHead (&RootBridgeList
);
1715 // Notify the bus allocation phase is about to start
1717 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1719 DEBUG((EFI_D_ERROR
, "PCI Bus First Scanning\n"));
1720 RootBridgeHandle
= NULL
;
1721 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1724 // if a root bridge instance is found, create root bridge device for it
1727 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1729 if (RootBridgeDev
== NULL
) {
1730 return EFI_OUT_OF_RESOURCES
;
1734 // Enumerate all the buses under this root bridge
1737 Status
= PciRootBridgeEnumerator (
1742 if (gPciHotPlugInit
!= NULL
) {
1743 InsertTailList (&RootBridgeList
, &(RootBridgeDev
->Link
));
1745 DestroyRootBridge (RootBridgeDev
);
1747 if (EFI_ERROR (Status
)) {
1753 // Notify the bus allocation phase is finished for the first time
1755 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1757 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1759 if (gPciHotPlugInit
!= NULL
) {
1761 // Reset all assigned PCI bus number in all PPB
1763 RootBridgeHandle
= NULL
;
1764 Link
= GetFirstNode (&RootBridgeList
);
1765 while ((PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) &&
1766 (!IsNull (&RootBridgeList
, Link
))) {
1767 RootBridgeDev
= PCI_IO_DEVICE_FROM_LINK (Link
);
1769 // Get the Bus information
1771 Status
= PciResAlloc
->StartBusEnumeration (
1774 (VOID
**) &Configuration
1776 if (EFI_ERROR (Status
)) {
1781 // Get the bus number to start with
1783 StartBusNumber
= (UINT8
) (Configuration
->AddrRangeMin
);
1785 ResetAllPpbBusNumber (
1790 gBS
->FreePool (Configuration
);
1791 Link
= GetNextNode (&RootBridgeList
, Link
);
1792 DestroyRootBridge (RootBridgeDev
);
1796 // Wait for all HPC initialized
1798 Status
= AllRootHPCInitialized (STALL_1_SECOND
* 15);
1800 if (EFI_ERROR (Status
)) {
1805 // Notify the bus allocation phase is about to start for the 2nd time
1807 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1809 DEBUG((EFI_D_ERROR
, "PCI Bus Second Scanning\n"));
1810 RootBridgeHandle
= NULL
;
1811 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1814 // if a root bridge instance is found, create root bridge device for it
1817 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1819 if (RootBridgeDev
== NULL
) {
1820 return EFI_OUT_OF_RESOURCES
;
1824 // Enumerate all the buses under this root bridge
1827 Status
= PciRootBridgeEnumerator (
1832 DestroyRootBridge (RootBridgeDev
);
1833 if (EFI_ERROR (Status
)) {
1839 // Notify the bus allocation phase is to end for the 2nd time
1841 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1846 // Notify the resource allocation phase is to start
1848 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginResourceAllocation
);
1850 RootBridgeHandle
= NULL
;
1851 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1854 // if a root bridge instance is found, create root bridge device for it
1857 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1859 if (RootBridgeDev
== NULL
) {
1860 return EFI_OUT_OF_RESOURCES
;
1863 Status
= StartManagingRootBridge (RootBridgeDev
);
1865 if (EFI_ERROR (Status
)) {
1869 PciRootBridgeIo
= RootBridgeDev
->PciRootBridgeIo
;
1870 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
1872 if (EFI_ERROR (Status
)) {
1876 Status
= PciGetBusRange (&Descriptors
, &MinBus
, NULL
, NULL
);
1878 if (EFI_ERROR (Status
)) {
1883 // Determine root bridge attribute by calling interface of Pcihostbridge
1886 DetermineRootBridgeAttributes (
1892 // Collect all the resource information under this root bridge
1893 // A database that records all the information about pci device subject to this
1894 // root bridge will then be created
1896 Status
= PciPciDeviceInfoCollector (
1901 if (EFI_ERROR (Status
)) {
1905 InsertRootBridge (RootBridgeDev
);
1908 // Record the hostbridge handle
1910 AddHostBridgeEnumerator (RootBridgeDev
->PciRootBridgeIo
->ParentHandle
);
1917 Read PCI device configuration register by specified address.
1919 This function check the incompatiblilites on PCI device. Return the register
1922 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1923 @param PciIo A pointer to EFI_PCI_PROTOCOL.
1924 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
1925 @param Width Signifies the width of the memory operations.
1926 @param Address The address within the PCI configuration space for the PCI controller.
1927 @param Buffer For read operations, the destination buffer to store the results. For
1928 write operations, the source buffer to write data from.
1930 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
1931 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
1932 @retval EFI_INVALID_PARAMETER Buffer is NULL.
1933 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1938 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
1939 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
1940 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
1948 EFI_PCI_REGISTER_ACCESS_DATA
*PciRegisterAccessData
;
1949 UINT64 AccessAddress
;
1954 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
1956 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT
) {
1958 // check access compatibility at first time
1960 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_READ
, Address
& 0xff, Width
, &PciRegisterAccessData
);
1962 if (Status
== EFI_SUCCESS
) {
1964 // there exist incompatibility on this operation
1966 AccessWidth
= Width
;
1968 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
1969 AccessWidth
= PciRegisterAccessData
->Width
;
1972 AccessAddress
= Address
& ~((1 << AccessWidth
) - 1);
1976 Pointer
= (UINT8
*) &TempBuffer
;
1980 if (PciRootBridgeIo
!= NULL
) {
1981 Status
= PciRootBridgeIo
->Pci
.Read (
1983 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) AccessWidth
,
1988 } else if (PciIo
!= NULL
) {
1989 Status
= PciIo
->Pci
.Read (
1991 (EFI_PCI_IO_PROTOCOL_WIDTH
) AccessWidth
,
1992 (UINT32
) AccessAddress
,
1998 if (Status
!= EFI_SUCCESS
) {
2002 Stride
= (UINTN
)1 << AccessWidth
;
2003 AccessAddress
+= Stride
;
2004 if (AccessAddress
>= (Address
+ LShiftU64 (1ULL, (UINTN
)Width
))) {
2006 // if all datas have been read, exist
2013 if ((AccessAddress
& 0xff) < PciRegisterAccessData
->EndOffset
) {
2015 // if current offset doesn't reach the end
2020 FreePool (PciRegisterAccessData
);
2023 // continue checking access incompatibility
2025 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_READ
, AccessAddress
& 0xff, AccessWidth
, &PciRegisterAccessData
);
2026 if (Status
== EFI_SUCCESS
) {
2027 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
2028 AccessWidth
= PciRegisterAccessData
->Width
;
2033 FreePool (PciRegisterAccessData
);
2036 case EfiPciWidthUint8
:
2037 * (UINT8
*) Buffer
= (UINT8
) TempBuffer
;
2039 case EfiPciWidthUint16
:
2040 * (UINT16
*) Buffer
= (UINT16
) TempBuffer
;
2042 case EfiPciWidthUint32
:
2043 * (UINT32
*) Buffer
= (UINT32
) TempBuffer
;
2046 return EFI_UNSUPPORTED
;
2053 // AccessWidth incompatible check not supportted
2054 // or, there doesn't exist incompatibility on this operation
2056 if (PciRootBridgeIo
!= NULL
) {
2057 Status
= PciRootBridgeIo
->Pci
.Read (
2059 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
2066 Status
= PciIo
->Pci
.Read (
2068 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
2079 Update register value by checking PCI device incompatibility.
2081 This function check register value incompatibilites on PCI device. Return the register
2084 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
2085 @param AccessType Access type, READ or WRITE.
2086 @param Width Signifies the width of the memory operations.
2087 @param Address The address within the PCI configuration space.
2088 @param Buffer Store the register data.
2090 @retval EFI_SUCCESS The data has been updated.
2095 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
2096 IN UINT64 AccessType
,
2103 EFI_PCI_REGISTER_VALUE_DATA
*PciRegisterData
;
2109 // check register value incompatibility
2111 Status
= PciRegisterUpdateCheck (PciDeviceInfo
, AccessType
, Address
& 0xff, &PciRegisterData
);
2113 if (Status
== EFI_SUCCESS
) {
2115 AndValue
= ((UINT32
) PciRegisterData
->AndValue
) >> (((UINT8
) Address
& 0x3) * 8);
2116 OrValue
= ((UINT32
) PciRegisterData
->OrValue
) >> (((UINT8
) Address
& 0x3) * 8);
2118 TempValue
= * (UINT32
*) Buffer
;
2119 if (PciRegisterData
->AndValue
!= VALUE_NOCARE
) {
2120 TempValue
&= AndValue
;
2122 if (PciRegisterData
->OrValue
!= VALUE_NOCARE
) {
2123 TempValue
|= OrValue
;
2127 case EfiPciWidthUint8
:
2128 *(UINT8
*)Buffer
= (UINT8
) TempValue
;
2131 case EfiPciWidthUint16
:
2132 *(UINT16
*)Buffer
= (UINT16
) TempValue
;
2134 case EfiPciWidthUint32
:
2135 *(UINT32
*)Buffer
= TempValue
;
2139 return EFI_UNSUPPORTED
;
2142 FreePool (PciRegisterData
);
2149 Write PCI device configuration register by specified address.
2151 This function check the incompatiblilites on PCI device, and write date
2154 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2155 @param PciIo A pointer to EFI_PCI_PROTOCOL.
2156 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
2157 @param Width Signifies the width of the memory operations.
2158 @param Address The address within the PCI configuration space for the PCI controller.
2159 @param Buffer For read operations, the destination buffer to store the results. For
2160 write operations, the source buffer to write data from.
2162 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2163 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2164 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2165 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2170 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
2171 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
2172 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
2180 EFI_PCI_REGISTER_ACCESS_DATA
*PciRegisterAccessData
;
2181 UINT64 AccessAddress
;
2187 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
2189 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT
) {
2191 // check access compatibility at first time
2193 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_WRITE
, Address
& 0xff, Width
, &PciRegisterAccessData
);
2195 if (Status
== EFI_SUCCESS
) {
2197 // there exist incompatibility on this operation
2199 AccessWidth
= Width
;
2201 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
2202 AccessWidth
= PciRegisterAccessData
->Width
;
2205 AccessAddress
= Address
& ~((1 << AccessWidth
) - 1);
2208 Pointer
= (UINT8
*) &Buffer
;
2209 Data
= * (UINT64
*) Buffer
;
2213 if (AccessWidth
> Width
) {
2215 // if actual access width is larger than orignal one, additional data need to be read back firstly
2217 Status
= ReadConfigData (PciRootBridgeIo
, PciIo
, PciDeviceInfo
, AccessWidth
, AccessAddress
, &Data
);
2218 if (Status
!= EFI_SUCCESS
) {
2223 // check data read incompatibility
2225 UpdateConfigData (PciDeviceInfo
, PCI_REGISTER_READ
, AccessWidth
, AccessAddress
& 0xff, &Data
);
2227 Shift
= (UINTN
)(Address
- AccessAddress
) * 8;
2229 case EfiPciWidthUint8
:
2230 Data
= (* (UINT8
*) Buffer
) << Shift
| (Data
& ~(0xff << Shift
));
2233 case EfiPciWidthUint16
:
2234 Data
= (* (UINT16
*) Buffer
) << Shift
| (Data
& ~(0xffff << Shift
));
2239 // check data write incompatibility
2241 UpdateConfigData (PciDeviceInfo
, PCI_REGISTER_WRITE
, AccessWidth
, MultU64x32 (AccessAddress
, 0xff), &Data
);
2244 if (PciRootBridgeIo
!= NULL
) {
2245 Status
= PciRootBridgeIo
->Pci
.Write (
2247 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) AccessWidth
,
2253 Status
= PciIo
->Pci
.Write (
2255 (EFI_PCI_IO_PROTOCOL_WIDTH
) AccessWidth
,
2256 (UINT32
) AccessAddress
,
2262 if (Status
!= EFI_SUCCESS
) {
2266 Data
= RShiftU64 (Data
, ((1 << AccessWidth
) * 8));
2268 Stride
= (UINTN
)1 << AccessWidth
;
2269 AccessAddress
+= Stride
;
2270 if (AccessAddress
>= (Address
+ LShiftU64 (1ULL, (UINTN
)Width
))) {
2272 // if all datas have been written, exist
2279 if ((AccessAddress
& 0xff) < PciRegisterAccessData
->EndOffset
) {
2281 // if current offset doesn't reach the end
2286 FreePool (PciRegisterAccessData
);
2289 // continue checking access incompatibility
2291 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_WRITE
, AccessAddress
& 0xff, AccessWidth
, &PciRegisterAccessData
);
2292 if (Status
== EFI_SUCCESS
) {
2293 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
2294 AccessWidth
= PciRegisterAccessData
->Width
;
2299 FreePool (PciRegisterAccessData
);
2306 // AccessWidth incompatible check not supportted
2307 // or, there doesn't exist incompatibility on this operation
2309 if (PciRootBridgeIo
!= NULL
) {
2310 Status
= PciRootBridgeIo
->Pci
.Write (
2312 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
2318 Status
= PciIo
->Pci
.Write (
2320 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
2331 Abstract PCI device device information.
2333 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2334 @param PciIo A pointer to EFI_PCI_PROTOCOL.
2335 @param Pci A pointer to PCI_TYPE00.
2336 @param Address The address within the PCI configuration space for the PCI controller.
2337 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
2339 @retval EFI_SUCCESS Pci device device information has been abstracted.
2343 GetPciDeviceDeviceInfo (
2344 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
2345 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
2346 IN PCI_TYPE00
*Pci
, OPTIONAL
2347 IN UINT64 Address
, OPTIONAL
2348 OUT EFI_PCI_DEVICE_INFO
*PciDeviceInfo
2353 UINT32 PciConfigData
;
2354 PCI_IO_DEVICE
*PciIoDevice
;
2356 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
2358 if (PciIo
!= NULL
) {
2359 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
2362 // get pointer to PCI_TYPE00 from PciIoDevice
2364 Pci
= &PciIoDevice
->Pci
;
2369 // while PCI_TYPE00 hasn't been gotten, read PCI device device information directly
2371 PciAddress
= Address
& 0xffffffffffffff00ULL
;
2372 Status
= PciRootBridgeIo
->Pci
.Read (
2380 if (EFI_ERROR (Status
)) {
2384 if ((PciConfigData
& 0xffff) == 0xffff) {
2385 return EFI_NOT_FOUND
;
2388 PciDeviceInfo
->VendorID
= PciConfigData
& 0xffff;
2389 PciDeviceInfo
->DeviceID
= PciConfigData
>> 16;
2391 Status
= PciRootBridgeIo
->Pci
.Read (
2398 if (EFI_ERROR (Status
)) {
2402 PciDeviceInfo
->RevisionID
= PciConfigData
& 0xf;
2404 Status
= PciRootBridgeIo
->Pci
.Read (
2412 if (EFI_ERROR (Status
)) {
2416 PciDeviceInfo
->SubsystemVendorID
= PciConfigData
& 0xffff;
2417 PciDeviceInfo
->SubsystemID
= PciConfigData
>> 16;
2420 PciDeviceInfo
->VendorID
= Pci
->Hdr
.VendorId
;
2421 PciDeviceInfo
->DeviceID
= Pci
->Hdr
.DeviceId
;
2422 PciDeviceInfo
->RevisionID
= Pci
->Hdr
.RevisionID
;
2423 PciDeviceInfo
->SubsystemVendorID
= Pci
->Device
.SubsystemVendorID
;
2424 PciDeviceInfo
->SubsystemID
= Pci
->Device
.SubsystemID
;
2431 Read PCI configuration space with incompatibility check.
2433 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2434 @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL.
2435 @param Pci A pointer to PCI_TYPE00.
2436 @param Width Signifies the width of the memory operations.
2437 @param Address The address within the PCI configuration space for the PCI controller.
2438 @param Count The number of unit to be read.
2439 @param Buffer For read operations, the destination buffer to store the results. For
2440 write operations, the source buffer to write data from.
2442 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2443 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2444 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2445 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2449 PciIncompatibilityCheckRead (
2450 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
2451 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
2452 IN PCI_TYPE00
*Pci
, OPTIONAL
2460 EFI_PCI_DEVICE_INFO PciDeviceInfo
;
2463 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
2466 // get PCI device device information
2468 Status
= GetPciDeviceDeviceInfo (PciRootBridgeIo
, PciIo
, Pci
, Address
, &PciDeviceInfo
);
2469 if (Status
!= EFI_SUCCESS
) {
2473 Stride
= 1 << Width
;
2475 for (; Count
> 0; Count
--, Address
+= Stride
, Buffer
= (UINT8
*)Buffer
+ Stride
) {
2478 // read configuration register
2480 Status
= ReadConfigData (PciRootBridgeIo
, PciIo
, &PciDeviceInfo
, (UINT64
) Width
, Address
, Buffer
);
2482 if (Status
!= EFI_SUCCESS
) {
2487 // update the data read from configuration register
2489 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT
) {
2490 UpdateConfigData (&PciDeviceInfo
, PCI_REGISTER_READ
, Width
, Address
& 0xff, Buffer
);
2498 Write PCI configuration space with incompatibility check.
2500 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2501 @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL.
2502 @param Pci A pointer to PCI_TYPE00.
2503 @param Width Signifies the width of the memory operations.
2504 @param Address The address within the PCI configuration space for the PCI controller.
2505 @param Count The number of unit to be write.
2506 @param Buffer For read operations, the destination buffer to store the results. For
2507 write operations, the source buffer to write data from.
2509 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2510 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2511 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2512 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2516 PciIncompatibilityCheckWrite (
2517 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
2518 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
2519 IN PCI_TYPE00
*Pci
, OPTIONAL
2527 EFI_PCI_DEVICE_INFO PciDeviceInfo
;
2531 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
2534 // get PCI device device information
2536 Status
= GetPciDeviceDeviceInfo (PciRootBridgeIo
, PciIo
, Pci
, Address
, &PciDeviceInfo
);
2537 if (Status
!= EFI_SUCCESS
) {
2541 Stride
= 1 << Width
;
2543 for (; Count
> 0; Count
--, Address
+= Stride
, Buffer
= (UINT8
*) Buffer
+ Stride
) {
2548 case EfiPciWidthUint8
:
2549 Data
= * (UINT8
*) Buffer
;
2551 case EfiPciWidthUint16
:
2552 Data
= * (UINT16
*) Buffer
;
2555 case EfiPciWidthUint32
:
2556 Data
= * (UINT32
*) Buffer
;
2560 return EFI_UNSUPPORTED
;
2564 // update the data writen into configuration register
2566 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT
) {
2567 UpdateConfigData (&PciDeviceInfo
, PCI_REGISTER_WRITE
, Width
, Address
& 0xff, &Data
);
2571 // write configuration register
2573 Status
= WriteConfigData (PciRootBridgeIo
, PciIo
, &PciDeviceInfo
, Width
, Address
, &Data
);
2575 if (Status
!= EFI_SUCCESS
) {
2584 Read PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2586 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2587 @param Pci A pointer to PCI_TYPE00.
2588 @param Width Signifies the width of the memory operations.
2589 @param Address The address within the PCI configuration space for the PCI controller.
2590 @param Count The number of unit to be read.
2591 @param Buffer For read operations, the destination buffer to store the results. For
2592 write operations, the source buffer to write data from.
2594 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2595 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2596 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2597 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2601 PciRootBridgeIoRead (
2602 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
2603 IN PCI_TYPE00
*Pci
, OPTIONAL
2604 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
2610 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_READ_SUPPORT
) {
2612 // if PCI incompatibility check enabled
2614 return PciIncompatibilityCheckRead (
2624 return PciRootBridgeIo
->Pci
.Read (
2635 Write PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2637 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2638 @param Pci A pointer to PCI_TYPE00.
2639 @param Width Signifies the width of the memory operations.
2640 @param Address The address within the PCI configuration space for the PCI controller.
2641 @param Count The number of unit to be read.
2642 @param Buffer For read operations, the destination buffer to store the results. For
2643 write operations, the source buffer to write data from.
2645 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2646 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2647 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2648 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2652 PciRootBridgeIoWrite (
2653 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
2655 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
2661 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_WRITE_SUPPORT
) {
2663 // if PCI incompatibility check enabled
2665 return PciIncompatibilityCheckWrite (
2676 return PciRootBridgeIo
->Pci
.Write (
2687 Read PCI configuration space through EFI_PCI_IO_PROTOCOL.
2689 @param PciIo A pointer to the EFI_PCI_O_PROTOCOL.
2690 @param Width Signifies the width of the memory operations.
2691 @param Address The address within the PCI configuration space for the PCI controller.
2692 @param Count The number of unit to be read.
2693 @param Buffer For read operations, the destination buffer to store the results. For
2694 write operations, the source buffer to write data from.
2696 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2697 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2698 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2699 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2704 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2705 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
2711 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_READ_SUPPORT
) {
2713 // if PCI incompatibility check enabled
2715 return PciIncompatibilityCheckRead (
2725 return PciIo
->Pci
.Read (
2736 Write PCI configuration space through EFI_PCI_IO_PROTOCOL.
2738 @param PciIo A pointer to the EFI_PCI_O_PROTOCOL.
2739 @param Width Signifies the width of the memory operations.
2740 @param Address The address within the PCI configuration space for the PCI controller.
2741 @param Count The number of unit to be read.
2742 @param Buffer For read operations, the destination buffer to store the results. For
2743 write operations, the source buffer to write data from.
2745 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2746 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2747 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2748 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2753 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2754 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
2760 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_WRITE_SUPPORT
) {
2763 // if PCI incompatibility check enabled
2765 return PciIncompatibilityCheckWrite (
2776 return PciIo
->Pci
.Write (