中断处理

此部分内容参考《Windows驱动开发技术详解》第16章 16.6.2
首先在获得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可以这样设计:

VOID DPCForISR(IN PKDPC Dpc,IN PVOID Context,IN  PVOID fdo,IN PVOID pIrp)
{
    KdPrint(("DPCForISR"));
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值