DMA 通道对象

注释

Microsoft支持多样化的包容性环境。 本文包含有关无偏见通信 Microsoft风格指南 识别为排除项的术语的参考。 本文中的单词或短语用于一致性,因为它当前显示在软件中。 当软件更新以删除某种语言时,本文将随之更新以保持一致。

PortCls 系统驱动程序实现 IDmaChannel 和 IDmaChannelSlave 接口,以实现 WaveCyclic 和 WavePci 微型端口驱动程序的优势。 IDmaChannel 表示 DMA 通道及其关联的 DMA 缓冲区和缓冲区使用参数。 此外,WaveCyclic 微型端口驱动程序使用 IDmaChannelSlave 管理从属设备的 DMA 通道。 IDmaChannelSlave 继承自 IDmaChannel。 有关控制 DMA 操作的信息,请参阅 适配器对象和 DMA

IDmaChannel 对象封装以下内容:

  • 主设备或从属设备的 DMA 通道

  • 与通道关联的数据缓冲区

  • 描述通道的使用方式的信息

端口和微型端口驱动程序使用 DMA 通道对象来传达有关 DMA 通道使用情况的信息。 通常,微型端口驱动程序在初始化期间或在创建流期间分配一组 DMA 通道。 在创建新流期间,微型端口驱动程序告知端口驱动程序将哪个 DMA 通道对象用于流。

可以为主设备或从属设备创建 DMA 通道对象:

  • 从属设备没有内置的 DMA 硬件功能,并且必须依赖系统 DMA 控制器来执行设备所需的任何数据传输。

  • 主设备使用自己的总线主控 DMA 硬件在系统总线上执行数据传输。

有关使用从属 DMA 通道对象的 WaveCyclic 设备的示例,请参阅早期版本的 Microsoft Windows 驱动程序工具包(WDK)中的 Sb16 示例音频驱动程序。 主 DMA 通道对象仅仅是一个用于在端口和微型端口驱动程序之间共享有关 DMA 通道信息的平台。 有关主设备和从属设备的详细信息,请参阅 适配器对象简介

主设备或从属设备的 DMA 通道对象公开以下内容:

  • 适配器对象

  • 驱动程序和 DMA 硬件可以共享的单个通用缓冲区

  • 可以查询和更改的缓冲区大小值

适配器对象是物理设备对象的 DMA 适配器结构(PDO)。 当微型端口驱动程序通过调用以下方法之一创建 DMA 通道对象时,会自动创建适配器对象:

IPortWavePci::NewMasterDmaChannel

IPortWaveCyclic::NewMasterDmaChannel

IPortWaveCyclic::NewSlaveDmaChannel

方法 IDmaChannel::GetAdapterObject 可用于获取指向适配器对象的指针。

适配器驱动程序还可以调用 PcNewDmaChannel 函数来创建 DMA 通道对象,但此函数比 IPortWaveXxx::NewXxxDmaChannel 调用更难使用,因为调用方必须显式指定设备对象和其他上下文信息。

对于从属设备的 DMA 通道,IDmaChannel::TransferCount 方法返回调用 IDmaChannelSlave::Start 中指定的最大传输大小(MapSize 参数)。 此外,适配器对象提供了一些用于操作和查询 DMA 设备的方法。 这些方法都对主 DMA 通道没有意义。

IDmaChannel::AllocateBufferIDmaChannel::FreeBuffer 用于管理与 DMA 通道对象关联的单个公共缓冲区。 保证对象分配的缓冲区可供驱动程序(使用内核虚拟内存地址)和 DMA 设备(具有物理内存地址)访问。 此外,缓冲区在物理上是连续的。 通常,最佳策略是在微型端口驱动程序初始化期间分配 DMA 缓冲区,当时物理连续内存最为充足。 IDmaChannel::AllocatedBufferSize 返回在调用 IDmaChannel::AllocateBuffer时指定的缓冲区大小。

IDmaChannel::MaximumBufferSize 指示可以使用的实际最大缓冲区大小。 如果分配的大小不是页面大小的偶数,则这可能会超过分配的大小。 如果 DMA 设备不支持分配大小的传输,则它可能小于分配的大小。 IDmaChannel::BufferSizeIDmaChannel::SetBufferSize 用于查询和设置要用于 DMA 传输的缓冲区大小。 分配缓冲区时,缓冲区大小设置为最大缓冲区大小。 初始化后,端口驱动程序和微型端口驱动程序都有机会更改缓冲区大小或发现其当前值。 微型端口驱动程序使用 IDmaChannel::BufferSize 的结果来确定当 DMA 通道启动时 DMA 操作的传输大小。 IDmaChannel::SystemAddressIDmaChannel::P hysicalAddress 分别用于获取缓冲区的虚拟地址和物理地址。

IDmaChannel::CopyToIDmaChannel::CopyFrom 从 DMA 缓冲区复制示例数据。 WaveCyclic 端口驱动程序调用这些方法,以在应用程序缓冲区和微型端口驱动程序的循环缓冲区之间复制音频数据。

DMA 缓冲区不一定用于传输流数据。 对于 WavePci 端口驱动程序,流式传输的数据以散播/聚集映射列表的形式传递到小端口驱动程序(或从中检索)。 但是,微型端口驱动程序仍可能使用 DMA 缓冲区作为共享内存空间,以便与适配器驱动程序通信。

端口驱动程序为微型端口驱动程序提供可用于创建 DMA 通道的函数。 除非在端口驱动程序的说明中另有说明,否则绝对不需要使用从端口驱动程序分配的 DMA 对象。 端口驱动程序只需要一个指向支持所需方法的 IDmaChannel 接口的指针。 查看每个端口驱动程序的文档,了解端口驱动程序所需的 DMA 通道方法列表。

通常,最简单的方法是使用端口驱动程序实现的 DMA 通道分配函数。 在极少数情况下,微型端口驱动程序开发人员可能需要实现自己的 DMA 通道对象以满足其特定适配器的特殊要求。 这有时需要实现新对象。 在其他情况下,让微型端口驱动程序的流对象公开 IDmaChannel 接口并实现 DMA 通道方法本身就足够了。

IDmaChannel 接口支持以下方法:

IDmaChannel::AllocateBuffer

IDmaChannel::AllocatedBufferSize

IDmaChannel::BufferSize

IDmaChannel::CopyFrom

IDmaChannel::CopyTo

IDmaChannel::FreeBuffer

IDmaChannel::GetAdapterObject

IDmaChannel::MaximumBufferSize

IDmaChannel::PhysicalAddress

IDmaChannel::SetBufferSize

IDmaChannel::SystemAddress

IDmaChannel::TransferCount

IDmaChannelSlave 接口通过添加以下方法扩展 IDmaChannel

IDmaChannelSlave::ReadCounter

IDmaChannelSlave::Start

IDmaChannelSlave::Stop

IDmaChannelSlave::WaitForTC