• 中断处理


    首先在获得PCI配置空间资源的时候,就要获得中断资源,根据CM_PARTIAL_RESOURCE_DESCRIPTOR 结构的 Type 域来区分需要获得什么样的中断资源的时候,如果Type类型为:CmResourceTypeInterrupt,此时需要将中断资源从CM_PARTIAL_RESOURCE_DESCRIPTOR中取出:

    irql = (KIRQL) resource->u.Interrupt.Level;              //中断级别

                                vector = resource->u.Interrupt.Vector;                     // 中断向量

                                affinity = resource->u.Interrupt.Affinity;

                                mode = (resource->Flags == CM_RESOURCE_INTERRUPT_LATCHED)

                                         ? Latched : LevelSensitive;

                                irqshare = resource->ShareDisposition == CmResourceShareShared;

                                gotinterrupt = TRUE;

    获取以上这些信心之后我们就可以注册中断,通过IoConnectInterrupt()函数来实现:

    函数定义如下:

    IoConnectInterrupt

    OUT PKINTERRUPT *InterruptObject,//指向驱动程序提供的中断对象存储地址,该参数随后

    //要传递给KeSynchronizeExecution。

    OUT PKSERVICE_ROUTINE ServiceRoutine,//中断服务例程的入口

    IN PVOID ServiceContext,//指向驱动指定的即将传递给ISR的参数,ServiceContext必须在

    //常驻内存中,可以是驱动程序创建的设备驱动的设备扩展,也可

    //以是驱动创建的控制对象的控制拓展,还可以是设备驱动分配的

    //非分页内存。

    IN PKSPIN_LOCK SpinLock OPTIONAL,//指向已经初始化的自旋所,驱动程序负责自旋所的存

    //储,并且该自旋所将用来同步被驱动程序其它例程共

    //享的数据的访问,该参数在ISR处理多个中断向量或

    //者驱动程序包含不止一个ISR时需要设置,否则,驱

    //动程序不需要为中断自旋所分配存储空间,参数设置

    //为NULL。

    IN ULONG Vector,                //输入获取的中断向量

    IN KIRQL Irql,                    //输入获取的中断优先级DIRQL

    IN KIRQL SynchronizeIrql,         //指明ISR执行所在的DIRQL,当ISR需要处理多个中断

    //向量或者驱动程序有多个ISR的时候,该值选择全部中

    //断资源的u.Interrupt.Level中的最高值,否则和上面的

    //Irql变量相等。

    IN KINTERRUPT_MODE InterruptMode,//电平触发或者边沿触发

    IN BOOLEAN ShareVector,           //指明中断向量是否是可共享的。

    IN KAFFINITY ProcessorEnableMask,//指定一个KAFFINITY值,用来说明设备中断可以在什

    //么样的处理器平台上发生。

    IN BOOLEAN FloatingSave          //指明是否需要保存设备中断时的浮点堆栈,在X86平

    //台下,该值必须是FALSE。

    );

    实际使用时:

    status = IoConnectInterrupt(&pdx->InterruptObject, (PKSERVICE_ROUTINE) ISRInterrupt,

                       (PVOID) pdx, NULL, vector, irql, irql, mode, irqshare, affinity, FALSE);

    第二个参数为我们自定义的中断服务例程,当驱动通过这个函数接收中断,之后调用相应的DPC(deferred procedure calls,延迟过程调用)处理函数,DPC的使用主要是为了提高处理效率。但是首先要注册DPC处理函数,通过:

    VOID KeInitializeDpc(

      __out     PRKDPC Dpc,

      __in      PKDEFERRED_ROUTINE DeferredRoutine,

      __in_opt  PVOID DeferredContext

    );

    来实现注册DPC处理函数。

    实际应用:

    KeInitializeDpc(&pdx->fdo->Dpc,DPCForISR,NULL);

    BOOLEAN ISRInterrupt(PKINTERRUPT InterruptObject, PDEVICE_EXTENSION pdx)

    {                                                               

             //中断响应,通知硬件该中断已经处理,不用再发该中断

             WRITE_REGISTER_ULONG((PULONG) &pdx->pHBARegs->IntrMask,0x00000001);

             pdx->inthw_cnt++;

             KeInsertQueueDpc(&pdx->fdo->Dpc,pdx->fdo,pdx->fdo->CurrentIrp );

             return TRUE;

    }

    在该函数中,将中断请求插入到中断处理队列中,交由DPC来处理

    BOOLEAN KeInsertQueueDpc(

      __inout   PRKDPC Dpc,

      __in_opt  PVOID SystemArgument1,

      __in_opt  PVOID SystemArgument2

    );

    DPC的标准格式为:

    KDEFERRED_ROUTINE CustomDpc;

    VOID CustomDpc(

      __in      struct _KDPC *Dpc,

      __in_opt  PVOID DeferredContext,

      __in_opt  PVOID SystemArgument1,

      __in_opt  PVOID SystemArgument2

    )

    { ... }

    其中参数(注意来源):

    Dpc [in]

    Caller-supplied pointer to a KDPC structure, which represents the DPC object that is associated with this CustomDpc routine.

    DeferredContext [in, optional]

    Caller-supplied pointer to driver-defined context information that was specified in a previous call to KeInitializeDpc.

    SystemArgument1 [in, optional]

    Caller-supplied pointer to driver-supplied information that was specified in a previous call to KeInsertQueueDpc.

    SystemArgument2 [in, optional]

    Caller-supplied pointer to driver-supplied information that was specified in a previous call to KeInsertQueueDpc.

    这里DPC可以这样设计:

    VOID DPCForISR(IN PKDPC Dpc,IN PVOID Context,IN  PVOID fdo,IN PVOID pIrp)

    {

             PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)

    ((PDEVICE_OBJECT)fdo)->DeviceExtension;

            

             KeAcquireSpinLock(&pdx->spinLock,&pdx->oldIrql);

    //Int_stat 寄存器由硬件填写的

             int_status = READ_REGISTER_ULONG((PULONG) &pdx->pHBARegs->Int_stat);

             KdPrint(("interrupt!int status is 0x%0x\n",int_status));

             while(int_status) //循环处理中断,直到处理完

             {

                      

                       if(int_status >= INT_RECV_0 && int_status <= INT_RECV_23)

                       {

                                RecvTask(pdx,int_status-1);

                                pdx->recint_cnt[int_status-1]++;

                       }

                       if(int_status >= INT_LINK0_BUILD && int_status <= INT_LINK3_BUILD)

                       {

                                pdx->rx_fc_desc_buf_virt[int_status-25]->link_state=1;

                                pdx->bldint_cnt[int_status-25]++;

                                KdPrint(("Build!int status is 0x%0x\n",int_status));

                       }

                      

                       if(int_status >= INT_LINK0_BREAK && int_status <= INT_LINK3_BREAK)

                       {

                                pdx->rx_fc_desc_buf_virt[int_status-29]->link_state=0;

                                pdx->brkint_cnt[int_status-29]++;

                       }

                       pdx->intsw_cnt++;

                       int_status = READ_REGISTER_ULONG((PULONG) &pdx->pHBARegs->Int_stat);

                       KdPrint(("interrupt!int status is 0x%0x\n",int_status));

             }

            

             return ;             

    }

    在DPC中完成具体的操作,这样中断处理就结束了。

    make it simple, make it happen
  • 相关阅读:
    shell脚本杀掉指定进程下所有子进程(包括子进程的子进程)
    XDebug调试
    PHP基础入门
    猴子补丁(Monkey Patching)
    编写python高质量python代码的59个有效方法
    ubuntu中不能使用终端的情况
    一些个人有用的网站
    Ubuntu将自带的python3升级
    [Vue warn]: You may have an infinite update loop in a component render function.
    OO第四单元总结&期末总结
  • 原文地址:https://www.cnblogs.com/zhuyp1015/p/2396630.html
Copyright © 2020-2023  润新知