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;
}
}