次の方法で共有


バージョン 3 の DMA ルーチンの基本的な呼び出しパターン

DMA 操作インターフェイスのバージョン 3 のルーチンを使用する DMA 転送を実行するには、ドライバーは次の一覧で説明されている手順に従う必要があります。 これらの手順は、下位デバイスとバス マスター デバイスの両方に共通しています。 このインターフェイスのバージョン 3 は、Windows 8 以降で利用できます。 このインターフェイスのルーチンの詳細については、 DMA_OPERATIONSを参照してください。

手順 1:DMA アダプター オブジェクトを取得する

DMA 転送の準備として、ドライバーは IoGetDmaAdapter ルーチンを呼び出して DMA アダプター オブジェクトを取得します。 DMA アダプター オブジェクトは、バス マスター デバイスまたはシステム DMA コントローラーの要求行を表すソフトウェア オブジェクトです。 このオブジェクトには、デバイスとの間でデータを転送するために使用されるバスの DMA 操作インターフェイスが含まれています。 さらに、このオブジェクトは、転送を実行するために必要な共有リソースへのドライバーのアクセスを同期します。 詳細については、 アダプタオブジェクトの概要を参照してください。

手順 2:必要な DMA リソースの説明を取得する

ドライバーは、転送を 実行する必要がある DMA リソースの説明を取得する GetDmaTransferInfo ルーチンを呼び出します。

この呼び出しの入力パラメーターは、転送に使用するメモリ バッファーと、転送の方向 (読み取りまたは書き込み) を記述します。

この呼び出しから取得されるリソース要件には、マップ レジスタの数と、転送のデータ バッファーを記述するために必要な散布図/収集リストのサイズが含まれます。 AllocateAdapterChannelEx ルーチンの後続の呼び出し ( 手順 3を参照) では、ドライバーは入力パラメーターとしてマップ レジスタ数を指定します。

手順 3: 必要な DMA リソースを要求する

ドライバーは、DMA アダプター オブジェクトに 割り当てるリソースを割り当てるために AllocateAdapterChannelEx ルーチンを呼び出します。 これらのリソースには、DMA チャネルとマップ レジスタが含まれます。

AllocateAdapterChannelEx 呼び出しは、非同期または同期にすることができます。

DMA_SYNCHRONOUS_CALLBACK フラグが設定されていない場合、呼び出しは非同期です。 この場合、 ExecutionRoutine パラメーターは、要求されたリソースが使用可能になった際に呼び出される呼び出し元が指定した実行ルーチンを指します。 成功した場合、非同期 AllocateAdapterChannelEx 呼び出しは、実行ルーチンの実行を待たずにSTATUS_SUCCESSを返します。

DMA_SYNCHRONOUS_CALLBACKフラグが設定されている場合、 AllocateAdapterChannelEx 呼び出しは同期的です。 この場合、呼び出しの ExecutionRoutine パラメーターは任意であり、 AllocateAdapterChannelEx は次のように動作します。

  • ExecutionRoutine が NULL 以外で、DMA リソースをすぐに割り当てることができる場合、 AllocateAdapterChannelEx は呼び出し元のスレッドのコンテキストで実行ルーチンを呼び出します。 実行ルーチンの実行が完了すると、 AllocateAdapterChannelEx はSTATUS_SUCCESSを返します。 リソースがすぐに使用できない場合、 AllocateAdapterChannelEx は失敗し、エラー状態コード STATUS_INSUFFICIENT_RESOURCESを返します。

  • ExecutionRoutine が NULL で、 AllocateAdapterChannelEx が DMA リソースをすぐに割り当てることができる場合、 AllocateAdapterChannelEx はSTATUS_SUCCESSを返します。 すべてのリソースがすぐに使用できない場合、呼び出しはエラー状態コードSTATUS_INSUFFICIENT_RESOURCESで失敗します。

STATUS_SUCCESSを返す同期呼び出しの場合、 AllocateAdapterChannelEx への MapRegisterBase パラメーターが NULL 以外の場合、 AllocateAdapterChannelEx は割り当てられたマップ レジスタのベース アドレスを MapRegisterBase パラメーターが指すアドレスに書き込みます。 ExecutionRoutine が NULL の場合、 MapRegisterBase は NULL 以外である必要があります。 ExecutionRoutine が NULL 以外の場合、 AllocateAdapterChannelEx への MapRegisterBase パラメーターは任意であり、実行ルーチンは入力パラメーターとしてマップ レジスタのベース アドレスを受け取ります。

非同期 AllocateAdapterChannelEx 呼び出しの場合、 ExecutionRoutine は NULL 以外である必要があり、実行ルーチンは入力パラメーターとしてマップ レジスタのベース アドレスを受け取ります。

以降の MapTransferEx ルーチンの呼び出し ( 手順 5を参照) では、ドライバーは、マップ レジスタのベース アドレスを入力パラメーターとして提供します。

ExecutionRoutine が NULL 以外の場合、実行ルーチンは、割り当てられたリソースの処理を示す状態値を返します。 システム DMA 転送の場合、この戻り値は KeepObject である必要があります。 この値は、アダプター オブジェクト (およびその割り当てられているすべてのリソース) が使用中であり、解放してはならないことをオペレーティング システムに通知します。 実行ルーチンが指定されていない場合、ドライバーは代わりに FreeAdapterObject ルーチンを呼び出し、 AllocationOption パラメーターとして KeepObject を指定する必要があります。

