/** @file\r
PCI resouces support functions implemntation for PCI Bus module.\r
\r
-Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<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
PCI_RESOURCE_NODE *Node;\r
UINT64 Offset;\r
EFI_PCI_PLATFORM_POLICY PciPolicy;\r
+ UINT64 PaddingAperture;\r
\r
if (!mPolicyDetermined) {\r
//\r
mPolicyDetermined = TRUE;\r
}\r
\r
- Aperture = 0;\r
+ Aperture = 0;\r
+ PaddingAperture = 0;\r
\r
if (Bridge == NULL) {\r
return ;\r
}\r
\r
- CurrentLink = Bridge->ChildList.ForwardLink;\r
-\r
//\r
// Assume the bridge is aligned\r
//\r
- while (CurrentLink != &Bridge->ChildList) {\r
+ for ( CurrentLink = GetFirstNode (&Bridge->ChildList)\r
+ ; !IsNull (&Bridge->ChildList, CurrentLink)\r
+ ; CurrentLink = GetNextNode (&Bridge->ChildList, CurrentLink)\r
+ ) {\r
\r
Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
-\r
+ if (Node->ResourceUsage == PciResUsagePadding) {\r
+ ASSERT (PaddingAperture == 0);\r
+ PaddingAperture = Node->Length;\r
+ continue;\r
+ }\r
//\r
// Consider the aperture alignment\r
//\r
// Increment aperture by the length of node\r
//\r
Aperture += Node->Length;\r
-\r
- CurrentLink = CurrentLink->ForwardLink;\r
}\r
\r
//\r
- // At last, adjust the aperture with the bridge's\r
- // alignment\r
+ // Adjust the aperture with the bridge's alignment\r
//\r
Offset = Aperture & (Bridge->Alignment);\r
\r
Bridge->Alignment = Node->Alignment;\r
}\r
}\r
+\r
+ //\r
+ // Hotplug controller needs padding resources.\r
+ // Use the larger one between the padding resource and actual occupied resource.\r
+ //\r
+ Bridge->Length = MAX (Bridge->Length, PaddingAperture);\r
}\r
\r
/**\r
IN PCI_RESOURCE_NODE *Bridge\r
)\r
{\r
- UINT64 Aperture;\r
+ UINT64 Aperture[2];\r
LIST_ENTRY *CurrentLink;\r
PCI_RESOURCE_NODE *Node;\r
\r
- UINT64 Offset;\r
-\r
- Aperture = 0;\r
-\r
if (Bridge == NULL) {\r
return ;\r
}\r
return ;\r
}\r
\r
- CurrentLink = Bridge->ChildList.ForwardLink;\r
-\r
+ Aperture[PciResUsageTypical] = 0;\r
+ Aperture[PciResUsagePadding] = 0;\r
//\r
// Assume the bridge is aligned\r
//\r
- while (CurrentLink != &Bridge->ChildList) {\r
-\r
+ for ( CurrentLink = GetFirstNode (&Bridge->ChildList)\r
+ ; !IsNull (&Bridge->ChildList, CurrentLink)\r
+ ; CurrentLink = GetNextNode (&Bridge->ChildList, CurrentLink)\r
+ ) {\r
Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
\r
//\r
- // Apply padding resource if available\r
+ // It's possible for a bridge to contain multiple padding resource\r
+ // nodes due to DegradeResource().\r
//\r
- Offset = Aperture & (Node->Alignment);\r
-\r
- if (Offset != 0) {\r
-\r
- Aperture = Aperture + (Node->Alignment + 1) - Offset;\r
-\r
- }\r
-\r
+ ASSERT ((Node->ResourceUsage == PciResUsageTypical) ||\r
+ (Node->ResourceUsage == PciResUsagePadding));\r
+ ASSERT (Node->ResourceUsage < ARRAY_SIZE (Aperture));\r
//\r
// Recode current aperture as a offset\r
- // this offset will be used in future real allocation\r
+ // Apply padding resource to meet alignment requirement\r
+ // Node offset will be used in future real allocation\r
//\r
- Node->Offset = Aperture;\r
+ Node->Offset = ALIGN_VALUE (Aperture[Node->ResourceUsage], Node->Alignment + 1);\r
\r
//\r
- // Increment aperture by the length of node\r
+ // Record the total aperture.\r
//\r
- Aperture += Node->Length;\r
-\r
- //\r
- // Consider the aperture alignment\r
- //\r
- CurrentLink = CurrentLink->ForwardLink;\r
+ Aperture[Node->ResourceUsage] = Node->Offset + Node->Length;\r
}\r
\r
//\r
- // At last, adjust the aperture with the bridge's\r
- // alignment\r
+ // Adjust the aperture with the bridge's alignment\r
//\r
- Offset = Aperture & (Bridge->Alignment);\r
- if (Offset != 0) {\r
- Aperture = Aperture + (Bridge->Alignment + 1) - Offset;\r
- }\r
+ Aperture[PciResUsageTypical] = ALIGN_VALUE (Aperture[PciResUsageTypical], Bridge->Alignment + 1);\r
+ Aperture[PciResUsagePadding] = ALIGN_VALUE (Aperture[PciResUsagePadding], Bridge->Alignment + 1);\r
\r
//\r
- // If the bridge has already padded the resource and the\r
- // amount of padded resource is larger, then keep the\r
- // padded resource\r
+ // Hotplug controller needs padding resources.\r
+ // Use the larger one between the padding resource and actual occupied resource.\r
//\r
- if (Bridge->Length < Aperture) {\r
- Bridge->Length = Aperture;\r
- }\r
+ Bridge->Length = MAX (Aperture[PciResUsageTypical], Aperture[PciResUsagePadding]);\r
\r
//\r
- // At last, adjust the bridge's alignment to the first child's alignment\r
- // if the bridge has at least one child\r
+ // Adjust the bridge's alignment to the MAX (first) alignment of all children.\r
//\r
CurrentLink = Bridge->ChildList.ForwardLink;\r
if (CurrentLink != &Bridge->ChildList) {\r
{\r
PCI_RESOURCE_NODE *Node;\r
\r
- DEBUG ((\r
- EFI_D_INFO,\r
- "PCI-IOV B%x.D%x.F%x - VfResource (Bar - 0x%x) (Type - 0x%x) (Length - 0x%x)\n",\r
- (UINTN)PciDev->BusNumber,\r
- (UINTN)PciDev->DeviceNumber,\r
- (UINTN)PciDev->FunctionNumber,\r
- (UINTN)Bar,\r
- (UINTN)ResType,\r
- (UINTN)Length\r
- ));\r
-\r
Node = CreateResourceNode (PciDev, Length, Alignment, Bar, ResType, ResUsage);\r
if (Node == NULL) {\r
return Node;\r
IN PCI_RESOURCE_NODE *PMem64Node\r
)\r
{\r
- PCI_IO_DEVICE *Temp;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
LIST_ENTRY *ChildDeviceLink;\r
LIST_ENTRY *ChildNodeLink;\r
LIST_ENTRY *NextChildNodeLink;\r
- PCI_RESOURCE_NODE *TempNode;\r
+ PCI_RESOURCE_NODE *ResourceNode;\r
\r
- //\r
- // If any child device has both option ROM and 64-bit BAR, degrade its PMEM64/MEM64\r
- // requests in case that if a legacy option ROM image can not access 64-bit resources.\r
- //\r
- ChildDeviceLink = Bridge->ChildList.ForwardLink;\r
- while (ChildDeviceLink != NULL && ChildDeviceLink != &Bridge->ChildList) {\r
- Temp = PCI_IO_DEVICE_FROM_LINK (ChildDeviceLink);\r
- if (Temp->RomSize != 0) {\r
- if (!IsListEmpty (&Mem64Node->ChildList)) { \r
- ChildNodeLink = Mem64Node->ChildList.ForwardLink;\r
- while (ChildNodeLink != &Mem64Node->ChildList) {\r
- TempNode = RESOURCE_NODE_FROM_LINK (ChildNodeLink);\r
- NextChildNodeLink = ChildNodeLink->ForwardLink;\r
-\r
- if (TempNode->PciDev == Temp) {\r
- RemoveEntryList (ChildNodeLink);\r
- InsertResourceNode (Mem32Node, TempNode);\r
+ if (FeaturePcdGet (PcdPciDegradeResourceForOptionRom)) {\r
+ //\r
+ // If any child device has both option ROM and 64-bit BAR, degrade its PMEM64/MEM64\r
+ // requests in case that if a legacy option ROM image can not access 64-bit resources.\r
+ //\r
+ ChildDeviceLink = Bridge->ChildList.ForwardLink;\r
+ while (ChildDeviceLink != NULL && ChildDeviceLink != &Bridge->ChildList) {\r
+ PciIoDevice = PCI_IO_DEVICE_FROM_LINK (ChildDeviceLink);\r
+ if (PciIoDevice->RomSize != 0) {\r
+ if (!IsListEmpty (&Mem64Node->ChildList)) {\r
+ ChildNodeLink = Mem64Node->ChildList.ForwardLink;\r
+ while (ChildNodeLink != &Mem64Node->ChildList) {\r
+ ResourceNode = RESOURCE_NODE_FROM_LINK (ChildNodeLink);\r
+ NextChildNodeLink = ChildNodeLink->ForwardLink;\r
+\r
+ if ((ResourceNode->PciDev == PciIoDevice) &&\r
+ (ResourceNode->Virtual || !PciIoDevice->PciBar[ResourceNode->Bar].BarTypeFixed)\r
+ ) {\r
+ RemoveEntryList (ChildNodeLink);\r
+ InsertResourceNode (Mem32Node, ResourceNode);\r
+ }\r
+ ChildNodeLink = NextChildNodeLink;\r
}\r
- ChildNodeLink = NextChildNodeLink;\r
- } \r
- }\r
-\r
- if (!IsListEmpty (&PMem64Node->ChildList)) { \r
- ChildNodeLink = PMem64Node->ChildList.ForwardLink;\r
- while (ChildNodeLink != &PMem64Node->ChildList) {\r
- TempNode = RESOURCE_NODE_FROM_LINK (ChildNodeLink);\r
- NextChildNodeLink = ChildNodeLink->ForwardLink;\r
+ }\r
\r
- if (TempNode->PciDev == Temp) {\r
- RemoveEntryList (ChildNodeLink);\r
- InsertResourceNode (PMem32Node, TempNode);\r
+ if (!IsListEmpty (&PMem64Node->ChildList)) {\r
+ ChildNodeLink = PMem64Node->ChildList.ForwardLink;\r
+ while (ChildNodeLink != &PMem64Node->ChildList) {\r
+ ResourceNode = RESOURCE_NODE_FROM_LINK (ChildNodeLink);\r
+ NextChildNodeLink = ChildNodeLink->ForwardLink;\r
+\r
+ if ((ResourceNode->PciDev == PciIoDevice) &&\r
+ (ResourceNode->Virtual || !PciIoDevice->PciBar[ResourceNode->Bar].BarTypeFixed)\r
+ ) {\r
+ RemoveEntryList (ChildNodeLink);\r
+ InsertResourceNode (PMem32Node, ResourceNode);\r
+ }\r
+ ChildNodeLink = NextChildNodeLink;\r
}\r
- ChildNodeLink = NextChildNodeLink;\r
- } \r
- }\r
+ }\r
\r
+ }\r
+ ChildDeviceLink = ChildDeviceLink->ForwardLink;\r
}\r
- ChildDeviceLink = ChildDeviceLink->ForwardLink;\r
}\r
\r
//\r
);\r
\r
Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;\r
-\r
- DEBUG ((\r
- EFI_D_INFO,\r
- "PCI-IOV B%x.D%x.F%x - VF Bar (Offset - 0x%x) 32Mem (Address - 0x%x)\n",\r
- (UINTN)Node->PciDev->BusNumber,\r
- (UINTN)Node->PciDev->DeviceNumber,\r
- (UINTN)Node->PciDev->FunctionNumber,\r
- (UINTN)(Node->PciDev->VfPciBar[Node->Bar]).Offset,\r
- (UINTN)Address\r
- ));\r
-\r
break;\r
\r
case PciBarTypeMem64:\r
);\r
\r
Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;\r
-\r
- DEBUG ((\r
- EFI_D_INFO,\r
- "PCI-IOV B%x.D%x.F%x - VF Bar (Offset - 0x%x) 64Mem (Address - 0x%lx)\n",\r
- (UINTN)Node->PciDev->BusNumber,\r
- (UINTN)Node->PciDev->DeviceNumber,\r
- (UINTN)Node->PciDev->FunctionNumber,\r
- (UINTN)(Node->PciDev->VfPciBar[Node->Bar]).Offset,\r
- (UINT64)Address\r
- ));\r
-\r
break;\r
\r
case PciBarTypeIo16:\r
\r
case PPB_BAR_0:\r
case PPB_BAR_1:\r
- PciIo->Pci.Write (\r
+ switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {\r
+\r
+ case PciBarTypeIo16:\r
+ case PciBarTypeIo32:\r
+ case PciBarTypeMem32:\r
+ case PciBarTypePMem32:\r
+\r
+ PciIo->Pci.Write (\r
PciIo,\r
EfiPciIoWidthUint32,\r
(Node->PciDev->PciBar[Node->Bar]).Offset,\r
&Address\r
);\r
\r
- Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
- Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
+ break;\r
+\r
+ case PciBarTypeMem64:\r
+ case PciBarTypePMem64:\r
+\r
+ Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);\r
+\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ (Node->PciDev->PciBar[Node->Bar]).Offset,\r
+ 1,\r
+ &Address32\r
+ );\r
+\r
+ Address32 = (UINT32) RShiftU64 (Address, 32);\r
\r
+ PciIo->Pci.Write (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4),\r
+ 1,\r
+ &Address32\r
+ );\r
+\r
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
break;\r
\r
case PPB_IO_RANGE:\r
InitializeListHead (&ResourcePool->ChildList);\r
}\r
\r
-\r
-/**\r
- Get all resource information for given Pci device.\r
-\r
- @param PciDev Pci device instance.\r
- @param IoBridge Io resource node.\r
- @param Mem32Bridge 32-bit memory node.\r
- @param PMem32Bridge 32-bit Pmemory node.\r
- @param Mem64Bridge 64-bit memory node.\r
- @param PMem64Bridge 64-bit PMemory node.\r
- @param IoPool Link list header for Io resource.\r
- @param Mem32Pool Link list header for 32-bit memory.\r
- @param PMem32Pool Link list header for 32-bit Prefetchable memory.\r
- @param Mem64Pool Link list header for 64-bit memory.\r
- @param PMem64Pool Link list header for 64-bit Prefetchable memory.\r
-\r
-**/\r
-VOID\r
-GetResourceMap (\r
- IN PCI_IO_DEVICE *PciDev,\r
- IN PCI_RESOURCE_NODE **IoBridge,\r
- IN PCI_RESOURCE_NODE **Mem32Bridge,\r
- IN PCI_RESOURCE_NODE **PMem32Bridge,\r
- IN PCI_RESOURCE_NODE **Mem64Bridge,\r
- IN PCI_RESOURCE_NODE **PMem64Bridge,\r
- IN PCI_RESOURCE_NODE *IoPool,\r
- IN PCI_RESOURCE_NODE *Mem32Pool,\r
- IN PCI_RESOURCE_NODE *PMem32Pool,\r
- IN PCI_RESOURCE_NODE *Mem64Pool,\r
- IN PCI_RESOURCE_NODE *PMem64Pool\r
- )\r
-{\r
-\r
- PCI_RESOURCE_NODE *Temp;\r
- LIST_ENTRY *CurrentLink;\r
-\r
- CurrentLink = IoPool->ChildList.ForwardLink;\r
-\r
- //\r
- // Get Io resource map\r
- //\r
- while (CurrentLink != &IoPool->ChildList) {\r
-\r
- Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
-\r
- if (Temp->PciDev == PciDev) {\r
- *IoBridge = Temp;\r
- }\r
-\r
- CurrentLink = CurrentLink->ForwardLink;\r
- }\r
-\r
- //\r
- // Get Mem32 resource map\r
- //\r
- CurrentLink = Mem32Pool->ChildList.ForwardLink;\r
-\r
- while (CurrentLink != &Mem32Pool->ChildList) {\r
-\r
- Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
-\r
- if (Temp->PciDev == PciDev) {\r
- *Mem32Bridge = Temp;\r
- }\r
-\r
- CurrentLink = CurrentLink->ForwardLink;\r
- }\r
-\r
- //\r
- // Get Pmem32 resource map\r
- //\r
- CurrentLink = PMem32Pool->ChildList.ForwardLink;\r
-\r
- while (CurrentLink != &PMem32Pool->ChildList) {\r
-\r
- Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
-\r
- if (Temp->PciDev == PciDev) {\r
- *PMem32Bridge = Temp;\r
- }\r
-\r
- CurrentLink = CurrentLink->ForwardLink;\r
- }\r
-\r
- //\r
- // Get Mem64 resource map\r
- //\r
- CurrentLink = Mem64Pool->ChildList.ForwardLink;\r
-\r
- while (CurrentLink != &Mem64Pool->ChildList) {\r
-\r
- Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
-\r
- if (Temp->PciDev == PciDev) {\r
- *Mem64Bridge = Temp;\r
- }\r
-\r
- CurrentLink = CurrentLink->ForwardLink;\r
- }\r
-\r
- //\r
- // Get Pmem64 resource map\r
- //\r
- CurrentLink = PMem64Pool->ChildList.ForwardLink;\r
-\r
- while (CurrentLink != &PMem64Pool->ChildList) {\r
-\r
- Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
-\r
- if (Temp->PciDev == PciDev) {\r
- *PMem64Bridge = Temp;\r
- }\r
-\r
- CurrentLink = CurrentLink->ForwardLink;\r
- }\r
-}\r
-\r
/**\r
Destory given resource tree.\r
\r