Partager via


Travailler avec la norme GUID_DEVICE_RESET_INTERFACE_STANDARD

L’interface GUID_DEVICE_RESET_INTERFACE_STANDARD définit un moyen standard pour les pilotes de fonction de tenter de réinitialiser et de récupérer un appareil défectueux.

Deux types de réinitialisations d’appareils sont disponibles via cette interface :

  • Réinitialisation au niveau fonctionnel de l’appareil. Dans ce cas, l’opération de réinitialisation est limitée à un appareil spécifique et n’est pas visible pour d’autres appareils. L’appareil reste connecté au bus tout au long de la réinitialisation et retourne à un état valide (état initial) après la réinitialisation. Ce type de réinitialisation a le moins d’impact sur le système.

  • Ce type de réinitialisation peut être implémenté par le pilote de bus ou par le microprogramme ACPI. Le pilote de bus peut implémenter une réinitialisation au niveau de la fonction si la spécification du bus définit un mécanisme de réinitialisation en bande qui répond à l’exigence. Le microprogramme ACPI peut éventuellement remplacer une réinitialisation au niveau de chaque fonction, telle que définie par le pilote de bus, par sa propre implémentation.

  • Réinitialisation de l’appareil au niveau de la plateforme. Dans ce cas, l’opération de réinitialisation entraîne le signalement de l’appareil comme manquant dans le bus. L’opération de réinitialisation affecte un appareil spécifique et tous les autres appareils connectés via le même rail d’alimentation ou la même ligne de réinitialisation. Ce type de réinitialisation a le plus d’impact sur le système. Le système d’exploitation démantèle et reconstruit les structures de données de tous les appareils affectés afin de garantir que tout redémarre depuis un état initial.

À compter de Windows 10, ces entrées de Registre sous la HKLM\SYSTEM\CurrentControlSet\Control\Pnp clé configurent l’opération de réinitialisation :

  • DeviceResetRetryInterval : période avant le démarrage de l’opération de réinitialisation. La valeur par défaut est de 3 secondes. La valeur minimale est de 100 millisecondes ; la valeur maximale est de 30 secondes.

  • DeviceResetMaximumRetries : nombre maximal de tentatives de réinitialisation de l'appareil.

Remarque

L’interface GUID_DEVICE_RESET_INTERFACE_STANDARD est disponible à partir de Windows 10.

Utilisation de l’interface de réinitialisation de l’appareil

Si un pilote de fonction détecte que l’appareil ne fonctionne pas correctement, il doit d’abord tenter une réinitialisation au niveau de la fonction. Si une réinitialisation au niveau de la fonction ne résout pas le problème, le pilote peut choisir de tenter une réinitialisation au niveau de la plateforme. Toutefois, une réinitialisation au niveau de la plateforme ne doit être utilisée que comme option finale.

Pour rechercher cette interface, un pilote de périphérique envoie une IRP_MN_QUERY_INTERFACE IRP vers le bas de la pile des pilotes. Pour cet IRP, le pilote définit le paramètre d’entrée InterfaceType sur GUID_DEVICE_RESET_INTERFACE_STANDARD. Lorsque l'IRP est terminé avec succès, le paramètre de sortie de l'interface est un pointeur vers une structure DEVICE_RESET_INTERFACE_STANDARD. Cette structure contient un pointeur vers la routine DeviceReset, qui peut être utilisée pour demander une réinitialisation au niveau de la fonction ou au niveau de la plateforme.

Prise en charge de l’interface de réinitialisation de périphérique dans les pilotes de fonction

Pour prendre en charge l’interface de réinitialisation de l’appareil, la pile d’appareils doit répondre aux exigences suivantes.

Le pilote de fonction doit gérer correctement IRP_MN_QUERY_REMOVE_DEVICE, IRP_MN_REMOVE_DEVICE et IRP_MN_SURPRISE_REMOVAL.

