阅读:1839回复:12
ds中的5933dma编程
我要使用5933进行不间断的数据输出(ds编程)。思路如下:
1。在设备对象类声明一个pmdl,使之指向连续内存作为缓冲区。声明一个事件作为与应用程序同步的手段。 2。应用程序通过deviceioctl得到驱动发给的缓冲区句柄。驱动把该句柄发给应用程序后把事件设为信号态。 3。应用程序一直循环,每次得到事件后向缓冲区中写入数据,事件取消,通过deviceioctl通知驱动开始输出数据。 4。驱动初始化dma,开始传送,初始化函数Initiate( KDevice* pDevice, KDmaAdapter* pAdapter, PMDL Memory, DMA_DIRECTION Dir, DMAREADY_CALLBACK Callback, KCommonDmaBuffer* pBuffer = NULL PVOID pContext = NULL, BOOLEAN BusMasterKeepAdapter = FALSE )中Memory参数用缓冲区指针。 5。dma的callback函数中,当BytesRemaining( )不为0时,用pXfer->GetTransferDescriptors的物理地址和长度设置5933的传送地址MRAR和传送长度MRTC,设置中断允许读完成后发生中断,开始5933读操作。当BytesRemaining( )为0时,设置同步事件。 6。isr的dpc中pXfer->Continue(UseTransferSize)。 问题是:设完中断后就马上产生中断,结果就让整个运行中止了。 大虾们帮我看一下我的dma设置有没有问题?特别是我这样使用缓冲区对不对。 如果想使用KCommonDmaBuffer对象,应该如何操作? Initiate(……)中BusMasterKeepAdapter 的含义是什么? 以上问题得到回答都给分。 |
|
最新喜欢:![]()
|
沙发#
发布于:2002-06-28 21:53
这个问题,我也不会,我先给你捧场。到时候会了,可要说说。
|
|
|
板凳#
发布于:2002-07-01 09:20
这个问题,我也不会,我先给你捧场。到时候会了,可要说说。 多谢捧场 |
|
|
地板#
发布于:2002-07-01 09:50
/******
如果想使用KCommonDmaBuffer对象,应该如何操作? **********/ 首先声明 KDmaAdapter m_DmaAdapter; KCommonDmaBuffer m_DmaSendBuffer; InitializeAdapter() { DEVICE_DESCRIPTION dd; // Set up the adapter description for the slaved device RtlZeroMemory(&dd, sizeof(DEVICE_DESCRIPTION)); dd.Version = DEVICE_DESCRIPTION_VERSION; dd.Master = TRUE; dd.ScatterGather = FALSE; dd.DemandMode = FALSE; dd.AutoInitialize = FALSE; dd.Dma32BitAddresses= TRUE; dd.IgnoreCount = FALSE; dd.BusNumber = m_Cfg.Bus(); dd.DmaChannel = 0; dd.InterfaceType = PCIBus; dd.DmaWidth = Width32Bits; dd.DmaSpeed = Compatible; dd.MaximumLength = 2^32; // 初始化适配器对象 m_DmaAdapter.Initialize(&dd); if ((PADAPTER_OBJECT)m_DmaAdapter == NULL) return STATUS_UNSUCCESSFUL; else return STATUS_SUCCESS; } InitializeDmaBuffer() { //分配1M字节空间给DMA0发送缓冲区 m_DmaSendBuffer.Initialize(&m_DmaAdapter, 1024*1024,FALSE); if (m_DmaSendBuffer.IsValid() != TRUE) return STATUS_UNSUCCESSFUL; return STATUS_SUCCESS; } 此时m_DmaSendBuffer中存放的就是虚拟地址(不确定,查看帮助)。 |
|
|
地下室#
发布于:2002-07-01 11:02
多谢,那么,dma传送初始化函数中的参数PMDL Memory必须是write 或read中传来的mdl,不能是自己创建的对不对?
|
|
|
5楼#
发布于:2002-07-01 11:27
多谢,那么,dma传送初始化函数中的参数PMDL Memory必须是write 或read中传来的mdl,不能是自己创建的对不对? MDL是操作系统创建的。应用层向驱动程序发送数据的时候,操作系统根据应用层分配的分页内存而创建的,无非是形容有几个页,每个页的地址 是多少。自己应该不能创建吧?! |
|
|
6楼#
发布于:2002-07-01 11:39
多谢,接分
有问题再请教 |
|
|
7楼#
发布于:2002-07-01 11:59
多谢,接分 给的分太多了。我都成第一名了, 真不好意思。 |
|
|
8楼#
发布于:2002-07-02 09:42
我想问一下:
在nt下 ,我定义了一个,kdmaadapter对象,一个*kdmatransfer对象。然后 m_Transfer=new(nonpagepool)kdmatransfer(this,&m_dmaread); 这里创造对象是成功的。 m_Transfer.Initiate(I.mdl(),fromdevicetomemory, linkto(ondmaready),null,false); 就是在这个地方老是出现页面访问错误:page fault(0e).就是初始化不了 m_Transfer. 这个地方的I.mdl(),他所指向的内存空间到底是在什么地方分配的(分页,非分页)? 这到底是怎么回事?难道是页面没对齐? |
|
|
9楼#
发布于:2002-07-02 09:43
仁兄,借宝地一问:
在nt下 ,我定义了一个,kdmaadapter对象,一个*kdmatransfer对象。然后 m_Transfer=new(nonpagepool)kdmatransfer(this,&m_dmaread); 这里创造对象是成功的。 m_Transfer.Initiate(I.mdl(),fromdevicetomemory, linkto(ondmaready),null,false); 就是在这个地方老是出现页面访问错误:page fault(0e).就是初始化不了 m_Transfer. 这个地方的I.mdl(),他所指向的内存空间到底是在什么地方分配的(分页,非分页)? 这到底是怎么回事?难道是页面没对齐? |
|
|
10楼#
发布于:2002-07-02 11:34
这个问题最好另起一帖问一下。
不过,我想知道你是在哪里进行初始化的。我的想法是应该在处理read IRP的函数中。此处的I就是该函数传过来的IRP。 |
|
|
11楼#
发布于:2002-07-03 21:41
我想问一下:
在nt下 ,我定义了一个,kdmaadapter对象,一个*kdmatransfer对象。然后 m_Transfer=new(nonpagepool)kdmatransfer(this,&m_dmaread); 这里创造对象是成功的。 m_Transfer.Initiate(I.mdl(),fromdevicetomemory, linkto(ondmaready),null,false); 就是在这个地方老是出现页面访问错误:page fault(0e).就是初始化不了 m_Transfer. 这个地方的I.mdl(),他所指向的内存空间到底是在什么地方分配的(分页,非分页)? 这到底是怎么回事?难道是页面没对齐? |
|
|
12楼#
发布于:2002-07-10 17:05
dma传送初始化函数中的参数PMDL Memory必须是write 或read中传来的mdl,不能是自己创建的对不对?
你说得很对,只是不一定是从write 或read中传来,凡是直接IO的方式都是可以的,DeviceIoControl也可以,而且通常是从DeviceIoControl传过来。 nt下 ,我定义了一个,kdmaadapter对象,一个*kdmatransfer对象? 完全没必要这样定义两个,一个kdmadapter对象占用不了多少内存,直接在设备的继承类的头文件中定义一个kdmaadapter的实例即可。 DS的DMA编程主要是用户定义的回调函数代码编写,DS是个分割传输,考虑的很周到,如果你有耐心连续对source中的Kdmaxfer.cpp看上6个小时,你就会能清它的逻辑,在回调函数编写时,它的传递参数KIrp I,你不要用,如果你想获得当前的Irp,参照Dpc_ForIsr即可 |
|