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

注解

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

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

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

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

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

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

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

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

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

管理一个或多个 DirectSound 硬件加速流的微型端口驱动程序通常忽略 Flags 参数, (请参阅 WDM 音频) 中的 DirectSound 硬件加速 。 对于 DirectSound 缓冲区,可将整个缓冲区附加到单个 IRP。 如果缓冲区较大,并且微型端口驱动程序仅在到达缓冲区末尾时才计划硬件中断,则中断将相隔太远,以至于 DMA 队列可能会耗尽。 此外,如果驱动程序正在管理大量流,则每当 Flags 参数发出流上最终映射条件的信号时,计划硬件中断可能会生成过多的中断,从而可能降低性能。 在这些情况下,微型端口驱动程序不应依赖硬件中断来获取映射。 相反,它应计划计时器 DPC 定期发生,以获取映射。

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

若要避免潜在的死锁,适配器驱动程序必须在调用 GetMapping期间避免持有旋转锁。 有关使用旋转锁序列化对多处理器系统中共享数据结构和外围设备的访问的代码示例,请参阅 Microsoft Windows 驱动程序工具包 (WDK) 中的 ac97 示例音频驱动程序。 示例代码在调用 之前调用 KeReleaseSpinLock,并在调用 GetMappingGetMapping调用 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