Schreiben von DPC-Routinen
Die Hauptverantwortung von DpcForIsr - und CustomDpc-Routinen besteht darin, sicherzustellen, dass der nächste Geräte-E/A-Vorgang umgehend gestartet und die aktuelle IRP abgeschlossen wird.
Zusätzliche Arbeit, die von jeder DpcForIsr - oder CustomDpc-Routine ausgeführt wird, hängt vom Design des Treibers und der Art des Geräts ab. Eine DpcForIsr - oder CustomDpc-Routine kann beispielsweise auch eine der folgenden Aktionen ausführen:
Wiederholen Sie einen Vorgang, bei dem ein Timeout aufgetreten ist oder ein Fehler aufgetreten ist.
Rufen Sie IoAllocateErrorLogEntry auf, richten Sie ein Fehlerprotokollpaket ein, um einen Geräte-E/A-Fehler zu melden, und rufen Sie IoWriteErrorLogEntry auf.
Weitere Informationen zur Behandlung von E/A-Fehlern finden Sie unter Protokollierungsfehler.
Wenn der Treiber gepufferte E/A verwendet oder der IRP einen Gerätesteuerungsvorgang angibt, übertragen Sie die vom Gerät eingelesenen Daten an den Systempuffer bei Irp-AssociatedIrp.SystemBuffer>, bevor Sie die IRP abschließen.
Wenn der Treiber direkte E/A verwendet und große Übertragungen in kleinere Teile aufteilen muss, speichern Sie den Zustand für jeden gerade abgeschlossenen Teilübertragungsvorgang, berechnen Sie den nächsten Teilübertragungsbereich, und verwenden Sie eine vom Treiber bereitgestellte SynchCritSection-Routine , um das Gerät für den nächsten Teilübertragungsvorgang zu programmieren.
Selbst ein Treiber, der gepufferte E/A verwendet, muss möglicherweise eine Übertragungsanforderung aufteilen, wenn sein Gerät über eingeschränkte Übertragungsfunktionen verfügt.
Wenn der Treiber paketbasiertes DMA verwendet, rufen Sie nach jedem Geräteübertragungsvorgang FlushAdapterBuffers auf, und rufen Sie FreeAdapterChannel oder FreeMapRegisters auf, wenn eine Sequenz von Teilübertragungen ausgeführt wird und die vollständige Übertragungsanforderung erfüllt ist.
Wenn eine angeforderte Übertragung nur teilweise durch einen einzelnen DMA-Vorgang erfüllt wird, ist die DpcForIsr - oder CustomDpc-Routine in der Regel für die Einrichtung eines oder mehrerer DMA-Vorgänge verantwortlich, bis die vom IRP angegebene Anzahl von Bytes vollständig übertragen wurde.
Weitere Informationen zur Verwendung von DMA finden Sie unter Adapterobjekte und DMA.
Wenn der Treiber programmierte E/A (PIO) verwendet, rufen Sie KeFlushIoBuffers am Ende jedes Übertragungsvorgangs auf, wenn der aktuelle IRP einen Lesevorgang anfordert.
Wenn eine angeforderte Übertragung nur teilweise durch einen einzelnen PIO-Vorgang erfüllt wird, ist die DpcForIsr - oder CustomDpc-Routine normalerweise für das Einrichten eines oder mehrerer Übertragungsvorgänge verantwortlich, bis die vom IRP angegebene Anzahl von Bytes vollständig übertragen wurde.
Weitere Informationen zur Verwendung von PIO finden Sie unter Using Direct E/O( Using Direct E/O).
Wenn ein Nicht-WDM-Treiber über eine ControllerControl-Routine verfügt, rufen Sie IoFreeController auf, wenn ein angeforderter Vorgang abgeschlossen ist.
Beachten Sie, dass eine DpcForIsr - oder CustomDpc-Routine normalerweise den größten Teil der Geräte-E/A-Verarbeitung des Treibers ausführt, um IRPs zu erfüllen. Diese Routinen teilen sich auch einen Teil der Verantwortung für das Anstehen von IRPs für das Gerät mit den Dispatchroutinen des Fahrers.
Beachten Sie die folgenden allgemeinen Entwurfsrichtlinien.
Jede DpcForIsr - oder CustomDpc-Routine sollte IoStartNextPacket aufrufen, sobald sie diesen Aufruf sicher tätigen kann: Das heißt, ohne möglicherweise einen Ressourcenkonflikt oder eine Rennbedingung mit der StartIo-Routine des Fahrers oder mit einer anderen Routine zu verursachen, die die StartIo-Routine verursacht.
Wenn ein Treiber seine eigene Warteschlangen von IRPs verwaltet, sollte seine DpcForIsr - oder CustomDpc-Routine den Treiber benachrichtigen, sobald es sicher ist, die nächste IRP zu entfernen und das Gerät für die nächste Anforderung einzurichten.
Eine DpcForIsr - oder CustomDpc-Routine muss IoStartNextPacket aufrufen oder die entsprechende Treiberroutine anderweitig benachrichtigen, wenn die Geräte-E/A-Verarbeitung für die nächste Anforderung gestartet werden kann. Je nach Treiber und Gerät kann dies vor abschluss der aktuellen IRP-Routine mit IoCompleteRequest durch die DpcForIsr- oder CustomDpc-Routine erfolgen, oder es kann unmittelbar vor abschluss der aktuellen IRP auftreten und die Steuerung zurückgibt.