pcirootbridgeio.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,750 行 · 第 1/4 页
C
1,750 行
Returns:
EFI_SUCCESS - TODO: Add description for return value
--*/
{
MAP_INFO *MapInfo;
//
// 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;
//
// 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);
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
RootBridgeIoAllocateBuffer (
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
)
/*++
Routine Description:
TODO: Add function description
Arguments:
This - TODO: add argument description
Type - TODO: add argument description
MemoryType - TODO: add argument description
Pages - TODO: add argument description
HostAddress - TODO: add argument description
Attributes - TODO: add argument description
Returns:
EFI_UNSUPPORTED - TODO: Add description for return value
EFI_INVALID_PARAMETER - TODO: Add description for return value
EFI_UNSUPPORTED - TODO: Add description for return value
EFI_INVALID_PARAMETER - TODO: Add description for return value
EFI_SUCCESS - TODO: Add description for return value
--*/
{
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;
}
if ((EFI_PHYSICAL_ADDRESS) (UINTN) (*HostAddress) > 0xffffffff) {
return EFI_UNSUPPORTED;
}
//
// 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) (UINTN) (0xffffffff);
Status = gBS->AllocatePages (AllocateMaxAddress, MemoryType, Pages, &PhysicalAddress);
if (EFI_ERROR (Status)) {
return Status;
}
*HostAddress = (VOID *) (UINTN) PhysicalAddress;
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
RootBridgeIoFreeBuffer (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN UINTN Pages,
OUT VOID *HostAddress
)
/*++
Routine Description:
TODO: Add function description
Arguments:
This - TODO: add argument description
Pages - TODO: add argument description
HostAddress - TODO: add argument description
Returns:
TODO: add return values
--*/
{
return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);
}
EFI_STATUS
EFIAPI
RootBridgeIoFlush (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
)
/*++
Routine Description:
Arguments:
Returns:
--*/
// TODO: This - add argument and description to function comment
// TODO: EFI_SUCCESS - add return value to function comment
{
//
// not supported yet
//
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
RootBridgeIoGetAttributes (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
OUT UINT64 *Supported,
OUT UINT64 *Attributes
)
/*++
Routine Description:
Arguments:
Returns:
--*/
// TODO: This - add argument and description to function comment
// TODO: Supported - add argument and description to function comment
// TODO: Attributes - 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
{
PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
if (Attributes == NULL && Supported == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Set the return value for Supported and Attributes
//
if (Supported) {
*Supported = PrivateData->Supports;
}
if (Attributes) {
*Attributes = PrivateData->Attributes;
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
RootBridgeIoSetAttributes (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN UINT64 Attributes,
IN OUT UINT64 *ResourceBase,
IN OUT UINT64 *ResourceLength
)
/*++
Routine Description:
Arguments:
Returns:
--*/
// TODO: This - add argument and description to function comment
// TODO: Attributes - add argument and description to function comment
// TODO: ResourceBase - add argument and description to function comment
// TODO: ResourceLength - add argument and description to function comment
// TODO: EFI_UNSUPPORTED - add return value to function comment
// TODO: EFI_SUCCESS - add return value to function comment
// TODO: EFI_SUCCESS - add return value to function comment
{
PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
UINT64 Address;
UINT16 Data;
PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
if (Attributes) {
if ((Attributes & (~(PrivateData->Supports))) != 0) {
return EFI_UNSUPPORTED;
}
}
if (Attributes == PrivateData->Attributes) {
return EFI_SUCCESS;
}
//
// Set IDE primary
//
if (Attributes & EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO) {
Address = EFI_PCI_ADDRESS (0x0, 0x1f, 0x1, 0x40);
This->Pci.Read (This, EfiPciWidthUint16, Address, 1, &Data);
Data |= 0x8000;
This->Pci.Write (This, EfiPciWidthUint16, Address, 1, &Data);
}
//
// Set IDE secondary
//
if (Attributes & EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO) {
Address = EFI_PCI_ADDRESS (0x0, 0x1f, 0x1, 0x42);
This->Pci.Read (This, EfiPciWidthUint16, Address, 1, &Data);
Data |= 0x8000;
This->Pci.Write (This, EfiPciWidthUint16, Address, 1, &Data);
}
//
// It is just a trick for some attribute can only be enabled or disabled
// otherwise it can impact on other devices
//
PrivateData->Attributes = Attributes;
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
RootBridgeIoConfiguration (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
OUT VOID **Resources
)
/*++
Routine Description:
Arguments:
Returns:
--*/
// TODO: This - add argument and description to function comment
// TODO: Resources - add argument and description to function comment
// TODO: EFI_SUCCESS - add return value to function comment
{
PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
UINTN Index;
PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
for (Index = 0; Index < TypeMax; Index++) {
if (PrivateData->ResAllocNode[Index].Status == ResAllocated) {
mConfiguration.SpaceDesp[Index].AddrRangeMin = PrivateData->ResAllocNode[Index].Base;
mConfiguration.SpaceDesp[Index].AddrRangeMax =
PrivateData->ResAllocNode[Index].Base + PrivateData->ResAllocNode[Index].Length - 1;
mConfiguration.SpaceDesp[Index].AddrLen = PrivateData->ResAllocNode[Index].Length;
}
}
*Resources = &mConfiguration;
return EFI_SUCCESS;
}
//
// Internal function
//
STATIC
EFI_STATUS
RootBridgeIoPciRW (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
IN BOOLEAN Write,
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
IN UINT64 UserAddress,
IN UINTN Count,
IN OUT VOID *UserBuffer
)
/*++
Routine Description:
Arguments:
Returns:
--*/
// TODO: This - add argument and description to function comment
// TODO: Write - add argument and description to function comment
// TODO: Width - add argument and description to function comment
// TODO: UserAddress - add argument and description to function comment
// TODO: Count - add argument and description to function comment
// TODO: UserBuffer - add argument and description to function comment
// TODO: EFI_INVALID_PARAMETER - add return value to function comment
// TODO: EFI_UNSUPPORTED - add return value to function comment
// TODO: EFI_SUCCESS - add return value to function comment
{
PCI_CONFIG_ACCESS_CF8 Pci;
PCI_CONFIG_ACCESS_CF8 PciAligned;
UINT32 InStride;
UINT32 OutStride;
UINTN PciData;
UINTN PciDataStride;
PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
if ((Width & 0x03) >= EfiPciWidthUint64) {
return EFI_INVALID_PARAMETER;
}
PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
InStride = 1 << (Width & 0x03);
OutStride = InStride;
if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
InStride = 0;
}
if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) {
OutStride = 0;
}
if (((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &UserAddress)->ExtendedRegister != 0) {
//
// For Pci bus driver has made parameter check before calling this function,
// there is no need to check the parameters again here
//
return EFI_UNSUPPORTED;
} else {
Pci.Reg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &UserAddress)->Register;
}
Pci.Func = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &UserAddress)->Function;
Pci.Dev = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &UserAddress)->Device;
Pci.Bus = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &UserAddress)->Bus;
Pci.Reserved = 0;
Pci.Enable = 1;
//
// PCI Configure access are all 32-bit aligned, but by accessing the
// CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
// are possible on PCI.
//
// To read a byte of PCI configuration space you load 0xcf8 and
// read 0xcfc, 0xcfd, 0xcfe, 0xcff
//
PciDataStride = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &UserAddress)->Register & 0x03;
while (Count) {
PciAligned = Pci;
PciAligned.Reg &= 0xfc;
PciData = PrivateData->PciData + PciDataStride;
EfiAcquireLock (&PrivateData->PciLock);
This->Io.Write (
This,
EfiPciWidthUint32,
PrivateData->PciAddress,
1,
&PciAligned
);
if (Write) {
This->Io.Write (This, Width, PciData, 1, UserBuffer);
} else {
This->Io.Read (This, Width, PciData, 1, UserBuffer);
}
EfiReleaseLock (&PrivateData->PciLock);
UserBuffer = ((UINT8 *) UserBuffer) + OutStride;
PciDataStride = (PciDataStride + InStride) % 4;
Pci.Reg += InStride;
Count -= 1;
}
return EFI_SUCCESS;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?