dengyih
驱动牛犊
驱动牛犊
  • 注册日期2004-11-02
  • 最后登录2004-11-26
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
20楼#
发布于:2004-11-16 21:55
最后,我想在讲讲使用向导来生成驱动程序:
可以使用的向导有两种:
1. DriverWorks的PCI向导。
2. WinDriver的向导。
这两个都很好用,以下就这两个工具进行一些浅陋的说明。

一.DriverWorks的Wizard
在用DriverWorks生成PCI模板的初期,要求输入Vendor ID(对于9054,默认为0x10B5),DeviceID(9054默认为0x9054),SubsystemID(9054默认为0x9054),和RevisionID。这些信息都用于inf文件的生成,当查阅INF时,可以看见以下的键值:
%DeviceDesc% = MyPciTest_DDI, PCIVEN_10B5&DEV_9054&SUBSYS_00009054&REV_00
我们从中可以看到这些值在生成驱动的位置。
当将PCI卡插入插槽时,Pnp Manager会检查注册表,看有无与这个设备相应的记录。其实,VendorID,DeviceID,SubsystemID和RevisionID就是用于标识这个注册表的相应记录的。如果是已经安装INF和SYS,则系统会自己完成所以的任务,它的工作应该是AddDevice(此处我不敢肯定,希望高手指点)。若未安装此驱动时,会启动硬件向导,要求用户提供inf,由inf完成注册表的更新,并安装sys文件。
由DriverWorks的向导生成的PCI驱动,和《武》提供的9054驱动的框架是一样的。再加一些补充的硬件操作就可以完成一个驱动的编写了。但如果希望驱动能完成更复杂的特定工作,恐怕还需理解DDK的基本工作原理。

二.使用WinDriver的Wizard
通过阅读WinDriver的快速生成PCI驱动程序的帮助就可以在10分钟内做一个驱动。我在亲历过后,不得不佩服,大洋彼岸的同僚,他们可以将开发平台做得如此简便,实用,可谓一绝。我觉得,在驱动开发的初期,使用它,一定是很好的,可以很快地检查硬件的工作情况,并执行简单的调试任务。WinDriver的最大的特点是,即时生成程序,在用户模式下进行调试。光这两点,就值得我们好好学习的了。我在这里就将生成PCI驱动的8个步骤简译如下:
1. 插入PCI硬件。(这个硬件就是我们做的PCI卡。)
2. 打开Wizard。
3. 选择你的硬件(在Wizard的列表中,会出现所有安装在PC机上的硬件,如果我们把9054插入,那么它会显示出来)。
4. 生成INF文件
5. 探测硬件
a) Wizard会自动探测你硬件的硬件资源(I/O ranges, Memory ranges and Interrupt)
b) 如果不是PNP的,你可以手工进行定义。
6. 测试硬件
a) 在写你的驱动时,这个时很重要的,它可以保证你的硬件入你所愿地工作。
b) 读、写I/O Port, Memory space 和 你定义的寄存器。
c) “Listen”硬件的中断。
7. 生成Driver Code
8. 生成INF文件。

这种生成驱动的方法,很直观,而且更妙的是可以什么都不做,就可以检测硬件了,这些都要归功于WinDriver的底层驱动,这使得,通过WinDriver取得的驱动是不能独立运行的,必须要WinDriver的支持。但这点小瑕疵,并不影响我们去使用它。如果它不是太贵的话,真应该去买正版的,我想他们也需要“顶顶”的支持。



newluck
驱动牛犊
驱动牛犊
  • 注册日期2004-10-27
  • 最后登录2005-01-15
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
21楼#
发布于:2004-12-08 21:39
dengyih老哥:
你太强了!
我能问你一下continue()式传输什么的阿,看完了帮助很糊涂,
a segment of transfer 指的是什么阿?是一次DMA需要好几次才能传输完成吗?还是指的下一次传输的需要设置的东西?
我对continue()很迷茫?
假如我用ReadFile来读一次DMA,那么会执行到OnDmaReady,然后StartDMA,它是一个判断语句
if ((ULONG) pXfer->BytesRemaining() == I.ReadSize())
StartDMA(ptd->td_PhysAddr.LowPart,ptd->td_Length)
可是第一次没传完,再传会再次调用StartDMA(?),但是
pXfer->BytesRemaining() 不== I.ReadSize(),那还怎么办?是不是我的理解有错误?
pXfer->SequenceTransferDescriptors()传输一次DMA为什么要获得好几次TransferDescriptors?
请你给我强一下这个流程?
谢!!!!
imagewxg
驱动小牛
驱动小牛
  • 注册日期2003-05-22
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分221分
  • 威望23点
  • 贡献值0点
  • 好评度22点
  • 原创分0分
  • 专家分0分
22楼#
发布于: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了,不知我理解的对不对?

[编辑 -  12/9/04 by  imagewxg]
jetjay
驱动牛犊
驱动牛犊
  • 注册日期2005-03-04
  • 最后登录2005-06-02
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
23楼#
发布于:2005-03-17 16:13
好帖啊 !!!好佩服各位大虾
IceDeng
驱动牛犊
驱动牛犊
  • 注册日期2004-02-03
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分100分
  • 威望10点
  • 贡献值0点
  • 好评度10点
  • 原创分0分
  • 专家分0分
24楼#
发布于:2005-03-18 11:39
绝对好贴!!
bluesword
驱动牛犊
驱动牛犊
  • 注册日期2005-01-13
  • 最后登录2006-07-01
  • 粉丝0
  • 关注0
  • 积分3分
  • 威望1点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
