Interruption

L'interruption sous NT ne gère pas les masques d'interruption, la sauvegarde du contexte, c'est le travail de Windows NT.

Ce n'est qu'un sous-programme irql appellé par NT qu'il faut installer. La fonction d'it doit faire le moins de travail possible. Elle différer le maximum de traitement sur la DPC une autre fonction.

NT fait s'exécuter d'abord toutes les fonctions d'IT, et lorsqu'il n'y a aucune fonction d'it, il exécute les DPC de chaque driver dans l'ordre FIFO des its d'origine

Si vous voulez gérer les conflits entre carte il vous faudra aussi déclarer les ressources utilisées

 

Installation d'it et DPC

Voici un exemple

void Install_IRQ10(void)
{

    int irq = 10;
    int vector = irq+8;
    KIRQL irql = irq;
    KAFFINITY Affinity;
    ULONG MappedVector;
    NTSTATUS ioConnectStatus;
#ifdef TRACE_IRQ
    DbgPrint("irq 10 installation\n");
#endif
    if( IRQ_used[IRQ10] == FALSE)
    {
    // récupérer le vecteur d'interruption
        MappedVector = HalGetInterruptVector(Isa, // Interface type
                0, // Bus number
                irq, // niveau IRQ 
                vector, // vecteur IRQ 
                &irql, // niveau IRQ NT 
                &Affinity // masque IRQ 
               );

    // enregistre la routine DPC 
        IoInitializeDpcRequest(DeviceObject,DpcRoutine);
    // connecte le driver à l'IRQ
        ioConnectStatus = IoConnectInterrupt(&InterruptObjectIrq10,
            InterruptServiceRoutineIrq10,
            DeviceObject,
            NULL,
            MappedVector,
            irql,
            irql,
            Latched,
            FALSE,
            Affinity,
            FALSE
            );
#ifdef TRACE_IRQ

DbgPrint("irql=%d\n",irql);
DbgPrint("affinity=%d\n",Affinity);
DbgPrint("mapped vecteur=%u\n",MappedVector);
#endif
if ( NT_SUCCESS (ioConnectStatus) )

    #ifdef TRACE_IRQ
    DbgPrint("irq 10 installee\n");
    #endif
    DbgPrint("irq 10 installee\n");

    IRQ_used[IRQ10] = TRUE;
    // IoDeleteDevice(deviceObjectIrq03);
    // ntStatus=ioConnectStatus;
}
else
{
#ifdef TRACE_IRQ    
    DbgPrint("irq 10 installation refusee\n");
#endif 
}
}
}


Fonction d'interruption

La fonction irql peut faire le travail si son opération est rapide sinon elle doit donner la main à la dpc

// routine d'interruption 
BOOLEAN InterruptServiceRoutineIrq10(IN PKINTERRUPT Interrupt,IN OUT PVOID Context)
{
PDEVICE_OBJECT DeviceObject;
PDEVICE_EXTENSION deviceExtension;

// DbgPrint("irq10\n");
DeviceObject = (struct _DEVICE_OBJECT *)Context;
deviceExtension = (device extension type *)DeviceObject->DeviceExtension;
// deviceExtension->IRQattente(10);
IoRequestDpc(DeviceObject, DeviceObject->CurrentIrp, NULL );
return TRUE;
}

DPC

La DPC récupère le contexte du driver (extension), éventuellement la requête en attente (irp)

En cas d'irp elle peut indiquer que le travail est terminé (iocompleterequest) rendant la main au programme appelant


// Routine DPC 
VOID DpcRoutine( IN PKDPC Dpc,IN PVOID DeferredContext,IN PVOID SystemArgument1,
IN PVOID SystemArgument2)
{
    PDEVICE_OBJECT DeviceObject;
    PDEVICE_EXTENSION extension;
    PIRP Irp;

    // DbgPrint("dpc\n");
    DeviceObject = (struct _DEVICE_OBJECT *)DeferredContext;
    Irp = DeviceObject->CurrentIrp;
    extension = (device extension type *)DeviceObject->DeviceExtension;
    // autre traitement plus long ....
    extension->IRQattente(10);

/* if (Irp) 
{ // renvoi l'IRP 
    Irp->IoStatus.Information = sizeof(UCHAR);
    Irp->IoStatus.Status = STATUS_SUCCESS;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
}*/
}

Desinstallation

void ResetIRQ10(void)
{
#ifdef TRACE_IRQ 
DbgPrint("irq 10 reset\n");
#endif

if (IRQ_used[IRQ10])
{
#ifdef TRACE_IRQ 
DbgPrint("irq 10 disconnected\n");
#endif
DbgPrint("irq 10 disconnected\n");
IoDisconnectInterrupt(InterruptObjectIrq10);
IRQ_used[IRQ10] = FALSE;
}
}

 

Accueil ] Remonter ] spinlock ] timer ]