DMA 通道对象

注意

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

PortCls 系统驱动程序会实现 IDmaChannelIDmaChannelSlave 接口,以方便 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 硬件可以共享的一个公共缓冲区

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

适配器对象物理设备对象 (PDO) 的 DMA 适配器结构。 当微型端口驱动程序通过调用以下方法之一创建 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::PhysicalAddress 分别用于获取缓冲区的虚拟地址和物理地址。

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