Démarrage d’un appareil dans un pilote de fonction
Un pilote de fonction définit une routine IoCompletion , transmet une requête IRP_MN_START_DEVICE dans la pile de l’appareil et reporte ses opérations de démarrage jusqu’à ce que tous les pilotes inférieurs aient terminé l’IRP. Consultez Reporting PnP IRP Processing Until Lower Drivers Finish pour plus d’informations sur l’utilisation d’un événement de noyau et d’une routine IoCompletion pour reporter le traitement IRP.
Lorsque sa routine DispatchPnP reprend le contrôle une fois que tous les pilotes inférieurs ont terminé l’IRP, le pilote de fonction effectue ses tâches de démarrage de l’appareil. Un pilote de fonction démarre l’appareil avec une procédure semblable à celle-ci :
Si un pilote inférieur a échoué à l’IRP (IoCallDriver a renvoyé une erreur), ne poursuivez pas le traitement de l’IRP. Effectuez le nettoyage nécessaire et revenez à partir de la routine DispatchPnP (passez à la dernière étape de cette liste).
Si les pilotes inférieurs ont correctement traité l’IRP, démarrez l’appareil.
Les étapes exactes pour démarrer un appareil varient d’un appareil à l’autre. Ces étapes peuvent inclure le mappage de l’espace d’E/S, l’initialisation des registres matériels, la définition de l’état d’alimentation D0 et la connexion de l’interruption à IoConnectInterrupt. Si le pilote redémarre un appareil après une demande de IRP_MN_STOP_DEVICE , il peut avoir l’état de l’appareil à restaurer.
L’appareil doit être sous tension avant que des pilotes puissent y accéder. Pour plus d’informations, consultez Mise sous tension d’un appareil .
Si l’appareil doit être activé pour la mise en éveil, son propriétaire de la stratégie d’alimentation (généralement le pilote de fonction) doit envoyer un IRP d’attente/veille une fois qu’il a mis l’appareil sous tension et avant qu’il n’ait terminé la demande IRP_MN_START_DEVICE . Pour plus d’informations, consultez Envoi d’un IRP d’attente/veille.
Démarrez les IRP dans la file d’attente qui contient des IRP.
Effacez l’indicateur de HOLD_NEW_REQUESTS défini par le pilote et démarrez les irPs dans la file d’attente IRP. Les pilotes doivent effectuer cette opération lors du démarrage d’un appareil pour la première fois et lors du redémarrage d’un appareil après un arrêt ou un arrêt de la requête IRP. Pour plus d’informations, consultez Conservation des IRP entrants lorsqu’un appareil est suspendu .
[Facultatif] Activez les interfaces pour l’appareil en appelant IoSetDeviceInterfaceState.
Activez les interfaces, le cas échéant, que le pilote a précédemment inscrites dans sa routine AddDevice (ou dans un INF ou par un autre composant tel qu’un co-programme d’installation).
Sur Windows 2000 et versions ultérieures de Windows, le gestionnaire PnP n’envoie pas de notification d’arrivées d’interface d’appareil tant que l’IRP IRP_MN_START_DEVICE n’a pas terminé, ce qui indique que tous les pilotes de l’appareil ont terminé leurs opérations de démarrage. Le gestionnaire PnP échoue également à toutes les demandes de création qui arrivent avant que tous les pilotes de l’appareil terminent l’IRP de démarrage.
Terminez l’IRP.
La routine IoCompletion du pilote de fonction a renvoyé STATUS_MORE_PROCESSING_REQUIRED, comme décrit dans Reporting PnP IRP Processing Until Lower Drivers Finish, de sorte que la routine DispatchPnP du pilote de fonction doit appeler IoCompleteRequest pour reprendre le traitement de la fin des E/S.
Si les opérations de démarrage du pilote de fonction ont réussi, le pilote définit Irp-IoStatus.Status> sur STATUS_SUCCESS, appelle IoCompleteRequest avec une priorité de IO_NO_INCREMENT et retourne STATUS_SUCCESS à partir de sa routine DispatchPnP.
Si le pilote de fonction rencontre une erreur lors de ses opérations de démarrage, il définit une status d’erreur dans l’IRP, appelle IoCompleteRequest avec IO_NO_INCREMENT et retourne l’erreur à partir de sa routine DispatchPnP.
Si un pilote inférieur a échoué à l’IRP (IoCallDriver a renvoyé une erreur), le pilote de fonction appelle IoCompleteRequest avec IO_NO_INCREMENT et retourne l’erreur IoCallDriver à partir de sa routine DispatchPnP . Le pilote de fonction ne définit pas Irp-IoStatus.Status> dans ce cas, car le status a déjà été défini par le pilote inférieur qui a échoué à l’IRP.
Lorsqu’un pilote de fonction reçoit une demande de IRP_MN_START_DEVICE, il doit examiner les structures IrpSp-Parameters.StartDevice.AllocationResources> et IrpSp-Parameters.StartDevice.AllocationResourcesTranslated>, qui décrivent respectivement les ressources brutes et traduites que le gestionnaire PnP a attribuées à l’appareil. Les pilotes doivent enregistrer une copie de chaque liste de ressources dans l’extension de périphérique en tant qu’aide au débogage.
Les listes de ressources sont jumelées CM_RESOURCE_LIST structures, dans lesquelles chaque élément de la liste brute correspond au même élément de la liste traduite. Par exemple, si AllocationResources.List[0] décrit une plage de ports d’E/S brute, AllocationResourcesTranslated.List[0] décrit la même plage après la traduction. Chaque ressource traduite inclut une adresse physique et le type de la ressource.
Si un pilote se voit attribuer une ressource de mémoire traduite (CmResourceTypeMemory), il doit appeler MmMapIoSpace pour mapper l’adresse physique en une adresse virtuelle via laquelle il peut accéder aux registres d’appareils. Pour qu’un pilote fonctionne de manière indépendante de la plateforme, il doit case activée chaque ressource retournée, traduite et la mapper, si nécessaire.
Un pilote de fonction doit effectuer les opérations suivantes en réponse à un IRP_MN_START_DEVICE pour garantir l’accès à toutes les ressources d’appareil :
Copiez IrpSp-Parameters.StartDevice.AllocationResources> dans l’extension de l’appareil.
Copiez IrpSp-Parameters.StartDevice.AllocationResourcesTranslated> dans l’extension de l’appareil.
Dans une boucle, inspectez chaque élément de descripteur dans AllocationResourcesTranslated. Si le type de ressource de descripteur est CmResourceTypeMemory, appelez MmMapIoSpace en passant l’adresse physique et la longueur de la ressource traduite.
Lorsque le pilote reçoit une demande IRP_MN_STOP_DEVICE, IRP_MN_REMOVE_DEVICE ou IRP_MN_SURPRISE_REMOVAL , il doit libérer les mappages en appelant MmUnmapIoSpace dans une boucle similaire. Le pilote doit également appeler MmUnmapIoSpace s’il doit échouer la demande de IRP_MN_START_DEVICE .
Pour plus d’informations, consultez Mappage d’adresses Bus-Relative à des adresses virtuelles .