クライアント実装シーケンスの処理

オプションの EvtSpbControllerLock および EvtSpbControllerUnlock イベント コールバック関数は、補完的な操作を実行します。 EvtSpbControllerLock 関数は、IOCTL_SPB_LOCK_CONTROLLER 要求のハンドラーです。 EvtSpbControllerUnlock 関数は、IOCTL_SPB_UNLOCK_CONTROLLER 要求のハンドラーです。 クライアント (つまり、バス上の周辺機器のドライバー) は、I/O 転送シーケンスを開始および終了するためにこれらの要求を送信します。 ほとんどの SPB コントローラー ドライバーは、IOCTL_SPB_LOCK_CONTROLLER および IOCTL_SPB_UNLOCK_CONTROLLER 要求をサポートしていないため、EvtSpbControllerLock および EvtSpbControllerUnlock 関数を実装しません。

クライアントは、一連の単純な転送要求 (つまり、IRP_MJ_READ および IRP_MJ_WRITE 要求) として I/O 転送シーケンスを実行できます。 シーケンス内の最初の転送には、IOCTL_SPB_LOCK_CONTROLLER 要求が先行する必要があります。この要求は、I/O 転送シーケンスの間バスをロックするように SPB コントローラー ドライバーに指示します。 最後の転送の後に、バスのロックを解除するようにドライバーに指示する IOCTL_SPB_UNLOCK_CONTROLLER 要求が続く必要があります。 このタイプの I/O 転送シーケンスは、単一要求シーケンスと区別するための「クライアント実装シーケンス」と呼ばれ、IOCTL_SPB_LOCK_CONTROLLER および IOCTL_SPB_UNLOCK_CONTROLLER 要求の代わりに IOCTL_SPB_UNLOCK_CONTROLLER 要求を使用します。

周辺機器のドライバーがバスのロックを保持している間、バス コントローラーはバス上の他の周辺機器へのアクセスを許可しません。 バス ロック操作の詳細は、バスの種類によって異なります。 I2C コントローラーの場合、転送方向の変更 (読み取りとそれに続く書き込み、またはその逆) には、I2C 再起動操作が必要です。 SPI コントローラーの場合、ターゲット デバイスに対するチップ選択はコントローラーのロックが有効な間、アサートされたままである必要があります。 詳細については、「Atomic Bus Operations」を参照してください。

クライアント実装の転送シーケンスのサポートは任意です。 SPB コントローラー ドライバーは、コントローラーが次の操作を実行できる場合にのみ、それらをサポートするように要求する必要があります。

  • クライアントが実装したシーケンスの間、バスをロックします。
  • いつでもバスのロックを解除します。 たとえば、バイト転送の間にロック解除要求が発生した場合、コントローラーは、バス経由の次のバイト転送を待たずにバスのロックを解除できる必要があります。

バスがロックされている間、クライアントは任意の一連の単純な転送要求を送信できます。 つまり、シーケンスは任意の長さにすることができ、読み取りと書き込みを自由に組み合わせにすることができます。

クライアント実装シーケンスのサポートを示すために、SPB コントローラー ドライバーは EvtSpbControllerUnlock 関数を実装します。 ドライバーがこの関数を実装する場合、SPB フレームワーク拡張機能 (SpbCx) は、クライアントからの IOCTL_SPB_LOCK_CONTROLLER および IOCTL_SPB_UNLOCK_CONTROLLER 要求を受け入れます。 それ以外の場合、STATUS_NOT_SUPPORTED のステータス コードを使用して要求を完了することによって、SpbCx はこれらの要求に失敗します。

EvtSpbControllerUnlock 関数を実装する SPB コントローラー ドライバーは、EvtSpbControllerLock 関数を実装するのに必要ありません。 ただし、EvtSpbControllerLock 関数を実装する SPB コントローラー ドライバーは、EvtSpbControllerUnlock 関数も実装する必要があります。

ドライバーが EvtSpbControllerUnlock 関数を実装しているが EvtSpbControllerLock 関数を実装していない場合、SpbCx は EvtSpbControllerUnlock 関数を呼び出して IOCTL_SPB_UNLOCK_CONTROLLER 要求を処理しますが、STATUS_SUCCESS のステータス コードを使用して IOCTL_SPB_LOCK_CONTROLLER 要求を完了するだけです。

ドライバーには、クライアントによって実装されたシーケンスの開始を検出する 2 つの方法があります。 まず、ドライバーが EvtSpbControllerLock 関数を実装している場合、SpbCx はこの関数を呼び出して、クライアントからの IOCTL_SPB_LOCK_CONTROLLER 要求を処理します。 ドライバーは、シーケンス内の最初の転送要求の前に発生するこの呼び出しに依存できます。 次に、ドライバーが EvtSpbControllerLock 関数を実装していない場合、ドライバーは、ドライバーがクライアントからの単純な転送要求を処理するときに SpbRequestGetParameters メソッドを呼び出すことができます。 要求された転送がシーケンスの最初の転送であることを示すために、このメソッドは、メソッドの出力構造体の Position メンバーを SpbRequestSequencePositionFirst に設定します。

EvtSpbControllerUnlock コールバックは、ドライバーがシーケンスの終了を判断できる唯一の方法です。 EvtSpbControllerUnlock 関数を実装していないドライバーは、クライアント実装シーケンスをサポートできません。