TM03/TE16のサポート - Page 3

2003.12.11

次に TM03 のレジスタに関連した定義をします。

皆さん良くご存知のように、 この手の周辺機器のコントローラにはレジスタが内蔵されていて、 そのレジスタに READ するとコントローラの状態がわかったり、 WRITE すると所定の動作を行ったりします。 つまりOSのデバイスドライバなどは、 この手のレジスタを介して周辺機器を制御するわけですが、 エミュレータではターゲットプログラムのレジスタに対する操作を ちゃんとフォローできないといけないわけ。 少なくともデバイスドライバをだませるぐらいにはね。


TM03 のレジスタマクロを定義する
ということで、 例の TM03マニュアル を見てみたのですが ・・・ Unix 側のデバイスドライバ (ht.c) と突き合わせるとレジスタが足りないのです。 PDP-11 の場合、 TM03RH11RH70 といった MASSBUS アダプタを介して接続されるので、 これが何かをしているのかも知れないし、 TM03 がアップデートされてレジスタが追加されたのかも知れない (あるいはその両方) ですが、 その真偽のほどは棚に上げて、 ここでは Unix 側のデバイスドライバと内容が一致した ../PDP10/pdp10_tu.c のマクロをそのまま流用します。


$ cvs diff -u
cvs diff: Diffing .
Index: pdp11_tu.c
===================================================================
RCS file: /wrk/simh/cvs/src/simh/pdp11e/pdp11_tu.c,v
retrieving revision 1.7
diff -u -r1.7 pdp11_tu.c
--- pdp11_tu.c	11 Dec 2003 03:52:18 -0000	1.7
+++ pdp11_tu.c	11 Dec 2003 04:20:46 -0000
@@ -8,6 +8,177 @@
 #define TU_NUMDR	8				/* #drives */
 
 
