Starten eines Geräts in einem Funktionstreiber

Ein Funktionstreiber legt eine IoCompletion-Routine fest, übergibt eine IRP_MN_START_DEVICE Anforderung im Gerätestapel und verschiebt seine Startvorgänge, bis alle niedrigeren Treiber mit dem IRP abgeschlossen sind. Ausführliche Informationen zur Verwendung eines Kernelereignisses und einer IoCompletion-Routine zum Verschieben der IRP-Verarbeitung finden Sie unter Verschieben der PnP-IRP-Verarbeitung bis zum Beenden niedrigerer Treiber.

Wenn die DispatchPnP-Routine die Kontrolle wiedererlangt, nachdem alle niedrigeren Treiber mit dem IRP abgeschlossen sind, führt der Funktionstreiber seine Aufgaben zum Starten des Geräts aus. Ein Funktionstreiber startet das Gerät mit einer Prozedur wie der folgenden:

  1. Wenn bei einem niedrigeren Treiber ein Fehler beim IRP aufgetreten ist (IoCallDriver hat einen Fehler zurückgegeben), setzen Sie die Verarbeitung des IRP nicht fort. Führen Sie alle erforderlichen Bereinigungen durch und kehren Sie von der DispatchPnP-Routine zurück (wechseln Sie zum letzten Schritt in dieser Liste).

  2. Wenn niedrigere Treiber die IRP erfolgreich verarbeitet haben, starten Sie das Gerät.

    Die genauen Schritte zum Starten eines Geräts variieren von Gerät zu Gerät. Diese Schritte können das Zuordnen des E/A-Speicherplatzes, das Initialisieren von Hardwareregistern, das Festlegen des Geräts in den D0-Netzzustand und das Verbinden des Interrupts mit IoConnectInterrupt umfassen. Wenn der Treiber ein Gerät nach einer IRP_MN_STOP_DEVICE Anforderung neu startet, muss der Treiber möglicherweise den Gerätezustand wiederherstellen.

    Das Gerät muss eingeschaltet sein, bevor Treiber darauf zugreifen können. Weitere Informationen finden Sie unter Einschalten eines Geräts .

    Wenn das Gerät für das Reaktivieren aktiviert werden soll, sollte der Besitzer der Energierichtlinie (in der Regel der Funktionstreiber) nach dem Einschalten des Geräts und vor Abschluss der IRP_MN_START_DEVICE-Anforderung einen Warte-/Wake-IRP senden. Weitere Informationen finden Sie unter Senden eines Warte-/Wake-IRP.

  3. Starten Sie IRPs in der IRP-Holding-Warteschlange.

    Löschen Sie das vom Treiber definierte HOLD_NEW_REQUESTS Flag, und starten Sie die IRPs in der IRP-Warteschlange. Treiber sollten dies beim erstmaligen Starten eines Geräts und beim Neustart eines Geräts nach einem Abfragestopp oder -Beenden von IRP tun. Weitere Informationen finden Sie unter Halten eingehender IRPs, wenn ein Gerät angehalten wird .

  4. [Optional] Aktivieren Sie Schnittstellen für das Gerät, indem Sie IoSetDeviceInterfaceState aufrufen.

    Aktivieren Sie ggf. die Schnittstellen, die der Treiber zuvor in seiner AddDevice-Routine (oder in einem INF oder einer anderen Komponente wie einem Co-Installer) registriert hat.

    Unter Windows 2000 und höheren Versionen von Windows sendet der PnP-Manager erst Benachrichtigungen über Geräteschnittstelleneinkünfte, bis die IRP_MN_START_DEVICE IRP abgeschlossen ist. Dies gibt an, dass alle Treiber für das Gerät ihre Startvorgänge abgeschlossen haben. Der PnP-Manager schlägt auch alle Erstellungsanforderungen fehl, die eingehen, bevor alle Treiber für das Gerät die Start-IRP abschließen.

  5. Schließen Sie die IRP ab.

    Die IoCompletion-Routine des Funktionstreibers hat STATUS_MORE_PROCESSING_REQUIRED zurückgegeben, wie unter Verschieben der PnP-IRP-Verarbeitung bis zum Abschluss der niedrigeren Treiber beschrieben. Daher muss die DispatchPnP-Routine des Funktionstreibers IoCompleteRequest aufrufen, um die E/A-Vervollständigungsverarbeitung fortzusetzen.

    Wenn die Startvorgänge des Funktionstreibers erfolgreich waren, legt der Treiber Irp-IoStatus.Status> auf STATUS_SUCCESS fest, ruft IoCompleteRequest mit einer Prioritätserhöhung von IO_NO_INCREMENT auf und gibt STATUS_SUCCESS aus seiner DispatchPnP-Routine zurück.

    Wenn beim Funktionstreiber während seiner Startvorgänge ein Fehler auftritt, legt der Treiber einen Fehler status im IRP fest, ruft IoCompleteRequest mit IO_NO_INCREMENT auf und gibt den Fehler aus seiner DispatchPnP-Routine zurück.

    Wenn bei einem niedrigeren Treiber ein Fehler beim IRP aufgetreten ist (IoCallDriver hat einen Fehler zurückgegeben), ruft der Funktionstreiber IoCompleteRequest mit IO_NO_INCREMENT auf und gibt den IoCallDriver-Fehler aus seiner DispatchPnP-Routine zurück. Der Funktionstreiber legt in diesem Fall Irp-IoStatus.Status> nicht fest, da die status bereits vom niedrigeren Treiber festgelegt wurde, bei dem die IRP fehlgeschlagen ist.

