中断处理 - IoConnectInterrupt和中断处理例程

由于PCI设备的多样化,而系统的中断数量是有限的。所以采用多个设备共用一个中断号。在获取到中断后,操作系统会询问这条中断线上的所以设备。设备通过查询中断寄存器就可以知道是不是自己的中断,如果不是则在中断处理例程中返回FALSE,如果是则处理并返回TRUE。
在操作系统收到IRP_MN_START_DEVICE请求时,PDO会获取到中断相关的资源。参考例子如下:

NTSTATUS GetPciResource(IN PDEVICE_EXTENSION pExtension, IN PCM_PARTIAL_RESOURCE_LIST list)
{
    PDEVICE_OBJECT fdo = pExtension->fdo;

    KINTERRUPT_MODE  mode;
    BOOLEAN          irqshare;
    BOOLEAN          gotinterrupt = FALSE;

    PCM_PARTIAL_RESOURCE_DESCRIPTOR resource = &list->PartialDescriptors[0];
    ULONG nres = list->Count;
    for (ULONG i = 0; i < nres; ++i, ++resource)
    {                       // for each resource
        switch (resource->Type)
        {                   // switch on resource type
        case CmResourceTypeInterrupt:
        {
            KdPrint(("resource->Type = CmResourceTypeInterrupt\n"));
            pExtension->Irql = (KIRQL)resource->u.Interrupt.Level;
            pExtension->Vector = resource->u.Interrupt.Vector;
            pExtension->Affinity = resource->u.Interrupt.Affinity;
            mode = (resource->Flags == CM_RESOURCE_INTERRUPT_LATCHED) ? Latched : LevelSensitive;
            irqshare = (resource->ShareDisposition == CmResourceShareShared);
            gotinterrupt = TRUE;
        }break;
        default:
            KdPrint(("Unexpected I/O resource type %d\n", resource->Type));
            break;
        }                   // switch on resource type
    }                       // for each resource

    return STATUS_SUCCESS;
}

获取到中断资源后,驱动程序可以使用IoConnectInterrupt将中断与中断处理函数挂接。IoConnectInterrupt的原型如下:

NTSTATUS IoConnectInterrupt(
  _Out_    PKINTERRUPT       *InterruptObject,  //输出一个INTERRUPT结构的中断对象
  _In_     PKSERVICE_ROUTINE ServiceRoutine,    //中断处理例程
  _In_opt_ PVOID             ServiceContext,    //中断处理例程的参数
  _In_opt_ PKSPIN_LOCK       SpinLock,          //用于同步的自旋锁
  _In_     ULONG             Vector,            //中断向量号,在PDO获得
  _In_     KIRQL             Irql,              //中断优先级,在PDO获得
  _In_     KIRQL             SynchronizeIrql,   //同IRQL
  _In_     KINTERRUPT_MODE   InterruptMode,     //中断模式,Latched(电平触发),LevelSensitive (边沿触发)
  _In_     BOOLEAN           ShareVector,       //是否与其他设备共享中断向量,设为TRUE
  _In_     KAFFINITY         ProcessorEnableMask,//CPU屏蔽位,在PDO获得
  _In_     BOOLEAN           FloatingSave       //X86平台默认为FALSE
);
 NTSTATUS status = IoConnectInterrupt(&pExtension->pInterruptObject, (PKSERVICE_ROUTINE)OnInterrupt,
        (PVOID)pExtension, NULL, pExtension->Vector, pExtension->Irql, pExtension->Irql, LevelSensitive, TRUE, pExtension->Affinity, FALSE);
    if (!NT_SUCCESS(status))
    {
        KdPrint(("IoConnectInterrupt failed - %X\n", status));
        return status;
    }

中断处理例程原型如下:

KSERVICE_ROUTINE InterruptService;

BOOLEAN InterruptService(
  _In_ struct _KINTERRUPT *Interrupt,
  _In_ PVOID              ServiceContext
)
{ ... }

值得注意的是,如果不是自己设备产生的中断,一定要返回FALSE,如果是自己设备的中断,则必须清除掉中断。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值