25楼#
发布于:2005-03-31 09:45
好贴,支持
zmwk
驱动中牛
驱动中牛
  • 注册日期2001-05-15
  • 最后登录2009-04-05
  • 粉丝0
  • 关注0
  • 积分59分
  • 威望51点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
26楼#
发布于:2005-04-04 14:45
应该整理一下上传呀!
A strong man can save himself. A great man can save another.
jetjay
驱动牛犊
驱动牛犊
  • 注册日期2005-03-04
  • 最后登录2005-06-02
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
27楼#
发布于:2005-04-08 22:05
受益匪浅啊
eagelangel
驱动牛犊
驱动牛犊
  • 注册日期2005-04-13
  • 最后登录2005-06-29
  • 粉丝0
  • 关注0
  • 积分8分
  • 威望1点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
28楼#
发布于:2005-06-08 15:05
好贴!顶……
muyuguang
驱动牛犊
驱动牛犊
  • 注册日期2004-10-28
  • 最后登录2006-05-28
  • 粉丝0
  • 关注0
  • 积分4分
  • 威望1点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
29楼#
发布于:2005-07-07 20:06
下面是引用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了,不知我理解的对不对?

.......



我也觉的楼主在这一点上是不是不小心给弄错了。
 
不过从楼主那里还是可以学到很多东东,谢了!!!!
木鱼
muyuguang
驱动牛犊
驱动牛犊
  • 注册日期2004-10-28
  • 最后登录2006-05-28
  • 粉丝0
  • 关注0
  • 积分4分
  • 威望1点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
30楼#
发布于: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了,不知我理解的对不对?

.......



我也觉的楼主在这一点上是不是不小心给弄错了。
 
不过从楼主那里还是可以学到很多东东,谢了!!!!
木鱼
muyuguang
驱动牛犊
驱动牛犊
  • 注册日期2004-10-28
  • 最后登录2006-05-28
  • 粉丝0
  • 关注0
  • 积分4分
  • 威望1点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
31楼#
发布于: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了,不知我理解的对不对?

.......



我也觉的楼主在这一点上是不是不小心给弄错了。
 
不过从楼主那里还是可以学到很多东东,谢了!!!!
木鱼
ghfv18
驱动牛犊
驱动牛犊
  • 注册日期2003-05-02
  • 最后登录2010-01-31
  • 粉丝0
  • 关注0
  • 积分31分
  • 威望14点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
32楼#
发布于: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);
    }
}
谢谢众位大师指点帮忙
我很高兴加入我们的该论坛,我认为这样会增加我的知识构成和技能,同时也增加我为社会作出更多的奉献
ghfv18
驱动牛犊
驱动牛犊
  • 注册日期2003-05-02
  • 最后登录2010-01-31
  • 粉丝0
  • 关注0
  • 积分31分
  • 威望14点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
33楼#
发布于: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);
    }
}
谢谢众位大师指点帮忙
我很高兴加入我们的该论坛,我认为这样会增加我的知识构成和技能,同时也增加我为社会作出更多的奉献
imazy
驱动牛犊
驱动牛犊
  • 注册日期2006-11-18
  • 最后登录2010-01-01
  • 粉丝0
  • 关注0
  • 积分3分
  • 威望26点
  • 贡献值0点
  • 好评度22点
  • 原创分0分
  • 专家分0分
34楼#
发布于:2007-02-03 16:40
好贴呀。一个字:顶!
ghfv18
驱动牛犊
驱动牛犊
  • 注册日期2003-05-02
  • 最后登录2010-01-31
  • 粉丝0
  • 关注0
  • 积分31分
  • 威望14点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
35楼#
发布于:2007-02-05 14:04
楼主和各位高手帮忙解决一下小弟的困难呀,很急
我很高兴加入我们的该论坛,我认为这样会增加我的知识构成和技能,同时也增加我为社会作出更多的奉献
wzgodzhi
驱动牛犊
驱动牛犊
  • 注册日期2007-01-16
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分760分
  • 威望77点
  • 贡献值0点
  • 好评度76点
  • 原创分0分
  • 专家分0分
36楼#
发布于:2007-03-06 16:58
虽然不是很懂,但也得到了不少启发,谢谢了
wzgodzhi
驱动牛犊
驱动牛犊
  • 注册日期2007-01-16
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分760分
  • 威望77点
  • 贡献值0点
  • 好评度76点
  • 原创分0分
  • 专家分0分
37楼#
发布于:2007-03-06 16:58
虽然不是很懂,但也得到了不少启发,谢谢了
ghfv18
驱动牛犊
驱动牛犊
  • 注册日期2003-05-02
  • 最后登录2010-01-31
  • 粉丝0
  • 关注0
  • 积分31分
  • 威望14点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
38楼#
发布于:2007-03-07 17:49
找到原因了:在回调函数Ondmaready中参数Kirp I 没有返回数值,其为0。但不知道为什么出现这种错误。请问哪位高手知道,是否是版本的问题, 我用的版本是3.1。但用2.6版本生成的代码,在3.1版本编译后安装运行可以通过。没有重起的现象。Ondmaready函数中参数Kirp I 有数值
我很高兴加入我们的该论坛,我认为这样会增加我的知识构成和技能,同时也增加我为社会作出更多的奉献
oppstone
驱动牛犊
驱动牛犊
  • 注册日期2007-03-30
  • 最后登录2007-07-28
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望2点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
39楼#
发布于:2007-06-12 22:33
偶还没怎么入门,不过,帮助很大啊,谢谢了
游客

返回顶部