« Lattice XP2のUSB-JTAG書き込み | トップページ | データ転送速度190MBytes/sec達成!! »

2009.03.17

PCIのコンフィグ空間を読み書きするWDM

PCI デバイスの構成情報と場所情報の取得方法を参考にして、コンフィグ空間の読み書きができるようにしたのですが、DeviceIoControlの中からやるとブルー画面になってしまいました。

今、クリーム色の「WDMデバイスドライバ」という書籍を参考に作っていますが、このサンプルコードでは、DeviceIoControlのハンドラの中でスピンロックを取得しているようです。これがまずかったようです。
スピンロックというのは、カーネルモードのデバイスドライバの中のコードに排他制御をかけるためのしくみです。
あるCPUがI/O処理をしているときに別のCPUが同じリソースに対してI/O処理をしないようにするため、デバイスドライバのもっともコアな部分では排他制御が必要になることが多くあります。

しかし、スピンロックはIRPを下に送るとかいう抽象的な処理の際にはやってはいけないようですね。あくまでも低レベルのI/O処理ルーチンをロックするために使うべきなのでしょう。

ところで、「PCIデバッグライブラリ」では、バス番号やデバイス番号を自由に設定して他のデバイスのコンフィギュレーション空間を見ることができましたが、これはHalGetBusDataByOffeset()関数を使うことによって実現していました。
しかし、WDMでは、HalGetBusData()が使えなくなっていました。つまり、WDMのPCIドライバは、自分のデバイスのコンフィギュレーション空間しか見ることができません。

WDMの自分で作るデバイスドライバ(ファンクションドライバ)は、バスにアクセスするのではなく、バスドライバに処理を委託するのです。自分のデバイスのバス番号さえ、バスドライバから教えてもらうわけです。

NTからWindows2000に変わって、デバイスドライバでさえもやりたいことが自由にやらせてもらえない環境になりました。

PCIの持つメモリやI/O空間の情報を得る正当な方法は、PnPで IRP_MN_START_DEVICE が送られてきたとき(つまり、デバイスが開始したとき)に、AllocatedResourcesTranslated構造体の中身を解析することのようです。コンフィギュレーションレジスタに一切アクセスすることなく、BAR0~BAR5がどのアドレスに割り当てられたかや割り込みラインなどの情報も得られます。
要するに、Windows2000になってから、バスが抽象化され、バスに一切触ることなく、コンフィグレーション空間の知識も知らなくてもよくなり、安全なやり方が提供されるようになったのです。

それなら面倒なカーネルモードじゃなくてもいいじゃん、と思うのは私だけでしょうか。

|

« Lattice XP2のUSB-JTAG書き込み | トップページ | データ転送速度190MBytes/sec達成!! »

コメント

自己レスです。
WDMでも、WRITE_PORT_LONGなどのマクロが使えるので、I/Oポートの0xCF8や0xCFCを使って、他のPCIカードのコンフィグ空間へもアクセスできました。
さすがカーネルモード。

投稿: なひたふ | 2009.03.19 22:25

コメントを書く



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




« Lattice XP2のUSB-JTAG書き込み | トップページ | データ転送速度190MBytes/sec達成!! »