使用基于数据包的系统 DMA

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

  • 在尝试分配系统 DMA 控制器 (之前,KeFlushIoBuffers 有关详细信息,请参阅维护缓存一致性)

  • 当驱动程序准备好针对 DMA 对设备进行编程并需要系统 DMA 控制器时,AllocateAdapterChannel

    AllocateAdapterChannel 依次调用驱动程序的 AdapterControl 例程。

  • MmGetMdlVirtualAddress 获取 MDL 中的索引,在对 MapTransfer 的初始调用中需要作为参数

  • MapTransfer 为传输操作对系统 DMA 控制器进行编程

    驱动程序可能需要多次调用 MapTransfer 来传输所有请求的数据,如 拆分传输请求中所述。

  • FlushAdapterBuffers ,就在每个 DMA 传输操作与从属设备之间

    如果驱动程序必须多次调用 MapTransfer 以传输所有请求的数据,则它必须调用 FlushAdapterBuffers 的次数与调用 MapTransfer 的次数一样多。

  • FreeAdapterChannel 只要传输了所有请求的数据,或者驱动程序因设备 I/O 错误导致 IRP 失败

IoGetDmaAdapter 返回的适配器对象指针是每个例程的必需参数,KeFlushIoBuffersMmGetMdlVirtualAddress 除外,后者需要指向在 Irp-MdlAddress> 传递的 MDL 的指针。

各个驱动程序在不同点调用此支持例程序列,具体取决于实现每个驱动程序以为其设备提供服务的方式。 例如,一个驱动程序的 StartIo 例程可能会调用 AllocateAdapterChannel,另一个驱动程序可能会从从驱动程序创建的互锁队列中删除 IRP 的例程发出此调用,另一个驱动程序可能在其从属 DMA 设备指示它已准备好传输数据时发出此调用。