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 + -
显示快捷键?