アドテックシステムサイエンス aPCI-P54 Linux デバイスドライバ


概要

本ドライバは アドテックシステムサイエンス社製 PCIボード aPCI-P54,入出力48点 TTLレベルパラレルI/Oボードをユーザプログラムから使用するための デバイスドライバ(モジュール)である.I/Oアクセスに限れば,Linuxでは root の権限のプロセスから直接操作可能であるが,本ドライバでは 若干のオーバヘッドはあるものの一般ユーザの権限での I/Oアクセス, さらには割り込み機能の利用を可能とする.

特徴

本ドライバは以下の特徴を有する. (*): 実装したのみで実際には機能は確認していない.

コンパイル・ロード

コンパイルはソース,ヘッダファイルを用意し,
gcc -c apcip54.c -DLINUX -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -m486
で行う. これにより apcip54.o が作成される.できた apcip54.o はLinuxの モジュールである. root になって insmod apcip54 でモジュールが ロードされる. この際, コンソールにはドライバのボード認識情報が 表示される. モジュールの除去は rmmod apcip54 である.

本ドライバはデバイスドライバのメジャー番号58(暫定)を使用する (マイナー番号は現在チェックしていないが, 将来的には 他のADなどのボードと区別することになると考えられる). アクセスするために デバイスファイルが必要となるため, mknod で 作成する. 方法は mknod /dev/apcip54 c 58 0 である. これは root で一度実行すれば良い.

Makefile による make

必要ならば, Makefile の冒頭のデバイスのメジャー番号, RDTSC使用の 有無(Pentium以降なら推奨)を変更の上, make する. Slackware 3.5(kernel 2.0.36,gcc: 2.7.2.3)で問題ないことを確認している. そのあと root で make makedev とすることで, デバイスファイルを作成する. make ins でドライバ(モジュール)の登録ができる.

コンフィギュレーション


ボード・ドライバの使用法の概要

以下にあらわれる ioctl へのリクエスト番号は後述する.

1:root権限で直接操作

/dev/apcip54 を open() した後, ioctl にてドライバに aPCIP54_CHECKBSN と ボードの設定BSNをわたし, ボードの存在を確認する. BSNが不明な場合, BSN に0-15を順次指定し, 検索すれば良い. BSNが確定後, aPCIP54_BASEADDRESS により, I/Oのベースアドレスを取得, 得られた アドレスを基準に inb/outb などの関数(-O2オプションをつけてコンパイル すると, インライン展開される)を用いて直接アクセスする. なお, ボードのアドレスを得た場合, close() してもかまわない.

2:ドライバ経由の間接操作

これには root の権限は不要である. /dev/apcip54をopen()しaPCIP54_CHECKBSN でボードを確認するところまでは同じである. ベースアドレスは必要ない. I/Oのアクセスは aPCIP54_READPORT, aPCIP54_WRITEPORT により行う. これには引数として, ボード識別のための BSN(0-15)およびポート番号 (0-15), ポートの値を含む構造体 struct aPCIP54port へのポインタを渡す. ポートに対して, 一括の入出力を行うaPCIP54_READPORTBSN, aPCIP54_WRITEPORTBSN もあり, その場合, BSN, 書き込み時のマスク, ポート値の配列を含む aPCIP54portBSNを渡す.

3:割り込みの使用

割り込みの利用にもrootの権限は不要である. /dev/apcip54 をopen()し BSNを取得する. その後, ioctl() にて aPCIP54_SETIRQMASK リクエストを 行い, 応答する割り込みを設定する. 割り込みマスクは struct aPCIP54irq 内のirq_maskメンバで指定する. ビットが1であるところに対して 応答する. このマスクは全BSNに対応したものであり, 下位より4ビットずつ 各ボードの PC0,PC3,PF0,PF3 に対応する(全64ビット). すなわち, BSNに応じて, 適当なところを指定しなければならないが, 全ボードの 割り込みに対して一括して応答することが可能である. なお, ボード自体の割り込み設定は, aPCIP54_SETIRQMASKのリクエストの 処理過程で自動的に設定されるため, 操作する必要はない.

