/** @file\r
PCI emumeration support functions implementation for PCI Bus module.\r
\r
-Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2016, 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
(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
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
\r
DEBUG ((\r
EFI_D_INFO,\r
- " BAR[%d]: Type = %s; Alignment = 0x%x;\tLength = 0x%x;\tOffset = 0x%02x\n",\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
DEBUG ((\r
EFI_D_INFO,\r
- " VFBAR[%d]: Type = %s; Alignment = 0x%x;\tLength = 0x%x;\tOffset = 0x%02x\n",\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
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
UINT8 Value;\r
EFI_PCI_IO_PROTOCOL *PciIo;\r
UINT8 Temp;\r
+ UINT32 PMemBaseLimit;\r
+ UINT16 PrefetchableMemoryBase;\r
+ UINT16 PrefetchableMemoryLimit;\r
\r
PciIoDevice = CreatePciIoDevice (\r
Bridge,\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 (DumpPciBars (PciIoDevice););\r
+ DEBUG_CODE (\r
+ DumpPpbPaddingResource (PciIoDevice, PciBarTypeUnknown);\r
+ DumpPciBars (PciIoDevice);\r
+ );\r
\r
return PciIoDevice;\r
}\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
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 (IS_PCI_LPC (&PciIoDevice->Pci)) {\r
Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;\r
- Attributes |= (mReserveIsaAliases ? EFI_PCI_IO_ATTRIBUTE_ISA_IO : \\r
- EFI_PCI_IO_ATTRIBUTE_ISA_IO_16);\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
if (IS_PCI_VGA (&PciIoDevice->Pci)) {\r
Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;\r
- Attributes |= (mReserveVgaAliases ? EFI_PCI_IO_ATTRIBUTE_VGA_IO : \\r
- EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);\r
+ Attributes |= (mReserveVgaAliases ? (UINT64) EFI_PCI_IO_ATTRIBUTE_VGA_IO : \\r
+ (UINT64) EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);\r
}\r
}\r
\r
//\r
// Assume the PCI Root Bridge supports DAC\r
//\r
- PciIoDevice->Supports |= (EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE |\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
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
//\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
UINT32 Value;\r
UINT32 OriginalValue;\r
UINT32 Mask;\r
- UINT32 Data;\r
- UINT8 Index;\r
EFI_STATUS Status;\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
- }\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
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
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