pcidevicesupport.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 974 行 · 第 1/2 页
C
974 行
EfiPciIoWidthUint8,
0,
sizeof (PciData),
&PciData
);
if ((((PciData.Bridge.IoBase & 0xF) == 0) &&
(PciData.Bridge.IoBase != 0 || PciData.Bridge.IoLimit != 0)) ||
(((PciData.Bridge.IoBase & 0xF) == 1) &&
((PciData.Bridge.IoBase & 0xF0) != 0 || (PciData.Bridge.IoLimit & 0xF0) != 0 || PciData.Bridge.IoBaseUpper16 != 0 || PciData.Bridge.IoLimitUpper16 != 0))) {
PciIoDevice->PciIo.Attributes(
&(PciIoDevice->PciIo),
EfiPciIoAttributeOperationEnable,
(EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
NULL
);
}
if ((PciData.Bridge.MemoryBase & 0xFFF0) != 0 || (PciData.Bridge.MemoryLimit & 0xFFF0) != 0) {
PciIoDevice->PciIo.Attributes(
&(PciIoDevice->PciIo),
EfiPciIoAttributeOperationEnable,
(EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
NULL
);
}
if ((((PciData.Bridge.PrefetchableMemoryBase & 0xF) == 0) &&
(PciData.Bridge.PrefetchableMemoryBase != 0 || PciData.Bridge.PrefetchableMemoryLimit != 0)) ||
(((PciData.Bridge.PrefetchableMemoryBase & 0xF) == 1) &&
((PciData.Bridge.PrefetchableMemoryBase & 0xFFF0) != 0 || (PciData.Bridge.PrefetchableMemoryLimit & 0xFFF0) != 0 || PciData.Bridge.PrefetchableBaseUpper32 != 0 || PciData.Bridge.PrefetchableLimitUpper32 != 0))) {
PciIoDevice->PciIo.Attributes(
&(PciIoDevice->PciIo),
EfiPciIoAttributeOperationEnable,
(EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
NULL
);
}
return EFI_SUCCESS;
}
EFI_STATUS
StartPciDevicesOnBridge (
IN EFI_HANDLE Controller,
IN PCI_IO_DEVICE *RootBridge,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
/*++
Routine Description:
Start to manage the PCI device on specified the root bridge or PCI-PCI Bridge
Arguments:
Controller - An efi handle.
RootBridge - A pointer to the PCI_IO_DEVICE.
RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL.
NumberOfChildren - Children number.
ChildHandleBuffer - A pointer to the child handle buffer.
Returns:
None
--*/
{
PCI_IO_DEVICE *Temp;
PCI_IO_DEVICE *PciIoDevice;
EFI_DEV_PATH_PTR Node;
EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath;
EFI_STATUS Status;
EFI_LIST_ENTRY *CurrentLink;
CurrentLink = RootBridge->ChildList.ForwardLink;
while (CurrentLink && CurrentLink != &RootBridge->ChildList) {
Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
if (RemainingDevicePath != NULL) {
Node.DevPath = RemainingDevicePath;
if (Node.Pci->Device != Temp->DeviceNumber ||
Node.Pci->Function != Temp->FunctionNumber) {
CurrentLink = CurrentLink->ForwardLink;
continue;
}
//
// Check if the device has been assigned with required resource
//
if (!Temp->Allocated) {
return EFI_NOT_READY;
}
//
// Check if the current node has been registered before
// If it is not, register it
//
if (!Temp->Registered) {
PciIoDevice = Temp;
Status = RegisterPciDevice (
Controller,
PciIoDevice,
NULL
);
}
//
// Get the next device path
//
CurrentDevicePath = EfiNextDevicePathNode (RemainingDevicePath);
if (EfiIsDevicePathEnd (CurrentDevicePath)) {
return EFI_SUCCESS;
}
//
// If it is a PPB
//
if (IS_PCI_BRIDGE (&(Temp->Pci))) {
Status = StartPciDevicesOnBridge (
Controller,
Temp,
CurrentDevicePath
);
EnableBridgeAttributes (Temp);
return Status;
} else {
//
// Currently, the PCI bus driver only support PCI-PCI bridge
//
return EFI_UNSUPPORTED;
}
} else {
//
// If remaining device path is NULL,
// try to enable all the pci devices under this bridge
//
if (!Temp->Registered && Temp->Allocated) {
PciIoDevice = Temp;
Status = RegisterPciDevice (
Controller,
PciIoDevice,
NULL
);
}
if (IS_PCI_BRIDGE (&(Temp->Pci))) {
Status = StartPciDevicesOnBridge (
Controller,
Temp,
RemainingDevicePath
);
EnableBridgeAttributes (Temp);
}
CurrentLink = CurrentLink->ForwardLink;
continue;
}
}
return EFI_NOT_FOUND;
}
EFI_STATUS
StartPciDevices (
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
/*++
Routine Description:
Start to manage the PCI device according to RemainingDevicePath
If RemainingDevicePath == NULL, the PCI bus driver will start
to manage all the PCI devices it found previously
Arguments:
Controller - An efi handle.
RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL.
Returns:
None
--*/
{
EFI_DEV_PATH_PTR Node;
PCI_IO_DEVICE *RootBridge;
EFI_LIST_ENTRY *CurrentLink;
if (RemainingDevicePath != NULL) {
//
// Check if the RemainingDevicePath is valid
//
Node.DevPath = RemainingDevicePath;
if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||
Node.DevPath->SubType != HW_PCI_DP &&
DevicePathNodeLength (Node.DevPath) != sizeof (PCI_DEVICE_PATH)
) {
return EFI_UNSUPPORTED;
}
}
CurrentLink = gPciDevicePool.ForwardLink;
while (CurrentLink && CurrentLink != &gPciDevicePool) {
RootBridge = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
//
// Locate the right root bridge to start
//
if (RootBridge->Handle == Controller) {
StartPciDevicesOnBridge (
Controller,
RootBridge,
RemainingDevicePath
);
}
CurrentLink = CurrentLink->ForwardLink;
}
return EFI_SUCCESS;
}
PCI_IO_DEVICE *
CreateRootBridge (
IN EFI_HANDLE RootBridgeHandle
)
/*++
Routine Description:
Arguments:
RootBridgeHandle - An efi handle.
Returns:
None
--*/
{
EFI_STATUS Status;
PCI_IO_DEVICE *Dev;
Dev = NULL;
Status = gBS->AllocatePool (
EfiBootServicesData,
sizeof (PCI_IO_DEVICE),
(VOID **) &Dev
);
if (EFI_ERROR (Status)) {
return NULL;
}
EfiZeroMem (Dev, sizeof (PCI_IO_DEVICE));
Dev->Signature = PCI_IO_DEVICE_SIGNATURE;
Dev->Handle = RootBridgeHandle;
InitializeListHead (&Dev->ChildList);
return Dev;
}
PCI_IO_DEVICE *
GetRootBridgeByHandle (
EFI_HANDLE RootBridgeHandle
)
/*++
Routine Description:
Arguments:
RootBridgeHandle - An efi handle.
Returns:
None
--*/
{
PCI_IO_DEVICE *RootBridgeDev;
EFI_LIST_ENTRY *CurrentLink;
CurrentLink = gPciDevicePool.ForwardLink;
while (CurrentLink && CurrentLink != &gPciDevicePool) {
RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
if (RootBridgeDev->Handle == RootBridgeHandle) {
return RootBridgeDev;
}
CurrentLink = CurrentLink->ForwardLink;
}
return NULL;
}
BOOLEAN
RootBridgeExisted (
IN EFI_HANDLE RootBridgeHandle
)
/*++
Routine Description:
This function searches if RootBridgeHandle has already existed
in current device pool.
If so, it means the given root bridge has been already enumerated.
Arguments:
RootBridgeHandle - An efi handle.
Returns:
None
--*/
{
PCI_IO_DEVICE *Bridge;
Bridge = GetRootBridgeByHandle (RootBridgeHandle);
if (Bridge != NULL) {
return TRUE;
}
return FALSE;
}
BOOLEAN
PciDeviceExisted (
IN PCI_IO_DEVICE *Bridge,
IN PCI_IO_DEVICE *PciIoDevice
)
/*++
Routine Description:
Arguments:
Bridge - A pointer to the PCI_IO_DEVICE.
PciIoDevice - A pointer to the PCI_IO_DEVICE.
Returns:
None
--*/
{
PCI_IO_DEVICE *Temp;
EFI_LIST_ENTRY *CurrentLink;
CurrentLink = Bridge->ChildList.ForwardLink;
while (CurrentLink && CurrentLink != &Bridge->ChildList) {
Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
if (Temp == PciIoDevice) {
return TRUE;
}
if (!IsListEmpty (&Temp->ChildList)) {
if (PciDeviceExisted (Temp, PciIoDevice)) {
return TRUE;
}
}
CurrentLink = CurrentLink->ForwardLink;
}
return FALSE;
}
PCI_IO_DEVICE *
ActiveVGADeviceOnTheSameSegment (
IN PCI_IO_DEVICE *VgaDevice
)
/*++
Routine Description:
Arguments:
VgaDevice - A pointer to the PCI_IO_DEVICE.
Returns:
None
--*/
{
EFI_LIST_ENTRY *CurrentLink;
PCI_IO_DEVICE *Temp;
CurrentLink = gPciDevicePool.ForwardLink;
while (CurrentLink && CurrentLink != &gPciDevicePool) {
Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
if (Temp->PciRootBridgeIo->SegmentNumber == VgaDevice->PciRootBridgeIo->SegmentNumber) {
Temp = ActiveVGADeviceOnTheRootBridge (Temp);
if (Temp != NULL) {
return Temp;
}
}
CurrentLink = CurrentLink->ForwardLink;
}
return NULL;
}
PCI_IO_DEVICE *
ActiveVGADeviceOnTheRootBridge (
IN PCI_IO_DEVICE *RootBridge
)
/*++
Routine Description:
Arguments:
RootBridge - A pointer to the PCI_IO_DEVICE.
Returns:
None
--*/
{
EFI_LIST_ENTRY *CurrentLink;
PCI_IO_DEVICE *Temp;
CurrentLink = RootBridge->ChildList.ForwardLink;
while (CurrentLink && CurrentLink != &RootBridge->ChildList) {
Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
if (IS_PCI_VGA(&Temp->Pci) &&
(Temp->Attributes &
(EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY |
EFI_PCI_IO_ATTRIBUTE_VGA_IO |
EFI_PCI_IO_ATTRIBUTE_VGA_IO_16))) {
return Temp;
}
if (IS_PCI_BRIDGE (&Temp->Pci)) {
Temp = ActiveVGADeviceOnTheRootBridge (Temp);
if (Temp != NULL) {
return Temp;
}
}
CurrentLink = CurrentLink->ForwardLink;
}
return NULL;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?