PMAP_TRANSFER_EX回调函数 (wdm.h)
MapTransferEx 例程设置映射寄存器,以将散点/收集列表中的物理地址映射到执行 DMA 传输所需的逻辑地址。
语法
PMAP_TRANSFER_EX PmapTransferEx;
NTSTATUS PmapTransferEx(
[in] PDMA_ADAPTER DmaAdapter,
[in] PMDL Mdl,
[in] PVOID MapRegisterBase,
[in] ULONGLONG Offset,
[in] ULONG DeviceOffset,
[in, out] PULONG Length,
[in] BOOLEAN WriteToDevice,
[out, optional] PSCATTER_GATHER_LIST ScatterGatherBuffer,
[in] ULONG ScatterGatherBufferLength,
[in, optional] PDMA_COMPLETION_ROUTINE DmaCompletionRoutine,
[in, optional] PVOID CompletionContext
)
{...}
参数
[in] DmaAdapter
指向 DMA_ADAPTER 结构的指针。 此结构是适配器对象,表示驱动程序的总线主 DMA 设备或系统 DMA 通道。 调用方从对 IoGetDmaAdapter 例程的上一次调用中获取了此指针。
[in] Mdl
指向 MDL 链的指针,用于描述虚拟内存中锁定缓冲区集合的物理页面布局。 DMA 传输的散点/收集列表将使用由 Offset 和 Length 参数指定的内存区域。 有关 MDL 链的详细信息,请参阅 使用 MDL。
[in] MapRegisterBase
为适配器对象分配的映射寄存器的句柄。 调用方以前从 AllocateAdapterChannelEx 例程获取此句柄。
[in] Offset
MDL 链描述的内存起始位置的字节偏移量。 此偏移量指定用于 DMA 传输的 I/O 数据缓冲区的起始位置。 如果向调用方提供散点/收集列表,则此偏移量将确定列表中第一个缓冲区片段的起始地址。 如果 MDL 链中的 MDL 描述内存的总 N 个字节, 则 Offset 的有效值介于 0 到 N–1 之间。 有关详细信息,请参阅“备注”。
[in] DeviceOffset
目标设备的数据寄存器或 FIFO 与设备基址的字节偏移量。 此参数适用于具有多个 FIFO 的设备,这些 FIFO 可由系统 DMA 控制器访问。 此参数仅用于系统 DMA 传输。 对于总线主传输,请将此参数设置为零。
[in, out] Length
指向变量的指针,该变量包含用于 DMA 传输的 I/O 数据缓冲区的长度(以字节为单位)。 在输入时,此变量包含调用驱动程序请求的长度。 在返回之前,例程会将映射缓冲区的实际长度写入此变量。 从 MapTransferEx 返回时*Length 的值指示映射了多少个字节。 如果映射寄存器数和散点/收集缓冲区大小足以映射调用方请求的整个长度,则 *Length 的输入和输出值相同。 如果 MDL 链中的 MDL 描述内存的总 N 个字节,则 *Length 的有效值介于 0 到 N–Offset 之间。
[in] WriteToDevice
DMA 传输的方向。 对于写入操作,将此参数设置为 TRUE ,以便将数据从内存传输到设备。 对于读取操作,将此参数设置为 FALSE ,以便将数据从设备传输到内存。
[out, optional] ScatterGatherBuffer
指向调用方分配的缓冲区的指针,例程在其中写入 DMA 传输的散点/收集列表。 此列表以 SCATTER_GATHER_LIST 结构开头,紧跟 SCATTER_GATHER_ELEMENT 数组。 对于使用总线主 DMA 设备的驱动程序, ScatterGatherBuffer 是必需参数。 对于使用系统 DMA 控制器的驱动程序, ScatterGatherBuffer 参数是可选的,可以为 NULL。 有关详细信息,请参阅“备注”。
[in] ScatterGatherBufferLength
ScatterGatherBuffer 参数指向的缓冲区的大小(以字节为单位)。 分配的缓冲区大小必须足够大,才能包含散点/收集列表,以及操作系统在此缓冲区中存储的内部数据。 若要确定所需的缓冲区大小,请调用 GetDmaTransferInfo 或 CalculateScatterGatherList 例程。 如果 ScatterGatherBuffer 为 NULL,请将 ScatterGatherBufferLength 设置为零。
[in, optional] DmaCompletionRoutine
指向调用方提供的 DmaCompletionRoutine 例程的指针,该例程将在 DMA 传输完成时调用。 如果目标设备使用生成 DMA 完成中断的系统 DMA 控制器,则调用此例程。 DMA 传输完成后,DISPATCH_LEVEL调用 DmaCompletionRoutine 例程。 对于系统 DMA 适配器,此参数是可选的,可以为 NULL。 对于总线主适配器,请将此参数设置为 NULL。
[in, optional] CompletionContext
DmaCompletionRoutine 例程的驱动程序确定上下文。 此上下文作为 CompletionContext 参数提供给 DmaCompletionRoutine 例程。 如果 DmaCompletionRoutine 参数为 NULL,请将 CompletionContext 设置为 NULL。
返回值
如果调用成功,MapTransferEx 将返回STATUS_SUCCESS。 可能的错误返回值包括以下状态代码。
返回代码 | 说明 |
---|---|
|
由于调用方传递的参数值无效,例程失败。 |
|
ScatterGatherBuffer 中调用方提供的缓冲区太小,无法包含散点/收集列表。 |
|
例程未能分配 DMA 传输所需的资源。 |
|
此转移已取消。 |
注解
MapTransferEx 不是可直接按名称调用的系统例程。此例程只能由DMA_OPERATIONS结构中返回的地址中的指针调用 。 驱动程序通过调用 IoGetDmaAdapter(DeviceDescription 参数的 Version 成员设置为 DEVICE_DESCRIPTION_VERSION3)来获取此例程的地址。 如果 IoGetDmaAdapter 返回 NULL,则例程在平台上不可用。
对于使用系统 DMA 控制器的传输,调用方可以选择提供传输完成后调用的 DmaCompletionRoutine 回调例程。 操作系统计划此回调以响应来自系统 DMA 控制器的 DMA 完成中断。
MapTransferEx 可以设置的映射寄存器数不能超过驱动程序从 IoGetDmaAdapter 获取的最大值。
Mdl、Offset 和 Length 参数描述所请求的 DMA 传输的 I/O 数据缓冲区。 分配的映射寄存器数可能不足以映射此缓冲区中的所有内存,或者 ScatterGatherBuffer 指向的散点/收集缓冲区可能不够大,无法描述整个缓冲区。 MapTransferEx 将输出值写入 *Length ,告诉驱动程序例程映射了请求的 DMA 传输的缓冲区内存量。 例程将散点/收集列表写入 ScatterGatherBuffer 指向的缓冲区。 此列表描述例程成功映射的缓冲区片段。
如果对 MapTransferEx 的 调用成功, 则 MapTransferEx 将在返回之前写入 *Length 输出值。 如果调用方指定 DmaCompletionRoutine,则更新后的 *Length 输出值始终在 DmaCompletionRoutine 运行之前写入。 有关详细信息,请参阅 多次调用 MapTransferEx。
Offset 参数指定 MDL 链中的起始偏移量,该链描述 I/O 数据缓冲区中的内存。 例如,假设 MDL 链包含两个 MDL,MDL₁ 和 MDLЛ,MDL₁ 描述内存的 N₁ 字节,MDLー 描述 N 个字节。 如果 Offset = N,其中 N₁ < N < ₁ + Nл,则缓冲区不包含 MDL₁ 描述的内存,并且从 MDLЛ 描述的内存中的 N - N₁ 字节的偏移量开始。
如果传输使用系统 DMA 控制器,则调用方可以设置 ScatterGatherBuffer = NULL,在这种情况下 ,MapTransferEx 使用内部分配的默认缓冲区来保存散点/收集列表。 默认缓冲区保证足够大,以包含至少一个元素的散点/收集列表。 如果默认缓冲区用于许多元素的散点/收集传输,则可能需要多次调用 MapTransferEx 来完成传输。 如果 DMA 控制器硬件支持散点/收集传输,则使用默认缓冲区可能会降低性能。
如果 ScatterGatherBuffer 为非 NULL 且 ScatterGatherBufferSize 指定的大小太小,无法包含至少一个元素的散点/收集列表, 则 MapTransferEx 将失败并返回STATUS_INVALID_PARAMETER。
MapTransferEx 是 MapTransfer 例程的扩展版本。 扩展版本具有以下优点:
- MapTransferEx 可以在一次调用中处理 MDL 链中的所有缓冲区片段,但 MapTransfer 每次调用只能处理一个物理连续缓冲区片段。
- MapTransferEx 可以在一次调用中生成整个散点/收集列表,但 MapTransfer 每次调用只能生成一个散点/收集列表元素。
- MapTransferEx 可以在一次调用中映射散点/收集列表中的所有缓冲区片段,但 MapTransfer 每次调用只能映射一个物理连续缓冲区片段。
- MapTransferEx 只需要整个散点/收集列表的起始偏移量,但 MapTransfer 需要每个物理连续缓冲区片段的起始虚拟地址。
- MapTransferEx 调用可以映射通过一个或多个 MDL 扩展的缓冲区,但 MapTransfer 调用只能映射 MDL 描述的内存中的一个物理连续缓冲区片段。
- 对于系统 DMA 传输, MapTransferEx 允许调用方提供 DmaCompletionRoutine 回调例程,以便在传输完成后接收通知,但 MapTransfer 不提供在 DMA 传输完成时通知调用方的方法。
有关详细信息,请参阅 使用 MapTransferEx 例程。
要求
要求 | 值 |
---|---|
最低受支持的客户端 | 从Windows 8开始可用。 |
目标平台 | 桌面 |
标头 | wdm.h(包括 Wdm.h、Ntddk.h、Ntifs.h) |
IRQL | <= DISPATCH_LEVEL |