Freigeben über


Verwenden der MapTransferEx-Routine

Die MapTransferEx-Routine initialisiert einen Satz zuvor zugeordneter DMA-Ressourcen und startet eine DMA-Übertragung. Diese Routine ist in Version 3 der DMA-Betriebsschnittstelle verfügbar. Version 3 dieser Schnittstelle wird ab Windows 8 unterstützt. Weitere Informationen zur DMA-Betriebsschnittstelle finden Sie unter DMA_OPERATIONS.

Vergleich von MapTransferEx mit MapTransfer

MapTransferEx ist eine verbesserte Version der MapTransfer-Routine . MapTransfer ist ab Version 1 in Windows 2000 in allen Versionen der DMA-Betriebsschnittstelle verfügbar. Ein Aufruf von MapTransfer kann einen zusammenhängenden Block des physischen Arbeitsspeichers einer MDL zuordnen. Der Datenpuffer für eine komplexe DMA-Übertragung kann jedoch durch eine MDL-Kette beschrieben werden, und jede MDL in der Kette kann mehrere Blöcke mit physisch zusammenhängendem Arbeitsspeicher beschreiben. Um mapTransfer zum Übertragen eines solchen Puffers zu verwenden, muss ein Treiber viele Aufrufe an MapTransfer tätigen. In der Regel werden diese Aufrufe innerhalb eines Paars geschachtelter Schleifen ausgeführt. Die innere Schleife durchlaufen von einem Block zusammenhängenden physischen Arbeitsspeichers zum nächsten in jeder MDL, und die äußere Schleife durchlaufen von einer MDL zur nächsten in der MDL-Kette.

Im Gegensatz dazu kann ein Aufruf von MapTransferEx den gesamten Datenpuffer für eine komplexe DMA-Übertragung übertragen. Die folgenden drei MapTransferEx-Parameter beschreiben den Pufferspeicher, der für die Übertragung verwendet werden soll.

Parameter BESCHREIBUNG
Mdl

Ein Zeiger auf die erste MDL in einer Kette von mindestens einer MDLs. Weitere Informationen zu MDL-Ketten finden Sie unter Verwenden von MDLs.

Offset

Der Byteoffset des Puffers vom Anfang des Arbeitsspeichers, der von der MDL-Kette beschrieben wird.

Länge

Ein Zeiger auf einen Speicherort, der die Länge des Datenpuffers in Bytes enthält.

Zu Beginn eines MapTransferEx-Aufrufs wird die MapTransferEx-Routine durch die MDL-Kette ausgeführt, um den Start des Puffers zu ermitteln. Der Start des Puffers wird durch den Offset-Parameter angegeben. Als Nächstes erstellt MapTransferEx vom Anfang des Puffers bis zum Ende eine Scatter/Gather-Liste, in der jedes Pufferfragment in der Liste ein physisch zusammenhängender Speicherblock aus der MDL-Kette ist. Um diese Liste zu erstellen, führt MapTransferEx schritte von einem physisch zusammenhängenden Speicherblock in jeder MDL zum nächsten und von einer MDL zur nächsten in der MDL-Kette. Die Listenerstellung wird abgeschlossen, wenn die gesamt durch die Scatter/Gather-Liste beschriebene Pufferspeichermenge der Anzahl von Bytes entspricht, die durch den Eingabeparameter *Length angegeben wird. Die Reihenfolge der Pufferfragmente in der resultierenden Scatter/Gather-Liste entspricht der Reihenfolge der physisch zusammenhängenden Blöcke in der MDL-Kette.

Mehrere Aufrufe von MapTransferEx

MapTransferEx kann möglicherweise nicht immer einen gesamten DMA-Datenpuffer in einem Aufruf übertragen. In der folgenden Liste werden einige der Bedingungen beschrieben, die möglicherweise erfordern, dass MapTransferEx mehr als einmal aufgerufen wird, um die Übertragung abzuschließen:

  • Der DMA-Adapter erfordert Kartenregister, und die Anzahl der Kartenregister, die dem Adapter zugewiesen sind, reicht nicht aus, um den gesamten Puffer zu beschreiben.
  • Der vom Treiber zugewiesene Speicher, der die Scatter/Gather-Liste enthält, ist nicht groß genug, um die Scatter-/Gather-Liste für den gesamten Puffer zu enthalten.
  • Die Übertragung verwendet einen System-DMA-Controller, der die Anzahl der Pufferfragmente einschränkt, die in einer Hardware scatter/gather-Liste angegeben werden können.

In all diesen Fällen ordnet MapTransferEx so viel Datenpuffer wie möglich in einem Aufruf zu und teilt dem Treiber mit, wie viel des Puffers durch den Aufruf zugeordnet wurde. Die obige Liste enthält keine anderen Bedingungen, z. B. plattformspezifisches Cacheverhalten, für die möglicherweise mehrere Aufrufe von MapTransferEx erforderlich sind, um eine Übertragung abzuschließen. Zukünftige Hardwareplattformen können zusätzliche Einschränkungen für die DMA-Übertragungslänge auferlegen. Aus diesen Gründen sollten Treiberentwickler ihre Treiber so entwerfen, dass sie den Fall richtig behandeln, in dem MapTransferEx keinen gesamten DMA-Datenpuffer in einem Aufruf zuordnen kann.

Vor dem Aufruf von MapTransferEx legt der Aufrufer den *Length-Parameter auf die Anzahl von Bytes im DMA-Datenpuffer fest, die noch zugeordnet werden müssen. Vor der Rückgabe legt MapTransferEx *Length auf die Anzahl der Bytes im Puffer fest, die tatsächlich vom Aufruf zugeordnet wurden. Wenn ein MapTransferEx-Aufruf nicht die gesamte Pufferlänge zuordnen kann, wie durch den *Length-Eingabewert angegeben, ist der Ausgabewert von *Length kleiner als sein Eingabewert. Wenn eine DMA-Übertragung mindestens zwei MapTransferEx-Aufrufe erfordert, muss der aufrufende Treiber den *Length-Ausgabewert von einem Aufruf abrufen, bevor er den *Length-Eingabewert für den nächsten Aufruf angeben kann.

Wenn beispielsweise ein MapTransferEx-Aufruf nur X-Bytes an oder aus einem Puffer übertragen kann, für den Offset = B und *Length = N (bei eingabe) verwendet wird, dann wird bei der Rückgabe *Length = X verwendet. Für den nächsten Aufruf von MapTransferEx sollte der Treiber Offset = B + X und *Length = N - X festlegen. In beiden Aufrufen wird die gleiche MDL-Kette ohne Änderung verwendet.

Wenn der Aufrufer eine DmaCompletionRoutine angibt, schreibt MapTransferEx den *Length-Ausgabewert , bevor die Ausführung der DmaCompletionRoutine geplant wird. Dieses Verhalten stellt sicher, dass der aktualisierte *Length-Wert immer verfügbar ist, bevor DmaCompletionRoutine ausgeführt wird. Wenn für eine DMA-Übertragung beispielsweise zwei MapTransferEx-Aufrufe erforderlich sind, kann die DmaCompletionRoutine , die der erste Aufrufzeitplan hat, den Ausgabewert *Length aus dem ersten Aufruf abrufen. Die Routine kann dann diesen Wert verwenden, um den Eingabewert *Length für den zweiten Aufruf zu berechnen. In der Regel verweist der Length-Parameter auf eine Position im *CompletionContext-Wert , der für die DmaCompletionRoutine als Parameter angegeben wird.