SerCx2 カスタム-受信トランザクション
一部のシリアル コントローラー ハードウェアは、シリアル コントローラーからデータを読み込むための PIO またはシステム DMA 以外のデータ転送メカニズムを実装する場合があります。 シリアル コントローラー ドライバーは、カスタム受信トランザクションをサポートして、このデータ転送メカニズムを SerCx2 で使用できるようにすることができます。
カスタム受信トランザクションを開始するために、SerCx2 はドライバーの EvtSerCx2CustomReceiveTransactionStart イベント コールバック関数を呼び出し、読み取り (IRP_MJ_READ) 要求とトランザクションの読み取りバッファーの説明をパラメーターとして提供します。 この呼び出しでは、関数はトランザクションを開始して返します。 その後、ドライバーはトランザクションを完了し、読み取り要求を完了する必要があります。
カスタム受信オブジェクトの作成
SerCx2 がシリアル コントローラー ドライバーの EvtSerCx2CustomReceiveTransactionXxx** 関数のいずれかを呼び出す前に、ドライバーは SerCx2CustomReceiveTransactionCreate メソッドを呼び出して、これらの関数を SerCx2 に登録する必要があります。 このメソッドは、ドライバーの EvtSerCx2CustomReceiveTransactionXxx** 関数へのポインターを含む SERCX2_CUSTOM_RECEIVE_TRANSACTION_CONFIG 構造体へのポインターを入力パラメーターとして受け取ります。
ドライバーは、次の 2 つの関数を実装する必要があります。
オプションとして、ドライバーは次の 3 つの関数の一部またはすべてを実装できます。
- EvtSerCx2CustomReceiveTransactionEnableNewDataNotification
- EvtSerCx2CustomReceiveTransactionInitialize
- EvtSerCx2CustomReceiveTransactionCleanup
SerCx2CustomReceiveTransactionCreate メソッドは、カスタム受信オブジェクトを作成し、呼び出し元ドライバーにこのオブジェクトへの SERCX2CUSTOMRECEIVETRANSACTION ハンドルを提供します。 ドライバーの EvtSerCx2CustomReceiveTransactionXxx** 関数はすべて、このハンドルを最初のパラメーターとして受け取ります。 次の SerCx2 メソッドは、このハンドルを最初のパラメーターとして受け取ります。
- SerCx2CustomReceiveTransactionNewDataNotification
- SerCx2CustomReceiveTransactionReportProgress
- SerCx2CustomReceiveTransactionInitializeComplete
- SerCx2CustomReceiveTransactionCleanupComplete
ハードウェアの初期化とクリーンアップ
一部のシリアル コントローラー ドライバーでは、カスタム受信トランザクションの開始時にシリアル コントローラー ハードウェアを初期化したり、トランザクションの終了時にシリアル コントローラーのハードウェア状態をクリーンアップしたりする必要があります。
ドライバーが EvtSerCx2CustomReceiveTransactionInitialize イベント コールバック関数を実装する場合、SerCx2 はこの関数を呼び出して、トランザクションを開始する前にシリアル コントローラーを初期化します。 EvtSerCx2CustomReceiveTransactionInitialize 関数を実装する場合、SerCx2CustomReceiveTransactionInitializeComplete メソッドを呼び出して、ドライバーがシリアル コントローラーの初期化を完了したときに SerCx2 に通知する必要があります。
ドライバーが EvtSerCx2CustomReceiveTransactionCleanup イベント コールバック関数を実装する場合、SerCx2 はこの関数を呼び出して、トランザクションの終了後にハードウェアの状態をクリーンアップします。 EvtSerCx2CustomReceiveTransactionInitialize 関数を実装する場合、SerCx2CustomReceiveTransactionCleanupComplete メソッドを呼び出して、ドライバーがシリアル コントローラーのクリーンアップを完了したときに SerCx2 に通知する必要があります。
新着データ通知
オプションとして、シリアル コントローラー ドライバーは EvtSerCx2CustomReceiveTransactionEnableNewDataNotification イベント コールバック関数を実装できます。 実装されている場合、SerCx2 はこの関数を使用して、カスタム受信トランザクションとして処理される読み取り要求の処理中に発生する間隔タイムアウトを効率的に管理します。
シリアル コントローラーが受信した 2 つの連続するバイト間の間隔が、クライアントが指定した最大時間を超えると、間隔タイムアウトが発生します。 周辺機器ドライバーが SerCx2 に読み取り要求を送信した後、シリアル接続された周辺機器から少なくとも 1 バイトのデータを受信するまで、間隔タイムアウトは発生できません。 読み取り要求の到着から周辺機器からのデータの最初のバイトの受信までの時間は、最初のバイトの受信後に読み取り要求の残りのデータを受信するために必要な時間よりも大幅に長くなる可能性があります。 詳細については、SERIAL_TIMEOUTSをご覧ください。
SerCx2 は、EvtSerCx2CustomReceiveTransactionEnableNewDataNotification 関数が実装されている場合に呼び出して、新しいデータ通知を有効にします。 この通知が有効になっていて、シリアル コントローラーが周辺機器から 1 つ以上の新しいデータを受信する場合、または既に受信 FIFO にデータがある場合、シリアル コントローラー ドライバーは SerCx2CustomReceiveTransactionNewDataNotification メソッドを呼び出して SerCx2 に通知する必要があります。
可能な間隔タイムアウトを検出するために、SerCx2 は定期的に EvtSerCx2CustomReceiveTransactionQueryProgress イベント コールバック関数を呼び出して、直前の間隔中にデータが受信されたかどうかを確認します。 SerCx2 がデータの最初のバイトの受信を検出する方法は、シリアル コントローラー ドライバーが EvtSerCx2CustomReceiveTransactionEnableNewDataNotification 関数を実装するかどうかによって異なります。 この関数が実装されている場合、SerCx2 は関数を呼び出して新しいデータ通知を有効にし、データの最初のバイトを受信するとドライバーによって通知されます。 それ以外の場合、SerCx2 は EvtSerCx2CustomReceiveTransactionQueryProgress 関数を定期的に呼び出して最初のバイトの受信を検出し、これらの呼び出しを行うためにプロセッサを定期的にスリープ解除する必要がある場合があります。 したがって、EvtSerCx2CustomReceiveTransactionEnableNewDataNotification 関数を実装するドライバーは、頻繁にスリープ解除するプロセッサを必要としないことによって電力消費量を削減できます。
SerCx2 は、カスタム受信トランザクションの保留中の新規データ通知を明示的に取り消しません。 ただし、シリアル コントローラー ドライバーは、通知が有効かつドライバーが次のいずれかの理由で関連する読み取り要求を完了する必要がある場合、新しいデータ通知を暗黙的に取り消す必要があります。
- 読み取り要求がタイムアウトするか、取り消されます。
- シリアル コントローラーは D0 デバイスの電源状態を終了し、低電力状態に入ります。
通常、ドライバーは WdfRequestComplete などのメソッドを呼び出して要求を完了します。 要求完了後、ドライバーは SerCx2CustomReceiveTransactionNewDataNotification を呼び出すことはできません。
要求オブジェクトへのアクセス
カスタム受信トランザクションを開始するために、SerCx2 はドライバーの EvtSerCx2CustomReceiveTransactionStart 関数を呼び出し、関連付けられている読み取り要求 (WDFREQUEST オブジェクト ハンドルにカプセル化) をパラメーターとしてこの関数に渡します。 ドライバーは、トランザクションが完了したときにこの要求を完了する WdfRequestComplete などのメソッドを呼び出す役割を担います。 要求をすぐに完了できない限り、EvtSerCx2CustomReceiveTransactionStart 関数が返される前に、ドライバーは WdfRequestMarkCancelableEx などのメソッドを呼び出して要求をキャンセル可能としてマークする必要があります。
シリアル コントローラー ドライバーは、WdfRequestRetrieveOutputBuffer などのメソッドを使用して、読み取り要求のデータ バッファーにアクセスすることはできません。 代わりに、ドライバーは、このバッファーにアクセスするために EvtSerCx2CustomReceiveTransactionStart 関数に渡される Mdl、Offset、Length パラメーター値を使用する必要があります。
カスタム受信トランザクション中に、ドライバーは、要求オブジェクトにアタッチされているコンテキストでトランザクションに関する情報の格納が必要になる場合があります。 その場合、ドライバーの EvtDriverDeviceAdd イベント コールバック関数は、WdfDeviceInitSetRequestAttributes メソッドを呼び出して、要求オブジェクトに使用する属性を設定できます。 これらの属性には、要求コンテキストに使用する名前と割り当てサイズが含まれます。 この呼び出しで指定された要求属性は、SerCx2InitializeDevice メソッドの呼び出しでドライバーが指定する要求属性と一致する必要があります。 これらの属性は、ドライバーが SerCx2InitializeDevice に渡す SERCX2_CONFIG 構造体の RequestAttributes メンバーで指定されます。 詳細については、「SERCX2_CONFIG」を参照してください。
シリアル コントローラー ドライバーがカスタム受信トランザクションの開始時に受信する読み取り要求の場合、ドライバー フレームワークによって割り当てられた要求コンテキストは初期化されていません。 ドライバーは、ベスト プラクティスとして、RtlZeroMemory ルーチンを呼び出して、この要求コンテキストをすべてのゼロに初期化する必要があります。