Dans la plupart des cas, lorsque le pilote reçoit IRP_MN_QUERY_REMOVE_DEVICE, il doit retourner une valeur de réussite afin que le périphérique puisse être retiré en toute sécurité. Toutefois, il peut arriver que l’appareil ne puisse pas être arrêté en toute sécurité, par exemple si l’appareil est bloqué dans une boucle écrivant dans une mémoire tampon. Dans ce cas, le pilote doit retourner STATUS_DEVICE_HUNG à IRP_MN_QUERY_REMOVE_DEVICE. Le gestionnaire PnP poursuit le processus IRP_MN_QUERY_REMOVE_DEVICE et IRP_MN_REMOVE_DEVICE, mais cette pile particulière ne recevra pas IRP_MN_REMOVE_DEVICE. Au lieu de cela, la pile d’appareils reçoit IRP_MN_SURPRISE_REMOVAL une fois l’appareil réinitialisé.

Pour plus d’informations sur ces IRPS, consultez :

Gestion d’une demande de IRP_MN_QUERY_REMOVE_DEVICE

Gestion d’une demande de IRP_MN_REMOVE_DEVICE

Gestion d’une demande de IRP_MN_SURPRISE_REMOVAL

Prise en charge de l’interface de réinitialisation de périphérique dans les drivers de filtre

Les pilotes de filtre peuvent intercepter les IRP_MN_QUERY_INTERFACE IRPs qui ont le type d'interface GUID_DEVICE_RESET_INTERFACE_STANDARD. Ainsi, ils peuvent continuer à déléguer à l’interface GUID_DEVICE_RESET_INTERFACE_STANDARD, mais effectuer des opérations spécifiques à l’appareil avant ou après l’opération de réinitialisation. Ils peuvent également remplacer l’interface de GUID_DEVICE_RESET_INTERFACE_STANDARD retournée par le pilote de bus avec sa propre interface afin de fournir son propre opération de réinitialisation.

Prise en charge de l’interface de réinitialisation de périphérique dans les pilotes bus

Les pilotes de bus qui participent au processus de réinitialisation de l’appareil (autrement dit, les pilotes bus associés à l’appareil qui demandent la réinitialisation et les pilotes bus associés aux appareils qui répondent à la demande de réinitialisation) doivent répondre à l’une des exigences suivantes :

  • Soyez capable de brancher à chaud. Le pilote de bus doit être en mesure de détecter un appareil supprimé du bus sans préavis et un appareil connecté au bus.

  • Sinon, il doit implémenter l’interface GUID_REENUMERATE_SELF_INTERFACE_STANDARD. Cela simule l’extraction d’un appareil depuis un bus et son rebranchement. Les pilotes de bus intégrés (tels que PCI et SDBUS) prennent en charge cette interface. Par conséquent, si l'appareil à être réinitialisé utilise l'un de ces bus, aucune modification du pilote de bus ne sera requise.

Pour les pilotes de bus basés sur WDF, le cadre WDF inscrit l’interface GUID_REENUMERATE_SELF_INTERFACE_STANDARD au nom des pilotes. Par conséquent, l’inscription de cette interface n’est pas nécessaire pour ces pilotes. Si le pilote de bus doit effectuer certaines opérations avant que ses appareils enfants ne soient réénumérés, il doit s'enregistrer pour la fonction de rappel EvtChildListDeviceReenumerated et effectuer les opérations dans cette fonction. Étant donné que cette routine de rappel peut être appelée en parallèle pour tous les PDO, le code de la routine peut avoir besoin de se protéger contre les conditions de course.

Microprogramme ACPI : Réinitialisation au niveau fonctionnel

Pour prendre en charge la réinitialisation de l’appareil au niveau de la fonction, il doit y avoir une méthode _RST définie à l’intérieur de l’étendue de l’appareil. Si elle est présente, cette méthode remplace l'implémentation du pilote de bus pour la réinitialisation de périphérique au niveau de la fonction (si disponible) pour cet appareil. Lorsqu’elle est exécutée, la méthode _RST doit réinitialiser uniquement cet appareil et ne doit pas affecter d’autres appareils. En outre, l’appareil doit rester connecté sur le bus.

Microprogramme ACPI : Réinitialisation au niveau de la plateforme

