返回
UEFI开发探索14 – 访问PCI/PCI-E设备2
闲谈
2023-11-12 20:57:55
前言
在上一篇博客中,我们已经介绍了如何访问PCI设备。在本篇博客中,我们将继续深入探讨这一主题,并介绍如何理解PCI设备,以及在X86平台下访问PCIe设备的基本原理。
PCI设备的理解
要访问PCI设备,首先需要了解PCI设备的结构和工作原理。PCI设备通常由以下几个部分组成:
- PCI设备ID :用于标识PCI设备的唯一标识符。
- PCI地址 :用于寻址PCI设备的地址。
- PCI配置空间 :用于配置PCI设备的寄存器集。
- PCI中断线 :用于处理PCI设备中断的线路。
- PCI总线 :用于连接PCI设备的总线。
访问PCIe设备
在X86平台下,访问PCIe设备与访问PCI设备类似。然而,由于PCIe设备是一种高速设备,因此在访问PCIe设备时需要考虑一些特殊因素。
- PCIe设备的配置空间 :PCIe设备的配置空间与PCI设备的配置空间类似,但PCIe设备的配置空间更大。
- PCIe设备的中断线 :PCIe设备的中断线与PCI设备的中断线类似,但PCIe设备的中断线更多。
- PCIe总线 :PCIe总线与PCI总线类似,但PCIe总线的速度更快。
访问PCI/PCI-E设备的示例代码
为了帮助您理解如何访问PCI/PCI-E设备,我们提供了一个示例代码。该示例代码演示了如何访问PCI/PCI-E设备的配置空间和中断线。
#include <efi.h>
#include <uefi/pi/pi.h>
#include <uefi/pi/pci.h>
EFI_STATUS
EFIAPI
UefiMain(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_HANDLE PciRootHandle;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
EFI_PCI_IO_PROTOCOL *PciIo;
UINT64 PciAddress;
UINT8 Data;
// 获取PCI根桥接IO协议
Status = SystemTable->BootServices->LocateProtocol(
&gEfiPciRootBridgeIoProtocolGuid,
NULL,
(VOID **)&PciRootBridgeIo
);
if (EFI_ERROR(Status)) {
return Status;
}
// 获取PCI IO协议
Status = PciRootBridgeIo->GetVirtualDeviceIo(
PciRootBridgeIo,
EFI_PCI_IO_PROTOCOL_PCI_ROOT_BRIDGES_IO,
&PciIo
);
if (EFI_ERROR(Status)) {
return Status;
}
// 获取PCI设备地址
Status = PciIo->GetLocation(
PciIo,
&PciAddress
);
if (EFI_ERROR(Status)) {
return Status;
}
// 读取PCI设备配置空间
Status = PciIo->Pci.Read(
PciIo,
EfiPciWidthUint8,
0,
1,
&Data
);
if (EFI_ERROR(Status)) {
return Status;
}
// 打印PCI设备配置空间
Print(L"PCI设备配置空间:%x\n", Data);
// 获取PCI设备中断线
Status = PciIo->GetInterruptLine(
PciIo,
&Data
);
if (EFI_ERROR(Status)) {
return Status;
}
// 打印PCI设备中断线
Print(L"PCI设备中断线:%d\n", Data);
return EFI_SUCCESS;
}
结语
本文介绍了如何理解PCI设备,以及如何在X86平台下访问PCIe设备的基本原理。我们还提供了一个示例代码,演示了如何访问PCI/PCI-E设备的配置空间和中断线。希望本文对您有所帮助。