2 PCI emumeration support functions implementation for PCI Bus module.
4 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
12 extern CHAR16
*mBarTypeStr
[];
14 #define OLD_ALIGN 0xFFFFFFFFFFFFFFFFULL
15 #define EVEN_ALIGN 0xFFFFFFFFFFFFFFFEULL
16 #define SQUAD_ALIGN 0xFFFFFFFFFFFFFFFDULL
17 #define DQUAD_ALIGN 0xFFFFFFFFFFFFFFFCULL
20 This routine is used to check whether the pci device is present.
22 @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
23 @param Pci Output buffer for PCI device configuration space.
24 @param Bus PCI bus NO.
25 @param Device PCI device NO.
26 @param Func PCI Func NO.
28 @retval EFI_NOT_FOUND PCI device not present.
29 @retval EFI_SUCCESS PCI device is found.
34 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
45 // Create PCI address map in terms of Bus, Device and Func
47 Address
= EFI_PCI_ADDRESS (Bus
, Device
, Func
, 0);
50 // Read the Vendor ID register
52 Status
= PciRootBridgeIo
->Pci
.Read (
60 if (!EFI_ERROR (Status
) && (Pci
->Hdr
).VendorId
!= 0xffff) {
62 // Read the entire config header for the device
64 Status
= PciRootBridgeIo
->Pci
.Read (
68 sizeof (PCI_TYPE00
) / sizeof (UINT32
),
79 Collect all the resource information under this root bridge.
81 A database that records all the information about pci device subject to this
82 root bridge will then be created.
84 @param Bridge Parent bridge instance.
85 @param StartBusNumber Bus number of beginning.
87 @retval EFI_SUCCESS PCI device is found.
88 @retval other Some error occurred when reading PCI bridge information.
92 PciPciDeviceInfoCollector (
93 IN PCI_IO_DEVICE
*Bridge
,
94 IN UINT8 StartBusNumber
102 PCI_IO_DEVICE
*PciIoDevice
;
103 EFI_PCI_IO_PROTOCOL
*PciIo
;
105 Status
= EFI_SUCCESS
;
108 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
110 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
113 // Check to see whether PCI device is present
115 Status
= PciDevicePresent (
116 Bridge
->PciRootBridgeIo
,
118 (UINT8
) StartBusNumber
,
123 if (EFI_ERROR (Status
) && Func
== 0) {
125 // go to next device if there is no Function 0
130 if (!EFI_ERROR (Status
)) {
133 // Call back to host bridge function
135 PreprocessController (Bridge
, (UINT8
) StartBusNumber
, Device
, Func
, EfiPciBeforeResourceCollection
);
138 // Collect all the information about the PCI device discovered
140 Status
= PciSearchDevice (
143 (UINT8
) StartBusNumber
,
150 // Recursively scan PCI busses on the other side of PCI-PCI bridges
153 if (!EFI_ERROR (Status
) && (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
))) {
156 // If it is PPB, we need to get the secondary bus to continue the enumeration
158 PciIo
= &(PciIoDevice
->PciIo
);
160 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET
, 1, &SecBus
);
162 if (EFI_ERROR (Status
)) {
167 // Ensure secondary bus number is greater than the primary bus number to avoid
168 // any potential dead loop when PcdPciDisableBusEnumeration is set to TRUE
170 if (SecBus
<= StartBusNumber
) {
175 // Get resource padding for PPB
177 GetResourcePaddingPpb (PciIoDevice
);
180 // Deep enumerate the next level bus
182 Status
= PciPciDeviceInfoCollector (
189 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
192 // Skip sub functions, this is not a multi function device
205 Search required device and create PCI device instance.
207 @param Bridge Parent bridge instance.
208 @param Pci Input PCI device information block.
209 @param Bus PCI bus NO.
210 @param Device PCI device NO.
211 @param Func PCI func NO.
212 @param PciDevice Output of searched PCI device instance.
214 @retval EFI_SUCCESS Successfully created PCI device instance.
215 @retval EFI_OUT_OF_RESOURCES Cannot get PCI device information.
220 IN PCI_IO_DEVICE
*Bridge
,
225 OUT PCI_IO_DEVICE
**PciDevice
228 PCI_IO_DEVICE
*PciIoDevice
;
234 "PciBus: Discovered %s @ [%02x|%02x|%02x]\n",
235 IS_PCI_BRIDGE (Pci
) ? L
"PPB" :
236 IS_CARDBUS_BRIDGE (Pci
) ? L
"P2C" :
241 if (!IS_PCI_BRIDGE (Pci
)) {
243 if (IS_CARDBUS_BRIDGE (Pci
)) {
244 PciIoDevice
= GatherP2CInfo (
251 if ((PciIoDevice
!= NULL
) && gFullEnumeration
) {
252 InitializeP2C (PciIoDevice
);
257 // Create private data for Pci Device
259 PciIoDevice
= GatherDeviceInfo (
272 // Create private data for PPB
274 PciIoDevice
= GatherPpbInfo (
283 // Special initialization for PPB including making the PPB quiet
285 if ((PciIoDevice
!= NULL
) && gFullEnumeration
) {
286 InitializePpb (PciIoDevice
);
290 if (PciIoDevice
== NULL
) {
291 return EFI_OUT_OF_RESOURCES
;
295 // Update the bar information for this PCI device so as to support some specific device
297 UpdatePciInfo (PciIoDevice
);
299 if (PciIoDevice
->DevicePath
== NULL
) {
300 return EFI_OUT_OF_RESOURCES
;
304 // Detect this function has option rom
306 if (gFullEnumeration
) {
308 if (!IS_CARDBUS_BRIDGE (Pci
)) {
310 GetOpRomInfo (PciIoDevice
);
314 ResetPowerManagementFeature (PciIoDevice
);
319 // Insert it into a global tree for future reference
321 InsertPciDevice (Bridge
, PciIoDevice
);
324 // Determine PCI device attributes
327 if (PciDevice
!= NULL
) {
328 *PciDevice
= PciIoDevice
;
335 Dump the PPB padding resource information.
337 @param PciIoDevice PCI IO instance.
338 @param ResourceType The desired resource type to dump.
339 PciBarTypeUnknown means to dump all types of resources.
342 DumpPpbPaddingResource (
343 IN PCI_IO_DEVICE
*PciIoDevice
,
344 IN PCI_BAR_TYPE ResourceType
347 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
350 if (PciIoDevice
->ResourcePaddingDescriptors
== NULL
) {
354 if (ResourceType
== PciBarTypeIo16
|| ResourceType
== PciBarTypeIo32
) {
355 ResourceType
= PciBarTypeIo
;
358 for (Descriptor
= PciIoDevice
->ResourcePaddingDescriptors
; Descriptor
->Desc
!= ACPI_END_TAG_DESCRIPTOR
; Descriptor
++) {
360 Type
= PciBarTypeUnknown
;
361 if (Descriptor
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
&& Descriptor
->ResType
== ACPI_ADDRESS_SPACE_TYPE_IO
) {
363 } else if (Descriptor
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
&& Descriptor
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
) {
365 if (Descriptor
->AddrSpaceGranularity
== 32) {
369 if (Descriptor
->SpecificFlag
== EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) {
370 Type
= PciBarTypePMem32
;
376 if (Descriptor
->SpecificFlag
== 0) {
377 Type
= PciBarTypeMem32
;
381 if (Descriptor
->AddrSpaceGranularity
== 64) {
385 if (Descriptor
->SpecificFlag
== EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) {
386 Type
= PciBarTypePMem64
;
392 if (Descriptor
->SpecificFlag
== 0) {
393 Type
= PciBarTypeMem64
;
398 if ((Type
!= PciBarTypeUnknown
) && ((ResourceType
== PciBarTypeUnknown
) || (ResourceType
== Type
))) {
401 " Padding: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx\n",
402 mBarTypeStr
[Type
], Descriptor
->AddrRangeMax
, Descriptor
->AddrLen
410 Dump the PCI BAR information.
412 @param PciIoDevice PCI IO instance.
416 IN PCI_IO_DEVICE
*PciIoDevice
421 for (Index
= 0; Index
< PCI_MAX_BAR
; Index
++) {
422 if (PciIoDevice
->PciBar
[Index
].BarType
== PciBarTypeUnknown
) {
428 " BAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n",
429 Index
, mBarTypeStr
[MIN (PciIoDevice
->PciBar
[Index
].BarType
, PciBarTypeMaxType
)],
430 PciIoDevice
->PciBar
[Index
].Alignment
, PciIoDevice
->PciBar
[Index
].Length
, PciIoDevice
->PciBar
[Index
].Offset
434 for (Index
= 0; Index
< PCI_MAX_BAR
; Index
++) {
435 if ((PciIoDevice
->VfPciBar
[Index
].BarType
== PciBarTypeUnknown
) && (PciIoDevice
->VfPciBar
[Index
].Length
== 0)) {
441 " VFBAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n",
442 Index
, mBarTypeStr
[MIN (PciIoDevice
->VfPciBar
[Index
].BarType
, PciBarTypeMaxType
)],
443 PciIoDevice
->VfPciBar
[Index
].Alignment
, PciIoDevice
->VfPciBar
[Index
].Length
, PciIoDevice
->VfPciBar
[Index
].Offset
446 DEBUG ((EFI_D_INFO
, "\n"));
450 Create PCI device instance for PCI device.
452 @param Bridge Parent bridge instance.
453 @param Pci Input PCI device information block.
454 @param Bus PCI device Bus NO.
455 @param Device PCI device Device NO.
456 @param Func PCI device's func NO.
458 @return Created PCI device instance.
463 IN PCI_IO_DEVICE
*Bridge
,
472 PCI_IO_DEVICE
*PciIoDevice
;
474 PciIoDevice
= CreatePciIoDevice (
482 if (PciIoDevice
== NULL
) {
487 // If it is a full enumeration, disconnect the device in advance
489 if (gFullEnumeration
) {
491 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
496 // Start to parse the bars
498 for (Offset
= 0x10, BarIndex
= 0; Offset
<= 0x24 && BarIndex
< PCI_MAX_BAR
; BarIndex
++) {
499 Offset
= PciParseBar (PciIoDevice
, Offset
, BarIndex
);
503 // Parse the SR-IOV VF bars
505 if (PcdGetBool (PcdSrIovSupport
) && PciIoDevice
->SrIovCapabilityOffset
!= 0) {
506 for (Offset
= PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_BAR0
, BarIndex
= 0;
507 Offset
<= PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_BAR5
;
510 ASSERT (BarIndex
< PCI_MAX_BAR
);
511 Offset
= PciIovParseVfBar (PciIoDevice
, Offset
, BarIndex
);
515 DEBUG_CODE (DumpPciBars (PciIoDevice
););
520 Create PCI device instance for PCI-PCI bridge.
522 @param Bridge Parent bridge instance.
523 @param Pci Input PCI device information block.
524 @param Bus PCI device Bus NO.
525 @param Device PCI device Device NO.
526 @param Func PCI device's func NO.
528 @return Created PCI device instance.
533 IN PCI_IO_DEVICE
*Bridge
,
540 PCI_IO_DEVICE
*PciIoDevice
;
543 EFI_PCI_IO_PROTOCOL
*PciIo
;
545 UINT32 PMemBaseLimit
;
546 UINT16 PrefetchableMemoryBase
;
547 UINT16 PrefetchableMemoryLimit
;
549 PciIoDevice
= CreatePciIoDevice (
557 if (PciIoDevice
== NULL
) {
561 if (gFullEnumeration
) {
562 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
565 // Initialize the bridge control register
567 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED
);
572 // PPB can have two BARs
574 if (PciParseBar (PciIoDevice
, 0x10, PPB_BAR_0
) == 0x14) {
578 PciParseBar (PciIoDevice
, 0x14, PPB_BAR_1
);
581 PciIo
= &PciIoDevice
->PciIo
;
584 // Test whether it support 32 decode or not
586 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Temp
);
587 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &gAllOne
);
588 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Value
);
589 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Temp
);
592 if ((Value
& 0x01) != 0) {
593 PciIoDevice
->Decodes
|= EFI_BRIDGE_IO32_DECODE_SUPPORTED
;
595 PciIoDevice
->Decodes
|= EFI_BRIDGE_IO16_DECODE_SUPPORTED
;
600 // if PcdPciBridgeIoAlignmentProbe is TRUE, PCI bus driver probes
601 // PCI bridge supporting non-standard I/O window alignment less than 4K.
604 PciIoDevice
->BridgeIoAlignment
= 0xFFF;
605 if (FeaturePcdGet (PcdPciBridgeIoAlignmentProbe
)) {
607 // Check any bits of bit 3-1 of I/O Base Register are writable.
608 // if so, it is assumed non-standard I/O window alignment is supported by this bridge.
609 // Per spec, bit 3-1 of I/O Base Register are reserved bits, so its content can't be assumed.
611 Value
= (UINT8
)(Temp
^ (BIT3
| BIT2
| BIT1
));
612 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Value
);
613 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Value
);
614 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Temp
);
615 Value
= (UINT8
)((Value
^ Temp
) & (BIT3
| BIT2
| BIT1
));
618 PciIoDevice
->BridgeIoAlignment
= 0x7FF;
621 PciIoDevice
->BridgeIoAlignment
= 0x3FF;
623 case BIT3
| BIT2
| BIT1
:
624 PciIoDevice
->BridgeIoAlignment
= 0x1FF;
629 Status
= BarExisted (
637 // Test if it supports 64 memory or not
639 // The bottom 4 bits of both the Prefetchable Memory Base and Prefetchable Memory Limit
641 // 0 - the bridge supports only 32 bit addresses.
642 // 1 - the bridge supports 64-bit addresses.
644 PrefetchableMemoryBase
= (UINT16
)(PMemBaseLimit
& 0xffff);
645 PrefetchableMemoryLimit
= (UINT16
)(PMemBaseLimit
>> 16);
646 if (!EFI_ERROR (Status
) &&
647 (PrefetchableMemoryBase
& 0x000f) == 0x0001 &&
648 (PrefetchableMemoryLimit
& 0x000f) == 0x0001) {
649 Status
= BarExisted (
656 if (!EFI_ERROR (Status
)) {
657 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
658 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED
;
660 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
665 // Memory 32 code is required for ppb
667 PciIoDevice
->Decodes
|= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
;
669 GetResourcePaddingPpb (PciIoDevice
);
672 DumpPpbPaddingResource (PciIoDevice
, PciBarTypeUnknown
);
673 DumpPciBars (PciIoDevice
);
681 Create PCI device instance for PCI Card bridge device.
683 @param Bridge Parent bridge instance.
684 @param Pci Input PCI device information block.
685 @param Bus PCI device Bus NO.
686 @param Device PCI device Device NO.
687 @param Func PCI device's func NO.
689 @return Created PCI device instance.
694 IN PCI_IO_DEVICE
*Bridge
,
701 PCI_IO_DEVICE
*PciIoDevice
;
703 PciIoDevice
= CreatePciIoDevice (
711 if (PciIoDevice
== NULL
) {
715 if (gFullEnumeration
) {
716 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
719 // Initialize the bridge control register
721 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED
);
725 // P2C only has one bar that is in 0x10
727 PciParseBar (PciIoDevice
, 0x10, P2C_BAR_0
);
730 // Read PciBar information from the bar register
732 GetBackPcCardBar (PciIoDevice
);
733 PciIoDevice
->Decodes
= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
|
734 EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
|
735 EFI_BRIDGE_IO32_DECODE_SUPPORTED
;
737 DEBUG_CODE (DumpPciBars (PciIoDevice
););
743 Create device path for pci device.
745 @param ParentDevicePath Parent bridge's path.
746 @param PciIoDevice Pci device instance.
748 @return Device path protocol instance for specific pci device.
751 EFI_DEVICE_PATH_PROTOCOL
*
752 CreatePciDevicePath (
753 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
754 IN PCI_IO_DEVICE
*PciIoDevice
758 PCI_DEVICE_PATH PciNode
;
761 // Create PCI device path
763 PciNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
764 PciNode
.Header
.SubType
= HW_PCI_DP
;
765 SetDevicePathNodeLength (&PciNode
.Header
, sizeof (PciNode
));
767 PciNode
.Device
= PciIoDevice
->DeviceNumber
;
768 PciNode
.Function
= PciIoDevice
->FunctionNumber
;
769 PciIoDevice
->DevicePath
= AppendDevicePathNode (ParentDevicePath
, &PciNode
.Header
);
771 return PciIoDevice
->DevicePath
;
775 Check whether the PCI IOV VF bar is existed or not.
777 @param PciIoDevice A pointer to the PCI_IO_DEVICE.
778 @param Offset The offset.
779 @param BarLengthValue The bar length value returned.
780 @param OriginalBarValue The original bar value returned.
782 @retval EFI_NOT_FOUND The bar doesn't exist.
783 @retval EFI_SUCCESS The bar exist.
788 IN PCI_IO_DEVICE
*PciIoDevice
,
790 OUT UINT32
*BarLengthValue
,
791 OUT UINT32
*OriginalBarValue
794 EFI_PCI_IO_PROTOCOL
*PciIo
;
795 UINT32 OriginalValue
;
800 // Ensure it is called properly
802 ASSERT (PciIoDevice
->SrIovCapabilityOffset
!= 0);
803 if (PciIoDevice
->SrIovCapabilityOffset
== 0) {
804 return EFI_NOT_FOUND
;
807 PciIo
= &PciIoDevice
->PciIo
;
810 // Preserve the original value
813 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, (UINT32
)Offset
, 1, &OriginalValue
);
816 // Raise TPL to high level to disable timer interrupt while the BAR is probed
818 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
820 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, (UINT32
)Offset
, 1, &gAllOne
);
821 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, (UINT32
)Offset
, 1, &Value
);
824 // Write back the original value
826 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, (UINT32
)Offset
, 1, &OriginalValue
);
829 // Restore TPL to its original level
831 gBS
->RestoreTPL (OldTpl
);
833 if (BarLengthValue
!= NULL
) {
834 *BarLengthValue
= Value
;
837 if (OriginalBarValue
!= NULL
) {
838 *OriginalBarValue
= OriginalValue
;
842 return EFI_NOT_FOUND
;
849 Check whether the bar is existed or not.
851 @param PciIoDevice A pointer to the PCI_IO_DEVICE.
852 @param Offset The offset.
853 @param BarLengthValue The bar length value returned.
854 @param OriginalBarValue The original bar value returned.
856 @retval EFI_NOT_FOUND The bar doesn't exist.
857 @retval EFI_SUCCESS The bar exist.
862 IN PCI_IO_DEVICE
*PciIoDevice
,
864 OUT UINT32
*BarLengthValue
,
865 OUT UINT32
*OriginalBarValue
868 EFI_PCI_IO_PROTOCOL
*PciIo
;
869 UINT32 OriginalValue
;
873 PciIo
= &PciIoDevice
->PciIo
;
876 // Preserve the original value
878 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &OriginalValue
);
881 // Raise TPL to high level to disable timer interrupt while the BAR is probed
883 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
885 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &gAllOne
);
886 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &Value
);
889 // Write back the original value
891 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &OriginalValue
);
894 // Restore TPL to its original level
896 gBS
->RestoreTPL (OldTpl
);
898 if (BarLengthValue
!= NULL
) {
899 *BarLengthValue
= Value
;
902 if (OriginalBarValue
!= NULL
) {
903 *OriginalBarValue
= OriginalValue
;
907 return EFI_NOT_FOUND
;
914 Test whether the device can support given attributes.
916 @param PciIoDevice Pci device instance.
917 @param Command Input command register value, and
918 returned supported register value.
919 @param BridgeControl Input bridge control value for PPB or P2C, and
920 returned supported bridge control value.
921 @param OldCommand Returned and stored old command register offset.
922 @param OldBridgeControl Returned and stored old Bridge control value for PPB or P2C.
926 PciTestSupportedAttribute (
927 IN PCI_IO_DEVICE
*PciIoDevice
,
928 IN OUT UINT16
*Command
,
929 IN OUT UINT16
*BridgeControl
,
930 OUT UINT16
*OldCommand
,
931 OUT UINT16
*OldBridgeControl
937 // Preserve the original value
939 PCI_READ_COMMAND_REGISTER (PciIoDevice
, OldCommand
);
942 // Raise TPL to high level to disable timer interrupt while the BAR is probed
944 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
946 PCI_SET_COMMAND_REGISTER (PciIoDevice
, *Command
);
947 PCI_READ_COMMAND_REGISTER (PciIoDevice
, Command
);
950 // Write back the original value
952 PCI_SET_COMMAND_REGISTER (PciIoDevice
, *OldCommand
);
955 // Restore TPL to its original level
957 gBS
->RestoreTPL (OldTpl
);
959 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
) || IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
962 // Preserve the original value
964 PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice
, OldBridgeControl
);
967 // Raise TPL to high level to disable timer interrupt while the BAR is probed
969 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
971 PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice
, *BridgeControl
);
972 PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice
, BridgeControl
);
975 // Write back the original value
977 PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice
, *OldBridgeControl
);
980 // Restore TPL to its original level
982 gBS
->RestoreTPL (OldTpl
);
985 *OldBridgeControl
= 0;
991 Set the supported or current attributes of a PCI device.
993 @param PciIoDevice Structure pointer for PCI device.
994 @param Command Command register value.
995 @param BridgeControl Bridge control value for PPB or P2C.
996 @param Option Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES.
1000 PciSetDeviceAttribute (
1001 IN PCI_IO_DEVICE
*PciIoDevice
,
1003 IN UINT16 BridgeControl
,
1011 if ((Command
& EFI_PCI_COMMAND_IO_SPACE
) != 0) {
1012 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IO
;
1015 if ((Command
& EFI_PCI_COMMAND_MEMORY_SPACE
) != 0) {
1016 Attributes
|= EFI_PCI_IO_ATTRIBUTE_MEMORY
;
1019 if ((Command
& EFI_PCI_COMMAND_BUS_MASTER
) != 0) {
1020 Attributes
|= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
;
1023 if ((Command
& EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
) != 0) {
1024 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
;
1027 if ((BridgeControl
& EFI_PCI_BRIDGE_CONTROL_ISA
) != 0) {
1028 Attributes
|= EFI_PCI_IO_ATTRIBUTE_ISA_IO
;
1031 if ((BridgeControl
& EFI_PCI_BRIDGE_CONTROL_VGA
) != 0) {
1032 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_IO
;
1033 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
;
1034 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
;
1037 if ((BridgeControl
& EFI_PCI_BRIDGE_CONTROL_VGA_16
) != 0) {
1038 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
;
1039 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16
;
1042 if (Option
== EFI_SET_SUPPORTS
) {
1044 Attributes
|= (UINT64
) (EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE
|
1045 EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED
|
1046 EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE
|
1047 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE
|
1048 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM
|
1049 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
);
1051 if (IS_PCI_LPC (&PciIoDevice
->Pci
)) {
1052 Attributes
|= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO
;
1053 Attributes
|= (mReserveIsaAliases
? (UINT64
) EFI_PCI_IO_ATTRIBUTE_ISA_IO
: \
1054 (UINT64
) EFI_PCI_IO_ATTRIBUTE_ISA_IO_16
);
1057 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
) || IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
1059 // For bridge, it should support IDE attributes
1061 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO
;
1062 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO
;
1064 if (mReserveVgaAliases
) {
1065 Attributes
&= ~(UINT64
)(EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
| \
1066 EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16
);
1068 Attributes
&= ~(UINT64
)(EFI_PCI_IO_ATTRIBUTE_VGA_IO
| \
1069 EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
);
1073 if (IS_PCI_IDE (&PciIoDevice
->Pci
)) {
1074 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO
;
1075 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO
;
1078 if (IS_PCI_VGA (&PciIoDevice
->Pci
)) {
1079 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
;
1080 Attributes
|= (mReserveVgaAliases
? (UINT64
) EFI_PCI_IO_ATTRIBUTE_VGA_IO
: \
1081 (UINT64
) EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
);
1085 PciIoDevice
->Supports
= Attributes
;
1086 PciIoDevice
->Supports
&= ( (PciIoDevice
->Parent
->Supports
) | \
1087 EFI_PCI_IO_ATTRIBUTE_IO
| EFI_PCI_IO_ATTRIBUTE_MEMORY
| \
1088 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
);
1092 // When this attribute is clear, the RomImage and RomSize fields in the PCI IO were
1093 // initialized based on the PCI option ROM found through the ROM BAR of the PCI controller.
1094 // When this attribute is set, the PCI option ROM described by the RomImage and RomSize
1095 // fields is not from the the ROM BAR of the PCI controller.
1097 if (!PciIoDevice
->EmbeddedRom
) {
1098 Attributes
|= EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM
;
1100 PciIoDevice
->Attributes
= Attributes
;
1105 Determine if the device can support Fast Back to Back attribute.
1107 @param PciIoDevice Pci device instance.
1108 @param StatusIndex Status register value.
1110 @retval EFI_SUCCESS This device support Fast Back to Back attribute.
1111 @retval EFI_UNSUPPORTED This device doesn't support Fast Back to Back attribute.
1115 GetFastBackToBackSupport (
1116 IN PCI_IO_DEVICE
*PciIoDevice
,
1117 IN UINT8 StatusIndex
1120 EFI_PCI_IO_PROTOCOL
*PciIo
;
1122 UINT32 StatusRegister
;
1125 // Read the status register
1127 PciIo
= &PciIoDevice
->PciIo
;
1128 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
, StatusIndex
, 1, &StatusRegister
);
1129 if (EFI_ERROR (Status
)) {
1130 return EFI_UNSUPPORTED
;
1134 // Check the Fast B2B bit
1136 if ((StatusRegister
& EFI_PCI_FAST_BACK_TO_BACK_CAPABLE
) != 0) {
1139 return EFI_UNSUPPORTED
;
1144 Process the option ROM for all the children of the specified parent PCI device.
1145 It can only be used after the first full Option ROM process.
1147 @param PciIoDevice Pci device instance.
1151 ProcessOptionRomLight (
1152 IN PCI_IO_DEVICE
*PciIoDevice
1155 PCI_IO_DEVICE
*Temp
;
1156 LIST_ENTRY
*CurrentLink
;
1159 // For RootBridge, PPB , P2C, go recursively to traverse all its children
1161 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
1162 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
1164 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1166 if (!IsListEmpty (&Temp
->ChildList
)) {
1167 ProcessOptionRomLight (Temp
);
1170 PciRomGetImageMapping (Temp
);
1173 // The OpRom has already been processed in the first round
1175 Temp
->AllOpRomProcessed
= TRUE
;
1177 CurrentLink
= CurrentLink
->ForwardLink
;
1182 Determine the related attributes of all devices under a Root Bridge.
1184 @param PciIoDevice PCI device instance.
1188 DetermineDeviceAttribute (
1189 IN PCI_IO_DEVICE
*PciIoDevice
1193 UINT16 BridgeControl
;
1195 UINT16 OldBridgeControl
;
1196 BOOLEAN FastB2BSupport
;
1197 PCI_IO_DEVICE
*Temp
;
1198 LIST_ENTRY
*CurrentLink
;
1202 // For Root Bridge, just copy it by RootBridgeIo protocol
1203 // so as to keep consistent with the actual attribute
1205 if (PciIoDevice
->Parent
== NULL
) {
1206 Status
= PciIoDevice
->PciRootBridgeIo
->GetAttributes (
1207 PciIoDevice
->PciRootBridgeIo
,
1208 &PciIoDevice
->Supports
,
1209 &PciIoDevice
->Attributes
1211 if (EFI_ERROR (Status
)) {
1215 // Assume the PCI Root Bridge supports DAC
1217 PciIoDevice
->Supports
|= (UINT64
)(EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE
|
1218 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM
|
1219 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
);
1224 // Set the attributes to be checked for common PCI devices and PPB or P2C
1225 // Since some devices only support part of them, it is better to set the
1226 // attribute according to its command or bridge control register
1228 Command
= EFI_PCI_COMMAND_IO_SPACE
|
1229 EFI_PCI_COMMAND_MEMORY_SPACE
|
1230 EFI_PCI_COMMAND_BUS_MASTER
|
1231 EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
;
1233 BridgeControl
= EFI_PCI_BRIDGE_CONTROL_ISA
| EFI_PCI_BRIDGE_CONTROL_VGA
| EFI_PCI_BRIDGE_CONTROL_VGA_16
;
1236 // Test whether the device can support attributes above
1238 PciTestSupportedAttribute (PciIoDevice
, &Command
, &BridgeControl
, &OldCommand
, &OldBridgeControl
);
1241 // Set the supported attributes for specified PCI device
1243 PciSetDeviceAttribute (PciIoDevice
, Command
, BridgeControl
, EFI_SET_SUPPORTS
);
1246 // Set the current attributes for specified PCI device
1248 PciSetDeviceAttribute (PciIoDevice
, OldCommand
, OldBridgeControl
, EFI_SET_ATTRIBUTES
);
1251 // Enable other PCI supported attributes but not defined in PCI_IO_PROTOCOL
1252 // For PCI Express devices, Memory Write and Invalidate is hardwired to 0b so only enable it for PCI devices.
1253 if (!PciIoDevice
->IsPciExp
) {
1254 PCI_ENABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE
);
1258 FastB2BSupport
= TRUE
;
1261 // P2C can not support FB2B on the secondary side
1263 if (IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
1264 FastB2BSupport
= FALSE
;
1268 // For RootBridge, PPB , P2C, go recursively to traverse all its children
1270 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
1271 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
1273 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1274 Status
= DetermineDeviceAttribute (Temp
);
1275 if (EFI_ERROR (Status
)) {
1279 // Detect Fast Back to Back support for the device under the bridge
1281 Status
= GetFastBackToBackSupport (Temp
, PCI_PRIMARY_STATUS_OFFSET
);
1282 if (FastB2BSupport
&& EFI_ERROR (Status
)) {
1283 FastB2BSupport
= FALSE
;
1286 CurrentLink
= CurrentLink
->ForwardLink
;
1289 // Set or clear Fast Back to Back bit for the whole bridge
1291 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
1293 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
)) {
1295 Status
= GetFastBackToBackSupport (PciIoDevice
, PCI_BRIDGE_STATUS_REGISTER_OFFSET
);
1297 if (EFI_ERROR (Status
) || (!FastB2BSupport
)) {
1298 FastB2BSupport
= FALSE
;
1299 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK
);
1301 PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK
);
1305 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
1306 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
1307 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1308 if (FastB2BSupport
) {
1309 PCI_ENABLE_COMMAND_REGISTER (Temp
, EFI_PCI_COMMAND_FAST_BACK_TO_BACK
);
1311 PCI_DISABLE_COMMAND_REGISTER (Temp
, EFI_PCI_COMMAND_FAST_BACK_TO_BACK
);
1314 CurrentLink
= CurrentLink
->ForwardLink
;
1318 // End for IsListEmpty
1324 This routine is used to update the bar information for those incompatible PCI device.
1326 @param PciIoDevice Input Pci device instance. Output Pci device instance with updated
1329 @retval EFI_SUCCESS Successfully updated bar information.
1330 @retval EFI_UNSUPPORTED Given PCI device doesn't belong to incompatible PCI device list.
1335 IN OUT PCI_IO_DEVICE
*PciIoDevice
1341 VOID
*Configuration
;
1342 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1344 Configuration
= NULL
;
1345 Status
= EFI_SUCCESS
;
1347 if (gIncompatiblePciDeviceSupport
== NULL
) {
1349 // It can only be supported after the Incompatible PCI Device
1350 // Support Protocol has been installed
1352 Status
= gBS
->LocateProtocol (
1353 &gEfiIncompatiblePciDeviceSupportProtocolGuid
,
1355 (VOID
**) &gIncompatiblePciDeviceSupport
1358 if (Status
== EFI_SUCCESS
) {
1360 // Check whether the device belongs to incompatible devices from protocol or not
1361 // If it is , then get its special requirement in the ACPI table
1363 Status
= gIncompatiblePciDeviceSupport
->CheckDevice (
1364 gIncompatiblePciDeviceSupport
,
1365 PciIoDevice
->Pci
.Hdr
.VendorId
,
1366 PciIoDevice
->Pci
.Hdr
.DeviceId
,
1367 PciIoDevice
->Pci
.Hdr
.RevisionID
,
1368 PciIoDevice
->Pci
.Device
.SubsystemVendorID
,
1369 PciIoDevice
->Pci
.Device
.SubsystemID
,
1375 if (EFI_ERROR (Status
) || Configuration
== NULL
) {
1376 return EFI_UNSUPPORTED
;
1380 // Update PCI device information from the ACPI table
1382 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
;
1384 while (Ptr
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
1386 if (Ptr
->Desc
!= ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
1388 // The format is not support
1393 for (BarIndex
= 0; BarIndex
< PCI_MAX_BAR
; BarIndex
++) {
1394 if ((Ptr
->AddrTranslationOffset
!= MAX_UINT64
) &&
1395 (Ptr
->AddrTranslationOffset
!= MAX_UINT8
) &&
1396 (Ptr
->AddrTranslationOffset
!= BarIndex
)
1399 // Skip updating when AddrTranslationOffset is not MAX_UINT64 or MAX_UINT8 (wide match).
1400 // Skip updating when current BarIndex doesn't equal to AddrTranslationOffset.
1401 // Comparing against MAX_UINT8 is to keep backward compatibility.
1407 switch (Ptr
->ResType
) {
1408 case ACPI_ADDRESS_SPACE_TYPE_MEM
:
1411 // Make sure the bar is memory type
1413 if (CheckBarType (PciIoDevice
, (UINT8
) BarIndex
, PciBarTypeMem
)) {
1417 // Ignored if granularity is 0.
1418 // Ignored if PCI BAR is I/O or 32-bit memory.
1419 // If PCI BAR is 64-bit memory and granularity is 32, then
1420 // the PCI BAR resource is allocated below 4GB.
1421 // If PCI BAR is 64-bit memory and granularity is 64, then
1422 // the PCI BAR resource is allocated above 4GB.
1424 if (PciIoDevice
->PciBar
[BarIndex
].BarType
== PciBarTypeMem64
) {
1425 switch (Ptr
->AddrSpaceGranularity
) {
1427 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeMem32
;
1429 PciIoDevice
->PciBar
[BarIndex
].BarTypeFixed
= TRUE
;
1436 if (PciIoDevice
->PciBar
[BarIndex
].BarType
== PciBarTypePMem64
) {
1437 switch (Ptr
->AddrSpaceGranularity
) {
1439 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypePMem32
;
1441 PciIoDevice
->PciBar
[BarIndex
].BarTypeFixed
= TRUE
;
1450 case ACPI_ADDRESS_SPACE_TYPE_IO
:
1453 // Make sure the bar is IO type
1455 if (CheckBarType (PciIoDevice
, (UINT8
) BarIndex
, PciBarTypeIo
)) {
1464 // Update the new alignment for the device
1466 SetNewAlign (&(PciIoDevice
->PciBar
[BarIndex
].Alignment
), Ptr
->AddrRangeMax
);
1469 // Update the new length for the device
1471 if (Ptr
->AddrLen
!= 0) {
1472 PciIoDevice
->PciBar
[BarIndex
].Length
= Ptr
->AddrLen
;
1480 FreePool (Configuration
);
1486 This routine will update the alignment with the new alignment.
1487 Compare with OLD_ALIGN/EVEN_ALIGN/SQUAD_ALIGN/DQUAD_ALIGN is to keep
1488 backward compatibility.
1490 @param Alignment Input Old alignment. Output updated alignment.
1491 @param NewAlignment New alignment.
1496 IN OUT UINT64
*Alignment
,
1497 IN UINT64 NewAlignment
1500 UINT64 OldAlignment
;
1504 // The new alignment is the same as the original,
1507 if ((NewAlignment
== 0) || (NewAlignment
== OLD_ALIGN
)) {
1511 // Check the validity of the parameter
1513 if (NewAlignment
!= EVEN_ALIGN
&&
1514 NewAlignment
!= SQUAD_ALIGN
&&
1515 NewAlignment
!= DQUAD_ALIGN
) {
1516 *Alignment
= NewAlignment
;
1520 OldAlignment
= (*Alignment
) + 1;
1524 // Get the first non-zero hex value of the length
1526 while ((OldAlignment
& 0x0F) == 0x00) {
1527 OldAlignment
= RShiftU64 (OldAlignment
, 4);
1532 // Adjust the alignment to even, quad or double quad boundary
1534 if (NewAlignment
== EVEN_ALIGN
) {
1535 if ((OldAlignment
& 0x01) != 0) {
1536 OldAlignment
= OldAlignment
+ 2 - (OldAlignment
& 0x01);
1538 } else if (NewAlignment
== SQUAD_ALIGN
) {
1539 if ((OldAlignment
& 0x03) != 0) {
1540 OldAlignment
= OldAlignment
+ 4 - (OldAlignment
& 0x03);
1542 } else if (NewAlignment
== DQUAD_ALIGN
) {
1543 if ((OldAlignment
& 0x07) != 0) {
1544 OldAlignment
= OldAlignment
+ 8 - (OldAlignment
& 0x07);
1549 // Update the old value
1551 NewAlignment
= LShiftU64 (OldAlignment
, ShiftBit
) - 1;
1552 *Alignment
= NewAlignment
;
1558 Parse PCI IOV VF bar information and fill them into PCI device instance.
1560 @param PciIoDevice Pci device instance.
1561 @param Offset Bar offset.
1562 @param BarIndex Bar index.
1564 @return Next bar offset.
1569 IN PCI_IO_DEVICE
*PciIoDevice
,
1575 UINT32 OriginalValue
;
1580 // Ensure it is called properly
1582 ASSERT (PciIoDevice
->SrIovCapabilityOffset
!= 0);
1583 if (PciIoDevice
->SrIovCapabilityOffset
== 0) {
1590 Status
= VfBarExisted (
1597 if (EFI_ERROR (Status
)) {
1598 PciIoDevice
->VfPciBar
[BarIndex
].BaseAddress
= 0;
1599 PciIoDevice
->VfPciBar
[BarIndex
].Length
= 0;
1600 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= 0;
1603 // Scan all the BARs anyway
1605 PciIoDevice
->VfPciBar
[BarIndex
].Offset
= (UINT16
) Offset
;
1609 PciIoDevice
->VfPciBar
[BarIndex
].Offset
= (UINT16
) Offset
;
1610 if ((Value
& 0x01) != 0) {
1612 // Device I/Os. Impossible
1621 PciIoDevice
->VfPciBar
[BarIndex
].BaseAddress
= OriginalValue
& Mask
;
1623 switch (Value
& 0x07) {
1626 //memory space; anywhere in 32 bit address space
1629 if ((Value
& 0x08) != 0) {
1630 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypePMem32
;
1632 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypeMem32
;
1635 PciIoDevice
->VfPciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1636 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->VfPciBar
[BarIndex
].Length
- 1;
1641 PciIoDevice
->VfPciBar
[BarIndex
].Length
= MultU64x32 (PciIoDevice
->VfPciBar
[BarIndex
].Length
, PciIoDevice
->InitialVFs
);
1645 if (PciIoDevice
->VfPciBar
[BarIndex
].Alignment
< PciIoDevice
->SystemPageSize
- 1) {
1646 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->SystemPageSize
- 1;
1652 // memory space; anywhere in 64 bit address space
1655 if ((Value
& 0x08) != 0) {
1656 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypePMem64
;
1658 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypeMem64
;
1662 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
1663 // is regarded as an extension for the first bar. As a result
1664 // the sizing will be conducted on combined 64 bit value
1665 // Here just store the masked first 32bit value for future size
1668 PciIoDevice
->VfPciBar
[BarIndex
].Length
= Value
& Mask
;
1669 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->VfPciBar
[BarIndex
].Length
- 1;
1671 if (PciIoDevice
->VfPciBar
[BarIndex
].Alignment
< PciIoDevice
->SystemPageSize
- 1) {
1672 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->SystemPageSize
- 1;
1676 // Increment the offset to point to next DWORD
1680 Status
= VfBarExisted (
1687 if (EFI_ERROR (Status
)) {
1692 // Fix the length to support some special 64 bit BAR
1694 Value
|= ((UINT32
) -1 << HighBitSet32 (Value
));
1697 // Calculate the size of 64bit bar
1699 PciIoDevice
->VfPciBar
[BarIndex
].BaseAddress
|= LShiftU64 ((UINT64
) OriginalValue
, 32);
1701 PciIoDevice
->VfPciBar
[BarIndex
].Length
= PciIoDevice
->VfPciBar
[BarIndex
].Length
| LShiftU64 ((UINT64
) Value
, 32);
1702 PciIoDevice
->VfPciBar
[BarIndex
].Length
= (~(PciIoDevice
->VfPciBar
[BarIndex
].Length
)) + 1;
1703 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->VfPciBar
[BarIndex
].Length
- 1;
1708 PciIoDevice
->VfPciBar
[BarIndex
].Length
= MultU64x32 (PciIoDevice
->VfPciBar
[BarIndex
].Length
, PciIoDevice
->InitialVFs
);
1712 if (PciIoDevice
->VfPciBar
[BarIndex
].Alignment
< PciIoDevice
->SystemPageSize
- 1) {
1713 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->SystemPageSize
- 1;
1722 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1723 PciIoDevice
->VfPciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1724 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->VfPciBar
[BarIndex
].Length
- 1;
1726 if (PciIoDevice
->VfPciBar
[BarIndex
].Alignment
< PciIoDevice
->SystemPageSize
- 1) {
1727 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->SystemPageSize
- 1;
1735 // Check the length again so as to keep compatible with some special bars
1737 if (PciIoDevice
->VfPciBar
[BarIndex
].Length
== 0) {
1738 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1739 PciIoDevice
->VfPciBar
[BarIndex
].BaseAddress
= 0;
1740 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= 0;
1744 // Increment number of bar
1750 Parse PCI bar information and fill them into PCI device instance.
1752 @param PciIoDevice Pci device instance.
1753 @param Offset Bar offset.
1754 @param BarIndex Bar index.
1756 @return Next bar offset.
1761 IN PCI_IO_DEVICE
*PciIoDevice
,
1767 UINT32 OriginalValue
;
1774 Status
= BarExisted (
1781 if (EFI_ERROR (Status
)) {
1782 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= 0;
1783 PciIoDevice
->PciBar
[BarIndex
].Length
= 0;
1784 PciIoDevice
->PciBar
[BarIndex
].Alignment
= 0;
1787 // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway
1789 PciIoDevice
->PciBar
[BarIndex
].Offset
= (UINT8
) Offset
;
1793 PciIoDevice
->PciBar
[BarIndex
].BarTypeFixed
= FALSE
;
1794 PciIoDevice
->PciBar
[BarIndex
].Offset
= (UINT8
) Offset
;
1795 if ((Value
& 0x01) != 0) {
1801 if ((Value
& 0xFFFF0000) != 0) {
1805 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeIo32
;
1806 PciIoDevice
->PciBar
[BarIndex
].Length
= ((~(Value
& Mask
)) + 1);
1807 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1813 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeIo16
;
1814 PciIoDevice
->PciBar
[BarIndex
].Length
= 0x0000FFFF & ((~(Value
& Mask
)) + 1);
1815 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1819 // Workaround. Some platforms implement IO bar with 0 length
1820 // Need to treat it as no-bar
1822 if (PciIoDevice
->PciBar
[BarIndex
].Length
== 0) {
1823 PciIoDevice
->PciBar
[BarIndex
].BarType
= (PCI_BAR_TYPE
) 0;
1826 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= OriginalValue
& Mask
;
1832 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= OriginalValue
& Mask
;
1834 switch (Value
& 0x07) {
1837 //memory space; anywhere in 32 bit address space
1840 if ((Value
& 0x08) != 0) {
1841 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypePMem32
;
1843 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeMem32
;
1846 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1847 if (PciIoDevice
->PciBar
[BarIndex
].Length
< (SIZE_4KB
)) {
1849 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
1851 PciIoDevice
->PciBar
[BarIndex
].Alignment
= (SIZE_4KB
- 1);
1853 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1858 // memory space; anywhere in 64 bit address space
1861 if ((Value
& 0x08) != 0) {
1862 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypePMem64
;
1864 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeMem64
;
1868 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
1869 // is regarded as an extension for the first bar. As a result
1870 // the sizing will be conducted on combined 64 bit value
1871 // Here just store the masked first 32bit value for future size
1874 PciIoDevice
->PciBar
[BarIndex
].Length
= Value
& Mask
;
1875 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1878 // Increment the offset to point to next DWORD
1882 Status
= BarExisted (
1889 if (EFI_ERROR (Status
)) {
1891 // the high 32 bit does not claim any BAR, we need to re-check the low 32 bit BAR again
1893 if (PciIoDevice
->PciBar
[BarIndex
].Length
== 0) {
1895 // some device implement MMIO bar with 0 length, need to treat it as no-bar
1897 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1903 // Fix the length to support some special 64 bit BAR
1906 DEBUG ((EFI_D_INFO
, "[PciBus]BAR probing for upper 32bit of MEM64 BAR returns 0, change to 0xFFFFFFFF.\n"));
1907 Value
= (UINT32
) -1;
1909 Value
|= ((UINT32
)(-1) << HighBitSet32 (Value
));
1913 // Calculate the size of 64bit bar
1915 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
|= LShiftU64 ((UINT64
) OriginalValue
, 32);
1917 PciIoDevice
->PciBar
[BarIndex
].Length
= PciIoDevice
->PciBar
[BarIndex
].Length
| LShiftU64 ((UINT64
) Value
, 32);
1918 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(PciIoDevice
->PciBar
[BarIndex
].Length
)) + 1;
1919 if (PciIoDevice
->PciBar
[BarIndex
].Length
< (SIZE_4KB
)) {
1921 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
1923 PciIoDevice
->PciBar
[BarIndex
].Alignment
= (SIZE_4KB
- 1);
1925 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1934 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1935 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1936 if (PciIoDevice
->PciBar
[BarIndex
].Length
< (SIZE_4KB
)) {
1938 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
1940 PciIoDevice
->PciBar
[BarIndex
].Alignment
= (SIZE_4KB
- 1);
1942 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1949 // Check the length again so as to keep compatible with some special bars
1951 if (PciIoDevice
->PciBar
[BarIndex
].Length
== 0) {
1952 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1953 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= 0;
1954 PciIoDevice
->PciBar
[BarIndex
].Alignment
= 0;
1958 // Increment number of bar
1964 This routine is used to initialize the bar of a PCI device.
1966 @param PciIoDevice Pci device instance.
1968 @note It can be called typically when a device is going to be rejected.
1972 InitializePciDevice (
1973 IN PCI_IO_DEVICE
*PciIoDevice
1976 EFI_PCI_IO_PROTOCOL
*PciIo
;
1979 PciIo
= &(PciIoDevice
->PciIo
);
1982 // Put all the resource apertures
1983 // Resource base is set to all ones so as to indicate its resource
1984 // has not been allocated
1986 for (Offset
= 0x10; Offset
<= 0x24; Offset
+= sizeof (UINT32
)) {
1987 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, Offset
, 1, &gAllOne
);
1992 This routine is used to initialize the bar of a PCI-PCI Bridge device.
1994 @param PciIoDevice PCI-PCI bridge device instance.
1999 IN PCI_IO_DEVICE
*PciIoDevice
2002 EFI_PCI_IO_PROTOCOL
*PciIo
;
2004 PciIo
= &(PciIoDevice
->PciIo
);
2007 // Put all the resource apertures including IO16
2008 // Io32, pMem32, pMem64 to quiescent state
2009 // Resource base all ones, Resource limit all zeros
2011 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &gAllOne
);
2012 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1D, 1, &gAllZero
);
2014 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x20, 1, &gAllOne
);
2015 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x22, 1, &gAllZero
);
2017 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x24, 1, &gAllOne
);
2018 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x26, 1, &gAllZero
);
2020 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x28, 1, &gAllOne
);
2021 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x2C, 1, &gAllZero
);
2024 // Don't support use io32 as for now
2026 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x30, 1, &gAllOne
);
2027 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x32, 1, &gAllZero
);
2030 // Force Interrupt line to zero for cards that come up randomly
2032 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x3C, 1, &gAllZero
);
2036 This routine is used to initialize the bar of a PCI Card Bridge device.
2038 @param PciIoDevice PCI Card bridge device.
2043 IN PCI_IO_DEVICE
*PciIoDevice
2046 EFI_PCI_IO_PROTOCOL
*PciIo
;
2048 PciIo
= &(PciIoDevice
->PciIo
);
2051 // Put all the resource apertures including IO16
2052 // Io32, pMem32, pMem64 to quiescent state(
2053 // Resource base all ones, Resource limit all zeros
2055 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x1c, 1, &gAllOne
);
2056 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x20, 1, &gAllZero
);
2058 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x24, 1, &gAllOne
);
2059 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x28, 1, &gAllZero
);
2061 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x2c, 1, &gAllOne
);
2062 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x30, 1, &gAllZero
);
2064 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x34, 1, &gAllOne
);
2065 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x38, 1, &gAllZero
);
2068 // Force Interrupt line to zero for cards that come up randomly
2070 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x3C, 1, &gAllZero
);
2074 Create and initialize general PCI I/O device instance for
2075 PCI device/bridge device/hotplug bridge device.
2077 @param Bridge Parent bridge instance.
2078 @param Pci Input Pci information block.
2079 @param Bus Device Bus NO.
2080 @param Device Device device NO.
2081 @param Func Device func NO.
2083 @return Instance of PCI device. NULL means no instance created.
2088 IN PCI_IO_DEVICE
*Bridge
,
2095 PCI_IO_DEVICE
*PciIoDevice
;
2096 EFI_PCI_IO_PROTOCOL
*PciIo
;
2099 PciIoDevice
= AllocateZeroPool (sizeof (PCI_IO_DEVICE
));
2100 if (PciIoDevice
== NULL
) {
2104 PciIoDevice
->Signature
= PCI_IO_DEVICE_SIGNATURE
;
2105 PciIoDevice
->Handle
= NULL
;
2106 PciIoDevice
->PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
2107 PciIoDevice
->DevicePath
= NULL
;
2108 PciIoDevice
->BusNumber
= Bus
;
2109 PciIoDevice
->DeviceNumber
= Device
;
2110 PciIoDevice
->FunctionNumber
= Func
;
2111 PciIoDevice
->Decodes
= 0;
2113 if (gFullEnumeration
) {
2114 PciIoDevice
->Allocated
= FALSE
;
2116 PciIoDevice
->Allocated
= TRUE
;
2119 PciIoDevice
->Registered
= FALSE
;
2120 PciIoDevice
->Attributes
= 0;
2121 PciIoDevice
->Supports
= 0;
2122 PciIoDevice
->BusOverride
= FALSE
;
2123 PciIoDevice
->AllOpRomProcessed
= FALSE
;
2125 PciIoDevice
->IsPciExp
= FALSE
;
2127 CopyMem (&(PciIoDevice
->Pci
), Pci
, sizeof (PCI_TYPE01
));
2130 // Initialize the PCI I/O instance structure
2132 InitializePciIoInstance (PciIoDevice
);
2133 InitializePciDriverOverrideInstance (PciIoDevice
);
2134 InitializePciLoadFile2 (PciIoDevice
);
2135 PciIo
= &PciIoDevice
->PciIo
;
2138 // Create a device path for this PCI device and store it into its private data
2140 CreatePciDevicePath (
2146 // Detect if PCI Express Device
2148 PciIoDevice
->PciExpressCapabilityOffset
= 0;
2149 Status
= LocateCapabilityRegBlock (
2151 EFI_PCI_CAPABILITY_ID_PCIEXP
,
2152 &PciIoDevice
->PciExpressCapabilityOffset
,
2155 if (!EFI_ERROR (Status
)) {
2156 PciIoDevice
->IsPciExp
= TRUE
;
2159 if (PcdGetBool (PcdAriSupport
)) {
2161 // Check if the device is an ARI device.
2163 Status
= LocatePciExpressCapabilityRegBlock (
2165 EFI_PCIE_CAPABILITY_ID_ARI
,
2166 &PciIoDevice
->AriCapabilityOffset
,
2169 if (!EFI_ERROR (Status
)) {
2171 // We need to enable ARI feature before calculate BusReservation,
2172 // because FirstVFOffset and VFStride may change after that.
2174 EFI_PCI_IO_PROTOCOL
*ParentPciIo
;
2178 // Check if its parent supports ARI forwarding.
2180 ParentPciIo
= &Bridge
->PciIo
;
2181 ParentPciIo
->Pci
.Read (
2183 EfiPciIoWidthUint32
,
2184 Bridge
->PciExpressCapabilityOffset
+ EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_OFFSET
,
2188 if ((Data32
& EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_ARI_FORWARDING
) != 0) {
2190 // ARI forward support in bridge, so enable it.
2192 ParentPciIo
->Pci
.Read (
2194 EfiPciIoWidthUint32
,
2195 Bridge
->PciExpressCapabilityOffset
+ EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET
,
2199 if ((Data32
& EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING
) == 0) {
2200 Data32
|= EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING
;
2201 ParentPciIo
->Pci
.Write (
2203 EfiPciIoWidthUint32
,
2204 Bridge
->PciExpressCapabilityOffset
+ EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET
,
2210 " ARI: forwarding enabled for PPB[%02x:%02x:%02x]\n",
2212 Bridge
->DeviceNumber
,
2213 Bridge
->FunctionNumber
2218 DEBUG ((EFI_D_INFO
, " ARI: CapOffset = 0x%x\n", PciIoDevice
->AriCapabilityOffset
));
2223 // Initialization for SR-IOV
2226 if (PcdGetBool (PcdSrIovSupport
)) {
2227 Status
= LocatePciExpressCapabilityRegBlock (
2229 EFI_PCIE_CAPABILITY_ID_SRIOV
,
2230 &PciIoDevice
->SrIovCapabilityOffset
,
2233 if (!EFI_ERROR (Status
)) {
2234 UINT32 SupportedPageSize
;
2236 UINT16 FirstVFOffset
;
2242 // If the SR-IOV device is an ARI device, then Set ARI Capable Hierarchy for the device.
2244 if (PcdGetBool (PcdAriSupport
) && PciIoDevice
->AriCapabilityOffset
!= 0) {
2247 EfiPciIoWidthUint16
,
2248 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL
,
2252 Data16
|= EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL_ARI_HIERARCHY
;
2255 EfiPciIoWidthUint16
,
2256 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL
,
2263 // Calculate SystemPageSize
2268 EfiPciIoWidthUint32
,
2269 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_SUPPORTED_PAGE_SIZE
,
2273 PciIoDevice
->SystemPageSize
= (PcdGet32 (PcdSrIovSystemPageSize
) & SupportedPageSize
);
2274 ASSERT (PciIoDevice
->SystemPageSize
!= 0);
2278 EfiPciIoWidthUint32
,
2279 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_SYSTEM_PAGE_SIZE
,
2281 &PciIoDevice
->SystemPageSize
2284 // Adjust SystemPageSize for Alignment usage later
2286 PciIoDevice
->SystemPageSize
<<= 12;
2289 // Calculate BusReservation for PCI IOV
2293 // Read First FirstVFOffset, InitialVFs, and VFStride
2297 EfiPciIoWidthUint16
,
2298 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_FIRSTVF
,
2304 EfiPciIoWidthUint16
,
2305 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_INITIALVFS
,
2307 &PciIoDevice
->InitialVFs
2311 EfiPciIoWidthUint16
,
2312 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_VFSTRIDE
,
2319 PFRid
= EFI_PCI_RID(Bus
, Device
, Func
);
2320 LastVF
= PFRid
+ FirstVFOffset
+ (PciIoDevice
->InitialVFs
- 1) * VFStride
;
2323 // Calculate ReservedBusNum for this PF
2325 PciIoDevice
->ReservedBusNum
= (UINT16
)(EFI_PCI_BUS_OF_RID (LastVF
) - Bus
+ 1);
2329 " SR-IOV: SupportedPageSize = 0x%x; SystemPageSize = 0x%x; FirstVFOffset = 0x%x;\n",
2330 SupportedPageSize
, PciIoDevice
->SystemPageSize
>> 12, FirstVFOffset
2334 " InitialVFs = 0x%x; ReservedBusNum = 0x%x; CapOffset = 0x%x\n",
2335 PciIoDevice
->InitialVFs
, PciIoDevice
->ReservedBusNum
, PciIoDevice
->SrIovCapabilityOffset
2340 if (PcdGetBool (PcdMrIovSupport
)) {
2341 Status
= LocatePciExpressCapabilityRegBlock (
2343 EFI_PCIE_CAPABILITY_ID_MRIOV
,
2344 &PciIoDevice
->MrIovCapabilityOffset
,
2347 if (!EFI_ERROR (Status
)) {
2348 DEBUG ((EFI_D_INFO
, " MR-IOV: CapOffset = 0x%x\n", PciIoDevice
->MrIovCapabilityOffset
));
2353 // Initialize the reserved resource list
2355 InitializeListHead (&PciIoDevice
->ReservedResourceList
);
2358 // Initialize the driver list
2360 InitializeListHead (&PciIoDevice
->OptionRomDriverList
);
2363 // Initialize the child list
2365 InitializeListHead (&PciIoDevice
->ChildList
);
2371 This routine is used to enumerate entire pci bus system
2372 in a given platform.
2374 It is only called on the second start on the same Root Bridge.
2376 @param Controller Parent bridge handler.
2378 @retval EFI_SUCCESS PCI enumeration finished successfully.
2379 @retval other Some error occurred when enumerating the pci bus system.
2383 PciEnumeratorLight (
2384 IN EFI_HANDLE Controller
2389 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2390 PCI_IO_DEVICE
*RootBridgeDev
;
2393 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
2396 MaxBus
= PCI_MAX_BUS
;
2400 // If this root bridge has been already enumerated, then return successfully
2402 if (GetRootBridgeByHandle (Controller
) != NULL
) {
2407 // Open pci root bridge io protocol
2409 Status
= gBS
->OpenProtocol (
2411 &gEfiPciRootBridgeIoProtocolGuid
,
2412 (VOID
**) &PciRootBridgeIo
,
2413 gPciBusDriverBinding
.DriverBindingHandle
,
2415 EFI_OPEN_PROTOCOL_BY_DRIVER
2417 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
2421 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
2423 if (EFI_ERROR (Status
)) {
2427 while (PciGetBusRange (&Descriptors
, &MinBus
, &MaxBus
, NULL
) == EFI_SUCCESS
) {
2430 // Create a device node for root bridge device with a NULL host bridge controller handle
2432 RootBridgeDev
= CreateRootBridge (Controller
);
2434 if (RootBridgeDev
== NULL
) {
2440 // Record the root bridge-io protocol
2442 RootBridgeDev
->PciRootBridgeIo
= PciRootBridgeIo
;
2444 Status
= PciPciDeviceInfoCollector (
2449 if (!EFI_ERROR (Status
)) {
2452 // Remove those PCI devices which are rejected when full enumeration
2454 RemoveRejectedPciDevices (RootBridgeDev
->Handle
, RootBridgeDev
);
2457 // Process option rom light
2459 ProcessOptionRomLight (RootBridgeDev
);
2462 // Determine attributes for all devices under this root bridge
2464 DetermineDeviceAttribute (RootBridgeDev
);
2467 // If successfully, insert the node into device pool
2469 InsertRootBridge (RootBridgeDev
);
2473 // If unsuccessfully, destroy the entire node
2475 DestroyRootBridge (RootBridgeDev
);
2485 Get bus range from PCI resource descriptor list.
2487 @param Descriptors A pointer to the address space descriptor.
2488 @param MinBus The min bus returned.
2489 @param MaxBus The max bus returned.
2490 @param BusRange The bus range returned.
2492 @retval EFI_SUCCESS Successfully got bus range.
2493 @retval EFI_NOT_FOUND Can not find the specific bus.
2498 IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
**Descriptors
,
2501 OUT UINT16
*BusRange
2504 while ((*Descriptors
)->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
2505 if ((*Descriptors
)->ResType
== ACPI_ADDRESS_SPACE_TYPE_BUS
) {
2506 if (MinBus
!= NULL
) {
2507 *MinBus
= (UINT16
) (*Descriptors
)->AddrRangeMin
;
2510 if (MaxBus
!= NULL
) {
2511 *MaxBus
= (UINT16
) (*Descriptors
)->AddrRangeMax
;
2514 if (BusRange
!= NULL
) {
2515 *BusRange
= (UINT16
) (*Descriptors
)->AddrLen
;
2524 return EFI_NOT_FOUND
;
2528 This routine can be used to start the root bridge.
2530 @param RootBridgeDev Pci device instance.
2532 @retval EFI_SUCCESS This device started.
2533 @retval other Failed to get PCI Root Bridge I/O protocol.
2537 StartManagingRootBridge (
2538 IN PCI_IO_DEVICE
*RootBridgeDev
2541 EFI_HANDLE RootBridgeHandle
;
2543 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2546 // Get the root bridge handle
2548 RootBridgeHandle
= RootBridgeDev
->Handle
;
2549 PciRootBridgeIo
= NULL
;
2552 // Get the pci root bridge io protocol
2554 Status
= gBS
->OpenProtocol (
2556 &gEfiPciRootBridgeIoProtocolGuid
,
2557 (VOID
**) &PciRootBridgeIo
,
2558 gPciBusDriverBinding
.DriverBindingHandle
,
2560 EFI_OPEN_PROTOCOL_BY_DRIVER
2563 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
2568 // Store the PciRootBridgeIo protocol into root bridge private data
2570 RootBridgeDev
->PciRootBridgeIo
= PciRootBridgeIo
;
2577 This routine can be used to check whether a PCI device should be rejected when light enumeration.
2579 @param PciIoDevice Pci device instance.
2581 @retval TRUE This device should be rejected.
2582 @retval FALSE This device shouldn't be rejected.
2586 IsPciDeviceRejected (
2587 IN PCI_IO_DEVICE
*PciIoDevice
2597 // PPB should be skip!
2599 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
)) {
2603 if (IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
2605 // Only test base registers for P2C
2607 for (BarOffset
= 0x1C; BarOffset
<= 0x38; BarOffset
+= 2 * sizeof (UINT32
)) {
2609 Mask
= (BarOffset
< 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC;
2610 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
2611 if (EFI_ERROR (Status
)) {
2615 TestValue
= TestValue
& Mask
;
2616 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2618 // The bar isn't programed, so it should be rejected
2627 for (BarOffset
= 0x14; BarOffset
<= 0x24; BarOffset
+= sizeof (UINT32
)) {
2631 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
2632 if (EFI_ERROR (Status
)) {
2636 if ((TestValue
& 0x01) != 0) {
2642 TestValue
= TestValue
& Mask
;
2643 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2653 TestValue
= TestValue
& Mask
;
2655 if ((TestValue
& 0x07) == 0x04) {
2660 BarOffset
+= sizeof (UINT32
);
2661 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2664 // Test its high 32-Bit BAR
2666 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
2667 if (TestValue
== OldValue
) {
2677 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2688 Reset all bus number from specific bridge.
2690 @param Bridge Parent specific bridge.
2691 @param StartBusNumber Start bus number.
2695 ResetAllPpbBusNumber (
2696 IN PCI_IO_DEVICE
*Bridge
,
2697 IN UINT8 StartBusNumber
2707 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2709 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
2711 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
2712 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
2715 // Check to see whether a pci device is present
2717 Status
= PciDevicePresent (
2725 if (EFI_ERROR (Status
) && Func
== 0) {
2727 // go to next device if there is no Function 0
2732 if (!EFI_ERROR (Status
) && (IS_PCI_BRIDGE (&Pci
))) {
2735 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
2736 Status
= PciRootBridgeIo
->Pci
.Read (
2743 SecondaryBus
= (UINT8
)(Register
>> 8);
2745 if (SecondaryBus
!= 0) {
2746 ResetAllPpbBusNumber (Bridge
, SecondaryBus
);
2750 // Reset register 18h, 19h, 1Ah on PCI Bridge
2752 Register
&= 0xFF000000;
2753 Status
= PciRootBridgeIo
->Pci
.Write (
2762 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
2764 // Skip sub functions, this is not a multi function device
2766 Func
= PCI_MAX_FUNC
;