ハードウェア制御が出来る PCIDEBUG.DLL を、Pythonから呼べるようにする
ご存知とは思いますが、Windowsは基本的にハードウェア資源に直接アクセス出来ません。
ところが、世の中には便利なものを物を作る方も居られまして、ガジマルの森さんの所で提供されているPCIDEBUG.DLLでは、以下のハードウェア資源にアクセスできます。
- PCIコンフィギュレーションレジスタ空間へのアクセス
- I/O空間へのアクセス
- 物理メモリへのアクセス
- 割り込みのインターセプト
組み込み制御を行いたい時に、非常に便利ですよね?
ってな訳で、先の ctypesのネタを使って、PCIDEBUG.DLLをPythonから呼び出せるようにしてみましょう。
準備
ダウンロードページから、以下のファイルをダウンロードします。
- pdbg10.lzh
展開後、Pythonコードの作成と実行に必要なのは、以下のファイルです。
- Pcidebug.sys
- PCIDEBUG.DLL
- Pcidef.h
- Pcifunc.h
ヘッダファイルから ctypes コードを生成する
まずは、pcifunc.hから、XMLを生成しましょう。
…の前に、pcifunc.hに以下の行を追加してください。
(実は、この行が必要だと言う事を知らず、何度も挑戦して敗れ去ってしまいました。あはは)
/* PCIDEBUG.DLL export 関数 */ #include <windef.h> # <- この行が重要 #ifndef _NTDDK_
では早速。
F:\Wacky\Test\python\test>python C:\tool2\Python24\Lib\site-packages\ctypes\wrap \h2xml.py F:\Wacky\Test\python\test\Pcifunc.h -I "C:\Program Files\Microsoft Vis ual Studio\VC98\Include" -o pcifunc.xml -q -c
これで、pcifunc.xmlが出来ました。
では、XMLファイルからPythonコードを生成します。
F:\Wacky\Test\python\test>python C:\tool2\Python24\Lib\site-packages\ctypes\wrap \xml2py.py pcifunc.xml -o pcifunc.py -l pcidebug.dll # unresolved alias: iscsymf = __iscsymf # unresolved alias: MB_CUR_MAX = __mb_cur_max # unresolved alias: toascii = __toascii # unresolved alias: wcswcs = wcsstr # unresolved alias: NTSYSAPI = DECLSPEC_IMPORT # unresolved alias: iscsym = __iscsym
これで完了です。pcifunc.pyが出来ています。
信じられない程の、簡単さです。
動かしてみる
では早速動かしてみましょう。
動かす際、pcifunc.pyと同じフォルダに、pcidebug.dllとpcidebug.sysがある事を確認してください。
F:\Wacky\Test\python\test>ipython F:\Wacky\Test\python\test>python C:\tool2\Python24\Scripts\ipython WARNING: Could not import user config! ('C:\Documents and Settings\user\_ipython/ipy_user_conf.py' does not exist? Please run '%upgrade') Python 2.4.2 (#67, Sep 28 2005, 12:41:11) [MSC v.1310 32 bit (Intel)] Type "copyright", "credits" or "license" for more information. IPython 0.7.2 -- An enhanced Interactive Python. ? -> Introduction to IPython's features. %magic -> Information about IPython's 'magic' % functions. help -> Python's own help system. object? -> Details about 'object'. ?object also works, ?? prints more. In [1]: import pcifunc In [2]: pcifunc.getdllstatus() Out[2]: 0 # ↑PCIDEBUG.DLLが呼び出し可能である事を確認。 In [3]: pcifunc._pciBusNumber() Out[3]: 3 # ↑このパソコンでは、PCIバスの最大数は3。 In [4]: hex(pcifunc._pciConfigReadLong(0, 0)) Out[4]: '0x25788086L' # ↑バス番号:0,デバイス番号:0,ファンクション番号:0のレジスタ番号:0の、PCIレジスタ値。 In [5]: hex(pcifunc._pciConfigReadLong(1 << 3, 0)) Out[5]: '0x25798086L' # ↑バス番号:0,デバイス番号:1,ファンクション番号:0のレジスタ番号:0の、PCIレジスタ値。 In [6]: hex(pcifunc._pciConfigReadLong(2 << 3, 0)) Out[6]: '0xFFFFFFFFL' # ↑バス番号:0,デバイス番号:2,ファンクション番号:0のレジスタ番号:0の、PCIレジスタ値。
どうやらアクセスできたっぽいです。
試しに、pdbg10.lzhに付属している。PCIデバイスの列挙ツール(pciwatch.exe)で確認してみましょう。
PCIDEBUG.DLL posted from フォト蔵
デバイス(Device)一覧に出てくる、'0 0 0 : 8086 2578'は、バス番号、デバイス番号、ファンクション番号、レジスタ0のワード値(ベンダID)、レジスタ2のワード値(デバイスID)という意味です。
上の結果と合わせてみると、確かに合ってます。
どうやら、呼び出し出来たようです。