dengyih
驱动牛犊
驱动牛犊
  • 注册日期2004-11-02
  • 最后登录2004-11-26
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:11532回复:49

多种开发工具开发的9054驱动源程序比较

楼主#
更多 发布于:2004-11-08 10:23
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进行寻址。
(陆续有来)


jjfx6110
驱动牛犊
驱动牛犊
  • 注册日期2008-12-30
  • 最后登录2009-01-12
  • 粉丝0
  • 关注0
  • 积分4分
  • 威望41点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2009-01-08 13:00
东西很多,很好
zhuo811
驱动牛犊
驱动牛犊
  • 注册日期2008-02-13
  • 最后登录2010-06-21
  • 粉丝0
  • 关注0
  • 积分33分
  • 威望198点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2008-12-16 10:34
搂主 ,你说的这两本书是相当的 难找 ,我在网上和中关村的 书店都跑遍 了 , 没有找到。手头上只有一本武安河的<WDM驱动程序开发2>,没有找到1,我在书店碰到过《windows 2000设备驱动 开发指南》下集,没有上集,确实是本极好的书,可惜都找不到,你能不能提供个卖书的地?
或者有没有电子版的阿 ?
newcreater
驱动牛犊
驱动牛犊
  • 注册日期2008-06-11
  • 最后登录2018-08-08
  • 粉丝1
  • 关注0
  • 积分51分
  • 威望112点
  • 贡献值1点
  • 好评度0点
  • 原创分0分
  • 专家分0分
  • 社区居民
地板#
发布于:2008-07-13 17:07
感谢楼主,太好了
yejinweioo
驱动牛犊
驱动牛犊
  • 注册日期2008-03-19
  • 最后登录2010-01-06
  • 粉丝0
  • 关注0
  • 积分14分
  • 威望105点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2008-07-09 16:50
谢谢!
anchoret
驱动牛犊
驱动牛犊
  • 注册日期2005-12-23
  • 最后登录2013-08-13
  • 粉丝0
  • 关注0
  • 积分22分
  • 威望150点
  • 贡献值0点
  • 好评度16点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2008-05-08 14:24
thx a lot!!
anchoret
驱动牛犊
驱动牛犊
  • 注册日期2005-12-23
  • 最后登录2013-08-13
  • 粉丝0
  • 关注0
  • 积分22分
  • 威望150点
  • 贡献值0点
  • 好评度16点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2008-05-08 14:23
thx a lot!
chelalv
驱动牛犊
驱动牛犊
  • 注册日期2008-03-22
  • 最后登录2010-04-15
  • 粉丝1
  • 关注0
  • 积分22分
  • 威望146点
  • 贡献值0点
  • 好评度8点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2008-04-21 10:43
确实受益匪浅~~~~~~~~~
Linbrid
驱动牛犊
驱动牛犊
  • 注册日期2007-10-23
  • 最后登录2008-04-15
  • 粉丝0
  • 关注0
  • 积分60分
  • 威望7点
  • 贡献值0点
  • 好评度6点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2008-04-01 13:13
谢希大哥,收藏了~
dino200606
驱动牛犊
驱动牛犊
  • 注册日期2008-01-19
  • 最后登录2019-05-19
  • 粉丝3
  • 关注0
  • 积分10分
  • 威望98点
  • 贡献值0点
  • 好评度6点
  • 原创分0分
  • 专家分0分
  • 社区居民
9楼#
发布于:2008-03-21 17:30
楼主前辈,了解SFILTER吗 可以发个DDK的例子FILYSPY的剖析教程上来吗 小弟看得似懂非懂的,很需要一个前辈的指导啊,谢谢啊
suohaha
驱动牛犊
驱动牛犊
  • 注册日期2006-04-23
  • 最后登录2013-03-13
  • 粉丝0
  • 关注0
  • 积分70分
  • 威望8点
  • 贡献值0点
  • 好评度7点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2007-07-25 12:38
谢谢谢谢
oppstone
驱动牛犊
驱动牛犊
  • 注册日期2007-03-30
  • 最后登录2007-07-28
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望2点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2007-06-12 22:33
偶还没怎么入门,不过,帮助很大啊,谢谢了
ghfv18
驱动牛犊
驱动牛犊
  • 注册日期2003-05-02
  • 最后登录2010-01-31
  • 粉丝0
  • 关注0
  • 积分31分
  • 威望14点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2007-03-07 17:49
