add SR-IOV support in EDK II.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@9269 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
htao
2009-09-16 09:32:06 +00:00
parent fd53905e69
commit 7fc72ecb0d
11 changed files with 988 additions and 10 deletions

View File

@ -544,6 +544,94 @@ GetResourceFromDevice (
}
//
// Add VF resource
//
for (Index = 0; Index < PCI_MAX_BAR; Index++) {
switch ((PciDev->VfPciBar)[Index].BarType) {
case PciBarTypeMem32:
Node = CreateVfResourceNode (
PciDev,
(PciDev->VfPciBar)[Index].Length,
(PciDev->VfPciBar)[Index].Alignment,
Index,
PciBarTypeMem32,
PciResUsageTypical
);
InsertResourceNode (
Mem32Node,
Node
);
break;
case PciBarTypeMem64:
Node = CreateVfResourceNode (
PciDev,
(PciDev->VfPciBar)[Index].Length,
(PciDev->VfPciBar)[Index].Alignment,
Index,
PciBarTypeMem64,
PciResUsageTypical
);
InsertResourceNode (
Mem64Node,
Node
);
break;
case PciBarTypePMem64:
Node = CreateVfResourceNode (
PciDev,
(PciDev->VfPciBar)[Index].Length,
(PciDev->VfPciBar)[Index].Alignment,
Index,
PciBarTypePMem64,
PciResUsageTypical
);
InsertResourceNode (
PMem64Node,
Node
);
break;
case PciBarTypePMem32:
Node = CreateVfResourceNode (
PciDev,
(PciDev->VfPciBar)[Index].Length,
(PciDev->VfPciBar)[Index].Alignment,
Index,
PciBarTypePMem32,
PciResUsageTypical
);
InsertResourceNode (
PMem32Node,
Node
);
break;
case PciBarTypeIo16:
case PciBarTypeIo32:
break;
case PciBarTypeUnknown:
break;
default:
break;
}
}
// If there is no resource requested from this device,
// then we indicate this device has been allocated naturally.
//
@ -599,6 +687,53 @@ CreateResourceNode (
return Node;
}
/**
This function is used to create a IOV VF resource node.
@param PciDev Pci device instance.
@param Length Length of Io/Memory resource.
@param Alignment Alignment of resource.
@param Bar Bar index.
@param ResType Type of resource: IO/Memory.
@param ResUsage Resource usage.
@return PCI resource node created for given VF PCI device.
NULL means PCI resource node is not created.
**/
PCI_RESOURCE_NODE *
CreateVfResourceNode (
IN PCI_IO_DEVICE *PciDev,
IN UINT64 Length,
IN UINT64 Alignment,
IN UINT8 Bar,
IN PCI_BAR_TYPE ResType,
IN PCI_RESOURCE_USAGE ResUsage
)
{
PCI_RESOURCE_NODE *Node;
DEBUG ((
EFI_D_INFO,
"PCI-IOV B%x.D%x.F%x - VfResource (Bar - 0x%x) (Type - 0x%x) (Length - 0x%x)\n",
(UINTN)PciDev->BusNumber,
(UINTN)PciDev->DeviceNumber,
(UINTN)PciDev->FunctionNumber,
(UINTN)Bar,
(UINTN)ResType,
(UINTN)Length
));
Node = CreateResourceNode (PciDev, Length, Alignment, Bar, ResType, ResUsage);
if (Node == NULL) {
return Node;
}
Node->Virtual = TRUE;
return Node;
}
/**
This function is used to extract resource request from
device node list.
@ -1094,6 +1229,13 @@ ProgramBar (
UINT64 Address;
UINT32 Address32;
//
// Check VF BAR
//
if (Node->Virtual) {
ProgramVfBar (Base, Node);
}
Address = 0;
PciIo = &(Node->PciDev->PciIo);
@ -1159,6 +1301,116 @@ ProgramBar (
}
}
/**
Program IOV VF Bar register for PCI device.
@param Base Base address for PCI device resource to be progammed.
@param Node Point to resoure node structure.
**/
EFI_STATUS
ProgramVfBar (
IN UINT64 Base,
IN PCI_RESOURCE_NODE *Node
)
{
EFI_PCI_IO_PROTOCOL *PciIo;
UINT64 Address;
UINT32 Address32;
ASSERT (Node->Virtual);
if (!Node->Virtual) {
return EFI_UNSUPPORTED;
}
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->VfPciBar[Node->Bar]).BarType) {
case PciBarTypeMem32:
case PciBarTypePMem32:
PciIo->Pci.Write (
PciIo,
EfiPciIoWidthUint32,
(Node->PciDev->VfPciBar[Node->Bar]).Offset,
1,
&Address
);
Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;
DEBUG ((
EFI_D_INFO,
"PCI-IOV B%x.D%x.F%x - VF Bar (Offset - 0x%x) 32Mem (Address - 0x%x)\n",
(UINTN)Node->PciDev->BusNumber,
(UINTN)Node->PciDev->DeviceNumber,
(UINTN)Node->PciDev->FunctionNumber,
(UINTN)(Node->PciDev->VfPciBar[Node->Bar]).Offset,
(UINTN)Address
));
break;
case PciBarTypeMem64:
case PciBarTypePMem64:
Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);
PciIo->Pci.Write (
PciIo,
EfiPciIoWidthUint32,
(Node->PciDev->VfPciBar[Node->Bar]).Offset,
1,
&Address32
);
Address32 = (UINT32) RShiftU64 (Address, 32);
PciIo->Pci.Write (
PciIo,
EfiPciIoWidthUint32,
((Node->PciDev->VfPciBar[Node->Bar]).Offset + 4),
1,
&Address32
);
Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;
DEBUG ((
EFI_D_INFO,
"PCI-IOV B%x.D%x.F%x - VF Bar (Offset - 0x%x) 64Mem (Address - 0x%lx)\n",
(UINTN)Node->PciDev->BusNumber,
(UINTN)Node->PciDev->DeviceNumber,
(UINTN)Node->PciDev->FunctionNumber,
(UINTN)(Node->PciDev->VfPciBar[Node->Bar]).Offset,
(UINT64)Address
));
break;
case PciBarTypeIo16:
case PciBarTypeIo32:
break;
default:
break;
}
return EFI_SUCCESS;
}
/**
Program PCI-PCI bridge apperture.