uPD7210 ドライバ
for FreeBSD-4.8 RELEASE.
■ 概要 ■
これは、日本電気製のGPIBドライバIC uPD7210を使用したGPIBカードを、
FreeBSDで使用するためのデバイスドライバです。
サポートしているカードは、以下のとおりです。
(PC9801用)
日本電気 PC-9801-29(N)
(PC互換機用)
コンテック GP-IB(PC)L
コンテック GP-IB(PCI)L
汎用部分がほとんどなので、少しの改造で uPD7210を使った他社のボードでも
動作可能と思われます。
■ 仕様/特徴 ■
トーカ機能、リスナ機能、コントローラ機能を持ちます。
GPIBの規格どおり、複数のリスナに対し同時に転送が可能です。
コントローラ専用です。(いまのところ...)
自アドレスは、30固定です。MY_ADDRESSを書き換えてコンパイルすることで、
変更が可能です。
一回に1KB以上の転送はできません。1KBをオーバーする場合は、そこで転送が
打ち切られます。GPIB_BUFFERSIZEを書き換えてコンパイルすることで変更が
可能です。
SRQ機能は、実装していません。
ポーリングは、serial pollのみ実装しています。
■ ダウンロード ■
ここからダウンロードできます。
http://www.youko-house.ne.jp/~hirohito/soft/upd7210-2/upd7210-2.1.tgz
■ インストール ■
以下の手順に従って、インストールします。
カーネルの再構築を行うので、あらかじめカーネルソースを展開しておかなけ
ればなりません。
(1) アーカイブに含まれるファイル upd7210*.[ch]を、
/usr/src/sys/dev/upd7210 下へ展開する。
mkdir /usr/src/sys/dev/upd7210
cp upd7210*.[ch] /usr/src/sys/dev/upd7210
(2) /usr/src/sys/conf/files.i386 に、以下の行を追加する。
dev/upd7210/upd7210.c optional gpib
dev/upd7210/upd7210_isa.c optional gpib isa
dev/upd7210/upd7210_pci.c optional gpib pci
dev/upd7210/upd7210_pccaard.c optional gpib card
(3) /usr/src/sys/conf/files.pc98 に、以下の行を追加する。
dev/upd7210/upd7210.c optional gpib
dev/upd7210/upd7210_cbus.c optional gpib isa
(4) /usr/src/sys/conf/options.i386 に、以下の行を追加する。
GPIB_CONTEC_PC gpib.h
GPIB_CONTEC_PCL gpib.h
GPIB_CONTEC_PCIL gpib.h
GPIB_CONTEC_PCCARD gpib.h
(5) /usr/src/sys/conf/options.pc98 に、以下の行を追加する。
GPIB_PC9801_29 gpib.h
(6) カーネルコンフィグファイルへ、以下の行を追加する。
device gpib0 at isa? port 0x300 irq 5
options "GPIB_CONTEC_PCL"
#portとirqは、ボード上のスイッチの設定に合わせ、変更する。
#pcibusの時は、device gpibだけで良い。
#使用するボード名を、options.*に追加した中から指定する。
(7) カーネルを再構築する。
(8) 再起動し、起動時のメッセージで gpib0が認識されていることを確認する。
(9) デバイスノードの作成。rootでloginして、以下のように実行する。
#cd /dev
#mknod gpib0 c 210 0
(10) 接続したい機器アドレスの、デバイスノードを作る。アドレスは、
マイナデバイス番号に指定する。
たとえば機器のアドレスが3なら、以下のように指定する。
#mknod gpib0a3 c 210 3
~ ~
(11) 作成したデバイスノードのモードを、適切に設定する。
たとえば、gpib0を全ユーザに使用許可するなら以下のように指定する。
#chmod a+rw gpib0
■ デバイスノードについて ■
● /dev/gpib0
このデバイスノードは、ボード本体の制御用です。
後述のライブラリ libgpib でも使用します。
● /dev/gpib0a??
このデバイスは、デバイスノードを使って相手機器のGPIBアドレスを特定する
場合に使用します。シェルスクリプトでGPIB通信する場合などに、これを使い
ます。
ライブラリ libgpibや ioctlのみを使用する場合は、GPIBアドレスをパラメー
タで指定するため、このデバイスノードは作らなくてもかまいません。
■ 使用方法1 -- シェルスクリプトから使用する ■
echo などのコマンドを利用して、シェルスクリプトからGPIB機器の制御を行
うことができます。
例1) リセットコマンドの送信
echo -n "*RST" >/dev/gpib0a3
例2) データを受信して、ファイルへ保存
cat /dev/gpib0a3 > file
例3) データを一行受信して、変数へ代入
x=`head -n 1 </dev/gpib0a3` ; echo $x
■ 使用方法2 -- C言語で接続機器毎のデバイスノードを利用する ■
デバイスノードを利用することで、通常のファイル入出力の要領でGPIB機器
の制御を行うことができます。
/*==== SAMPLE PROGRAM ====*/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
int main()
{
int fd, len;
char msg[5] = "*IDN?", buff[256];
do {
if( (fd = open( "/dev/gpib0a1", O_RDWR )) < 0 ) break;
if( write( fd, msg, sizeof msg ) < 0 ) break; /* TALK */
if( (len = read( fd, buff, sizeof buff )) < 0 ) break; /* LISTEN */
printf( "%.*s\n", len, buff );
} while( 0 );
if( errno > 0 ) {
perror( "GPIBTEST" );
return 1;
}
close( fd );
return 0;
}
■ 使用方法3 -- Cのライブラリを使用する ■
添付のlibgpib.cを使用して、C言語から使用することができます。基本的に次
項で説明するIOCTLのwrapper ですが、IOCTLを直接扱うのに比べて、簡単に
使える代わりに機能は限られます。
実装してある関数
int GPIB_init();
初期化。使用前に1度 call します。
戻り値:エラーならマイナス値。
int GPIB_close();
終了。プログラム終了前に1度 callします。
戻り値:エラーならマイナス値。
int GPIB_write( int addr, const char *msg );
addrのアドレスを持つ機器に、msgを 送信(TALK)します。
戻り値:エラーならマイナス値。
int GPIB_read( int addr, char *buf, int len );
addrのアドレスを持つ機器から、最大lenサイズのデータを
受信(LISTEN)します。
戻り値:エラーならマイナス値。
int GPIB_get_status( int addr );
addrのアドレスを持つ機器から、ステータスバイトを取得します。
戻り値:取得したステータス。
/*==== SAMPLE PROGRAM : sample.c ====*/
/* How to compile $cc -o sample sample.c libgpib.c */
#include <stdio.h>
#include <stdlib.h>
#include "upd7210.h"
main()
{
int addr = 1, status;
char buffer[256];
if( GPIB_init() < 0 ) {
perror( "" );
exit( 1 );
}
GPIB_write( addr, "*IDN?" );
GPIB_read( addr, buffer, sizeof buffer );
printf( "read data: %s", buffer );
status = GPIB_get_status( addr );
printf( "status: 0x%2.2x\n", status );
GPIB_close();
}
■ 使用方法 -- IOCTLを使用する ■
デバイスドライバの全機能を利用できます。
以下、リファレンスと、使用例です。
● Interface clear uniline message
ioctl( fd, GPIB_IFC, &gpkt );
printf( "gpib errno = %d\n", gpkt.errno );
● Enable REN uniline message
ioctl( fd, GPIB_REMOTE, &gpkt );
printf( "gpib errno = %d\n", gpkt.errno );
● Disable REN uniline message
ioctl( fd, GPIB_LOCAL, &gpkt );
printf( "gpib errno = %d\n", gpkt.errno );
● Arbitrary multiline command
char cmd[2] = { 0x3f, 0x5f }; /* UNL, UNT */
gpkt.message = cmd;
gpkt.msglen = 2;
ioctl( fd, GPIB_COMMAND, &gpkt );
printf( "gpib errno = %d\n", gpkt.errno );
● Un Talk
ioctl( fd, GPIB_UNT, &gpkt );
printf( "gpib errno = %d\n", gpkt.errno );
● Un Listen
ioctl( fd, GPIB_UNL, &gpkt );
printf( "gpib errno = %d\n", gpkt.errno );
● Set talker address
gpkt.talker = 10; /* speciry talker address 10 */
ioctl( fd, GPIB_STA, &gpkt );
printf( "gpib errno = %d\n", gpkt.errno );
● Set listener address
gpkt.listener[0] = 5; /* speciry listen address 5,4 and 3 */
gpkt.listener[1] = 4;
gpkt.listener[2] = 3;
gpkt.listener[3] = -1; /* terminate minous value */
ioctl( fd, GPIB_SLA, &gpkt );
printf( "gpib errno = %d\n", gpkt.errno );
● Device clear
ioctl( fd, GPIB_DCL, &gpkt );
printf( "gpib errno = %d\n", gpkt.errno );
● Go to local
gpkt.listener[0] = 5; /* speciry listen address 5,4 and 3 */
gpkt.listener[1] = 4;
gpkt.listener[2] = 3;
gpkt.listener[3] = -1; /* terminate minous value */
ioctl( fd, GPIB_GTL, &gpkt );
printf( "gpib errno = %d\n", gpkt.errno );
● Local lock out
ioctl( fd, GPIB_LLO, &gpkt );
printf( "gpib errno = %d\n", gpkt.errno );
● Selected device clear
gpkt.listener[0] = 5; /* speciry listen address 5,4 and 3 */
gpkt.listener[1] = 4;
gpkt.listener[2] = 3;
gpkt.listener[3] = -1; /* terminate minous value */
ioctl( fd, GPIB_SDC, &gpkt );
printf( "gpib errno = %d\n", gpkt.errno );
● Group execute trigger
gpkt.listener[0] = 5; /* speciry listen address 5,4 and 3 */
gpkt.listener[1] = 4;
gpkt.listener[2] = 3;
gpkt.listener[3] = -1; /* terminate minous value */
ioctl( fd, GPIB_GET, &gpkt );
printf( "gpib errno = %d\n", gpkt.errno );
● Talk
gpkt.listener[0] = 5; /* speciry listen address 5,4 and 3 */
gpkt.listener[1] = 4;
gpkt.listener[2] = 3;
gpkt.listener[3] = -1; /* terminate minous value */
gpkt.delimiter = GPIB_DLM_CR|GPIB_DLM_LF|GPIB_DLM_EOI;
gpkt.message = "*RST";
gpkt.msglen = strlen( gpkt.message );
ioctl( fd, GPIB_TALK, &gpkt );
printf( "errno=%d\n", gpkt.errno );
● Listen
char buffer[256];
gpkt.talker = 5;
gpkt.delimiter = GPIB_DLM_CR|GPIB_DLM_LF|GPIB_DLM_EOI;
gpkt.message = buffer;
gpkt.msglen = sizeof( buffer );
ioctl( fd, GPIB_LISTEN, &gpkt );
gpkt.message[gpkt.msglen] = 0;
printf( "errno=%d, msglen=%d\n", gpkt.errno, gpkt.msglen );
printf( "message=%s", gpkt.message );
● Serial poll
gpkt.listener[0] = 5; /* speciry listen address 5,4 and 3 */
gpkt.listener[1] = 4;
gpkt.listener[2] = 3;
gpkt.listener[3] = -1; /* terminate minous value */
ioctl( fd, GPIB_SP, &gpkt );
printf( "Status = %2.2x, %2.2x, %2.2x\n",
gpkt.listener[0], gpkt.listener[1], gpkt.listener[2] );
/* uPD7210 device driver ioctl function sample */
#include "upd7210.h"
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
int main()
{
int fd;
GPIB_PACKET gpkt;
char buffer[256];
if( (fd = open( "/dev/gpib0", O_RDWR )) < 0 )
{ perror( "" );
exit( 1 );
}
gpkt.listener[0] = 1; /* Listener address */
gpkt.listener[1] = -1;
gpkt.delimiter = GPIB_DLM_CR|GPIB_DLM_LF|GPIB_DLM_EOI;
gpkt.message = "*IDN?";
gpkt.msglen = strlen( gpkt.message );
ioctl( fd, GPIB_TALK, &gpkt );
printf( "talk: error=%d\n", gpkt.errno );
gpkt.talker = 1; /* Talker address */
gpkt.delimiter = GPIB_DLM_CR|GPIB_DLM_LF|GPIB_DLM_EOI;
gpkt.message = buffer;
gpkt.msglen = sizeof( buffer );
ioctl( fd, GPIB_LISTEN, &gpkt );
gpkt.message[gpkt.msglen] = 0;
printf( "listen: errno=%d, msglen=%d\n", gpkt.errno, gpkt.msglen );
printf( "message=%s", gpkt.message );
close( fd );
return 0;
}
■ 参考資料 ■
http://www.daemonnews.org/200008/isa.html
http://www.daemonnews.org/200007/newbus-intro.html
BSD magazine No.16 (株)アスキー
■ 謝辞 ■
ver 1.1
GP-IB(PC)Lをサポートするにあたり、株式会社コンテック様 及び
ぷらっとホーム株式会社様に、実機貸出の御協力をいただきました。
ありがとうございました。
ver 1.0
当ドライバの実機でのテスターとして、滝沢 聡さんに大変お世話になりました。
当ドライバーは、私が FreeBSDのデバイスドライバの勉強のために作り始めた
ものです。本当に簡単なテストバージョンが、まがりなりにも動作したもので
すから、調子に乗って GPIBのほとんどの機能を実装するまでになりました。
その要所要所において、滝沢さんにはテストを行っていただき、詳細なレポー
トをいただきました。滝沢さんのご尽力なしでは、当ドライバーは単なる私の
勉強用テストプログラムに過ぎなかったと思います。
本当にありがとうございました。