Verwenden von Passive-Level Interruptdienstroutinen

Ab Windows 8 kann ein Treiber die IoConnectInterruptEx-Routine verwenden, um eine InterruptService-Routine (ISR) auf passiver Ebene zu registrieren. Wenn der zugeordnete Interrupt auftritt, plant der Interrupt-Trap-Handler des Kernels die Ausführung dieser Routine bei IRQL = PASSIVE_LEVEL. Ein ISR muss möglicherweise auf passiver Ebene ausgeführt werden, wenn er nur über E/A-Anforderungen auf die Hardwareregister eines Geräts zugreifen kann. Ein ISR auf passiver Ebene kann eine E/A-Anforderung synchron an ein Gerät senden und blockieren, bis die Anforderung abgeschlossen ist.

Registrieren eines Passive-Level ISR

Der Eingabeparameter auf IoConnectInterruptEx ist ein Zeiger auf eine IO_CONNECT_INTERRUPT_PARAMETERS-Struktur . Um einen ISR auf passiver Ebene zu registrieren, legen Sie das Versionselement dieser Struktur entweder auf CONNECT_FULLY_SPECIFIED oder CONNECT_LINE_BASED fest. Wenn Version = CONNECT_FULLY_SPECIFIED, legen Sie das Irql-Element auf PASSIVE_LEVEL, das SynchronizeIrql-Element auf PASSIVE_LEVEL und das SpinLock-Element auf NULL fest. Wenn Version = CONNECT_LINE_BASED, legen Sie SynchronizeIrql = PASSIVE_LEVEL und SpinLock = NULL fest.

Wenn das Interruptobjekt einen ISR auf passiver Ebene angibt, verwendet die KeSynchronizeExecution-Routine ein Kernelsynchronisierungsereignisobjekt anstelle einer Spinsperre, um die Ausführung der SynchCritSection-Routine mit dem ISR zu synchronisieren.

Dieses Ereignisobjekt wird von der IoConnectInterruptEx-Routine in dem Aufruf zugeordnet, der den ISR auf passiver Ebene registriert. Der Aufrufer darf in diesem Aufruf keine Drehsperre bereitstellen. (Das heißt, der Aufrufer muss das SpinLock-Element der IO_CONNECT_INTERRUPT_PARAMETERS-Struktur auf NULL festlegen, wenn der ISR auf passiver Ebene ausgeführt werden soll.) Andernfalls schlägt IoConnectInterruptEx fehl und gibt fehler status STATUS_INVALID_PARAMETER zurück.

Die Routinen KeAcquireInterruptSpinLock und KeReleaseInterruptSpinLock verursachen eine Fehlerüberprüfung, wenn der ISR für das angegebene Interruptobjekt mit IRQL = PASSIVE_LEVEL ausgeführt wird.

Geräte, die Passive-Level Interrupt-Behandlung erfordern

Bei einem speicherseitig zugeordneten Gerät, das eine pegelgesteuerte Interruptanforderung signalisiert, wird der ISR des Geräts normalerweise über DIRQL aus dem Interrupt-Trap-Handler des Kernels aufgerufen. Der ISR bearbeitet die Hardwareregister im Gerät, um den Interrupt zu deaktivieren.

Ein ISR muss jedoch möglicherweise unter IRQL = PASSIVE_LEVEL ausgeführt werden, wenn das zugeordnete Gerät eine pegelgesteuerte Interruptanforderung signalisiert, auf die Hardwareregister des Geräts jedoch nicht direkt von einer ISR aus zugegriffen werden kann, die über DIRQL aus dem Interrupt-Trap-Handler des Kernels aufgerufen wird. Beispielsweise sind die Geräteregister möglicherweise nicht speicherseitig zugeordnet, oder der ISR wird während eines Registrierungszugriffs vorübergehend blockiert.

Ab Windows 8 kann ein Treiber einen ISR auf passiver Ebene registrieren. Wenn der Interrupt auftritt, plant der Interrupt-Trap-Handler des Kernels die Ausführung des ISR bei IRQL = PASSIVE_LEVEL. Bevor der Handler zurückgibt, muss er den Interrupt im Interruptcontroller (oder GPIO-Controller) zum Schweigen bringen. Wenn ein Gerät einen vom Rand ausgelösten Interrupt signalisiert, löscht der Handler den Interrupt im Interruptcontroller. Wenn das Gerät einen pegelgesteuerten Interrupt signalisiert, maskiert der Handler den Interrupt vorübergehend im Interruptcontroller. nachdem der ISR ausgeführt wurde, entlarmt der Kernel den Interrupt.