手順 4:必要に応じて、保留中のリソース要求を取り消します

AllocateAdapterChannelEx 呼び出しが DMA アダプターをキューに登録して DMA リソースを待機した後、ドライバーは必要に応じて CancelAdapterChannel ルーチンを呼び出して保留中のリソース要求を取り消すことができます。

CancelAdapterChannel が TRUE を返した場合、リソース要求は正常に取り消されます。 AllocateAdapterChannelEx 呼び出しで実行ルーチンが指定された場合、このルーチンは実行されません。

CancelAdapterChannel が FALSE を返した場合、リソース要求は既に許可されているため、取り消すことができません。 AllocateAdapterChannelEx 呼び出しで実行ルーチンが指定された場合、このルーチンが呼び出されます。

手順 5:DMA リソースを初期化し、DMA 転送を開始する

ドライバーはDMA リソースを初期化し、DMA 転送を開始する MapTransferEx を呼び出します。 この呼び出しは、 AllocateAdapterChannelEx を呼び出すのと同じドライバー スレッドで発生するか、ドライバーが AllocateAdapterChannelEx に提供する実行ルーチンで発生する可能性もあります。 DMA データ バッファー全体を転送するために複数の MapTransferEx 呼び出しが必要な場合は、前の MapTransferEx 呼び出しの完了ルーチンで後の MapTransferEx 呼び出しが発生する可能性があります。

MapTransferEx では、入力パラメーターとしてチェーンされた MDL がサポートされています。 各 MDL は、仮想メモリ内で連続する DMA バッファーの領域を記述します。 MapTransferEx は、散布図/収集リストを構築するときに、ドライバーの介入なしに、仮想的に連続するバッファー領域から次のバッファー領域への遷移を自動的に処理します。 詳細については、 MapTransferEx ルーチンの使用を参照してください。

システム DMA 転送の場合、DMA 完了ルーチンへのポインターは、オプションの DmaCompletionRoutine パラメーターで MapTransferEx に渡すことができます。 このルーチンは、DMA 転送が完了したことを示すシステム DMA コントローラーからの割り込みに応答してディスパッチ レベルで実行するようにスケジュールされています。

MapTransferEx は、要求された転送サイズ全体をマップできない場合、*長さ 出力パラメーターをマップされた長さに設定し、STATUS_SUCCESSを返します。

手順 6:必要に応じて、ハードウェア固有の操作を実行する

MapTransferEx は、DMA 転送が正常に開始されたことを示すSTATUS_SUCCESSを返します。 一部のプラットフォームでは、転送を開始するために MapTransferEx 呼び出しの外部でドライバーが追加のアクションを実行する必要がある場合がありますが、この種類の遅延開始はすべてのプラットフォームで必要ありません。 ドライバーは割り当てられたリソースの使用とリリースに関する決定のために、このような遅延に依存してはなりません。

DMAオペレーションインターフェースのルーチンは、これらのルーチンを使用するドライバにとって透過的な方法で、DMA転送のキャッシュコヒーレンシーを維持します。 ハードウェアでキャッシュの一貫性を強制しないプラットフォームでは、 MapTransferEx により、書き込み (メモリからデバイスへの) 転送の前にプロセッサ データ キャッシュがフラッシュされます。 読み取り (デバイスからメモリへの) 転送では、すべての MapTransferEx 呼び出しに続く FlushAdapterBuffersEx ルーチン ( 手順 8を参照) の呼び出し中にキャッシュが無効になります。

手順 7:DMA 転送が完了したときに通知を受信する

DMA 転送が完了すると、次の 2 つの方法のいずれかでドライバーに通知されます。

  • バス マスター デバイスのデバイス ドライバーへの割り込み
  • システム DMA コントローラーを使用する下位デバイスに対するドライバー提供の完了ルーチンの実行

システム DMA 転送の場合、ドライバーは入力パラメーターとして MapTransferEx に完了ルーチンを提供できます。

手順 8:キャッシュに残るデータをフラッシュする

DMA 転送が完了したら、ドライバーは FlushAdapterBuffersEx ルーチンを呼び出し、キャッシュ内の残りのデータをフラッシュする必要があります。 ドライバーは、MapTransferExを 呼び出す度に FlushAdapterBuffersEx を呼び出す必要があります。

MapTransferEx 呼び出しが DMA データ バッファーの一部のみをマップする場合、ドライバーは再メインデータをマップするために MapTransferEx を再度呼び出す必要があります。 複雑な転送には、複数の MapTransferEx 呼び出しが必要な場合があります。 追加の MapTransferEx 呼び出しごとに、手順 5 から 8 を繰り返します。

手順 9:DMA チャネルとマップ レジスタを解放する

DMA データ バッファー全体が正常にマップされ、最終的な転送が完了したら、ドライバーは FreeAdapterChannel ルーチンを呼び出し、DMA チャネルと以前に割り当てられたマップ レジスタをリリースする必要があります。

手順 10:DMA アダプター オブジェクトをリリースする

すべての DMA 転送が完了し、以前に割り当てられたマップ レジスタがリリースされると、ドライバーは PutDmaAdapter ルーチンを呼び出してアダプター オブジェクトをリリースします。