E/A-Übertragungssequenzen

Die SPB-Frameworkerweiterung (SpbCx) unterstützt E/A-Übertragungssequenzen. Eine E/A-Übertragungssequenz ist eine geordnete Gruppe von Busübertragungen (Lese- und Schreibvorgänge), die als einzelner Atombusvorgang ausgeführt wird. Alle Übertragungen in einer E/A-Übertragungssequenz greifen auf dasselbe Zielgerät auf dem Bus zu. Während eine Sequenz ausgeführt wird, kann auf keine anderen Geräte im Bus zugegriffen werden, auch wenn der SPB-Controllertreiber möglicherweise E/A-Anforderungen für andere Geräte empfängt, bevor die E/A-Übertragungssequenz abgeschlossen ist.

Ein Beispiel für eine E/A-Übertragungssequenz ist ein Schreib-/Lesevorgang, bei dem es sich um einen Busschreibvorgang gefolgt von einem Buslesevorgang handelt. Ein Clientperipheriegerätetreiber kann diesen Sequenztyp verwenden, um in ein Funktionsauswahlregister in einem mit SPB verbundenen Peripheriegerät zu schreiben und dann den Wert der ausgewählten Gerätefunktion zu lesen. Diese beiden Übertragungen können unterschiedlich lang sein. Beispielsweise kann der Schreibvorgang ein Byte von Daten übertragen, und der Lesevorgang kann viele Bytes an Daten übertragen.

Typen von E/A-Übertragungssequenzen

Ein Client kann eine E/A-Übertragungssequenz auf eine der folgenden Arten initiieren:

  1. Der Client kann die gesamte Sequenz in einer IOCTL_SPB_EXECUTE_SEQUENCE E/A-Steuerungsanforderung angeben. Mit dieser Anforderung kann der SPB-Controllertreiber alle verfügbaren hardwarespezifischen Leistungsoptimierungen verwenden, um die Übertragungssequenz auszuführen. Weitere Informationen finden Sie unter Einzelanforderungssequenzen.

  2. Der Client kann eine IOCTL_SPB_LOCK_CONTROLLER E/A-Steuerungsanforderung senden, um den Controller am Anfang einer Sequenz zu sperren, und eine IOCTL_SPB_UNLOCK_CONTROLLER senden, wenn die Sequenz abgeschlossen ist. Während der Controller gesperrt ist, sendet der Client für jeden Lese- oder Schreibvorgang in der Sequenz eine separate E/A-Anforderung (IRP_MJ_READ oder IRP_MJ_WRITE). Weitere Informationen finden Sie unter Vom Client implementierte Sequenzen.

Wenn möglich, sollte ein Client die IOCTL_SPB_EXECUTE_SEQUENCE-Anforderung verwenden, die schneller ist, weniger fehleranfällig ist und die Zeit, in der andere Clients aus dem Bus gesperrt sind, erheblich verkürzt. Ein Client kann jedoch die IOCTL_SPB_LOCK_CONTROLLER und IOCTL_SPB_UNLOCK_CONTROLLER Anforderungen verwenden, wenn er den Wert betrachten muss, der während einer der Übertragungen in der Sequenz gelesen wird, bevor er eine spätere Übertragung in der Sequenz initiieren kann. In diesem Fall ist ein sorgfältiger Entwurf erforderlich, um zu vermeiden, dass andere Clients länger als erforderlich aus dem Bus gesperrt werden, und ein schlecht entworfener Peripherietreiber kann die Gesamtleistung des Systems beeinträchtigen.

Single-Request Sequenzen

Um die Leistung zu verbessern, sollte Ihr SPB-Controllertreiber eine EvtSpbControllerIoSequence-Rückruffunktion implementieren, um IOCTL_SPB_EXECUTE_SEQUENCE Anforderungen zu verarbeiten. Dieser Ansatz erhöht die Komplexität des SPB-Controllertreibers, verhindert jedoch, dass der Client eine E/A-Übertragungssequenz als eine Reihe einzelner Lese- und Schreibvorgänge ausführen muss, während andere Clients vom Bus ausgeschlossen sind.

Hinweis

Die Implementierung einer EvtSpbControllerIoSequence-Funktion wird dringend empfohlen und kann zu einer Voraussetzung für Windows 8 werden.

Die Implementierung einer Übertragungssequenz ähnelt der eines einfachen Lese- oder Schreibvorgangs, erfordert jedoch zusätzlich Aktualisierungen des gespeicherten Zustands des Sequenzvorgangs zwischen den einzelnen Übertragungen in der Sequenz. Nach Abschluss der ersten Übertragung aktualisiert der SPB-Controllertreiber den Sequenzzustand, um die nächste Übertragung in der Sequenz auszuwählen. Der Sequenzzustand wird im Gerätekontext gespeichert und enthält das SPBREQUEST-Handle , das an den EvtSpbControllerIoSequence-Rückruf übergeben wird. Der SPB-Controllertreiber verwendet dieses Handle, um die Puffer-, Längen-, Richtungs- und Positionsparameter für die einzelnen Übertragungen in der Sequenz abzurufen. Weitere Informationen zum Abrufen dieser Parameter finden Sie unter SpbRequestGetTransferParameters.