Wenn ein Funktionstreiber eine IRP_MN_START_DEVICE Anforderung empfängt, sollte er die Strukturen unter IrpSp-Parameters.StartDevice.AssignedResources> und IrpSp-Parameters.StartDevice.AssignedResourcesTranslated untersuchen, die die rohen und übersetzten Ressourcen beschreiben, die der PnP-Manager> dem Gerät zugewiesen hat. Treiber sollten eine Kopie jeder Ressourcenliste in der Geräteerweiterung als Debughilfe speichern.

Die Ressourcenlisten werden CM_RESOURCE_LIST Strukturen gekoppelt, in denen jedes Element der rohen Liste demselben Element der übersetzten Liste entspricht. Wenn beispielsweise AllocatedResources.List[0] einen unformatierten E/A-Portbereich beschreibt, beschreibt AllocatedResourcesTranslated.List[0] den gleichen Bereich nach der Übersetzung. Jede übersetzte Ressource enthält eine physische Adresse und den Typ der Ressource.

Wenn einem Treiber eine übersetzte Speicherressource (CmResourceTypeMemory) zugewiesen wird, muss mmMapIoSpace aufgerufen werden, um die physische Adresse einer virtuellen Adresse zuzuordnen, über die er auf Geräteregister zugreifen kann. Damit ein Treiber plattformunabhängig arbeiten kann, sollte er jede zurückgegebene, übersetzte Ressource überprüfen und bei Bedarf zuordnen.

Ein Funktionstreiber sollte als Reaktion auf eine IRP_MN_START_DEVICE folgendes tun, um den Zugriff auf alle Geräteressourcen sicherzustellen:

  1. Kopieren Sie IrpSp-Parameters.StartDevice.AllocatedResources> in die Geräteerweiterung.

  2. Kopieren Sie IrpSp-Parameters.StartDevice.AllocatedResourcesTranslated> in die Geräteerweiterung.

  3. Überprüfen Sie in einer Schleife jedes Deskriptorelement in AllocatedResourcesTranslated. Wenn der Deskriptorressourcentyp CmResourceTypeMemory ist, rufen Sie MmMapIoSpace auf, und übergeben Sie die physische Adresse und länge der übersetzten Ressource.

Wenn der Treiber eine IRP_MN_STOP_DEVICE, IRP_MN_REMOVE_DEVICE oder IRP_MN_SURPRISE_REMOVAL Anforderung empfängt, muss er die Zuordnungen freigeben, indem er MmUnmapIoSpace in einer ähnlichen Schleife aufruft. Der Treiber sollte auch MmUnmapIoSpace aufrufen, wenn die IRP_MN_START_DEVICE-Anforderung fehlschlagen muss.

Weitere Informationen finden Sie unter Zuordnen Bus-Relative Adressen zu virtuellen Adressen .