5

我正在评估将几年前编写的设备驱动程序从 32 位移植到 64 位。物理设备是 32 位 PCI 卡。也就是说,该设备是 32 位的,但我需要从 Win7x64 访问它。该设备向 Windows 世界提供一些寄存器,然后执行繁重的总线主数据传输到一块驱动程序分配的内存中。

我在 Microsoft 文档中读到,您可以指示驱动程序是否支持 64 位 DMA。如果不是,则 DMA 是双缓冲的。但是,我不确定是否是这种情况。我的驱动程序将/可能是一个完整的 64 位驱动程序,因此它可以支持处理器地址空间中的 64 位地址,但实际的物理设备不支持它。事实上,设备 BAR 必须映射到 4 GB 以下,并且设备必须获得一个 PC RAM 地址才能执行 4 GB 以下的总线主控。这是否意味着我的驱动程序将始终通过双缓冲?这是一个对性能非常敏感的过程,双缓冲可能会阻止整个系统工作。

当然,设计一个新的 64 位 PCI(或 PCI-E)板是没有问题的。

任何人都可以为这个过程提供一些资源(除了 MS 页面)?

非常感谢!

4

2 回答 2

0

这是一个旧帖子,我希望答案仍然相关......

这里有两个部分,PCI target 和 PCI master access。

PCI 目标访问:驱动程序将 PCI BAR 映射到 64 位虚拟地址空间,驱动程序只需通过指针读取/写入。

PCI 主访问:您需要通过调用IoGetDmaAdapter()创建一个 DmaAdapter 对象。创建时,您还描述了您的设备是 32 位的(请参阅 DEVICE_DESCRIPTION 参数)。然后调用DmaAdapter::AllocateCommonBuffer()方法在 PC RAM 中分配一个连续的 DMA 缓冲区。

不过,我不确定双缓冲。根据我的经验,不使用双缓冲,而是 DmaAdapter::AllocateCommonBuffer() 如果无法分配满足 DEVICE_DESCRIPTION 的缓冲区(在您的情况下为 32 位 dma 寻址),则会失败。

于 2014-08-31T15:02:38.343 回答
0

为仅支持 32 位 PCI 寻址的设备编写 64 位驱动程序没有问题。正如 Alexey 所指出的,您创建的 DMA 适配器对象指定了您设备的硬件寻址能力。当您分配 DMA 缓冲区时,操作系统会考虑到这一点,并确保在您的硬件可访问区域内分配这些缓冲区。Linux 驱动程序的行为类似,您的驱动程序必须提供一个 DMA 地址掩码以与您的设备相关联,稍后使用的 DMA 函数将引用该掩码。

如果您的应用程序分配了一个需要 DMA 进出的缓冲区,您可能会遇到的性能损失。这个缓冲区可以分散在整个内存中,内存中的页面超过 4G。如果您的驱动程序计划对这些进行 DMA,则需要在 DMA 期间将缓冲区页面锁定在 RAM 中,并根据页面位置为您的 DMA 引擎构建一个 SGL。问题是,对于 4G 以上的页面,操作系统必须将它们复制/移动到 4G 以下的页面,以便您的 DMA 引擎能够访问它们。这就是潜在的性能冲击所在。

于 2021-08-06T05:45:44.263 回答