pcirootbridgeio.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,750 行 · 第 1/4 页
C
1,750 行
Returns:
--*/
// TODO: This - add argument and description to function comment
// TODO: Width - add argument and description to function comment
// TODO: Address - add argument and description to function comment
// TODO: Count - add argument and description to function comment
// TODO: Buffer - add argument and description to function comment
// TODO: EFI_INVALID_PARAMETER - add return value to function comment
// TODO: EFI_INVALID_PARAMETER - add return value to function comment
// TODO: EFI_INVALID_PARAMETER - add return value to function comment
// TODO: EFI_INVALID_PARAMETER - add return value to function comment
// TODO: EFI_INVALID_PARAMETER - add return value to function comment
{
UINTN AlignMask;
PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OldWidth;
UINTN OldCount;
UINTN Counter;
UINTN InStride;
UINTN OutStride;
CHAR8 Buf[16];
CHAR8 *Ptr;
CHAR8 *TempBuf;
EFI_STATUS Status;
if (Buffer == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Width < 0 || Width >= EfiPciWidthMaximum) {
return EFI_INVALID_PARAMETER;
}
PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
AlignMask = (1 << (Width & 0x03)) - 1;
//
// Check Io access limit
//
if (Address < PrivateData->IoBase) {
return EFI_INVALID_PARAMETER;
}
OldWidth = Width;
OldCount = Count;
if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
Count = 1;
}
Width &= 0x03;
if (Address + (1 << Width) * Count - 1 >= PrivateData->IoLimit) {
return EFI_INVALID_PARAMETER;
}
if (Address & AlignMask) {
return EFI_INVALID_PARAMETER;
}
Counter = OldCount;
TempBuf = (CHAR8 *) Buffer;
Status = EFI_SUCCESS;
if ((UINTN) Buffer & AlignMask) {
Ptr = (CHAR8 *) (((UINTN) (((UINTN) Buf) &~(AlignMask))) + (1 << Width));
while (Counter > 0) {
InStride = (OldCount - Counter) << Width;
OutStride = (OldCount - Counter) << Width;
if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
InStride = 0;
}
if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {
OutStride = 0;
}
EfiCopyMem (Ptr, TempBuf + OutStride, (1 << Width));
Status = mCpuIo->Io.Write (
mCpuIo,
(EFI_CPU_IO_PROTOCOL_WIDTH) OldWidth,
Address + InStride,
1,
(VOID *) Ptr
);
if (EFI_ERROR (Status)) {
return Status;
}
Counter--;
}
} else {
Status = mCpuIo->Io.Write (
mCpuIo,
(EFI_CPU_IO_PROTOCOL_WIDTH) OldWidth,
Address,
OldCount,
Buffer
);
}
return Status;
}
EFI_STATUS
EFIAPI
RootBridgeIoCopyMem (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 DestAddress,
IN UINT64 SrcAddress,
IN UINTN Count
)
/*++
Routine Description:
Memory copy
Arguments:
Returns:
--*/
// TODO: This - add argument and description to function comment
// TODO: Width - add argument and description to function comment
// TODO: DestAddress - add argument and description to function comment
// TODO: SrcAddress - add argument and description to function comment
// TODO: Count - add argument and description to function comment
// TODO: EFI_INVALID_PARAMETER - add return value to function comment
// TODO: EFI_SUCCESS - add return value to function comment
// TODO: EFI_SUCCESS - add return value to function comment
{
EFI_STATUS Status;
BOOLEAN Direction;
UINTN Stride;
UINTN Index;
UINT8 Buffer[16];
UINT8 *Result;
if (Width < 0 || Width > EfiPciWidthUint64) {
return EFI_INVALID_PARAMETER;
}
if (DestAddress == SrcAddress) {
return EFI_SUCCESS;
}
//
// Align result buffer
//
Result = (UINT8 *) ((UINTN) (Buffer + 8) & (UINTN) (-8));
Stride = 1 << Width;
Direction = TRUE;
if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {
Direction = FALSE;
SrcAddress = SrcAddress + (Count - 1) * Stride;
DestAddress = DestAddress + (Count - 1) * Stride;
}
for (Index = 0; Index < Count; Index++) {
Status = RootBridgeIoMemRead (
This,
Width,
SrcAddress,
1,
Result
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = RootBridgeIoMemWrite (
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
EFIAPI
RootBridgeIoPciRead (
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
)
/*++
Routine Description:
Pci read
Arguments:
Returns:
--*/
// TODO: This - add argument and description to function comment
// TODO: Width - add argument and description to function comment
// TODO: Address - add argument and description to function comment
// TODO: Count - add argument and description to function comment
// TODO: Buffer - add argument and description to function comment
// TODO: EFI_INVALID_PARAMETER - add return value to function comment
// TODO: EFI_INVALID_PARAMETER - add return value to function comment
{
if (Buffer == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Width < 0 || Width >= EfiPciWidthMaximum) {
return EFI_INVALID_PARAMETER;
}
//
// Read Pci configuration space
//
return RootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
}
EFI_STATUS
EFIAPI
RootBridgeIoPciWrite (
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
)
/*++
Routine Description:
Pci write
Arguments:
Returns:
--*/
// TODO: This - add argument and description to function comment
// TODO: Width - add argument and description to function comment
// TODO: Address - add argument and description to function comment
// TODO: Count - add argument and description to function comment
// TODO: Buffer - add argument and description to function comment
// TODO: EFI_INVALID_PARAMETER - add return value to function comment
// TODO: EFI_INVALID_PARAMETER - add return value to function comment
{
if (Buffer == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Width < 0 || Width >= EfiPciWidthMaximum) {
return EFI_INVALID_PARAMETER;
}
//
// Write Pci configuration space
//
return RootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
}
EFI_STATUS
EFIAPI
RootBridgeIoMap (
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
)
/*++
Routine Description:
TODO: Add function description
Arguments:
This - TODO: add argument description
Operation - TODO: add argument description
HostAddress - TODO: add argument description
NumberOfBytes - TODO: add argument description
DeviceAddress - TODO: add argument description
Mapping - TODO: add argument description
Returns:
EFI_INVALID_PARAMETER - TODO: Add description for return value
EFI_INVALID_PARAMETER - TODO: Add description for return value
EFI_UNSUPPORTED - TODO: Add description for return value
EFI_SUCCESS - TODO: Add description for return value
--*/
{
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS PhysicalAddress;
MAP_INFO *MapInfo;
if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// 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
);
}
//
// 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;
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
RootBridgeIoUnmap (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN VOID *Mapping
)
/*++
Routine Description:
TODO: Add function description
Arguments:
This - TODO: add argument description
Mapping - TODO: add argument description
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?