pcienumeratorsupport.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,385 行 · 第 1/3 页
C
1,385 行
}
PCI_IO_DEVICE *
GatherPPBInfo (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
IN PCI_TYPE00 *Pci,
UINT8 Bus,
UINT8 Device,
UINT8 Func
)
/*++
Routine Description:
Arguments:
Returns:
None
--*/
{
PCI_IO_DEVICE *PciIoDevice;
EFI_STATUS Status;
UINT32 Value;
EFI_PCI_IO_PROTOCOL *PciIo;
UINT8 Temp;
PciIoDevice = CreatePciIoDevice (
PciRootBridgeIo,
Pci,
Bus,
Device,
Func
);
if (!PciIoDevice) {
return NULL;
}
if (gFullEnumeration) {
PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
//
// Initalize the bridge control register
//
PciDisableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED);
}
PciIo = &PciIoDevice->PciIo;
//
// Test whether it support 32 decode or not
//
PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
if (Value) {
if (Value & 0x01) {
PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED;
} else {
PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;
}
}
Status = BarExisted (
PciIoDevice,
0x24,
NULL,
NULL
);
//
// test if it supports 64 memory or not
//
if (!EFI_ERROR (Status)) {
Status = BarExisted (
PciIoDevice,
0x28,
NULL,
NULL
);
if (!EFI_ERROR (Status)) {
PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;
} else {
PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
}
}
//
// Memory 32 code is required for ppb
//
PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;
return PciIoDevice;
}
PCI_IO_DEVICE *
GatherP2CInfo (
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
IN PCI_TYPE00 *Pci,
UINT8 Bus,
UINT8 Device,
UINT8 Func
)
/*++
Routine Description:
Arguments:
Returns:
None
--*/
{
PCI_IO_DEVICE *PciIoDevice;
PciIoDevice = CreatePciIoDevice (
PciRootBridgeIo,
Pci,
Bus,
Device,
Func
);
if (!PciIoDevice) {
return NULL;
}
if (gFullEnumeration) {
PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
//
// Initalize the bridge control register
//
PciDisableBridgeControlRegister (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED);
}
//
// P2C only has one bar that is in 0x10
//
PciParseBar(PciIoDevice, 0x10, 0);
PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED |
EFI_BRIDGE_PMEM32_DECODE_SUPPORTED |
EFI_BRIDGE_IO32_DECODE_SUPPORTED;
return PciIoDevice;
}
EFI_DEVICE_PATH_PROTOCOL *
CreatePciDevicePath (
IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
IN PCI_IO_DEVICE *PciIoDevice
)
/*++
Routine Description:
Arguments:
Returns:
None
--*/
{
PCI_DEVICE_PATH PciNode;
//
// Create PCI device path
//
PciNode.Header.Type = HARDWARE_DEVICE_PATH;
PciNode.Header.SubType = HW_PCI_DP;
SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
PciNode.Device = PciIoDevice->DeviceNumber;
PciNode.Function = PciIoDevice->FunctionNumber;
PciIoDevice->DevicePath = EfiAppendDevicePathNode (ParentDevicePath, &PciNode.Header);
return PciIoDevice->DevicePath;
}
EFI_STATUS
BarExisted (
IN PCI_IO_DEVICE *PciIoDevice,
IN UINTN Offset,
OUT UINT32 *BarLengthValue,
OUT UINT32 *OriginalBarValue
)
/*++
Routine Description:
Check the bar is existed or not.
Arguments:
PciIoDevice - A pointer to the PCI_IO_DEVICE.
Offset - The offset.
BarLengthValue - The bar length value.
OriginalBarValue - The original bar value.
Returns:
EFI_NOT_FOUND - The bar don't exist.
EFI_SUCCESS - The bar exist.
--*/
{
EFI_PCI_IO_PROTOCOL *PciIo;
UINT32 OriginalValue;
UINT32 Value;
EFI_TPL OldTpl;
PciIo = &PciIoDevice->PciIo;
//
// Preserve the original value
//
PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);
//
// Raise TPL to high level to disable timer interrupt while the BAR is probed
//
OldTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL);
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAllOne);
PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Value);
//
// Write back the original value
//
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);
//
// Restore TPL to its original level
//
gBS->RestoreTPL (OldTpl);
if (BarLengthValue != NULL) {
*BarLengthValue = Value;
}
if (OriginalBarValue != NULL) {
*OriginalBarValue = OriginalValue;
}
if (Value == 0) {
return EFI_NOT_FOUND;
} else {
return EFI_SUCCESS;
}
}
EFI_STATUS
DetermineDeviceAttribute (
IN PCI_IO_DEVICE *PciIoDevice
)
/*++
Routine Description:
Determine the related attributes of all devices under a Root Bridge
Arguments:
Returns:
None
--*/
{
UINT16 Command;
UINT16 BridgeControl;
Command = 0;
PciIoDevice->Supports |= EFI_PCI_DEVICE_ENABLE;
PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
if (IS_PCI_VGA (&(PciIoDevice->Pci))){
//
// If the device is VGA, VGA related Attributes are supported
//
PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO ;
PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY ;
PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_IO ;
}
if(IS_ISA_BRIDGE(&(PciIoDevice->Pci)) || IS_INTEL_ISA_BRIDGE(&(PciIoDevice->Pci))) {
//
// If the devie is a ISA Bridge, set the two attributes
//
PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;
PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;
}
if (IS_PCI_GFX (&(PciIoDevice->Pci))) {
//
// If the device is GFX, then only set the EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
// attribute
//
PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO ;
}
//
// If the device is IDE, IDE related attributes are supported
//
if (IS_PCI_IDE (&(PciIoDevice->Pci))) {
PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO ;
PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO ;
}
PciReadCommandRegister(PciIoDevice, &Command);
if (Command & EFI_PCI_COMMAND_IO_SPACE) {
PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_IO;
}
if (Command & EFI_PCI_COMMAND_MEMORY_SPACE) {
PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY;
}
if (Command & EFI_PCI_COMMAND_BUS_MASTER) {
PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;
}
if (IS_PCI_BRIDGE (&(PciIoDevice->Pci)) ||
IS_CARDBUS_BRIDGE (&(PciIoDevice->Pci))){
//
// If it is a PPB, read the Bridge Control Register to determine
// the relevant attributes
//
BridgeControl = 0;
PciReadBridgeControlRegister(PciIoDevice, &BridgeControl);
//
// Determine whether the ISA bit is set
// If ISA Enable on Bridge is set, the PPB
// will block forwarding 0x100-0x3ff for each 1KB in the
// first 64KB I/O range.
//
if (!BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) {
PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;
}
//
// Determine whether the VGA bit is set
// If it is set, the bridge is set to decode VGA memory range
// and palette register range
//
if (IS_PCI_VGA (&(PciIoDevice->Pci)) &&BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) {
PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;
PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
}
//
// if the palette snoop bit is set, then the brige is set to
// decode palette IO write
//
if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) {
PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
}
}
return EFI_SUCCESS;
}
UINTN
PciParseBar (
IN PCI_IO_DEVICE *PciIoDevice,
IN UINTN Offset,
IN UINTN BarIndex
)
/*++
Routine Description:
Arguments:
Returns:
None
--*/
{
UINT32 Value;
UINT64 BarValue64;
UINT32 OriginalValue;
UINT32 Mask;
UINT32 Data;
UINT8 Index;
EFI_STATUS Status;
OriginalValue = 0;
Value = 0;
BarValue64 = 0;
Status = BarExisted (
PciIoDevice,
Offset,
&Value,
&OriginalValue
);
if (EFI_ERROR (Status)) {
PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
PciIoDevice->PciBar[BarIndex].Length = 0;
PciIoDevice->PciBar[BarIndex].Alignment = 0;
//
// Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway
//
PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
return Offset + 4;
}
PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
if (Value & 0x01) {
//
// Device I/Os
//
Mask = 0xfffffffc;
if (Value & 0xFFFF0000) {
//
// It is a IO32 bar
//
PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo32;
PciIoDevice->PciBar[BarIndex].Length = ((~(Value & Mask)) + 1);
PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
} else {
//
// It is a IO16 bar
//
PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo16;
PciIoDevice->PciBar[BarIndex].Length = 0x0000FFFF & ((~(Value & Mask)) + 1);
PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
}
//
// Workaround. Some platforms inplement IO bar with 0 length
// Need to treat it as no-bar
//
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?