記憶域クラス ドライバーの BuildRequest ルーチン
すべての上位レベルのカーネル モード ドライバーと同様に、記憶域クラス ドライバーは、記憶域周辺機器への要求を処理するときに、次の下位ドライバーの IRP の I/O スタックの場所を設定する必要があります。 クラス ドライバーがシステム提供のポート ドライバーの SRB を使用して設定する IRP では、ポート ドライバーの I/O スタックの場所は次のように設定されます。
MajorFunction には、IRP_MJ_SCSI が含まれています
Parameters.Scsi.Srb には、SRB へのポインターが含まれています
各クラス ドライバーは、SRB のメモリを割り当てるだけでなく、基になるストレージ ポート ドライバーの CDB を使用して設定する役割を担います。 クラス ドライバーは、ExInitializeNPageLookasideList を使用してその SRB のルックアサイド リストを設定するか、非ページ メモリの ExAllocatePool を呼び出すことができます。 ルックアサイド リストと非ページ プールの使用の詳細については、ルックアサイド リストの使用を参照してください。
プールからメモリを割り当てる場合でも、ドライバーが作成したルックアサイド リストからメモリを割り当てる場合でも、すべての記憶域クラス ドライバーは、SRB に割り当てるメモリを解放する役割を担います。 記憶域クラス ドライバーの IoCompletion ルーチンは、記憶域クラス ドライバーの IoCompletion ルーチンで説明されています。通常は、SRB に割り当てられたメモリをルックアサイド リストに解放します。
クラス ドライバーの BuildRequest ルーチンは、デバイスと通信するために設定した CDB の長さを含め、SRB メンバーに適切な値を設定する必要があります。 要求センス情報を返す要求や、ドライバーが再試行する必要がある可能性がある要求の場合は、IRP で IoCompletion ルーチンを設定します。 読み取り要求または書き込み要求の場合は、それぞれ適切な転送方向 (SRB_FLAGS_DATA_IN または SRB_FLAGS_DATA_OUT) で SrbFlags を使用します。
BuildRequest ルーチンは、SendSrbSynchronous ルーチンと SendSrbAsynchronous ルーチンのペアで SRB を設定する責任を共有する場合があります。 つまり、 BuildRequest ルーチンは、すべての要求に対して一般的に設定される SRB メンバーを設定できます。一方 、SendSrbXxx ルーチンは、各要求の種類にのみ関連する SRB 値を設定します。 IRP が SendSrbAsynchronous ルーチンからポート ドライバーに渡される場合、IRP は、ドライバーが提供する IoCompletion ルーチンを使用して設定する必要があります。
クラス ドライバーが読み込まれた後、ほとんどの SRB を Function メンバーで SRB_FUNCTION_EXECUTE_SCSI に設定し、バス経由で送信するデバイス I/O 要求を示します。
システム定義 SRB メンバーとその値の詳細については、SCSI_REQUEST_BLOCK を参照してください。
センス データ要求用の SRB の設定
クラス ドライバーは、ターゲット コントローラーがチェック条件を返すときに、ポート ドライバーが SCSI センス データ要求または同等の情報を返すように要求できます。 これを行うために、クラス ドライバーは SRB に SenseInfoBuffer ポインターと SenseInfoBufferLength を設定し、チェック条件が発生した場合にポート ドライバーがセンス データ要求情報を返すことができるようにします。 ポート ドライバーは、IRP を返すときに、SRB_STATUS_AUTOSENSE_VALID を持つ SrbStatus メンバーを設定することによって、センス データ要求情報を返したことを示します。 InterpretSenseInfo ルーチンの詳細については、記憶域クラス ドライバーの InterpretRequestSense ルーチンを参照してください。
再試行
記憶域クラス ドライバーは、ターゲット/コントローラーのエラー、バスのリセット、または要求タイムアウトのために失敗した要求を再試行する役割を担います。 そのため、多くのクラス ドライバーは IRP の独自の I/O スタックの場所に再試行回数を保持します。 このようなクラス ドライバーの BuildRequest ルーチンは、IoCompletion ルーチンを設定し、IRP をポート ドライバーに送信する前に、特定の要求の再試行制限を初期化することもできます。 RetryRequest ルーチンの詳細については、記憶域クラス ドライバーの RetryRequest ルーチンを参照してください。