Senden verketteter MDL-Strukturen
In diesem Artikel werden die Funktionen für verkettete MDLs im USB-Treiberstapel beschrieben und beschrieben, wie ein Clienttreiber einen Übertragungspuffer als Kette von MDL-Strukturen senden kann.
Die meisten USB-Hostcontroller erfordern, dass der Übertragungspuffer praktisch zusammenhängend ist. Praktisch zusammenhängend bedeutet, dass der Puffer an einer beliebigen Stelle auf einer Seite beginnen und enden kann, aber der Rest des Puffers muss auf einer Seitengrenze beginnen und enden. Viele USB-Clienttreiber können diese Anforderung erfüllen. Für bestimmte Clienttreiber, insbesondere solche, die dem Puffer zusätzliche Daten hinzufügen oder daraus entfernen müssen, ist die Zuweisung von praktisch zusammenhängendem Arbeitsspeicher für den Übertragungspuffer jedoch nicht vorzuziehen.
Betrachten Sie beispielsweise einen Netzwerkstapel mit drei Treibern, einem Netzwerkprotokolltreiber, einem Zwischentreiber und einem Miniporttreiber. Der Protokolltreiber initiiert eine Übertragung und sendet ein Paket an den nächsten Treiber im Stapel: den Zwischentreiber. Der Zwischentreiber möchte dem Paket einen benutzerdefinierten Header (in einem separaten Speicherblock enthalten) hinzufügen. Der Zwischentreiber sendet diesen Header und das empfangene Paket an den nächsten Treiber im Stapel: den Miniporttreiber. Der Miniporttreiber verbindet sich mit dem USB-Treiberstapel und muss daher einen nahezu zusammenhängenden Übertragungspuffer vorbereiten. Um einen solchen Puffer zu erstellen, ordnet der Miniporttreiber einen großen Puffer zu, fügt den benutzerdefinierten Header hinzu und kopiert dann die Nutzlast. Da die Nutzlast in der Regel groß ist, kann das Kopieren der gesamten Nutzlast erhebliche Auswirkungen auf die Leistung haben.
Der Clienttreiber kann diese Auswirkungen auf die Leistung überwinden, indem er den Übertragungspuffer als Eine Kette von Speicherdeskriptorlisten (MDLs) sendet. Der neue USB-Treiberstapel in Windows 8 kann eine verkettete MDL (siehe MDL) vom Clienttreiber akzeptieren. Durch die Bereitstellung einer verketteten MDL kann der Clienttreiber auf nicht zusammenhängende Seiten im Arbeitsspeicher verweisen, anstatt überflüssige Kopiervorgänge auszuführen. Die Funktion entfernt Einschränkungen in Bezug auf Anzahl, Größe und Ausrichtung von Puffern, sodass der Übertragungspuffer im physischen Arbeitsspeicher segmentiert werden kann.
Um verkettete MDLs zu verwenden, muss der Clienttreiber erkennen, ob der zugrunde liegende USB-Treiberstapel, der von Windows geladen wird, die Funktion unterstützt, und dann eine Kette von MDLs in einer ordnungsgemäßen Reihenfolge erstellen.
Vorbereitung
Die verkettete MDL-Funktion wird nur für Massenübertragungen, isochrone Übertragungen und Unterbrechungen unterstützt. Bevor Sie die verkettete MDL-Funktion abfragen, stellen Sie sicher, dass Ihr Clienttreiber über ein USBD-Handle für die Treiberregistrierung beim USB-Treiberstapel verfügt. Rufen Sie USBD_CreateHandle auf, um ein USBD-Handle zu erstellen. In der Regel erstellt der Clienttreiber das USBD-Handle in seiner AddDevice-Routine .
Sie können die verkettete MDL-Funktion im IRP_MN_START_DEVICE-Handler des Clienttreibers oder jederzeit später abfragen. Der Clienttreiber darf diese Funktion nicht in seiner AddDevice-Routine abfragen.
Anweisungen
Rufen Sie die USBD_QueryUsbCapability-Routine auf, um zu ermitteln, ob der USB-Treiberstapel die Funktion für verkettete MDLs unterstützt. Um diese Funktion abzufragen, geben Sie UsbCapabilityChainedMdls als GUID an. Legen Sie den OutputBuffer-Parameter auf NULL und den OutputBufferSize-Parameter auf 0 fest.
Überprüfen Sie den NTSTATUS-Wert, der von USBD_QueryUsbCapability zurückgegeben wird, und werten Sie das Ergebnis aus. Wenn die Routine erfolgreich abgeschlossen wird, wird die Funktion für verkettete MDLs unterstützt. Jeder andere Wert gibt an, dass die Funktion nicht unterstützt wird.
Erstellen Sie die Kette von MDLs. Jede MDL verfügt über einen Next-Zeiger , der auf eine andere MDL zeigt.
Der Treiber kann eine MDL-Kette erstellen, indem er den Zeiger Weiter manuell festlegt.
Im vorherigen Beispiel sendet der Protokolltreiber das Paket als MDL. Der Zwischentreiber kann eine weitere MDL erstellen, die mit den Headerdaten auf den Speicherblock verweist. Um eine Kette zu erstellen, kann der Zwischentreiber den MDL-Zeiger des Header-MDL auf die vom Protokolltreiber empfangene MDL zeigen. Der Zwischentreiber kann dann die Kette von zwei MDLs an den Miniporttreiber weiterleiten, der einen Verweis auf die verkettete MDL in der URB für die Anforderung bereitstellt und die Anforderung an den USB-Treiberstapel übermittelt. Weitere Informationen finden Sie unter Verwenden von MDLs.
Legen Sie beim Erstellen einer URB für eine E/A-Anforderung, die verkettete MDLs verwendet, den TransferBufferMDL-Member der zugeordneten URB-Struktur (z. B. _URB_BULK_OR_INTERRUPT_TRANSFER oder _URB_ISOCH_TRANSFER) auf die erste MDL in der Kette fest, und legen Sie TransferBufferLength auf die Gesamtzahl der zu übertragenden Bytes fest. Die Daten umfassen möglicherweise mehr als einen MDL-Eintrag in der MDL-Kette.
In Windows 8 wurden zwei neue Typen von URB-Funktionen hinzugefügt, die es einem Clienttreiber ermöglichen, verkettete MDLs für Datenübertragungen zu verwenden. Wenn Sie diese Funktion verwenden möchten, stellen Sie sicher, dass das Element Function des URB-Headers auf eine der folgenden URB-Funktionen festgelegt ist:
- URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER_USING_CHAINED_MDL
- URB_FUNCTION_ISOCH_TRANSFER_USING_CHAINED_MDL
Informationen zu diesen URB-Funktionen finden Sie unter _URB_HEADER.
Hinweise
Ein Codebeispiel, das den zugrunde liegenden USB-Treiberstapel abfragt, um zu bestimmen, ob der Treiberstapel verkettete MDLs akzeptieren kann, finden Sie unter USBD_QueryUsbCapability.