数据复制和缓存策略
WaveCyclic 微型端口驱动程序在 HD 音频控制器硬件访问的 DMA 缓冲区与用户模式音频应用程序访问的客户端缓冲区之间复制音频数据:
对于播放数据流,驱动程序会将数据从客户端缓冲区复制到 DMA 缓冲区。
对于捕获数据流,驱动程序会将数据从 DMA 缓冲区复制到客户端缓冲区。
对于播放和捕获流,驱动程序可以通过启用 DMA 缓冲区内存(缓存类型 MmCached)的缓存,并依靠 PCI 控制器的总线窥探机制来确保缓存一致性,从而实现出色的性能。 但是,某些 PCI Express 控制器实现不会窥探 HD 音频控制器的等时数据传输(如 Intel 的初始 PCI Express 芯片集)。
函数驱动程序无法检测 PCI 控制器硬件是否支持窥探 DMA 缓冲区传输或执行等时数据传输。 为了避免潜在的缓存一致性问题,驱动程序会通过将该内存的缓存类型指定为 MmWriteCombined 来禁用 DMA 缓冲区内存的缓存。 (MmNonCached 也适用,但可能不会表现良好。)如果编写基于示例函数驱动程序的自定义适配器驱动程序,则 WaveCyclic 微型端口驱动程序的行为应类似,除非可以验证 PCI 控制器是否确实支持窥探 DMA 缓冲区传输。
为支持不执行总线窥探的设备和系统,自定义函数驱动程序必须遵循以下规则:
对于播放流,将 DMA 缓冲区的缓存类型指定为 MmWriteCombined。 将客户端缓冲区中的数据块复制到 DMA 缓冲区后,调用 KeMemoryBarrier 函数以使该数据对 DMA 引擎可见。 KeMemoryBarrier 以高效的方式将复制的数据刷新到内存中,使处理器的数据缓存基本上不受干扰。
对于捕获流,将 DMA 缓冲区的缓存类型指定为 MmWriteCombined 或 MmNonCached。 此外,函数驱动程序应避免写入 DMA 缓冲区。 如果它必须对音频样本执行就地处理,则应首先将数据复制到别处。
函数驱动程序复制到 DMA 缓冲区或从 DMA 缓冲区复制的数据块不需要在写入合并缓冲区边界上开始或结束,并且其大小不需要是写入组合缓冲区大小的倍数(通常为 32 或 64 字节)。
对于使用 HDAUDIO_BUS_INTERFACE_BDL 版本的 DDI 的编解码器函数驱动程序,AllocateContiguousDmaBuffer 例程会执行 DMA 缓冲区内存的分配和映射。 该例程始终将缓冲区的缓存类型设置为 MmWriteCombined。
有关写入合并的详细信息,请参阅 Intel 网站上的 IA-32 Intel 体系结构软件开发人员手册。