ControllerControl-Routineanforderungen
Wie der Name schon sagt, ist eine ControllerControl-Routine einem Controllerobjekt zugeordnet. Wenn die ControllerControl-Routine ausgeführt wird, ist die durch das Controllerobjekt dargestellte Hardware frei, und auf die Controllererweiterung wird in der Regel nicht von einer anderen Treiberroutine zugegriffen, es sei denn, die Controllererweiterung enthält Kontext, der für die ISR des Treibers freigegeben wird.
In der Regel führt eine ControllerControl-Routine mindestens Folgendes aus:
Updates oder initialisiert den Kontext, den der Treiber in der Geräteerweiterung des Zielgeräteobjekts und in der Controllererweiterung verwaltet.
Wenn der Treiber DMA verwendet, ist seine ControllerControl-Routine in der Regel dafür verantwortlich, zu bestimmen, ob eine bestimmte Übertragungsanforderung aufgrund von systembedingten oder gerätebedingten Einschränkungen für die Größe der einzelnen DMA-Übertragungen in Teilübertragungen aufgeteilt werden muss. Unter diesen Umständen ist die ControllerControl-Routine auch für den Aufruf von AllocateAdapterChannel zuständig, wenn der Treiber über eine AdapterControl-Routine verfügt.
Wenn der Treiber PIO verwendet, ist seine ControllerControl-Routine auch für das Aufteilen von Übertragungsanforderungen in Teilübertragungsbereiche und für den Aufruf von MmGetSystemAddressForMdlSafe mit der MDL unter Irp-MdlAddress> verantwortlich.
Programmiert die Hardware für den angeforderten E/A-Vorgang
Wenn über den ISR auf das Gerät oder die Controllererweiterung zugegriffen werden kann, muss die ControllerControl-Routine eine SynchCritSection-Routine verwenden, die durch Aufrufen von KeSynchronizeExecution aufgerufen wird. Weitere Informationen finden Sie unter Verwenden kritischer Abschnitte.
Wenn der Treiber über eine Cancel-Routine verfügt, muss seine ControllerControl-Routine auch das Irp-Cancel-Feld> überprüfen, um zu bestimmen, ob die aktuelle IRP abgebrochen werden soll, und führen Sie eine der folgenden Aktionen aus:
Wenn Irp-Cancel> auf TRUE festgelegt ist, muss die ControllerControl-Routine die folgenden Aktionen ausführen:
Legen Sie STATUS_CANCELLED für Status und null für Informationen im E/A-status-Block des IRP fest.
Rufen Sie IoFreeController auf, um das Controllerobjekt freizugeben, damit der nächste Gerätevorgang sofort gestartet werden kann.
Rufen Sie IoStartNextPacket auf , oder entfernen Sie die nächste IRP, wenn der Treiber eine eigene Warteschlange verwaltet.
Schließen Sie die abgebrochene IRP mit IoCompleteRequest ab, und geben Sie die Steuerung zurück.
Wenn Irp-Cancel> nicht auf TRUE festgelegt ist, muss die ControllerControl-Routine stattdessen die folgenden Aktionen ausführen:
Rufen Sie IoSetCancelRoutine auf , um den Routineeinstiegspunkt Abbrechen für den IRP auf NULL zurückzusetzen. Rufen Sie die Abbruchsperre für diesen Aufruf ab, wenn der Treiber die vom E/A-Manager bereitgestellte Gerätewarteschlange im Geräteobjekt verwendet.
Programmieren Sie die Hardware für den angeforderten E/A-Vorgang mithilfe einer SynchCritSection-Routine , die durch Aufrufen von KeSynchronizeExecution aufgerufen wird. Weitere Informationen finden Sie unter Verwenden kritischer Abschnitte.
Weitere Informationen zum Behandeln abbrechbarer IRPs finden Sie unter Abbrechen von IRPs.
Bei den meisten interruptgesteuerten E/A-Vorgängen mit Ausnahme von überlappenden Vorgängen auf verschiedenen Geräten, die an den physischen Controller/Adapter angefügt sind, sollte eine ControllerControl-RoutineKeepObject zurückgeben, da die DpcForIsr - oder CustomDpc-Routine den Vorgang und die IRP abgeschlossen.
Sobald die E/A-Vorgänge zur Erfüllung der aktuellen Anforderung abgeschlossen sind, sollte die Routine, mit der das IRP abgeschlossen wird, IoFreeController und IoStartNextPacket aufrufen, damit die nächste Anforderung so schnell wie möglich verarbeitet werden kann.
Wenn die ControllerControl-Routine selbst ein IRP abschließt oder wenn sie einen Vorgang, z. B. eine Datenträgersuche, für ein Zielgeräteobjekt (Datenträger) einrichten kann, das mit einem Vorgang für ein anderes Geräteobjekt überlappen könnte, sollte die ControllerControl-RoutineDeallocateObject zurückgeben.