IEEE 1394 バスでの非同期 I/O 要求パケットの送信
ドライバーは、REQUEST_ASYNC_READ、REQUEST_ASYNC_WRITE、REQUEST_ASYNC_LOCK を使って、IEEE 1394 バス上のデバイスに非同期読み取り、書き込み、ロック操作を送信します。 REQUEST_ASYNC_READ と REQUEST_ASYNC_WRITE の場合、操作固有の IRB のパラメーターは、IRB の u.AsyncRead メンバーまたは u.AsyncWrite メンバーに格納されます。
アドレス指定の種類
非同期 I/O 要求を行うドライバーは、IRB の DestinationAddress メンバーに IO_ADDRESS 型の宛先アドレスを指定する必要があります。 宛先アドレスは、ノード アドレスとアドレス オフセットの 2 つの値で構成されます。 バス ドライバーがこれら 2 つの値をどのように解釈するかは、要求を開始するドライバーが使用するアドレス指定のモードによって異なります。
normal、raw、virtual という 3 つのモードのアドレス指定を使用して、非同期 1394 パケットを送信できます。
normal モードのアドレス指定では、要求を開始するドライバーがアドレス オフセットを指定しますが、ターゲット デバイスのノード アドレスは指定しません。 バス ドライバーは、デバイスの列挙時にそのデバイスの PDO に格納した情報を使用してノード アドレスを指定します。
raw モードのアドレス指定では、要求を開始するドライバーがノード アドレスとアドレス オフセットの両方を指定する必要があります。 さらにドライバーは、ターゲット デバイスの PDO に要求を送信する代わりに、ホスト コントローラーの PDO に要求を送信する必要があります。 これにより、パケット内のノード アドレス情報を上書きしてはならないことをバス ドライバーに通知します。
virtual モードのアドレス指定では、raw モードのアドレス指定と同様に、要求を開始するドライバーがパケット内でターゲット デバイスのノード アドレスを明示的に示す必要があります。 ただし、仮想デバイスには 1394 バス上の実際のノード アドレスがありません。 仮想デバイスのノード アドレスは、仮想デバイスのドライバーがそのパケットを識別できるようにするための規則によって定められる値に過ぎません。 仮想デバイスのドライバーが適切に動作している場合は、バス上でブロードキャストされたすべてのパケットを受信し、そのデバイスの "ノード アドレス" として事前に定められた値を含むパケットを探して取捨選択する必要があります。
バス ドライバーがパケットに記録されているノード アドレスを上書きするのを防ぐために、仮想デバイスの要求を開始するドライバーが特別な手順を実行する必要はありません。 バス ドライバーは、最初に仮想デバイスを列挙するときに、そのデバイスが仮想であることを示すフラグをデバイスの PDO のデバイス拡張に設定します。 このデバイスの要求を受信すると、バス ドライバーはそれが仮想デバイスであることを確認できるため、パケット内のノード アドレスを上書きしません。
I/O 要求のバッファリング
非同期 I/O 要求を開始するドライバーは、I/O バッファーを指定する MDL へのポインターを提供する必要があります。 このポインターは、IRB の Mdl メンバーに設定されます。 バス ドライバーは、このバッファーを使ってデバイスから読み取ったデータをコピーするか、デバイスに書き込むデータのソースとして使用します。
ドライバーは、u.AsyncXXX の nNumberOfBytesToRead メンバーまたは nNumberOfBytesToWrite メンバーでデータ バッファーのサイズを、nBlockSize メンバーでブロック サイズを指定します。 トランザクションが実際に行われるときに、バス ドライバーは nBlockSize で指定されたサイズのパケットにデータを分割します。 既定では、バス ドライバーはデータの読み取りまたは書き込みを隣接して行います。つまり、デバイスのアドレス空間内の隣接する位置で各ブロックの読み取りまたは書き込みを行います。
次の図は、隣接するデータ ブロックを示しています。
必要に応じて、ドライバーは要求の ASYNC_FLAGS_NONINCREMENTING フラグを指定できます。その後、バス ドライバーは各ブロックに同じアドレス セットを使用します。
次の図は、非同期の非インクリメント データ ブロックを示しています。
警告 バス ドライバーでは、デバイスとコンピューター間の現在の接続速度の最大非同期パケット サイズと、デバイスがその構成 ROM の MAX_REC フィールドで報告する最大速度が強制されます。 nBlockSize がこれらの値のいずれかより大きい場合、バス ドライバーは強制される値をブロック サイズに使用します。 ドライバーが ASYNC_FLAGS_NONINCREMENTING フラグを設定する場合、これが望ましい動作を実現する可能性は低くなります。 ドライバーがこのフラグを設定する場合は、要求を送信する前に、ブロック サイズが強制される上限よりも小さいことをチェックする必要があります。
ロック要求の送信
IEEE 1394 バス プロトコルでは非同期ロック要求を提供しています。これにより、アトミックなテスト アンド セット型の操作が可能になります。 ドライバーは、宛先アドレス (u.AsyncLock.DestinationAddress) を指定するだけでなく、トランザクションの種類 (u.AsyncLock.fulTransactionType) も指定します。 操作のデータ値と引数の値 (詳しくは IEEE 1394 仕様を参照) は、u.AsyncLock.DataValues と u.AsyncLock.Arguments で渡されます。
バス リセットの世代
非同期 I/O を使用するデバイス ドライバーは、バス リセットの世代を追跡します。 各非同期要求で、デバイス ドライバーはその値を要求の IRB の u.AsyncXxx.ulGeneration メンバーで報告します。 バス ドライバーは、その値を実際の世代数と比較し、一致しなかった場合は状態値 STATUS_INVALID_GENERATION で要求を失敗させます。 このように要求が失敗した場合、ドライバーは REQUEST_GET_GENERATION_COUNT バス要求を使用して、正しい世代を照会する必要があります。 ただし、ドライバーは、そのバス リセット通知コールバックで新しい世代を取得するまで、この状態で失敗した要求を再発行してはなりません。 これにより、そのデバイスがバス上にまだ存在することが保証されます。 クライアント ドライバーは、バス リセットの通知を受け取るために IRP_MN_BUS_RESET に依存してはならないことに注意してください。 IRP_MN_BUS_RESET は、Windows XP 以降のオペレーティング システムでは廃止されています。