/** @file\r
PCI emumeration support functions implementation for PCI Bus module.\r
\r
-Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2018, 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
\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
\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
PciSetDeviceAttribute (PciIoDevice, OldCommand, OldBridgeControl, EFI_SET_ATTRIBUTES);\r
\r
//\r
- // Enable other supported attributes but not defined in PCI_IO_PROTOCOL\r
- //\r
- PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE);\r
+ // Enable other PCI supported attributes but not defined in PCI_IO_PROTOCOL\r
+ // For PCI Express devices, Memory Write and Invalidate is hardwired to 0b so only enable it for PCI devices.\r
+ if (!PciIoDevice->IsPciExp) {\r
+ PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE);\r
+ }\r
}\r
\r
FastB2BSupport = TRUE;\r
{\r
EFI_STATUS Status;\r
UINTN BarIndex;\r
- UINTN BarEndIndex;\r
BOOLEAN SetFlag;\r
VOID *Configuration;\r
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
break;\r
}\r
\r
- BarIndex = (UINTN) Ptr->AddrTranslationOffset;\r
- BarEndIndex = BarIndex;\r
-\r
- //\r
- // Update all the bars in the device\r
- //\r
- if (BarIndex == PCI_BAR_ALL) {\r
- BarIndex = 0;\r
- BarEndIndex = PCI_MAX_BAR - 1;\r
- }\r
-\r
- if (BarIndex > PCI_MAX_BAR) {\r
- Ptr++;\r
- continue;\r
- }\r
+ for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex++) {\r
+ if ((Ptr->AddrTranslationOffset != MAX_UINT64) &&\r
+ (Ptr->AddrTranslationOffset != MAX_UINT8) &&\r
+ (Ptr->AddrTranslationOffset != BarIndex)\r
+ ) {\r
+ //\r
+ // Skip updating when AddrTranslationOffset is not MAX_UINT64 or MAX_UINT8 (wide match).\r
+ // Skip updating when current BarIndex doesn't equal to AddrTranslationOffset.\r
+ // Comparing against MAX_UINT8 is to keep backward compatibility.\r
+ //\r
+ continue;\r
+ }\r
\r
- for (; BarIndex <= BarEndIndex; BarIndex++) {\r
SetFlag = FALSE;\r
switch (Ptr->ResType) {\r
case ACPI_ADDRESS_SPACE_TYPE_MEM:\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
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