我正在评估将几年前写的设备驱动程序从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页面)?
非常感谢!
答案 0 :(得分:0)
这是一篇很老的帖子,我希望答案仍然相关......
这里有两个部分,PCI目标和PCI主访问。
PCI目标访问:驱动程序将PCI BAR映射到64位虚拟地址空间,驱动程序只通过指针读取/写入。
PCI主访问:您需要通过调用IoGetDmaAdapter()来创建DmaAdapter对象。创建时,您还会描述您的设备是32位(请参阅DEVICE_DESCRIPTION参数)。然后调用DmaAdapter::AllocateCommonBuffer()方法在PC RAM中分配连续的DMA缓冲区。
我不确定双缓冲。根据我的经验,不使用双缓冲,相反,如果无法分配满足DEVICE_DESCRIPTION的缓冲区(在您的情况下为32位dma寻址),DmaAdapter :: AllocateCommonBuffer()就会失败。
答案 1 :(得分:0)
为仅支持 32 位 PCI 寻址的设备编写 64 位驱动程序没有问题。正如 Alexey 指出的,您创建的 DMA 适配器对象指定了您设备的硬件寻址能力。当您分配 DMA 缓冲区时,操作系统会考虑到这一点,并确保在您的硬件可访问区域内分配这些缓冲区。 Linux 驱动程序的行为类似,其中您的驱动程序必须提供 DMA 地址掩码以与稍后使用的 DMA 函数将引用的设备相关联。
您可能遇到的性能问题是,如果您的应用程序分配了一个您需要 DMA 到/从的缓冲区。这个缓冲区可以分散在整个内存中,内存中的页面超过 4G。如果您的驱动程序计划对这些进行 DMA,则需要在 DMA 期间锁定 RAM 中的缓冲区页面,并根据页面位置为您的 DMA 引擎构建 SGL。问题是,对于 4G 以上的页面,操作系统必须将它们复制/移动到 4G 以下的页面,以便您的 DMA 引擎能够访问它们。这就是潜在的性能损失所在。