Verwenden von Scatter/Gather DMA

Treiber, die system- oder bus-master, paketbasierte DMA ausführen, können Unterstützungsroutinen verwenden, die speziell für scatter/gather DMA entwickelt wurden. Anstatt die Sequenz von Routinen aufzurufen, die unter Verwenden Packet-Based System-DMA und Paketbasierter Bus-Master DMA beschrieben sind, kann ein Treiber GetScatterGatherList und PutScatterGatherList verwenden.

Ein Gerät muss keine integrierte Scatter/Gather-Unterstützung für seinen Treiber haben, um diese Routinen verwenden zu können.

Treiber, die paketbasierte DMA verwenden, rufen die folgende allgemeine Sequenz von Unterstützungsroutinen für Scatter-/Gather-Vorgänge auf:

  1. MmGetMdlVirtualAddress zum Abrufen eines Indexes in die MDL, erforderlich als Parameter im Aufruf von GetScatterGatherList

  2. GetScatterGatherList, wenn der Treiber bereit ist, sein Gerät für DMA zu programmieren und den System-DMA-Controller oder bus-master-Adapter benötigt

    GetScatterGatherList weist den System-DMA-Controller oder bus-master-Adapter zu, bestimmt, wie viele Kartenregister erforderlich sind, und weist sie zu, füllt die Scatter/Gather-Liste aus und ruft die AdapterListControl-Routine des Treibers auf, wenn der DMA-Controller oder adapter und die Kartenregister verfügbar sind.

  3. PutScatterGatherList , sobald alle angeforderten Daten übertragen wurden oder der Treiber die IRP aufgrund eines Geräte-E/A-Fehlers ausfällt

    PutScatterGatherList löscht die Adapterpuffer, gibt die Kartenregister frei und gibt die Scatter/Gather-Liste frei. Der Treiber muss PutScatterGatherList aufrufen, bevor er auf die Daten im Puffer zugreifen kann.

Der von IoGetDmaAdapter zurückgegebene Adapterobjektzeiger ist ein erforderlicher Parameter für jede dieser Routinen mit Ausnahme von MmGetMdlVirtualAddress, für die ein Zeiger auf die MDL unter Irp-MdlAddress > erforderlich ist.

Die GetScatterGatherList-Routine umfasst Aufrufe von AllocateAdapterChannel und MapTransfer, sodass der Treiber diese Aufrufe nicht tätigen muss. Die Routine verwendet Folgendes als Parameter:

  • Ein Zeiger auf die vonIoGetDmaAdapter zurückgegebene DMA_ADAPTER-Struktur

  • Ein Zeiger auf das Zielgerätobjekt für den DMA-Vorgang

  • Ein Zeiger auf die MDL, der den Puffer bei Irp-MdlAddress> beschreibt

  • Ein Zeiger auf die aktuelle virtuelle Adresse im Puffer, der von der Mdl beschrieben wird

  • Die Anzahl der bytes, die zugeordnet werden sollen

  • Ein Zeiger auf eine AdapterListControl-Routine , die die Übertragung ausführt

  • Ein Zeiger auf einen vom Treiber definierten Kontextbereich, der an die AdapterListControl-Routine übergeben werden soll

  • Ein boolescher Wert: TRUE für eine Übertragung auf das Gerät; False andernfalls

Nach der Ermittlung der Anzahl der erforderlichen Kartenregister, der Zuordnung des Adapterkanals und der Kartenregister, dem Ausfüllen der Scatter-/Gather-Liste und der Vorbereitung für die Übertragung ruft GetScatterGatherList die vom Treiber bereitgestellte AdapterListControl-Routine auf. Die AdapterListControl-Routine wird in einem beliebigen Threadkontext unter IRQL = DISPATCH_LEVEL ausgeführt.

Die AdapterListControl-Routine , die ein Treiber in Aufrufen von GetScatterGatherList bereitstellt, unterscheidet sich in den folgenden wichtigen Punkten von der AdapterControl-Routine , die an AllocateAdapterChannel übergeben wird:

  • Die AdapterListControl-Routine hat keinen Rückgabewert, während die AdapterControl-Routine einen IO_ALLOCATION_ACTION zurückgibt.

  • Anstelle eines Zeigers auf mapRegisterBase für die systemseitig zugewiesenen Kartenregister verweist der dritte Parameter auf eine AdapterListControl-Routine auf eine SCATTER_GATHER_LIST Struktur, über die der Treiber DMA ausführen kann.

  • Die AdapterListControl-Routine führt eine Teilmenge der Aufgaben aus, die in einer AdapterControl-Routine erforderlich sind.

    Die AdapterListControl-Routine ruft "AllocateAdapterChannel " oder "MapTransfer" nicht auf. Die einzige Aufgabe besteht darin, den Eingabepunkt punkt-/sammlungslistenzeiger zu speichern, sein Gerät einzurichten und die Scatter/Gather-Liste zum Ausführen von DMA zu verwenden.

Die Scatter/Gather-Listenstruktur enthält ein SCATTER_GATHER_ELEMENT Array und die Anzahl der Elemente im Array. Jedes Element des Arrays stellt die Länge und die physische Startadresse eines physisch zusammenhängenden Punkt-/Sammlungsbereichs bereit. Ein Treiber verwendet die Länge und Adresse bei Datenübertragungen.

Ein Treiber kann GetScatterGatherList unabhängig davon verwenden, ob sein Gerät scatter/gather DMA unterstützt. Für ein Gerät, das scatter/gather DMA nicht unterstützt, enthält die Scatter/Gather-Liste nur ein Element.

Die Verwendung der Scatter/Gather-Routinen kann die Leistung gegenüber dem Aufrufen von AllocateAdapterChannel verbessern (wie zuvor unter Verwenden Packet-Based System-DMA und Verwenden Packet-Based Bus-Master DMA beschrieben). Im Gegensatz zu Aufrufen von AllocateAdapterChannel können mehrere Aufrufe von GetScatterGatherList für ein Geräteobjekt gleichzeitig in die Warteschlange gestellt werden. Ein Treiber kann GetScatterGatherList für einen anderen DMA-Vorgang für dasselbe Treiberobjekt erneut aufrufen, bevor seine AdapterListControl-Routine die Ausführung abgeschlossen hat.

Bei der Rückkehr von der vom Treiber bereitgestellten AdapterListControl-Routine behält GetScatterGatherList die Kartenregister bei, gibt aber die DMA-Adapterstruktur frei.

Wenn der Treiber die Übertragungsanforderung des aktuellen IRP erfüllt hat oder die IRP aufgrund eines Geräte- oder Bus-E/A-Fehlers fehlschlagen muss, muss er PutScatterGatherList aufrufen, bevor er auf die übertragenen Daten im Puffer zugreifen kann. PutScatterGatherList löscht die Adapterpuffer und gibt die Kartenregister und die Scatter/Gather-Liste frei.