第 9 章 実行に当たっての問題
11.6 Kernel PlugIn の仕組み
11.6.5 Kernel PlugIn での割り込み処理
このサンプルでは、ユーザーモードの WinDriver アプリケーションから Kernel PlugIn ドライバへの アクセスを行います。デフォルトでは、KP_XXX Kernel PlugIn ドライバへのハンドルで、選択した PCI デバイスを開きます。成功した場合、セクション [11.6.3] の説明のとおり、Kernel PlugIn ドライ バと通信を行います。Kernel PlugIn へのハンドルを開くのに失敗した場合、デバイスとのすべての 通信をユーザーモードから実行します。
z xxx_diag: xxx_diag ユーザーモードアプリケーションのビルド用の Project および/または
make ファイル。
Windows プロジェクト ファイルは、x86\ (32 ビット) および amd64\ (64 ビット) ディレクトリ以下の ターゲット IDE のサブディレクトリ(msdev2005 / msdev2003 / msdev_6 / cbuilder4 / cbuilder3) にあります。
MSDEV ディレクトリには、Kernel PlugIn ドライバおよびユーザーモードアプリケーションのプロ
ジェクト用のワークスペース/ソリューションファイルも含まれています。
Linux および Solaris の makefile は、それぞれ linux/ および solaris/ にあります。
z xxx_files.txt: 生成されたファイルの一覧と生成されたコードのビルド手順
z xxx.inf: 対象のデバイスの WinDriver INF ファイル (Windows 98 / Me / 2000 / XP / Server 2003 / Vista で、PCI または PCMCIA などの Plug and Play デバイスの場合のみ)
ドライバ コード
WD_IntWait()
WinDriver カーネル ハードウェア
WD_IntWait()
ユーザー モード カーネル モード
割り込み 信号
図 11.2: Kernel PlugIn なしでの割り込みの処理
11.6.5.2 カーネルでの割り込み処理 (Kernel PlugIn あり)
Kernel PlugIn で割り込みを処理するには、Kernel PlugIn ドライバの名前をWDC_xxxDeviceOpen() 関数
へ渡すことによって、ユーザーモードアプリケーションが Kernel PlugIn ドライバでデバイスへのハンドルを開 き (PCI、PCMCIA、ISA)、そして fUseKP パラメータに TRUE を設定して、WDC_IntEnable() を呼びま す。低水準 WD_xxx() API に関する詳細は、WinDriver PCI 低水準 API リファレンスを参照してください。
ドライバ コード WD_IntEnable()
. .
WinDriver カーネル
KP_IntAtIrql() {
優先度の 高いコード }
KP_IntAtDpc() {
優先度の 低いコード }
WinDriver Kernel PlugIn
割り込み 信号 ユーザー モード
カーネル モード
ハードウェア
図 11.3: Kernel PlugIn ありでの割り込み処理
WDC_xxx API を使用しない場合、アプリケーションは、Kernel PlugIn ドライバへのハンドルを
WD_IntEnable() 関数またはラッパー InterruptEnable() 関数へ渡します (WD_IntEnable() と WD_IntWait() を呼びます)。Kernel PlugIn 割り込み処理を有効にします。(関数へ渡される
WD_INTERRUPT 構造体の hKernelPlugIn フィールド内に Kernel PlugIn ハンドルを渡します。) Kernel PlugIn で割り込みを有効にするために、WDC_IntEnable() / InterruptEnable() / WD_IntEnable() を呼ぶときに、Kernel PlugIn の KP_IntEnable() コールバック関数を有効にしま す。この関数で、Kernel PlugIn 割り込み処理へ渡される割り込みコンテキストを設定できます。また同様に、
ハードウェアで実際に割り込みを有効にするためにデバイスへの書き込みや、デバイスの割り込みを正確に 有効にするために必要なコードを実装できます。
Kernel PlugIn 割り込みハンドラが有効な場合、KP_IntAtIrql() が割り込みのたびに呼び出されます。
KP_IntAtIrql() 関数のコードは HIGH IRQL で実行されます。このコードの実行中はシステムが停止し ます (そのため、コンテキストスイッチや、優先度の低い割り込みが処理されません)。
KP_IntAtIrql() 関数内のコードは、次の制約があります。
z ページしないメモリに対してのみアクセス可能です。
z 次の関数だけを呼び出し可能です (または、これらの関数を呼び出したラッパー関数)。
○ WDC_MultiTransfer()、WD_Transfer()、WD_MultiTransfer() または WD_DebugAdd()。
○ 高い 割り込み要求レベルから呼び出される OS 固有のカーネル関数 (WinDDK 関数など)。
(これらの関数を使用すると、その他の OS とのコード互換性が損なわれる場合があるのでご 注意ください。)
malloc()、free() または上記の関数以外の WDC_xxx または WD_xxx API 関数は呼びません。
前述の制限のため、KP_IntAtIrql() に記述するコードはできだけ小さくします (レベルセンシティブ割 り込みの検知/消去など)。割り込み処理で実行するその他をコードを KP_IntAtDpc() で実装します。
KP_IntAtDpc() は、遅延した割り込みレベルで実行し、KP_IntAtIrql() と同じ制限を持っていま せん。KP_IntAtIrql() が戻り値を返した後に (TRUE を返した場合)、KP_IntAtDpc() を呼びます。
ユーザーモードで割り込み処理を行うこともできます。カーネルモードでの割り込み処理が終了した後に、
ユーザーモードの割り込み処理ルーティンを呼ぶ回数が KP_IntAtDpc() の戻り値となります。