Hinzufügen eines PnP-Geräts zu einem laufenden System
In diesem Abschnitt wird die Abfolge von Ereignissen beschrieben, die auftreten, wenn das System ein PnP-Gerät konfiguriert, das ein Benutzer einem ausgeführten Computer hinzugefügt hat. In dieser Diskussion werden die Rollen des PnP-Managers, der Bustreiber sowie der Funktions- und Filtertreiber bei der Auflistung und Konfiguration eines neuen Geräts erläutert.
Die meisten dieser Diskussionen sind auch für die Konfiguration eines PnP-Geräts relevant, das beim Starten des Computers vorhanden ist. Insbesondere werden Geräte, deren Treiber SERVICE_DEMAND_START in einer INF-Datei gekennzeichnet sind, im Wesentlichen auf die gleiche Weise konfiguriert, ob das Gerät dynamisch hinzugefügt wird oder zur Startzeit vorhanden ist.
Die folgende Abbildung zeigt die ersten Schritte beim Konfigurieren des Geräts, beginnend mit dem Anschließen der Hardware an den Computer.
Die folgenden Hinweise entsprechen den eingekreisten Zahlen in der vorherigen Abbildung:
Ein Benutzer steckt ein PnP-Gerät in einen freien Steckplatz auf einem PnP-Bus.
In diesem Beispiel schließt der Benutzer einen PnP-USB-Joystick an den Hub auf einem USB-Hostcontroller an. Der USB-Hub ist ein PnP-Bus-Gerät, weil untergeordnete Geräte an ihn angeschlossen werden können.
Der Funktionstreiber für das Busgerät stellt fest, dass sich ein neues Gerät an seinem Bus befindet.
Wie der Fahrer dies bestimmt, hängt von der Busarchitektur ab. Bei einigen Bussen erhält der Bustreiber eine Hot-Plug-Benachrichtigung über neue Geräte. Wenn der Bus die Hot-Plug-Benachrichtigung nicht unterstützt, muss der Benutzende in der Systemsteuerung entsprechende Maßnahmen ergreifen, damit der Bus aufgelistet wird.
In diesem Beispiel unterstützt der USB-Bus die Hot-Plug-Benachrichtigung, so dass der Funktionstreiber für den USB-Bus darüber informiert wird, dass sich seine untergeordneten Elemente geändert haben.
Der Funktionstreiber für das Bus-Gerät benachrichtigt den PnP-Manager, dass sich die Menge der untergeordneten Geräte geändert hat.
Der Funktionstreiber benachrichtigt den PnP-Manager durch den Aufruf IoInvalidateDeviceRelations mit einem Typ BusRelations.
Der PnP-Manager fragt die Treiber des Busses nach der aktuellen Liste der Geräte auf dem Bus ab.
Der PnP-Manager sendet eine IRP_MN_QUERY_DEVICE_RELATIONS-Anfrage an den Gerätestack für den Bus. Der Parameters.QueryDeviceRelations.Type-Wert ist BusRelations, was bedeutet, dass der PnP-Manager nach der aktuellen Liste der am Bus vorhandenen Geräte fragt (Bus-Relations).
Der PnP-Manager sendet den IRP an den obersten Treiber im Gerätestack für den Bus. Gemäß den Regeln für PnP-IRPs bearbeitet jeder Treiber im Stack die IRP, falls erforderlich, und gibt die IRP an den nächsten Treiber weiter.
Der Funktionstreiber für das Gerät am Bus verarbeitet den IRP.
Auf der Referenzseite für IRP_MN_QUERY_DEVICE_RELATIONS finden Sie ausführliche Informationen zum Umgang mit diesem IRP.
In diesem Beispiel behandelt der USB-Hub-Treiber dieses IRP für den Hub FDO. Der Hub-Treiber erstellt ein PDO für das Joystick-Gerät und nimmt einen referenzierten Zeiger auf das Joystick-PDO in seine Liste der untergeordneten Geräte auf, die mit dem IRP zurückgegeben werden.
Wenn der übergeordnete Bustreiber des USB-Hubs (das Treiberpaar USB Host-Controller Klasse/Miniklasse) den IRP abschließt, wandert der IRP mit Hilfe der von den Hub-Treibern registrierten IoCompletion-Routinen den Gerätestack wieder hinauf.
Beachten Sie, dass der Bus-Funktionstreiber eine Änderung in seiner Liste der untergeordneten Elemente meldet, indem er den PnP-Manager nach seiner Liste der untergeordneten Elemente abfragt. Die daraus resultierende IRP_MN_QUERY_DEVICE_RELATIONS-Anfrage wird von allen Treibern für das Bus-Gerät gesehen. In der Regel ist der Busfunktionstreiber der einzige Treiber, der die IRP bearbeitet und untergeordnete Elemente liefert. In einigen Gerätekonstellationen ist ein Bus-Filtertreiber vorhanden und beteiligt sich an der Erstellung der Liste der Busbeziehungen. Ein Beispiel ist ACPI, das sich als Busfiltertreiber für ACPI-Geräte anschließt. In einigen Gerätestacks behandeln Nicht-Bus-Filtertreiber die IRP_MN_QUERY_DEVICE_RELATIONS-Anfrage, aber das ist nicht typisch.
Zu diesem Zeitpunkt verfügt der PnP-Manager über die aktuelle Liste der Geräte auf dem Bus. Der PnP-Manager bestimmt dann, ob geräte neu eingetroffen sind oder entfernt wurden. In diesem Beispiel gibt es ein neues Gerät. Die folgende Abbildung zeigt den PnP-Manager, der einen Devnode für das neue Gerät erstellt und mit der Konfiguration des Geräts beginnt.
Die folgenden Hinweise entsprechen den eingekreisten Zahlen in der vorherigen Abbildung:
Der PnP-Manager erstellt Devnodes für alle neuen untergeordneten Geräte auf dem Bus.
Der PnP-Manager vergleicht die Liste der Bus-Relationen, die in der IRP_MN_QUERY_DEVICE_RELATIONS-IRP zurückgegeben wurde, mit der Liste der untergeordneten Elemente für den Bus, die derzeit im PnP-Gerätebaum gespeichert sind. Der PnP-Manager erstellt einen Devnode für jedes neue Gerät und leitet die Verarbeitung von entfernten Geräten ein.
In diesem Beispiel gibt es ein neues Gerät (einen Joystick), sodass der PnP-Manager einen Devnode für den Joystick erstellt. Zu diesem Zeitpunkt ist der einzige Treiber, der für den Joystick konfiguriert ist, der übergeordnete USB-Hub-Bustreiber, der das PDO des Joysticks erstellt hat. Alle optionalen Busfiltertreiber wären auch im Gerätestapel vorhanden, aber im Beispiel werden Busfiltertreiber aus Gründen der Einfachheit weggelassen.
Der breite Pfeil zwischen den beiden devnodes in der vorherigen Abbildung zeigt an, dass der joystick devnode ein untergeordneter devnode des USB-Hubs ist.
Der PnP-Manager sammelt Informationen über das neue Gerät und beginnt mit der Konfiguration des Geräts.
Der PnP-Manager sendet eine Abfolge von IRPs an den Gerätestapel, um Informationen über das Gerät zu sammeln. Zu diesem Zeitpunkt besteht der Gerätestack nur noch aus dem PDO, das vom übergeordneten Bustreiber des Geräts erstellt wurde, und aus Filter-DOs für alle optionalen Busfiltertreiber. Daher sind der Bustreiber und die Busfiltertreiber die einzigen Treiber, die auf diese IRPs reagieren. In diesem Beispiel ist der einzige Treiber im Gerätestack des Joysticks der übergeordnete Bustreiber, der USB-Hub-Treiber.
Der PnP-Manager sammelt Informationen über ein neues Gerät, indem er IRPs an den Gerätestapel sendet. Zu diesen IRPs gehören die folgenden:
IRP_MN_QUERY_ID, ein separater IRP für jeden der folgenden Typen von Hardware-IDs:
BusQueryDeviceID
BusQueryInstanceID
BusQueryHardwareIDs
BusQueryCompatibleIDs
BusQueryContainerID
IRP_MN_QUERY_DEVICE_TEXT, ein separater IRP für jedes der folgenden Elemente:
DeviceTextDescription
DeviceTextLocationInformation
Der PnP-Manager sendet die oben aufgeführten IRPs in dieser Phase der Verarbeitung eines neuen PnP-Geräts, aber nicht unbedingt in der aufgeführten Reihenfolge, daher sollten Sie keine Annahmen über die Reihenfolge treffen, in der die IRPs gesendet werden. Außerdem sollten Sie nicht davon ausgehen, dass der PnP-Manager nur die oben aufgeführten IRPs sendet.
Der PnP-Manager überprüft die Registrierung, um festzustellen, ob das Gerät zuvor auf diesem Computer installiert wurde. Der PnP-Manager sucht nach einem <enumerator>\<deviceID>-Unterschlüssel für das Gerät unter dem Enum-Zweig. In diesem Beispiel ist das Gerät neu und muss von Grund auf konfiguriert werden.
Der PnP-Manager speichert Informationen über das Gerät in der Registrierung.
Der Enum-Zweig der Registrierung ist für die Verwendung durch Komponenten des Betriebssystems reserviert und sein Layout kann sich ändern. Autoren von Treibern müssen Systemfunktionen verwenden, um Informationen über die Treiber zu extrahieren. Greifen Sie nicht direkt von einem Treiber auf den Enum-Zweig zu. Die folgenden Enum-Informationen sind nur zu Debugging-Zwecken aufgeführt.
Der PnP-Manager erstellt einen Unterschlüssel für das Gerät unter dem Schlüssel für den Enumerator des Geräts.
Der PnP-Manager erstellt einen Unterschlüssel namens HKLM\System\CurrentControlSet\Enum\<Enumerator>\<deviceID>. Er erstellt den Unterschlüssel <enumerator>, wenn dieser nicht bereits existiert.
Ein Enumerator ist eine Komponente, die PnP-Geräte basierend auf einem PnP-Hardware-Standard ermittelt. Die Aufgaben eines Enumerators werden von einem PnP-Bustreiber in Zusammenarbeit mit dem PnP-Manager ausgeführt. Ein Gerät wird in der Regel von seinem übergeordneten Bustreiber aufgelistet, wie z. B. PCI oder PCMCIA. Einige Geräte werden von einem Busfiltertreiber wie z. B. ACPI aufgelistet.
Der PnP-Manager erstellt einen Unterschlüssel für diese Instanz des Geräts.
Wenn Capabilities.UniqueID als TRUE für IRP_MN_QUERY_CAPABILITIES zurückgegeben wird, ist die eindeutige ID des Geräts systemweit eindeutig. Ist dies nicht der Fall, ändert der PnP-Manager die ID so, dass sie systemweit eindeutig ist.
Der PnP-Manager erstellt einen Unterschlüssel namens HKLM\System\CurrentControlSet\Enum\<enumerator>\<deviceID>\<instanceID>.
Der PnP-Manager schreibt Informationen über das Gerät in den Unterschlüssel für die Instanz des Geräts.
Der PnP-Manager speichert Informationen, einschließlich folgender, wenn sie für das Gerät bereitgestellt wurden:
DeviceDesc– von IRP_MN_QUERY_DEVICE_TEXT
Location– von IRP_MN_QUERY_DEVICE_TEXT
Funktionen - die Flags aus IRP_MN_QUERY_CAPABILITIES
UINumber– von IRP_MN_QUERY_CAPABILITIES
HardwareID– von IRP_MN_QUERY_ID
CompatibleIDs– von IRP_MN_QUERY_ID
ContainerID– von IRP_MN_QUERY_ID
LogConf\BootConfig– von IRP_MN_QUERY_RESOURCES
LogConf\BasicConfigVector– von IRP_MN_QUERY_RESOURCE_REQUIREMENTS
An diesem Punkt ist der PnP-Manager bereit, den Funktionstreiber und die Filtertreiber für das Gerät zu lokalisieren, falls vorhanden. (Siehe folgende Abbildung.)
Die folgenden Hinweise entsprechen den nummerierten Kreisen in der vorherigen Abbildung:
Der PnP-Manager im Kernel-Modus stimmt sich mit dem PnP-Manager im Benutzermodus und den Setup-Komponenten im Benutzermodus ab, um die Funktions- und Filtertreiber für das Gerät zu finden, falls es welche gibt.
Der PnP-Manager im Kernel-Modus stellt ein Ereignis für den PnP-Manager im Benutzermodus in eine Warteschlange, das ein Gerät identifiziert, das installiert werden muss. Sobald sich ein privilegierter Benutzer anmeldet, fahren die Benutzermoduskomponenten mit der Suche nach Treibern fort. In der Übersicht zur Geräteinstallation finden Sie Informationen zu den Komponenten der Einrichtung und ihrer Rolle bei der Installation eines Geräts.
Die Setup-Komponenten im Benutzermodus weisen den PnP-Manager im Kernel-Modus an, die Funktions- und Filtertreiber zu laden.
Die Komponenten im Benutzermodus rufen den Kernel-Modus auf, um die Treiber zu laden und rufen ihre AddDevice-Routinen auf.
Die folgende Abbildung zeigt, wie der PnP-Manager die Treiber lädt (falls zutreffend), ihre AddDevice-Routinen aufruft und die Treiber anweist, das Gerät zu starten.
Die folgenden Hinweise entsprechen den nummerierten Kreisen in der vorherigen Abbildung:
Lower-Filter-Treiber
Bevor der Funktionstreiber an den Gerätestack angehängt wird, verarbeitet der PnP-Manager alle Lower-Filter-Treiber. Für jeden Lower-Filter-Treiber ruft der PnP-Manager die Routine DriverEntry des Treibers auf, wenn der Treiber noch nicht geladen ist. Dann ruft der PnP-Manager die Funktion AddDevice des Treibers auf. In seiner AddDevice-Routine erstellt der Filtertreiber ein Filter-Geräteobjekt (Filter DO) und hängt es an den Gerätestack an (IoAttachDeviceToDeviceStack). Sobald er sein Geräteobjekt an den Gerätestack angehängt hat, ist der Treiber als Treiber für das Gerät interagiert.
Im Beispiel des USB-Joysticks gibt es einen Treiber mit einem Lower-Filter- für das Gerät.
Funktionstreiber
Nachdem alle Lower-Filter angehängt sind, verarbeitet der PnP-Manager den Funktionstreiber. Der PnP-Manager ruft die Routine DriverEntry des Funktionstreibers auf, wenn der Treiber noch nicht geladen ist, und ruft die Routine AddDevice des Funktionstreibers auf. Der Funktionstreiber erstellt ein Funktionsgeräteobjekt (Function Device Object, FDO) und fügt es an den Gerätestapel an.
In diesem Beispiel ist der Funktionstreiber für den USB-Joystick eigentlich ein Treiberpaar: der HID-Klassentreiber und der HID-Miniklassentreiber. Die beiden Treiber arbeiten zusammen, um als Funktionstreiber zu dienen. Das Treiberpaar erstellt nur ein FDO und fügt es an den Gerätestack an.
Upper-Filter-Treiber
Nachdem der Funktionstreiber angehängt ist, verarbeitet der PnP-Manager alle Upper-Filter-Treiber.
In diesem Beispiel gibt es einen Upper-Filter-Treiber für das Gerät.
Zuweisen von Ressourcen und Starten des Geräts
Der PnP-Manager weist dem Gerät bei Bedarf Ressourcen zu und gibt einen IRP zum Starten des Geräts aus.
Zuweisung von Ressourcen
Zu einem früheren Zeitpunkt im Konfigurationsprozess hat der PnP-Manager die Hardware-Ressourcenanforderungen für das Gerät vom übergeordneten Bustreiber des Geräts abgefragt. Nachdem der vollständige Satz von Treibern für das Gerät geladen ist, sendet der PnP-Manager eine IRP_MN_FILTER_RESOURCE_REQUIREMENTS-Anfrage an den Gerätestack. Alle Treiber im Stapel haben die Möglichkeit, dieses IRP zu verarbeiten und die Ressourcenanforderungenliste des Geräts bei Bedarf zu ändern.
Der PnP-Manager weist dem Gerät, falls erforderlich, Ressourcen zu, basierend auf den Anforderungen des Geräts und den derzeit verfügbaren Ressourcen.
Möglicherweise muss der PnP-Manager die Ressourcenzuordnungen vorhandener Geräte neu anordnen, um die Anforderungen des neuen Geräts zu erfüllen. Diese Neuzuweisung von Ressourcen wird als"Rebalancing" bezeichnet. Die Treiber für die vorhandenen Geräte erhalten während eines Rebalancings eine Sequenz von Stop- und Start-IRPs, aber das Rebalancing muss für die Benutzenden transparent sein.
Im Beispiel des USB-Joysticks benötigen USB-Geräte keine Hardwareressourcen, sodass der PnP-Manager die Ressourcenliste auf NULL-festlegt.
Starten des Geräts (IRP_MN_START_DEVICE)
Sobald der PnP-Manager dem Gerät Ressourcen zugewiesen hat, sendet er ein IRP_MN_START_DEVICE-IRP an den Gerätestack, um die Treiber anzuweisen, das Gerät zu starten.
Nachdem das Gerät gestartet wurde, sendet der PnP-Manager drei weitere IRPs an die Treiber für das Gerät:
-
Nachdem der Start-IRP erfolgreich abgeschlossen wurde, sendet der PnP-Manager ein weiteres IRP_MN_QUERY_CAPABILITIES-IRP an den Gerätestack. Alle Treiber für das Gerät haben die Möglichkeit, das IRP zu verarbeiten. Der PnP-Manager sendet dieses IRP zu diesem Zeitpunkt, nachdem alle Treiber angeschlossen sind und das Gerät gestartet wird, da die Funktions- oder Filtertreiber möglicherweise auf das Gerät zugreifen müssen, um Funktionsinformationen zu sammeln.
-
Dieser IRP bietet einem Treiber die Möglichkeit, beispielsweise zu melden, dass das Gerät nicht in Benutzeroberflächen wie Device Manager und dem Hotplug-Programm angezeigt werden soll. Dies ist nützlich für Geräte, die zwar auf einem System vorhanden sind, aber in der aktuellen Konfiguration nicht verwendet werden können, wie z. B. ein Game Port auf einem Laptop, der nicht verwendet werden kann, wenn der Laptop abgedockt ist.
IRP_MN_QUERY_DEVICE_RELATIONS für Busbeziehungen
Der PnP-Manager sendet diesen IRP, um festzustellen, ob das Gerät untergeordnete Geräte hat. Ist dies der Fall, konfiguriert der PnP-Manager jedes untergeordnete Gerät.
Verwendung von GUID_PNP_LOCATION_INTERFACE
Die Schnittstelle GUID_PNP_LOCATION_INTERFACE liefert die SPDRP_LOCATION_PATHS Plug-and-Play (PnP)-Geräteeigenschaft für ein Gerät.
Um diese Schnittstelle in Ihrem Treiber zu implementieren, behandeln Sie das IRP_MN_QUERY_INTERFACE-IRP mit InterfaceType = GUID_PNP_LOCATION_INTERFACE. Ihr Treiber liefert einen Zeiger auf eine PNP_LOCATION_INTERFACE-Struktur, die Zeiger auf die einzelnen Funktionen der Schnittstelle enthält. Die PnpGetLocationString-Routine liefert das gerätespezifische Element der SPDRP_LOCATION_PATHS-Eigenschaft des Geräts.