IPortWavePciStream::GetMapping 方法 (portcls.h)

GetMapping 方法从端口驱动程序获取映射,并将标记与映射相关联。

语法

NTSTATUS GetMapping(
  [in]  PVOID             Tag,
  [out] PPHYSICAL_ADDRESS PhysicalAddress,
  [out] PVOID             *VirtualAddress,
  [out] PULONG            ByteCount,
  [out] PULONG            Flags
);

参数

[in] Tag

指定要与映射关联的标记值。 端口驱动程序可以在后续 IMiniportWavePciStream::RevokeMappings 调用中使用此标记来标识要撤销的映射列表中的映射。 微型端口驱动程序使用标记来标识 IPortWavePciStream::ReleaseMapping 调用中释放映射的映射。

[out] PhysicalAddress

物理地址的输出指针。 此参数指向调用方分配的指针变量,该方法在其中写入映射的物理地址。 指定此参数的有效非 NULL 指针值。

[out] VirtualAddress

虚拟地址的输出指针。 此参数指向调用方分配的指针变量,该方法将映射的虚拟地址写入其中。 指定此参数的有效非 NULL 指针值。

[out] ByteCount

字节计数的输出指针。 此参数指向调用方分配的 ULONG 变量,该方法将映射中的字节数写入其中。 指定此参数的有效非 NULL 指针值。

[out] Flags

状态标志的输出指针。 此参数指向调用方分配的 ULONG 变量,该方法在其中写入状态标志。 指定此参数的有效非 NULL 指针值。 非零标志值指示在此调用中获取的映射是 I/O 数据包中的最后一个映射。 此标志可用于指示硬件在完成此映射时应中断微型端口驱动程序。 为了响应中断,微型端口驱动程序可以获取要传送到硬件的新映射。 微型端口驱动程序不强制以这种方式使用标志。

返回值

如果调用成功,GetMapping 返回STATUS_SUCCESS。 否则,该方法将返回适当的错误代码。 下表显示了一些可能的返回状态代码。

返回代码 描述
STATUS_NOT_FOUND
映射不可用,但当映射可用时,端口驱动程序将调用 IMiniportWavePciStream::MappingAvailable

言论

通过 GetMapping 方法获取的映射应通过调用 IPortWavePciStream::ReleaseMapping 释放,除非端口驱动程序吊销它们。 端口驱动程序可以通过调用流的 IMiniportWavePciStream::RevokeMappings 方法来撤销映射。

通过微型端口驱动程序的呈现引脚播放的流的缓冲区存储附加到一个或多个 IRP。 每个 IRP 都包含流的缓冲区存储的一部分。 每个 IRP 的缓冲区存储在虚拟内存中是连续的,但构成缓冲区的内存页通常不会映射到物理内存中的连续位置。 尽管驱动程序可以使用编程 I/O 通过其映射到虚拟内存来访问缓冲区,但 DMA 控制器需要物理映射。

WavePci 端口驱动程序使用 GetMapping 方法将缓冲区作为物理映射序列公开给微型端口驱动程序。 典型的映射是一个内存页或更小的大小,尽管如果两个或更多页碰巧占用物理内存中的相邻位置,映射可能会超过页面大小。

初始调用 GetMapping 输出缓冲区开头的映射。 对 GetMapping 的每个连续调用都显示缓冲区中的下一个顺序映射。 到达缓冲区末尾后,下一个 GetMapping 调用将输出缓冲区开头的映射,映射序列将重复。

映射的内核模式虚拟内存地址通过 VirtualAddress 参数输出。 微型端口驱动程序使用此地址在直接程序控制下访问映射。 包含映射的页面已锁定,当驱动程序访问映射时,不会发生任何页面错误。 音频设备的总线主 DMA 控制器使用通过 PhysicalAddress 参数输出的地址来访问映射。

Tag 参数是调用方选择唯一标识映射的 PVOID 值:

  • 端口驱动程序可能使用此标记在后续调用 IMiniportWavePciStream::RevokeMappings中标识映射。
  • 微型端口驱动程序可以使用此标记来标识对 IPortWavePciStream::ReleaseMapping的后续调用中的映射。
尽管 标记 定义为 PVOID 类型,但端口驱动程序从未尝试将此值用作指针,并且不需要它是有效的指针。

