pcatpcirootbridgeio.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,024 行 · 第 1/2 页
C
1,024 行
if (EFI_ERROR (Status)) {
return Status;
}
Status = PcatRootBridgeIoMemWrite (
This,
Width,
DestAddress,
1,
&Result
);
if (EFI_ERROR (Status)) {
return Status;
}
if (Direction) {
SrcAddress += Stride;
DestAddress += Stride;
} else {
SrcAddress -= Stride;
DestAddress -= Stride;
}
}
return EFI_SUCCESS;
}
EFI_STATUS
PcatRootBridgeIoPciRead (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
)
{
if (Buffer == NULL) {
return EFI_INVALID_PARAMETER;
}
return PcatRootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
}
EFI_STATUS
PcatRootBridgeIoPciWrite (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
)
{
if (Buffer == NULL) {
return EFI_INVALID_PARAMETER;
}
return PcatRootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
}
EFI_STATUS
PcatRootBridgeIoMap (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
IN VOID *HostAddress,
IN OUT UINTN *NumberOfBytes,
OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
OUT VOID **Mapping
)
{
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS PhysicalAddress;
MAP_INFO *MapInfo;
MAP_INFO_INSTANCE *MapInstance;
PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
if ( HostAddress == NULL || NumberOfBytes == NULL ||
DeviceAddress == NULL || Mapping == NULL ) {
return EFI_INVALID_PARAMETER;
}
//
// Perform a fence operation to make sure all memory operations are flushed
//
MEMORY_FENCE();
//
// Initialize the return values to their defaults
//
*Mapping = NULL;
//
// Make sure that Operation is valid
//
if (Operation < 0 || Operation >= EfiPciOperationMaximum) {
return EFI_INVALID_PARAMETER;
}
//
// Most PCAT like chipsets can not handle performing DMA above 4GB.
// If any part of the DMA transfer being mapped is above 4GB, then
// map the DMA transfer to a buffer below 4GB.
//
PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;
if ((PhysicalAddress + *NumberOfBytes) > 0x100000000) {
//
// Common Buffer operations can not be remapped. If the common buffer
// if above 4GB, then it is not possible to generate a mapping, so return
// an error.
//
if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) {
return EFI_UNSUPPORTED;
}
//
// Allocate a MAP_INFO structure to remember the mapping when Unmap() is
// called later.
//
Status = gBS->AllocatePool (
EfiBootServicesData,
sizeof(MAP_INFO),
&MapInfo
);
if (EFI_ERROR (Status)) {
*NumberOfBytes = 0;
return Status;
}
//
// Return a pointer to the MAP_INFO structure in Mapping
//
*Mapping = MapInfo;
//
// Initialize the MAP_INFO structure
//
MapInfo->Operation = Operation;
MapInfo->NumberOfBytes = *NumberOfBytes;
MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES(*NumberOfBytes);
MapInfo->HostAddress = PhysicalAddress;
MapInfo->MappedHostAddress = 0x00000000ffffffff;
//
// Allocate a buffer below 4GB to map the transfer to.
//
Status = gBS->AllocatePages (
AllocateMaxAddress,
EfiBootServicesData,
MapInfo->NumberOfPages,
&MapInfo->MappedHostAddress
);
if (EFI_ERROR(Status)) {
gBS->FreePool (MapInfo);
*NumberOfBytes = 0;
return Status;
}
//
// If this is a read operation from the Bus Master's point of view,
// then copy the contents of the real buffer into the mapped buffer
// so the Bus Master can read the contents of the real buffer.
//
if (Operation == EfiPciOperationBusMasterRead || Operation == EfiPciOperationBusMasterRead64) {
EfiCopyMem (
(VOID *)(UINTN)MapInfo->MappedHostAddress,
(VOID *)(UINTN)MapInfo->HostAddress,
MapInfo->NumberOfBytes
);
}
Status =gBS->AllocatePool (
EfiBootServicesData,
sizeof(MAP_INFO_INSTANCE),
&MapInstance
);
if (EFI_ERROR(Status)) {
gBS->FreePages (MapInfo->MappedHostAddress,MapInfo->NumberOfPages);
gBS->FreePool (MapInfo);
*NumberOfBytes = 0;
return Status;
}
MapInstance->Map=MapInfo;
PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
InsertTailList(&PrivateData->MapInfo,&MapInstance->Link);
//
// The DeviceAddress is the address of the maped buffer below 4GB
//
*DeviceAddress = MapInfo->MappedHostAddress;
} else {
//
// The transfer is below 4GB, so the DeviceAddress is simply the HostAddress
//
*DeviceAddress = PhysicalAddress;
}
//
// Perform a fence operation to make sure all memory operations are flushed
//
MEMORY_FENCE();
return EFI_SUCCESS;
}
EFI_STATUS
PcatRootBridgeIoUnmap (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN VOID *Mapping
)
{
MAP_INFO *MapInfo;
PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
EFI_LIST_ENTRY *Link;
//
// Perform a fence operation to make sure all memory operations are flushed
//
MEMORY_FENCE();
PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
//
// See if the Map() operation associated with this Unmap() required a mapping buffer.
// If a mapping buffer was not required, then this function simply returns EFI_SUCCESS.
//
if (Mapping != NULL) {
//
// Get the MAP_INFO structure from Mapping
//
MapInfo = (MAP_INFO *)Mapping;
for (Link = PrivateData->MapInfo.ForwardLink; Link != &PrivateData->MapInfo; Link = Link->ForwardLink) {
if (((MAP_INFO_INSTANCE*)Link)->Map == MapInfo)
break;
}
if (Link == &PrivateData->MapInfo) {
return EFI_INVALID_PARAMETER;
}
RemoveEntryList(Link);
((MAP_INFO_INSTANCE*)Link)->Map = NULL;
gBS->FreePool((MAP_INFO_INSTANCE*)Link);
//
// If this is a write operation from the Bus Master's point of view,
// then copy the contents of the mapped buffer into the real buffer
// so the processor can read the contents of the real buffer.
//
if (MapInfo->Operation == EfiPciOperationBusMasterWrite || MapInfo->Operation == EfiPciOperationBusMasterWrite64) {
EfiCopyMem (
(VOID *)(UINTN)MapInfo->HostAddress,
(VOID *)(UINTN)MapInfo->MappedHostAddress,
MapInfo->NumberOfBytes
);
}
//
// Free the mapped buffer and the MAP_INFO structure.
//
gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages);
gBS->FreePool (Mapping);
}
//
// Perform a fence operation to make sure all memory operations are flushed
//
MEMORY_FENCE();
return EFI_SUCCESS;
}
EFI_STATUS
PcatRootBridgeIoAllocateBuffer (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN EFI_ALLOCATE_TYPE Type,
IN EFI_MEMORY_TYPE MemoryType,
IN UINTN Pages,
OUT VOID **HostAddress,
IN UINT64 Attributes
)
{
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS PhysicalAddress;
//
// Validate Attributes
//
if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {
return EFI_UNSUPPORTED;
}
//
// Check for invalid inputs
//
if (HostAddress == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
//
if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) {
return EFI_INVALID_PARAMETER;
}
//
// Limit allocations to memory below 4GB
//
PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(0xffffffff);
Status = gBS->AllocatePages (AllocateMaxAddress, MemoryType, Pages, &PhysicalAddress);
if (EFI_ERROR (Status)) {
return Status;
}
*HostAddress = (VOID *)(UINTN)PhysicalAddress;
return EFI_SUCCESS;
}
EFI_STATUS
PcatRootBridgeIoFreeBuffer (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN UINTN Pages,
OUT VOID *HostAddress
)
{
if( HostAddress == NULL ){
return EFI_INVALID_PARAMETER;
}
return gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, Pages);
}
EFI_STATUS
PcatRootBridgeIoFlush (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
)
{
//
// Perform a fence operation to make sure all memory operations are flushed
//
MEMORY_FENCE();
return EFI_SUCCESS;
}
EFI_STATUS
PcatRootBridgeIoGetAttributes (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
OUT UINT64 *Supported, OPTIONAL
OUT UINT64 *Attributes
)
{
PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
if (Attributes == NULL && Supported == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Supported is an OPTIONAL parameter. See if it is NULL
//
if (Supported) {
//
// This is a generic driver for a PC-AT class system. It does not have any
// chipset specific knowlegde, so none of the attributes can be set or
// cleared. Any attempt to set attribute that are already set will succeed,
// and any attempt to set an attribute that is not supported will fail.
//
*Supported = PrivateData->Attributes;
}
//
// Set Attrbutes to the attributes detected when the PCI Root Bridge was initialized
//
if (Attributes) {
*Attributes = PrivateData->Attributes;
}
return EFI_SUCCESS;
}
EFI_STATUS
PcatRootBridgeIoSetAttributes (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN UINT64 Attributes,
IN OUT UINT64 *ResourceBase,
IN OUT UINT64 *ResourceLength
)
{
PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
//
// This is a generic driver for a PC-AT class system. It does not have any
// chipset specific knowlegde, so none of the attributes can be set or
// cleared. Any attempt to set attribute that are already set will succeed,
// and any attempt to set an attribute that is not supported will fail.
//
if (Attributes & (~PrivateData->Attributes)) {
return EFI_UNSUPPORTED;
}
return EFI_SUCCESS;
}
EFI_STATUS
PcatRootBridgeIoConfiguration (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
OUT VOID **Resources
)
{
PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
*Resources = PrivateData->Configuration;
return EFI_SUCCESS;
}
//
// Internal function
//
STATIC
EFI_STATUS
EFIAPI
PcatRootBridgeIoMemRW (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINTN Count,
IN BOOLEAN InStrideFlag,
IN PTR In,
IN BOOLEAN OutStrideFlag,
OUT PTR Out
)
/*++
Routine Description:
Private service to provide the memory read/write
Arguments:
Width of the Memory Access
Count of the number of accesses to perform
Returns:
Status
EFI_SUCCESS - Successful transaction
EFI_INVALID_PARAMETER - Unsupported width and address combination
--*/
{
UINTN Stride;
UINTN InStride;
UINTN OutStride;
Width = Width & 0x03;
Stride = 1 << Width;
InStride = InStrideFlag ? Stride : 0;
OutStride = OutStrideFlag ? Stride : 0;
//
// Loop for each iteration and move the data
//
switch (Width) {
case EfiPciWidthUint8:
for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
MEMORY_FENCE();
*In.ui8 = *Out.ui8;
MEMORY_FENCE();
}
break;
case EfiPciWidthUint16:
for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
MEMORY_FENCE();
*In.ui16 = *Out.ui16;
MEMORY_FENCE();
}
break;
case EfiPciWidthUint32:
for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
MEMORY_FENCE();
*In.ui32 = *Out.ui32;
MEMORY_FENCE();
}
break;
default:
return EFI_INVALID_PARAMETER;
}
return EFI_SUCCESS;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?