PCIE 子系统框架
PCIe(Peripheral Component Interconnect Express)是一种高速串行总线标准,用于连接计算机的外设。PCIE子系统框架是Linux内核用于支持PCIe设备的驱动程序的基础框架,它包含一系列接口和函数,可以让驱动程序开发人员更容易地编写、测试和调试PCIe设备的驱动程序。
PCIE子系统框架的核心是PCIe总线驱动程序,它负责管理PCIe总线的初始化、配置、寻址和访问等功能。驱动程序开发人员可以使用PCIe总线驱动程序提供的接口来注册PCIe设备驱动程序、处理中断、读写寄存器和DMA操作等。此外,PCIe子系统框架还提供了一些辅助函数和宏定义,用于简化驱动程序的编写过程。
PCIE子系统框架的一些重要接口和函数包括:
pci_register_driver()/pci_unregister_driver():用于注册和注销PCIe设备驱动程序。
pci_enable_device()/pci_disable_device():用于启用和禁用PCIe设备,并分配和释放设备资源。
pci_request_regions()/pci_release_regions():用于请求和释放设备的I/O端口、内存映射和中断资源等。
pci_iomap()/pci_iounmap():用于映射和解除映射设备的I/O端口或内存空间。
pci_enable_msi()/pci_disable_msi():用于启用和禁用设备的MSI(Message Signaled Interrupts)中断。
pci_irq_vector():用于获取设备的中断向量。
pci_map_sg()/pci_unmap_sg():用于将设备内存映射到散列表中。
pci_dma_sync_sg_for_cpu()/pci_dma_sync_sg_for_device():用于同步DMA缓冲区和设备内存之间的数据传输。
pci_set_drvdata()/pci_get_drvdata():用于存储和获取设备特定数据的指针。
使用PCIE子系统框架,驱动程序开发人员可以更快速地开发PCIe设备的驱动程序,并减少错误和故障的发生。
以下是 PCIe 子系统中常用的一些接口函数:
pci_register_driver() 和 pci_unregister_driver():分别用于注册和注销 PCI 驱动程序。
pci_enable_device() 和 pci_disable_device():分别用于启用和禁用 PCI 设备。
pci_request_region() 和 pci_release_region():分别用于请求和释放 PCI 区域。
pci_request_irq() 和 pci_free_irq():分别用于请求和释放 PCI 设备的中断。
pci_set_master() 和 pci_clear_master():分别用于设置和清除 PCI 设备的总线主控模式。
pci_enable_msi() 和 pci_disable_msi():分别用于启用和禁用 PCI 设备的 MSI 中断。
pci_enable_msix() 和 pci_disable_msix():分别用于启用和禁用 PCI 设备的 MSIX 中断。
pci_enable_sriov() 和 pci_disable_sriov():分别用于启用和禁用 PCI 设备的 SR-IOV 功能。
pci_find_capability() 和 pci_read_config_dword():分别用于查找和读取 PCI 设备的配置寄存器。
pci_set_drvdata() 和 pci_get_drvdata():分别用于设置和获取 PCI 设备的私有数据。
pci_save_state() 和 pci_restore_state():分别用于保存和恢复 PCI 设备的状态。
pci_bus_read_config_byte() 和 pci_bus_write_config_byte():分别用于读取和写入 PCI 总线的配置寄存器。
pci_find_device() 和 pci_find_slot():分别用于查找指定设备ID或槽位号的PCI设备。
pci_get_domain_bus_and_slot():用于查找指定域、总线和槽位号的PCI设备。
这些接口函数可以通过PCI子系统框架来访问PCI总线,进行PCI设备驱动程序的开发。
例子程序
以下是一个简单的 PCIe 驱动的示例代码,包括设备树和驱动代码。
设备树:
/dts-v1/;
/include/ "dtsi/pinctrl-jetson-io.h"
/ {
model = "NVIDIA Jetson Nano Developer Kit";
compatible = "nvidia,jetson-nano-pcie", "nvidia,jetson-nano";
fragment@0 {
target = <&pcie>;
__overlay__ {
status = "okay";
num-lanes = <1>;
max-speed = <2>;
bus-range = <0 1>;
ranges = <0x02000000 0 0x80000000 0x80000000 0 0x1000000>; // 2GB window
mydevice: mydevice@0,0 {
compatible = "mycompany,mydevice";
reg = <0x0 0x0 0x0 0x0>;
};
};
};
};
驱动代码:
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
static const struct pci_device_id mydevice_pci_ids[] = {
{ PCI_DEVICE(0x1234, 0x5678) },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, mydevice_pci_ids);
static int mydevice_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
int ret;
/* enable the device */
ret = pci_enable_device(pdev);
if (ret < 0) {
dev_err(&pdev->dev, "failed to enable device\n");
return ret;
}
/* configure the device */
pci_set_master(pdev);
/* register a platform device */
ret = platform_device_register_simple("mydevice", -1, NULL, 0);
if (ret < 0) {
dev_err(&pdev->dev, "failed to register platform device\n");
pci_disable_device(pdev);
return ret;
}
return 0;
}
static void mydevice_remove(struct pci_dev *pdev)
{
/* unregister the platform device */
platform_device_unregister(platform_device_find("mydevice", -1));
/* disable the device */
pci_disable_device(pdev);
}
static struct pci_driver mydevice_driver = {
.name = "mydevice",
.id_table = mydevice_pci_ids,
.probe = mydevice_probe,
.remove = mydevice_remove,
};
module_pci_driver(mydevice_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("My PCIe device driver");
这个驱动将寻找 ID 为 0x1234:0x5678 的 PCIe 设备,然后为它创建一个平台设备 mydevice。当设备被移除时,平台设备也会被自动注销。