pciio.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,868 行 · 第 1/4 页
C
1,868 行
None
--*/
{
EFI_STATUS Status;
PCI_IO_DEVICE *PciIoDevice;
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
if (Operation < 0 || Operation >= EfiPciIoOperationMaximum) {
return EFI_INVALID_PARAMETER;
}
if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) {
return EFI_INVALID_PARAMETER;
}
if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) {
Operation = Operation + EfiPciOperationBusMasterRead64;
}
Status = PciIoDevice->PciRootBridgeIo->Map (
PciIoDevice->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,
HostAddress,
NumberOfBytes,
DeviceAddress,
Mapping
);
return Status;
}
EFI_STATUS
EFIAPI
PciIoUnmap (
IN EFI_PCI_IO_PROTOCOL *This,
IN VOID *Mapping
)
/*++
Routine Description:
Unmaps a memory region for DMA
Arguments:
Returns:
None
--*/
{
EFI_STATUS Status;
PCI_IO_DEVICE *PciIoDevice;
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
Status = PciIoDevice->PciRootBridgeIo->Unmap (
PciIoDevice->PciRootBridgeIo,
Mapping
);
return Status;
}
EFI_STATUS
EFIAPI
PciIoAllocateBuffer (
IN EFI_PCI_IO_PROTOCOL *This,
IN EFI_ALLOCATE_TYPE Type,
IN EFI_MEMORY_TYPE MemoryType,
IN UINTN Pages,
OUT VOID **HostAddress,
IN UINT64 Attributes
)
/*++
Routine Description:
Allocates a common buffer for DMA
Arguments:
Returns:
None
--*/
{
EFI_STATUS Status;
PCI_IO_DEVICE *PciIoDevice;
if (Attributes &
(~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED))) {
return EFI_UNSUPPORTED;
}
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) {
Attributes |= EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
}
Status = PciIoDevice->PciRootBridgeIo->AllocateBuffer (
PciIoDevice->PciRootBridgeIo,
Type,
MemoryType,
Pages,
HostAddress,
Attributes
);
return Status;
}
EFI_STATUS
EFIAPI
PciIoFreeBuffer (
IN EFI_PCI_IO_PROTOCOL *This,
IN UINTN Pages,
IN VOID *HostAddress
)
/*++
Routine Description:
Frees a common buffer
Arguments:
Returns:
None
--*/
{
EFI_STATUS Status;
PCI_IO_DEVICE *PciIoDevice;
if( HostAddress == NULL ){
return EFI_INVALID_PARAMETER;
}
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
Status = PciIoDevice->PciRootBridgeIo->FreeBuffer (
PciIoDevice->PciRootBridgeIo,
Pages,
HostAddress
);
return Status;
}
EFI_STATUS
EFIAPI
PciIoFlush (
IN EFI_PCI_IO_PROTOCOL *This
)
/*++
Routine Description:
Flushes a DMA buffer
Arguments:
Returns:
None
--*/
{
EFI_STATUS Status;
UINT32 Register;
PCI_IO_DEVICE *PciIoDevice;
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
//
// If the device is behind a PCI-PCI Bridge, then perform a read cycles to the device to
// flush the posted write cycles through the PCI-PCI bridges
//
if (PciIoDevice->Parent != NULL) {
Status = This->Pci.Read (This, EfiPciIoWidthUint32, 0, 1, &Register);
}
//
// Call the PCI Root Bridge I/O Protocol to flush the posted write cycles through the chipset
//
Status = PciIoDevice->PciRootBridgeIo->Flush (
PciIoDevice->PciRootBridgeIo
);
return Status;
}
EFI_STATUS
EFIAPI
PciIoGetLocation (
IN EFI_PCI_IO_PROTOCOL *This,
OUT UINTN *Segment,
OUT UINTN *Bus,
OUT UINTN *Device,
OUT UINTN *Function
)
/*++
Routine Description:
Gets a PCI device's current bus number, device number, and function number.
Arguments:
Returns:
None
--*/
{
PCI_IO_DEVICE *PciIoDevice;
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
if (Segment == NULL || Bus == NULL || Device == NULL || Function == NULL) {
return EFI_INVALID_PARAMETER;
}
*Segment = PciIoDevice->PciRootBridgeIo->SegmentNumber;
*Bus = PciIoDevice->BusNumber;
*Device = PciIoDevice->DeviceNumber;
*Function = PciIoDevice->FunctionNumber;
return EFI_SUCCESS;
}
BOOLEAN
CheckBarType (
IN PCI_IO_DEVICE *PciIoDevice,
UINT8 BarIndex,
PCI_BAR_TYPE BarType
)
/*++
Routine Description:
Sets a PCI controllers attributes on a resource range
Arguments:
Returns:
None
--*/
{
switch (BarType) {
case PciBarTypeMem:
if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem32 &&
PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem32 &&
PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem64 &&
PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem64 ) {
return FALSE;
}
return TRUE;
case PciBarTypeIo:
if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo32 &&
PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo16){
return FALSE;
}
return TRUE;
default:
break;
}
return FALSE;
}
EFI_STATUS
EFIAPI
PciIoAttributes (
IN EFI_PCI_IO_PROTOCOL * This,
IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
IN UINT64 Attributes,
OUT UINT64 *Result OPTIONAL
)
/*++
Routine Description:
Arguments:
Returns:
None
--*/
{
EFI_STATUS Status;
PCI_IO_DEVICE *PciIoDevice;
PCI_IO_DEVICE *Temp;
UINT64 NewAttributes;
UINT64 PciRootBridgeSupports;
UINT64 PciRootBridgeAttributes;
UINT64 NewPciRootBridgeAttributes;
UINT64 NewUpStreamBridgeAttributes;
UINT64 ModifiedPciRootBridgeAttributes;
UINT16 EnableCommand;
UINT16 DisableCommand;
UINT16 EnableBridge;
UINT16 DisableBridge;
UINT16 Command;
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
NewUpStreamBridgeAttributes = 0;
EnableCommand = 0;
DisableCommand = 0;
EnableBridge = 0;
DisableBridge = 0;
switch (Operation) {
case EfiPciIoAttributeOperationGet:
if (Result == NULL) {
return EFI_INVALID_PARAMETER;
}
*Result = PciIoDevice->Attributes;
return EFI_SUCCESS;
case EfiPciIoAttributeOperationSupported:
if (Result == NULL) {
return EFI_INVALID_PARAMETER;
}
*Result = PciIoDevice->Supports;
return EFI_SUCCESS;
case EfiPciIoAttributeOperationEnable:
if(Attributes & ~(PciIoDevice->Supports)) {
return EFI_UNSUPPORTED;
}
NewAttributes = PciIoDevice->Attributes | Attributes;
break;
case EfiPciIoAttributeOperationDisable:
if(Attributes & ~(PciIoDevice->Supports)) {
return EFI_UNSUPPORTED;
}
NewAttributes = PciIoDevice->Attributes & (~Attributes);
break;
case EfiPciIoAttributeOperationSet:
if(Attributes & ~(PciIoDevice->Supports)) {
return EFI_UNSUPPORTED;
}
NewAttributes = Attributes;
break;
default:
return EFI_INVALID_PARAMETER;
}
//
// If VGA_IO is set, then set VGA_MEMORY too. This driver can not enable them seperately.
//
if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {
NewAttributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
}
//
// If VGA_MEMORY is set, then set VGA_IO too. This driver can not enable them seperately.
//
if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY) {
NewAttributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;
}
//
// If the attributes are already set correctly, then just return EFI_SUCCESS;
//
if ((NewAttributes ^ PciIoDevice->Attributes) == 0) {
return EFI_SUCCESS;
}
//
// This driver takes care of EFI_PCI_IO_ATTRIBUTE_IO, EFI_PCI_IO_ATTRIBUTE_MEMORY, and
// EFI_PCI_IO_ATTRIBUTE_BUS_MASTER. Strip these 3 bits off the new attribute mask so
// a call to the PCI Root Bridge I/O Protocol can be made
//
if (!IS_PCI_BRIDGE(&PciIoDevice->Pci)) {
NewPciRootBridgeAttributes = NewAttributes & (~(EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE));
//
// Get the current attributes of this PCI device's PCI Root Bridge
//
Status = PciIoDevice->PciRootBridgeIo->GetAttributes (
PciIoDevice->PciRootBridgeIo,
&PciRootBridgeSupports,
&PciRootBridgeAttributes
);
//
// Check to see if any of the PCI Root Bridge attributes are being modified
//
ModifiedPciRootBridgeAttributes = NewPciRootBridgeAttributes ^ PciRootBridgeAttributes;
if (ModifiedPciRootBridgeAttributes) {
//
// Check to see if the PCI Root Bridge supports modifiying the attributes that are changing
//
if ((ModifiedPciRootBridgeAttributes & PciRootBridgeSupports) != ModifiedPciRootBridgeAttributes) {
// return EFI_UNSUPPORTED;
}
//
// Call the PCI Root Bridge to attempt to modify the attributes
//
Status = PciIoDevice->PciRootBridgeIo->SetAttributes (
PciIoDevice->PciRootBridgeIo,
NewPciRootBridgeAttributes,
NULL,
NULL
);
if (EFI_ERROR (Status)) {
//
// The PCI Root Bridge could not modify the attributes, so return the error.
//
return Status;
}
}
}
if (IS_PCI_BRIDGE(&PciIoDevice->Pci)) {
//
// Check to see if an VGA related attributes are being set.
//
if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO)) {
if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {
EnableBridge |= EFI_PCI_BRIDGE_CONTROL_VGA;
} else {
DisableBridge |= EFI_PCI_BRIDGE_CONTROL_VGA;
}
}
//
// Check to see if an VGA related attributes are being set.
// If ISA Enable on the PPB is set, the PPB will block the
// 0x100-0x3FF for each 1KB block in the first 64K I/O block
//
if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO)) {
if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) {
DisableBridge |= EFI_PCI_BRIDGE_CONTROL_ISA;
} else {
EnableBridge |= EFI_PCI_BRIDGE_CONTROL_ISA;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?