Wenn der SPB-Controllertreiber den angeforderten IOCTL_SPB_EXECUTE_SEQUENCE Vorgang nicht ausführen kann, schließt er die Anforderung mit einem Fehlercode ab. Wenn ein solcher Fehler auftritt, kann der Client den Bus optional sperren, die E/A-Übertragungssequenz explizit als eine Reihe einfacher E/A-Anforderungen ausführen und dann den Bus entsperren. Weitere Informationen finden Sie unter Vom Client implementierte Sequenzen.

SpbCx führt die Parameterüberprüfung für IOCTL_SPB_XXX-Anforderungen durch, die es von Peripheriegerätetreibern empfängt. Bei IOCTL_SPB_EXECUTE_SEQUENCE Anforderungen lehnt SpbCx sowohl leere Sequenzen als auch Sequenzen ab, die NULL-Pufferzeiger oder Puffer der Länge null enthalten.

Der SPB-Controllertreiber sollte überprüfen, ob die Länge jeder Übertragung in einer Sequenz den vom Treiber angegebenen Grenzwert nicht überschreitet. Beispielsweise schlägt der SkeletonI2C-Beispieltreiber im Windows Driver Kit (WDK) eine IOCTL_SPB_EXECUTE_SEQUENCE-Anforderung fehl, die eine Übertragung über 4K Bytes angibt, und legt den Statuscode für diese Anforderung auf STATUS_INVALID_PARAMETER fest. Vor dem Initiieren eines Sequenzvorgangs für eine IOCTL_SPB_EXECUTE_SEQUENCE-Anforderung sollte der Treiber die Parameter für alle Übertragungen in der Sequenz überprüfen, um sicherzustellen, dass der Vorgang erfolgreich abgeschlossen werden kann.

SpbCx geht nie einem EvtSpbControllerIoSequence-Rückruf mit einem EvtSpbControllerLock-Rückruf voran und folgt nie einem EvtSpbControllerIoSequence-Rückruf mit einem EvtSpbControllerUnlock-Rückruf .

Client-Implemented Sequenzen

Ein Client eines SPB-Controllertreibers kann explizit eine E/A-Übertragungssequenz als eine Reihe einfacher Lese- und Schreibvorgänge ausführen. Der Client kann entweder ein Kernelmodustreiber oder ein Benutzermodustreiber sein, der ein Peripheriegerät steuert, das an den Bus angefügt ist. Vor der ersten Übertragung in der Sequenz sendet der Client eine IOCTL_SPB_LOCK_CONTROLLER-Anforderung an das Zielgerät, um zu verhindern, dass andere, nicht verbundene Buszugriffe zwischen den Übertragungen in der Sequenz stattfinden. Als Nächstes sendet der Client IRP_MJ_READ - und IRP_MJ_WRITE-Anforderungen , um die Übertragungen in der Sequenz durchzuführen. Schließlich sendet der Client eine IOCTL_SPB_UNLOCK_CONTROLLER Anforderung zum Freigeben der Sperre.

Ein Client muss möglicherweise diese Art von E/A-Übertragungssequenz implementieren, wenn eine spätere Übertragung in der Sequenz eine Abhängigkeit von einer früheren Übertragung aufweist. Beispielsweise kann der erste Lesevorgang angeben, wie viele weitere Bytes später gelesen oder geschrieben werden sollen. Wenn jedoch keine solche Abhängigkeit vorhanden ist, sollte der Client eine IOCTL_SPB_EXECUTE_SEQUENCE Anforderung an den SPB-Controllertreiber senden, der die Sequenz effizienter ausführen kann.

Zwischen der IOCTL_SPB_LOCK_CONTROLLER Anforderung, die eine vom Client implementierte Sequenz startet, und der IOCTL_SPB_UNLOCK_CONTROLLER Anforderung, die die Sequenz beendet, sind die einzigen E/A-Anforderungen, die der Client an das Zielgerät senden kann, IRP_MJ_READ und IRP_MJ_WRITE Anforderungen. Jeder Verstoß gegen diese Regel ist ein Fehler.

SPB-Sperren werden nur verwendet, um zu gewährleisten, dass eine Sequenz von Lese- und Schreibvorgängen als atomischer Busvorgang ausgeführt wird und ausschließlich für diesen Zweck verwendet werden sollte.

Weitere Informationen finden Sie unter Behandeln Client-Implemented Sequenzen.