次の方法で共有


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

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

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

  • TransferCodecVerbs の呼び出しが非同期的に処理されるコマンドの一覧を送信すると、HD オーディオ バス ドライバーがコマンドを内部コマンド キューに追加するとすぐに、コーデックまたはコーデックがコマンドを処理するのを待たずにルーチンが返されます。 コーデックがコマンドを処理した後、バス ドライバーはコールバック ルーチンを呼び出すことによって関数ドライバーに通知します。

関数ドライバーは、送信するコーデック コマンドの性質に応じて、次の 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 への非同期呼び出しを行い、最初の呼び出しからコールバック ルーチンを待機せずに TransferCodecCommands を 2 回目に呼び出した場合、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 オーディオ DDI の両方のバージョンで使用できます。