Partager via


Utilisation des routines de service d’interruption au niveau passif

À partir de Windows 8, un pilote peut utiliser la routine IoConnectInterruptEx pour enregistrer une routine InterruptService au niveau passif (ISR). Lorsque l’interruption associée se produit, le gestionnaire de trappes d’interruption du noyau planifie cette routine pour s’exécuter à IRQL = PASSIVE_LEVEL. Un ISR peut avoir besoin de fonctionner au niveau passif s’il peut accéder aux registres matériels d’un appareil uniquement via des requêtes d’E/S. Un ISR au niveau passif peut envoyer de manière synchrone une requête d’E/S à un appareil et bloquer jusqu’à ce que la requête soit terminée.

Enregistrement d’un ISR au niveau passif

Le paramètre d’entrée de IoConnectInterruptEx est un pointeur vers une structure IO_CONNECT_INTERRUPT_PARAMETERS. Pour enregistrer un ISR au niveau passif, définissez le membre Version de cette structure sur CONNECT_FULLY_SPECIFIED ou CONNECT_LINE_BASED. Si Version = CONNECT_FULLY_SPECIFIED, définissez le membre Irql sur PASSIVE_LEVEL, le membre SynchronizeIrql sur PASSIVE_LEVEL, et le membre SpinLock sur NULL. Si Version = CONNECT_LINE_BASED, définissez SynchronizeIrql = PASSIVE_LEVEL et SpinLock = NULL.

Si l’objet d’interruption spécifie un ISR au niveau passif, la routine KeSynchronizeExecution utilise un objet d’événement de synchronisation du noyau au lieu d’un verrou tournant pour synchroniser l’exécution de la routine SynchCritSection avec l’ISR.

Cet objet événement est alloué par la routine IoConnectInterruptEx dans l’appel qui enregistre l’ISR au niveau passif. L’appelant ne doit pas fournir de verrou tournant dans cet appel. (C’est-à-dire que l’appelant doit définir le membre SpinLock de la structure IO_CONNECT_INTERRUPT_PARAMETERS sur NULL si l’ISR doit fonctionner au niveau passif.) Sinon, IoConnectInterruptEx échoue et retourne le statut d’erreur STATUS_INVALID_PARAMETER.

Les routines KeAcquireInterruptSpinLock et KeReleaseInterruptSpinLock provoquent un arrêt du système si l’ISR pour l’objet d’interruption fourni fonctionne à IRQL = PASSIVE_LEVEL.

Appareils nécessitant une gestion d’interruption au niveau passif

Pour un appareil à mémoire mappée signalant une demande d’interruption déclenchée par niveau, l’ISR de l’appareil est généralement appelé à DIRQL depuis le gestionnaire de trappes d’interruption du noyau. L’ISR manipule les registres matériels de l’appareil pour désactiver l’interruption.

Cependant, un ISR peut avoir besoin de fonctionner à IRQL = PASSIVE_LEVEL si l’appareil associé signale une demande d’interruption déclenchée par niveau mais que les registres matériels de l’appareil ne peuvent pas être accédés directement depuis un ISR appelé à DIRQL depuis le gestionnaire de trappes d’interruption du noyau. Par exemple, les registres de l’appareil peuvent ne pas être mappés en mémoire, ou l’ISR peut être temporairement bloqué lors d’un accès au registre.

À partir de Windows 8, un pilote peut enregistrer un ISR au niveau passif. Lorsque l’interruption se produit, le gestionnaire de trappes d’interruption du noyau planifie l’ISR pour fonctionner à IRQL = PASSIVE_LEVEL. Avant que le gestionnaire ne retourne, il doit désactiver l’interruption dans le contrôleur d’interruption (ou contrôleur GPIO). Si un appareil signale une interruption déclenchée par bord, le gestionnaire efface l’interruption dans le contrôleur d’interruption. Si l’appareil signale une interruption déclenchée par niveau, le gestionnaire masque temporairement l’interruption dans le contrôleur d’interruption ; après que l’ISR s’exécute, le noyau démasque l’interruption.

Exemple

Un exemple d’appareil pouvant nécessiter un ISR au niveau passif est un appareil capteur connecté à un bus série à faible consommation, tel que I²C. À partir de Windows 8, la prise en charge de l’I²C et d’autres bus périphériques simples (SPBs) est fournie par l’extension de framework SPB (SpbCx).

Pour accéder aux registres de l’appareil capteur connecté à l’I²C, le pilote du capteur envoie une requête d’E/S à l’appareil capteur, qui est gérée conjointement par SpbCx et par le pilote du contrôleur du bus. Pour effectuer l’opération demandée, le contrôleur SPB doit transférer les données de manière sérielle sur le bus. Ce transfert est relativement lent et ne peut pas être effectué dans les contraintes de temps d’un ISR fonctionnant à DIRQL. Cependant, un ISR au niveau passif peut envoyer la requête d’E/S de manière synchrone et bloquer jusqu’à ce que la requête soit terminée.

L’ISR au niveau passif dans cet exemple peut être bloqué plus longtemps si le contrôleur du bus I²C est éteint lorsque l’ISR envoie la requête d’E/S à l’appareil interrompu. Dans ce cas, le contrôleur doit terminer la transition vers l’état de puissance D0 avant de pouvoir transférer les données sur le bus.

Contrairement à un bus tel que PCI, le bus I²C dans cet exemple ne fournit aucun moyen spécifique au bus pour transmettre des demandes d’interruption des appareils périphériques au processeur. Au lieu de cela, l’appareil capteur peut signaler une interruption à une broche d’un appareil contrôleur GPIO, qui relaie ensuite la demande d’interruption au processeur. Pour plus d’informations, consultez Interruptions GPIO.

En général, les registres matériels d’un contrôleur GPIO sont mappés en mémoire et peuvent être accédés à DIRQL par le gestionnaire de trappes d’interruption du noyau. Lorsque l’appareil capteur provoque une interruption, le gestionnaire doit désactiver l’interruption en manipulant les bits d’interruption dans les registres du contrôleur GPIO.

Pour une interruption déclenchée par niveau, le gestionnaire de trappes du noyau masque la demande d’interruption à la broche GPIO, puis planifie l’ISR de l’appareil capteur pour fonctionner au niveau passif. L’ISR doit effacer la demande d’interruption de l’appareil capteur. Après que l’ISR retourne, le noyau démasque la demande d’interruption à la broche GPIO.

Pour une interruption déclenchée par bord, le gestionnaire de trappes du noyau efface la demande d’interruption à la broche GPIO, puis planifie l’ISR de l’appareil capteur pour fonctionner au niveau passif.

Routines de travail

Dans l’appel à IoConnectInterruptEx, un pilote a la possibilité de diviser le traitement de l’interruption entre un ISR au niveau passif et une routine de travail. En règle générale, l’ISR doit effectuer le traitement initial de l’interruption (par exemple, désactiver une interruption déclenchée par niveau) et différer le traitement supplémentaire à la routine de travail. Bien que l’ISR et la routine de travail fonctionnent tous deux au niveau passif, l’ISR fonctionne à une priorité relativement élevée et peut retarder d’autres tâches prioritaires. Ces tâches peuvent inclure des ISR au niveau passif pour de nouvelles interruptions.

Dans de rares cas, une interruption peut nécessiter si peu de traitement que l’ISR au niveau passif peut effectuer tout le traitement de l’interruption, et aucune routine de travail n’est requise.

Pour des informations sur l’utilisation des ISR au niveau passif dans les pilotes KMDF, veuillez consulter la section Prise en charge des interruptions au niveau passif.