+// TUCS1 (RW) 17772440 - control/status 1
+
+#define CS1_GO		CSR_GO			// go
+#define CS1_V_FNC	1			// function pos
+#define CS1_M_FNC	037			// function mask
+#define CS1_FNC		(CS1_M_FNC << CS1_V_FNC)
+#define  FNC_NOP	000			// no operation
+#define  FNC_UNLOAD	001			// unload
+#define  FNC_REWIND	003			// rewind
+#define  FNC_FCLR	004			// formatter clear
+#define  FNC_RIP	010			// read in preset
+#define  FNC_ERASE	012			// erase tape
+#define  FNC_WREOF	013			// write tape mark
+#define  FNC_SPACEF	014			// space forward
+#define  FNC_SPACER	015			// space reverse
+#define FNC_XFER	024			// >=? data xfr
+#define  FNC_WCHKF	024			// write check
+#define  FNC_WCHKR	027			// write check rev
+#define  FNC_WRITE	030			// write
+#define  FNC_READF	034			// read forward
+#define  FNC_READR	037			// read reverse
+#define CS1_IE		CSR_IE			// int enable
+#define CS1_DONE	CSR_DONE		// ready
+#define CS1_V_UAE	8			// Unibus addr ext
+#define CS1_M_UAE	03
+#define CS1_UAE		(CS1_M_UAE << CS1_V_UAE)
+#define CS1_DVA		0004000			// drive avail NI
+#define CS1_MCPE	0020000			// Mbus par err NI
+#define CS1_TRE		0040000			// transfer err
+#define CS1_SC		0100000			// special cond
+#define CS1_MBZ		0012000
+#define CS1_DRV		(CS1_FNC | CS1_GO)
+#define GET_FNC(x)	(((x) >> CS1_V_FNC) & CS1_M_FNC)
+#define GET_UAE(x)	(((x) & CS1_UAE) << (16 - CS1_V_UAE))
+
+// TUWC  (--) 17772442 - word count
+
+// TUBA  (--) 17772444 - base address
+
+#define BA_MBZ		0000001			// must be zero
+
+// TUFC  (--) 17772446 - frame count
+
+// TUCS2 (--) 17772450 - control/status 2
+
+#define CS2_V_FMTR	0			// formatter select
+#define CS2_M_FMTR	07
+#define CS2_FMTR	(CS2_M_FMTR << CS2_V_FMTR)
+#define CS2_UAI		0000010			// addr inhibit NI
+#define CS2_PAT		0000020			// parity test NI
+#define CS2_CLR		0000040			// controller clear
+#define CS2_IR		0000100			// input ready
+#define CS2_OR		0000200			// output ready
+#define CS2_MDPE	0000400			// Mbus par err NI
+#define CS2_MXF		0001000			// missed xfer NI
+#define CS2_PGE		0002000			// program err
+#define CS2_NEM		0004000			// nx mem err
+#define CS2_NEF		0010000			// nx fmter err
+#define CS2_PE		0020000			// parity err NI
+#define CS2_WCE		0040000			// write chk err NI
+#define CS2_DLT		0100000			// data late NI
+#define CS2_MBZ		(CS2_CLR | CS2_WCE)
+#define CS2_RW		(CS2_FMTR | CS2_UAI | CS2_PAT | CS2_MXF | CS2_PE)
+#define CS2_ERR		(CS2_MDPE | CS2_MXF | CS2_PGE | CS2_NEM | \
+			 CS2_NEF | CS2_PE | CS2_DLT )
+#define GET_FMTR(x)	(((x) >> CS2_V_FMTR) & CS2_M_FMTR)
+
+// TUFS  (RO) 17772452 - formatter status
+//   + indicates kept in drive status
+//   ^ indicates calculated on the fly
+
+#define FS_SAT		0000001			// slave attention
+#define FS_BOT		0000002			// ^beginning of tape
+#define FS_TMK		0000004			// end of file
+#define FS_ID		0000010			// ID burst detected
+#define FS_SLOW		0000020			// slowing down NI
+#define FS_PE		0000040			// ^PE status
+#define FS_SSC		0000100			// slave stat change
+#define FS_RDY		0000200			// ^formatter ready
+#define FS_FPR		0000400			// formatter present
+#define FS_EOT		0002000			// +end of tape
+#define FS_WRL		0004000			// ^write locked
+#define FS_MOL		0010000			// ^medium online
+#define FS_PIP		0020000			// +pos in progress
+#define FS_ERR		0040000			// ^error
+#define FS_ATA		0100000			// attention active
+#define FS_REW		0200000			// +rewinding
+
+#define FS_DYN		(FS_ERR | FS_PIP | FS_MOL | FS_WRL | FS_EOT | \
+			 FS_RDY | FS_PE | FS_BOT)
+
+// TUER  (RO) 17772454 - error register
+
+#define ER_ILF		0000001			// illegal func
+#define ER_ILR		0000002			// illegal register
+#define ER_RMR		0000004			// reg mod refused
+#define ER_MCP		0000010			// Mbus cpar err NI
+#define ER_FER		0000020			// format sel err
+#define ER_MDP		0000040			// Mbus dpar err NI
+#define ER_VPE		0000100			// vert parity err
+#define ER_CRC		0000200			// CRC err NI
+#define ER_NSG		0000400			// non std gap err NI
+#define ER_FCE		0001000			// frame count err
+#define ER_ITM		0002000			// inv tape mark NI
+#define ER_NXF		0004000			// wlock or fnc err
+#define ER_DTE		0010000			// time err NI
+#define ER_OPI		0020000			// op incomplete
+#define ER_UNS		0040000			// drive unsafe
+#define ER_DCK		0100000			// data check NI
+
+// TUAS  (RW) 17772456 - attention summary
+
+#define AS_U0		0000001			// unit 0 flag
+
+// TUCC  (RO) 17772460 - check character, read only
+
+#define CC_MBZ		0177000			// must be zero
+
+// TUDB  (--) 17772462 - data buffer
+
+// TUMR  (RW) 17772464 - maintenance register
+
+#define MR_RW		0177637			// read/write
+
+// TUDT  (RO) 17772466 - drive type
+
+#define DT_TAPE		0040000			// tape
+#define DT_PRES		0002000			// slave present
+#define DT_TM03		0000040			// TM03 formatter
+#define DT_OFF		0000010			// drive off
+#define DT_TE16		0000011			// TE16
+#define DT_TU45		0000012			// TU45
+#define DT_TU77		0000014			// TU77
+
+// TUSN  (RO) 17772470 - serial number
+
+// TUTC  (RW) 17772472 - tape control register
+
+#define TC_V_UNIT	0			// unit select
+#define TC_M_UNIT	07
+#define TC_V_EVN	0000010			// even parity
+#define TC_V_FMT	4			// format select
+#define TC_M_FMT	017
+//#define  TC_10C	00			// PDP-10 core dump
+//#define  TC_IND	03			// industry standard
+#define TC_V_DEN	8			// density select
+#define TC_M_DEN	07
+#define  TC_800		 3			// 800 bpi
+#define  TC_1600	 4			// 1600 bpi
+#define TC_AER		0010000			// abort on error
+#define TC_SAC		0020000			// slave addr change
+#define TC_FCS		0040000			// frame count status
+#define TC_ACC		0100000			// accelerating NI
+#define TC_RW		0013777
+#define TC_MBZ		0004000
+#define GET_DEN(x)	(((x) >> TC_V_DEN) & TC_M_DEN)
+#define GET_FMT(x)	(((x) >> TC_V_FMT) & TC_M_FMT)
+#define GET_DRV(x)	(((x) >> TC_V_UNIT) & TC_M_UNIT)
+
+// TUBAE (--) 17772474 - bus address extension
+
+#define AE_M_MAE	0				/* addr ext pos */
+#define AE_V_MAE	077				/* addr ext mask */
+#define AE_MBZ		0177700
+
+// TUCS3 (--) 17772476 - control/status 3 - unused except for duplicate IE
+
+#define CS3_IE		CSR_IE			// int enable
+#define CS3_MBZ		0177660
+
+
 t_stat tu_rd(int32 *data, int32 PA, int32 access);
 t_stat tu_wr(int32 data, int32 PA, int32 access);
 t_stat tu_svc(UNIT *uptr);
