我正在测试一个 PCI 端点驱动程序,我想做从 PCI RootPort 端到 PCI 端点端的简单复制。在 PCI Endpoint 端,我们有从 PCI 地址到 CPU 物理地址的地址转换。我们可以在转换中配置 CPU 物理地址,使其映射到特定的 DRAM 区域。问题是我们如何在特定的 CPU 物理地址分配内存缓冲区以确保来自 RootPort 端的写入确实有效?
任何建议表示赞赏。非常感谢!
我正在测试一个 PCI 端点驱动程序,我想做从 PCI RootPort 端到 PCI 端点端的简单复制。在 PCI Endpoint 端,我们有从 PCI 地址到 CPU 物理地址的地址转换。我们可以在转换中配置 CPU 物理地址,使其映射到特定的 DRAM 区域。问题是我们如何在特定的 CPU 物理地址分配内存缓冲区以确保来自 RootPort 端的写入确实有效?
任何建议表示赞赏。非常感谢!
您需要先保留物理内存区域。最简单但丑陋的方法是将“mem =”参数传递给内核命令行,该参数将您感兴趣的物理内存范围排除在内核内存管理之外,然后使用ioremap () 获取它的虚拟映射。
例如,如果您的机器有 256 Mb 的 RAM 使用 mem=255M 保留最后一个 Mb 供您使用,然后通过 ioermap() 映射它
注意:根据@Adrian Cox 的反馈修复了原始答案。
如果您可以即时重新映射转换,那么您应该像使用 DMA 的任何驱动程序一样工作。您对此的基本参考是LDD3 的第 15 章,以及Linux DMA API。
您分配的是一个 DMA 相干缓冲区,通过dma_alloc_coherent
. 在大多数平台上,您应该能够传入一个空struct device
指针并获得一个通用的 DMA 地址。这将为您提供一个内核虚拟地址来访问数据,以及一个 dma 地址,它是通过您的转换层映射的 CPU 物理地址。
如果您的地址转换不是很灵活,您可能需要修改端点的平台代码以尽早保留此缓冲区,以满足地址对齐要求。这有点复杂,但是最近的内核更新了 bigphysarea补丁,这可能有助于作为一个起点。