典型的 WavePci 微型端口驱动程序维护它接收的每个映射的记录。 标记可能是指向记录的指针或记录数组中的索引,例如,具体取决于实现。 标记的唯一要求是,它是可强制转换为 PVOID 类型的值。

标志 参数指示调用 GetMapping 是否检索了附加到当前映射 IRP 的音频数据缓冲区部分的最终映射。 当 标志 指示映射是 IRP 中的最后一个映射时,微型端口驱动程序可以武装硬件中断,以在微型端口驱动程序完成播放该映射时触发。 中断触发时,此事件通知微型端口驱动程序需要获取更多映射以添加到其 DMA 队列。 标志 参数通常由微型端口驱动程序使用,该驱动程序管理 KMixer 系统驱动程序中的单个播放流。 KMixer 使用多个映射 IRP(当前 KMixer 实现中的至少三个)来缓冲单个播放流。 因此,如果微型端口驱动程序在每次 DMA 控制器完成 IRP 中的最终映射时生成硬件中断,则中断应频繁发生,以使 DMA 队列不受饥饿。

标志 参数通常被管理一个或多个 DirectSound 硬件加速流的微型端口驱动程序忽略(请参阅 WDM 音频 中的 directSound 硬件加速)。 对于 DirectSound 缓冲区,可将整个缓冲区附加到单个 IRP。 如果缓冲区很大,微型端口驱动程序仅在硬件中断到达缓冲区的末尾时计划硬件中断,则中断将相距甚远,DMA 队列可能会耗尽。 此外,如果驱动程序管理大量流,则每次 标志 参数时,计划硬件中断可能会生成这么多中断,从而降低性能。 在这些情况下,微型端口驱动程序不应依赖于硬件中断来获取映射。 相反,它应将计时器 DPC 安排为定期进行以获取映射。

微型端口驱动程序最有可能在调用微型端口流对象的 SetStateServiceMappingAvailable 方法期间调用 GetMapping(请参阅 IMiniportWavePciStream)。

为了避免潜在的死锁,适配器驱动程序必须避免在调用 GetMapping时按住旋转锁。 有关使用旋转锁序列化对多处理器系统中共享数据结构和外围设备的访问的代码示例,请参阅 Microsoft Windows 驱动程序工具包(WDK)中的 ac97 示例音频驱动程序。 示例代码在调用 GetMapping 之前调用 KeReleaseSpinLock,并在调用 GetMapping后调用 KeAcquireSpinLock。 在调用释放和获取旋转锁之间,驱动程序线程不得假定它对旋转锁保护的数据或外围设备具有独占访问权限。 驱动程序验证程序 工具在调用 GetMapping期间检查活动旋转锁;如果检测到一个,则会生成0xC4(死锁检测)bug 检查。

尽管典型映射的大小是一个内存页或更少,但如果音频缓冲区的一部分占用物理内存中的两个或多个连续页面,单个映射可能会超过页面大小。 较大的映射可能会给 DMA 硬件造成问题,设计缺陷会限制块大小。 例如,如果 DMA 控制器可以处理单个页面的最大块大小,并且 GetMapping 输出大于页面的映射,微型端口驱动程序必须将映射拆分为 DMA 硬件可以处理的较小块。 如果生成的块数超过 DMA 硬件中的可用映射寄存器数,驱动程序无法在单个散点/收集 DMA作中排队所有块。 发生这种情况时,驱动程序必须跟踪映射的未排队部分,并在以后其他映射寄存器可用时启动剩余块的 DMA 传输。

在 Windows 98/Me、Windows 2000、Windows XP 和 Windows Server 2003 中,GetMapping 方法永远不会输出跨越 16 个以上的页面的映射。 此限制可能会在将来的 Windows 版本中更改。

有关映射的详细信息,请参阅 WavePci 延迟

要求

要求 价值
目标平台 普遍
标头 portcls.h (包括 Portcls.h)
IRQL <=DISPATCH_LEVEL

另请参阅

IMiniportWavePciStream::GetAllocatorFraming

IMiniportWavePciStream::MappingAvailable

IMiniportWavePciStream::RevokeMappings

IPortWavePciStream

IPortWavePciStream::ReleaseMapping

KeAcquireSpinLock

KeReleaseSpinLock