--- /dev/null
+/*++\r
+\r
+Copyright (c) 2006 - 2007, Intel Corporation\r
+All rights reserved. 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
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ PciResourceSupport.c\r
+\r
+Abstract:\r
+\r
+ PCI Bus Driver\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "pcibus.h"\r
+#include "PciResourceSupport.h"\r
+#include "PciCommand.h"\r
+\r
+EFI_STATUS\r
+SkipVGAAperture (\r
+ OUT UINT64 *Start,\r
+ IN UINT64 Length\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ The function is used to skip VGA range\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+// TODO: Start - add argument and description to function comment\r
+// TODO: Length - add argument and description to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ UINT64 Original;\r
+ UINT64 Mask;\r
+ UINT64 StartOffset;\r
+ UINT64 LimitOffset;\r
+\r
+ //\r
+ // For legacy VGA, bit 10 to bit 15 is not decoded\r
+ //\r
+ Mask = 0x3FF;\r
+\r
+ Original = *Start;\r
+ StartOffset = Original & Mask;\r
+ LimitOffset = ((*Start) + Length - 1) & Mask;\r
+ if (LimitOffset >= VGABASE1) {\r
+ *Start = *Start - StartOffset + VGALIMIT2 + 1;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+SkipIsaAliasAperture (\r
+ OUT UINT64 *Start,\r
+ IN UINT64 Length\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This function is used to skip ISA aliasing aperture\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+// TODO: Start - add argument and description to function comment\r
+// TODO: Length - add argument and description to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+\r
+ UINT64 Original;\r
+ UINT64 Mask;\r
+ UINT64 StartOffset;\r
+ UINT64 LimitOffset;\r
+\r
+ //\r
+ // For legacy ISA, bit 10 to bit 15 is not decoded\r
+ //\r
+ Mask = 0x3FF;\r
+\r
+ Original = *Start;\r
+ StartOffset = Original & Mask;\r
+ LimitOffset = ((*Start) + Length - 1) & Mask;\r
+\r
+ if (LimitOffset >= ISABASE) {\r
+ *Start = *Start - StartOffset + ISALIMIT + 1;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+InsertResourceNode (\r
+ PCI_RESOURCE_NODE *Bridge,\r
+ PCI_RESOURCE_NODE *ResNode\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This function inserts a resource node into the resource list.\r
+ The resource list is sorted in descend order.\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+// TODO: Bridge - add argument and description to function comment\r
+// TODO: ResNode - add argument and description to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ LIST_ENTRY *CurrentLink;\r
+ PCI_RESOURCE_NODE *Temp;\r
+ UINT64 ResNodeAlignRest;\r
+ UINT64 TempAlignRest;\r
+\r
+ InsertHeadList (&Bridge->ChildList, &ResNode->Link);\r
+\r
+ CurrentLink = Bridge->ChildList.ForwardLink->ForwardLink;\r
+ while (CurrentLink != &Bridge->ChildList) {\r
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+ if (ResNode->Alignment > Temp->Alignment) {\r
+ break;\r
+ } else if (ResNode->Alignment == Temp->Alignment) {\r
+ ResNodeAlignRest = ResNode->Length & ResNode->Alignment;\r
+ TempAlignRest = Temp->Length & Temp->Alignment;\r
+ if ((ResNodeAlignRest == 0) || (ResNodeAlignRest >= TempAlignRest)) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ SwapListEntries (&ResNode->Link, CurrentLink);\r
+\r
+ CurrentLink = ResNode->Link.ForwardLink;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+MergeResourceTree (\r
+ PCI_RESOURCE_NODE *Dst,\r
+ PCI_RESOURCE_NODE *Res,\r
+ BOOLEAN TypeMerge\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This routine is used to merge two different resource tree in need of\r
+ resoure degradation. For example, if a upstream PPB doesn't support,\r
+ prefetchable memory decoding, the PCI bus driver will choose to call this function\r
+ to merge prefectchable memory resource list into normal memory list.\r
+\r
+ If the TypeMerge is TRUE, Res resource type is changed to the type of destination resource\r
+ type.\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+// TODO: Dst - add argument and description to function comment\r
+// TODO: Res - add argument and description to function comment\r
+// TODO: TypeMerge - add argument and description to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+\r
+ LIST_ENTRY *CurrentLink;\r
+ PCI_RESOURCE_NODE *Temp;\r
+\r
+ while (!IsListEmpty (&Res->ChildList)) {\r
+ CurrentLink = Res->ChildList.ForwardLink;\r
+\r
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+ if (TypeMerge) {\r
+ Temp->ResType = Dst->ResType;\r
+ }\r
+\r
+ RemoveEntryList (CurrentLink);\r
+ InsertResourceNode (Dst, Temp);\r
+\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+CalculateApertureIo16 (\r
+ IN PCI_RESOURCE_NODE *Bridge\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This function is used to calculate the IO16 aperture\r
+ for a bridge.\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+// TODO: Bridge - add argument and description to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+\r
+ UINT64 Aperture;\r
+ LIST_ENTRY *CurrentLink;\r
+ PCI_RESOURCE_NODE *Node;\r
+ UINT64 offset;\r
+ BOOLEAN IsaEnable;\r
+ BOOLEAN VGAEnable;\r
+\r
+ //\r
+ // Always assume there is ISA device and VGA device on the platform\r
+ // will be customized later\r
+ //\r
+ IsaEnable = FALSE;\r
+ VGAEnable = FALSE;\r
+\r
+ if (FeaturePcdGet (PcdPciIsaEnable)){\r
+ IsaEnable = TRUE;\r
+ }\r
+\r
+ if (FeaturePcdGet (PcdPciVgaEnable)){\r
+ VGAEnable = TRUE;\r
+ }\r
+\r
+ Aperture = 0;\r
+\r
+ if (!Bridge) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+ //\r
+ // Assume the bridge is aligned\r
+ //\r
+ while (CurrentLink != &Bridge->ChildList) {\r
+\r
+ Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+ //\r
+ // Consider the aperture alignment\r
+ //\r
+ offset = Aperture & (Node->Alignment);\r
+\r
+ if (offset) {\r
+\r
+ Aperture = Aperture + (Node->Alignment + 1) - offset;\r
+\r
+ }\r
+\r
+ //\r
+ // IsaEnable and VGAEnable can not be implemented now.\r
+ // If both of them are enabled, then the IO resource would\r
+ // become too limited to meet the requirement of most of devices.\r
+ //\r
+\r
+ if (IsaEnable || VGAEnable) {\r
+ if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci)) && !IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {\r
+ //\r
+ // Check if there is need to support ISA/VGA decoding\r
+ // If so, we need to avoid isa/vga aliasing range\r
+ //\r
+ if (IsaEnable) {\r
+ SkipIsaAliasAperture (\r
+ &Aperture,\r
+ Node->Length \r
+ );\r
+ offset = Aperture & (Node->Alignment);\r
+ if (offset) {\r
+ Aperture = Aperture + (Node->Alignment + 1) - offset;\r
+ }\r
+ } else if (VGAEnable) {\r
+ SkipVGAAperture (\r
+ &Aperture,\r
+ Node->Length\r
+ );\r
+ offset = Aperture & (Node->Alignment);\r
+ if (offset) {\r
+ Aperture = Aperture + (Node->Alignment + 1) - offset;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ Node->Offset = Aperture;\r
+\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
+ //\r
+ offset = Aperture & (Bridge->Alignment);\r
+\r
+ if (offset) {\r
+ Aperture = Aperture + (Bridge->Alignment + 1) - offset;\r
+ }\r
+\r
+ Bridge->Length = Aperture;\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
+ //\r
+ CurrentLink = Bridge->ChildList.ForwardLink;\r
+ if (CurrentLink != &Bridge->ChildList) {\r
+ Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+ if (Node->Alignment > Bridge->Alignment) {\r
+ Bridge->Alignment = Node->Alignment;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+CalculateResourceAperture (\r
+ IN PCI_RESOURCE_NODE *Bridge\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This function is used to calculate the resource aperture\r
+ for a given bridge device\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+// TODO: Bridge - add argument and description to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ UINT64 Aperture;\r
+ LIST_ENTRY *CurrentLink;\r
+ PCI_RESOURCE_NODE *Node;\r
+\r
+ UINT64 offset;\r
+\r
+ Aperture = 0;\r
+\r
+ if (!Bridge) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (Bridge->ResType == PciBarTypeIo16) {\r
+ return CalculateApertureIo16 (Bridge);\r
+ }\r
+\r
+ CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+ //\r
+ // Assume the bridge is aligned\r
+ //\r
+ while (CurrentLink != &Bridge->ChildList) {\r
+\r
+ Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+ //\r
+ // Apply padding resource if available\r
+ //\r
+ \r
+ offset = Aperture & (Node->Alignment);\r
+\r
+ if (offset) {\r
+\r
+ Aperture = Aperture + (Node->Alignment + 1) - offset;\r
+\r
+ }\r
+\r
+ //\r
+ // Recode current aperture as a offset\r
+ // this offset will be used in future real allocation\r
+ //\r
+ Node->Offset = Aperture;\r
+\r
+ //\r
+ // Increment aperture by the length of node\r
+ //\r
+ Aperture += Node->Length;\r
+\r
+ //\r
+ // Consider the aperture alignment\r
+ //\r
+ \r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+\r
+ //\r
+ // At last, adjust the aperture with the bridge's\r
+ // alignment\r
+ //\r
+ offset = Aperture & (Bridge->Alignment);\r
+ if (offset) {\r
+ Aperture = Aperture + (Bridge->Alignment + 1) - offset;\r
+ }\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
+ //\r
+ if (Bridge->Length < Aperture) {\r
+ Bridge->Length = Aperture;\r
+ }\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
+ //\r
+ CurrentLink = Bridge->ChildList.ForwardLink;\r
+ if (CurrentLink != &Bridge->ChildList) {\r
+ Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+ if (Node->Alignment > Bridge->Alignment) {\r
+ Bridge->Alignment = Node->Alignment;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+GetResourceFromDevice (\r
+ PCI_IO_DEVICE *PciDev,\r
+ PCI_RESOURCE_NODE *IoNode,\r
+ PCI_RESOURCE_NODE *Mem32Node,\r
+ PCI_RESOURCE_NODE *PMem32Node,\r
+ PCI_RESOURCE_NODE *Mem64Node,\r
+ PCI_RESOURCE_NODE *PMem64Node\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+// TODO: PciDev - add argument and description to function comment\r
+// TODO: IoNode - add argument and description to function comment\r
+// TODO: Mem32Node - add argument and description to function comment\r
+// TODO: PMem32Node - add argument and description to function comment\r
+// TODO: Mem64Node - add argument and description to function comment\r
+// TODO: PMem64Node - add argument and description to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+\r
+ UINT8 Index;\r
+ PCI_RESOURCE_NODE *Node;\r
+ BOOLEAN ResourceRequested;\r
+\r
+ Node = NULL;\r
+ ResourceRequested = FALSE;\r
+\r
+ for (Index = 0; Index < PCI_MAX_BAR; Index++) {\r
+\r
+ switch ((PciDev->PciBar)[Index].BarType) {\r
+\r
+ case PciBarTypeMem32:\r
+\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ (PciDev->PciBar)[Index].Length,\r
+ (PciDev->PciBar)[Index].Alignment,\r
+ Index,\r
+ PciBarTypeMem32,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ InsertResourceNode (\r
+ Mem32Node,\r
+ Node\r
+ );\r
+\r
+ ResourceRequested = TRUE;\r
+ break;\r
+\r
+ case PciBarTypeMem64:\r
+\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ (PciDev->PciBar)[Index].Length,\r
+ (PciDev->PciBar)[Index].Alignment,\r
+ Index,\r
+ PciBarTypeMem64,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ InsertResourceNode (\r
+ Mem64Node,\r
+ Node\r
+ );\r
+\r
+ ResourceRequested = TRUE;\r
+ break;\r
+\r
+ case PciBarTypePMem64:\r
+\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ (PciDev->PciBar)[Index].Length,\r
+ (PciDev->PciBar)[Index].Alignment,\r
+ Index,\r
+ PciBarTypePMem64,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ InsertResourceNode (\r
+ PMem64Node,\r
+ Node\r
+ );\r
+\r
+ ResourceRequested = TRUE;\r
+ break;\r
+\r
+ case PciBarTypePMem32:\r
+\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ (PciDev->PciBar)[Index].Length,\r
+ (PciDev->PciBar)[Index].Alignment,\r
+ Index,\r
+ PciBarTypePMem32,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ InsertResourceNode (\r
+ PMem32Node,\r
+ Node\r
+ );\r
+ ResourceRequested = TRUE;\r
+ break;\r
+\r
+ case PciBarTypeIo16:\r
+ case PciBarTypeIo32:\r
+\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ (PciDev->PciBar)[Index].Length,\r
+ (PciDev->PciBar)[Index].Alignment,\r
+ Index,\r
+ PciBarTypeIo16,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ InsertResourceNode (\r
+ IoNode,\r
+ Node\r
+ );\r
+ ResourceRequested = TRUE;\r
+ break;\r
+\r
+ case PciBarTypeUnknown:\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // If there is no resource requested from this device,\r
+ // then we indicate this device has been allocated naturally.\r
+ //\r
+ if (!ResourceRequested) {\r
+ PciDev->Allocated = TRUE;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+PCI_RESOURCE_NODE *\r
+CreateResourceNode (\r
+ IN PCI_IO_DEVICE *PciDev,\r
+ IN UINT64 Length,\r
+ IN UINT64 Alignment,\r
+ IN UINT8 Bar,\r
+ IN PCI_BAR_TYPE ResType,\r
+ IN PCI_RESOURCE_USAGE ResUsage\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This function is used to create a resource node\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+// TODO: PciDev - add argument and description to function comment\r
+// TODO: Length - add argument and description to function comment\r
+// TODO: Alignment - add argument and description to function comment\r
+// TODO: Bar - add argument and description to function comment\r
+// TODO: ResType - add argument and description to function comment\r
+// TODO: ResUsage - add argument and description to function comment\r
+{\r
+ PCI_RESOURCE_NODE *Node;\r
+\r
+ Node = NULL;\r
+\r
+ Node = AllocatePool (sizeof (PCI_RESOURCE_NODE));\r
+ if (Node == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ ZeroMem (Node, sizeof (PCI_RESOURCE_NODE));\r
+\r
+ Node->Signature = PCI_RESOURCE_SIGNATURE;\r
+ Node->PciDev = PciDev;\r
+ Node->Length = Length;\r
+ Node->Alignment = Alignment;\r
+ Node->Bar = Bar;\r
+ Node->ResType = ResType;\r
+ Node->Reserved = FALSE;\r
+ Node->ResourceUsage = ResUsage;\r
+ InitializeListHead (&Node->ChildList);\r
+ return Node;\r
+}\r
+\r
+EFI_STATUS\r
+CreateResourceMap (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN PCI_RESOURCE_NODE *IoNode,\r
+ IN PCI_RESOURCE_NODE *Mem32Node,\r
+ IN PCI_RESOURCE_NODE *PMem32Node,\r
+ IN PCI_RESOURCE_NODE *Mem64Node,\r
+ IN PCI_RESOURCE_NODE *PMem64Node\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This routine is used to extract resource request from\r
+ device node list.\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+// TODO: Bridge - add argument and description to function comment\r
+// TODO: IoNode - add argument and description to function comment\r
+// TODO: Mem32Node - add argument and description to function comment\r
+// TODO: PMem32Node - add argument and description to function comment\r
+// TODO: Mem64Node - add argument and description to function comment\r
+// TODO: PMem64Node - add argument and description to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ PCI_IO_DEVICE *Temp;\r
+ PCI_RESOURCE_NODE *IoBridge;\r
+ PCI_RESOURCE_NODE *Mem32Bridge;\r
+ PCI_RESOURCE_NODE *PMem32Bridge;\r
+ PCI_RESOURCE_NODE *Mem64Bridge;\r
+ PCI_RESOURCE_NODE *PMem64Bridge;\r
+ LIST_ENTRY *CurrentLink;\r
+\r
+ CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+ while (CurrentLink && CurrentLink != &Bridge->ChildList) {\r
+\r
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+ //\r
+ // Create resource nodes for this device by scanning the\r
+ // Bar array in the device private data\r
+ // If the upstream bridge doesn't support this device,\r
+ // no any resource node will be created for this device\r
+ //\r
+ GetResourceFromDevice (\r
+ Temp,\r
+ IoNode,\r
+ Mem32Node,\r
+ PMem32Node,\r
+ Mem64Node,\r
+ PMem64Node\r
+ );\r
+\r
+ if (IS_PCI_BRIDGE (&Temp->Pci)) {\r
+\r
+ //\r
+ // If the device has children, create a bridge resource node for this PPB\r
+ // Note: For PPB, memory aperture is aligned with 1MB and IO aperture\r
+ // is aligned with 4KB\r
+ // This device is typically a bridge device like PPB and P2C\r
+ //\r
+ IoBridge = CreateResourceNode (\r
+ Temp,\r
+ 0,\r
+ 0xFFF,\r
+ PPB_IO_RANGE,\r
+ PciBarTypeIo16,\r
+ PciResUsageTypical\r
+ ); //0x1000 aligned\r
+ \r
+ Mem32Bridge = CreateResourceNode (\r
+ Temp,\r
+ 0,\r
+ 0xFFFFF,\r
+ PPB_MEM32_RANGE,\r
+ PciBarTypeMem32,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ PMem32Bridge = CreateResourceNode (\r
+ Temp,\r
+ 0,\r
+ 0xFFFFF,\r
+ PPB_PMEM32_RANGE,\r
+ PciBarTypePMem32,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ Mem64Bridge = CreateResourceNode (\r
+ Temp,\r
+ 0,\r
+ 0xFFFFF,\r
+ PPB_MEM64_RANGE,\r
+ PciBarTypeMem64,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ PMem64Bridge = CreateResourceNode (\r
+ Temp,\r
+ 0,\r
+ 0xFFFFF,\r
+ PPB_PMEM64_RANGE,\r
+ PciBarTypePMem64,\r
+ PciResUsageTypical\r
+ );\r
+\r
+ //\r
+ // Recursively create resouce map on this bridge\r
+ //\r
+ CreateResourceMap (\r
+ Temp,\r
+ IoBridge,\r
+ Mem32Bridge,\r
+ PMem32Bridge,\r
+ Mem64Bridge,\r
+ PMem64Bridge\r
+ );\r
+\r
+ if (ResourceRequestExisted (IoBridge)) {\r
+ InsertResourceNode (\r
+ IoNode,\r
+ IoBridge\r
+ );\r
+ } else {\r
+ gBS->FreePool (IoBridge);\r
+ IoBridge = NULL;\r
+ }\r
+\r
+ //\r
+ // If there is node under this resource bridge,\r
+ // then calculate bridge's aperture of this type\r
+ // and insert it into the respective resource tree.\r
+ // If no, delete this resource bridge\r
+ //\r
+ if (ResourceRequestExisted (Mem32Bridge)) {\r
+ InsertResourceNode (\r
+ Mem32Node,\r
+ Mem32Bridge\r
+ );\r
+ } else {\r
+ gBS->FreePool (Mem32Bridge);\r
+ Mem32Bridge = NULL;\r
+ }\r
+\r
+ //\r
+ // If there is node under this resource bridge,\r
+ // then calculate bridge's aperture of this type\r
+ // and insert it into the respective resource tree.\r
+ // If no, delete this resource bridge\r
+ //\r
+ if (ResourceRequestExisted (PMem32Bridge)) {\r
+ InsertResourceNode (\r
+ PMem32Node,\r
+ PMem32Bridge\r
+ );\r
+ } else {\r
+ gBS->FreePool (PMem32Bridge);\r
+ PMem32Bridge = NULL;\r
+ }\r
+\r
+ //\r
+ // If there is node under this resource bridge,\r
+ // then calculate bridge's aperture of this type\r
+ // and insert it into the respective resource tree.\r
+ // If no, delete this resource bridge\r
+ //\r
+ if (ResourceRequestExisted (Mem64Bridge)) {\r
+ InsertResourceNode (\r
+ Mem64Node,\r
+ Mem64Bridge\r
+ );\r
+ } else {\r
+ gBS->FreePool (Mem64Bridge);\r
+ Mem64Bridge = NULL;\r
+ }\r
+\r
+ //\r
+ // If there is node under this resource bridge,\r
+ // then calculate bridge's aperture of this type\r
+ // and insert it into the respective resource tree.\r
+ // If no, delete this resource bridge\r
+ //\r
+ if (ResourceRequestExisted (PMem64Bridge)) {\r
+ InsertResourceNode (\r
+ PMem64Node,\r
+ PMem64Bridge\r
+ );\r
+ } else {\r
+ gBS->FreePool (PMem64Bridge);\r
+ PMem64Bridge = NULL;\r
+ }\r
+\r
+ }\r
+\r
+ //\r
+ // If it is P2C, apply hard coded resource padding\r
+ //\r
+ //\r
+ if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {\r
+ ResourcePaddingForCardBusBridge (\r
+ Temp,\r
+ IoNode,\r
+ Mem32Node,\r
+ PMem32Node,\r
+ Mem64Node,\r
+ PMem64Node\r
+ );\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+ //\r
+ //\r
+ // To do some platform specific resource padding ...\r
+ //\r
+ ResourcePaddingPolicy (\r
+ Bridge,\r
+ IoNode,\r
+ Mem32Node,\r
+ PMem32Node,\r
+ Mem64Node,\r
+ PMem64Node\r
+ );\r
+\r
+ //\r
+ // Degrade resource if necessary\r
+ //\r
+ DegradeResource (\r
+ Bridge,\r
+ Mem32Node,\r
+ PMem32Node,\r
+ Mem64Node,\r
+ PMem64Node\r
+ );\r
+\r
+ //\r
+ // Calculate resource aperture for this bridge device\r
+ //\r
+ CalculateResourceAperture (Mem32Node);\r
+ CalculateResourceAperture (PMem32Node);\r
+ CalculateResourceAperture (Mem64Node);\r
+ CalculateResourceAperture (PMem64Node);\r
+ CalculateResourceAperture (IoNode);\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+ResourcePaddingPolicy (\r
+ PCI_IO_DEVICE *PciDev,\r
+ PCI_RESOURCE_NODE *IoNode,\r
+ PCI_RESOURCE_NODE *Mem32Node,\r
+ PCI_RESOURCE_NODE *PMem32Node,\r
+ PCI_RESOURCE_NODE *Mem64Node,\r
+ PCI_RESOURCE_NODE *PMem64Node\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This function is used to do the resource padding for a specific platform\r
+\r
+Arguments:\r
+\r
+ PciDev - A pointer to the PCI_IO_DEVICE structrue. \r
+ IoNode - A pointer to the PCI_RESOURCE_NODE structrue.\r
+ Mem32Node - A pointer to the PCI_RESOURCE_NODE structrue.\r
+ PMem32Node - A pointer to the PCI_RESOURCE_NODE structrue.\r
+ Mem64Node - A pointer to the PCI_RESOURCE_NODE structrue.\r
+ PMem64Node - A pointer to the PCI_RESOURCE_NODE structrue.\r
+\r
+Returns:\r
+ Status code\r
+\r
+ None\r
+\r
+--*/\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ //\r
+ // Create padding resource node\r
+ //\r
+ if (PciDev->ResourcePaddingDescriptors != NULL) {\r
+ ApplyResourcePadding (\r
+ PciDev,\r
+ IoNode,\r
+ Mem32Node,\r
+ PMem32Node,\r
+ Mem64Node,\r
+ PMem64Node\r
+ );\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+DegradeResource (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN PCI_RESOURCE_NODE *Mem32Node,\r
+ IN PCI_RESOURCE_NODE *PMem32Node,\r
+ IN PCI_RESOURCE_NODE *Mem64Node,\r
+ IN PCI_RESOURCE_NODE *PMem64Node\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This function is used to degrade resource if the upstream bridge \r
+ doesn't support certain resource. Degradation path is \r
+ PMEM64 -> MEM64 -> MEM32\r
+ PMEM64 -> PMEM32 -> MEM32\r
+ IO32 -> IO16\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+// TODO: Bridge - add argument and description to function comment\r
+// TODO: Mem32Node - add argument and description to function comment\r
+// TODO: PMem32Node - add argument and description to function comment\r
+// TODO: Mem64Node - add argument and description to function comment\r
+// TODO: PMem64Node - add argument and description to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+\r
+ //\r
+ // If bridge doesn't support Prefetchable\r
+ // memory64, degrade it to Prefetchable memory32\r
+ //\r
+ if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM64_DECODE_SUPPORTED)) {\r
+ MergeResourceTree (\r
+ PMem32Node,\r
+ PMem64Node,\r
+ TRUE\r
+ );\r
+ } else {\r
+ //\r
+ // if no PMem32 request, still keep PMem64. Otherwise degrade to PMem32\r
+ //\r
+ if (PMem32Node != NULL) {\r
+ MergeResourceTree (\r
+ PMem32Node,\r
+ PMem64Node,\r
+ TRUE\r
+ );\r
+ }\r
+ }\r
+\r
+\r
+ //\r
+ // If bridge doesn't support Mem64\r
+ // degrade it to mem32\r
+ //\r
+ if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_MEM64_DECODE_SUPPORTED)) {\r
+ MergeResourceTree (\r
+ Mem32Node,\r
+ Mem64Node,\r
+ TRUE\r
+ );\r
+ }\r
+\r
+ //\r
+ // If bridge doesn't support Pmem32\r
+ // degrade it to mem32\r
+ //\r
+ if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM32_DECODE_SUPPORTED)) {\r
+ MergeResourceTree (\r
+ Mem32Node,\r
+ PMem32Node,\r
+ TRUE\r
+ );\r
+ }\r
+\r
+ //\r
+ // if bridge supports combined Pmem Mem decoding\r
+ // merge these two type of resource\r
+ //\r
+ if (BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED)) {\r
+ MergeResourceTree (\r
+ Mem32Node,\r
+ PMem32Node,\r
+ FALSE\r
+ );\r
+\r
+ MergeResourceTree (\r
+ Mem64Node,\r
+ PMem64Node,\r
+ FALSE\r
+ );\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+BOOLEAN\r
+BridgeSupportResourceDecode (\r
+ IN PCI_IO_DEVICE *Bridge,\r
+ IN UINT32 Decode\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Bridge - TODO: add argument description\r
+ Decode - TODO: add argument description\r
+\r
+Returns:\r
+\r
+ TODO: add return values\r
+\r
+--*/\r
+{\r
+ /*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+ \r
+ None\r
+\r
+--*/\r
+ if ((Bridge->Decodes) & Decode) {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+EFI_STATUS\r
+ProgramResource (\r
+ IN UINT64 Base,\r
+ IN PCI_RESOURCE_NODE *Bridge\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This function is used to program the resource allocated \r
+ for each resource node\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+// TODO: Base - add argument and description to function comment\r
+// TODO: Bridge - add argument and description to function comment\r
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ LIST_ENTRY *CurrentLink;\r
+ PCI_RESOURCE_NODE *Node;\r
+ EFI_STATUS Status;\r
+\r
+ if (Base == gAllOne) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+ while (CurrentLink != &Bridge->ChildList) {\r
+\r
+ Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+ if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci))) {\r
+\r
+ if (IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {\r
+ ProgramP2C (Base, Node);\r
+ } else {\r
+ ProgramBar (Base, Node);\r
+ }\r
+ } else {\r
+ Status = ProgramResource (Base + Node->Offset, Node);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ ProgramPpbApperture (Base, Node);\r
+ }\r
+\r
+ CurrentLink = CurrentLink->ForwardLink;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ProgramBar (\r
+ IN UINT64 Base,\r
+ IN PCI_RESOURCE_NODE *Node\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+ \r
+ None\r
+\r
+--*/\r
+// TODO: Base - add argument and description to function comment\r
+// TODO: Node - add argument and description to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINT64 Address;\r
+ UINT32 Address32;\r
+\r
+ Address = 0;\r
+ PciIo = &(Node->PciDev->PciIo);\r
+\r
+ Address = Base + Node->Offset;\r
+\r
+ //\r
+ // Indicate pci bus driver has allocated\r
+ // resource for this device\r
+ // It might be a temporary solution here since\r
+ // pci device could have multiple bar\r
+ //\r
+ Node->PciDev->Allocated = TRUE;\r
+\r
+ switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {\r
+\r
+ case PciBarTypeIo16:\r
+ case PciBarTypeIo32:\r
+ case PciBarTypeMem32:\r
+ case PciBarTypePMem32:\r
+\r
+ PciIoWrite (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ (Node->PciDev->PciBar[Node->Bar]).Offset,\r
+ 1,\r
+ &Address\r
+ );\r
+\r
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+\r
+ break;\r
+\r
+ case PciBarTypeMem64:\r
+ case PciBarTypePMem64:\r
+\r
+ Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);\r
+\r
+ PciIoWrite (\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
+ PciIoWrite (\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
+\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ProgramPpbApperture (\r
+ IN UINT64 Base,\r
+ IN PCI_RESOURCE_NODE *Node\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+ \r
+ None\r
+\r
+--*/\r
+// TODO: Base - add argument and description to function comment\r
+// TODO: Node - add argument and description to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINT64 Address;\r
+ UINT32 Address32;\r
+\r
+ Address = 0;\r
+ //\r
+ // if no device south of this PPB, return anyway\r
+ // Apperture is set default in the initialization code\r
+ //\r
+ if (Node->Length == 0 || Node->ResourceUsage == PciResUsagePadding) {\r
+ //\r
+ // For padding resource node, just ignore when programming\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ PciIo = &(Node->PciDev->PciIo);\r
+ Address = Base + Node->Offset;\r
+\r
+ //\r
+ // Indicate the PPB resource has been allocated\r
+ //\r
+ Node->PciDev->Allocated = TRUE;\r
+\r
+ switch (Node->Bar) {\r
+\r
+ case PPB_BAR_0:\r
+ case PPB_BAR_1:\r
+ PciIoWrite (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ (Node->PciDev->PciBar[Node->Bar]).Offset,\r
+ 1,\r
+ &Address\r
+ );\r
+\r
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
+\r
+ break;\r
+\r
+ case PPB_IO_RANGE:\r
+\r
+ Address32 = ((UINT32) (Address)) >> 8;\r
+ PciIoWrite (\r
+ PciIo,\r
+ EfiPciIoWidthUint8,\r
+ 0x1C,\r
+ 1,\r
+ &Address32\r
+ );\r
+\r
+ Address32 >>= 8;\r
+ PciIoWrite (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ 0x30,\r
+ 1,\r
+ &Address32\r
+ );\r
+\r
+ Address32 = (UINT32) (Address + Node->Length - 1);\r
+ Address32 = ((UINT32) (Address32)) >> 8;\r
+ PciIoWrite (\r
+ PciIo,\r
+ EfiPciIoWidthUint8,\r
+ 0x1D,\r
+ 1,\r
+ &Address32\r
+ );\r
+\r
+ Address32 >>= 8;\r
+ PciIoWrite (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ 0x32,\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
+ case PPB_MEM32_RANGE:\r
+\r
+ Address32 = ((UINT32) (Address)) >> 16;\r
+ PciIoWrite (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ 0x20,\r
+ 1,\r
+ &Address32\r
+ );\r
+\r
+ Address32 = (UINT32) (Address + Node->Length - 1);\r
+ Address32 = ((UINT32) (Address32)) >> 16;\r
+ PciIoWrite (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ 0x22,\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
+ case PPB_PMEM32_RANGE:\r
+ case PPB_PMEM64_RANGE:\r
+\r
+ Address32 = ((UINT32) (Address)) >> 16;\r
+ PciIoWrite (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ 0x24,\r
+ 1,\r
+ &Address32\r
+ );\r
+\r
+ Address32 = (UINT32) (Address + Node->Length - 1);\r
+ Address32 = ((UINT32) (Address32)) >> 16;\r
+ PciIoWrite (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ 0x26,\r
+ 1,\r
+ &Address32\r
+ );\r
+\r
+ Address32 = (UINT32) RShiftU64 (Address, 32);\r
+ PciIoWrite (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0x28,\r
+ 1,\r
+ &Address32\r
+ );\r
+\r
+ Address32 = (UINT32) RShiftU64 ((Address + Node->Length - 1), 32);\r
+ PciIoWrite (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0x2C,\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
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ProgrameUpstreamBridgeForRom (\r
+ IN PCI_IO_DEVICE *PciDevice,\r
+ IN UINT32 OptionRomBase,\r
+ IN BOOLEAN Enable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+--*/\r
+// TODO: PciDevice - add argument and description to function comment\r
+// TODO: OptionRomBase - add argument and description to function comment\r
+// TODO: Enable - add argument and description to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ PCI_IO_DEVICE *Parent;\r
+ PCI_RESOURCE_NODE Node;\r
+ //\r
+ // For root bridge, just return.\r
+ //\r
+ Parent = PciDevice->Parent;\r
+ ZeroMem (&Node, sizeof (Node));\r
+ while (Parent) {\r
+ if (!IS_PCI_BRIDGE (&Parent->Pci)) {\r
+ break;\r
+ }\r
+\r
+ Node.PciDev = Parent;\r
+ Node.Length = PciDevice->RomSize;\r
+ Node.Alignment = 0;\r
+ Node.Bar = PPB_MEM32_RANGE;\r
+ Node.ResType = PciBarTypeMem32;\r
+ Node.Offset = 0;\r
+\r
+ //\r
+ // Program PPB to only open a single <= 16<MB apperture\r
+ //\r
+ if (Enable) {\r
+ ProgramPpbApperture (OptionRomBase, &Node);\r
+ PciEnableCommandRegister (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);\r
+ } else {\r
+ InitializePpb (Parent);\r
+ PciDisableCommandRegister (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);\r
+ }\r
+\r
+ Parent = Parent->Parent;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+BOOLEAN\r
+ResourceRequestExisted (\r
+ IN PCI_RESOURCE_NODE *Bridge\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+ Bridge - A pointer to the PCI_RESOURCE_NODE.\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ if (Bridge != NULL) {\r
+ if (!IsListEmpty (&Bridge->ChildList) || Bridge->Length != 0) {\r
+ return TRUE;\r
+ }\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+EFI_STATUS\r
+InitializeResourcePool (\r
+ PCI_RESOURCE_NODE *ResourcePool,\r
+ PCI_BAR_TYPE ResourceType\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+// TODO: ResourcePool - add argument and description to function comment\r
+// TODO: ResourceType - add argument and description to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+\r
+ ZeroMem (ResourcePool, sizeof (PCI_RESOURCE_NODE));\r
+ ResourcePool->ResType = ResourceType;\r
+ ResourcePool->Signature = PCI_RESOURCE_SIGNATURE;\r
+ InitializeListHead (&ResourcePool->ChildList);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+GetResourceMap (\r
+ PCI_IO_DEVICE *PciDev,\r
+ PCI_RESOURCE_NODE **IoBridge,\r
+ PCI_RESOURCE_NODE **Mem32Bridge,\r
+ PCI_RESOURCE_NODE **PMem32Bridge,\r
+ PCI_RESOURCE_NODE **Mem64Bridge,\r
+ PCI_RESOURCE_NODE **PMem64Bridge,\r
+ PCI_RESOURCE_NODE *IoPool,\r
+ PCI_RESOURCE_NODE *Mem32Pool,\r
+ PCI_RESOURCE_NODE *PMem32Pool,\r
+ PCI_RESOURCE_NODE *Mem64Pool,\r
+ PCI_RESOURCE_NODE *PMem64Pool\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+// TODO: PciDev - add argument and description to function comment\r
+// TODO: IoBridge - add argument and description to function comment\r
+// TODO: Mem32Bridge - add argument and description to function comment\r
+// TODO: PMem32Bridge - add argument and description to function comment\r
+// TODO: Mem64Bridge - add argument and description to function comment\r
+// TODO: PMem64Bridge - add argument and description to function comment\r
+// TODO: IoPool - add argument and description to function comment\r
+// TODO: Mem32Pool - add argument and description to function comment\r
+// TODO: PMem32Pool - add argument and description to function comment\r
+// TODO: Mem64Pool - add argument and description to function comment\r
+// TODO: PMem64Pool - add argument and description to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\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
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+DestroyResourceTree (\r
+ IN PCI_RESOURCE_NODE *Bridge\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+// TODO: Bridge - add argument and description to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ PCI_RESOURCE_NODE *Temp;\r
+ LIST_ENTRY *CurrentLink;\r
+\r
+ while (!IsListEmpty (&Bridge->ChildList)) {\r
+\r
+ CurrentLink = Bridge->ChildList.ForwardLink;\r
+\r
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
+\r
+ RemoveEntryList (CurrentLink);\r
+\r
+ if (IS_PCI_BRIDGE (&(Temp->PciDev->Pci))) {\r
+ DestroyResourceTree (Temp);\r
+ }\r
+\r
+ gBS->FreePool (Temp);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+RecordReservedResource (\r
+ IN UINT64 Base,\r
+ IN UINT64 Length,\r
+ IN PCI_BAR_TYPE ResType,\r
+ IN PCI_IO_DEVICE *Bridge\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+// TODO: Base - add argument and description to function comment\r
+// TODO: Length - add argument and description to function comment\r
+// TODO: ResType - add argument and description to function comment\r
+// TODO: Bridge - add argument and description to function comment\r
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ PCI_RESERVED_RESOURCE_LIST *ReservedNode;\r
+\r
+ ReservedNode = AllocatePool (sizeof (PCI_RESERVED_RESOURCE_LIST));\r
+ if (ReservedNode == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ ReservedNode->Signature = RESERVED_RESOURCE_SIGNATURE;\r
+ ReservedNode->Node.Base = Base;\r
+ ReservedNode->Node.Length = Length;\r
+ ReservedNode->Node.ResType = ResType;\r
+\r
+ InsertTailList (&Bridge->ReservedResourceList, &(ReservedNode->Link));\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ResourcePaddingForCardBusBridge (\r
+ PCI_IO_DEVICE *PciDev,\r
+ PCI_RESOURCE_NODE *IoNode,\r
+ PCI_RESOURCE_NODE *Mem32Node,\r
+ PCI_RESOURCE_NODE *PMem32Node,\r
+ PCI_RESOURCE_NODE *Mem64Node,\r
+ PCI_RESOURCE_NODE *PMem64Node\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+// TODO: PciDev - add argument and description to function comment\r
+// TODO: IoNode - add argument and description to function comment\r
+// TODO: Mem32Node - add argument and description to function comment\r
+// TODO: PMem32Node - add argument and description to function comment\r
+// TODO: Mem64Node - add argument and description to function comment\r
+// TODO: PMem64Node - add argument and description to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ PCI_RESOURCE_NODE *Node;\r
+\r
+ Node = NULL;\r
+\r
+ //\r
+ // Memory Base/Limit Register 0\r
+ // Bar 1 denodes memory range 0\r
+ //\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ 0x2000000,\r
+ 0x1ffffff,\r
+ 1,\r
+ PciBarTypeMem32,\r
+ PciResUsagePadding\r
+ );\r
+\r
+ InsertResourceNode (\r
+ Mem32Node,\r
+ Node\r
+ );\r
+\r
+ //\r
+ // Memory Base/Limit Register 1\r
+ // Bar 2 denodes memory range1\r
+ //\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ 0x2000000,\r
+ 0x1ffffff,\r
+ 2,\r
+ PciBarTypePMem32,\r
+ PciResUsagePadding\r
+ );\r
+\r
+ InsertResourceNode (\r
+ PMem32Node,\r
+ Node\r
+ );\r
+\r
+ //\r
+ // Io Base/Limit\r
+ // Bar 3 denodes io range 0\r
+ //\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ 0x100,\r
+ 0xff,\r
+ 3,\r
+ PciBarTypeIo16,\r
+ PciResUsagePadding\r
+ );\r
+\r
+ InsertResourceNode (\r
+ IoNode,\r
+ Node\r
+ );\r
+\r
+ //\r
+ // Io Base/Limit\r
+ // Bar 4 denodes io range 0\r
+ //\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ 0x100,\r
+ 0xff,\r
+ 4,\r
+ PciBarTypeIo16,\r
+ PciResUsagePadding\r
+ );\r
+\r
+ InsertResourceNode (\r
+ IoNode,\r
+ Node\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ProgramP2C (\r
+ IN UINT64 Base,\r
+ IN PCI_RESOURCE_NODE *Node\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+ \r
+ None\r
+\r
+--*/\r
+// TODO: Base - add argument and description to function comment\r
+// TODO: Node - add argument and description to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINT64 Address;\r
+ UINT64 TempAddress;\r
+ UINT16 BridgeControl;\r
+\r
+ Address = 0;\r
+ PciIo = &(Node->PciDev->PciIo);\r
+\r
+ Address = Base + Node->Offset;\r
+\r
+ //\r
+ // Indicate pci bus driver has allocated\r
+ // resource for this device\r
+ // It might be a temporary solution here since\r
+ // pci device could have multiple bar\r
+ //\r
+ Node->PciDev->Allocated = TRUE;\r
+\r
+ switch (Node->Bar) {\r
+\r
+ case P2C_BAR_0:\r
+ PciIoWrite (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ (Node->PciDev->PciBar[Node->Bar]).Offset,\r
+ 1,\r
+ &Address\r
+ );\r
+\r
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
+ break;\r
+\r
+ case P2C_MEM_1:\r
+ PciIoWrite (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0x1c,\r
+ 1,\r
+ &Address\r
+ );\r
+\r
+ TempAddress = Address + Node->Length - 1;\r
+ PciIoWrite (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0x20,\r
+ 1,\r
+ &TempAddress\r
+ );\r
+\r
+ if (Node->ResType == PciBarTypeMem32) {\r
+\r
+ //\r
+ // Set non-prefetchable bit\r
+ //\r
+ PciIoRead (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ 0x3e,\r
+ 1,\r
+ &BridgeControl\r
+ );\r
+\r
+ BridgeControl &= 0xfeff;\r
+ PciIoWrite (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ 0x3e,\r
+ 1,\r
+ &BridgeControl\r
+ );\r
+\r
+ } else {\r
+\r
+ //\r
+ // Set pre-fetchable bit\r
+ //\r
+ PciIoRead (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ 0x3e,\r
+ 1,\r
+ &BridgeControl\r
+ );\r
+\r
+ BridgeControl |= 0x0100;\r
+ PciIoWrite (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ 0x3e,\r
+ 1,\r
+ &BridgeControl\r
+ );\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].BarType = Node->ResType;\r
+\r
+ break;\r
+\r
+ case P2C_MEM_2:\r
+ PciIoWrite (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0x24,\r
+ 1,\r
+ &Address\r
+ );\r
+\r
+ TempAddress = Address + Node->Length - 1;\r
+\r
+ PciIoWrite (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0x28,\r
+ 1,\r
+ &TempAddress\r
+ );\r
+\r
+ if (Node->ResType == PciBarTypeMem32) {\r
+\r
+ //\r
+ // Set non-prefetchable bit\r
+ //\r
+ PciIoRead (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ 0x3e,\r
+ 1,\r
+ &BridgeControl\r
+ );\r
+\r
+ BridgeControl &= 0xfdff;\r
+ PciIoWrite (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ 0x3e,\r
+ 1,\r
+ &BridgeControl\r
+ );\r
+ } else {\r
+\r
+ //\r
+ // Set pre-fetchable bit\r
+ //\r
+ PciIoRead (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ 0x3e,\r
+ 1,\r
+ &BridgeControl\r
+ );\r
+\r
+ BridgeControl |= 0x0200;\r
+ PciIoWrite (\r
+ PciIo,\r
+ EfiPciIoWidthUint16,\r
+ 0x3e,\r
+ 1,\r
+ &BridgeControl\r
+ );\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].BarType = Node->ResType;\r
+ break;\r
+\r
+ case P2C_IO_1:\r
+ PciIoWrite (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0x2c,\r
+ 1,\r
+ &Address\r
+ );\r
+ TempAddress = Address + Node->Length - 1;\r
+ PciIoWrite (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0x30,\r
+ 1,\r
+ &TempAddress\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].BarType = Node->ResType;\r
+\r
+ break;\r
+\r
+ case P2C_IO_2:\r
+ PciIoWrite (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0x34,\r
+ 1,\r
+ &Address\r
+ );\r
+\r
+ TempAddress = Address + Node->Length - 1;\r
+ PciIoWrite (\r
+ PciIo,\r
+ EfiPciIoWidthUint32,\r
+ 0x38,\r
+ 1,\r
+ &TempAddress\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].BarType = Node->ResType;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ApplyResourcePadding (\r
+ PCI_IO_DEVICE *PciDev,\r
+ PCI_RESOURCE_NODE *IoNode,\r
+ PCI_RESOURCE_NODE *Mem32Node,\r
+ PCI_RESOURCE_NODE *PMem32Node,\r
+ PCI_RESOURCE_NODE *Mem64Node,\r
+ PCI_RESOURCE_NODE *PMem64Node\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+ \r
+ None\r
+\r
+--*/\r
+// TODO: PciDev - add argument and description to function comment\r
+// TODO: IoNode - add argument and description to function comment\r
+// TODO: Mem32Node - add argument and description to function comment\r
+// TODO: PMem32Node - add argument and description to function comment\r
+// TODO: Mem64Node - add argument and description to function comment\r
+// TODO: PMem64Node - add argument and description to function comment\r
+// TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
+ PCI_RESOURCE_NODE *Node;\r
+ UINT8 DummyBarIndex;\r
+\r
+ DummyBarIndex = 0;\r
+ Ptr = PciDev->ResourcePaddingDescriptors;\r
+\r
+ while (((EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr)->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
+\r
+ if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {\r
+ if (Ptr->AddrLen != 0) {\r
+\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ Ptr->AddrLen,\r
+ Ptr->AddrRangeMax,\r
+ DummyBarIndex,\r
+ PciBarTypeIo16,\r
+ PciResUsagePadding\r
+ );\r
+ InsertResourceNode (\r
+ IoNode,\r
+ Node\r
+ );\r
+ }\r
+\r
+ Ptr++;\r
+ continue;\r
+ }\r
+\r
+ if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
+\r
+ if (Ptr->AddrSpaceGranularity == 32) {\r
+\r
+ //\r
+ // prefechable\r
+ //\r
+ if (Ptr->SpecificFlag == 0x6) {\r
+ if (Ptr->AddrLen) {\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ Ptr->AddrLen,\r
+ Ptr->AddrRangeMax,\r
+ DummyBarIndex,\r
+ PciBarTypePMem32,\r
+ PciResUsagePadding\r
+ );\r
+ InsertResourceNode (\r
+ PMem32Node,\r
+ Node\r
+ );\r
+ }\r
+\r
+ Ptr++;\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Non-prefechable\r
+ //\r
+ if (Ptr->SpecificFlag == 0) {\r
+ if (Ptr->AddrLen) {\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ Ptr->AddrLen,\r
+ Ptr->AddrRangeMax,\r
+ DummyBarIndex,\r
+ PciBarTypeMem32,\r
+ PciResUsagePadding\r
+ );\r
+ InsertResourceNode (\r
+ Mem32Node,\r
+ Node\r
+ );\r
+ }\r
+\r
+ Ptr++;\r
+ continue;\r
+ }\r
+ }\r
+\r
+ if (Ptr->AddrSpaceGranularity == 64) {\r
+\r
+ //\r
+ // prefechable\r
+ //\r
+ if (Ptr->SpecificFlag == 0x6) {\r
+ if (Ptr->AddrLen) {\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ Ptr->AddrLen,\r
+ Ptr->AddrRangeMax,\r
+ DummyBarIndex,\r
+ PciBarTypePMem64,\r
+ PciResUsagePadding\r
+ );\r
+ InsertResourceNode (\r
+ PMem64Node,\r
+ Node\r
+ );\r
+ }\r
+\r
+ Ptr++;\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Non-prefechable\r
+ //\r
+ if (Ptr->SpecificFlag == 0) {\r
+ if (Ptr->AddrLen) {\r
+ Node = CreateResourceNode (\r
+ PciDev,\r
+ Ptr->AddrLen,\r
+ Ptr->AddrRangeMax,\r
+ DummyBarIndex,\r
+ PciBarTypeMem64,\r
+ PciResUsagePadding\r
+ );\r
+ InsertResourceNode (\r
+ Mem64Node,\r
+ Node\r
+ );\r
+ }\r
+\r
+ Ptr++;\r
+ continue;\r
+ }\r
+ }\r
+ }\r
+\r
+ Ptr++;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+//\r
+// Light PCI bus driver woundn't support hotplug root device\r
+// So no need to pad resource for them\r
+//\r
+VOID\r
+GetResourcePaddingPpb (\r
+ IN PCI_IO_DEVICE *PciIoDevice\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Get resource.\r
+\r
+Arguments:\r
+\r
+ PciIoDevice A pointer to a pci device.\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ if (gPciHotPlugInit) {\r
+ if (PciIoDevice->ResourcePaddingDescriptors == NULL) {\r
+ GetResourcePaddingForHpb (PciIoDevice);\r
+ }\r
+ }\r
+}\r