PCI/PCIe 设备如何在 Linux 内核中初始化/注册自己?

hoo*_*oao 5 linux linux-device-driver linux-kernel pci pci-e

当内核启动时,PCI 子系统pci_bus为每个物理 PCI 总线创建一个,然后pci_bus添加到pci_root_buses(带有 PCI 配置)。但是 PCI 设备驱动程序通过注册驱动程序pci_register_driver,并将 PCI 驱动程序添加到pci_bus_type.

我的问题?

  • 怎么pci_bus_type知道PCI配置。
  • pci_bus_type和之间是什么关系pci_root_buses

Ale*_*lex 5

由于问题部分不完整,但评论太小而无法给出答案,因此我会尝试将其混为一谈。

因此内核试图从驱动程序开发人员那里抽象出 PCI(e) 总线的物理实现。因此,NVidia Tegra 上的 PCI 总线与 Freescale ARM 上的 PCI 总线和 x86_64 PCI 总线不同,但无论实际总线实现如何,都应该可以针对它们注册设备。

该结构pci_root_buses是抽象 PCI 总线的列表,其中的实现可能不同。

您可以在总线类型结构中看到这一点,其中定义了函数指针以允许每个实际总线具有如何处理设备的不同实现。我认为最好阅读LDD3 中PCI 章节并特别查看Boot Time

另请查看配置时间以了解内核如何将驱动程序与硬件匹配。PCI 的粗略思想是内核可以发现总线并将内存映射到每个物理 PCI 设备,从而允许访问设备的 PCI 配置空间。驱动程序开发人员通过调用pci_register_driver并因此告诉内核哪些驱动程序函数用于某些供应商 ID 来注册设备类。

再次查看 LDD3,您可能正在寻找的缺失映射似乎是探测函数:

int (*probe) (struct pci_dev *dev, const struct pci_device_id *id);
Run Code Online (Sandbox Code Playgroud)

指向 PCI 驱动程序中的探测函数的指针。当 PCI 内核有一个struct pci_dev它认为这个驱动程序想要控制的对象时,这个函数就会被调用。一个指向struct pci_device_idPCI 内核用来做出这个决定的指针也被传递给这个函数。如果 PCI 驱动程序声明struct pci_dev传递给它的 ,它应该正确地初始化设备并且return 0. 如果驱动程序不想声明设备,或者发生错误,它应该返回一个负错误值。本章稍后将提供有关此功能的更多详细信息。

内核数据结构

进一步阅读