$ 

ここで定義したレジスタのうち、 最後の2つ (BAE, CS3)../PDP10/pdp10_tu.c には定義されていません。 これは PDP-11/70 の MASSBUS アダプタ RH70 特有のもので、 PDP-11/70 の 22 bit Addressing に必要なものらしい。
この部分だけ ../PDP11/pdp11_rp.c に定義されていたマクロを流用しました。
詳しくはまた後で、、、


REG 構造体を記述する
エミュレータでは、 デバイスのレジスタは変数として定義されます。 で、レジスタへの読み出し/書き込みが発生すると、 エミュレートすべき振舞を行うと共に 該当する変数にその操作を行います。 先ほど保留にした REG 構造体は、 SIMH のコマンドモードで この変数へのアクセス方法を定義するものなんですね。

ということで、 ここではデバイスのレジスタに相当する変数と REG 構造体の配列を定義します。 例によって ../PDP10/pdp10_tu.c../PDP11/pdp11_rp.c の内容を参考にします。


$ cvs diff -u
cvs diff: Diffing .
Index: pdp11_tu.c
===================================================================
RCS file: /wrk/simh/cvs/src/simh/pdp11e/pdp11_tu.c,v
retrieving revision 1.8
diff -u -r1.8 pdp11_tu.c
--- pdp11_tu.c	11 Dec 2003 04:46:53 -0000	1.8
+++ pdp11_tu.c	11 Dec 2003 05:11:26 -0000
@@ -5,6 +5,10 @@
 #include "pdp11_defs.h"
 #include "sim_tape.h"
 
+extern int32 int_req[IPL_HLVL];
+extern int32 int_vec[IPL_HLVL][32];
+
+
 #define TU_NUMDR	8				/* #drives */
 
 
@@ -179,6 +183,24 @@
 #define CS3_MBZ		0177660
 
 
+int32 tucs1 = 0;				// control/status 1
+int32 tuwc  = 0;				// word count
+int32 tuba  = 0;				// bus address
+int32 tufc  = 0;				// frame count
+int32 tucs2 = 0;				// control/status 2
+int32 tufs  = 0;				// formatter status
+int32 tuer  = 0;				// error status
+int32 tucc  = 0;				// check character
+int32 tudb  = 0;				// data buffer
+int32 tumr  = 0;				// maint register
+int32 tutc  = 0;				// tape control
+int32 tubae = 0;				// bus address ext
+int32 tucs3 = 0;				// control/status 3
+
+int32 tuiff = 0;				// INTR flip/flop
+int32 tu_stopioe = 1;				// stop on error
+
+
 t_stat tu_rd(int32 *data, int32 PA, int32 access);
 t_stat tu_wr(int32 data, int32 PA, int32 access);
 t_stat tu_svc(UNIT *uptr);
