Présentation du chemin des IIP d’attente/veille via une arborescence d’appareils
Au sein d’une pile d’appareils unique, le propriétaire de la stratégie d’alimentation envoie un IRP d’attente/veille et tous les pilotes gèrent l’IRP d’attente/veille, comme décrit dans Vue d’ensemble de l’opération d’attente/veille et détaillé dans Envoi d’un IRP d’attente/veille et réception d’un IRP d’attente/veille, respectivement.
Au sein d’une branche de l’arborescence d’appareils (qui comprend un devnode feuille et les devnodes de ses parents, grands-parents, etc.), les pilotes doivent coopérer pour s’assurer qu’un IRP d’attente/veille atteint un pilote capable d’activer tout le matériel nécessaire au réveil.
Sur les ordinateurs ACPI, ACPI est responsable de l’activation du registre d’événements de usage général (GPE) propre au système associé au signal de mise en éveil de chaque appareil feuille. Par conséquent, les pilotes doivent demander et transférer les IRP d’attente/éveil jusqu’à ce qu’un pilote de filtre ACPI (inséré dans la pile des appareils au démarrage) ou le pilote ACPI Windows sous-jacent, Acpi.sys. En réponse, ACPI active le registre, maintient l’IRP en attente jusqu’à l’arrivée du signal, puis termine l’IRP. Étant donné que l’ACPI peut répondre au signal de réveil, il n’envoie pas l’IRP à un pilote inférieur.
Les pilotes de filtre ACPI, comme le pilote ACPI sous-jacent lui-même, sont transparents pour les autres pilotes. Pour offrir une flexibilité maximale dans la conception matérielle, la position exacte d’un pilote de filtre ACPI dans n’importe quelle pile d’appareils est spécifique à l’appareil et au système. Lors de la conception d’un pilote, vous ne pouvez pas faire d’hypothèses sur la présence ou la position d’un filtre ACPI dans la pile des appareils.
N’oubliez pas que les pilotes qui énumèrent les enfants créent un PDO pour chaque appareil enfant et un FDO pour l’appareil parent. Le pilote fait donc office de pilote de bus pour un périphérique enfant et de pilote de fonction/propriétaire de stratégie pour un appareil parent. Par conséquent, chaque fois qu’un pilote de bus reçoit un IRP d’attente/veille pour un PDO enfant, il doit demander un autre IRP d’attente/veille pour son AOP parent.
La figure suivante montre un exemple de configuration dans lequel une telle situation se produit.
Dans l’exemple de configuration, le clavier et le modem sont des enfants du hub USB, qui est à son tour un enfant du contrôleur hôte USB, qui est énuméré par le bus PCI. L’illustration suivante montre les piles d’appareils pour le clavier dans l’exemple de configuration.
Comme le montre la figure précédente, lecture de bas en haut :
Le pilote WINDOWS ACPI, Acpi.sys, crée l’AOP pour PCI.
Le pilote PCI crée le FDO PCI et le contrôleur hôte USB PDO et possède la stratégie pour la pile de périphériques PCI.
Le pilote de contrôleur hôte USB (une paire de pilotes de port hôte/miniport) crée le FDO du contrôleur hôte USB et l’AOP hub USB. Il est propriétaire de la stratégie pour la pile de périphériques du contrôleur hôte USB. Notez que Acpi.sys crée également un filtre DO dans cette pile.
Le pilote du hub USB crée le FDO hub USB et l’AOP du clavier. Ce pilote est propriétaire de la stratégie d’alimentation pour la pile de périphériques hub USB.
Le pilote de fonction du clavier est la paire pilote/minidriver de classe USB HID. Ce pilote crée le FDO pour le clavier et possède sa stratégie d’alimentation. Étant donné que le clavier n’a pas d’appareils enfants, ce pilote ne crée aucun PDO.
Notez que chaque pile d’appareils peut inclure des DO de filtre facultatifs supplémentaires qui ne sont pas affichés.
Pour permettre à l’entrée au clavier de réveiller le système, le propriétaire de la stratégie du clavier demande une IRP_MN_WAIT_WAKE pour son AOP. Cette IRP définit une chaîne d’autres IRP d’attente/veille, comme illustré dans la figure suivante.
Lorsqu’un pilote de bus reçoit une IRP_MN_WAIT_WAKE ciblée sur un AOP qu’il a créé, il doit demander un autre IRP_MN_WAIT_WAKE pour la pile d’appareils pour laquelle il est propriétaire de la stratégie d’alimentation et créer un FDO.
Comme le montre la figure précédente :
Le pilote de clavier appelle PoRequestPowerIrp pour envoyer un IRP d’attente/veille (IRP1) à son PDO.
Le gestionnaire d’alimentation alloue l’IRP et l’envoie via le gestionnaire d’E/S en haut de la pile de l’appareil pour le clavier. Les pilotes définissent des routines IoCompletion et passent l’IRP vers le bas de la pile jusqu’à ce qu’il atteigne le PDO du clavier. Le pilote de hub USB, qui fait office de pilote de bus pour le clavier, maintient IRP1 en attente.
Étant donné que le pilote du hub USB ne peut pas réveiller le système lorsque le signal de réveil arrive, le pilote du hub USB doit appeler PoRequestPowerIrp pour demander un IRP d’attente/veille (IRP2) pour la pile de périphériques hub USB.
Le gestionnaire d’alimentation envoie cette IRP en haut de la pile de périphériques hub USB. Les pilotes de cette pile définissent des routines IoCompletion et passent l’IRP au pilote du contrôleur hôte USB (qui agit comme pilote de bus pour le hub USB). Le pilote du contrôleur hôte USB maintient IRP2 en attente jusqu’à ce que le clavier signale un événement de veille.
De même, le pilote du contrôleur hôte USB ne peut pas réveiller le système. Par conséquent, le pilote du contrôleur hôte USB appelle PoRequestPowerIrp pour envoyer un IRP d’attente/veille (IRP3) à la pile de périphériques du contrôleur hôte USB.
Le gestionnaire d’alimentation envoie cette IRP en haut de la pile de périphériques du contrôleur hôte USB, où les pilotes définissent les routines IoCompletion et passent l’IRP au pilote PCI (qui fait office de pilote de bus pour le hub USB). Le pilote PCI maintient IRP3 en attente jusqu’à ce que le clavier signale un événement de veille.
Le pilote PCI ne pouvant pas réveiller le système, le pilote PCI appelle PoRequestPowerIrp pour envoyer un IRP d’attente/veille (IRP4) à la pile de périphériques PCI. Son parent est le périphérique racine, pour lequel ACPI est le pilote de bus.
Le gestionnaire d’alimentation envoie l’IRP en haut de la pile de périphériques de bus PCI ; ses pilotes définissent des routines d’achèvement et passent l’IRP au pilote Windows ACPI, Acpi.sys.
Acpi.sys peut réveiller le système, de sorte qu’il n’envoie pas d’IRP d’attente/veille à un autre PDO. Acpi.sys maintient IRP4 en attente jusqu’à ce qu’un signal de veille arrive.
Lorsque le clavier affirme le signal de réveil, Acpi.sys l’intercepte. ACPI, toutefois, ne peut pas déterminer que le clavier a affirmé le signal, mais seulement que le signal est passé par l’appareil racine. Acpi.sys termine ensuite IRP4, et le gestionnaire d’E/S appelle les routines IoCompletion qui remontent la pile d’appareils PCI. Lorsque L’IRP4 est terminé et que toutes les routines IoCompletion ont été exécutées, la routine de rappel du pilote PCI est appelée. Dans sa routine de rappel, le pilote PCI détermine que le signal est passé par le contrôleur hôte USB. Le pilote PCI termine ensuite IRP3. La même séquence se produit via la pile du contrôleur hôte USB et la pile du hub USB, jusqu’à ce que le pilote du clavier reçoive IRP1. À ce stade, le pilote de clavier peut traiter l’événement de réveil, si nécessaire.
Chaque fois qu’un pilote envoie un IRP d’attente/veille à un PDO parent, il doit définir une routine Cancel pour sa propre IRP. La définition d’une routine d’annulation donne au pilote la possibilité d’annuler la nouvelle IRP si l’IRP qui l’a déclenchée est annulée. Dans l’exemple USB, si le pilote de clavier annule son IRP d’attente/veille (désactivant ainsi la mise en éveil du clavier), le hub USB, le contrôleur hôte USB et les pilotes PCI doivent annuler les IRP qu’ils ont envoyés à la suite de l’IRP du clavier. Pour plus d’informations, consultez Annuler les routines pour les irps d’attente/éveil.
Bien qu’un pilote parent puisse énumérer plusieurs enfants qui peuvent être activés pour l’attente/la veille, un seul IRP d’attente/veille peut être en attente pour un PDO. Dans ce cas, le pilote parent doit s’assurer qu’il maintient un IRP d’attente/veille en attente chaque fois que l’un de ses appareils est activé pour le réveil. Pour ce faire, le pilote incrémente un compteur interne chaque fois qu’il reçoit un IRP d’attente/veille. Chaque fois que le pilote termine un IRP d’attente/veille, il décrémente le nombre et, si la valeur résultante est différente de zéro, envoie un autre IRP d’attente/veille à sa pile d’appareils.
Par exemple, dans la configuration USB indiquée précédemment dans l’exemple de configuration USB , le hub USB énumère deux appareils, un clavier et un modem. Lorsque le pilote du hub USB reçoit un IRP d’attente/veille pour l’AOP du clavier, il incrémente le nombre d’IRP d’attente/veille avant de demander un IRP pour son propre PDO. Si le propriétaire de la stratégie du modem active ultérieurement la mise en éveil pour le modem, le pilote du hub USB met en attente la nouvelle IRP pour l’AOP du modem et incrémente son nombre de références d’attente/veille. Toutefois, étant donné que le PDO du hub USB ne peut pas avoir deux IRP d’attente/veille simultanément, le pilote du hub USB ne demande pas de nouvelle IRP d’attente/veille pour le PDO du hub USB.
Lorsqu’un signal de mise en éveil arrive à partir du clavier ou du modem, le pilote du hub USB détermine l’appareil signalé, termine l’IRP correspondant et décrémente son nombre de références. Étant donné que les deux appareils ont été activés pour la mise en éveil (et que son nombre de références est différent de zéro), il doit envoyer sa propre pile d’appareils une autre IRP d’attente/veille pour « réarmer » son propre PDO pour le réveil. (Il en va de même pour le contrôleur hôte USB et le pilote PCI.)
Toutefois, un conducteur ne s’envoie pas un IRP pour réactiver l’attente/veille sur le même appareil sur lequel un signal de réveil vient d’arriver. Seul le gestionnaire de stratégie d’alimentation de l’appareil peut le faire. La réactivation de l’attente/veille n’est pas automatique.