Koordinieren von E/A-Anforderungen mit dem Energiezustand der Komponente
[Gilt nur für KMDF]
Ein KMDF-Treiber für ein Gerät mit mehreren Komponenten darf Anforderungen nur an Komponenten senden, die sich im aktiven Zustand befinden. In der Regel weist der Treiber Komponenten oder Komponentengruppen E/A-Warteschlangen zu.
Betrachten Sie zunächst eine Warteschlange, die einer einzelnen Komponente zugewiesen ist. Der Treiber startet die Warteschlange, wenn die Komponente aktiv wird, und beendet die Warteschlange, wenn die Komponente im Leerlauf ist. Wenn KMDF also einen Anforderungshandler für die Warteschlange aufruft, befindet sich das Gerät im Zustand vollständig aktiviert (D0), und die erforderliche Komponente ist aktiv. Der Anforderungshandler kann sicher auf Komponentenhardware zugreifen.
Das gleiche Konzept gilt für eine Warteschlange, die einer Gruppe von Komponenten zugewiesen ist. In diesem Fall startet der Treiber die Warteschlange, wenn alle Komponenten in der Gruppe aktiv sind. Der Treiber beendet die Warteschlange, wenn eine der Komponenten im Leerlauf ist.
In diesem Thema wird beschrieben, wie ein KMDF-Treiber für ein Gerät mit mehreren Komponenten eine solche Unterstützung in einer Situation implementieren kann, in der mehrere Anforderungstypen auftreten, die unterschiedliche Komponentenkombinationen erfordern.
Beispiel
Identifizieren Sie für jeden vom Treiber unterstützten Anforderungstyp die erforderlichen Komponenten. Betrachten Sie beispielsweise ein Gerät mit drei Komponenten: 0, 1 und 2, für das der Treiber drei Arten von Anforderungen empfängt: A, B und C. Die Komponentenanforderungen der Anforderungen sind wie folgt:
Anforderungstyp | Erforderliche Komponenten |
---|---|
Ein | 0,2 |
B | 1 |
C | 0,1,2 |
In diesem Beispiel gibt es drei unterschiedliche Komponentensätze, eine für jeden Anforderungstyp. Der Treiber stellt eine standardmäßige, stromverwaltete E/A-Warteschlange für das Gerät sowie eine zusätzliche energieverwaltete Warteschlange bereit, die jedem Satz von Komponenten entspricht. Im obigen Beispiel erstellt der Treiber eine primäre und drei sekundäre Warteschlangen, eine für jeden Komponentensatz. Diese Warteschlangenkonfiguration wird im folgenden Diagramm dargestellt:
Der Treiber verwaltet eine Bitmaske für jeden Komponentensatz. Jedes Bit in der Bitmaske stellt den Aktiv-/Leerlaufzustand einer der Komponenten dar. Wenn das Bit festgelegt ist, ist die Komponente aktiv. Wenn das Bit gelöscht wird, befindet sich die Komponente im Leerlauf.
Wenn eine Anforderung eingeht, bestimmt ein Anforderungshandler für die Warteschlange der obersten Ebene, welche Komponenten die Anforderung benötigt, und ruft poFxActivateComponent für jede anforderung auf. Der Anforderungshandler leitet dann die Anforderung an die sekundäre E/A-Warteschlange weiter, die dem Satz dieser Komponente entspricht.
Wenn eine Komponente aktiv wird, ruft das Power Management Framework (PoFx) die ComponentActiveConditionCallback-Routine des Treibers auf. In diesem Rückruf legt der Treiber das Bit fest, das der angegebenen Komponente entspricht, in jeder Bitmaske, in der diese Komponente dargestellt wird. Wenn alle Bits in einer bestimmten Bitmaske festgelegt sind, sind alle Komponenten in der entsprechenden Gruppe aktiv. Für jeden vollständig aktiven Komponentensatz ruft der Treiber WdfIoQueueStart auf, um die entsprechende sekundäre E/A-Warteschlange zu starten.
Betrachten Sie beispielsweise das hypothetische Gerät oben. Angenommen, die Komponente 0 ist aktiv, während sich die Komponenten 1 und 2 im Leerlauf befinden. Wenn Komponente 2 aktiv wird, ruft PoFx die ComponentActiveConditionCallback-Routine dieser Komponente auf. Die Anforderungstypen A und C verwenden Komponente 2, sodass der Treiber die Bitmasken für diese beiden Anforderungstypen bearbeitet. Da jetzt alle Bits in der Bitmaske für Anforderungstyp A festgelegt sind, startet der Treiber die Warteschlange für den Anforderungstyp A. Allerdings sind nicht alle Bits für den Anforderungstyp C festgelegt (Komponente 1 befindet sich noch im Leerlauf). Der Treiber startet die Warteschlange für den Anforderungstyp C nicht.
Wenn eine sekundäre E/A-Warteschlange gestartet wird, beginnt das Framework mit der Übermittlung der Anforderungen, die in der Warteschlange gespeichert sind. Im Anforderungshandler für die sekundäre E/A-Warteschlange kann der Treiber die Anforderungen sicher verarbeiten, da die Komponente aktiv ist und für jede Anforderung ein Energieverweis für die Komponente erstellt wurde.
Wenn der Treiber die Verarbeitung einer Anforderung abgeschlossen hat, ruft er PoFxIdleComponent für jede Komponente auf, die von der Anforderung verwendet wurde, und schließt dann die Anforderung ab. Wenn keine Anforderungen mehr mithilfe einer Komponente vorhanden sind, ruft das Power Framework die ComponentIdleConditionCallback-Routine des Treibers auf.
In diesem Rückruf löscht der Treiber das Bit, das der angegebenen Komponente entspricht, in jeder Bitmaske, in der diese Komponente dargestellt wird. Wenn eine bestimmte Bitmaske angibt, dass die Komponente die erste in der entsprechenden Gruppe ist, die zur Leerlaufbedingung übergeht, ruft der Treiber WdfIoQueueStop auf, um die entsprechende sekundäre E/A-Warteschlange zu beenden. Auf diese Weise stellt der Treiber sicher, dass die Warteschlange keine Anforderungen sendet, es sei denn, alle Komponenten in der entsprechenden Gruppe sind aktiv.
Betrachten Sie noch einmal das obige Beispiel. Angenommen, alle Komponenten sind aktiv und daher werden alle Warteschlangen gestartet. Wenn Komponente 1 in den Leerlauf wechselt, ruft PoFx die ComponentIdleConditionCallback-Routine für Komponente 1 auf. In diesem Rückruf bearbeitet der Treiber die Bitmasken für die Anforderungstypen B und C, da er Komponente 1 verwendet. Da Komponente 1 die erste Komponente ist, die für beide Anforderungstypen in den Leerlauf wechselt, beendet der Treiber die Warteschlangen für die Anforderungstypen B und C.
Angenommen, an diesem Punkt wird Komponente 0 im Leerlauf. In ComponentIdleConditionCallback für Komponente 0 bearbeitet der Treiber die Bitmasken für die Anforderungstypen A und C. Da Komponente 0 die erste Komponente ist, die für den Anforderungstyp A in den Leerlauf wechselt (Komponente 2 ist noch aktiv), beendet der Treiber die Warteschlange für den Anforderungstyp A. Für anforderungstyp C ist Komponente 0 jedoch nicht die erste Komponente, die in den Leerlauf wechselt. Der Treiber beendet die Warteschlange für den Anforderungstyp C nicht (dies war zuvor der Fall).
Um die in diesem Beispiel beschriebene Technik zu verwenden, muss der Treiber auch eine EvtIoCanceledOnQueue-Rückruffunktion für jede seiner sekundären Warteschlangen registrieren. Wenn eine Anforderung in der sekundären Warteschlange abgebrochen werden soll, kann der Treiber diesen Rückruf verwenden, um PoFxIdleComponent für jede entsprechende Komponente aufzurufen. Dadurch wird der Energieverweis freigegeben, den der Anforderungshandler beim Aufrufen von PoFxActivateComponent verwendet hat, bevor die Anforderung an die sekundäre Warteschlange weitergeleitet wird.