次の方法で共有


同期および非同期のコーデック コマンド

TransferCodecVerbs ルーチンを使用すると、ファンクション ドライバーが HD Audio コントローラーに接続されているオーディオ コーデックおよびモデム コーデックにコマンドを送信できるようになります。 コーデック コマンドは同期または非同期で実行できます。

  • TransferCodecVerbs への呼び出しが、同期的に処理されるコマンドのリストを送信する場合、ルーチンは、コーデックがすべてのコマンドを処理した後にのみ戻ります。

  • TransferCodecVerbs への呼び出しが非同期で処理されるコマンドのリストを送信する場合、ルーチンは、HD Audio バス ドライバーがコマンドを内部コマンド キューに追加するとすぐに、コーデックがコマンドを処理するのを待たずに戻ります。 コーデックがコマンドを処理した後、バス ドライバーはコールバック ルーチンを呼び出してファンクション ドライバーに通知します。

送信するコーデック コマンドの性質に応じて、ファンクション ドライバーは次の 1 つ以上の手法を使用してコーデックから応答を取得します。

  • ファンクション ドライバーが追加の処理を実行する前にコーデックからの応答が必要な場合、ファンクション ドライバーは同期モードを使用します。

  • ファンクション ドライバーがコーデック コマンドが完了するのを待つ必要がない場合は、コーデックの応答を確認し、コマンドがいつ完了したかを知るために、非同期モードを使用し、コールバック ルーチンを無視し (コーデック コマンド用のストレージを解放する場合を除く)、コーデック コマンドに対する応答を破棄または無視します。

  • ファンクション ドライバーがコーデック コマンドがいつ完了するかを知る必要があるが、応答を確認する必要はない場合は、非同期モードを使用し、通知にコールバック ルーチンを利用します。 ただし、コーデック コマンドに対する応答は破棄または無視されます。 コールバック ルーチンは、カーネル ストリーミング (KS) イベントを使用して、ドライバーの主要部分に通知を送信する場合があります。

  • ファンクション ドライバーがコーデック コマンドがいつ完了するか、および応答が何であるかを認識する必要があるが、コマンドが完了するのを待たずにすぐに処理を再開する必要がある場合、ファンクション ドライバーは非同期モードを使用し、コールバック ルーチンを受信するまで応答の読み取りを回避します。 コールバック ルーチンまたはドライバーの主要部分のいずれかが応答を検査できます。

TransferCodecVerbs は、コマンドのリストをバス ドライバーの内部コマンド キューに追加することに成功すると、STATUS_SUCCESS を返します。 呼び出しが成功しても、応答が無効な場合があります。 ファンクション ドライバーは、コーデック応答のステータス ビットをチェックして、それらが有効かどうかを判断する必要があります。 このルールは、同期モードと非同期モードの両方に適用されます。

無効な応答の原因は、次のいずれかである可能性があります:

  • コマンドがコーデックに到達しませんでした。

  • コーデックは応答しましたが、RIRB で先入れ先出し (FIFO) オーバーランが発生したときに応答が失われました。

後者の問題は、RIRB FIFO のサイズが不十分であることを示しています。

各コーデック応答には、応答が有効かどうかを示す IsValid フラグと、RIRB FIFO オーバーランが発生したかどうかを示す HasFifoOverrun フラグが含まれています。 IsValid = 0 (応答が無効であることを示す) の場合、HasFifoOverrun フラグは失敗の原因を特定するのに役立ちます:

  • HasFifoOverrun = 0 の場合、コーデックは必要な時間間隔内に応答できませんでした。 考えられる原因は、コマンドがコーデックに到達しなかったことです。

  • HasFifoOverrun = 1 の場合、コマンドはおそらくコーデックに到達しましたが、FIFO オーバーランにより応答が失われました。

TransferCodecCommands の呼び出し中に、呼び出し元は HDAUDIO_CODEC_TRANSFER 構造体の配列へのポインターを提供します。 各構造にはコマンドが含まれており、応答用のスペースが提供されます。 バス ドライバーは常に、各応答を、応答をトリガーしたコマンドを含む構造体に書き込みます。

TransferCodecCommands の呼び出しごとに、コマンドが処理される順序は、配列内のコマンドの順序によって決まります。 配列内の最初のコマンドの処理は常に 2 番目のコマンドの処理が開始される前に完了し、以下同様に続きます。

さらに、クライアントが TransferCodecCommands への非同期呼び出しを行った後、最初の呼び出しからのコールバック ルーチンを待たずに 2 回目に TransferCodecCommands を呼び出した場合、2 つの呼び出しからの 2 つのコマンド グループが処理される相対的な順序は、クライアントが 2 つのコマンド グループを送信した順序によって定義されます。 したがって、バス ドライバーは、2 番目の呼び出しからのコマンドの処理を開始する前に、最初の呼び出しからのすべてのコマンドを処理します。

ただし、2 つの異なるファンクション ドライバー インスタンスによって送信されるコマンドの相対的な順序は未定義です。 (各インスタンスには独自の物理デバイス オブジェクトがあります。)たとえば、インスタンス 1 が TransferCodecCommands を呼び出してコマンド A、B、および C を A-B-C の順序で送信し、インスタンス 2 が TransferCodecCommands を呼び出してコマンド X、Y、Z を X-Y-Z の順序で送信した場合、バス ドライバーは A-X-Y-B-Z-C の順序でコマンドを実行する可能性があります。

別々のファンクション ドライバー スレッドが同じハードウェア リソース セットへのアクセスを共有する場合、異なるドライバー スレッドからのコマンドの相対的な順序が重要になる場合があります。 その場合、ファンクション ドライバーはスレッド間のリソースの共有を同期する責任があります。

たとえば、一連のデータ バイトをコーデックに書き込むためのハードウェア インターフェイスは、インデックス レジスタと 8 ビット データ レジスタで構成される場合があります。 まず、ファンクション ドライバーはコーデック コマンドを送信して、開始インデックスをインデックス レジスタにロードします。 次に、ドライバーはデータの最初のバイトをデータ レジスタに書き込むコマンドを送信します。 インデックス レジスタは、転送が完了するまでデータ レジスタへの連続書き込みごとにインクリメントされます。 ただし、2 つのドライバ スレッドがインデックス レジスタとデータ レジスタへのアクセスを適切に同期できない場合、2 つのスレッドによる個々のレジスタ アクセスの相対的な順序は定義されず、結果としてデータの破損または無効なハードウェア構成が発生する可能性があります。

TransferCodecVerbs ルーチンは、HD Audio DDI の両方のバージョンで使用できます。