@@ -188,6 +210,7 @@
 t_stat tu_detach(UNIT *uptr);
 t_stat tu_vlock(UNIT *uptr, int32 val, char *cptr, void *desc);
 
+
 UNIT tu_unit[] = {
 	{ UDATA(&tu_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) },
 	{ UDATA(&tu_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) },
@@ -200,6 +223,25 @@
 };
 
 REG tu_reg[] = {
+	{ GRDATA(TUCS1, tucs1, DEV_RDX, 16, 0) },
+	{ GRDATA(TUWC,  tuwc,  DEV_RDX, 16, 0) },
+	{ GRDATA(TUBA,  tuba,  DEV_RDX, 16, 0) },
+	{ GRDATA(TUFC,  tufc,  DEV_RDX, 16, 0) },
+	{ GRDATA(TUCS2, tucs2, DEV_RDX, 16, 0) },
+	{ GRDATA(TUFS,  tufs,  DEV_RDX, 16, 0) },
+	{ GRDATA(TUER,  tuer,  DEV_RDX, 16, 0) },
+	{ GRDATA(TUCC,  tucc,  DEV_RDX, 16, 0) },
+	{ GRDATA(TUDB,  tudb,  DEV_RDX, 16, 0) },
+	{ GRDATA(TUMR,  tumr,  DEV_RDX, 16, 0) },
+	{ GRDATA(TUTC,  tutc,  DEV_RDX, 16, 0) },
+	{ GRDATA(TUMR,  tumr,  DEV_RDX, 16, 0) },
+	{ GRDATA(TUTC,  tutc,  DEV_RDX, 16, 0) },
+	{ FLDATA(IFF,      tuiff,      0) },
+	{ FLDATA(INT,      IREQ(TU),   INT_V_RP) },
+	{ FLDATA(SC,       tucs1,      CSR_V_ERR) },
+	{ FLDATA(DONE,     tucs1,      CSR_V_DONE) },
+	{ FLDATA(IE,       tucs1,      CSR_V_IE) },
+	{ FLDATA(STOP_IOE, tu_stopioe, 0) },
 	{ NULL }
 };
$ 
 

REG 構造体の定義のためには各種マクロを使います。 詳細は "Writing a Simulator for the SIMH System" を見てね。 なお、 REG 構造体にはレジスタに対応する変数だけでなく、 その他の変数も任意に定義することができます。 デバッグ目的で一時的に mogifier を追加することもアリです。

では、無事に登録できたかどうか確認しましょう。


$ make
cc -g -DVM_PDP11 -I./ -I../ -I../PDP11   -c -o pdp11_tu.o pdp11_tu.c
cc  -o pdp11e  pdp11_fp.o pdp11_cpu.o pdp11_dz.o pdp11_cis.o pdp11_lp.o pdp11_rk.o pdp11_rl.o pdp11_rp.o pdp11_rx.o pdp11_stddev.o pdp11_sys.o pdp11_tc.o pdp11_tm.o pdp11_ts.o pdp11_io.o pdp11_rq.o pdp11_tq.o pdp11_pclk.o pdp11_ry.o pdp11_pt.o pdp11_hk.o pdp11_xq.o pdp11_xu.o pdp11_tu.o scp.o scp_tty.o sim_sock.o sim_tmxr.o sim_ether.o sim_tape.o -lm
$ ./pdp11e

PDP-11 simulator V3.0-2
sim> ex tu state
TUCS1:  000000
TUWC:   000000
TUBA:   000000
TUFC:   000000
TUCS2:  000000
TUFS:   000000
TUER:   000000
TUCC:   000000
TUDB:   000000
TUMR:   000000
TUTC:   000000
TUMR:   000000
TUTC:   000000
IFF:    0
INT:    0
SC:     0
DONE:   0
IE:     0
STOP_IOE:       1
sim> quit
Goodbye
$ 

どうやら無事動いているようです。

このように SIMH では examine コマンドを使うと デバイスローカルの変数も参照できます。 もちろん、 deposit コマンドで任意の値を設定することもできます。




PREV   NEXT