割り込みのマスクを指定したのち, select()システムコールにより, /dev/apcip54 を open した際のファイル記述子を読み込みで待機にする. 割り込みが発生した場合, もしくは引数で指定したタイムアウトを した場合に select()から実行が戻るため, 割り込みによる ものかを FD_ISSETにより確認する. なお, 割り込みは select()を 呼び出したあとに発生したものだけに応答し, それ以前に発生した ものには応答しない. 例外的に, 複数のデバイスに対して同時に selectを発行し, 他のデバイスが先に読み取り可能になった場合には 次のselectまでに受けた割り込みに対しても応答する.
割り込み直後の割り込み発生ボードの全ポートの値および, 発生時間は aPCIP54_GETINTERRUPTSTATUS リクエストで確認できる. これは 最後に発生した割り込みの状況を保存する. 発生時間はPentium 以降のCPUに装備されている RDTSC 命令によるもので, リセット後に CPUのサイクルごとに0からカウントアップする64bit のカウンタの 値である(最新のCPUでも千年程度は単調増加が保証されることが計算できる).
なお, Pentium以前のCPUなどで RDTSCをサポートしていない場合は, ソース頭部の #define USERDTSC をコメントアウトする. その場合, Linuxの内部タイマによる数値(一般に100/sec)が使用される.

実際の割り込み発生からの応答速度であるが, マルチタスクOSであるが ゆえに, 一概に言えない. 期待値としては以下のようになる.


ioctl リクエスト一覧

ボードの認識確認

ボード値取得リクエスト

リクエストには次の構造体へのポインタを引数とする.
struct aPCIP54value
{
  int bsn;                  // BSN指定
  int value;                // 値入力
};
bsn はボード番号をあらかじめ指定し, ioctlが成功した場合, value に 値が返る.

1ポート入出力

リクエストには次の構造体へのポインタを引数とする.
struct aPCIP54port
{
  int bsn;         // BSN指定
  int port;        // ポート指定
  int value;       // 値指定/読み込み結果
};
bsn はボード番号(0-15)を指定し, port は読み書きするオフセット(0-15, 0-5:通常ポート,6:方向設定, 15:ローカルコントロール)である. 書き込み時はvalue(0-255)を事前設定し, 読み出し時にはvalueに値(0-255)が返る.

ボード一括ポート入出力

リクエストには次の構造体へのポインタを引数とする.
struct aPCIP54portBSN
{
  int bsn,mask;             // BSN および 書き込みマスク指定
  unsigned char ports[8];   // 入出力データ
};
bsn(0-15) はボード番号を指定, mask は書き込み時のマスクを指定する. ports は書き込み/読み取り内容.

割り込み


付属チェックプログラム apcip54check

本プログラムは最低限の機能チェックを行うためのプログラムである. 起動オプションは特にない. 4種類のコマンドがあり, である. 数値はすべて16進数で指定する. 割り込みマスクを設定した上で, 割り込みを検出すると, その情報が表示される (自分自身のポート出力にも割り込みは応答するため, ボード単体で試験可能).
例:
% ./apcip54check
check aPCIP54: BSN 0: no board
check aPCIP54: BSN 1: no board
check aPCIP54: BSN 2: no board
check aPCIP54: BSN 3: Exist       Base address:14F0  IRQ:10
check aPCIP54: BSN 4: no board
check aPCIP54: BSN 5: no board
check aPCIP54: BSN 6: no board
check aPCIP54: BSN 7: no board
check aPCIP54: BSN 8: no board
check aPCIP54: BSN 9: no board
check aPCIP54: BSN 10: no board
check aPCIP54: BSN 11: no board
check aPCIP54: BSN 12: no board
check aPCIP54: BSN 13: no board
check aPCIP54: BSN 14: no board
check aPCIP54: BSN 15: no board
o3 6 3                // ボード3のポート6=方向指定  PCのみ出力
o3 2 0                //           ポート2=PCに0を出力
m3 ff                 //           割り込みマスクを全有効
irq mask: 000000000000F000       // 割り込みマスクの表示(確認)
o3 2 1                //           PC0をビット立て
Interrupt detected:   //           割り込み検出
Interrupt: 0000000000001000     BSN:port 3:PC0   // ボード3 PC0
time: 112624950631326,  delay:0.066939[msec]     // 時間
interrupt count: 1                  // 割り込み回数
ports: FF FF 01 FF FF FF            // 割り込み時のポート状態
quit
%
なお, delay と表示されているのは, 割り込み発生後に select()により ユーザプロセスに実行が移るまでの概算の時間である. apcip54check.c の 冒頭のCPUCLOCKにより計算されるので, コンピュータに応じて変更すること.

本ドライバについて



熊谷正朗/くまがいまさあき/Masaaki KUMAGAI kumagai@emura.mech.tohoku.ac.jp