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.
22 Retrieve the BAR information via PciIo interface.
24 @param PciIoDevice Pci device instance.
28 IN PCI_IO_DEVICE
*PciIoDevice
33 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
38 // Read PciBar information from the bar register
40 if (!gFullEnumeration
) {
44 &(PciIoDevice
->PciIo
),
51 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BaseAddress
= (UINT64
) (Address
);
52 (PciIoDevice
->PciBar
)[P2C_MEM_1
].Length
= 0x2000000;
53 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BarType
= PciBarTypeMem32
;
57 &(PciIoDevice
->PciIo
),
63 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BaseAddress
= (UINT64
) (Address
);
64 (PciIoDevice
->PciBar
)[P2C_MEM_2
].Length
= 0x2000000;
65 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BarType
= PciBarTypePMem32
;
69 &(PciIoDevice
->PciIo
),
75 (PciIoDevice
->PciBar
)[P2C_IO_1
].BaseAddress
= (UINT64
) (Address
);
76 (PciIoDevice
->PciBar
)[P2C_IO_1
].Length
= 0x100;
77 (PciIoDevice
->PciBar
)[P2C_IO_1
].BarType
= PciBarTypeIo16
;
81 &(PciIoDevice
->PciIo
),
87 (PciIoDevice
->PciBar
)[P2C_IO_2
].BaseAddress
= (UINT64
) (Address
);
88 (PciIoDevice
->PciBar
)[P2C_IO_2
].Length
= 0x100;
89 (PciIoDevice
->PciBar
)[P2C_IO_2
].BarType
= PciBarTypeIo16
;
93 if (gPciHotPlugInit
!= NULL
) {
94 GetResourcePaddingForHpb (PciIoDevice
);
99 Remove rejected pci device from specific root bridge
102 @param RootBridgeHandle specific parent root bridge handle.
103 @param Bridge Bridge device instance.
105 @retval EFI_SUCCESS Success operation.
108 RemoveRejectedPciDevices (
109 EFI_HANDLE RootBridgeHandle
,
110 IN PCI_IO_DEVICE
*Bridge
114 LIST_ENTRY
*CurrentLink
;
115 LIST_ENTRY
*LastLink
;
117 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
121 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
123 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
125 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
127 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
129 // Remove rejected devices recusively
131 RemoveRejectedPciDevices (RootBridgeHandle
, Temp
);
134 // Skip rejection for all PPBs, while detect rejection for others
136 if (IsPciDeviceRejected (Temp
)) {
139 // For P2C, remove all devices on it
141 if (!IsListEmpty (&Temp
->ChildList
)) {
142 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Temp
);
146 // Finally remove itself
148 LastLink
= CurrentLink
->BackLink
;
149 RemoveEntryList (CurrentLink
);
150 FreePciDevice (Temp
);
152 CurrentLink
= LastLink
;
156 CurrentLink
= CurrentLink
->ForwardLink
;
163 Wrapper function for allocating resource for pci host bridge.
165 @param PciResAlloc Point to protocol instance EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
169 PciHostBridgeResourceAllocator (
170 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
173 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
174 return PciHostBridgeResourceAllocator_WithHotPlugDeviceSupport (
178 return PciHostBridgeResourceAllocator_WithoutHotPlugDeviceSupport (
185 Submits the I/O and memory resource requirements for the specified PCI Root Bridge.
187 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
189 @retval EFI_SUCCESS Success.
192 PciHostBridgeResourceAllocator_WithoutHotPlugDeviceSupport (
193 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
196 PCI_IO_DEVICE
*RootBridgeDev
;
197 EFI_HANDLE RootBridgeHandle
;
205 UINT64 MaxOptionRomSize
;
206 PCI_RESOURCE_NODE
*IoBridge
;
207 PCI_RESOURCE_NODE
*Mem32Bridge
;
208 PCI_RESOURCE_NODE
*PMem32Bridge
;
209 PCI_RESOURCE_NODE
*Mem64Bridge
;
210 PCI_RESOURCE_NODE
*PMem64Bridge
;
211 PCI_RESOURCE_NODE IoPool
;
212 PCI_RESOURCE_NODE Mem32Pool
;
213 PCI_RESOURCE_NODE PMem32Pool
;
214 PCI_RESOURCE_NODE Mem64Pool
;
215 PCI_RESOURCE_NODE PMem64Pool
;
216 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD ExtendedData
;
219 // Initialize resource pool
222 InitializeResourcePool (&IoPool
, PciBarTypeIo16
);
223 InitializeResourcePool (&Mem32Pool
, PciBarTypeMem32
);
224 InitializeResourcePool (&PMem32Pool
, PciBarTypePMem32
);
225 InitializeResourcePool (&Mem64Pool
, PciBarTypeMem64
);
226 InitializeResourcePool (&PMem64Pool
, PciBarTypePMem64
);
228 RootBridgeDev
= NULL
;
229 RootBridgeHandle
= 0;
231 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
233 // Get RootBridg Device by handle
235 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
237 if (RootBridgeDev
== NULL
) {
238 return EFI_NOT_FOUND
;
242 // Get host bridge handle for status report
244 ExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
247 // Create the entire system resource map from the information collected by
248 // enumerator. Several resource tree was created
251 IoBridge
= CreateResourceNode (
260 Mem32Bridge
= CreateResourceNode (
269 PMem32Bridge
= CreateResourceNode (
278 Mem64Bridge
= CreateResourceNode (
287 PMem64Bridge
= CreateResourceNode (
297 // Create resourcemap by going through all the devices subject to this root bridge
299 Status
= CreateResourceMap (
309 // Get the max ROM size that the root bridge can process
311 RootBridgeDev
->RomSize
= Mem32Bridge
->Length
;
314 // Get Max Option Rom size for current root bridge
316 MaxOptionRomSize
= GetMaxOptionRomSize (RootBridgeDev
);
319 // Enlarger the mem32 resource to accomdate the option rom
320 // if the mem32 resource is not enough to hold the rom
322 if (MaxOptionRomSize
> Mem32Bridge
->Length
) {
324 Mem32Bridge
->Length
= MaxOptionRomSize
;
325 RootBridgeDev
->RomSize
= MaxOptionRomSize
;
328 // Alignment should be adjusted as well
330 if (Mem32Bridge
->Alignment
< MaxOptionRomSize
- 1) {
331 Mem32Bridge
->Alignment
= MaxOptionRomSize
- 1;
336 // Based on the all the resource tree, contruct ACPI resource node to
337 // submit the resource aperture to pci host bridge protocol
339 Status
= ConstructAcpiResourceRequestor (
350 // Insert these resource nodes into the database
352 InsertResourceNode (&IoPool
, IoBridge
);
353 InsertResourceNode (&Mem32Pool
, Mem32Bridge
);
354 InsertResourceNode (&PMem32Pool
, PMem32Bridge
);
355 InsertResourceNode (&Mem64Pool
, Mem64Bridge
);
356 InsertResourceNode (&PMem64Pool
, PMem64Bridge
);
358 if (Status
== EFI_SUCCESS
) {
360 // Submit the resource requirement
362 Status
= PciResAlloc
->SubmitResources (
364 RootBridgeDev
->Handle
,
369 // Free acpi resource node
371 if (AcpiConfig
!= NULL
) {
372 FreePool (AcpiConfig
);
375 if (EFI_ERROR (Status
)) {
377 // Destroy all the resource tree
379 DestroyResourceTree (&IoPool
);
380 DestroyResourceTree (&Mem32Pool
);
381 DestroyResourceTree (&PMem32Pool
);
382 DestroyResourceTree (&Mem64Pool
);
383 DestroyResourceTree (&PMem64Pool
);
392 // Notify pci bus driver starts to program the resource
394 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeAllocateResources
);
396 if (EFI_ERROR (Status
)) {
398 // Allocation failed, then return
400 return EFI_OUT_OF_RESOURCES
;
403 // Raise the EFI_IOB_PCI_RES_ALLOC status code
405 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
407 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_RES_ALLOC
,
408 (VOID
*) &ExtendedData
,
409 sizeof (ExtendedData
)
413 // Notify pci bus driver starts to program the resource
415 NotifyPhase (PciResAlloc
, EfiPciHostBridgeSetResources
);
417 RootBridgeDev
= NULL
;
419 RootBridgeHandle
= 0;
421 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
423 // Get RootBridg Device by handle
425 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
427 if (RootBridgeDev
== NULL
) {
428 return EFI_NOT_FOUND
;
432 // Get acpi resource node for all the resource types
435 Status
= PciResAlloc
->GetProposedResources (
437 RootBridgeDev
->Handle
,
440 if (EFI_ERROR (Status
)) {
445 // Get the resource base by interpreting acpi resource node
458 // Process option rom for this root bridge
460 Status
= ProcessOptionRom (RootBridgeDev
, Mem32Base
, RootBridgeDev
->RomSize
);
463 // Create the entire system resource map from the information collected by
464 // enumerator. Several resource tree was created
466 Status
= GetResourceMap (
480 if (EFI_ERROR (Status
)) {
485 // Program IO resources
493 // Program Mem32 resources
501 // Program PMem32 resources
509 // Program Mem64 resources
517 // Program PMem64 resources
524 FreePool (AcpiConfig
);
528 // Destroy all the resource tree
530 DestroyResourceTree (&IoPool
);
531 DestroyResourceTree (&Mem32Pool
);
532 DestroyResourceTree (&PMem32Pool
);
533 DestroyResourceTree (&Mem64Pool
);
534 DestroyResourceTree (&PMem64Pool
);
537 // Notify the resource allocation phase is to end
539 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndResourceAllocation
);
545 Submits the I/O and memory resource requirements for the specified PCI Root Bridge.
547 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
549 @retval EFI_SUCCESS Success.
552 PciHostBridgeResourceAllocator_WithHotPlugDeviceSupport (
553 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
556 PCI_IO_DEVICE
*RootBridgeDev
;
557 EFI_HANDLE RootBridgeHandle
;
566 UINT64 Mem32ResStatus
;
567 UINT64 PMem32ResStatus
;
568 UINT64 Mem64ResStatus
;
569 UINT64 PMem64ResStatus
;
570 UINT64 MaxOptionRomSize
;
571 PCI_RESOURCE_NODE
*IoBridge
;
572 PCI_RESOURCE_NODE
*Mem32Bridge
;
573 PCI_RESOURCE_NODE
*PMem32Bridge
;
574 PCI_RESOURCE_NODE
*Mem64Bridge
;
575 PCI_RESOURCE_NODE
*PMem64Bridge
;
576 PCI_RESOURCE_NODE IoPool
;
577 PCI_RESOURCE_NODE Mem32Pool
;
578 PCI_RESOURCE_NODE PMem32Pool
;
579 PCI_RESOURCE_NODE Mem64Pool
;
580 PCI_RESOURCE_NODE PMem64Pool
;
582 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData
;
583 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData
;
591 // It will try several times if the resource allocation fails
596 // Initialize resource pool
598 InitializeResourcePool (&IoPool
, PciBarTypeIo16
);
599 InitializeResourcePool (&Mem32Pool
, PciBarTypeMem32
);
600 InitializeResourcePool (&PMem32Pool
, PciBarTypePMem32
);
601 InitializeResourcePool (&Mem64Pool
, PciBarTypeMem64
);
602 InitializeResourcePool (&PMem64Pool
, PciBarTypePMem64
);
604 RootBridgeDev
= NULL
;
605 RootBridgeHandle
= 0;
607 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
610 // Get RootBridg Device by handle
612 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
614 if (RootBridgeDev
== NULL
) {
615 return EFI_NOT_FOUND
;
619 // Create the entire system resource map from the information collected by
620 // enumerator. Several resource tree was created
623 IoBridge
= CreateResourceNode (
632 Mem32Bridge
= CreateResourceNode (
641 PMem32Bridge
= CreateResourceNode (
650 Mem64Bridge
= CreateResourceNode (
659 PMem64Bridge
= CreateResourceNode (
669 // Create resourcemap by going through all the devices subject to this root bridge
671 Status
= CreateResourceMap (
681 // Get the max ROM size that the root bridge can process
683 RootBridgeDev
->RomSize
= Mem32Bridge
->Length
;
686 // Skip to enlarge the resource request during realloction
690 // Get Max Option Rom size for current root bridge
692 MaxOptionRomSize
= GetMaxOptionRomSize (RootBridgeDev
);
695 // Enlarger the mem32 resource to accomdate the option rom
696 // if the mem32 resource is not enough to hold the rom
698 if (MaxOptionRomSize
> Mem32Bridge
->Length
) {
700 Mem32Bridge
->Length
= MaxOptionRomSize
;
701 RootBridgeDev
->RomSize
= MaxOptionRomSize
;
704 // Alignment should be adjusted as well
706 if (Mem32Bridge
->Alignment
< MaxOptionRomSize
- 1) {
707 Mem32Bridge
->Alignment
= MaxOptionRomSize
- 1;
713 // Based on the all the resource tree, contruct ACPI resource node to
714 // submit the resource aperture to pci host bridge protocol
716 Status
= ConstructAcpiResourceRequestor (
727 // Insert these resource nodes into the database
729 InsertResourceNode (&IoPool
, IoBridge
);
730 InsertResourceNode (&Mem32Pool
, Mem32Bridge
);
731 InsertResourceNode (&PMem32Pool
, PMem32Bridge
);
732 InsertResourceNode (&Mem64Pool
, Mem64Bridge
);
733 InsertResourceNode (&PMem64Pool
, PMem64Bridge
);
735 if (Status
== EFI_SUCCESS
) {
737 // Submit the resource requirement
739 Status
= PciResAlloc
->SubmitResources (
741 RootBridgeDev
->Handle
,
747 // Free acpi resource node
749 if (AcpiConfig
!= NULL
) {
750 FreePool (AcpiConfig
);
753 if (EFI_ERROR (Status
)) {
755 // Destroy all the resource tree
757 DestroyResourceTree (&IoPool
);
758 DestroyResourceTree (&Mem32Pool
);
759 DestroyResourceTree (&PMem32Pool
);
760 DestroyResourceTree (&Mem64Pool
);
761 DestroyResourceTree (&PMem64Pool
);
767 // Notify pci bus driver starts to program the resource
770 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeAllocateResources
);
772 if (!EFI_ERROR (Status
)) {
774 // Allocation succeed, then continue the following
780 // If the resource allocation is unsuccessful, free resources on bridge
783 RootBridgeDev
= NULL
;
784 RootBridgeHandle
= 0;
786 IoResStatus
= EFI_RESOURCE_SATISFIED
;
787 Mem32ResStatus
= EFI_RESOURCE_SATISFIED
;
788 PMem32ResStatus
= EFI_RESOURCE_SATISFIED
;
789 Mem64ResStatus
= EFI_RESOURCE_SATISFIED
;
790 PMem64ResStatus
= EFI_RESOURCE_SATISFIED
;
792 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
794 // Get RootBridg Device by handle
796 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
797 if (RootBridgeDev
== NULL
) {
798 return EFI_NOT_FOUND
;
802 // Get host bridge handle for status report
804 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
807 // Get acpi resource node for all the resource types
811 Status
= PciResAlloc
->GetProposedResources (
813 RootBridgeDev
->Handle
,
817 if (EFI_ERROR (Status
)) {
821 if (AcpiConfig
!= NULL
) {
823 // Adjust resource allocation policy for each RB
825 GetResourceAllocationStatus (
833 FreePool (AcpiConfig
);
841 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
844 // It is very difficult to follow the spec here
845 // Device path , Bar index can not be get here
847 ZeroMem (&AllocFailExtendedData
, sizeof (AllocFailExtendedData
));
849 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
851 EFI_IO_BUS_PCI
| EFI_IOB_EC_RESOURCE_CONFLICT
,
852 (VOID
*) &AllocFailExtendedData
,
853 sizeof (AllocFailExtendedData
)
856 Status
= PciHostBridgeAdjustAllocation (
870 // Destroy all the resource tree
872 DestroyResourceTree (&IoPool
);
873 DestroyResourceTree (&Mem32Pool
);
874 DestroyResourceTree (&PMem32Pool
);
875 DestroyResourceTree (&Mem64Pool
);
876 DestroyResourceTree (&PMem64Pool
);
878 NotifyPhase (PciResAlloc
, EfiPciHostBridgeFreeResources
);
880 if (EFI_ERROR (Status
)) {
892 // Raise the EFI_IOB_PCI_RES_ALLOC status code
894 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
896 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_RES_ALLOC
,
897 (VOID
*) &HandleExtendedData
,
898 sizeof (HandleExtendedData
)
902 // Notify pci bus driver starts to program the resource
904 NotifyPhase (PciResAlloc
, EfiPciHostBridgeSetResources
);
906 RootBridgeDev
= NULL
;
908 RootBridgeHandle
= 0;
910 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
913 // Get RootBridg Device by handle
915 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
917 if (RootBridgeDev
== NULL
) {
918 return EFI_NOT_FOUND
;
922 // Get acpi resource node for all the resource types
925 Status
= PciResAlloc
->GetProposedResources (
927 RootBridgeDev
->Handle
,
931 if (EFI_ERROR (Status
)) {
936 // Get the resource base by interpreting acpi resource node
949 // Process option rom for this root bridge
951 Status
= ProcessOptionRom (RootBridgeDev
, Mem32Base
, RootBridgeDev
->RomSize
);
954 // Create the entire system resource map from the information collected by
955 // enumerator. Several resource tree was created
957 Status
= GetResourceMap (
971 if (EFI_ERROR (Status
)) {
976 // Program IO resources
984 // Program Mem32 resources
992 // Program PMem32 resources
1000 // Program Mem64 resources
1008 // Program PMem64 resources
1015 FreePool (AcpiConfig
);
1019 // Destroy all the resource tree
1021 DestroyResourceTree (&IoPool
);
1022 DestroyResourceTree (&Mem32Pool
);
1023 DestroyResourceTree (&PMem32Pool
);
1024 DestroyResourceTree (&Mem64Pool
);
1025 DestroyResourceTree (&PMem64Pool
);
1028 // Notify the resource allocation phase is to end
1030 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndResourceAllocation
);
1036 Wapper function of scanning pci bus and assign bus number to the given PCI bus system
1037 Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
1039 @param Bridge Bridge device instance.
1040 @param StartBusNumber start point.
1041 @param SubBusNumber Point to sub bus number.
1042 @param PaddedBusRange Customized bus number.
1044 @retval EFI_SUCCESS Success.
1045 @retval EFI_DEVICE_ERROR Fail to scan bus.
1049 IN PCI_IO_DEVICE
*Bridge
,
1050 IN UINT8 StartBusNumber
,
1051 OUT UINT8
*SubBusNumber
,
1052 OUT UINT8
*PaddedBusRange
1055 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1056 return PciScanBus_WithHotPlugDeviceSupport (
1063 return PciScanBus_WithoutHotPlugDeviceSupport (
1073 Wapper function of scanning pci bus and assign bus number to the given PCI bus system
1074 Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
1076 @param Bridge Bridge device instance.
1077 @param StartBusNumber start point.
1078 @param SubBusNumber Point to sub bus number.
1079 @param PaddedBusRange Customized bus number.
1081 @retval EFI_SUCCESS Success.
1082 @retval EFI_DEVICE_ERROR Fail to scan bus.
1085 PciScanBus_WithoutHotPlugDeviceSupport (
1086 IN PCI_IO_DEVICE
*Bridge
,
1087 IN UINT8 StartBusNumber
,
1088 OUT UINT8
*SubBusNumber
,
1089 OUT UINT8
*PaddedBusRange
1099 PCI_IO_DEVICE
*PciDevice
;
1100 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1102 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
1106 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
1107 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
1110 // Check to see whether a pci device is present
1112 Status
= PciDevicePresent (
1120 if (!EFI_ERROR (Status
)) {
1121 DEBUG((EFI_D_ERROR
, "Found DEV(%02d,%02d,%02d)\n", StartBusNumber
, Device
, Func
));
1123 if (IS_PCI_BRIDGE (&Pci
) ||
1124 IS_CARDBUS_BRIDGE (&Pci
)) {
1127 // Get the bridge information
1129 Status
= PciSearchDevice (
1138 if (EFI_ERROR (Status
)) {
1143 // Add feature to support customized secondary bus number
1145 if (*SubBusNumber
== 0) {
1146 *SubBusNumber
= *PaddedBusRange
;
1147 *PaddedBusRange
= 0;
1152 SecondBus
= (*SubBusNumber
);
1154 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
1156 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
1158 Status
= PciRootBridgeIoWrite (
1168 // Initialize SubBusNumber to SecondBus
1170 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1171 Status
= PciRootBridgeIoWrite (
1180 // If it is PPB, resursively search down this bridge
1182 if (IS_PCI_BRIDGE (&Pci
)) {
1184 // Temporarily initialize SubBusNumber to maximum bus number to ensure the
1185 // PCI configuration transaction to go through any PPB
1187 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1189 Status
= PciRootBridgeIoWrite (
1198 PreprocessController (
1200 PciDevice
->BusNumber
,
1201 PciDevice
->DeviceNumber
,
1202 PciDevice
->FunctionNumber
,
1203 EfiPciBeforeChildBusEnumeration
1206 DEBUG((EFI_D_ERROR
, "Scan PPB(%02d,%02d,%02d)\n", PciDevice
->BusNumber
, PciDevice
->DeviceNumber
,PciDevice
->FunctionNumber
));
1207 Status
= PciScanBus (
1209 (UINT8
) (SecondBus
),
1214 if (EFI_ERROR (Status
)) {
1215 return EFI_DEVICE_ERROR
;
1220 // Set the current maximum bus number under the PPB
1223 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1225 Status
= PciRootBridgeIoWrite (
1236 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
1239 // Skip sub functions, this is not a multi function device
1242 Func
= PCI_MAX_FUNC
;
1251 Wapper function of scanning pci bus and assign bus number to the given PCI bus system
1252 Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
1254 @param Bridge Bridge device instance.
1255 @param StartBusNumber start point.
1256 @param SubBusNumber Point to sub bus number.
1257 @param PaddedBusRange Customized bus number.
1259 @retval EFI_SUCCESS Success.
1260 @retval EFI_DEVICE_ERROR Fail to scan bus.
1263 PciScanBus_WithHotPlugDeviceSupport (
1264 IN PCI_IO_DEVICE
*Bridge
,
1265 IN UINT8 StartBusNumber
,
1266 OUT UINT8
*SubBusNumber
,
1267 OUT UINT8
*PaddedBusRange
1278 PCI_IO_DEVICE
*PciDevice
;
1280 EFI_HPC_STATE State
;
1282 EFI_HPC_PADDING_ATTRIBUTES Attributes
;
1283 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1285 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1288 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
1292 Attributes
= (EFI_HPC_PADDING_ATTRIBUTES
) 0;
1295 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
1296 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
1299 // Check to see whether a pci device is present
1301 Status
= PciDevicePresent (
1309 if (EFI_ERROR (Status
)) {
1312 // Skip sub functions, this is not a multi function device
1314 Func
= PCI_MAX_FUNC
;
1320 DEBUG((EFI_D_ERROR
, "Found DEV(%02d,%02d,%02d)\n", StartBusNumber
, Device
, Func
));
1323 // Get the PCI device information
1325 Status
= PciSearchDevice (
1334 ASSERT (!EFI_ERROR (Status
));
1336 PciAddress
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0);
1338 if (!IS_PCI_BRIDGE (&Pci
)) {
1340 // PCI bridges will be called later
1341 // Here just need for PCI device or PCI to cardbus controller
1342 // EfiPciBeforeChildBusEnumeration for PCI Device Node
1344 PreprocessController (
1346 PciDevice
->BusNumber
,
1347 PciDevice
->DeviceNumber
,
1348 PciDevice
->FunctionNumber
,
1349 EfiPciBeforeChildBusEnumeration
1354 // For Pci Hotplug controller devcie only
1356 if (gPciHotPlugInit
!= NULL
) {
1358 // Check if it is a Hotplug PCI controller
1360 if (IsRootPciHotPlugController (PciDevice
->DevicePath
, &HpIndex
)) {
1362 if (!gPciRootHpcData
[HpIndex
].Initialized
) {
1364 Status
= CreateEventForHpc (HpIndex
, &Event
);
1366 ASSERT (!EFI_ERROR (Status
));
1368 Status
= gPciHotPlugInit
->InitializeRootHpc (
1370 gPciRootHpcPool
[HpIndex
].HpcDevicePath
,
1376 PreprocessController (
1378 PciDevice
->BusNumber
,
1379 PciDevice
->DeviceNumber
,
1380 PciDevice
->FunctionNumber
,
1381 EfiPciBeforeChildBusEnumeration
1387 if (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
)) {
1390 // Get the bridge information
1393 if (gPciHotPlugInit
!= NULL
) {
1395 if (IsRootPciHotPlugBus (PciDevice
->DevicePath
, &HpIndex
)) {
1398 // If it is initialized, get the padded bus range
1400 Status
= gPciHotPlugInit
->GetResourcePadding (
1402 gPciRootHpcPool
[HpIndex
].HpbDevicePath
,
1405 (VOID
**) &Descriptors
,
1409 if (EFI_ERROR (Status
)) {
1414 Status
= PciGetBusRange (
1421 FreePool (Descriptors
);
1423 if (EFI_ERROR (Status
)) {
1432 // Add feature to support customized secondary bus number
1434 if (*SubBusNumber
== 0) {
1435 *SubBusNumber
= *PaddedBusRange
;
1436 *PaddedBusRange
= 0;
1440 SecondBus
= *SubBusNumber
;
1442 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
1443 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
1445 Status
= PciRootBridgeIoWrite (
1456 // If it is PPB, resursively search down this bridge
1458 if (IS_PCI_BRIDGE (&Pci
)) {
1461 // Initialize SubBusNumber to Maximum bus number
1464 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1465 Status
= PciRootBridgeIoWrite (
1475 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
1477 PreprocessController (
1479 PciDevice
->BusNumber
,
1480 PciDevice
->DeviceNumber
,
1481 PciDevice
->FunctionNumber
,
1482 EfiPciBeforeChildBusEnumeration
1485 DEBUG((EFI_D_ERROR
, "Scan PPB(%02d,%02d,%02d)\n", PciDevice
->BusNumber
, PciDevice
->DeviceNumber
,PciDevice
->FunctionNumber
));
1486 Status
= PciScanBus (
1488 (UINT8
) (SecondBus
),
1493 if (EFI_ERROR (Status
)) {
1494 return EFI_DEVICE_ERROR
;
1500 // Ensure the device is enabled and initialized
1502 if ((Attributes
== EfiPaddingPciRootBridge
) &&
1503 (State
& EFI_HPC_STATE_ENABLED
) != 0 &&
1504 (State
& EFI_HPC_STATE_INITIALIZED
) != 0) {
1505 *PaddedBusRange
= (UINT8
) ((UINT8
) (BusRange
) +*PaddedBusRange
);
1507 *SubBusNumber
= (UINT8
) ((UINT8
) (BusRange
) +*SubBusNumber
);
1512 // Set the current maximum bus number under the PPB
1514 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1516 Status
= PciRootBridgeIoWrite (
1526 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
1529 // Skip sub functions, this is not a multi function device
1531 Func
= PCI_MAX_FUNC
;
1541 Process Option Rom on this host bridge.
1543 @param Bridge Pci bridge device instance.
1545 @retval EFI_SUCCESS Success.
1548 PciRootBridgeP2CProcess (
1549 IN PCI_IO_DEVICE
*Bridge
1552 LIST_ENTRY
*CurrentLink
;
1553 PCI_IO_DEVICE
*Temp
;
1554 EFI_HPC_STATE State
;
1558 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1560 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
1562 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1564 if (IS_CARDBUS_BRIDGE (&Temp
->Pci
)) {
1566 if (gPciHotPlugInit
!= NULL
&& Temp
->Allocated
) {
1569 // Raise the EFI_IOB_PCI_HPC_INIT status code
1571 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1573 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_HPC_INIT
,
1577 PciAddress
= EFI_PCI_ADDRESS (Temp
->BusNumber
, Temp
->DeviceNumber
, Temp
->FunctionNumber
, 0);
1578 Status
= gPciHotPlugInit
->InitializeRootHpc (
1586 if (!EFI_ERROR (Status
)) {
1587 Status
= PciBridgeEnumerator (Temp
);
1589 if (EFI_ERROR (Status
)) {
1594 CurrentLink
= CurrentLink
->ForwardLink
;
1600 if (!IsListEmpty (&Temp
->ChildList
)) {
1601 Status
= PciRootBridgeP2CProcess (Temp
);
1604 CurrentLink
= CurrentLink
->ForwardLink
;
1611 Process Option Rom on this host bridge.
1613 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
1615 @retval EFI_NOT_FOUND Can not find the root bridge instance.
1616 @retval EFI_SUCCESS Success process.
1619 PciHostBridgeP2CProcess (
1620 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1623 EFI_HANDLE RootBridgeHandle
;
1624 PCI_IO_DEVICE
*RootBridgeDev
;
1627 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1631 RootBridgeHandle
= NULL
;
1633 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1636 // Get RootBridg Device by handle
1638 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
1640 if (RootBridgeDev
== NULL
) {
1641 return EFI_NOT_FOUND
;
1644 Status
= PciRootBridgeP2CProcess (RootBridgeDev
);
1646 if (EFI_ERROR (Status
)) {
1656 This function is used to enumerate the entire host bridge
1657 in a given platform.
1659 @param PciResAlloc A pointer to the resource allocate protocol.
1661 @retval EFI_OUT_OF_RESOURCES no enough resource.
1662 @retval EFI_SUCCESS Success.
1666 PciHostBridgeEnumerator (
1667 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1670 EFI_HANDLE RootBridgeHandle
;
1671 PCI_IO_DEVICE
*RootBridgeDev
;
1673 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1675 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1676 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration
;
1677 UINT8 StartBusNumber
;
1678 LIST_ENTRY RootBridgeList
;
1681 InitializeHotPlugSupport ();
1683 InitializeListHead (&RootBridgeList
);
1686 // Notify the bus allocation phase is about to start
1688 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1690 DEBUG((EFI_D_ERROR
, "PCI Bus First Scanning\n"));
1691 RootBridgeHandle
= NULL
;
1692 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1695 // if a root bridge instance is found, create root bridge device for it
1698 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1700 if (RootBridgeDev
== NULL
) {
1701 return EFI_OUT_OF_RESOURCES
;
1705 // Enumerate all the buses under this root bridge
1708 Status
= PciRootBridgeEnumerator (
1713 if (gPciHotPlugInit
!= NULL
) {
1714 InsertTailList (&RootBridgeList
, &(RootBridgeDev
->Link
));
1716 DestroyRootBridge (RootBridgeDev
);
1718 if (EFI_ERROR (Status
)) {
1724 // Notify the bus allocation phase is finished for the first time
1726 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1728 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1730 if (gPciHotPlugInit
!= NULL
) {
1732 // Reset all assigned PCI bus number in all PPB
1734 RootBridgeHandle
= NULL
;
1735 Link
= GetFirstNode (&RootBridgeList
);
1736 while ((PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) &&
1737 (!IsNull (&RootBridgeList
, Link
))) {
1738 RootBridgeDev
= PCI_IO_DEVICE_FROM_LINK (Link
);
1740 // Get the Bus information
1742 Status
= PciResAlloc
->StartBusEnumeration (
1745 (VOID
**) &Configuration
1747 if (EFI_ERROR (Status
)) {
1752 // Get the bus number to start with
1754 StartBusNumber
= (UINT8
) (Configuration
->AddrRangeMin
);
1756 ResetAllPpbBusNumber (
1761 FreePool (Configuration
);
1762 Link
= GetNextNode (&RootBridgeList
, Link
);
1763 DestroyRootBridge (RootBridgeDev
);
1767 // Wait for all HPC initialized
1769 Status
= AllRootHPCInitialized (STALL_1_SECOND
* 15);
1771 if (EFI_ERROR (Status
)) {
1776 // Notify the bus allocation phase is about to start for the 2nd time
1778 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1780 DEBUG((EFI_D_ERROR
, "PCI Bus Second Scanning\n"));
1781 RootBridgeHandle
= NULL
;
1782 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1785 // if a root bridge instance is found, create root bridge device for it
1788 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1790 if (RootBridgeDev
== NULL
) {
1791 return EFI_OUT_OF_RESOURCES
;
1795 // Enumerate all the buses under this root bridge
1798 Status
= PciRootBridgeEnumerator (
1803 DestroyRootBridge (RootBridgeDev
);
1804 if (EFI_ERROR (Status
)) {
1810 // Notify the bus allocation phase is to end for the 2nd time
1812 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1817 // Notify the resource allocation phase is to start
1819 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginResourceAllocation
);
1821 RootBridgeHandle
= NULL
;
1822 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1825 // if a root bridge instance is found, create root bridge device for it
1828 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1830 if (RootBridgeDev
== NULL
) {
1831 return EFI_OUT_OF_RESOURCES
;
1834 Status
= StartManagingRootBridge (RootBridgeDev
);
1836 if (EFI_ERROR (Status
)) {
1840 PciRootBridgeIo
= RootBridgeDev
->PciRootBridgeIo
;
1841 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
1843 if (EFI_ERROR (Status
)) {
1847 Status
= PciGetBusRange (&Descriptors
, &MinBus
, NULL
, NULL
);
1849 if (EFI_ERROR (Status
)) {
1854 // Determine root bridge attribute by calling interface of Pcihostbridge
1857 DetermineRootBridgeAttributes (
1863 // Collect all the resource information under this root bridge
1864 // A database that records all the information about pci device subject to this
1865 // root bridge will then be created
1867 Status
= PciPciDeviceInfoCollector (
1872 if (EFI_ERROR (Status
)) {
1876 InsertRootBridge (RootBridgeDev
);
1879 // Record the hostbridge handle
1881 AddHostBridgeEnumerator (RootBridgeDev
->PciRootBridgeIo
->ParentHandle
);
1888 Read PCI device configuration register by specified address.
1890 This function check the incompatiblilites on PCI device. Return the register
1893 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1894 @param PciIo A pointer to EFI_PCI_PROTOCOL.
1895 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
1896 @param Width Signifies the width of the memory operations.
1897 @param Address The address within the PCI configuration space for the PCI controller.
1898 @param Buffer For read operations, the destination buffer to store the results. For
1899 write operations, the source buffer to write data from.
1901 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
1902 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
1903 @retval EFI_INVALID_PARAMETER Buffer is NULL.
1904 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1909 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
1910 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
1911 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
1919 EFI_PCI_REGISTER_ACCESS_DATA
*PciRegisterAccessData
;
1920 UINT64 AccessAddress
;
1925 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
1927 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT
) {
1929 // check access compatibility at first time
1931 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_READ
, Address
& 0xff, Width
, &PciRegisterAccessData
);
1933 if (Status
== EFI_SUCCESS
) {
1935 // there exist incompatibility on this operation
1937 AccessWidth
= Width
;
1939 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
1940 AccessWidth
= PciRegisterAccessData
->Width
;
1943 AccessAddress
= Address
& ~((1 << AccessWidth
) - 1);
1947 Pointer
= (UINT8
*) &TempBuffer
;
1951 if (PciRootBridgeIo
!= NULL
) {
1952 Status
= PciRootBridgeIo
->Pci
.Read (
1954 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) AccessWidth
,
1959 } else if (PciIo
!= NULL
) {
1960 Status
= PciIo
->Pci
.Read (
1962 (EFI_PCI_IO_PROTOCOL_WIDTH
) AccessWidth
,
1963 (UINT32
) AccessAddress
,
1969 if (Status
!= EFI_SUCCESS
) {
1973 Stride
= (UINTN
)1 << AccessWidth
;
1974 AccessAddress
+= Stride
;
1975 if (AccessAddress
>= (Address
+ LShiftU64 (1ULL, (UINTN
)Width
))) {
1977 // if all datas have been read, exist
1984 if ((AccessAddress
& 0xff) < PciRegisterAccessData
->EndOffset
) {
1986 // if current offset doesn't reach the end
1991 FreePool (PciRegisterAccessData
);
1994 // continue checking access incompatibility
1996 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_READ
, AccessAddress
& 0xff, AccessWidth
, &PciRegisterAccessData
);
1997 if (Status
== EFI_SUCCESS
) {
1998 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
1999 AccessWidth
= PciRegisterAccessData
->Width
;
2004 FreePool (PciRegisterAccessData
);
2007 case EfiPciWidthUint8
:
2008 * (UINT8
*) Buffer
= (UINT8
) TempBuffer
;
2010 case EfiPciWidthUint16
:
2011 * (UINT16
*) Buffer
= (UINT16
) TempBuffer
;
2013 case EfiPciWidthUint32
:
2014 * (UINT32
*) Buffer
= (UINT32
) TempBuffer
;
2017 return EFI_UNSUPPORTED
;
2024 // AccessWidth incompatible check not supportted
2025 // or, there doesn't exist incompatibility on this operation
2027 if (PciRootBridgeIo
!= NULL
) {
2028 Status
= PciRootBridgeIo
->Pci
.Read (
2030 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
2037 Status
= PciIo
->Pci
.Read (
2039 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
2050 Update register value by checking PCI device incompatibility.
2052 This function check register value incompatibilites on PCI device. Return the register
2055 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
2056 @param AccessType Access type, READ or WRITE.
2057 @param Width Signifies the width of the memory operations.
2058 @param Address The address within the PCI configuration space.
2059 @param Buffer Store the register data.
2061 @retval EFI_SUCCESS The data has been updated.
2066 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
2067 IN UINT64 AccessType
,
2074 EFI_PCI_REGISTER_VALUE_DATA
*PciRegisterData
;
2080 // check register value incompatibility
2082 Status
= PciRegisterUpdateCheck (PciDeviceInfo
, AccessType
, Address
& 0xff, &PciRegisterData
);
2084 if (Status
== EFI_SUCCESS
) {
2086 AndValue
= ((UINT32
) PciRegisterData
->AndValue
) >> (((UINT8
) Address
& 0x3) * 8);
2087 OrValue
= ((UINT32
) PciRegisterData
->OrValue
) >> (((UINT8
) Address
& 0x3) * 8);
2089 TempValue
= * (UINT32
*) Buffer
;
2090 if (PciRegisterData
->AndValue
!= VALUE_NOCARE
) {
2091 TempValue
&= AndValue
;
2093 if (PciRegisterData
->OrValue
!= VALUE_NOCARE
) {
2094 TempValue
|= OrValue
;
2098 case EfiPciWidthUint8
:
2099 *(UINT8
*)Buffer
= (UINT8
) TempValue
;
2102 case EfiPciWidthUint16
:
2103 *(UINT16
*)Buffer
= (UINT16
) TempValue
;
2105 case EfiPciWidthUint32
:
2106 *(UINT32
*)Buffer
= TempValue
;
2110 return EFI_UNSUPPORTED
;
2113 FreePool (PciRegisterData
);
2120 Write PCI device configuration register by specified address.
2122 This function check the incompatiblilites on PCI device, and write date
2125 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2126 @param PciIo A pointer to EFI_PCI_PROTOCOL.
2127 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
2128 @param Width Signifies the width of the memory operations.
2129 @param Address The address within the PCI configuration space for the PCI controller.
2130 @param Buffer For read operations, the destination buffer to store the results. For
2131 write operations, the source buffer to write data from.
2133 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2134 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2135 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2136 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2141 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
2142 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
2143 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
2151 EFI_PCI_REGISTER_ACCESS_DATA
*PciRegisterAccessData
;
2152 UINT64 AccessAddress
;
2158 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
2160 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT
) {
2162 // check access compatibility at first time
2164 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_WRITE
, Address
& 0xff, Width
, &PciRegisterAccessData
);
2166 if (Status
== EFI_SUCCESS
) {
2168 // there exist incompatibility on this operation
2170 AccessWidth
= Width
;
2172 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
2173 AccessWidth
= PciRegisterAccessData
->Width
;
2176 AccessAddress
= Address
& ~((1 << AccessWidth
) - 1);
2179 Pointer
= (UINT8
*) &Buffer
;
2180 Data
= * (UINT64
*) Buffer
;
2184 if (AccessWidth
> Width
) {
2186 // if actual access width is larger than orignal one, additional data need to be read back firstly
2188 Status
= ReadConfigData (PciRootBridgeIo
, PciIo
, PciDeviceInfo
, AccessWidth
, AccessAddress
, &Data
);
2189 if (Status
!= EFI_SUCCESS
) {
2194 // check data read incompatibility
2196 UpdateConfigData (PciDeviceInfo
, PCI_REGISTER_READ
, AccessWidth
, AccessAddress
& 0xff, &Data
);
2198 Shift
= (UINTN
)(Address
- AccessAddress
) * 8;
2200 case EfiPciWidthUint8
:
2201 Data
= (* (UINT8
*) Buffer
) << Shift
| (Data
& ~(0xff << Shift
));
2204 case EfiPciWidthUint16
:
2205 Data
= (* (UINT16
*) Buffer
) << Shift
| (Data
& ~(0xffff << Shift
));
2210 // check data write incompatibility
2212 UpdateConfigData (PciDeviceInfo
, PCI_REGISTER_WRITE
, AccessWidth
, MultU64x32 (AccessAddress
, 0xff), &Data
);
2215 if (PciRootBridgeIo
!= NULL
) {
2216 Status
= PciRootBridgeIo
->Pci
.Write (
2218 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) AccessWidth
,
2224 Status
= PciIo
->Pci
.Write (
2226 (EFI_PCI_IO_PROTOCOL_WIDTH
) AccessWidth
,
2227 (UINT32
) AccessAddress
,
2233 if (Status
!= EFI_SUCCESS
) {
2237 Data
= RShiftU64 (Data
, ((1 << AccessWidth
) * 8));
2239 Stride
= (UINTN
)1 << AccessWidth
;
2240 AccessAddress
+= Stride
;
2241 if (AccessAddress
>= (Address
+ LShiftU64 (1ULL, (UINTN
)Width
))) {
2243 // if all datas have been written, exist
2250 if ((AccessAddress
& 0xff) < PciRegisterAccessData
->EndOffset
) {
2252 // if current offset doesn't reach the end
2257 FreePool (PciRegisterAccessData
);
2260 // continue checking access incompatibility
2262 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_WRITE
, AccessAddress
& 0xff, AccessWidth
, &PciRegisterAccessData
);
2263 if (Status
== EFI_SUCCESS
) {
2264 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
2265 AccessWidth
= PciRegisterAccessData
->Width
;
2270 FreePool (PciRegisterAccessData
);
2277 // AccessWidth incompatible check not supportted
2278 // or, there doesn't exist incompatibility on this operation
2280 if (PciRootBridgeIo
!= NULL
) {
2281 Status
= PciRootBridgeIo
->Pci
.Write (
2283 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
2289 Status
= PciIo
->Pci
.Write (
2291 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
2302 Abstract PCI device device information.
2304 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2305 @param PciIo A pointer to EFI_PCI_PROTOCOL.
2306 @param Pci A pointer to PCI_TYPE00.
2307 @param Address The address within the PCI configuration space for the PCI controller.
2308 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
2310 @retval EFI_SUCCESS Pci device device information has been abstracted.
2314 GetPciDeviceDeviceInfo (
2315 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
2316 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
2317 IN PCI_TYPE00
*Pci
, OPTIONAL
2318 IN UINT64 Address
, OPTIONAL
2319 OUT EFI_PCI_DEVICE_INFO
*PciDeviceInfo
2324 UINT32 PciConfigData
;
2325 PCI_IO_DEVICE
*PciIoDevice
;
2327 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
2329 if (PciIo
!= NULL
) {
2330 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
2333 // get pointer to PCI_TYPE00 from PciIoDevice
2335 Pci
= &PciIoDevice
->Pci
;
2340 // while PCI_TYPE00 hasn't been gotten, read PCI device device information directly
2342 PciAddress
= Address
& 0xffffffffffffff00ULL
;
2343 Status
= PciRootBridgeIo
->Pci
.Read (
2351 if (EFI_ERROR (Status
)) {
2355 if ((PciConfigData
& 0xffff) == 0xffff) {
2356 return EFI_NOT_FOUND
;
2359 PciDeviceInfo
->VendorID
= PciConfigData
& 0xffff;
2360 PciDeviceInfo
->DeviceID
= PciConfigData
>> 16;
2362 Status
= PciRootBridgeIo
->Pci
.Read (
2369 if (EFI_ERROR (Status
)) {
2373 PciDeviceInfo
->RevisionID
= PciConfigData
& 0xf;
2375 Status
= PciRootBridgeIo
->Pci
.Read (
2383 if (EFI_ERROR (Status
)) {
2387 PciDeviceInfo
->SubsystemVendorID
= PciConfigData
& 0xffff;
2388 PciDeviceInfo
->SubsystemID
= PciConfigData
>> 16;
2391 PciDeviceInfo
->VendorID
= Pci
->Hdr
.VendorId
;
2392 PciDeviceInfo
->DeviceID
= Pci
->Hdr
.DeviceId
;
2393 PciDeviceInfo
->RevisionID
= Pci
->Hdr
.RevisionID
;
2394 PciDeviceInfo
->SubsystemVendorID
= Pci
->Device
.SubsystemVendorID
;
2395 PciDeviceInfo
->SubsystemID
= Pci
->Device
.SubsystemID
;
2402 Read PCI configuration space with incompatibility check.
2404 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2405 @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL.
2406 @param Pci A pointer to PCI_TYPE00.
2407 @param Width Signifies the width of the memory operations.
2408 @param Address The address within the PCI configuration space for the PCI controller.
2409 @param Count The number of unit to be read.
2410 @param Buffer For read operations, the destination buffer to store the results. For
2411 write operations, the source buffer to write data from.
2413 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2414 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2415 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2416 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2420 PciIncompatibilityCheckRead (
2421 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
2422 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
2423 IN PCI_TYPE00
*Pci
, OPTIONAL
2431 EFI_PCI_DEVICE_INFO PciDeviceInfo
;
2434 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
2437 // get PCI device device information
2439 Status
= GetPciDeviceDeviceInfo (PciRootBridgeIo
, PciIo
, Pci
, Address
, &PciDeviceInfo
);
2440 if (Status
!= EFI_SUCCESS
) {
2444 Stride
= 1 << Width
;
2446 for (; Count
> 0; Count
--, Address
+= Stride
, Buffer
= (UINT8
*)Buffer
+ Stride
) {
2449 // read configuration register
2451 Status
= ReadConfigData (PciRootBridgeIo
, PciIo
, &PciDeviceInfo
, (UINT64
) Width
, Address
, Buffer
);
2453 if (Status
!= EFI_SUCCESS
) {
2458 // update the data read from configuration register
2460 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT
) {
2461 UpdateConfigData (&PciDeviceInfo
, PCI_REGISTER_READ
, Width
, Address
& 0xff, Buffer
);
2469 Write PCI configuration space with incompatibility check.
2471 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2472 @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL.
2473 @param Pci A pointer to PCI_TYPE00.
2474 @param Width Signifies the width of the memory operations.
2475 @param Address The address within the PCI configuration space for the PCI controller.
2476 @param Count The number of unit to be write.
2477 @param Buffer For read operations, the destination buffer to store the results. For
2478 write operations, the source buffer to write data from.
2480 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2481 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2482 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2483 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2487 PciIncompatibilityCheckWrite (
2488 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
2489 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
2490 IN PCI_TYPE00
*Pci
, OPTIONAL
2498 EFI_PCI_DEVICE_INFO PciDeviceInfo
;
2502 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
2505 // get PCI device device information
2507 Status
= GetPciDeviceDeviceInfo (PciRootBridgeIo
, PciIo
, Pci
, Address
, &PciDeviceInfo
);
2508 if (Status
!= EFI_SUCCESS
) {
2512 Stride
= 1 << Width
;
2514 for (; Count
> 0; Count
--, Address
+= Stride
, Buffer
= (UINT8
*) Buffer
+ Stride
) {
2519 case EfiPciWidthUint8
:
2520 Data
= * (UINT8
*) Buffer
;
2522 case EfiPciWidthUint16
:
2523 Data
= * (UINT16
*) Buffer
;
2526 case EfiPciWidthUint32
:
2527 Data
= * (UINT32
*) Buffer
;
2531 return EFI_UNSUPPORTED
;
2535 // update the data writen into configuration register
2537 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT
) {
2538 UpdateConfigData (&PciDeviceInfo
, PCI_REGISTER_WRITE
, Width
, Address
& 0xff, &Data
);
2542 // write configuration register
2544 Status
= WriteConfigData (PciRootBridgeIo
, PciIo
, &PciDeviceInfo
, Width
, Address
, &Data
);
2546 if (Status
!= EFI_SUCCESS
) {
2555 Read PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2557 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2558 @param Pci A pointer to PCI_TYPE00.
2559 @param Width Signifies the width of the memory operations.
2560 @param Address The address within the PCI configuration space for the PCI controller.
2561 @param Count The number of unit to be read.
2562 @param Buffer For read operations, the destination buffer to store the results. For
2563 write operations, the source buffer to write data from.
2565 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2566 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2567 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2568 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2572 PciRootBridgeIoRead (
2573 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
2574 IN PCI_TYPE00
*Pci
, OPTIONAL
2575 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
2581 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_READ_SUPPORT
) {
2583 // if PCI incompatibility check enabled
2585 return PciIncompatibilityCheckRead (
2595 return PciRootBridgeIo
->Pci
.Read (
2606 Write PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2608 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2609 @param Pci A pointer to PCI_TYPE00.
2610 @param Width Signifies the width of the memory operations.
2611 @param Address The address within the PCI configuration space for the PCI controller.
2612 @param Count The number of unit to be read.
2613 @param Buffer For read operations, the destination buffer to store the results. For
2614 write operations, the source buffer to write data from.
2616 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2617 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2618 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2619 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2623 PciRootBridgeIoWrite (
2624 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
2626 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
2632 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_WRITE_SUPPORT
) {
2634 // if PCI incompatibility check enabled
2636 return PciIncompatibilityCheckWrite (
2647 return PciRootBridgeIo
->Pci
.Write (
2658 Read PCI configuration space through EFI_PCI_IO_PROTOCOL.
2660 @param PciIo A pointer to the EFI_PCI_O_PROTOCOL.
2661 @param Width Signifies the width of the memory operations.
2662 @param Address The address within the PCI configuration space for the PCI controller.
2663 @param Count The number of unit to be read.
2664 @param Buffer For read operations, the destination buffer to store the results. For
2665 write operations, the source buffer to write data from.
2667 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2668 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2669 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2670 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2675 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2676 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
2682 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_READ_SUPPORT
) {
2684 // if PCI incompatibility check enabled
2686 return PciIncompatibilityCheckRead (
2696 return PciIo
->Pci
.Read (
2707 Write PCI configuration space through EFI_PCI_IO_PROTOCOL.
2709 @param PciIo A pointer to the EFI_PCI_O_PROTOCOL.
2710 @param Width Signifies the width of the memory operations.
2711 @param Address The address within the PCI configuration space for the PCI controller.
2712 @param Count The number of unit to be read.
2713 @param Buffer For read operations, the destination buffer to store the results. For
2714 write operations, the source buffer to write data from.
2716 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2717 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2718 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2719 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2724 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2725 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
2731 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_WRITE_SUPPORT
) {
2734 // if PCI incompatibility check enabled
2736 return PciIncompatibilityCheckWrite (
2747 return PciIo
->Pci
.Write (