2 PCI emumeration support functions implementation for PCI Bus module.
4 Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 extern CHAR16
*mBarTypeStr
[];
20 #define OLD_ALIGN 0xFFFFFFFFFFFFFFFFULL
21 #define EVEN_ALIGN 0xFFFFFFFFFFFFFFFEULL
22 #define SQUAD_ALIGN 0xFFFFFFFFFFFFFFFDULL
23 #define DQUAD_ALIGN 0xFFFFFFFFFFFFFFFCULL
26 This routine is used to check whether the pci device is present.
28 @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
29 @param Pci Output buffer for PCI device configuration space.
30 @param Bus PCI bus NO.
31 @param Device PCI device NO.
32 @param Func PCI Func NO.
34 @retval EFI_NOT_FOUND PCI device not present.
35 @retval EFI_SUCCESS PCI device is found.
40 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
51 // Create PCI address map in terms of Bus, Device and Func
53 Address
= EFI_PCI_ADDRESS (Bus
, Device
, Func
, 0);
56 // Read the Vendor ID register
58 Status
= PciRootBridgeIo
->Pci
.Read (
66 if (!EFI_ERROR (Status
) && (Pci
->Hdr
).VendorId
!= 0xffff) {
68 // Read the entire config header for the device
70 Status
= PciRootBridgeIo
->Pci
.Read (
74 sizeof (PCI_TYPE00
) / sizeof (UINT32
),
85 Collect all the resource information under this root bridge.
87 A database that records all the information about pci device subject to this
88 root bridge will then be created.
90 @param Bridge Parent bridge instance.
91 @param StartBusNumber Bus number of begining.
93 @retval EFI_SUCCESS PCI device is found.
94 @retval other Some error occurred when reading PCI bridge information.
98 PciPciDeviceInfoCollector (
99 IN PCI_IO_DEVICE
*Bridge
,
100 IN UINT8 StartBusNumber
108 PCI_IO_DEVICE
*PciIoDevice
;
109 EFI_PCI_IO_PROTOCOL
*PciIo
;
111 Status
= EFI_SUCCESS
;
114 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
116 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
119 // Check to see whether PCI device is present
121 Status
= PciDevicePresent (
122 Bridge
->PciRootBridgeIo
,
124 (UINT8
) StartBusNumber
,
129 if (EFI_ERROR (Status
) && Func
== 0) {
131 // go to next device if there is no Function 0
136 if (!EFI_ERROR (Status
)) {
139 // Call back to host bridge function
141 PreprocessController (Bridge
, (UINT8
) StartBusNumber
, Device
, Func
, EfiPciBeforeResourceCollection
);
144 // Collect all the information about the PCI device discovered
146 Status
= PciSearchDevice (
149 (UINT8
) StartBusNumber
,
156 // Recursively scan PCI busses on the other side of PCI-PCI bridges
159 if (!EFI_ERROR (Status
) && (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
))) {
162 // If it is PPB, we need to get the secondary bus to continue the enumeration
164 PciIo
= &(PciIoDevice
->PciIo
);
166 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET
, 1, &SecBus
);
168 if (EFI_ERROR (Status
)) {
173 // Ensure secondary bus number is greater than the primary bus number to avoid
174 // any potential dead loop when PcdPciDisableBusEnumeration is set to TRUE
176 if (SecBus
<= StartBusNumber
) {
181 // Get resource padding for PPB
183 GetResourcePaddingPpb (PciIoDevice
);
186 // Deep enumerate the next level bus
188 Status
= PciPciDeviceInfoCollector (
195 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
198 // Skip sub functions, this is not a multi function device
211 Seach required device and create PCI device instance.
213 @param Bridge Parent bridge instance.
214 @param Pci Input PCI device information block.
215 @param Bus PCI bus NO.
216 @param Device PCI device NO.
217 @param Func PCI func NO.
218 @param PciDevice Output of searched PCI device instance.
220 @retval EFI_SUCCESS Successfully created PCI device instance.
221 @retval EFI_OUT_OF_RESOURCES Cannot get PCI device information.
226 IN PCI_IO_DEVICE
*Bridge
,
231 OUT PCI_IO_DEVICE
**PciDevice
234 PCI_IO_DEVICE
*PciIoDevice
;
240 "PciBus: Discovered %s @ [%02x|%02x|%02x]\n",
241 IS_PCI_BRIDGE (Pci
) ? L
"PPB" :
242 IS_CARDBUS_BRIDGE (Pci
) ? L
"P2C" :
247 if (!IS_PCI_BRIDGE (Pci
)) {
249 if (IS_CARDBUS_BRIDGE (Pci
)) {
250 PciIoDevice
= GatherP2CInfo (
257 if ((PciIoDevice
!= NULL
) && gFullEnumeration
) {
258 InitializeP2C (PciIoDevice
);
263 // Create private data for Pci Device
265 PciIoDevice
= GatherDeviceInfo (
278 // Create private data for PPB
280 PciIoDevice
= GatherPpbInfo (
289 // Special initialization for PPB including making the PPB quiet
291 if ((PciIoDevice
!= NULL
) && gFullEnumeration
) {
292 InitializePpb (PciIoDevice
);
296 if (PciIoDevice
== NULL
) {
297 return EFI_OUT_OF_RESOURCES
;
301 // Update the bar information for this PCI device so as to support some specific device
303 UpdatePciInfo (PciIoDevice
);
305 if (PciIoDevice
->DevicePath
== NULL
) {
306 return EFI_OUT_OF_RESOURCES
;
310 // Detect this function has option rom
312 if (gFullEnumeration
) {
314 if (!IS_CARDBUS_BRIDGE (Pci
)) {
316 GetOpRomInfo (PciIoDevice
);
320 ResetPowerManagementFeature (PciIoDevice
);
325 // Insert it into a global tree for future reference
327 InsertPciDevice (Bridge
, PciIoDevice
);
330 // Determine PCI device attributes
333 if (PciDevice
!= NULL
) {
334 *PciDevice
= PciIoDevice
;
341 Dump the PPB padding resource information.
343 @param PciIoDevice PCI IO instance.
344 @param ResourceType The desired resource type to dump.
345 PciBarTypeUnknown means to dump all types of resources.
348 DumpPpbPaddingResource (
349 IN PCI_IO_DEVICE
*PciIoDevice
,
350 IN PCI_BAR_TYPE ResourceType
353 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
356 if (PciIoDevice
->ResourcePaddingDescriptors
== NULL
) {
360 if (ResourceType
== PciBarTypeIo16
|| ResourceType
== PciBarTypeIo32
) {
361 ResourceType
= PciBarTypeIo
;
364 for (Descriptor
= PciIoDevice
->ResourcePaddingDescriptors
; Descriptor
->Desc
!= ACPI_END_TAG_DESCRIPTOR
; Descriptor
++) {
366 Type
= PciBarTypeUnknown
;
367 if (Descriptor
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
&& Descriptor
->ResType
== ACPI_ADDRESS_SPACE_TYPE_IO
) {
369 } else if (Descriptor
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
&& Descriptor
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
) {
371 if (Descriptor
->AddrSpaceGranularity
== 32) {
375 if (Descriptor
->SpecificFlag
== EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) {
376 Type
= PciBarTypePMem32
;
382 if (Descriptor
->SpecificFlag
== 0) {
383 Type
= PciBarTypeMem32
;
387 if (Descriptor
->AddrSpaceGranularity
== 64) {
391 if (Descriptor
->SpecificFlag
== EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) {
392 Type
= PciBarTypePMem64
;
398 if (Descriptor
->SpecificFlag
== 0) {
399 Type
= PciBarTypeMem64
;
404 if ((Type
!= PciBarTypeUnknown
) && ((ResourceType
== PciBarTypeUnknown
) || (ResourceType
== Type
))) {
407 " Padding: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx\n",
408 mBarTypeStr
[Type
], Descriptor
->AddrRangeMax
, Descriptor
->AddrLen
416 Dump the PCI BAR information.
418 @param PciIoDevice PCI IO instance.
422 IN PCI_IO_DEVICE
*PciIoDevice
427 for (Index
= 0; Index
< PCI_MAX_BAR
; Index
++) {
428 if (PciIoDevice
->PciBar
[Index
].BarType
== PciBarTypeUnknown
) {
434 " BAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n",
435 Index
, mBarTypeStr
[MIN (PciIoDevice
->PciBar
[Index
].BarType
, PciBarTypeMaxType
)],
436 PciIoDevice
->PciBar
[Index
].Alignment
, PciIoDevice
->PciBar
[Index
].Length
, PciIoDevice
->PciBar
[Index
].Offset
440 for (Index
= 0; Index
< PCI_MAX_BAR
; Index
++) {
441 if ((PciIoDevice
->VfPciBar
[Index
].BarType
== PciBarTypeUnknown
) && (PciIoDevice
->VfPciBar
[Index
].Length
== 0)) {
447 " VFBAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n",
448 Index
, mBarTypeStr
[MIN (PciIoDevice
->VfPciBar
[Index
].BarType
, PciBarTypeMaxType
)],
449 PciIoDevice
->VfPciBar
[Index
].Alignment
, PciIoDevice
->VfPciBar
[Index
].Length
, PciIoDevice
->VfPciBar
[Index
].Offset
452 DEBUG ((EFI_D_INFO
, "\n"));
456 Create PCI device instance for PCI device.
458 @param Bridge Parent bridge instance.
459 @param Pci Input PCI device information block.
460 @param Bus PCI device Bus NO.
461 @param Device PCI device Device NO.
462 @param Func PCI device's func NO.
464 @return Created PCI device instance.
469 IN PCI_IO_DEVICE
*Bridge
,
478 PCI_IO_DEVICE
*PciIoDevice
;
480 PciIoDevice
= CreatePciIoDevice (
488 if (PciIoDevice
== NULL
) {
493 // If it is a full enumeration, disconnect the device in advance
495 if (gFullEnumeration
) {
497 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
502 // Start to parse the bars
504 for (Offset
= 0x10, BarIndex
= 0; Offset
<= 0x24 && BarIndex
< PCI_MAX_BAR
; BarIndex
++) {
505 Offset
= PciParseBar (PciIoDevice
, Offset
, BarIndex
);
509 // Parse the SR-IOV VF bars
511 if (PcdGetBool (PcdSrIovSupport
) && PciIoDevice
->SrIovCapabilityOffset
!= 0) {
512 for (Offset
= PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_BAR0
, BarIndex
= 0;
513 Offset
<= PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_BAR5
;
516 ASSERT (BarIndex
< PCI_MAX_BAR
);
517 Offset
= PciIovParseVfBar (PciIoDevice
, Offset
, BarIndex
);
521 DEBUG_CODE (DumpPciBars (PciIoDevice
););
526 Create PCI device instance for PCI-PCI bridge.
528 @param Bridge Parent bridge instance.
529 @param Pci Input PCI device information block.
530 @param Bus PCI device Bus NO.
531 @param Device PCI device Device NO.
532 @param Func PCI device's func NO.
534 @return Created PCI device instance.
539 IN PCI_IO_DEVICE
*Bridge
,
546 PCI_IO_DEVICE
*PciIoDevice
;
549 EFI_PCI_IO_PROTOCOL
*PciIo
;
551 UINT32 PMemBaseLimit
;
552 UINT16 PrefetchableMemoryBase
;
553 UINT16 PrefetchableMemoryLimit
;
555 PciIoDevice
= CreatePciIoDevice (
563 if (PciIoDevice
== NULL
) {
567 if (gFullEnumeration
) {
568 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
571 // Initalize the bridge control register
573 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED
);
578 // PPB can have two BARs
580 if (PciParseBar (PciIoDevice
, 0x10, PPB_BAR_0
) == 0x14) {
584 PciParseBar (PciIoDevice
, 0x14, PPB_BAR_1
);
587 PciIo
= &PciIoDevice
->PciIo
;
590 // Test whether it support 32 decode or not
592 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Temp
);
593 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &gAllOne
);
594 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Value
);
595 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Temp
);
598 if ((Value
& 0x01) != 0) {
599 PciIoDevice
->Decodes
|= EFI_BRIDGE_IO32_DECODE_SUPPORTED
;
601 PciIoDevice
->Decodes
|= EFI_BRIDGE_IO16_DECODE_SUPPORTED
;
606 // if PcdPciBridgeIoAlignmentProbe is TRUE, PCI bus driver probes
607 // PCI bridge supporting non-standard I/O window alignment less than 4K.
610 PciIoDevice
->BridgeIoAlignment
= 0xFFF;
611 if (FeaturePcdGet (PcdPciBridgeIoAlignmentProbe
)) {
613 // Check any bits of bit 3-1 of I/O Base Register are writable.
614 // if so, it is assumed non-standard I/O window alignment is supported by this bridge.
615 // Per spec, bit 3-1 of I/O Base Register are reserved bits, so its content can't be assumed.
617 Value
= (UINT8
)(Temp
^ (BIT3
| BIT2
| BIT1
));
618 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Value
);
619 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Value
);
620 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Temp
);
621 Value
= (UINT8
)((Value
^ Temp
) & (BIT3
| BIT2
| BIT1
));
624 PciIoDevice
->BridgeIoAlignment
= 0x7FF;
627 PciIoDevice
->BridgeIoAlignment
= 0x3FF;
629 case BIT3
| BIT2
| BIT1
:
630 PciIoDevice
->BridgeIoAlignment
= 0x1FF;
635 Status
= BarExisted (
643 // Test if it supports 64 memory or not
645 // The bottom 4 bits of both the Prefetchable Memory Base and Prefetchable Memory Limit
647 // 0 - the bridge supports only 32 bit addresses.
648 // 1 - the bridge supports 64-bit addresses.
650 PrefetchableMemoryBase
= (UINT16
)(PMemBaseLimit
& 0xffff);
651 PrefetchableMemoryLimit
= (UINT16
)(PMemBaseLimit
>> 16);
652 if (!EFI_ERROR (Status
) &&
653 (PrefetchableMemoryBase
& 0x000f) == 0x0001 &&
654 (PrefetchableMemoryLimit
& 0x000f) == 0x0001) {
655 Status
= BarExisted (
662 if (!EFI_ERROR (Status
)) {
663 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
664 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED
;
666 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
671 // Memory 32 code is required for ppb
673 PciIoDevice
->Decodes
|= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
;
675 GetResourcePaddingPpb (PciIoDevice
);
678 DumpPpbPaddingResource (PciIoDevice
, PciBarTypeUnknown
);
679 DumpPciBars (PciIoDevice
);
687 Create PCI device instance for PCI Card bridge device.
689 @param Bridge Parent bridge instance.
690 @param Pci Input PCI device information block.
691 @param Bus PCI device Bus NO.
692 @param Device PCI device Device NO.
693 @param Func PCI device's func NO.
695 @return Created PCI device instance.
700 IN PCI_IO_DEVICE
*Bridge
,
707 PCI_IO_DEVICE
*PciIoDevice
;
709 PciIoDevice
= CreatePciIoDevice (
717 if (PciIoDevice
== NULL
) {
721 if (gFullEnumeration
) {
722 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
725 // Initalize the bridge control register
727 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED
);
731 // P2C only has one bar that is in 0x10
733 PciParseBar (PciIoDevice
, 0x10, P2C_BAR_0
);
736 // Read PciBar information from the bar register
738 GetBackPcCardBar (PciIoDevice
);
739 PciIoDevice
->Decodes
= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
|
740 EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
|
741 EFI_BRIDGE_IO32_DECODE_SUPPORTED
;
743 DEBUG_CODE (DumpPciBars (PciIoDevice
););
749 Create device path for pci deivce.
751 @param ParentDevicePath Parent bridge's path.
752 @param PciIoDevice Pci device instance.
754 @return Device path protocol instance for specific pci device.
757 EFI_DEVICE_PATH_PROTOCOL
*
758 CreatePciDevicePath (
759 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
760 IN PCI_IO_DEVICE
*PciIoDevice
764 PCI_DEVICE_PATH PciNode
;
767 // Create PCI device path
769 PciNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
770 PciNode
.Header
.SubType
= HW_PCI_DP
;
771 SetDevicePathNodeLength (&PciNode
.Header
, sizeof (PciNode
));
773 PciNode
.Device
= PciIoDevice
->DeviceNumber
;
774 PciNode
.Function
= PciIoDevice
->FunctionNumber
;
775 PciIoDevice
->DevicePath
= AppendDevicePathNode (ParentDevicePath
, &PciNode
.Header
);
777 return PciIoDevice
->DevicePath
;
781 Check whether the PCI IOV VF bar is existed or not.
783 @param PciIoDevice A pointer to the PCI_IO_DEVICE.
784 @param Offset The offset.
785 @param BarLengthValue The bar length value returned.
786 @param OriginalBarValue The original bar value returned.
788 @retval EFI_NOT_FOUND The bar doesn't exist.
789 @retval EFI_SUCCESS The bar exist.
794 IN PCI_IO_DEVICE
*PciIoDevice
,
796 OUT UINT32
*BarLengthValue
,
797 OUT UINT32
*OriginalBarValue
800 EFI_PCI_IO_PROTOCOL
*PciIo
;
801 UINT32 OriginalValue
;
806 // Ensure it is called properly
808 ASSERT (PciIoDevice
->SrIovCapabilityOffset
!= 0);
809 if (PciIoDevice
->SrIovCapabilityOffset
== 0) {
810 return EFI_NOT_FOUND
;
813 PciIo
= &PciIoDevice
->PciIo
;
816 // Preserve the original value
819 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, (UINT32
)Offset
, 1, &OriginalValue
);
822 // Raise TPL to high level to disable timer interrupt while the BAR is probed
824 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
826 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, (UINT32
)Offset
, 1, &gAllOne
);
827 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, (UINT32
)Offset
, 1, &Value
);
830 // Write back the original value
832 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, (UINT32
)Offset
, 1, &OriginalValue
);
835 // Restore TPL to its original level
837 gBS
->RestoreTPL (OldTpl
);
839 if (BarLengthValue
!= NULL
) {
840 *BarLengthValue
= Value
;
843 if (OriginalBarValue
!= NULL
) {
844 *OriginalBarValue
= OriginalValue
;
848 return EFI_NOT_FOUND
;
855 Check whether the bar is existed or not.
857 @param PciIoDevice A pointer to the PCI_IO_DEVICE.
858 @param Offset The offset.
859 @param BarLengthValue The bar length value returned.
860 @param OriginalBarValue The original bar value returned.
862 @retval EFI_NOT_FOUND The bar doesn't exist.
863 @retval EFI_SUCCESS The bar exist.
868 IN PCI_IO_DEVICE
*PciIoDevice
,
870 OUT UINT32
*BarLengthValue
,
871 OUT UINT32
*OriginalBarValue
874 EFI_PCI_IO_PROTOCOL
*PciIo
;
875 UINT32 OriginalValue
;
879 PciIo
= &PciIoDevice
->PciIo
;
882 // Preserve the original value
884 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &OriginalValue
);
887 // Raise TPL to high level to disable timer interrupt while the BAR is probed
889 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
891 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &gAllOne
);
892 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &Value
);
895 // Write back the original value
897 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &OriginalValue
);
900 // Restore TPL to its original level
902 gBS
->RestoreTPL (OldTpl
);
904 if (BarLengthValue
!= NULL
) {
905 *BarLengthValue
= Value
;
908 if (OriginalBarValue
!= NULL
) {
909 *OriginalBarValue
= OriginalValue
;
913 return EFI_NOT_FOUND
;
920 Test whether the device can support given attributes.
922 @param PciIoDevice Pci device instance.
923 @param Command Input command register value, and
924 returned supported register value.
925 @param BridgeControl Inout bridge control value for PPB or P2C, and
926 returned supported bridge control value.
927 @param OldCommand Returned and stored old command register offset.
928 @param OldBridgeControl Returned and stored old Bridge control value for PPB or P2C.
932 PciTestSupportedAttribute (
933 IN PCI_IO_DEVICE
*PciIoDevice
,
934 IN OUT UINT16
*Command
,
935 IN OUT UINT16
*BridgeControl
,
936 OUT UINT16
*OldCommand
,
937 OUT UINT16
*OldBridgeControl
943 // Preserve the original value
945 PCI_READ_COMMAND_REGISTER (PciIoDevice
, OldCommand
);
948 // Raise TPL to high level to disable timer interrupt while the BAR is probed
950 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
952 PCI_SET_COMMAND_REGISTER (PciIoDevice
, *Command
);
953 PCI_READ_COMMAND_REGISTER (PciIoDevice
, Command
);
956 // Write back the original value
958 PCI_SET_COMMAND_REGISTER (PciIoDevice
, *OldCommand
);
961 // Restore TPL to its original level
963 gBS
->RestoreTPL (OldTpl
);
965 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
) || IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
968 // Preserve the original value
970 PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice
, OldBridgeControl
);
973 // Raise TPL to high level to disable timer interrupt while the BAR is probed
975 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
977 PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice
, *BridgeControl
);
978 PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice
, BridgeControl
);
981 // Write back the original value
983 PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice
, *OldBridgeControl
);
986 // Restore TPL to its original level
988 gBS
->RestoreTPL (OldTpl
);
991 *OldBridgeControl
= 0;
997 Set the supported or current attributes of a PCI device.
999 @param PciIoDevice Structure pointer for PCI device.
1000 @param Command Command register value.
1001 @param BridgeControl Bridge control value for PPB or P2C.
1002 @param Option Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES.
1006 PciSetDeviceAttribute (
1007 IN PCI_IO_DEVICE
*PciIoDevice
,
1009 IN UINT16 BridgeControl
,
1017 if ((Command
& EFI_PCI_COMMAND_IO_SPACE
) != 0) {
1018 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IO
;
1021 if ((Command
& EFI_PCI_COMMAND_MEMORY_SPACE
) != 0) {
1022 Attributes
|= EFI_PCI_IO_ATTRIBUTE_MEMORY
;
1025 if ((Command
& EFI_PCI_COMMAND_BUS_MASTER
) != 0) {
1026 Attributes
|= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
;
1029 if ((Command
& EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
) != 0) {
1030 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
;
1033 if ((BridgeControl
& EFI_PCI_BRIDGE_CONTROL_ISA
) != 0) {
1034 Attributes
|= EFI_PCI_IO_ATTRIBUTE_ISA_IO
;
1037 if ((BridgeControl
& EFI_PCI_BRIDGE_CONTROL_VGA
) != 0) {
1038 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_IO
;
1039 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
;
1040 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
;
1043 if ((BridgeControl
& EFI_PCI_BRIDGE_CONTROL_VGA_16
) != 0) {
1044 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
;
1045 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16
;
1048 if (Option
== EFI_SET_SUPPORTS
) {
1050 Attributes
|= (UINT64
) (EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE
|
1051 EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED
|
1052 EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE
|
1053 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE
|
1054 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM
|
1055 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
);
1057 if (IS_PCI_LPC (&PciIoDevice
->Pci
)) {
1058 Attributes
|= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO
;
1059 Attributes
|= (mReserveIsaAliases
? (UINT64
) EFI_PCI_IO_ATTRIBUTE_ISA_IO
: \
1060 (UINT64
) EFI_PCI_IO_ATTRIBUTE_ISA_IO_16
);
1063 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
) || IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
1065 // For bridge, it should support IDE attributes
1067 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO
;
1068 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO
;
1070 if (mReserveVgaAliases
) {
1071 Attributes
&= ~(UINT64
)(EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
| \
1072 EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16
);
1074 Attributes
&= ~(UINT64
)(EFI_PCI_IO_ATTRIBUTE_VGA_IO
| \
1075 EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
);
1079 if (IS_PCI_IDE (&PciIoDevice
->Pci
)) {
1080 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO
;
1081 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO
;
1084 if (IS_PCI_VGA (&PciIoDevice
->Pci
)) {
1085 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
;
1086 Attributes
|= (mReserveVgaAliases
? (UINT64
) EFI_PCI_IO_ATTRIBUTE_VGA_IO
: \
1087 (UINT64
) EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
);
1091 PciIoDevice
->Supports
= Attributes
;
1092 PciIoDevice
->Supports
&= ( (PciIoDevice
->Parent
->Supports
) | \
1093 EFI_PCI_IO_ATTRIBUTE_IO
| EFI_PCI_IO_ATTRIBUTE_MEMORY
| \
1094 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
);
1098 // When this attribute is clear, the RomImage and RomSize fields in the PCI IO were
1099 // initialized based on the PCI option ROM found through the ROM BAR of the PCI controller.
1100 // When this attribute is set, the PCI option ROM described by the RomImage and RomSize
1101 // fields is not from the the ROM BAR of the PCI controller.
1103 if (!PciIoDevice
->EmbeddedRom
) {
1104 Attributes
|= EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM
;
1106 PciIoDevice
->Attributes
= Attributes
;
1111 Determine if the device can support Fast Back to Back attribute.
1113 @param PciIoDevice Pci device instance.
1114 @param StatusIndex Status register value.
1116 @retval EFI_SUCCESS This device support Fast Back to Back attribute.
1117 @retval EFI_UNSUPPORTED This device doesn't support Fast Back to Back attribute.
1121 GetFastBackToBackSupport (
1122 IN PCI_IO_DEVICE
*PciIoDevice
,
1123 IN UINT8 StatusIndex
1126 EFI_PCI_IO_PROTOCOL
*PciIo
;
1128 UINT32 StatusRegister
;
1131 // Read the status register
1133 PciIo
= &PciIoDevice
->PciIo
;
1134 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
, StatusIndex
, 1, &StatusRegister
);
1135 if (EFI_ERROR (Status
)) {
1136 return EFI_UNSUPPORTED
;
1140 // Check the Fast B2B bit
1142 if ((StatusRegister
& EFI_PCI_FAST_BACK_TO_BACK_CAPABLE
) != 0) {
1145 return EFI_UNSUPPORTED
;
1150 Process the option ROM for all the children of the specified parent PCI device.
1151 It can only be used after the first full Option ROM process.
1153 @param PciIoDevice Pci device instance.
1157 ProcessOptionRomLight (
1158 IN PCI_IO_DEVICE
*PciIoDevice
1161 PCI_IO_DEVICE
*Temp
;
1162 LIST_ENTRY
*CurrentLink
;
1165 // For RootBridge, PPB , P2C, go recursively to traverse all its children
1167 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
1168 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
1170 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1172 if (!IsListEmpty (&Temp
->ChildList
)) {
1173 ProcessOptionRomLight (Temp
);
1176 PciRomGetImageMapping (Temp
);
1179 // The OpRom has already been processed in the first round
1181 Temp
->AllOpRomProcessed
= TRUE
;
1183 CurrentLink
= CurrentLink
->ForwardLink
;
1188 Determine the related attributes of all devices under a Root Bridge.
1190 @param PciIoDevice PCI device instance.
1194 DetermineDeviceAttribute (
1195 IN PCI_IO_DEVICE
*PciIoDevice
1199 UINT16 BridgeControl
;
1201 UINT16 OldBridgeControl
;
1202 BOOLEAN FastB2BSupport
;
1203 PCI_IO_DEVICE
*Temp
;
1204 LIST_ENTRY
*CurrentLink
;
1208 // For Root Bridge, just copy it by RootBridgeIo proctocol
1209 // so as to keep consistent with the actual attribute
1211 if (PciIoDevice
->Parent
== NULL
) {
1212 Status
= PciIoDevice
->PciRootBridgeIo
->GetAttributes (
1213 PciIoDevice
->PciRootBridgeIo
,
1214 &PciIoDevice
->Supports
,
1215 &PciIoDevice
->Attributes
1217 if (EFI_ERROR (Status
)) {
1221 // Assume the PCI Root Bridge supports DAC and Bus Master.
1223 PciIoDevice
->Supports
|= (UINT64
)(EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE
|
1224 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM
|
1225 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
|
1226 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
);
1231 // Set the attributes to be checked for common PCI devices and PPB or P2C
1232 // Since some devices only support part of them, it is better to set the
1233 // attribute according to its command or bridge control register
1235 Command
= EFI_PCI_COMMAND_IO_SPACE
|
1236 EFI_PCI_COMMAND_MEMORY_SPACE
|
1237 EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
;
1240 // Per PCI-to-PCI Bridge Architecture all PCI-to-PCI bridges are Bus Master capable.
1241 // So only test the Bus Master capability for PCI devices.
1243 if (!IS_PCI_BRIDGE(&PciIoDevice
->Pci
)) {
1244 Command
|= EFI_PCI_COMMAND_BUS_MASTER
;
1247 BridgeControl
= EFI_PCI_BRIDGE_CONTROL_ISA
| EFI_PCI_BRIDGE_CONTROL_VGA
| EFI_PCI_BRIDGE_CONTROL_VGA_16
;
1250 // Test whether the device can support attributes above
1252 PciTestSupportedAttribute (PciIoDevice
, &Command
, &BridgeControl
, &OldCommand
, &OldBridgeControl
);
1255 // Set the supported attributes for specified PCI device
1256 // Per PCI-to-PCI Bridge Architecture all PCI-to-PCI bridges are Bus Master capable.
1258 if (IS_PCI_BRIDGE(&PciIoDevice
->Pci
)) {
1259 Command
|= EFI_PCI_COMMAND_BUS_MASTER
;
1261 PciSetDeviceAttribute (PciIoDevice
, Command
, BridgeControl
, EFI_SET_SUPPORTS
);
1264 // Set the current attributes for specified PCI device
1266 PciSetDeviceAttribute (PciIoDevice
, OldCommand
, OldBridgeControl
, EFI_SET_ATTRIBUTES
);
1269 // Enable other supported attributes but not defined in PCI_IO_PROTOCOL
1271 PCI_ENABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE
);
1274 FastB2BSupport
= TRUE
;
1277 // P2C can not support FB2B on the secondary side
1279 if (IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
1280 FastB2BSupport
= FALSE
;
1284 // For RootBridge, PPB , P2C, go recursively to traverse all its children
1286 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
1287 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
1289 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1290 Status
= DetermineDeviceAttribute (Temp
);
1291 if (EFI_ERROR (Status
)) {
1295 // Detect Fast Bact to Bact support for the device under the bridge
1297 Status
= GetFastBackToBackSupport (Temp
, PCI_PRIMARY_STATUS_OFFSET
);
1298 if (FastB2BSupport
&& EFI_ERROR (Status
)) {
1299 FastB2BSupport
= FALSE
;
1302 CurrentLink
= CurrentLink
->ForwardLink
;
1305 // Set or clear Fast Back to Back bit for the whole bridge
1307 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
1309 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
)) {
1311 Status
= GetFastBackToBackSupport (PciIoDevice
, PCI_BRIDGE_STATUS_REGISTER_OFFSET
);
1313 if (EFI_ERROR (Status
) || (!FastB2BSupport
)) {
1314 FastB2BSupport
= FALSE
;
1315 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK
);
1317 PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK
);
1321 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
1322 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
1323 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1324 if (FastB2BSupport
) {
1325 PCI_ENABLE_COMMAND_REGISTER (Temp
, EFI_PCI_COMMAND_FAST_BACK_TO_BACK
);
1327 PCI_DISABLE_COMMAND_REGISTER (Temp
, EFI_PCI_COMMAND_FAST_BACK_TO_BACK
);
1330 CurrentLink
= CurrentLink
->ForwardLink
;
1334 // End for IsListEmpty
1340 This routine is used to update the bar information for those incompatible PCI device.
1342 @param PciIoDevice Input Pci device instance. Output Pci device instance with updated
1345 @retval EFI_SUCCESS Successfully updated bar information.
1346 @retval EFI_UNSUPPORTED Given PCI device doesn't belong to incompatible PCI device list.
1351 IN OUT PCI_IO_DEVICE
*PciIoDevice
1357 VOID
*Configuration
;
1358 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1360 Configuration
= NULL
;
1361 Status
= EFI_SUCCESS
;
1363 if (gIncompatiblePciDeviceSupport
== NULL
) {
1365 // It can only be supported after the Incompatible PCI Device
1366 // Support Protocol has been installed
1368 Status
= gBS
->LocateProtocol (
1369 &gEfiIncompatiblePciDeviceSupportProtocolGuid
,
1371 (VOID
**) &gIncompatiblePciDeviceSupport
1374 if (Status
== EFI_SUCCESS
) {
1376 // Check whether the device belongs to incompatible devices from protocol or not
1377 // If it is , then get its special requirement in the ACPI table
1379 Status
= gIncompatiblePciDeviceSupport
->CheckDevice (
1380 gIncompatiblePciDeviceSupport
,
1381 PciIoDevice
->Pci
.Hdr
.VendorId
,
1382 PciIoDevice
->Pci
.Hdr
.DeviceId
,
1383 PciIoDevice
->Pci
.Hdr
.RevisionID
,
1384 PciIoDevice
->Pci
.Device
.SubsystemVendorID
,
1385 PciIoDevice
->Pci
.Device
.SubsystemID
,
1391 if (EFI_ERROR (Status
) || Configuration
== NULL
) {
1392 return EFI_UNSUPPORTED
;
1396 // Update PCI device information from the ACPI table
1398 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
;
1400 while (Ptr
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
1402 if (Ptr
->Desc
!= ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
1404 // The format is not support
1409 for (BarIndex
= 0; BarIndex
< PCI_MAX_BAR
; BarIndex
++) {
1410 if ((Ptr
->AddrTranslationOffset
!= MAX_UINT64
) &&
1411 (Ptr
->AddrTranslationOffset
!= MAX_UINT8
) &&
1412 (Ptr
->AddrTranslationOffset
!= BarIndex
)
1415 // Skip updating when AddrTranslationOffset is not MAX_UINT64 or MAX_UINT8 (wide match).
1416 // Skip updating when current BarIndex doesn't equal to AddrTranslationOffset.
1417 // Comparing against MAX_UINT8 is to keep backward compatibility.
1423 switch (Ptr
->ResType
) {
1424 case ACPI_ADDRESS_SPACE_TYPE_MEM
:
1427 // Make sure the bar is memory type
1429 if (CheckBarType (PciIoDevice
, (UINT8
) BarIndex
, PciBarTypeMem
)) {
1433 // Ignored if granularity is 0.
1434 // Ignored if PCI BAR is I/O or 32-bit memory.
1435 // If PCI BAR is 64-bit memory and granularity is 32, then
1436 // the PCI BAR resource is allocated below 4GB.
1437 // If PCI BAR is 64-bit memory and granularity is 64, then
1438 // the PCI BAR resource is allocated above 4GB.
1440 if (PciIoDevice
->PciBar
[BarIndex
].BarType
== PciBarTypeMem64
) {
1441 switch (Ptr
->AddrSpaceGranularity
) {
1443 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeMem32
;
1445 PciIoDevice
->PciBar
[BarIndex
].BarTypeFixed
= TRUE
;
1452 if (PciIoDevice
->PciBar
[BarIndex
].BarType
== PciBarTypePMem64
) {
1453 switch (Ptr
->AddrSpaceGranularity
) {
1455 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypePMem32
;
1457 PciIoDevice
->PciBar
[BarIndex
].BarTypeFixed
= TRUE
;
1466 case ACPI_ADDRESS_SPACE_TYPE_IO
:
1469 // Make sure the bar is IO type
1471 if (CheckBarType (PciIoDevice
, (UINT8
) BarIndex
, PciBarTypeIo
)) {
1480 // Update the new alignment for the device
1482 SetNewAlign (&(PciIoDevice
->PciBar
[BarIndex
].Alignment
), Ptr
->AddrRangeMax
);
1485 // Update the new length for the device
1487 if (Ptr
->AddrLen
!= 0) {
1488 PciIoDevice
->PciBar
[BarIndex
].Length
= Ptr
->AddrLen
;
1496 FreePool (Configuration
);
1502 This routine will update the alignment with the new alignment.
1503 Compare with OLD_ALIGN/EVEN_ALIGN/SQUAD_ALIGN/DQUAD_ALIGN is to keep
1504 backward compatibility.
1506 @param Alignment Input Old alignment. Output updated alignment.
1507 @param NewAlignment New alignment.
1512 IN OUT UINT64
*Alignment
,
1513 IN UINT64 NewAlignment
1516 UINT64 OldAlignment
;
1520 // The new alignment is the same as the original,
1523 if ((NewAlignment
== 0) || (NewAlignment
== OLD_ALIGN
)) {
1527 // Check the validity of the parameter
1529 if (NewAlignment
!= EVEN_ALIGN
&&
1530 NewAlignment
!= SQUAD_ALIGN
&&
1531 NewAlignment
!= DQUAD_ALIGN
) {
1532 *Alignment
= NewAlignment
;
1536 OldAlignment
= (*Alignment
) + 1;
1540 // Get the first non-zero hex value of the length
1542 while ((OldAlignment
& 0x0F) == 0x00) {
1543 OldAlignment
= RShiftU64 (OldAlignment
, 4);
1548 // Adjust the alignment to even, quad or double quad boundary
1550 if (NewAlignment
== EVEN_ALIGN
) {
1551 if ((OldAlignment
& 0x01) != 0) {
1552 OldAlignment
= OldAlignment
+ 2 - (OldAlignment
& 0x01);
1554 } else if (NewAlignment
== SQUAD_ALIGN
) {
1555 if ((OldAlignment
& 0x03) != 0) {
1556 OldAlignment
= OldAlignment
+ 4 - (OldAlignment
& 0x03);
1558 } else if (NewAlignment
== DQUAD_ALIGN
) {
1559 if ((OldAlignment
& 0x07) != 0) {
1560 OldAlignment
= OldAlignment
+ 8 - (OldAlignment
& 0x07);
1565 // Update the old value
1567 NewAlignment
= LShiftU64 (OldAlignment
, ShiftBit
) - 1;
1568 *Alignment
= NewAlignment
;
1574 Parse PCI IOV VF bar information and fill them into PCI device instance.
1576 @param PciIoDevice Pci device instance.
1577 @param Offset Bar offset.
1578 @param BarIndex Bar index.
1580 @return Next bar offset.
1585 IN PCI_IO_DEVICE
*PciIoDevice
,
1591 UINT32 OriginalValue
;
1596 // Ensure it is called properly
1598 ASSERT (PciIoDevice
->SrIovCapabilityOffset
!= 0);
1599 if (PciIoDevice
->SrIovCapabilityOffset
== 0) {
1606 Status
= VfBarExisted (
1613 if (EFI_ERROR (Status
)) {
1614 PciIoDevice
->VfPciBar
[BarIndex
].BaseAddress
= 0;
1615 PciIoDevice
->VfPciBar
[BarIndex
].Length
= 0;
1616 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= 0;
1619 // Scan all the BARs anyway
1621 PciIoDevice
->VfPciBar
[BarIndex
].Offset
= (UINT16
) Offset
;
1625 PciIoDevice
->VfPciBar
[BarIndex
].Offset
= (UINT16
) Offset
;
1626 if ((Value
& 0x01) != 0) {
1628 // Device I/Os. Impossible
1637 PciIoDevice
->VfPciBar
[BarIndex
].BaseAddress
= OriginalValue
& Mask
;
1639 switch (Value
& 0x07) {
1642 //memory space; anywhere in 32 bit address space
1645 if ((Value
& 0x08) != 0) {
1646 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypePMem32
;
1648 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypeMem32
;
1651 PciIoDevice
->VfPciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1652 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->VfPciBar
[BarIndex
].Length
- 1;
1657 PciIoDevice
->VfPciBar
[BarIndex
].Length
= MultU64x32 (PciIoDevice
->VfPciBar
[BarIndex
].Length
, PciIoDevice
->InitialVFs
);
1661 if (PciIoDevice
->VfPciBar
[BarIndex
].Alignment
< PciIoDevice
->SystemPageSize
- 1) {
1662 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->SystemPageSize
- 1;
1668 // memory space; anywhere in 64 bit address space
1671 if ((Value
& 0x08) != 0) {
1672 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypePMem64
;
1674 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypeMem64
;
1678 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
1679 // is regarded as an extension for the first bar. As a result
1680 // the sizing will be conducted on combined 64 bit value
1681 // Here just store the masked first 32bit value for future size
1684 PciIoDevice
->VfPciBar
[BarIndex
].Length
= Value
& Mask
;
1685 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->VfPciBar
[BarIndex
].Length
- 1;
1687 if (PciIoDevice
->VfPciBar
[BarIndex
].Alignment
< PciIoDevice
->SystemPageSize
- 1) {
1688 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->SystemPageSize
- 1;
1692 // Increment the offset to point to next DWORD
1696 Status
= VfBarExisted (
1703 if (EFI_ERROR (Status
)) {
1708 // Fix the length to support some spefic 64 bit BAR
1710 Value
|= ((UINT32
) -1 << HighBitSet32 (Value
));
1713 // Calculate the size of 64bit bar
1715 PciIoDevice
->VfPciBar
[BarIndex
].BaseAddress
|= LShiftU64 ((UINT64
) OriginalValue
, 32);
1717 PciIoDevice
->VfPciBar
[BarIndex
].Length
= PciIoDevice
->VfPciBar
[BarIndex
].Length
| LShiftU64 ((UINT64
) Value
, 32);
1718 PciIoDevice
->VfPciBar
[BarIndex
].Length
= (~(PciIoDevice
->VfPciBar
[BarIndex
].Length
)) + 1;
1719 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->VfPciBar
[BarIndex
].Length
- 1;
1724 PciIoDevice
->VfPciBar
[BarIndex
].Length
= MultU64x32 (PciIoDevice
->VfPciBar
[BarIndex
].Length
, PciIoDevice
->InitialVFs
);
1728 if (PciIoDevice
->VfPciBar
[BarIndex
].Alignment
< PciIoDevice
->SystemPageSize
- 1) {
1729 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->SystemPageSize
- 1;
1738 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1739 PciIoDevice
->VfPciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1740 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->VfPciBar
[BarIndex
].Length
- 1;
1742 if (PciIoDevice
->VfPciBar
[BarIndex
].Alignment
< PciIoDevice
->SystemPageSize
- 1) {
1743 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->SystemPageSize
- 1;
1751 // Check the length again so as to keep compatible with some special bars
1753 if (PciIoDevice
->VfPciBar
[BarIndex
].Length
== 0) {
1754 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1755 PciIoDevice
->VfPciBar
[BarIndex
].BaseAddress
= 0;
1756 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= 0;
1760 // Increment number of bar
1766 Parse PCI bar information and fill them into PCI device instance.
1768 @param PciIoDevice Pci device instance.
1769 @param Offset Bar offset.
1770 @param BarIndex Bar index.
1772 @return Next bar offset.
1777 IN PCI_IO_DEVICE
*PciIoDevice
,
1783 UINT32 OriginalValue
;
1790 Status
= BarExisted (
1797 if (EFI_ERROR (Status
)) {
1798 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= 0;
1799 PciIoDevice
->PciBar
[BarIndex
].Length
= 0;
1800 PciIoDevice
->PciBar
[BarIndex
].Alignment
= 0;
1803 // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway
1805 PciIoDevice
->PciBar
[BarIndex
].Offset
= (UINT8
) Offset
;
1809 PciIoDevice
->PciBar
[BarIndex
].BarTypeFixed
= FALSE
;
1810 PciIoDevice
->PciBar
[BarIndex
].Offset
= (UINT8
) Offset
;
1811 if ((Value
& 0x01) != 0) {
1817 if ((Value
& 0xFFFF0000) != 0) {
1821 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeIo32
;
1822 PciIoDevice
->PciBar
[BarIndex
].Length
= ((~(Value
& Mask
)) + 1);
1823 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1829 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeIo16
;
1830 PciIoDevice
->PciBar
[BarIndex
].Length
= 0x0000FFFF & ((~(Value
& Mask
)) + 1);
1831 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1835 // Workaround. Some platforms inplement IO bar with 0 length
1836 // Need to treat it as no-bar
1838 if (PciIoDevice
->PciBar
[BarIndex
].Length
== 0) {
1839 PciIoDevice
->PciBar
[BarIndex
].BarType
= (PCI_BAR_TYPE
) 0;
1842 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= OriginalValue
& Mask
;
1848 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= OriginalValue
& Mask
;
1850 switch (Value
& 0x07) {
1853 //memory space; anywhere in 32 bit address space
1856 if ((Value
& 0x08) != 0) {
1857 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypePMem32
;
1859 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeMem32
;
1862 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1863 if (PciIoDevice
->PciBar
[BarIndex
].Length
< (SIZE_4KB
)) {
1865 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
1867 PciIoDevice
->PciBar
[BarIndex
].Alignment
= (SIZE_4KB
- 1);
1869 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1874 // memory space; anywhere in 64 bit address space
1877 if ((Value
& 0x08) != 0) {
1878 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypePMem64
;
1880 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeMem64
;
1884 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
1885 // is regarded as an extension for the first bar. As a result
1886 // the sizing will be conducted on combined 64 bit value
1887 // Here just store the masked first 32bit value for future size
1890 PciIoDevice
->PciBar
[BarIndex
].Length
= Value
& Mask
;
1891 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1894 // Increment the offset to point to next DWORD
1898 Status
= BarExisted (
1905 if (EFI_ERROR (Status
)) {
1907 // the high 32 bit does not claim any BAR, we need to re-check the low 32 bit BAR again
1909 if (PciIoDevice
->PciBar
[BarIndex
].Length
== 0) {
1911 // some device implement MMIO bar with 0 length, need to treat it as no-bar
1913 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1919 // Fix the length to support some spefic 64 bit BAR
1922 DEBUG ((EFI_D_INFO
, "[PciBus]BAR probing for upper 32bit of MEM64 BAR returns 0, change to 0xFFFFFFFF.\n"));
1923 Value
= (UINT32
) -1;
1925 Value
|= ((UINT32
)(-1) << HighBitSet32 (Value
));
1929 // Calculate the size of 64bit bar
1931 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
|= LShiftU64 ((UINT64
) OriginalValue
, 32);
1933 PciIoDevice
->PciBar
[BarIndex
].Length
= PciIoDevice
->PciBar
[BarIndex
].Length
| LShiftU64 ((UINT64
) Value
, 32);
1934 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(PciIoDevice
->PciBar
[BarIndex
].Length
)) + 1;
1935 if (PciIoDevice
->PciBar
[BarIndex
].Length
< (SIZE_4KB
)) {
1937 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
1939 PciIoDevice
->PciBar
[BarIndex
].Alignment
= (SIZE_4KB
- 1);
1941 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1950 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1951 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1952 if (PciIoDevice
->PciBar
[BarIndex
].Length
< (SIZE_4KB
)) {
1954 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
1956 PciIoDevice
->PciBar
[BarIndex
].Alignment
= (SIZE_4KB
- 1);
1958 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1965 // Check the length again so as to keep compatible with some special bars
1967 if (PciIoDevice
->PciBar
[BarIndex
].Length
== 0) {
1968 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1969 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= 0;
1970 PciIoDevice
->PciBar
[BarIndex
].Alignment
= 0;
1974 // Increment number of bar
1980 This routine is used to initialize the bar of a PCI device.
1982 @param PciIoDevice Pci device instance.
1984 @note It can be called typically when a device is going to be rejected.
1988 InitializePciDevice (
1989 IN PCI_IO_DEVICE
*PciIoDevice
1992 EFI_PCI_IO_PROTOCOL
*PciIo
;
1995 PciIo
= &(PciIoDevice
->PciIo
);
1998 // Put all the resource apertures
1999 // Resource base is set to all ones so as to indicate its resource
2000 // has not been alloacted
2002 for (Offset
= 0x10; Offset
<= 0x24; Offset
+= sizeof (UINT32
)) {
2003 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, Offset
, 1, &gAllOne
);
2008 This routine is used to initialize the bar of a PCI-PCI Bridge device.
2010 @param PciIoDevice PCI-PCI bridge device instance.
2015 IN PCI_IO_DEVICE
*PciIoDevice
2018 EFI_PCI_IO_PROTOCOL
*PciIo
;
2020 PciIo
= &(PciIoDevice
->PciIo
);
2023 // Put all the resource apertures including IO16
2024 // Io32, pMem32, pMem64 to quiescent state
2025 // Resource base all ones, Resource limit all zeros
2027 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &gAllOne
);
2028 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1D, 1, &gAllZero
);
2030 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x20, 1, &gAllOne
);
2031 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x22, 1, &gAllZero
);
2033 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x24, 1, &gAllOne
);
2034 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x26, 1, &gAllZero
);
2036 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x28, 1, &gAllOne
);
2037 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x2C, 1, &gAllZero
);
2040 // Don't support use io32 as for now
2042 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x30, 1, &gAllOne
);
2043 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x32, 1, &gAllZero
);
2046 // Force Interrupt line to zero for cards that come up randomly
2048 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x3C, 1, &gAllZero
);
2052 This routine is used to initialize the bar of a PCI Card Bridge device.
2054 @param PciIoDevice PCI Card bridge device.
2059 IN PCI_IO_DEVICE
*PciIoDevice
2062 EFI_PCI_IO_PROTOCOL
*PciIo
;
2064 PciIo
= &(PciIoDevice
->PciIo
);
2067 // Put all the resource apertures including IO16
2068 // Io32, pMem32, pMem64 to quiescent state(
2069 // Resource base all ones, Resource limit all zeros
2071 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x1c, 1, &gAllOne
);
2072 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x20, 1, &gAllZero
);
2074 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x24, 1, &gAllOne
);
2075 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x28, 1, &gAllZero
);
2077 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x2c, 1, &gAllOne
);
2078 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x30, 1, &gAllZero
);
2080 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x34, 1, &gAllOne
);
2081 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x38, 1, &gAllZero
);
2084 // Force Interrupt line to zero for cards that come up randomly
2086 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x3C, 1, &gAllZero
);
2090 Create and initiliaze general PCI I/O device instance for
2091 PCI device/bridge device/hotplug bridge device.
2093 @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2094 @param Pci Input Pci information block.
2095 @param Bus Device Bus NO.
2096 @param Device Device device NO.
2097 @param Func Device func NO.
2099 @return Instance of PCI device. NULL means no instance created.
2104 IN PCI_IO_DEVICE
*Bridge
,
2111 PCI_IO_DEVICE
*PciIoDevice
;
2112 EFI_PCI_IO_PROTOCOL
*PciIo
;
2115 PciIoDevice
= AllocateZeroPool (sizeof (PCI_IO_DEVICE
));
2116 if (PciIoDevice
== NULL
) {
2120 PciIoDevice
->Signature
= PCI_IO_DEVICE_SIGNATURE
;
2121 PciIoDevice
->Handle
= NULL
;
2122 PciIoDevice
->PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
2123 PciIoDevice
->DevicePath
= NULL
;
2124 PciIoDevice
->BusNumber
= Bus
;
2125 PciIoDevice
->DeviceNumber
= Device
;
2126 PciIoDevice
->FunctionNumber
= Func
;
2127 PciIoDevice
->Decodes
= 0;
2129 if (gFullEnumeration
) {
2130 PciIoDevice
->Allocated
= FALSE
;
2132 PciIoDevice
->Allocated
= TRUE
;
2135 PciIoDevice
->Registered
= FALSE
;
2136 PciIoDevice
->Attributes
= 0;
2137 PciIoDevice
->Supports
= 0;
2138 PciIoDevice
->BusOverride
= FALSE
;
2139 PciIoDevice
->AllOpRomProcessed
= FALSE
;
2141 PciIoDevice
->IsPciExp
= FALSE
;
2143 CopyMem (&(PciIoDevice
->Pci
), Pci
, sizeof (PCI_TYPE01
));
2146 // Initialize the PCI I/O instance structure
2148 InitializePciIoInstance (PciIoDevice
);
2149 InitializePciDriverOverrideInstance (PciIoDevice
);
2150 InitializePciLoadFile2 (PciIoDevice
);
2151 PciIo
= &PciIoDevice
->PciIo
;
2154 // Create a device path for this PCI device and store it into its private data
2156 CreatePciDevicePath (
2162 // Detect if PCI Express Device
2164 PciIoDevice
->PciExpressCapabilityOffset
= 0;
2165 Status
= LocateCapabilityRegBlock (
2167 EFI_PCI_CAPABILITY_ID_PCIEXP
,
2168 &PciIoDevice
->PciExpressCapabilityOffset
,
2171 if (!EFI_ERROR (Status
)) {
2172 PciIoDevice
->IsPciExp
= TRUE
;
2175 if (PcdGetBool (PcdAriSupport
)) {
2177 // Check if the device is an ARI device.
2179 Status
= LocatePciExpressCapabilityRegBlock (
2181 EFI_PCIE_CAPABILITY_ID_ARI
,
2182 &PciIoDevice
->AriCapabilityOffset
,
2185 if (!EFI_ERROR (Status
)) {
2187 // We need to enable ARI feature before calculate BusReservation,
2188 // because FirstVFOffset and VFStride may change after that.
2190 EFI_PCI_IO_PROTOCOL
*ParentPciIo
;
2194 // Check if its parent supports ARI forwarding.
2196 ParentPciIo
= &Bridge
->PciIo
;
2197 ParentPciIo
->Pci
.Read (
2199 EfiPciIoWidthUint32
,
2200 Bridge
->PciExpressCapabilityOffset
+ EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_OFFSET
,
2204 if ((Data32
& EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_ARI_FORWARDING
) != 0) {
2206 // ARI forward support in bridge, so enable it.
2208 ParentPciIo
->Pci
.Read (
2210 EfiPciIoWidthUint32
,
2211 Bridge
->PciExpressCapabilityOffset
+ EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET
,
2215 if ((Data32
& EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING
) == 0) {
2216 Data32
|= EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING
;
2217 ParentPciIo
->Pci
.Write (
2219 EfiPciIoWidthUint32
,
2220 Bridge
->PciExpressCapabilityOffset
+ EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET
,
2226 " ARI: forwarding enabled for PPB[%02x:%02x:%02x]\n",
2228 Bridge
->DeviceNumber
,
2229 Bridge
->FunctionNumber
2234 DEBUG ((EFI_D_INFO
, " ARI: CapOffset = 0x%x\n", PciIoDevice
->AriCapabilityOffset
));
2239 // Initialization for SR-IOV
2242 if (PcdGetBool (PcdSrIovSupport
)) {
2243 Status
= LocatePciExpressCapabilityRegBlock (
2245 EFI_PCIE_CAPABILITY_ID_SRIOV
,
2246 &PciIoDevice
->SrIovCapabilityOffset
,
2249 if (!EFI_ERROR (Status
)) {
2250 UINT32 SupportedPageSize
;
2252 UINT16 FirstVFOffset
;
2258 // If the SR-IOV device is an ARI device, then Set ARI Capable Hierarchy for the device.
2260 if (PcdGetBool (PcdAriSupport
) && PciIoDevice
->AriCapabilityOffset
!= 0) {
2263 EfiPciIoWidthUint16
,
2264 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL
,
2268 Data16
|= EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL_ARI_HIERARCHY
;
2271 EfiPciIoWidthUint16
,
2272 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL
,
2279 // Calculate SystemPageSize
2284 EfiPciIoWidthUint32
,
2285 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_SUPPORTED_PAGE_SIZE
,
2289 PciIoDevice
->SystemPageSize
= (PcdGet32 (PcdSrIovSystemPageSize
) & SupportedPageSize
);
2290 ASSERT (PciIoDevice
->SystemPageSize
!= 0);
2294 EfiPciIoWidthUint32
,
2295 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_SYSTEM_PAGE_SIZE
,
2297 &PciIoDevice
->SystemPageSize
2300 // Adjust SystemPageSize for Alignment usage later
2302 PciIoDevice
->SystemPageSize
<<= 12;
2305 // Calculate BusReservation for PCI IOV
2309 // Read First FirstVFOffset, InitialVFs, and VFStride
2313 EfiPciIoWidthUint16
,
2314 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_FIRSTVF
,
2320 EfiPciIoWidthUint16
,
2321 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_INITIALVFS
,
2323 &PciIoDevice
->InitialVFs
2327 EfiPciIoWidthUint16
,
2328 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_VFSTRIDE
,
2335 PFRid
= EFI_PCI_RID(Bus
, Device
, Func
);
2336 LastVF
= PFRid
+ FirstVFOffset
+ (PciIoDevice
->InitialVFs
- 1) * VFStride
;
2339 // Calculate ReservedBusNum for this PF
2341 PciIoDevice
->ReservedBusNum
= (UINT16
)(EFI_PCI_BUS_OF_RID (LastVF
) - Bus
+ 1);
2345 " SR-IOV: SupportedPageSize = 0x%x; SystemPageSize = 0x%x; FirstVFOffset = 0x%x;\n",
2346 SupportedPageSize
, PciIoDevice
->SystemPageSize
>> 12, FirstVFOffset
2350 " InitialVFs = 0x%x; ReservedBusNum = 0x%x; CapOffset = 0x%x\n",
2351 PciIoDevice
->InitialVFs
, PciIoDevice
->ReservedBusNum
, PciIoDevice
->SrIovCapabilityOffset
2356 if (PcdGetBool (PcdMrIovSupport
)) {
2357 Status
= LocatePciExpressCapabilityRegBlock (
2359 EFI_PCIE_CAPABILITY_ID_MRIOV
,
2360 &PciIoDevice
->MrIovCapabilityOffset
,
2363 if (!EFI_ERROR (Status
)) {
2364 DEBUG ((EFI_D_INFO
, " MR-IOV: CapOffset = 0x%x\n", PciIoDevice
->MrIovCapabilityOffset
));
2369 // Initialize the reserved resource list
2371 InitializeListHead (&PciIoDevice
->ReservedResourceList
);
2374 // Initialize the driver list
2376 InitializeListHead (&PciIoDevice
->OptionRomDriverList
);
2379 // Initialize the child list
2381 InitializeListHead (&PciIoDevice
->ChildList
);
2387 This routine is used to enumerate entire pci bus system
2388 in a given platform.
2390 It is only called on the second start on the same Root Bridge.
2392 @param Controller Parent bridge handler.
2394 @retval EFI_SUCCESS PCI enumeration finished successfully.
2395 @retval other Some error occurred when enumerating the pci bus system.
2399 PciEnumeratorLight (
2400 IN EFI_HANDLE Controller
2405 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2406 PCI_IO_DEVICE
*RootBridgeDev
;
2409 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
2412 MaxBus
= PCI_MAX_BUS
;
2416 // If this root bridge has been already enumerated, then return successfully
2418 if (GetRootBridgeByHandle (Controller
) != NULL
) {
2423 // Open pci root bridge io protocol
2425 Status
= gBS
->OpenProtocol (
2427 &gEfiPciRootBridgeIoProtocolGuid
,
2428 (VOID
**) &PciRootBridgeIo
,
2429 gPciBusDriverBinding
.DriverBindingHandle
,
2431 EFI_OPEN_PROTOCOL_BY_DRIVER
2433 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
2437 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
2439 if (EFI_ERROR (Status
)) {
2443 while (PciGetBusRange (&Descriptors
, &MinBus
, &MaxBus
, NULL
) == EFI_SUCCESS
) {
2446 // Create a device node for root bridge device with a NULL host bridge controller handle
2448 RootBridgeDev
= CreateRootBridge (Controller
);
2450 if (RootBridgeDev
== NULL
) {
2456 // Record the root bridgeio protocol
2458 RootBridgeDev
->PciRootBridgeIo
= PciRootBridgeIo
;
2460 Status
= PciPciDeviceInfoCollector (
2465 if (!EFI_ERROR (Status
)) {
2468 // Remove those PCI devices which are rejected when full enumeration
2470 RemoveRejectedPciDevices (RootBridgeDev
->Handle
, RootBridgeDev
);
2473 // Process option rom light
2475 ProcessOptionRomLight (RootBridgeDev
);
2478 // Determine attributes for all devices under this root bridge
2480 DetermineDeviceAttribute (RootBridgeDev
);
2483 // If successfully, insert the node into device pool
2485 InsertRootBridge (RootBridgeDev
);
2489 // If unsuccessly, destroy the entire node
2491 DestroyRootBridge (RootBridgeDev
);
2501 Get bus range from PCI resource descriptor list.
2503 @param Descriptors A pointer to the address space descriptor.
2504 @param MinBus The min bus returned.
2505 @param MaxBus The max bus returned.
2506 @param BusRange The bus range returned.
2508 @retval EFI_SUCCESS Successfully got bus range.
2509 @retval EFI_NOT_FOUND Can not find the specific bus.
2514 IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
**Descriptors
,
2517 OUT UINT16
*BusRange
2520 while ((*Descriptors
)->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
2521 if ((*Descriptors
)->ResType
== ACPI_ADDRESS_SPACE_TYPE_BUS
) {
2522 if (MinBus
!= NULL
) {
2523 *MinBus
= (UINT16
) (*Descriptors
)->AddrRangeMin
;
2526 if (MaxBus
!= NULL
) {
2527 *MaxBus
= (UINT16
) (*Descriptors
)->AddrRangeMax
;
2530 if (BusRange
!= NULL
) {
2531 *BusRange
= (UINT16
) (*Descriptors
)->AddrLen
;
2540 return EFI_NOT_FOUND
;
2544 This routine can be used to start the root bridge.
2546 @param RootBridgeDev Pci device instance.
2548 @retval EFI_SUCCESS This device started.
2549 @retval other Failed to get PCI Root Bridge I/O protocol.
2553 StartManagingRootBridge (
2554 IN PCI_IO_DEVICE
*RootBridgeDev
2557 EFI_HANDLE RootBridgeHandle
;
2559 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2562 // Get the root bridge handle
2564 RootBridgeHandle
= RootBridgeDev
->Handle
;
2565 PciRootBridgeIo
= NULL
;
2568 // Get the pci root bridge io protocol
2570 Status
= gBS
->OpenProtocol (
2572 &gEfiPciRootBridgeIoProtocolGuid
,
2573 (VOID
**) &PciRootBridgeIo
,
2574 gPciBusDriverBinding
.DriverBindingHandle
,
2576 EFI_OPEN_PROTOCOL_BY_DRIVER
2579 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
2584 // Store the PciRootBridgeIo protocol into root bridge private data
2586 RootBridgeDev
->PciRootBridgeIo
= PciRootBridgeIo
;
2593 This routine can be used to check whether a PCI device should be rejected when light enumeration.
2595 @param PciIoDevice Pci device instance.
2597 @retval TRUE This device should be rejected.
2598 @retval FALSE This device shouldn't be rejected.
2602 IsPciDeviceRejected (
2603 IN PCI_IO_DEVICE
*PciIoDevice
2613 // PPB should be skip!
2615 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
)) {
2619 if (IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
2621 // Only test base registers for P2C
2623 for (BarOffset
= 0x1C; BarOffset
<= 0x38; BarOffset
+= 2 * sizeof (UINT32
)) {
2625 Mask
= (BarOffset
< 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC;
2626 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
2627 if (EFI_ERROR (Status
)) {
2631 TestValue
= TestValue
& Mask
;
2632 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2634 // The bar isn't programed, so it should be rejected
2643 for (BarOffset
= 0x14; BarOffset
<= 0x24; BarOffset
+= sizeof (UINT32
)) {
2647 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
2648 if (EFI_ERROR (Status
)) {
2652 if ((TestValue
& 0x01) != 0) {
2658 TestValue
= TestValue
& Mask
;
2659 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2669 TestValue
= TestValue
& Mask
;
2671 if ((TestValue
& 0x07) == 0x04) {
2676 BarOffset
+= sizeof (UINT32
);
2677 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2680 // Test its high 32-Bit BAR
2682 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
2683 if (TestValue
== OldValue
) {
2693 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2704 Reset all bus number from specific bridge.
2706 @param Bridge Parent specific bridge.
2707 @param StartBusNumber Start bus number.
2711 ResetAllPpbBusNumber (
2712 IN PCI_IO_DEVICE
*Bridge
,
2713 IN UINT8 StartBusNumber
2723 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2725 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
2727 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
2728 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
2731 // Check to see whether a pci device is present
2733 Status
= PciDevicePresent (
2741 if (EFI_ERROR (Status
) && Func
== 0) {
2743 // go to next device if there is no Function 0
2748 if (!EFI_ERROR (Status
) && (IS_PCI_BRIDGE (&Pci
))) {
2751 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
2752 Status
= PciRootBridgeIo
->Pci
.Read (
2759 SecondaryBus
= (UINT8
)(Register
>> 8);
2761 if (SecondaryBus
!= 0) {
2762 ResetAllPpbBusNumber (Bridge
, SecondaryBus
);
2766 // Reset register 18h, 19h, 1Ah on PCI Bridge
2768 Register
&= 0xFF000000;
2769 Status
= PciRootBridgeIo
->Pci
.Write (
2778 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
2780 // Skip sub functions, this is not a multi function device
2782 Func
= PCI_MAX_FUNC
;