第 9 章 実行に当たっての問題
10.2 ユーザーモード ドライバのパフォーマンスの向上
一般的にメモリ マップの領域への転送は、I/O マップの領域への転送よりも高速です。これは、WinDriver では関数を呼び出さずに、ユーザーモードからメモリ マップの領域に直接アクセスできるためです (10.2.1 を参照)。
また、WinDriver API ではブロック (文字列) 転送を使用したり、いくつかのデータ転送関数の呼び出しを 1 つのマルチ転送関数の呼び出しにまとめて (10.2.2 を参照)、I/O およびメモリ データ転送のパフォーマンス を向上できます。
10.2.1 メモリ マップの領域への直接アクセス
WDC_xxxDeviceOpen() 関数 (PCI / PCMCIA / ISA) または低レベル WD_CardRegister() 関数で PCI / PCMCIA / ISA を登録すると、ユーザーモードおよびカーネルモードにおけるカードの物理メモリ領域 へのマップが返されます。これらのアドレスを使用して、どちらのモードからでもカード上のメモリ領域へ直接 アクセスできます。これにより、ユーザーモードとカーネルモード間のコンテキスト スイッチとメモリへアクセス するための関数呼び出しのオーバーヘッドを取り除きます。
WDC_MEM_DIRECT_ADDR マクロは、カード上の指定されたメモリ アドレス領域に直接アクセスするための ベース アドレス (ユーザーモードから呼び出された場合はユーザーモード マップ、Kernel PlugIn ドライバ
[第 11 章 ] から呼び出された場合はカーネルモード マップ) を返します。マップされたベース アドレスを指
定 さ れ た メ モ リ 領 域 内 の オ フ セ ッ ト と 共 に WDC_ReadMem8/16/32/64 マ ク ロ や WDC_WriteMem8/16/32/64 マクロへ渡し、ユーザーモードまたはカーネルモードから、カード上のメモ リ アドレスに直接アクセスすることができます。
さらに、WDC_ReadAddrBlock() と WDC_WriteAddrBlock() を除く WDC_ReadAddrXXX() 関数お よび WDC_WriteAddrXXX() 関数はすべて、呼び出しコンテキスト (ユーザーモードまたはカーネルモー ド) のマップを使用して、直接メモリ アドレスにアクセスします。
低レベル WD_xxx() APIを使用すると、WD_CardRegister() により、カード リソース アイテムの構造 体である pCardReg->Card.Item[i] の dwTransAddr フィールドおよび dwUserDirectAddr フィールドに保存されている、カードの物理メモリ領域のユーザーモード マップおよびカーネルモード マッ プが返されます。dwTransAddr は、WD_Transfer() や WD_MultiTransfer() の呼び出しにおい て、または Kernel PlugIn ドライバ [第 11 章 ] から直接メモリにアクセスする際に、ベース アドレスとして使用 します。ユーザーモードから直接メモリにアクセスするには、dwUserDirectAddr を通常のポインタとして 使用します。
どの方法でカード上のメモリにアクセスする場合でも、特に文字列転送コマンドを使用する際には、データ 型のサイズに応じてベース アドレスのアラインが重要です。または、転送を小さく分割します。データをアラ インする最も簡単な方法は、バッファを定義する際に、基本の型を使用することです。
例:
BYTE buf[len]; /* BYTE 転送の場合 – アラインなし */
WORD buf[len]; /* WORD 転送の場合 – 2 バイト境界でアライン */
UINT32 buf[len]; /*DWORD 転送の場合 – 4 バイト境界でアライン */
UINT64 buf[len]; /* QWORD 転送の場合 – 8 バイト境界でアライン */
10.2.2 ブロック転送および複数の転送のグループ化
メモリ アドレスや (メモリ アドレスとは異なり、直接アクセスすることができない) I/O アドレス から、またはメモリ アドレスや I/O アドレスへ大量のデータを転送するには、次の方法を使用して関数呼び出しオーバーヘッド およびユーザーモードとカーネルモード間のコンテキスト スイッチを削減し、パフォーマンスを向上させま す。
WDC_ReadAddrBlock() / WDC_WriteAddrBlock() または低レベル WD_Transfer() 関 数を使用してブロック (文字列) 転送を行う。
WDC_MultiTransfer() または低レベル WD_MultiTransfer() 関数を使用して複数の転 送を 1 つの関数呼び出しにまとめる。
10.2.3 64 ビット データ転送を行う
注意: 実際の 64 ビット転送の実行能力は、ハードウェア、CPU、ブリッジなどによる転送のサポートに依存 し、これらの仕様の組合せになどのよっても影響を受けます。
WinDriver は、サポートしている 64 ビット Windows および Linux プラットフォーム (一覧はセクション 9.6 を 参照) および 32 ビット Windows および Linux x86 プラットフォーム上での 、64 ビット PCI データ転送をサ ポートしています。PCI ハードウェア (カードおよびバス) が 64 ビットの場合、対象のホスト オペレーティング システムが 32 ビットでも、より高い処理能力をハードウェアに与えることができます。
この新しい技術は、32 ビットプラットフォームで以前では実現できなかったデータ転送の能力を飛躍的に高 めます。WDK または他のドライバ開発ツールで記述したドライバよりも高いパフォーマンスを WinDrinver で 開発したドライバが発揮します。Jungo Connectivity 社によるベンチマーク テストでは、64 ビット データ転送 で 32 ビット データ転送に比べ、データ転送速度が飛躍的に向上する結果が得られました。WinDriver で開 発されたドライバは、通常の 32 ビット データ転送で得られる性能よりも高い数字を得られることが実証されま した。
次の方法で 64 ビット データ転送を実行できます。
WDC_ReadAddr64()または WDC_WriteAddr64() を呼び出す。
アクセス モード WDC_SIZE_64 と共に WDC_ReadAddrBlock()または WDC_WriteAddrBlock() を呼び出す。
QWORD 読 み 取 り/書 き 込 み 転 送 コ マ ン ド と 共 に WDC_MultiTransfer()、 低 レ ベ ル WD_Transfer()、または WD_MultiTransfer() を呼び出す (詳細は、各関数の説明を参 照してください)。
WDC_PciReadCfg64() / WDC_PciWriteCfg64() ま た は WDC_PciReadCfgBySlot64() / WDC_PciWriteCfgBySlot64() を使用して、PCI 設定空間からまたは PCI 設定空間への 64 ビット転 送を実行することもできます。
第 11 章
Kernel PlugIn について
この章では、WinDriver の Kernel PlugIn の機能について説明します。
注意: Windows CE にはカーネルモードとユーザーモードの区別がないため Kernel PlugIn を実行できま せんが、Kernel PlugIn を使用しなくても最高のパフォーマンスを達成できます。
Windows CE で割り込み処理率を向上するには、セクション 9.2.9 を参照してください。