中断处理

来源:互联网 发布:json数据转化成数组 编辑:程序博客网 时间:2024/06/06 06:31

由于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;}
  • 3

获取到中断资源后,驱动程序可以使用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);
  • 1
 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,如果是自己设备的中断,则必须清除掉中断。