阅读:11532回复:49
多种开发工具开发的9054驱动源程序比较
9054驱动程序设计
提纲: 1. 驱动程序设计概述。 a) 驱动程序设计概述。 b) 9054的编程基础。 2. 使用DRIVERSTUDIO设计9054驱动程序。 3. 使用DDK设计9054驱动程序。 4. 使用DRIVERWORKS设计。 在WINDOWS2000中,驱动程序分为三种:总线驱动程序(bus driver),功能驱动程序(function driver),以及过滤驱动程序(filter driver)。总线驱动,是指PCI总线的PDO驱动,由WINDOWS提供,不需要我们去设计。在工作过程中,总线驱动将扫描PCI插槽,并枚举它们,负责管理PCI总线的物理信号。我们所指的驱动程序设计,实质上是功能驱动程序(function driver)和过滤驱动程序(filter driver)。前者负责PCI设备的逻辑功能实现,后者是对驱动程序的某些功能进行扩展或复合,不在本篇中讨论。 9054驱动程序设计讨论的就是功能驱动程序,实际上,我们能得到的编程工具都是指向这个层次的(当然还可以编写过滤程序)。在这些工具中DDK是Microsoft提供的,是整个驱动程序开发的基础,DriverStudio就是建立在此基础之上的,因没用过DriverWork所以不知DW能否独立地编写驱动。有人说,DDK是驱程的汇编,而DS是驱程的C语音,那么DW,我理解就是驱程的VB了。比较过DDK和DS和DW,DW确实是最简单的,甚至它已经为PLX9054写了模板,还提供了实例,因为它是PLX的合作伙伴。但在DW里基本看不见DDK的影子。和DW比较,DS就复杂一些了,它的许多功能歧视是DDK例程的打包,它通过类的方法将DDK的功能包装在一起。要了解驱动程序的设计,最后还是要了解DDK的。 在学习驱动程序设计的初期时,我看的是《Windows2000 设备驱动程序设计指南》,它是一本DDK入门的好书。但在一开始,我竟不能读懂,可能是因为外国人的写书习惯和我们的不同,因为不懂,所以认为是本臭书。后来,我看了武安河的《WDM设备驱动程序开发》,这回看懂了,并跟着做了几个程序,于是对武佩服得五体投地,好书!但DS仍是将驱动包了起来,而且书中仍有许多的疑点,于是回头重看了《Windows2000 设备驱动程序设计指南》,此时,发现这本书写得极好,它将我的疑问基本都解决了,无怪乎,在网上许多网友极力推荐,好书和臭书的截然相反的评价,正是由于自己的认识水平所决定的。其后,又看了一本,也可称为WDM程序设计奠基之作的《Programming the Microsoft Windows Driver Model》,虽还没看完,但有了前两本的基础,已基本可以进行编程了。在《WDM设备驱动程序开发》中提供了PLX9054的样例,在《Programming the Microsoft Windows Driver Model》提供了S5933的样例。前者是用DS写的,而后者使用DDK。接下来,我将分析PLX9054地DS的驱动程序,并将S5933的DDK驱动,改成PLX9054,最后,附上DW的PLX9054驱动。 PLX9054作为PCI控制芯片,它对驱动程序设计影响的有以下几方面: 1. 双DMA通道,并支持S/C DMA方式,猝发方式。 2. 有三个地址空间:LocalBus地址空间,EEPROM地址空间,IO寄存器空间。 3. 通过对IO寄存器操作完成各项任务。 4. 可以对LocalBus进行寻址。 (陆续有来) |
|
沙发#
发布于:2009-01-08 13:00
东西很多,很好
|
|
板凳#
发布于:2008-12-16 10:34
搂主 ,你说的这两本书是相当的 难找 ,我在网上和中关村的 书店都跑遍 了 , 没有找到。手头上只有一本武安河的<WDM驱动程序开发2>,没有找到1,我在书店碰到过《windows 2000设备驱动 开发指南》下集,没有上集,确实是本极好的书,可惜都找不到,你能不能提供个卖书的地?
或者有没有电子版的阿 ? |
|
地板#
发布于:2008-07-13 17:07
感谢楼主,太好了
![]() |
|
地下室#
发布于:2008-07-09 16:50
谢谢!
|
|
5楼#
发布于:2008-05-08 14:24
thx a lot!!
![]() |
|
6楼#
发布于:2008-05-08 14:23
thx a lot!
![]() |
|
7楼#
发布于:2008-04-21 10:43
确实受益匪浅~~~~~~~~~
|
|
8楼#
发布于:2008-04-01 13:13
谢希大哥,收藏了~
|
|
9楼#
发布于:2008-03-21 17:30
楼主前辈,了解SFILTER吗 可以发个DDK的例子FILYSPY的剖析教程上来吗 小弟看得似懂非懂的,很需要一个前辈的指导啊,谢谢啊
|
|
10楼#
发布于:2007-07-25 12:38
谢谢谢谢
|
|
11楼#
发布于:2007-06-12 22:33
偶还没怎么入门,不过,帮助很大啊,谢谢了
|
|
12楼#
发布于:2007-03-07 17:49
找到原因了:在回调函数Ondmaready中参数Kirp I 没有返回数值,其为0。但不知道为什么出现这种错误。请问哪位高手知道,是否是版本的问题, 我用的版本是3.1。但用2.6版本生成的代码,在3.1版本编译后安装运行可以通过。没有重起的现象。Ondmaready函数中参数Kirp I 有数值
|
|
|
13楼#
发布于:2007-03-06 16:58
虽然不是很懂,但也得到了不少启发,谢谢了
|
|
14楼#
发布于:2007-03-06 16:58
虽然不是很懂,但也得到了不少启发,谢谢了
|
|
15楼#
发布于:2007-02-05 14:04
楼主和各位高手帮忙解决一下小弟的困难呀,很急
|
|
|
16楼#
发布于:2007-02-03 16:40
好贴呀。一个字:顶!
|
|
17楼#
发布于:2007-02-02 14:31
寻求大师高手帮助
在驱动程序中,我写了一个Dma传输的程序,并没有涉及任何的硬件操作,在serialread调用定回调函数,回调函数然后,触发OnDmaReady()函数调用, 但是在程序运行时,在 sofitice中出现如下的错误: Break Due to KeBufCheckEx(unhandle kernel mode exception) Error = A (IROQL_NOT_Less_or_EQAOL) P1=60 D2=2 P3=0 P4=F47A0EC0 然后机器自动重新启动了。当屏蔽掉OnDmaReady()中的(ULONG) pXfer->BytesRemaining() == I.ReadSize()这段代码时 程序就不会出现任何的错误。我实在是弄不清这是什么的原因,请大家帮我检查一下我的程序错在那里? 后来发现VOIDOnDmaReady(KDmaTransfer *pXfer, KIrp I)中没有传递参数KIrp I,请问怎样修改 代码如下,版本为DS3.1 VOID P5064Device::OnDmaReady(KDmaTransfer *pXfer, KIrp I) { // All KDmaTransfer callbacks must first check to see if there are any bytes // left to transfer. //DMA 结束处理 t << "start ondmaready" << EOL; t << "IRP:" << I << EOL; if (pXfer->BytesRemaining() == 0) { // If there are no bytes left to transfer, the callback must call // Terminate(). Then it completes the IRP with STATUS_SUCCESS. pXfer->Terminate(); I.Information() = I.ReadSize(CURRENT); I.Status() = STATUS_SUCCESS; PnpNextIrp(I); m_CurrentTransfer = NULL; delete pXfer; return; } // We must get the descriptor for the physical memory location for // the DMA transfer. PTRANSFER_DESCRIPTOR ptd; //DMA 处理 while (pXfer->SequenceTransferDescriptors(&ptd)) { // program the h/w using ppTD t << " Physical address 0x" << ptd->td_PhysAddr.LowPart << ". Length is 0x" << ptd->td_Length << "." << EOL; } // If this is the first time through, then start the DMA going. // We only want to do this ONCE for a given Read transfer. That // way, our data will be collected smoothly, without interruptions // or dropouts. //DMA 开始 -》进入startDMA进行配置和启动DMA if ((ULONG) pXfer-BytesRemaining() == I.ReadSize()) { t << "GOTO StartDMA " << EOL; }> // StartDMA(ptd->td_PhysAddr.LowPart,ptd->td_Length,(I.MajorFunction() == IRP_MJ_READ) ? FromDeviceToMemory : FromMemoryToDevice); } void P5064Device::SerialRead(KIrp I) { t << "Entering SerialRead, " << I << EOL; NTSTATUS status = STATUS_SUCCESS; // KMemory Mem(m_Buffer.Mdl()); // m_IoPortRange1.outd(INTCSR,0x40000);//DMA通道0中断 // Create a new DMA transfer object for this IRP m_CurrentTransfer = new(NonPagedPool) KDmaTransfer(this, &m_Dma); RtlZeroMemory(m_Buffer.VirtualAddress(), MAX_DMA_LENGTH); if ( m_CurrentTransfer == NULL ) { status = STATUS_INSUFFICIENT_RESOURCES; //DbgPrint("BMDmaTstDevice: unable to allocate transfer object: %x\n", status); t <<"unable to allocate transfer object" <<EOL; I.Information() = 0; I.Status() = status; NextIrp(I); } status = m_CurrentTransfer->Initiate( this, &m_Dma, I.Mdl(), (I.MajorFunction() == IRP_MJ_READ) ? FromDeviceToMemory : FromMemoryToDevice, LinkTo(OnDmaReady), &m_Buffer ); // If the transfer cannot be initiated, complete it with an error status. if ( ! NT_SUCCESS(status) ) { t<<" unable to initiate transfer"<<EOL; delete m_CurrentTransfer; m_CurrentTransfer = NULL; I.Information() = 0; I.Status() = status; NextIrp(I); } } 谢谢众位大师指点帮忙 |
|
|
18楼#
发布于:2007-02-02 14:29
在驱动程序中,我写了一个Dma传输的程序,并没有涉及任何的硬件操作,在serialread调用定回调函数,回调函数然后,触发OnDmaReady()函数调用,
但是在程序运行时,在 sofitice中出现如下的错误: Break Due to KeBufCheckEx(unhandle kernel mode exception) Error = A (IROQL_NOT_Less_or_EQAOL) P1=60 D2=2 P3=0 P4=F47A0EC0 然后机器自动重新启动了。当屏蔽掉OnDmaReady()中的(ULONG) pXfer->BytesRemaining() == I.ReadSize()这段代码时 程序就不会出现任何的错误。我实在是弄不清这是什么的原因,请大家帮我检查一下我的程序错在那里? 后来发现VOIDOnDmaReady(KDmaTransfer *pXfer, KIrp I)中没有传递参数KIrp I,请问怎样修改 代码如下,版本为DS3.1 VOID P5064Device::OnDmaReady(KDmaTransfer *pXfer, KIrp I) { // All KDmaTransfer callbacks must first check to see if there are any bytes // left to transfer. //DMA 结束处理 t << "start ondmaready" << EOL; t << "IRP:" << I << EOL; if (pXfer->BytesRemaining() == 0) { // If there are no bytes left to transfer, the callback must call // Terminate(). Then it completes the IRP with STATUS_SUCCESS. pXfer->Terminate(); I.Information() = I.ReadSize(CURRENT); I.Status() = STATUS_SUCCESS; PnpNextIrp(I); m_CurrentTransfer = NULL; delete pXfer; return; } // We must get the descriptor for the physical memory location for // the DMA transfer. PTRANSFER_DESCRIPTOR ptd; //DMA 处理 while (pXfer->SequenceTransferDescriptors(&ptd)) { // program the h/w using ppTD t << " Physical address 0x" << ptd->td_PhysAddr.LowPart << ". Length is 0x" << ptd->td_Length << "." << EOL; } // If this is the first time through, then start the DMA going. // We only want to do this ONCE for a given Read transfer. That // way, our data will be collected smoothly, without interruptions // or dropouts. //DMA 开始 -》进入startDMA进行配置和启动DMA if ((ULONG) pXfer-BytesRemaining() == I.ReadSize()) { t << "GOTO StartDMA " << EOL; }> // StartDMA(ptd->td_PhysAddr.LowPart,ptd->td_Length,(I.MajorFunction() == IRP_MJ_READ) ? FromDeviceToMemory : FromMemoryToDevice); } void P5064Device::SerialRead(KIrp I) { t << "Entering SerialRead, " << I << EOL; NTSTATUS status = STATUS_SUCCESS; // KMemory Mem(m_Buffer.Mdl()); // m_IoPortRange1.outd(INTCSR,0x40000);//DMA通道0中断 // Create a new DMA transfer object for this IRP m_CurrentTransfer = new(NonPagedPool) KDmaTransfer(this, &m_Dma); RtlZeroMemory(m_Buffer.VirtualAddress(), MAX_DMA_LENGTH); if ( m_CurrentTransfer == NULL ) { status = STATUS_INSUFFICIENT_RESOURCES; //DbgPrint("BMDmaTstDevice: unable to allocate transfer object: %x\n", status); t <<"unable to allocate transfer object" <<EOL; I.Information() = 0; I.Status() = status; NextIrp(I); } status = m_CurrentTransfer->Initiate( this, &m_Dma, I.Mdl(), (I.MajorFunction() == IRP_MJ_READ) ? FromDeviceToMemory : FromMemoryToDevice, LinkTo(OnDmaReady), &m_Buffer ); // If the transfer cannot be initiated, complete it with an error status. if ( ! NT_SUCCESS(status) ) { t<<" unable to initiate transfer"<<EOL; delete m_CurrentTransfer; m_CurrentTransfer = NULL; I.Information() = 0; I.Status() = status; NextIrp(I); } } 谢谢众位大师指点帮忙 |
|
|
19楼#
发布于:2005-07-07 20:07
下面是引用imagewxg于2004-12-09 19:37发表的: 我也觉的楼主在这一点上是不是不小心给弄错了。 不过从楼主那里还是可以学到很多东东,谢了!!!! |
|
|
上一页
下一页