pcidevicesupport.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,352 行 · 第 1/3 页
C
1,352 行
EFI_LIST_ENTRY *CurrentLink;
PCI_IO_DEVICE *Temp;
while (!IsListEmpty (&Bridge->ChildList)) {
CurrentLink = Bridge->ChildList.ForwardLink;
Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
//
// Check if the current node has been deregistered before
// If it is not, then deregister it
//
if (Temp->Registered) {
DeRegisterPciDevice (RootBridgeHandle, Temp->Handle);
}
//
// Remove this node from the linked list
//
RemoveEntryList (CurrentLink);
if (!IsListEmpty (&Temp->ChildList)) {
RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp);
}
FreePciDevice (Temp);
}
return EFI_SUCCESS;
}
EFI_STATUS
DeRegisterPciDevice (
IN EFI_HANDLE Controller,
IN EFI_HANDLE Handle
)
/*++
Routine Description:
This function is used to de-register the PCI device from the EFI,
That includes un-installing PciIo protocol from the specified PCI
device handle.
Arguments:
Controller - An efi handle.
Handle - An efi handle.
Returns:
None
--*/
// TODO: EFI_SUCCESS - 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_PCI_IO_PROTOCOL *PciIo;
EFI_STATUS Status;
PCI_IO_DEVICE *PciIoDevice;
PCI_IO_DEVICE *Node;
EFI_LIST_ENTRY *CurrentLink;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
Status = gBS->OpenProtocol (
Handle,
&gEfiPciIoProtocolGuid,
(VOID **) &PciIo,
gPciBusDriverBinding.DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (!EFI_ERROR (Status)) {
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);
//
// If it is already de-registered
//
if (!PciIoDevice->Registered) {
return EFI_SUCCESS;
}
//
// If it is PPB, first de-register its children
//
if (!IsListEmpty (&PciIoDevice->ChildList)) {
CurrentLink = PciIoDevice->ChildList.ForwardLink;
while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) {
Node = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
Status = DeRegisterPciDevice (Controller, Node->Handle);
if (EFI_ERROR (Status)) {
return Status;
}
CurrentLink = CurrentLink->ForwardLink;
}
}
//
// Uninstall Pccard Hotplug GUID for Pccard device
//
UninstallPciHotplugGuid (PciIoDevice);
//
// Close the child handle
//
Status = gBS->CloseProtocol (
Controller,
&gEfiPciRootBridgeIoProtocolGuid,
gPciBusDriverBinding.DriverBindingHandle,
Handle
);
//
// Un-install the device path protocol and pci io protocol
//
if (PciIoDevice->BusOverride) {
Status = gBS->UninstallMultipleProtocolInterfaces (
Handle,
&gEfiDevicePathProtocolGuid,
PciIoDevice->DevicePath,
&gEfiPciIoProtocolGuid,
&PciIoDevice->PciIo,
&gEfiBusSpecificDriverOverrideProtocolGuid,
&PciIoDevice->PciDriverOverride,
NULL
);
} else {
Status = gBS->UninstallMultipleProtocolInterfaces (
Handle,
&gEfiDevicePathProtocolGuid,
PciIoDevice->DevicePath,
&gEfiPciIoProtocolGuid,
&PciIoDevice->PciIo,
NULL
);
}
if (EFI_ERROR (Status)) {
gBS->OpenProtocol (
Controller,
&gEfiPciRootBridgeIoProtocolGuid,
(VOID **) &PciRootBridgeIo,
gPciBusDriverBinding.DriverBindingHandle,
Handle,
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
);
return Status;
}
//
// The Device Driver should disable this device after disconnect
// so the Pci Bus driver will not touch this device any more.
// Restore the register field to the original value
//
PciIoDevice->Registered = FALSE;
PciIoDevice->Handle = NULL;
} else {
//
// Handle may be closed before
//
return EFI_SUCCESS;
}
return EFI_SUCCESS;
}
EFI_STATUS
StartPciDevicesOnBridge (
IN EFI_HANDLE Controller,
IN PCI_IO_DEVICE *RootBridge,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,
IN OUT UINT8 *NumberOfChildren,
IN OUT EFI_HANDLE *ChildHandleBuffer
)
/*++
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
--*/
// TODO: EFI_NOT_READY - add return value to function comment
// TODO: EFI_SUCCESS - add return value to function comment
// TODO: EFI_UNSUPPORTED - add return value to function comment
// TODO: EFI_NOT_FOUND - add return value to function comment
{
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;
UINT64 Supports;
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
);
}
if (NumberOfChildren != NULL && ChildHandleBuffer != NULL && Temp->Registered) {
ChildHandleBuffer[*NumberOfChildren] = Temp->Handle;
(*NumberOfChildren)++;
}
//
// Get the next device path
//
CurrentDevicePath = EfiNextDevicePathNode (RemainingDevicePath);
if (EfiIsDevicePathEnd (CurrentDevicePath)) {
return EFI_SUCCESS;
}
//
// If it is a PPB
//
if (!IsListEmpty (&Temp->ChildList)) {
Status = StartPciDevicesOnBridge (
Controller,
Temp,
CurrentDevicePath,
NumberOfChildren,
ChildHandleBuffer
);
Temp->PciIo.Attributes (
&(Temp->PciIo),
EfiPciIoAttributeOperationSupported,
0,
&Supports
);
Supports &= EFI_PCI_DEVICE_ENABLE;
Temp->PciIo.Attributes (
&(Temp->PciIo),
EfiPciIoAttributeOperationEnable,
Supports,
NULL
);
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 (NumberOfChildren != NULL && ChildHandleBuffer != NULL && Temp->Registered) {
ChildHandleBuffer[*NumberOfChildren] = Temp->Handle;
(*NumberOfChildren)++;
}
if (!IsListEmpty (&Temp->ChildList)) {
Status = StartPciDevicesOnBridge (
Controller,
Temp,
RemainingDevicePath,
NumberOfChildren,
ChildHandleBuffer
);
Temp->PciIo.Attributes (
&(Temp->PciIo),
EfiPciIoAttributeOperationSupported,
0,
&Supports
);
Supports &= EFI_PCI_DEVICE_ENABLE;
Temp->PciIo.Attributes (
&(Temp->PciIo),
EfiPciIoAttributeOperationEnable,
Supports,
NULL
);
}
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
--*/
// TODO: EFI_UNSUPPORTED - add return value to function comment
// TODO: EFI_SUCCESS - add return value to function comment
{
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,
NULL,
NULL
);
}
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;
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
Dev = NULL;
Status = gBS->AllocatePool (
EfiBootServicesData,
sizeof (PCI_IO_DEVICE),
(VOID **) &Dev
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?