PCIe设备发现算法伪代码

PCIe device discovery algorithm pseudo code

我有一个用 System Verilog 编写的 PCIe 模型,尽管我认为这个问题与语言无关。该模型在仿真中完美地执行了PCIe配置读写和内存读写。但是,我需要做的是 "discover" 我的 PCIe 设备并在模拟中配置我的配置 space 寄存器。是否有代表 Linux PCIe 枚举过程的样板伪代码块,我也可以添加自己的模型事务函数,以便获得 "Bus walk",然后是 BAR 编程,SR-如果发现 IOV 启用,MSIx 配置?这似乎是 PCIe 设备的常见练习,所以也许有模型。

做起来并不难。基本上你循环遍历配置 space,检查第一个根总线 0 上每个可能的设备。找到设备后,你根据其请求的大小为其分配内存 space 并编程BAR相应。如果您找到任何桥接器,您还可以配置并启用它们 - 用于此的基本桥接器寄存器是标准的。这包括分配上游和下游总线编号,然后允许您枚举新的下游总线,等等。

我必须这样做一次才能在没有 OS 或其他软件环境的系统上访问 PCI I/O 卡。这还不算太糟糕,它跨越了两个供应商的两个桥,以及 I/O 卡寄存器和 CPU 总线根桥设置。这是 PCI,不是 PCIe,但它们非常相似。如果硬件从未改变,您甚至可以完全使用 hard-coded 数字来完成它,但在我的情况下有几个变体,所以我实际上不得不做一些简单的枚举来动态查找设备编号。一个问题是,您可能需要稍微延迟或重试,以便让所有设备有时间在线,然后再尝试访问它们。

在这样做的过程中,我发现这本书非常宝贵PCI System Architecture (4th Edition). I notice there is also an version for PCIe: PCI Express System Architecture (1st Edition)。如果你还没有,我肯定会得到其中之一。这些书包含有关如何执行所有这些操作的详细算法和解释。当时我并没有真正使用或参考任何代码可言,但是...

我找到的最好的代码资源是 U-Boot。它以类似 low-level 的速度运行,并且完全独立,并且仍然相当小且尽可能简单。例如,枚举似乎以函数 pci_init() 调用板特定 pci_xxx_init() 开始。然后设置根桥,然后调用 drivers/pci/pci.c to do the real work. Also check out the routines in drivers/pci/pci_auto.c 中的 pci_hose_scan_bus() 以及文件夹的其余部分。

对于您的任务,您可能只需要一个非常小的子集,并且可以将这些文件的一部分破解成一个简单的驱动程序。基本上是一个 for() 循环和一些带有逻辑的 pci_read/write_config() 调用来识别您的设备和网桥 ID。