使用公用缓冲区总线主控 DMA

使用 Bus-Master DMA 中所述,一些总线主 DMA 设备的驱动程序以独占方式使用 common-buffer DMA,而某些驱动程序将 common-buffer DMA 与基于数据包的 DMA 结合使用。

经济地使用 common-buffer DMA。 设置公共缓冲区可能会占用一些 (或全部,具体取决于请求的缓冲区的大小) 与表示总线-主适配器的适配器对象关联的映射寄存器。

以经济方式设置公共缓冲区区域(例如,使用 PAGE_SIZE 区块或单个分配)会为基于数据包的 DMA 操作留出更多的映射寄存器。 它还使更多的系统内存可用,用于其他目的,从而产生更好的整体驱动程序和系统性能。

若要为总线主 DMA 设置公共缓冲区,总线主 DMA 设备驱动程序必须使用 IoGetDmaAdapter 返回的适配器对象指针调用 AllocateCommonBuffer。 通常,驱动程序从其 DispatchPnP 例程针对 IRP_MN_START_DEVICE 请求进行此调用。 仅当驱动程序在驱动程序保持加载状态时重复使用该缓冲区执行其 DMA 操作时,驱动程序才应分配公共缓冲区。 下图演示了对 AllocateCommonBuffer 的此类调用。

说明为总线主 dma 分配公共缓冲区的示意图。

请求的缓冲区大小(在上图中显示为 LengthForBuffer)决定了必须使用多少个映射寄存器来为公共缓冲区提供虚拟到逻辑映射。 使用 BYTES_TO_PAGES 宏确定 (BYTES_TO_PAGES (LengthForBuffer) ) 所需的最大页数。 此值不能大于 IoGetDmaAdapter 返回的 NumberOfMapRegisters

此外,调用方必须提供以下内容:

  • 一个布尔值,指示是否应启用缓存

    注意 此值将被忽略。 操作系统确定是否在要分配的公共缓冲区中启用缓存内存。 该决策基于处理器体系结构和设备总线。

    在具有基于 x86、基于 x64 和基于 Itanium 的处理器的计算机上,将启用缓存内存。

    在具有基于 Arm 或 Arm 64 的处理器的计算机上,操作系统不会自动为所有设备启用缓存内存。 系统依赖于每个设备的 ACPI_CCA 方法来确定设备是否与缓存一致。

  • 指向驱动程序定义的变量的指针,该变量包含上图中缓冲区 (BufferLogicalAddress 的设备可访问的基逻辑地址) 从 AllocateCommonBuffer 返回时

如果调用成功, AllocateCommonBuffer 将为上图) 中缓冲区 (BufferVirtualAddress 返回驱动程序可访问的基虚拟地址,驱动程序必须将其保存在其设备扩展、控制器扩展或其他驱动程序可访问的驻留存储区域 (驱动程序) 分配的非分页池中。

如果 AllocateCommonBuffer 无法为缓冲区分配内存,则返回 NULL。 如果返回的基本虚拟地址为 NULL,则驱动程序必须以独占方式使用系统基于数据包的 DMA 支持,或者驱动程序必须使 IRP_MN_START_DEVICE 请求失败,从而返回STATUS_INSUFFICIENT_RESOURCES。

否则,驱动程序可以使用分配的公共缓冲区作为驱动程序和适配器可访问的存储区域进行 DMA 传输。

当 PnP 管理器发送停止或删除设备的 IRP 时,驱动程序必须调用 FreeCommonBuffer 来释放已分配的每个公共缓冲区。