pciresourcesupport.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,318 行 · 第 1/4 页

C
2,318
字号
/*++

Copyright (c) 2004 - 2006, 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.             

Module Name:

  PciResourceSupport.c
  
Abstract:

  PCI Bus Driver

Revision History

--*/

#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
{
  EFI_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
{

  EFI_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;
  EFI_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;

#ifdef EFI_PCI_ISA_ENABLE
  IsaEnable = TRUE;
#endif

#ifdef EFI_PCI_VGA_ENABLE
  VGAEnable = TRUE;
#endif

  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;
  EFI_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;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?