スキャッター/ギャザー DMA の使用
システムまたはバス マスター、パケット ベースの DMA を実行するドライバーは、特にスキャッター/ギャザー DMA 用に設計されたサポート ルーチンを使用できます。 「パケット ベースのシステム DMA とパケット ベースのバス マスター DMA の使用」で説明されている一連のルーチンを呼び出す代わりに、ドライバーは GetScatterGatherList と PutScatterGatherList を使用できます。
デバイスがこれらのルーチンを使用するために、ドライバーにスキャッター/ギャザー サポートが組み込まれている必要はありません。
パケット ベースの DMA を使用するドライバーは、スキャッター/ギャザー操作に対して次の一般的な一連のサポート ルーチンを呼び出します。
MmGetMdlVirtualAddress は、MDL へのインデックスを取得します。GetScatterGatherList の呼び出しのパラメーターとして必要です。
GetScatterGatherList ドライバーが DMA 用にデバイスをプログラミングする準備が整い、システム DMA コントローラーまたはバス マスター アダプターが必要な場合
GetScatterGatherList は、システム DMA コントローラーまたはバス マスター アダプターを割り当て、必要なマップ レジスタの数を決定し、それらを割り当て、散布図/収集リストを入力して、DMA コントローラーまたはアダプターとマップ レジスタが使用可能になったときにドライバーの AdapterListControl ルーチンを呼び出します。
PutScatterGatherList は要求されたすべてのデータが転送されるか、デバイスの I/O エラーが原因でドライバーが IRP に失敗するとすぐに実行されます
PutScatterGatherList はアダプター バッファーをフラッシュし、マップ レジスタを解放して、スキャッター/ギャザー リストを解放します。 ドライバーは、バッファー内のデータにアクセスする前に PutScatterGatherList を呼び出す必要があります。
IoGetDmaAdapter によって返されるアダプター オブジェクト ポインターは、Irp->MdlAddress の MDL へのポインターを必要とする MmGetMdlVirtualAddress を除く、これらの各ルーチンに必要なパラメーターです。
GetScatterGatherList ルーチンには AllocateAdapterChannel と MapTransfer の呼び出しが含まれているため、ドライバーはこれらの呼び出しを行う必要はありません。 このルーチンは、以下のものをパラメータとして受け取ります。
IoGetDmaAdapter によって返される DMA_ADAPTER 構造体へのポインター
DMA 操作のターゲット デバイス オブジェクトへのポインター
Irp->MdlAddress のバッファーを記述する MDL へのポインター
Mdl によって記述されたバッファー内の現在の仮想アドレスへのポインター
マッピングされるバイト数
転送を実行する AdapterListControl ルーチンへのポインター
AdapterListControl ルーチンに渡されるドライバー定義コンテキスト領域へのポインター
ブール値: デバイスへの転送の場合は TRUE、それ以外は FALSE
必要なマップ レジスタの数を決定し、アダプター チャネルとマップ レジスタを割り当て、スキャッター/ギャザー リストを入力し、転送の準備を行った後、 GetScatterGatherList はドライバー提供 の AdapterListControl ルーチンを呼び出します。 AdapterListControl ルーチンは、IRQL = DISPATCH_LEVEL の任意のスレッド コンテキストで実行されます。
GetScatterGatherList の呼び出しでドライバーが提供する AdapterListControl ルーチンは、AllocateAdapterChannel に渡される AdapterControl ルーチンとは以下の重要な点で異なります。
AdapterListControl ルーチンには戻り値がありませんが、AdapterControl ルーチンは IO_ALLOCATION_ACTION を返します。
システム割り当てマップ レジスタの MapRegisterBase へのポインターではなく、AdapterListControl ルーチンの 3 番目のパラメーターは、ドライバーが DMA を実行できる SCATTER_GATHER_LIST 構造体を指します。
AdapterListControl ルーチンは、AdapterControl ルーチンで必要なタスクのサブセットを実行します。
AdapterListControl ルーチンは、AllocateAdapterChannel または MapTransfer を呼び出しません。 その唯一の役割は、入力キャッター/ギャザー リスト ポインターを保存し、そのデバイスを設定し、キャッター/ギャザー リストを使用して DMA を実行することです。
スキャッター/ギャザー リスト構造体には、 SCATTER_GATHER_ELEMENT 配列と配列内の要素の数が含まれます。 配列の各要素は、物理的に連続するスキャッター/ギャザー領域の長さと開始物理アドレスを提供します。 ドライバーは、データ転送で長さとアドレスを使用します。
ドライバーは、デバイスがスキャッター/ギャザー DMA をサポートしているかどうかに関係なく、GetScatterGatherList を使用できます。 スキャッター/ギャザー DMA をサポートしていないデバイスの場合、スキャッター/ギャザー リストには要素が 1 つだけ含まれます。
スキャッター/ギャザー ルーチンを使用すると、AllocateAdapterChannel の呼び出しよりもパフォーマンスを向上させることができます (パケット ベースのシステム DMA の使用とパケット ベースのバス マスター DMA の使用で説明されています)。 AllocateAdapterChannel の呼び出しとは異なり、1 つのデバイス オブジェクトに対して GetScatterGatherList への複数の呼び出しを一度にキューに入れることができます。 ドライバーは、AdapterListControl ルーチンの実行が完了する前に、GetScatterGatherList をもう一度呼び出して、同じドライバー オブジェクトに対する別の DMA 操作を行うことができます。
ドライバーが提供する AdapterListControl ルーチンから戻ると、GetScatterGatherList はマップ レジスタを保持しますが、DMA アダプター構造体を解放します。
ドライバーが現在の IRP の転送要求を満たしているか、デバイスまたはバス I/O エラーが原因で IRP をを失敗させなければならない場合は、バッファー内の転送されたデータにアクセスする前に PutScatterGatherList を呼び出す必要があります。 PutScatterGatherList はアダプター バッファーをフラッシュし、マップ レジスタとスキャッター/ギャザー リストを解放します。