Pour prendre en charge la réinitialisation de l’appareil au niveau de la plateforme, il existe deux options :

  • Le microprogramme ACPI peut définir une ressource PowerResource qui implémente la méthode _RST, et tous les appareils affectés par cette méthode de réinitialisation peuvent faire référence à ce PowerResource via un objet _PRR défini sous leur étendue d’appareil.

  • L’appareil peut déclarer un objet _PR3. Dans ce cas, le pilote ACPI utilise le cycle d’alimentation D3cold pour effectuer la réinitialisation, et les dépendances de réinitialisation entre les appareils seront déterminées à partir de l’objet _PR3.

Si l'objet _PRR existe dans l'étendue de l'appareil, le pilote ACPI utilise la méthode _RST dans la PowerResource référencée pour effectuer la réinitialisation. Si aucun objet _PRR n’est défini mais que l’objet _PR3 est défini, le pilote ACPI utilise le cycle d’alimentation D3cold pour effectuer la réinitialisation. Si ni l’objet _PRR ni _PR3 n’est défini, l’appareil ne prend pas en charge une réinitialisation au niveau de la plateforme et le pilote ACPI signale que la réinitialisation au niveau de la plateforme n’est pas disponible.

Vérification du microprogramme ACPI sur le système de test

Pour tester votre pilote qui prend en charge la réinitialisation et la récupération de l’appareil, suivez cette procédure. Cette procédure suppose que vous utilisez cet exemple de fichier ASL.

DefinitionBlock("SSDT.AML", "SSDT", 0x01, "XyzOEM", "TestTabl", 0x00001000)
{
   Scope(\_SB_)
      {
       PowerResource(PWFR, 0x5, 0x0)
       {
           Method(_RST, 0x0, NotSerialized)    { }
           
           // Placeholder methods as power resources need _ON, _OFF, _STA.
           Method(_STA, 0x0, NotSerialized)
           {
               Return(0xF)
           }

           Method(_ON_, 0x0, NotSerialized)    { }

           Method(_OFF, 0x0, NotSerialized)    { }

       } // PowerResource()
   } // Scope (\_SB_)

   // Assumes WiFi device is declared under \_SB.XYZ.
   Scope(\_SB_.XYZ.WIFI)
       {

       // Declare PWFR as WiFi reset power rail
       Name(_PRR, Package(One)
           {
               \_SB_.PWFR
           })
       } // Scope (\_SB)
}
  1. Compilez le fichier ASL de test en un AML à l’aide d’un compilateur ASL, tel que Asl.exe. L'exécutable est inclus dans le Kit de pilotes Windows (WDK).
Asl <test>.asl

La commande précédente génère SSDT.aml.

  1. Renommez SSDT.aml en acpitabl.dat.

  2. Copiez acpitabl.dat dans %systemroot%\system32 sur le système de test.

  3. Activez la signature de test sur le système de test.

bcdedit /set testsigning on
  1. Redémarrez le système de test.

  2. Vérifiez que la table est chargée. Dans le débogueur Windows, utilisez ces commandes.

  • !acpicache
  • dt adresse de _DESCRIPTION_HEADER de la table SSDT
0: kd> !acpicache
Dumping cached ACPI tables...
  SSDT @(ffffffffffd03018) Rev: 0x1 Len: 0x000043 TableID: TestTabl
  XSDT @(ffffffffffd05018) Rev: 0x1 Len: 0x000114 TableID: HSW-FFRD
       ...
       ...
 
0: kd> dt _DESCRIPTION_HEADER ffffffffffd03018
ACPI!_DESCRIPTION_HEADER
   +0x000 Signature        : 0x54445353
   +0x004 Length           : 0x43
   +0x008 Revision         : 0x1 ''
   +0x009 Checksum         : 0x37 '7'
   +0x00a OEMID            : [6]  "XyzOEM"
   +0x010 OEMTableID       : [8]  "TestTabl"
   +0x018 OEMRevision      : 0x1000
   +0x01c CreatorID        : [4]  "MSFT"
   +0x020 CreatorRev       : 0x5000000

Voir aussi

_STANDARD_D'INTERFACE_DE_RÉINITIALISATION_DU_DISPOSITIF