使用基于数据包的总线主控 DMA

若要使用基于数据包的 DMA,总线主 DMA 设备的驱动程序在处理请求 DMA 传输的 IRP 时调用以下常规支持例程序列:

  • 尝试为传输请求 (分配映射寄存器之前,请参阅 维护缓存一致性)

  • 当驱动程序准备好对 DMA 的总线主适配器进行编程时,AllocateAdapterChannel

  • MmGetMdlVirtualAddress 用于获取 MDL 中的索引(需要作为 MapTransfer 的初始参数), MapTransfer 使支持 IRP 缓冲区的系统物理内存可供设备访问

    请注意,任何驱动程序可能需要执行多个传输操作才能满足当前 IRP,如 拆分传输请求中所述。 没有散点/收集功能的设备的驱动程序每次传输操作都可以调用 MapTransfer 一次。 具有散点/收集功能的设备的驱动程序可以多次调用 MapTransfer 来设置每个传输操作。 或者,这些驱动程序可以使用系统的内置散点/收集支持,如 使用散点/收集 DMA 中所述。

  • 在目标设备的每个 DMA 传输操作结束时的 FlushAdapterBuffers,以确定是否已完全传输所有请求的数据

  • 完成当前 IRP 的所有 DMA 操作后,FreeMapRegisters 会立即执行,因为所有请求的数据都已完全传输,或者驱动程序必须因设备或总线 I/O 错误而使 IRP 失败

IoGetDmaAdapter 返回的适配器对象指针是 AllocateAdapterChannelMapTransferFlushAdapterBuffersFreeMapRegisters 的必需参数。 请注意,在 Windows 2000 之前的 Windows NT 版本中,总线主设备可以将 NULL 适配器对象指针传递给 MapTransferFlushAdapterBuffers。 在 Windows 2000 及更高版本中,驱动程序无法再执行此操作。

KeFlushIoBuffersMmGetMdlVirtualAddress 需要指向 Irp-MdlAddress> 处的 MDL 的指针。

各个驱动程序在不同点调用此支持例程序列,具体取决于实现每个驱动程序以为其设备提供服务的方式。 例如,一个驱动程序的 StartIo 例程可能会调用 AllocateAdapterChannel,而另一个驱动程序可能会从从驱动程序创建的互锁队列或设备队列中删除 IRP 的例程发出此调用。

使用基于数据包的 DMA 的任何驱动程序都可以使用旨在简化散点/收集 DMA 的支持例程,而不使用本节中所述的例程,而不管其设备是否具有内置的散点/收集支持。 有关详细信息 ,请参阅使用散点/收集 DMA