MapTransferEx ルーチンの使用
MapTransferEx ルーチンは、以前に割り当てられた DMA リソースのセットを初期化し、DMA 転送を開始します。 このルーチンは、DMA 操作インターフェイスのバージョン 3 で使用できます。 このインターフェイスのバージョン 3 は、Windows 8 以降でサポートされています。 DMA 操作インターフェイスの詳細については、「 DMA_OPERATIONS」を参照してください。
MapTransferEx と MapTransfer の比較
MapTransferEx は MapTransfer ルーチンの改善されたバージョンです。 MapTransfer は、Windows 2000 のバージョン 1 以降、すべてのバージョンの DMA 操作インターフェイスで使用できます。 MapTransfer を1 回呼び出すと、MDL から 1 つの連続した物理メモリ ブロックをマップできます。 ただし、複雑な DMA 転送用のデータ バッファーは MDL チェーンによって記述される場合があり、チェーン内の各 MDL は物理的に連続したメモリの複数のブロックを記述する場合があります。 MapTransfer を使用してこのようなバッファーを転送するには、ドライバーが MapTransferに対して多くの呼び出しを行う必要があります。 通常、これらの呼び出しは、入れ子になったループのペア内で行われます。 内部ループは、連続する物理メモリの 1 つのブロックから各 MDL 内の次のブロックに反復処理し、外側のループは MDL チェーン内の 1 つの MDL から次の MDL に反復処理します。
これに対し、 MapTransferEx を1 回呼び出すと、複雑な DMA 転送のためにデータ バッファー全体を転送できます。 次の 3 つの MapTransferEx パラメーターでは、転送に使用するバッファー メモリについて記述します。
パラメーター | 説明 |
---|---|
MDL | 1 つ以上の MDL のチェーン内の最初の MDL へのポインター。 MDL の使用の詳細については、「 「MDL の使用」を参照してください。 |
Offset | MDL チェーンによって記述されるメモリの先頭からのバッファーのバイト オフセット。 |
Length | データバッファの長さ (バイト単位) を格納する場所へのポインター。 |
MapTransferEx 呼び出しの開始時に MapTransferEx ルーチンは MDL チェーンを介してバッファーの開始を検索します。 バッファーの先頭は Offset パラメーターで指定します。 次に、バッファーの先頭から最後まで、 MapnsferEx は、リスト内の各バッファー フラグメントが MDL チェーンから物理的に連続したメモリブロックである散布図/収集リストを構築します。 このリストを構築するために、 MapTransferEx は、物理的に連続したメモリ ブロックから各 MDL 内の次のブロック、および MDL チェーン内の 1 つの MDL から次の MDL へと処理を進めます。 散布図/収集リストによって記述されたバッファー・メモリーの合計量が、*Length 入力パラメーターで指定されたバイト数と等しい場合、リストの作成は完了します。 結果として得られる散布図/収集リスト内のバッファー フラグメントの順序は、MDL チェーン内の物理的に連続するブロックの順序と一致します。
MapTransferEx の複数呼び出し
MapTransferEx は、1 回の呼び出しで DMA データ バッファー全体を転送できるとは限りません。 次の一覧では、転送を完了するために MapTransferEx を複数回呼び出す必要がある可能性があるいくつかの条件について説明します。
- DMA アダプターにはマップ レジスタが必要であり、アダプターに割り当てられたマップ レジスタの数だけではバッファー全体を記述できません。
- ドライバーが分散/収集リストを格納するために割り当てられたストレージは、バッファー全体の散布図/収集リストを格納するのに十分な大きさではありません。
- 転送では、ハードウェア散布図/収集リストで指定できるバッファー フラグメントの数を制限するシステム DMA コントローラーを使用します。
いずれの場合も、 MapTransferEx は 1 回の呼び出しで可能な限り多くのデータ バッファーをマップし、呼び出しによってマップされたバッファーの量をドライバーに通知します。 上記の一覧には、転送を完了するために MapTransferEx を複数回呼び出す必要がある可能性があるその他の条件、たとえばプラットフォーム固有のキャッシュ動作などは含まれていません。 将来のハードウェア プラットフォームでは、DMA 転送の長さに追加の制約が課される可能性があります。 このような理由から、ドライバー開発者は、 MapTransferEx が 1 回の呼び出しで DMA データ バッファー全体をマップできない場合を正しく処理するようにドライバーを設計する必要があります。
MapTransferExを呼び出す前に、呼び出し元は *Length パラメーターを、まだマップする必要がある DMA データ バッファー内のバイト数に設定します。 戻る前に、 MapTransferEx は *Length を、呼び出しによって実際にマップされたバッファー内のバイト数に設定します。 MapTransferEx 呼び出しで *Length 入力値で指定されたバッファー長全体をマップできない場合、 *Length の出力値は入力値より小さくなります。 DMA 転送で 2 回以上 MapTransferEx 呼び出しが必要な場合、呼び出し元のドライバーは、次の呼び出しで *Length 入力値を指定する前に、1 回の呼び出しで *Length 出力値を取得する必要があります。
たとえば、 MapTransferEx 呼び出しで、 Offset = B および *Length = N (入力時) のバッファー)との間で X バイトのみを転送できる場合、戻り値は *Length = X になります。 次の MapTransferExへの呼び出しでは、ドライバーは Offset = B + X と *Length = N - X を設定する必要があります。どちらの呼び出しでも、同じ MDL チェーンが変更なしで使用されます。
呼び出し元が DmaCompletionRoutine指定した場合、 MapTransferEx は*Length 出力値を DmaCompletionRoutine の実行をスケジュールする前に書き込みます。 この動作により、更新された *Length 値は、 DmaCompletionRoutine が実行される前に利用可能になります。 たとえば、DMA 転送に 2 回の MapTransferEx 呼び出しが必要な場合、最初の 呼び出しがスケジュールする DmaCompletionRoutine は、最初の呼び出しから *Length 出力値を取得できます。 その後、ルーチンはこの値を使用して、2 回目の呼び出しの *Length 入力値を計算できます。 通常 Length パラメーターは *CompletionContext 値内のパラメーターとして指定される DmaCompletionRoutine 値内の場所を指します。