/** @file\r
PCI emumeration support functions implementation for PCI Bus module.\r
\r
-Copyright (c) 2006 - 2009, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r
+This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
which accompanies this distribution. The full text of the license may be found at\r
http://opensource.org/licenses/bsd-license.php\r
\r
#include "PciBus.h"\r
\r
+extern CHAR16 *mBarTypeStr[];\r
+\r
+#define OLD_ALIGN 0xFFFFFFFFFFFFFFFFULL\r
+#define EVEN_ALIGN 0xFFFFFFFFFFFFFFFEULL\r
+#define SQUAD_ALIGN 0xFFFFFFFFFFFFFFFDULL\r
+#define DQUAD_ALIGN 0xFFFFFFFFFFFFFFFCULL\r
+\r
/**\r
This routine is used to check whether the pci device is present.\r
\r
(UINT8) Device,\r
(UINT8) Func\r
);\r
+\r
+ if (EFI_ERROR (Status) && Func == 0) {\r
+ //\r
+ // go to next device if there is no Function 0\r
+ //\r
+ break;\r
+ }\r
+\r
if (!EFI_ERROR (Status)) {\r
\r
//\r
return Status;\r
}\r
\r
+ //\r
+ // Ensure secondary bus number is greater than the primary bus number to avoid\r
+ // any potential dead loop when PcdPciDisableBusEnumeration is set to TRUE\r
+ //\r
+ if (SecBus <= StartBusNumber) {\r
+ break;\r
+ }\r
+\r
//\r
// Get resource padding for PPB\r
//\r
\r
PciIoDevice = NULL;\r
\r
+ DEBUG ((\r
+ EFI_D_INFO,\r
+ "PciBus: Discovered %s @ [%02x|%02x|%02x]\n",\r
+ IS_PCI_BRIDGE (Pci) ? L"PPB" :\r
+ IS_CARDBUS_BRIDGE (Pci) ? L"P2C" :\r
+ L"PCI",\r
+ Bus, Device, Func\r
+ ));\r
+\r
if (!IS_PCI_BRIDGE (Pci)) {\r
\r
if (IS_CARDBUS_BRIDGE (Pci)) {\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Dump the PPB padding resource information.\r
+\r
+ @param PciIoDevice PCI IO instance.\r
+ @param ResourceType The desired resource type to dump.\r
+ PciBarTypeUnknown means to dump all types of resources.\r
+**/\r
+VOID\r
+DumpPpbPaddingResource (\r
+ IN PCI_IO_DEVICE *PciIoDevice,\r
+ IN PCI_BAR_TYPE ResourceType\r
+ )\r
+{\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
+ PCI_BAR_TYPE Type;\r
+\r
+ if (PciIoDevice->ResourcePaddingDescriptors == NULL) {\r
+ return;\r
+ }\r
+\r
+ if (ResourceType == PciBarTypeIo16 || ResourceType == PciBarTypeIo32) {\r
+ ResourceType = PciBarTypeIo;\r
+ }\r
+\r
+ for (Descriptor = PciIoDevice->ResourcePaddingDescriptors; Descriptor->Desc != ACPI_END_TAG_DESCRIPTOR; Descriptor++) {\r
+\r
+ Type = PciBarTypeUnknown;\r
+ if (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {\r
+ Type = PciBarTypeIo;\r
+ } else if (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
+\r
+ if (Descriptor->AddrSpaceGranularity == 32) {\r
+ //\r
+ // prefechable\r
+ //\r
+ if (Descriptor->SpecificFlag == EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) {\r
+ Type = PciBarTypePMem32;\r
+ }\r
+\r
+ //\r
+ // Non-prefechable\r
+ //\r
+ if (Descriptor->SpecificFlag == 0) {\r
+ Type = PciBarTypeMem32;\r
+ }\r
+ }\r
+\r
+ if (Descriptor->AddrSpaceGranularity == 64) {\r
+ //\r
+ // prefechable\r
+ //\r
+ if (Descriptor->SpecificFlag == EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) {\r
+ Type = PciBarTypePMem64;\r
+ }\r
+\r
+ //\r
+ // Non-prefechable\r
+ //\r
+ if (Descriptor->SpecificFlag == 0) {\r
+ Type = PciBarTypeMem64;\r
+ }\r
+ }\r
+ }\r
+\r
+ if ((Type != PciBarTypeUnknown) && ((ResourceType == PciBarTypeUnknown) || (ResourceType == Type))) {\r
+ DEBUG ((\r
+ EFI_D_INFO,\r
+ " Padding: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx\n",\r
+ mBarTypeStr[Type], Descriptor->AddrRangeMax, Descriptor->AddrLen\r
+ ));\r
+ }\r
+ }\r
+\r
+}\r
+\r
+/**\r
+ Dump the PCI BAR information.\r
+\r
+ @param PciIoDevice PCI IO instance.\r
+**/\r
+VOID\r
+DumpPciBars (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ for (Index = 0; Index < PCI_MAX_BAR; Index++) {\r
+ if (PciIoDevice->PciBar[Index].BarType == PciBarTypeUnknown) {\r
+ continue;\r
+ }\r
+\r
+ DEBUG ((\r
+ EFI_D_INFO,\r
+ " BAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n",\r
+ Index, mBarTypeStr[MIN (PciIoDevice->PciBar[Index].BarType, PciBarTypeMaxType)],\r
+ PciIoDevice->PciBar[Index].Alignment, PciIoDevice->PciBar[Index].Length, PciIoDevice->PciBar[Index].Offset\r
+ ));\r
+ }\r
+\r
+ for (Index = 0; Index < PCI_MAX_BAR; Index++) {\r
+ if ((PciIoDevice->VfPciBar[Index].BarType == PciBarTypeUnknown) && (PciIoDevice->VfPciBar[Index].Length == 0)) {\r
+ continue;\r
+ }\r
+\r
+ DEBUG ((\r
+ EFI_D_INFO,\r
+ " VFBAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n",\r
+ Index, mBarTypeStr[MIN (PciIoDevice->VfPciBar[Index].BarType, PciBarTypeMaxType)],\r
+ PciIoDevice->VfPciBar[Index].Alignment, PciIoDevice->VfPciBar[Index].Length, PciIoDevice->VfPciBar[Index].Offset\r
+ ));\r
+ }\r
+ DEBUG ((EFI_D_INFO, "\n"));\r
+}\r
+\r
/**\r
Create PCI device instance for PCI device.\r
\r
UINTN Offset;\r
UINTN BarIndex;\r
PCI_IO_DEVICE *PciIoDevice;\r
- EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
\r
- PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
PciIoDevice = CreatePciIoDevice (\r
- PciRootBridgeIo,\r
+ Bridge,\r
Pci,\r
Bus,\r
Device,\r
return NULL;\r
}\r
\r
- //\r
- // Create a device path for this PCI device and store it into its private data\r
- //\r
- CreatePciDevicePath (\r
- Bridge->DevicePath,\r
- PciIoDevice\r
- );\r
-\r
//\r
// If it is a full enumeration, disconnect the device in advance\r
//\r
//\r
// Parse the SR-IOV VF bars\r
//\r
- if ((PciIoDevice->SrIovCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport)& EFI_PCI_IOV_POLICY_SRIOV) != 0)) {\r
+ if (PcdGetBool (PcdSrIovSupport) && PciIoDevice->SrIovCapabilityOffset != 0) {\r
for (Offset = PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_BAR0, BarIndex = 0;\r
Offset <= PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_BAR5;\r
BarIndex++) {\r
Offset = PciIovParseVfBar (PciIoDevice, Offset, BarIndex);\r
}\r
}\r
+\r
+ DEBUG_CODE (DumpPciBars (PciIoDevice););\r
return PciIoDevice;\r
}\r
\r
IN UINT8 Func\r
)\r
{\r
- EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
PCI_IO_DEVICE *PciIoDevice;\r
EFI_STATUS Status;\r
UINT8 Value;\r
EFI_PCI_IO_PROTOCOL *PciIo;\r
UINT8 Temp;\r
+ UINT32 PMemBaseLimit;\r
+ UINT16 PrefetchableMemoryBase;\r
+ UINT16 PrefetchableMemoryLimit;\r
\r
- PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
PciIoDevice = CreatePciIoDevice (\r
- PciRootBridgeIo,\r
+ Bridge,\r
Pci,\r
Bus,\r
Device,\r
return NULL;\r
}\r
\r
- //\r
- // Create a device path for this PCI device and store it into its private data\r
- //\r
- CreatePciDevicePath (\r
- Bridge->DevicePath,\r
- PciIoDevice\r
- );\r
-\r
if (gFullEnumeration) {\r
PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);\r
\r
\r
//\r
// if PcdPciBridgeIoAlignmentProbe is TRUE, PCI bus driver probes\r
- // PCI bridge supporting non-stardard I/O window alignment less than 4K.\r
+ // PCI bridge supporting non-standard I/O window alignment less than 4K.\r
//\r
\r
PciIoDevice->BridgeIoAlignment = 0xFFF;\r
if (FeaturePcdGet (PcdPciBridgeIoAlignmentProbe)) {\r
//\r
// Check any bits of bit 3-1 of I/O Base Register are writable.\r
- // if so, it is assumed non-stardard I/O window alignment is supported by this bridge.\r
+ // if so, it is assumed non-standard I/O window alignment is supported by this bridge.\r
// Per spec, bit 3-1 of I/O Base Register are reserved bits, so its content can't be assumed.\r
//\r
Value = (UINT8)(Temp ^ (BIT3 | BIT2 | BIT1));\r
PciIoDevice,\r
0x24,\r
NULL,\r
- NULL\r
+ &PMemBaseLimit\r
);\r
\r
//\r
// Test if it supports 64 memory or not\r
//\r
- if (!EFI_ERROR (Status)) {\r
-\r
+ // The bottom 4 bits of both the Prefetchable Memory Base and Prefetchable Memory Limit\r
+ // registers:\r
+ // 0 - the bridge supports only 32 bit addresses.\r
+ // 1 - the bridge supports 64-bit addresses.\r
+ //\r
+ PrefetchableMemoryBase = (UINT16)(PMemBaseLimit & 0xffff);\r
+ PrefetchableMemoryLimit = (UINT16)(PMemBaseLimit >> 16);\r
+ if (!EFI_ERROR (Status) &&\r
+ (PrefetchableMemoryBase & 0x000f) == 0x0001 &&\r
+ (PrefetchableMemoryLimit & 0x000f) == 0x0001) {\r
Status = BarExisted (\r
PciIoDevice,\r
0x28,\r
\r
GetResourcePaddingPpb (PciIoDevice);\r
\r
+ DEBUG_CODE (\r
+ DumpPpbPaddingResource (PciIoDevice, PciBarTypeUnknown);\r
+ DumpPciBars (PciIoDevice);\r
+ );\r
+\r
return PciIoDevice;\r
}\r
\r
IN UINT8 Func\r
)\r
{\r
- EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
PCI_IO_DEVICE *PciIoDevice;\r
\r
- PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
PciIoDevice = CreatePciIoDevice (\r
- PciRootBridgeIo,\r
+ Bridge,\r
Pci,\r
Bus,\r
Device,\r
return NULL;\r
}\r
\r
- //\r
- // Create a device path for this PCI device and store it into its private data\r
- //\r
- CreatePciDevicePath (\r
- Bridge->DevicePath,\r
- PciIoDevice\r
- );\r
-\r
if (gFullEnumeration) {\r
PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);\r
\r
EFI_BRIDGE_PMEM32_DECODE_SUPPORTED |\r
EFI_BRIDGE_IO32_DECODE_SUPPORTED;\r
\r
+ DEBUG_CODE (DumpPciBars (PciIoDevice););\r
+\r
return PciIoDevice;\r
}\r
\r
\r
if (Option == EFI_SET_SUPPORTS) {\r
\r
- Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE |\r
+ Attributes |= (UINT64) (EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE |\r
EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED |\r
EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE |\r
EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE |\r
EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM |\r
- EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;\r
+ EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE);\r
\r
- if ((Attributes & EFI_PCI_IO_ATTRIBUTE_IO) != 0) {\r
- Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;\r
- Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;\r
+ if (IS_PCI_LPC (&PciIoDevice->Pci)) {\r
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;\r
+ Attributes |= (mReserveIsaAliases ? (UINT64) EFI_PCI_IO_ATTRIBUTE_ISA_IO : \\r
+ (UINT64) EFI_PCI_IO_ATTRIBUTE_ISA_IO_16);\r
}\r
\r
if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
//\r
Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;\r
Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;\r
+\r
+ if (mReserveVgaAliases) {\r
+ Attributes &= ~(UINT64)(EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 | \\r
+ EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16);\r
+ } else {\r
+ Attributes &= ~(UINT64)(EFI_PCI_IO_ATTRIBUTE_VGA_IO | \\r
+ EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO);\r
+ }\r
} else {\r
\r
if (IS_PCI_IDE (&PciIoDevice->Pci)) {\r
\r
if (IS_PCI_VGA (&PciIoDevice->Pci)) {\r
Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;\r
- Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;\r
+ Attributes |= (mReserveVgaAliases ? (UINT64) EFI_PCI_IO_ATTRIBUTE_VGA_IO : \\r
+ (UINT64) EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);\r
}\r
}\r
\r
EFI_PCI_IO_ATTRIBUTE_BUS_MASTER );\r
\r
} else {\r
+ //\r
+ // When this attribute is clear, the RomImage and RomSize fields in the PCI IO were\r
+ // initialized based on the PCI option ROM found through the ROM BAR of the PCI controller.\r
+ // When this attribute is set, the PCI option ROM described by the RomImage and RomSize\r
+ // fields is not from the the ROM BAR of the PCI controller.\r
+ //\r
+ if (!PciIoDevice->EmbeddedRom) {\r
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM;\r
+ }\r
PciIoDevice->Attributes = Attributes;\r
}\r
}\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
+ //\r
+ // Assume the PCI Root Bridge supports DAC\r
+ //\r
+ PciIoDevice->Supports |= (UINT64)(EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE |\r
+ EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM |\r
+ EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE);\r
+\r
} else {\r
\r
//\r
)\r
{\r
EFI_STATUS Status;\r
- UINTN BarIndex;\r
- UINTN BarEndIndex;\r
+ UINT64 BarIndex;\r
+ UINT64 BarEndIndex;\r
BOOLEAN SetFlag;\r
VOID *Configuration;\r
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
Configuration = NULL;\r
Status = EFI_SUCCESS;\r
\r
- if (gEfiIncompatiblePciDeviceSupport == NULL) {\r
+ if (gIncompatiblePciDeviceSupport == NULL) {\r
//\r
// It can only be supported after the Incompatible PCI Device\r
// Support Protocol has been installed\r
Status = gBS->LocateProtocol (\r
&gEfiIncompatiblePciDeviceSupportProtocolGuid,\r
NULL,\r
- (VOID **) &gEfiIncompatiblePciDeviceSupport\r
+ (VOID **) &gIncompatiblePciDeviceSupport\r
);\r
}\r
if (Status == EFI_SUCCESS) {\r
// Check whether the device belongs to incompatible devices from protocol or not\r
// If it is , then get its special requirement in the ACPI table\r
//\r
- Status = gEfiIncompatiblePciDeviceSupport->CheckDevice (\r
- gEfiIncompatiblePciDeviceSupport,\r
- PciIoDevice->Pci.Hdr.VendorId,\r
- PciIoDevice->Pci.Hdr.DeviceId,\r
- PciIoDevice->Pci.Hdr.RevisionID,\r
- PciIoDevice->Pci.Device.SubsystemVendorID,\r
- PciIoDevice->Pci.Device.SubsystemID,\r
- &Configuration\r
- );\r
+ Status = gIncompatiblePciDeviceSupport->CheckDevice (\r
+ gIncompatiblePciDeviceSupport,\r
+ PciIoDevice->Pci.Hdr.VendorId,\r
+ PciIoDevice->Pci.Hdr.DeviceId,\r
+ PciIoDevice->Pci.Hdr.RevisionID,\r
+ PciIoDevice->Pci.Device.SubsystemVendorID,\r
+ PciIoDevice->Pci.Device.SubsystemID,\r
+ &Configuration\r
+ );\r
\r
}\r
\r
break;\r
}\r
\r
- BarIndex = (UINTN) Ptr->AddrTranslationOffset;\r
+ BarIndex = Ptr->AddrTranslationOffset;\r
BarEndIndex = BarIndex;\r
\r
//\r
// Update all the bars in the device\r
+ // Compare against 0xFF is to keep backward compatibility.\r
//\r
- if (BarIndex == PCI_BAR_ALL) {\r
+ if ((BarIndex == MAX_UINT64) || (BarIndex == 0xFF)) {\r
BarIndex = 0;\r
BarEndIndex = PCI_MAX_BAR - 1;\r
}\r
\r
- if (BarIndex > PCI_MAX_BAR) {\r
+ if (BarIndex >= PCI_MAX_BAR) {\r
Ptr++;\r
continue;\r
}\r
//\r
if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeMem)) {\r
SetFlag = TRUE;\r
+\r
+ //\r
+ // Ignored if granularity is 0.\r
+ // Ignored if PCI BAR is I/O or 32-bit memory.\r
+ // If PCI BAR is 64-bit memory and granularity is 32, then\r
+ // the PCI BAR resource is allocated below 4GB.\r
+ // If PCI BAR is 64-bit memory and granularity is 64, then\r
+ // the PCI BAR resource is allocated above 4GB.\r
+ //\r
+ if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeMem64) {\r
+ switch (Ptr->AddrSpaceGranularity) {\r
+ case 32:\r
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;\r
+ case 64:\r
+ PciIoDevice->PciBar[BarIndex].BarTypeFixed = TRUE;\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypePMem64) {\r
+ switch (Ptr->AddrSpaceGranularity) {\r
+ case 32:\r
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;\r
+ case 64:\r
+ PciIoDevice->PciBar[BarIndex].BarTypeFixed = TRUE;\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ }\r
}\r
break;\r
\r
//\r
// Update the new length for the device\r
//\r
- if (Ptr->AddrLen != PCI_BAR_NOCHANGE) {\r
+ if (Ptr->AddrLen != 0) {\r
PciIoDevice->PciBar[BarIndex].Length = Ptr->AddrLen;\r
}\r
}\r
\r
/**\r
This routine will update the alignment with the new alignment.\r
+ Compare with OLD_ALIGN/EVEN_ALIGN/SQUAD_ALIGN/DQUAD_ALIGN is to keep\r
+ backward compatibility.\r
\r
@param Alignment Input Old alignment. Output updated alignment.\r
@param NewAlignment New alignment.\r
// The new alignment is the same as the original,\r
// so skip it\r
//\r
- if (NewAlignment == PCI_BAR_OLD_ALIGN) {\r
+ if ((NewAlignment == 0) || (NewAlignment == OLD_ALIGN)) {\r
return ;\r
}\r
//\r
// Check the validity of the parameter\r
//\r
- if (NewAlignment != PCI_BAR_EVEN_ALIGN &&\r
- NewAlignment != PCI_BAR_SQUAD_ALIGN &&\r
- NewAlignment != PCI_BAR_DQUAD_ALIGN ) {\r
+ if (NewAlignment != EVEN_ALIGN &&\r
+ NewAlignment != SQUAD_ALIGN &&\r
+ NewAlignment != DQUAD_ALIGN ) {\r
*Alignment = NewAlignment;\r
return ;\r
}\r
//\r
// Adjust the alignment to even, quad or double quad boundary\r
//\r
- if (NewAlignment == PCI_BAR_EVEN_ALIGN) {\r
+ if (NewAlignment == EVEN_ALIGN) {\r
if ((OldAlignment & 0x01) != 0) {\r
OldAlignment = OldAlignment + 2 - (OldAlignment & 0x01);\r
}\r
- } else if (NewAlignment == PCI_BAR_SQUAD_ALIGN) {\r
+ } else if (NewAlignment == SQUAD_ALIGN) {\r
if ((OldAlignment & 0x03) != 0) {\r
OldAlignment = OldAlignment + 4 - (OldAlignment & 0x03);\r
}\r
- } else if (NewAlignment == PCI_BAR_DQUAD_ALIGN) {\r
+ } else if (NewAlignment == DQUAD_ALIGN) {\r
if ((OldAlignment & 0x07) != 0) {\r
OldAlignment = OldAlignment + 8 - (OldAlignment & 0x07);\r
}\r
UINT32 Value;\r
UINT32 OriginalValue;\r
UINT32 Mask;\r
- UINT32 Data;\r
- UINT8 Index;\r
EFI_STATUS Status;\r
\r
//\r
//\r
// Scan all the BARs anyway\r
//\r
- PciIoDevice->VfPciBar[BarIndex].Offset = (UINT8) Offset;\r
+ PciIoDevice->VfPciBar[BarIndex].Offset = (UINT16) Offset;\r
return Offset + 4;\r
}\r
\r
- PciIoDevice->VfPciBar[BarIndex].Offset = (UINT8) Offset;\r
- if (Value & 0x01) {\r
+ PciIoDevice->VfPciBar[BarIndex].Offset = (UINT16) Offset;\r
+ if ((Value & 0x01) != 0) {\r
//\r
// Device I/Os. Impossible\r
//\r
//memory space; anywhere in 32 bit address space\r
//\r
case 0x00:\r
- if (Value & 0x08) {\r
+ if ((Value & 0x08) != 0) {\r
PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypePMem32;\r
} else {\r
PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeMem32;\r
// memory space; anywhere in 64 bit address space\r
//\r
case 0x04:\r
- if (Value & 0x08) {\r
+ if ((Value & 0x08) != 0) {\r
PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypePMem64;\r
} else {\r
PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeMem64;\r
//\r
// Fix the length to support some spefic 64 bit BAR\r
//\r
- Data = Value;\r
- Index = 0;\r
- for (Data = Value; Data != 0; Data >>= 1) {\r
- Index ++;\r
- }\r
- Value |= ((UINT32)(-1) << Index); \r
+ Value |= ((UINT32) -1 << HighBitSet32 (Value));\r
\r
//\r
// Calculate the size of 64bit bar\r
UINT32 Value;\r
UINT32 OriginalValue;\r
UINT32 Mask;\r
- UINT32 Data;\r
- UINT8 Index;\r
EFI_STATUS Status;\r
\r
OriginalValue = 0;\r
return Offset + 4;\r
}\r
\r
+ PciIoDevice->PciBar[BarIndex].BarTypeFixed = FALSE;\r
PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;\r
if ((Value & 0x01) != 0) {\r
//\r
PciIoDevice->PciBar[BarIndex].BarType = (PCI_BAR_TYPE) 0;\r
}\r
\r
- PciIoDevice->PciBar[BarIndex].Prefetchable = FALSE;\r
PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;\r
\r
} else {\r
// some device implement MMIO bar with 0 length, need to treat it as no-bar\r
//\r
PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;\r
+ return Offset + 4;\r
}\r
- return Offset + 4;\r
}\r
\r
//\r
// Fix the length to support some spefic 64 bit BAR\r
//\r
- Data = Value;\r
- Index = 0;\r
- for (Data = Value; Data != 0; Data >>= 1) {\r
- Index ++;\r
+ if (Value == 0) {\r
+ DEBUG ((EFI_D_INFO, "[PciBus]BAR probing for upper 32bit of MEM64 BAR returns 0, change to 0xFFFFFFFF.\n"));\r
+ Value = (UINT32) -1;\r
+ } else {\r
+ Value |= ((UINT32)(-1) << HighBitSet32 (Value));\r
}\r
- Value |= ((UINT32)(-1) << Index);\r
\r
//\r
// Calculate the size of 64bit bar\r
**/\r
PCI_IO_DEVICE *\r
CreatePciIoDevice (\r
- IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,\r
+ IN PCI_IO_DEVICE *Bridge,\r
IN PCI_TYPE00 *Pci,\r
IN UINT8 Bus,\r
IN UINT8 Device,\r
IN UINT8 Func\r
)\r
{\r
- PCI_IO_DEVICE *PciIoDevice;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
EFI_PCI_IO_PROTOCOL *PciIo;\r
EFI_STATUS Status;\r
\r
\r
PciIoDevice->Signature = PCI_IO_DEVICE_SIGNATURE;\r
PciIoDevice->Handle = NULL;\r
- PciIoDevice->PciRootBridgeIo = PciRootBridgeIo;\r
+ PciIoDevice->PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
PciIoDevice->DevicePath = NULL;\r
PciIoDevice->BusNumber = Bus;\r
PciIoDevice->DeviceNumber = Device;\r
InitializePciLoadFile2 (PciIoDevice);\r
PciIo = &PciIoDevice->PciIo;\r
\r
+ //\r
+ // Create a device path for this PCI device and store it into its private data\r
+ //\r
+ CreatePciDevicePath (\r
+ Bridge->DevicePath,\r
+ PciIoDevice\r
+ );\r
+\r
//\r
// Detect if PCI Express Device\r
//\r
PciIoDevice->IsPciExp = TRUE;\r
}\r
\r
- //\r
- // Initialize for PCI IOV\r
- //\r
-\r
- //\r
- // Check ARI for function 0 only\r
- //\r
- Status = LocatePciExpressCapabilityRegBlock (\r
- PciIoDevice,\r
- EFI_PCIE_CAPABILITY_ID_ARI,\r
- &PciIoDevice->AriCapabilityOffset,\r
- NULL\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- DEBUG ((\r
- EFI_D_INFO,\r
- "PCI-IOV B%x.D%x.F%x - ARI Cap offset - 0x%x\n",\r
- (UINTN)Bus,\r
- (UINTN)Device,\r
- (UINTN)Func,\r
- (UINTN)PciIoDevice->AriCapabilityOffset\r
- ));\r
- }\r
+ if (PcdGetBool (PcdAriSupport)) {\r
+ //\r
+ // Check if the device is an ARI device.\r
+ //\r
+ Status = LocatePciExpressCapabilityRegBlock (\r
+ PciIoDevice,\r
+ EFI_PCIE_CAPABILITY_ID_ARI,\r
+ &PciIoDevice->AriCapabilityOffset,\r
+ NULL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // We need to enable ARI feature before calculate BusReservation,\r
+ // because FirstVFOffset and VFStride may change after that.\r
+ //\r
+ EFI_PCI_IO_PROTOCOL *ParentPciIo;\r
+ UINT32 Data32;\r
\r
- Status = LocatePciExpressCapabilityRegBlock (\r
- PciIoDevice,\r
- EFI_PCIE_CAPABILITY_ID_SRIOV,\r
- &PciIoDevice->SrIovCapabilityOffset,\r
- NULL\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- DEBUG ((\r
- EFI_D_INFO,\r
- "PCI-IOV B%x.D%x.F%x - SRIOV Cap offset - 0x%x\n",\r
- (UINTN)Bus,\r
- (UINTN)Device,\r
- (UINTN)Func,\r
- (UINTN)PciIoDevice->SrIovCapabilityOffset\r
- ));\r
- }\r
+ //\r
+ // Check if its parent supports ARI forwarding.\r
+ //\r
+ ParentPciIo = &Bridge->PciIo;\r
+ ParentPciIo->Pci.Read (\r
+ ParentPciIo, \r
+ EfiPciIoWidthUint32,\r
+ Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_OFFSET,\r
+ 1,\r
+ &Data32\r
+ );\r
+ if ((Data32 & EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_ARI_FORWARDING) != 0) {\r
+ //\r
+ // ARI forward support in bridge, so enable it.\r
+ //\r
+ ParentPciIo->Pci.Read (\r
+ ParentPciIo,\r
+ EfiPciIoWidthUint32,\r
+ Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET,\r
+ 1,\r
+ &Data32\r
+ );\r
+ if ((Data32 & EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING) == 0) {\r
+ Data32 |= EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING;\r
+ ParentPciIo->Pci.Write (\r
+ ParentPciIo,\r
+ EfiPciIoWidthUint32,\r
+ Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET,\r
+ 1,\r
+ &Data32\r
+ );\r
+ DEBUG ((\r
+ EFI_D_INFO,\r
+ " ARI: forwarding enabled for PPB[%02x:%02x:%02x]\n",\r
+ Bridge->BusNumber,\r
+ Bridge->DeviceNumber,\r
+ Bridge->FunctionNumber\r
+ ));\r
+ }\r
+ }\r
\r
- Status = LocatePciExpressCapabilityRegBlock (\r
- PciIoDevice,\r
- EFI_PCIE_CAPABILITY_ID_MRIOV,\r
- &PciIoDevice->MrIovCapabilityOffset,\r
- NULL\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- DEBUG ((\r
- EFI_D_INFO,\r
- "PCI-IOV B%x.D%x.F%x - MRIOV Cap offset - 0x%x\n",\r
- (UINTN)Bus,\r
- (UINTN)Device,\r
- (UINTN)Func,\r
- (UINTN)PciIoDevice->MrIovCapabilityOffset\r
- ));\r
+ DEBUG ((EFI_D_INFO, " ARI: CapOffset = 0x%x\n", PciIoDevice->AriCapabilityOffset));\r
+ }\r
}\r
\r
//\r
- // Calculate SystemPageSize\r
+ // Initialization for SR-IOV\r
//\r
- if ((PciIoDevice->SrIovCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport)& EFI_PCI_IOV_POLICY_SRIOV) != 0)) {\r
\r
- PciIo->Pci.Read (\r
- PciIo,\r
- EfiPciIoWidthUint32,\r
- PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SUPPORTED_PAGE_SIZE,\r
- 1,\r
- &PciIoDevice->SystemPageSize\r
- );\r
- DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - SupportedPageSize - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, PciIoDevice->SystemPageSize));\r
+ if (PcdGetBool (PcdSrIovSupport)) {\r
+ Status = LocatePciExpressCapabilityRegBlock (\r
+ PciIoDevice,\r
+ EFI_PCIE_CAPABILITY_ID_SRIOV,\r
+ &PciIoDevice->SrIovCapabilityOffset,\r
+ NULL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ UINT32 SupportedPageSize;\r
+ UINT16 VFStride;\r
+ UINT16 FirstVFOffset;\r
+ UINT16 Data16;\r
+ UINT32 PFRid;\r
+ UINT32 LastVF;\r
\r
- PciIoDevice->SystemPageSize = (PcdGet32(PcdSrIovSystemPageSize) & PciIoDevice->SystemPageSize);\r
- ASSERT (PciIoDevice->SystemPageSize != 0);\r
+ //\r
+ // If the SR-IOV device is an ARI device, then Set ARI Capable Hierarchy for the device.\r
+ //\r
+ if (PcdGetBool (PcdAriSupport) && PciIoDevice->AriCapabilityOffset != 0) {\r
+ PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL,\r
+ 1,\r
+ &Data16\r
+ );\r
+ Data16 |= EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL_ARI_HIERARCHY;\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL,\r
+ 1,\r
+ &Data16\r
+ );\r
+ }\r
\r
- PciIo->Pci.Write (\r
- PciIo,\r
- EfiPciIoWidthUint32,\r
- PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SYSTEM_PAGE_SIZE,\r
- 1,\r
- &PciIoDevice->SystemPageSize\r
- );\r
- DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - SystemPageSize - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, PciIoDevice->SystemPageSize));\r
- //\r
- // Adjust SystemPageSize for Alignment usage later\r
- //\r
- PciIoDevice->SystemPageSize <<= 12;\r
- }\r
+ //\r
+ // Calculate SystemPageSize\r
+ //\r
\r
- // Calculate BusReservation for PCI IOV\r
- //\r
- if ((PciIoDevice->SrIovCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport)& EFI_PCI_IOV_POLICY_SRIOV) != 0)) {\r
- UINT16 VFStride;\r
- UINT16 FirstVFOffset;\r
- UINT32 PFRID;\r
- UINT32 LastVF;\r
+ PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SUPPORTED_PAGE_SIZE,\r
+ 1,\r
+ &SupportedPageSize\r
+ );\r
+ PciIoDevice->SystemPageSize = (PcdGet32 (PcdSrIovSystemPageSize) & SupportedPageSize);\r
+ ASSERT (PciIoDevice->SystemPageSize != 0);\r
+\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SYSTEM_PAGE_SIZE,\r
+ 1,\r
+ &PciIoDevice->SystemPageSize\r
+ );\r
+ //\r
+ // Adjust SystemPageSize for Alignment usage later\r
+ //\r
+ PciIoDevice->SystemPageSize <<= 12;\r
\r
- //\r
- // Read First FirstVFOffset, InitialVFs, and VFStride\r
- //\r
- PciIo->Pci.Read (\r
- PciIo,\r
- EfiPciIoWidthUint16,\r
- PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_FIRSTVF,\r
- 1,\r
- &FirstVFOffset\r
- );\r
- DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - FirstVFOffset - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, (UINTN)FirstVFOffset));\r
-\r
- PciIo->Pci.Read (\r
- PciIo,\r
- EfiPciIoWidthUint16,\r
- PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_INITIALVFS,\r
- 1,\r
- &PciIoDevice->InitialVFs\r
- );\r
- DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - InitialVFs - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, (UINTN)PciIoDevice->InitialVFs));\r
-\r
- PciIo->Pci.Read (\r
- PciIo,\r
- EfiPciIoWidthUint16,\r
- PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_VFSTRIDE,\r
- 1,\r
- &VFStride\r
- );\r
- DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - VFStride - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, (UINTN)VFStride));\r
+ //\r
+ // Calculate BusReservation for PCI IOV\r
+ //\r
\r
- //\r
- // Calculate LastVF\r
- //\r
- PFRID = EFI_PCI_RID(Bus, Device, Func);\r
- LastVF = PFRID + FirstVFOffset + (PciIoDevice->InitialVFs - 1) * VFStride;\r
+ //\r
+ // Read First FirstVFOffset, InitialVFs, and VFStride\r
+ //\r
+ PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_FIRSTVF,\r
+ 1,\r
+ &FirstVFOffset\r
+ );\r
+ PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_INITIALVFS,\r
+ 1,\r
+ &PciIoDevice->InitialVFs\r
+ );\r
+ PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_VFSTRIDE,\r
+ 1,\r
+ &VFStride\r
+ );\r
+ //\r
+ // Calculate LastVF\r
+ //\r
+ PFRid = EFI_PCI_RID(Bus, Device, Func);\r
+ LastVF = PFRid + FirstVFOffset + (PciIoDevice->InitialVFs - 1) * VFStride;\r
\r
- //\r
- // Calculate ReservedBusNum for this PF\r
- //\r
- PciIoDevice->ReservedBusNum = (UINT16)(EFI_PCI_BUS_OF_RID (LastVF) - Bus + 1);\r
- DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - reserved bus number - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, (UINTN)PciIoDevice->ReservedBusNum));\r
+ //\r
+ // Calculate ReservedBusNum for this PF\r
+ //\r
+ PciIoDevice->ReservedBusNum = (UINT16)(EFI_PCI_BUS_OF_RID (LastVF) - Bus + 1);\r
+\r
+ DEBUG ((\r
+ EFI_D_INFO,\r
+ " SR-IOV: SupportedPageSize = 0x%x; SystemPageSize = 0x%x; FirstVFOffset = 0x%x;\n",\r
+ SupportedPageSize, PciIoDevice->SystemPageSize >> 12, FirstVFOffset\r
+ ));\r
+ DEBUG ((\r
+ EFI_D_INFO,\r
+ " InitialVFs = 0x%x; ReservedBusNum = 0x%x; CapOffset = 0x%x\n",\r
+ PciIoDevice->InitialVFs, PciIoDevice->ReservedBusNum, PciIoDevice->SrIovCapabilityOffset\r
+ ));\r
+ }\r
}\r
\r
+ if (PcdGetBool (PcdMrIovSupport)) {\r
+ Status = LocatePciExpressCapabilityRegBlock (\r
+ PciIoDevice,\r
+ EFI_PCIE_CAPABILITY_ID_MRIOV,\r
+ &PciIoDevice->MrIovCapabilityOffset,\r
+ NULL\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_INFO, " MR-IOV: CapOffset = 0x%x\n", PciIoDevice->MrIovCapabilityOffset));\r
+ }\r
+ }\r
\r
//\r
// Initialize the reserved resource list\r
Func\r
);\r
\r
+ if (EFI_ERROR (Status) && Func == 0) {\r
+ //\r
+ // go to next device if there is no Function 0\r
+ //\r
+ break;\r
+ }\r
+\r
if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci))) {\r
\r
Register = 0;\r