第 8 章 特定のチップ セットの拡張サポート
11.5 Kernel PlugIn の構造
11.5.1 構造の概要
ユーザーモードで記述したドライバは、デバイスにアクセスする際に WinDriver の関数 (WDC_xxx および/
または WD_xxx) を使用します。ユーザーモードで実装され、カーネルレベルのパフォーマンスの達成が必
要な関数 (割り込み処理など) の場合、WinDriver の Kernel PlugIn に移します。通常、ユーザーモードと
Kernel PlugIn の両方で同じ WinDriver API をサポートしているので、コードの修正をせずに、ユーザーモー
ドからカーネルへ WDC_xxx / WD_xxx 関数呼び出しを使用するようにコードを移行できます。
アプリケーション ( YourApp.EXE )
ドライバ コード
WinDriver ユーザーモード ライブラリ
(WinDrvr.h)
WinDriver カーネル
(WinDrvr.VXD、
WinDrvr.SYS) WinDriver
Kernel PlugIn 関数
KP_Init() KP_Open() KP_IntAtIrq() KP_IntAtDpc()
KP_Call() KP_Close()
Kernel PlugIn
I/O 割り込み 割り込み処理
メッセージ 受け渡し
WinDriver コンポーネント
記述するコンポーネント
ユーザー モード
カーネル モード
ハードウェア アプリケーション
( YourApp.EXE )
ドライバ コード
WinDriver ユーザーモード ライブラリ
(WinDrvr.h)
WinDriver カーネル
(WinDrvr.VXD、
WinDrvr.SYS) 記述するコンポーネント
WinDriver コンポーネント
WinDriver Kernel PlugIn 関数
KP_Init() KP_Open() KP_IntAtIrq() KP_IntAtDpc()
KP_Call() KP_Close()
Kernel PlugIn
I/O 割り込み 割り込み処理
メッセージ 受け渡し
ユーザー モード
カーネル モード
ハードウェア
図 11.1: KernelPlugIn の構造
11.5.2 WinDriver のカーネルと Kernel Plugin の相互作用
WinDriver のカーネルと WinDriver の Kernel PlugIn は次の 2 種類の相互作用があります:
1. 割り込み処理: WinDriver が割り込みを受信すると、ユーザーモードの割り込みハンドラーをデフォルト で有効にします。しかし、割り込みを Kernel PlugIn ドライバが処理するように設定し、WinDriver が割り 込みを受信すると、Kernel PlugIn ドライバのカーネルモードの割り込みハンドラーを有効にします。
Kernel PlugIn の割り込みハンドラーは、基本的に Kernel PlugIn へ移動する前に、ユーザーモードの
割り込みハンドラーで記述およびデバッグしたコードと同様ですが、ユーザーモードのコードの一部を 編集する必要があります。KernelPlugIn で割り込みの検知および処理を行うコードを再記述し、
KernelPlugIn の柔軟性を有効にします (セクション 11.6.5 を参照してください)。
2. メッセージ受け渡し: カーネルモードで関数を実行する場合 (I/O 処理関数など)、ユーザーモードのド ライバは WinDriver の Kernel PlugIn に「メッセージ」を渡します。このメッセージは特定の関数にマップ され、カーネル内で実行されます。この関数はユーザーモードで開発されたものと同じコードが含まれ ます。
ユーザーモード アプリケーションから Kernel PlugIn ドライバへメッセージを使用してデータを渡すことも できます。
11.5.3 Kernel Plugin コンポーネント
Kernel PlugIn の開発サイクルを終了すると、作成したドライバは以下のコンポーネントを持つことになります:
z WDC_xxx / WD_xxx API 関数で記述されたユーザーモード ドライバ アプリケーション(<アプリ ケーション名>/.exe)。
z WinDriver カーネルモジュール (windrvr6/.sys/.o)。
z カーネル レベルへ移動したドライバ機能を含む WDC_xxx / WD_xxx API 関数で記述された Kernel PlugIn ドライバ (<Kernel PlugIn ドライバ名>/.sys/.o)
11.5.4 Kernel PlugIn イベント シーケンス
以下、Kernel PlugIn で実装できるすべての関数の一般的なイベント シーケンスです:
11.5.4.1 ユーザーモードから Kernel PlugIn ドライバへのハンドルを開く イベント / コールバック 備考
イベント:
Windows は Kernel PlugIn ドライバをロードしま す。
このイベントはブート時にダイナミックロードにより行 われるか、またはレジストリからの指示として行われ ます。
コールバック:
KP_Init() Kernel PlugIn ルーチンを呼び出し ます。
KP_Init() が WinDriver に KP_Open() ルー チンの名前を知らせます。アプリケーションがドライ バを開く場合 (Kernel PlugIn ドライバを開く名前で WDC_xxxDeviceOpen() を呼び出す場合か、ま たは (ラッパー WDC_xxxDeviceOpen() 関数に 呼び出される) 低レベルの
WD_KernelPlugInOpen() 関数を呼び出す場
合)、WinDriver はこのルーチンを呼び出します。
イベント:
ユーザーモードドライバアプリケーションは
Kernel PlugIn ドライバを開く名前で
WDC_xxxDeviceOpen() を呼び出すか、また は (ラッパー WDC_xxxDeviceOpen() 関数に 呼び出される) 低レベルの
WD_KernelPlugInOpen() 関数を呼び出しま す。
コールバック:
KP_Open() Kernel PlugIn ルーチンを呼び出し ます。
KP_Open() 関数は WinDriver への Kernel PlugIn ドライバで実装した全コールバック関数名の通知に 使用されます。また、必要に応じて Kernel Plugin ド ライバの開始に使用されます。
11.5.4.2 Kernel PlugIn からのユーザーモード要求処理 イベント / コールバック 備考
イベント:
アプリケーションは WDC_callKerPlug()、ま たは低レベルの WD_KernelPlugInCall() 関数を呼び出します。
アプリケーションは WDC_CallKerPlug() / WD_KernelPlugInCall() を呼び出し、(Kernel
PlugIn ドライバの) カーネルモードでコードを実行し
ます。アプリケーションは Kernel PlugIn ドライバへ メッセージを渡します。 Kernel PlugIn ドライバは送ら れたメッセージに従って実行するコードを選択しま す。
コールバック:
KP_Call() Kernel PlugIn ルーチンを呼び出し ます。
KP_Call() はユーザーモードより渡されたメッ セージに従ってコードを実行します。
11.5.4.3 割り込み処理の有効化/無効化および高い割り込み要求処理 イベント / コールバック 備考
イベント:
アプリケーションは fUseKP 引数に TRUE を設定 して WDC_IntEnable() を呼ぶか (Kernel PlugIn でデバイスを開いた後)、または、
KernelPlugIn ドライバへのハンドルでより低レベ
ルな InterruptEnable() または
WD_IntEnable()関数を呼びます (関数へ渡さ
れた WD_INTERRUPT 構造体の
hKernelPlugIn フィールドに設定)。 コールバック:
KP_IntEnable() Kernel PlugIn ルーチンを呼 び出します。
この関数には Kernel PlugIn の割り込み処理に必要 な初期化設定を含めてください。
イベント:
ハードウェアが割り込みを発生します。
コールバック:
高い IRQL の Kernel PlugIn の割り込み処理 ルーチン - KP_IntAtIrql() (レガシー割り 込み) または KP_IntAtIrqlMSI() (MSI / MSI-X) を呼び出します。
KP_IntAtIrql() とKP_IntAtIrqlMSI() は 高い優先度で実行されるため、基本的な割り込み 処理 (割り込みを識別するために、レベル センシ ティブ割り込みの HW 割り込みシグナルの低くする など) だけを実行します。
より多くの割り込み処理が必要な場合、
KP_IntAtDpc() または KP_IntAtDpcMSI() で追加処理を引き継ぐために KP_IntAtIrql() (レガシー割り込み) または KP_IntAtIrqlMSI() (MSI / MSI-X) は TRUE を返します。
イベント:
割り込みが Kernel PlugIn で有効になっている場 合 (割り込みを有効にするイベントの詳細を参 照) 、アプリケーションは WDC_IntDisable() を呼び出すか、または、低レベルの
InterruptDisable() または
WD_IntDisable() 関数を呼び出します。
コールバック:
KP_IntDisable() Kernel PlugIn ルーチンが 呼び出されます。
この関数は KP_IntEnable() コールバックにより 割り当てられたメモリを解放します。
11.5.4.4 割り込み処理 – 異なる処理の呼び出し イベント / コールバック 備考
イベント:
Kernel PlugIn の高い IRQL の割り込みハンドラ - KP_IntAtIrql() または
KP_IntAtIrqlMSI() が TRUE を戻します。
カーネルで引き継いだ手順 (DPC) として追加の割 り込み処理を WinDriver へ伝えます。
コールバック:
Kernel PlugIn の DPC 割り込みハンドラ - KP_IntAtDpc() (レガシー割り込み) または
残りの割り込みコードを処理しますが、高い IRQL 割り込み処理よりは優先度が低いです。
KP_IntAtDpcMSI() (MSI / MSI-X) を呼び出 します。
イベント:
DPC 割り込みハンドラ - KP_IntAtDpc() は KP_IntAtDpcMSI() よりも大きい値を戻しま す。
ユーザーモードで処理するための割り込みコードが 必要です。
コールバック:
WD_IntWait() を戻します。
ユーザーモード割り込みハンドラ ルーチンが実行さ れます。
11.5.4.5 Plug-and-Play およびパワー マネージメント イベント / コールバック 備考
イベント:
アプリケーションは fUseKP 引数に TRUE を設定
して WDC_EventRegister() を呼んで、
Kernel PlugIn ドライバを使用して、Plug-and-Play およびパワーマネージメントの通知を受け取るよ うに登録します (Kernel PlugIn でデバイスを開い た後)。または、Kernel PlugIn ドライバへのハンド ルでより低レベルな EventRegister() または WD_EventRegister() 関数を呼び出します (関数に渡された WD_EVENT 構造体の hKernelPlugIn フィールドに設定)。
イベント:
Plug-and-Play またはパワー マネージメント イベン トが発生します。
コールバック:
KP_Event() が呼び出されます。
KP_Event() は、発生したイベントについての情 報を受け取ります。
イベント:
KP_Event() は TRUE を返します。
イベントは、ユーザーモードアプリケーションで処理 される必要があります。
コールバック:
WD_Intwait() を返します。
ユーザーモード割り込みハンドラアプリケーションイ ベントハンドラで処理を再開します。