Beispiel

Ein Beispiel für ein Gerät, das eine ISR auf passiver Ebene erfordert, ist ein Sensorgerät, das mit einem seriellen Bus mit geringer Leistung verbunden ist, z. B. I²C. Ab Windows 8 wird die Unterstützung für I²C und für andere einfache Peripheriebusse (SPBs) durch die SPB-Frameworkerweiterung (SpbCx) bereitgestellt.

Um auf die Register des mit I²C verbundenen Sensorgeräts zuzugreifen, sendet der Sensortreiber dem Sensorgerät eine E/A-Anforderung, die von SpbCx und dem Controllertreiber für den Bus gemeinsam bearbeitet wird. Zum Ausführen des angeforderten Vorgangs muss der SPB-Controller Daten seriell über den Bus übertragen. Diese Übertragung erfolgt relativ langsam und kann nicht innerhalb der Zeiteinschränkungen einer ISR ausgeführt werden, die bei DIRQL ausgeführt wird. Ein ISR auf passiver Ebene kann die E/A-Anforderung jedoch synchron senden und dann blockieren, bis die Anforderung abgeschlossen ist.

Der ISR auf passiver Ebene in diesem Beispiel kann für längere Zeit blockiert werden, wenn der I²C-Buscontroller deaktiviert ist, wenn der ISR die E/A-Anforderung an das unterbrechende Gerät sendet. In diesem Fall muss der Controller den Übergang zum D0-Energiezustand abschließen, bevor er die Daten über den Bus übertragen kann.

Im Gegensatz zu einem Bus wie PCI bietet der I²C-Bus in diesem Beispiel keine busspezifischen Mittel, um Interruptanforderungen von Peripheriegeräten an den Prozessor zu übermitteln. Stattdessen kann das Sensorgerät einen Interrupt an einen Pin an einem GPIO-Controllergerät signalisieren, wodurch die Interruptanforderung dann an den Prozessor weitergeleitet wird. Weitere Informationen finden Sie unter GPIO-Interrupts.

In der Regel sind die Hardwareregister eines GPIO-Controllers speicherseitig zugeordnet und können unter DIRQL vom Interrupt-Trap-Handler des Kernels zugegriffen werden. Wenn das Sensorgerät einen Interrupt verursacht, muss der Handler den Interrupt beenden, indem er die Interruptbits in den Registern des GPIO-Controllers manipuliert.

Bei einem leveltriggerten Interrupt maskiert der Interrupt-Trap-Handler des Kernels die Interruptanforderung am GPIO-Pin und plant dann die Ausführung des ISR des Sensorgeräts auf passiver Ebene. Der ISR muss die Interruptanforderung vom Sensorgerät löschen. Nachdem der ISR zurückgegeben wurde, entlarmt der Kernel die Interruptanforderung am GPIO-Pin.

Bei einem durch Edge ausgelösten Interrupt löscht der Trap-Handler des Kernels die Interruptanforderung am GPIO-Pin und plant dann die Ausführung des ISR des Sensorgeräts auf passiver Ebene.

Workerroutinen

Beim Aufruf von IoConnectInterruptEx hat ein Treiber die Möglichkeit, die Verarbeitung des Interrupts zwischen einer passiven ISR-Instanz und einer Workerroutine aufzuteilen. In der Regel sollte der ISR die anfängliche Verarbeitung des Interrupts durchführen (z. B. einen von der Ebene ausgelösten Interrupt zum Stummstellen) und die zusätzliche Verarbeitung für den Worker zurückstellen. Obwohl sowohl die ISR als auch der Worker auf passiver Ebene ausgeführt werden, wird die ISR mit einer relativ hohen Priorität ausgeführt und kann andere Aufgaben mit hoher Priorität verzögern. Diese Aufgaben können ISRs auf passiver Ebene für neue Interrupts enthalten.

In seltenen Fällen erfordert ein Interrupt möglicherweise so wenig Verarbeitung, dass der ISR auf passiver Ebene die gesamte Verarbeitung für den Interrupt ausführen kann, und keine Workerroutine erforderlich ist.

Informationen zur Verwendung von ISRs auf passiver Ebene in KMDF-Treibern finden Sie unter Unterstützen Passive-Level Interrupts.