找到原因了:在回调函数Ondmaready中参数Kirp I 没有返回数值,其为0。但不知道为什么出现这种错误。请问哪位高手知道,是否是版本的问题, 我用的版本是3.1。但用2.6版本生成的代码,在3.1版本编译后安装运行可以通过。没有重起的现象。Ondmaready函数中参数Kirp I 有数值
我很高兴加入我们的该论坛,我认为这样会增加我的知识构成和技能,同时也增加我为社会作出更多的奉献
wzgodzhi
驱动牛犊
驱动牛犊
  • 注册日期2007-01-16
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分760分
  • 威望77点
  • 贡献值0点
  • 好评度76点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2007-03-06 16:58
虽然不是很懂,但也得到了不少启发,谢谢了
wzgodzhi
驱动牛犊
驱动牛犊
  • 注册日期2007-01-16
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分760分
  • 威望77点
  • 贡献值0点
  • 好评度76点
  • 原创分0分
  • 专家分0分
14楼#
发布于:2007-03-06 16:58
虽然不是很懂,但也得到了不少启发,谢谢了
ghfv18
驱动牛犊
驱动牛犊
  • 注册日期2003-05-02
  • 最后登录2010-01-31
  • 粉丝0
  • 关注0
  • 积分31分
  • 威望14点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
15楼#
发布于:2007-02-05 14:04
楼主和各位高手帮忙解决一下小弟的困难呀,很急
我很高兴加入我们的该论坛,我认为这样会增加我的知识构成和技能,同时也增加我为社会作出更多的奉献
imazy
驱动牛犊
驱动牛犊
  • 注册日期2006-11-18
  • 最后登录2010-01-01
  • 粉丝0
  • 关注0
  • 积分3分
  • 威望26点
  • 贡献值0点
  • 好评度22点
  • 原创分0分
  • 专家分0分
16楼#
发布于:2007-02-03 16:40
好贴呀。一个字:顶!
ghfv18
驱动牛犊
驱动牛犊
  • 注册日期2003-05-02
  • 最后登录2010-01-31
  • 粉丝0
  • 关注0
  • 积分31分
  • 威望14点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
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);
    }
}
谢谢众位大师指点帮忙
我很高兴加入我们的该论坛,我认为这样会增加我的知识构成和技能,同时也增加我为社会作出更多的奉献
ghfv18
驱动牛犊
驱动牛犊
  • 注册日期2003-05-02
  • 最后登录2010-01-31
  • 粉丝0
  • 关注0
  • 积分31分
  • 威望14点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
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);
    }
}
谢谢众位大师指点帮忙
我很高兴加入我们的该论坛,我认为这样会增加我的知识构成和技能,同时也增加我为社会作出更多的奉献
muyuguang
驱动牛犊
驱动牛犊
  • 注册日期2004-10-28
  • 最后登录2006-05-28
  • 粉丝0
  • 关注0
  • 积分4分
  • 威望1点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
19楼#
发布于:2005-07-07 20:07
下面是引用imagewxg于2004-12-09 19:37发表的:
在这些工具中DDK是Microsoft提供的,是整个驱动程序开发的基础,DriverStudio就是建立在此基础之上的,因没用过DriverWork所以不知DW能否独立地编写驱动。有人说,DDK是驱程的汇编,而DS是驱程的C语音,那么DW,我理解就是驱程的VB了。比较过DDK和DS和DW,DW确实是最简单的,甚至它已经为PLX9054写了模板,还提供了实例,因为它是PLX的合作伙伴。但在DW里基本看不见DDK的影子。和DW比较,DS就复杂一些了,它的许多功能歧视是DDK例程的打包,它通过类的方法将DDK的功能包装在一起。要了解驱动程序的设计,最后还是要了解DDK的。


不能理解:DriverStudio中编写WDM驱动程序的工具就是driverwork,所以DS和DW应该是一个冬冬才对,我觉得是不是将windriver错写成了driverwork了,不知我理解的对不对?

.......



我也觉的楼主在这一点上是不是不小心给弄错了。
 
不过从楼主那里还是可以学到很多东东,谢了!!!!
木鱼
上一页
游客

返回顶部