« PCIeコアを更新(バースト転送対応) | トップページ | Lattice XP2のUSB-JTAG書き込み »

2009.03.13

WDM版の汎用PCIドライバ

WDM版の汎用PCIドライバを開発中です。
WDMではNTドライバと違い、建前上は自分で作ったドライバは下位のバスに接続されていることになります。その下位のバスのドライバは、プラグアンドプレイによって、アドインカードを見つけます。

だから、自分で作ったWDMドライバは、親ドライバから呼び出してもらうことによって、はじめて起動されます。
(NTドライバはサービスマネージャでいつでも起動できたのと対照的です)

よってPCI ExpressデバイスはPCIバスドライバから起動されますが、汎用PCIデバッグライブラリのように、カーネルモードでI/Oやメモリを自由にアクセスしたいドライバはどうすればよいのでしょうか?

この場合、親ドライバがいないので、パソコンの起動時にUnknownドライバ(正しい名前はわからない)から起動してもらうようです。このようなドライバは、コントロールパネルから「ハードウェアの追加」で強制的にインストールできます。

現在開発中の「PCI Express汎用デバイスドライバ」は、PCIカードのドライバとしてもインストールでき、また宙に浮いた単独のドライバとしてもインストールできるようにしました。

Devman

上の図は、同じドライバを、PCIカードと宙に浮いたドライバの2つインストールした場合の表示です。SYSファイルはひとつですが、どちらも独立して動いています。

さて、親ドライバの種類は、IoGetDeviceProperty()という関数を発行することで調べられるようです。この関数の引数にDevicePropertyEnumeratorNameを与えると、親ドライバの名前が返ってきます。これをAddDeviceの中でやることで、自分が何ドライバなのかを知ることができるというわけです。


status = IoGetDeviceProperty(pdo,
DevicePropertyEnumeratorName,
sizeof(tmp),
(PVOID)&tmp[0],
&length);
if(status == STATUS_SUCCESS)
{
if(!TkWStrCmp(tmp,L"Root"))
{
DebugPrint("Enumerator type is ROOT. This is a generic I/O driver.");
}
else if(!TkWStrCmp(tmp,L"PCI"))
{
DebugPrint("Enumerator type is PCI. This is a PCI device driver.");
isPci = TRUE;
}
else
{
DebugPrint("Enumerator type is unknown... Failed !");
return STATUS_UNSUCCESSFUL;
}
}

それがL"PCI"であれば、PCIバスドライバが親ドライバになっていることがわかります。
それがL"Root"であれば、親ドライバはなく、単独で存在しているドライバとなります。

PCIならば、IoGetDeviceProperty()をさらに使って、バス番号やデバイス番号を調べられます。
NT形式のドライバは、目的のアドインカードを探すため、バス番号とかを変えてスキャンしなければなりませんでした。WDMではPnPですから、ドライバの起動時にすでにバス番号・デバイス番号・ファンクション番号がわかっています。それは、下位のドライバに問い合わせることによって得られます。

また、NTドライバは、I/Oポートの0xCF8番とかを直接叩いてPCIのコンフィギュレーション空間にアクセスしていましたが、WDMではそれは良い方法とはされていません。

WDMでは、PCIバスドライバに対してIRP_MN_READ_CONFIGやIRP_MN_WRITE_CONFIGを発行することによって、PCIのコンフィギュレーション空間にアクセスするのが正当な方法のようです。やってみたら、確かにうまくいきました。コンフィグレジスタが読み出せています。
Config_rd_2

PCIコンフィグレジスタの読み書きは、デバイスドライバ内で自分でI/O操作をやるのではなく、下位のドライバに処理を依頼するようです。

このようにPCIのコンフィグ空間は隠蔽され仮想化されてしまいました。できる限りユーザにハードウェアをアクセスさせたくないようです。デバイスドライバなのに。

ところで、PCIのコンフィギュレーション空間は256バイトでしたが、PCI Expressでは4096バイトに拡張されました。上記の関数でPCI Express拡張コンフィギュレーションにアクセスできるかと思いましたが、だめなようです。

どうせ仮想化してくれるのであれば、拡張コンフィギュレーション空間にアクセスする方法も提供してほしかったです。もしかしたらそういう関数がすでにあるのかもしれません。

|

« PCIeコアを更新(バースト転送対応) | トップページ | Lattice XP2のUSB-JTAG書き込み »

コメント

コメントを書く



(ウェブ上には掲載しません)




« PCIeコアを更新(バースト転送対応) | トップページ | Lattice XP2のUSB-JTAG書き込み »