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