调试driver studio V3.1中的hwcap例子,发现AVStream把每帧图像缓冲区分成若干大小为4K Byte的mapping items,每个mapping item描述一块连续物理内存,每块内存大小只有4KB。所有这些内存块的虚拟地址是可以连续串联起来的,物理地址是分散的。
根据DDK文档说明,在调用KsDeviceRegisterAdapterObject()注册DMA Adapter的时候可以通过MaxMappingByteCount 参数来指定每个
mapping item包含的连续地址物理内存块大小。
但是实际测试中通过修改MaxMappingByteCount 并不能改变mapping item中的字节数量,mapping item中始终是4K。
请教如何修改可以使得AVStream将帧缓冲区划分为较大的连续物理地址内存块?
--续---
今天尝试了使用common buffer模式,做如下修改:
1,将PIN的sm_Flags改为KSPIN_FLAG_DO_NOT_INITIATE_PROCESSING。
2,修改OnStart()中的DMA Adapter初始化,删除原来的m_DMA,改用IoGetDmaAdapter()来自己获取DMA Adapter,在输入的参数中:
a) DMA Desctiptor的ScatterGather改为FALSE。
b) MapRegisters初始值设为BYTES_TO_PAGES(0x100000),也就是说我想申请最大1MB内存。
3,DMA Adapter成功获得之后调用其提供的方法AllocateCommonBuffer()来申请大小为MapRegisters * PAGE_SIZE的内存。
但是实际测试结果不如我所期待。在第2步完成后,返回的MapRegisters是8,也就是说系统告诉我只能给我8个PAGE的内存。
我再另外创建一个非AVStream的WDM驱动,在其Device类的OnStartDevice()中做与上面完全一样的事情,结果是可以成功获取1MB内存的。事实上,我尝试分配更大的内存,一直到32MB都可以成功。
有没有人能告诉我,在AVStream中如何才能实现分配大尺寸的common buffer?
或者说,不一定能保证解决问题,但是有任何建议敬请指出。
实际上common buffer不需要占用多个MapRegister,因为common buffer是物理上连续的,因此只需要一个MapRegisters就可以完成物理地址到虚拟地址的转换。
以上是我的猜测,因为我在AVStream中申请8MB连续内存实际上已经成功,即使MapRegisters仍然最大只有8.
关于MapRegisters的机制我还需要深入了解。