アダプター オブジェクトの取得
デバイスの起動に、システムまたはバス マスター DMA を使用するドライバーは、IoGetDmaAdapter を呼び出してアダプター オブジェクトへのポインターを取得し、各転送操作で使用可能なマップ レジスタの最大数を決定します。 ドライバーが IoGetDmaAdapter を呼び出すと、I/O マネージャーは HAL を呼び出し、必要なプラットフォーム固有の情報を取得します。
ドライバーは、IoGetDmaAdapter の呼び出しでシステム定義の DEVICE_DESCRIPTION 構造に特定の情報を提供する必要があります。 ドライバーは、値を設定する前に、RtlZeroMemory を使用して、DEVICE_DESCRIPTION 構造をゼロで初期化する必要があります。
必須のデータには、デバイスがバス マスターかどうか、スキャッター/ギャザー機能があるかどうか、デバイスが一度に転送できるデータのバイト数 (MaximumLength) など、ドライバーのデバイスの機能に関する情報が含まれます。
必須のデバイス記述データには、プラットフォーム固有の情報や、バス マスター デバイスのドライバーが制御するバスのシステム割り当て番号なども含まれます。 ドライバーは、IoGetDeviceProperty を呼び出すことによって、この情報を取得できます。
DEVICE_DESCRIPTION 構造には、一部の DMA デバイスまたはドライバーとは無関係な可能性があるいくつかのフィールドが含まれています。 たとえば、BusNumber フィールドは WDM ドライバーでは使用されません。 各ドライバーは、関連する構造メンバーの値を指定し、他のすべてのメンバーの値を 0 に設定する必要があります。
下位デバイスのドライバーは、ScatterGather フィールドで TRUE を渡すべきではありません。ただし、要求を複数の DMA 操作に分割する必要がある場合に、システム DMA コントローラーの再プログラミングを待機できる場合を除きます。
IoGetDmaAdapter は、アダプター オブジェクトへのポインターと、DMA 転送操作ごとにアダプター オブジェクトで使用できるマップ レジスタの数を示すプラットフォーム固有またはデバイス固有の値の両方を返します。
返されるアダプター オブジェクトには、ドライバーからアクセスできる 3 つのフィールドが含まれています。
バージョン番号 (バージョン)
サイズ (Size)
DMA_OPERATIONS 構造へのポインター (DmaOperations)
DMA_OPERATIONS 構造は、ドライバーがデバイスで DMA 操作を実行するために使用する必要がある関数へのポインターのテーブルで構成されています。 関数には、このデータ構造内のポインターを介してのみアクセスできます。ドライバーが名前で直接呼び出すことはできません。 (これらのルーチンにより、以前のバージョンの Windows NT でサポートされていた HalXxx ルーチンが置き換えられる点に注意してください。レガシ ドライバーの互換性を確保するため、Wdm.h ヘッダー ファイルと Ntddk.h ヘッダー ファイルは古い名前のマクロを提供しますが、新しいドライバーは常にデータ構造を介して関数を呼び出す必要があります)。
マップ レジスタの数は、デバイスやプラットフォームによって異なる場合があります。 一般に、HAL は次の条件に従ってマップ レジスタの数を割り当てます。
可能な場合、HAL は、ドライバーの IoGetDmaAdapter への呼び出しで指定されている、MaximumLength バイトを転送するのに必要なマップ レジスタの数より 1 つ大きい値を返します。
それ以外の場合、HAL は特定のプラットフォームに対して、より小さく、かつ可能な限り大きい値を返します。
言い換えると、HAL は通常、デバイスの DMA スループットを最大化するのに十分なマップ レジスタを各ドライバーに付与しますが、HAL は一部の Windows プラットフォームではより小さい値を返すことができます。 ドライバーが要求したマップ レジスタの数を取得する保証はないため、ドライバーは、常に戻り値をチェックする必要があります。
DMA デバイス ドライバーは、アダプター オブジェクト ポインターと、IoGetDmaAdapter によって返される NumberOfMapRegisters 値のストレージを提供する必要があります。 このポインターは、DMA に使用されるシステム提供のサポート ルーチンに必要なパラメーターです。 これらのサポート ルーチンの多くは IRQL = DISPATCH_LEVEL で呼び出す必要があるため、ドライバーによって割り当てられたストレージは常駐している必要があります。 ほとんどの DMA ドライバーは、デバイス拡張機能に必要なストレージを提供します。 ただし、ドライバーがコントローラー オブジェクトも使用している場合、またはドライバーによって割り当てられている非ページ プール内にある場合、ストレージをコントローラー拡張機能に配置できます。 詳しくは、「システム領域メモリの割り当て」と「ハードウェア優先順位の管理」をご覧ください。
ドライバーがすべての DMA 操作を完了すると、PutDmaAdapter を呼び出してアダプター オブジェクトを解放します。
次のセクションでは、「システム DMA の使用」と「バス マスター DMA の使用」では、DMA デバイスのモノリシック ドライバーがサポート ルーチンを使って転送要求を満たす方法について説明します。 これらのセクションでは、ドライバーに以下があることを前提としています。
標準 StartIo ルーチン (IRP の内部キューの設定と管理は行わない)
マップ レジスタの数が不足している転送要求を分割する内部ルーチン
デバイス固有の DMA 制約なし
言い換えると、これらのセクションでは、ドライバーの DMA 操作の最も簡単な手法について説明しますが、個々のドライバーでは必ずしもまったく同じ手法が使用されるとは限りません。 DMA デバイスのドライバーでは、大きな DMA 転送要求を分割する必要があるドライバー ルーチンは、ドライバー モデル (クラス/ポートまたはモノリシック)、デバイスの機能、ドライバーが処理する必要があるデバイス固有の DMA 制約によって決まります。