TM03/TE16のサポート - Page 5

2003.12.12

次にエミュレータエンジンから呼び出される、 入出力操作を司るルーチン tu_rd() と tu_wr() を実装します。

この2つのルーチンは原則として、 レジスタの内容を読み書きすることを目的としています。 が、 いわゆるコマンドレジスタ(TUCS1)などへ書き込みがされた場合、 実際のデバイスでは何らかの動作を始めるのですが、 それをエミュレートするため tu_go(), tu_svc(), tu_inta() も実装する必要があります。


tu_rd() を記述する


$ 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.15
diff -u -r1.15 pdp11_tu.c
--- pdp11_tu.c	11 Dec 2003 08:34:41 -0000	1.15
+++ pdp11_tu.c	11 Dec 2003 09:09:25 -0000
@@ -203,6 +203,26 @@
 int32 tuiff = 0;				// INTR flip/flop
 int32 tu_stopioe = 1;				// stop on error
 
+int32 reg_in_fmtr[] = {				// reg in formatter
+ 0,	// CS1
+ 0,	// WC
+ 0,	// BA
+ 1,	// FC
+ 0,	// CS2
+ 1,	// FS
+ 1,	// ER
+ 0,	// AS
+ 1,	// CC
+ 0,	// DB
+ 1,	// MR
+ 1,	// DT
+ 1,	// SN
+ 1,	// TC
+ 1,	// BAE
+ 1,	// CS3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+};
+
 static uint8 *xbuf = NULL;			// xfer buffer
 
 
@@ -397,6 +417,90 @@
 t_stat
 tu_rd(int32 *data, int32 PA, int32 access)
 {
+	int32 fmtr, drv, j;
+
+	fmtr = GET_FMTR(tucs2);				// get current fmtr
+	drv  =  GET_DRV(tutc);				// get current drive
+	j = (PA >> 1) & 017;				// get reg offset
+
+	if (reg_in_fmtr[j] && (fmtr != 0)) {		// nx formatter
+		tucs2 |= CS2_NEF;			// set error flag
+		update_tucs(CS1_SC, drv);		// request intr
+		*data = 0;
+		return(SCPE_OK);
+	}
+
+	update_tucs(0, drv);				// update status
+
+	switch (j) {					// decode PA<4:1>
+	case 000:					// MTCS1
+		if (fmtr != 0) {
+			*data = tucs1 & ~CS1_DRV;
+		} else {
+			*data = tucs1;
+		}
+		break;
+	case 001:					// TUWC
+		*data = tuwc;
+		break;
+	case 002:					// MTBA
+		tuba &= ~BA_MBZ;
+		*data = tuba;
+		break;
+	case 003:					// TUFC
+		*data = tufc;
+		break;
+	case 004:					// TUCS2
+		tucs2 = (tucs2 & ~CS2_MBZ) | CS2_IR | CS2_OR;
+		*data = tucs2;
+		break;
+	case 005:					// TUFS
+		*data = tufs & 0177777;			// mask off rewind
+		break;
+	case 006:					// TUER
+		*data = tuer;
+		break;
+	case 007:					// TUAS
+		if (tufs & FS_ATA) {
+			*data = AS_U0;
+		} else {
+			*data = 0;
+		}
+		break;
+	case 010:					// TUCC
+		tucc &= ~CC_MBZ;
+		*data = tucc;
+		break;
+	case 011:					// TUDB
+		*data = tudb;
+		break;
+	case 012:					// TUMR
+		*data = tumr;
+		break;
+	case 013:					// TUDT
+		if (tu_unit[drv].flags & UNIT_DIS) {
+			*data = DT_TAPE | DT_TM03 | DT_OFF;
+		} else {
+			*data = DT_TAPE | DT_TM03 | DT_PRES | DT_TE16;
+		}
+		break;
+	case 014:					// TUSN
+		if (tu_unit[drv].flags & UNIT_DIS) {
+			*data = 0;
+		} else {
+			*data = 040 | (drv + 1);
+		}
+		break;
+	case 015:					// TUTC
+		tutc &= ~TC_MBZ;
+		*data = tutc;
+		break;
+	default:					// all others
+		tuer |= ER_ILR;
+		update_tucs(0, drv);
+		break;
+	}
+
 	return(SCPE_OK);
 }
 

$ 
 


tu_wr() を記述する


$ 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.16
diff -u -r1.16 pdp11_tu.c
--- pdp11_tu.c	11 Dec 2003 09:13:29 -0000	1.16
+++ pdp11_tu.c	11 Dec 2003 10:10:21 -0000
@@ -222,6 +222,25 @@
  1,	// CS3
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
 };
+int32 reg_in_fmtr1[32] = {			// rmr if write + go
+ 0,	// CS1
+ 0,	// WC
+ 0,	// BA
+ 1,	// FC
+ 0,	// CS2
+ 1,	// FS
+ 1,	// ER
+ 0,	// AS
+ 1,	// CC
+ 0,	// DB
+ 0,	// MR
+ 1,	// DT
+ 1,	// SN
+ 1,	// TC
+ 1,	// BAE
+ 1,	// CS3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+};
 
 static uint8 *xbuf = NULL;			// xfer buffer
 
@@ -413,6 +432,11 @@
 	return;
 }
 
+void
+tu_go (int32 drv)
+{
+}
+
 
 t_stat
 tu_rd(int32 *data, int32 PA, int32 access)
@@ -507,6 +531,161 @@
 t_stat
 tu_wr(int32 data, int32 PA, int32 access)
 {
+	int32 cs1f, fmtr, drv, j;
+
+	cs1f = 0;					// no int on cs1 upd
+	fmtr = GET_FMTR (tucs2);			// get formatter
+	drv = GET_DRV (tutc);				// get current unit
+	j = (PA >> 1) & 017;				// get reg offset
+	if (reg_in_fmtr[j] && (fmtr != 0)) {		// nx formatter
+		tucs2 = tucs2 | CS2_NEF;		// set error flag
+		update_tucs (CS1_SC, drv);		// request intr
+		return SCPE_OK;  }
+	if (reg_in_fmtr1[j] &&				// formatter busy?
+	    ((tucs1 & CS1_DONE) == 0)) {
+		tuer = tuer | ER_RMR;			// won't write
+		update_tucs (0, drv);
+		return SCPE_OK;  }
+
+	switch (j) {					// decode PA<4:1>
+	case 000:					// MTCS1
+		if ((access == WRITEB) && (PA & 1)) {
+			data <<= 8;
+		}
+		if (data & CS1_TRE) {			// error clear?
+			tucs1 &= ~CS1_TRE;		// clr CS1
+			tucs2 &= ~CS2_ERR; 		// clr CS2<15:8>
+		}
+		if ((access == WRITE) || (PA & 1)) {	// hi byte write?
+			if (tucs1 & CS1_DONE) {		// done set?
+				tucs1 = (tucs1 & ~CS1_UAE) | (data & CS1_UAE);
+			}
+		}
+		if ((access == WRITE) || !(PA & 1)) {	// lo byte write?
+			if ((data & CS1_DONE) &&	// to DONE+IE?
+			    (data & CS1_IE)) {
+				tuiff = 1;		// set CSTB INTR
+			}
+			tucs1 = (tucs1 & ~CS1_IE) | (data & CS1_IE);
+			if (fmtr != 0) {		// nx formatter?
+				tucs2 |= CS2_NEF;	// set error flag
+				cs1f   = CS1_SC;	// req interrupt
+			} else if (tucs1 & CS1_GO) {	// busy?
+				if (tucs1 & CS1_DONE) {
+					tuer  |= ER_RMR;
+				} else {
+					tucs2 |= CS2_PGE;
+				}
+			} else {
+				tucs1 = (tucs1 & ~CS1_DRV) | (data & CS1_DRV);
+				if (tucs1 & CS1_GO) {
+					tu_go(drv);
+				}
+			}
+		}
+		break;
+	case 001:					// MTWC
+		if (access == WRITEB) {
+			if (PA & 1) {
+				data = (tuwc &  0377) | (data << 8);
+			} else {
+				data = (tuwc & ~0377) | data;
+			}
+		}
+		tuwc = data;
+		break;
+	case 002:					// MTBA
+		if (access == WRITEB) {
+			if (PA & 1) {
+				data = (tuba &  0377) | (data << 8);
+			} else {
+				data = (tuba & ~0377) | data;
+			}
+		}
+		tuba = data & ~BA_MBZ;
+		break;
+	case 003:					// TUFC
+		if (access == WRITEB) {
+			if (PA & 1) {
+				data = (tufc &  0377) | (data << 8);
+			} else {
+				data = (tufc & ~0377) | data;
+			}
+		}
+		tufc = data;
+		tutc |= TC_FCS;				// set fc flag
+		break;
+	case 004:					// TUCS2
+		if ((access == WRITEB) && (PA & 1)) {
+			data <<= 8;
+		}
+		if (data & CS2_CLR) {
+			tu_reset(&tu_dev);		// init?
+		} else {
+			if ((data & ~tucs2) & (CS2_PE | CS2_MXF)) {
+				cs1f = CS1_SC;		// diagn intr
+			}
+			if (access == WRITEB) {		// merge data
+				if (PA & 1) {
+					data = (tucs2 &    0377) | data;
+				} else {
+					data = (tucs2 & 0177400) | data;
+				}
+				tucs2 = (tucs2 & ~CS2_RW)
+				      | (data  &  CS2_RW) | CS2_IR | CS2_OR;
+			}
+		}
+		break;
+	case 007:					// TUAS
+		if ((access == WRITEB) && (PA & 1)) break;
+		if (data & AS_U0) {
+			tufs &= ~FS_ATA;
+		}
+		break;
+	case 011:					// MTDB
+		if (access == WRITEB) {
+			if (PA & 1) {
+				data = (tudb &  0377) | (data << 8);
+			} else {
+				data = (tudb & ~0377) | data;
+			}
+		}
+		tudb = data;
+		break;
+	case 012:					// TUMR
+		if (access == WRITEB) {
+			if (PA & 1) {
+				data = (tumr &  0377) | (data << 8);
+			} else {
+				data = (tumr & ~0377) | data;
+			}
+		}
+		tumr = (tumr & ~MR_RW) | (data & MR_RW);
+		break;
+	case 015:					// TUTC
+		if (access == WRITEB) {
+			if (PA & 1) {
+				data = (tutc &  0377) | (data << 8);
+			} else {
+				data = (tutc & ~0377) | data;
+			}
+		}
+		tutc = (tutc & ~TC_RW) | (data & TC_RW) | TC_SAC;
+		drv = GET_DRV(tutc);
+		break;
+	case 005:					// TUFS
+	case 006:					// TUER
+	case 010:					// TUCC
+	case 013:					// TUDT
+	case 014:					// TUSN
+		break;					// read only
+	default:					// all others
+		tuer |= ER_ILR;
+		break;
+	}						// end switch
+
+	update_tucs(cs1f, drv);				// update status
+
 	return(SCPE_OK);
 }
 
$ 


tu_go() を記述する


$ cvs diff -u > ~/public_html/COOKIES/SIMH/TE16/diff
cvs diff: Diffing .
Index: pdp11_tu.c
===================================================================
RCS file: /wrk/simh/cvs/src/simh/pdp11e/pdp11_tu.c,v
retrieving revision 1.17
diff -u -r1.17 pdp11_tu.c
--- pdp11_tu.c	11 Dec 2003 10:12:01 -0000	1.17
+++ pdp11_tu.c	11 Dec 2003 10:48:18 -0000
@@ -201,9 +201,10 @@
 int32 tucs3 = 0;				// control/status 3
 
 int32 tuiff = 0;				// INTR flip/flop
+int32 tu_time = 10;				// record latency
 int32 tu_stopioe = 1;				// stop on error
 
 int32 reg_in_fmtr[32] = {			// reg in formatter
  0,	// CS1
  0,	// WC
  0,	// BA
@@ -241,6 +242,34 @@
  1,	// CS3
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
 };
+int32 fmt_test[16] = {				// fmt bytes/10 wd
+  5,	// 00 PDP-10:10-Core Dump
+  0,	// 01 PDP-15:15-Core Dump
+  5,	// 02
+  4,	// 03 PDP-10:10-Compatible
+  0,	// 04
+  0,	// 05
+  0,	// 06
+  0,	// 07
+  0,	// 10
+  0,	// 11
+  0,	// 12
+  0,	// 13
+  5,	// 14 PDP-11:11-Normal
+  5,	// 15 PDP-11:11-Core Dump
+  0,	// 16 PDP-15:15-Normal
+  0	// 17 PDP-11:Reserved
+};
+int32 den_test[8] = {				// valid densities
+  0,	// 00
+  0,	// 01
+  0,	// 02
+  1,	// 03  800:NRZI
+  1,	// 04 1600:PE
+  0,	// 05 Reserved
+  0,	// 06 Reserved
+  0	// 07 Reserved
+};
 
 static uint8 *xbuf = NULL;			// xfer buffer
 
@@ -286,6 +315,7 @@
 	{ FLDATA(DONE,     tucs1,      CSR_V_DONE) },
 	{ FLDATA(IE,       tucs1,      CSR_V_IE) },
 	{ FLDATA(STOP_IOE, tu_stopioe, 0) },
+	{ DRDATA(TIME, tu_time, 24), PV_LEFT },
 	{ NULL }
 };
 
@@ -435,6 +465,141 @@
 void
 tu_go (int32 drv)
 {
+	int32 fnc, den, space_test = FS_BOT;
+	UNIT *uptr;
+
+	fnc = GET_FNC(tucs1);				// get function
+	den = GET_DEN(tutc);				// get density
+	uptr = tu_dev.units + drv;			// get unit
+
+	if ((fnc != FNC_FCLR) && 			// not clear
+	    ((tufs & FS_ERR) ||				// and error
+	     sim_is_active(uptr))) {			// or in motion?
+		tuer  |= ER_ILF;			// set error flag
+		tufs  |= FS_ATA;			// exception
+		tucs1 &= ~CS1_GO;			// clear go */
+		update_tucs(CS1_SC, drv);		// request intr
+		return;
+	}
+
+	tufs &= ~FS_ATA;				// clear attention
+	tutc &= ~TC_SAC;				// clear addr change
+
+	switch (fnc) {					// case on function
+	case FNC_FCLR:					// drive clear
+		tuer  = 0;				// clear errors
+		tutc &= ~TC_FCS;			// clear fc status
+		tufs &= ~(FS_SAT | FS_SSC | FS_ID | FS_TMK | FS_ERR);
+		sim_cancel(uptr);			// reset drive
+		uptr->USTAT = 0;
+	case FNC_NOP:
+		tucs1 &= ~CS1_GO;			// no operation
+		return;
+	case FNC_RIP:					// read-in preset
+		tutc = TC_800;				// density = 800
+		sim_tape_rewind(&tu_unit[0]);		// rewind unit 0
+		tu_unit[0].USTAT = 0;
+		tucs1 &= ~CS1_GO;
+		return;
+
+	case FNC_UNLOAD:				// unload
+		if ((uptr->flags & UNIT_ATT) == 0) {	// unattached?
+			tuer |= ER_UNS;
+			break;
+		}
+		detach_unit(uptr);
+		uptr->USTAT = FS_REW;
+		sim_activate(uptr, tu_time);
+		tucs1 &= ~CS1_GO;
+		return;	
+	case FNC_REWIND:
+		if ((uptr->flags & UNIT_ATT) == 0) {	// unattached?
+			tuer |= ER_UNS;
+			break;
+		}
+		uptr->USTAT = FS_PIP | FS_REW;
+		sim_activate(uptr, tu_time);
+		tucs1 &= ~CS1_GO;
+		return;
+
+	case FNC_SPACEF:
+		space_test = FS_EOT;	
+	case FNC_SPACER:
+		if ((uptr->flags & UNIT_ATT) == 0) {	// unattached?
+			tuer |= ER_UNS;
+			break;
+		}
+		if ((tufs & space_test) || ((tutc & TC_FCS) == 0)) {
+			tuer |= ER_NXF;
+			break;
+		}
+		uptr->USTAT = FS_PIP;
+		goto GO_XFER;
+
+	case FNC_WCHKR:					// wchk = read
+	case FNC_READR:					// read rev
+		if (tufs & FS_BOT) {			// beginning of tape?
+			tuer |= ER_NXF;
+			break;
+		}
+		goto DATA_XFER;
+
+	case FNC_WRITE:					// write
+		if (((tutc & TC_FCS) == 0) ||		// frame cnt = 0?
+		    ((den == TC_800) &&			// NRZI,
+		     (tufc > 0777765))) {		// fc < 13?
+			tuer |= ER_NXF;
+			break;
+		}
+	case FNC_WREOF:					// write tape mark
+	case FNC_ERASE:					// erase
+		if (sim_tape_wrp(uptr)) {		// write locked?
+			tuer |= ER_NXF;
+			break;
+		}
+	case FNC_WCHKF:					// wchk = read
+	case FNC_READF:					// read
+	DATA_XFER:
+		if ((uptr->flags & UNIT_ATT) == 0) {	// unattached?
+			tuer |= ER_UNS;
+			break;
+		}
+		if (fmt_test[GET_FMT(tutc)] == 0) {	// invalid format?
+			tuer |= ER_FER;
+			break;
+		}
+		if (den_test[den] == 0) {		// invalid density?
+			tuer |= ER_NXF;
+			break;
+		}
+		if (uptr->UDENS == UD_UNK) {
+			uptr->UDENS = den;		// set dens
+#if 0
+		} else if (uptr->UDENS != den) {	// density mismatch?
+			tuer |= ER_NXF;
+			break;
+#endif
+		}
+		uptr->USTAT = 0;
+		tucs1 &= ~CS1_DONE;			// clear done
+	GO_XFER:
+		tucs2 &= ~CS2_ERR;			// clear errors
+		tucs1 &= ~(CS1_TRE | CS1_MCPE);
+		tufs  &= ~(FS_TMK | FS_ID);		// clear eof, id
+		sim_activate(uptr, tu_time);
+		return;
+
+	default:					// all others
+		tuer |= ER_ILF;				// not supported
+		break;
+	}						// end case function
+
+	tucs1 &= ~CS1_GO;				// clear go
+	tufs |= FS_ATA;					// set attn
+
+	update_tucs(CS1_SC, drv);			// set intr
+
+	return;
 }
 
$ 
 


BAE,CS3 の入出力操作を追加する


$ 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.18
diff -u -r1.18 pdp11_tu.c
--- pdp11_tu.c  11 Dec 2003 10:53:01 -0000      1.18
+++ pdp11_tu.c  11 Dec 2003 11:36:11 -0000
@@ -5,6 +5,9 @@
 #include "pdp11_defs.h"
 #include "sim_tape.h"
 
+#define RH             (cpu_18b || (cpu_ubm && cpu_rh11))
+#define RH11           (RH)
+extern int32 cpu_18b, cpu_ubm, cpu_rh11;
 extern int32 int_req[IPL_HLVL];
 extern int32 int_vec[IPL_HLVL][32];
 
@@ -684,6 +687,16 @@
                tutc &= ~TC_MBZ;
                *data = tutc;
                break;
+       case 016:                                       // TUBAE
+               if (RH11) return SCPE_NXM;              // not in RH11
+               tubae &= ~AE_MBZ;
+               *data = tubae;
+               break;
+       case 017:                                       // TUCS3
+               if (RH11) return SCPE_NXM;              // not in RH11
+               tucs3 = (tucs3 & ~(CS3_IE | CS3_MBZ)) | (tucs1 & CS1_IE);
+               *data = tucs3;
+               break;
        default:                                        // all others
                tuer |= ER_ILR;
                update_tucs(0, drv);
@@ -837,6 +850,18 @@
                }
                tutc = (tutc & ~TC_RW) | (data & TC_RW) | TC_SAC;
                drv = GET_DRV(tutc);
                break;
+       case 016:                                       // TUBAE
+               if (RH11) return SCPE_NXM;              // not in RH11
+               if ((access == WRITEB) && (PA & 1)) break;
+               tubae = data & ~AE_MBZ;
+               tucs1 = (tucs1 & ~CS1_UAE) | ((tubae << CS1_V_UAE) & CS1_UAE);
+               break;
+       case 017:                                       // RPCS3
+               if (RH11) return SCPE_NXM;              // not in RH11
+               if ((access == WRITEB) && (PA & 1)) break;
+               tucs3 = data & ~CS3_MBZ;
+               tucs1 = (tucs1 & ~CS1_IE) | (tucs3 & CS3_IE);
+               break;
        case 005:                                       // TUFS
        case 006:                                       // TUER

$ 


tu_svc() を記述する


$ 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.19
diff -u -r1.19 pdp11_tu.c
--- pdp11_tu.c	11 Dec 2003 12:30:20 -0000	1.19
+++ pdp11_tu.c	12 Dec 2003 05:37:29 -0000
@@ -465,6 +465,211 @@
 	return;
 }
 
+
+t_stat
+tu_map_err (UNIT *uptr, t_stat st)
+{
+	switch (st) {
+	case MTSE_FMT:					// illegal fmt
+	case MTSE_UNATT:				// not attached
+		tuer = tuer | ER_NXF;			// can't execute
+	case MTSE_OK:					// no error
+		return SCPE_IERR;
+	case MTSE_TMK:					// end of file
+		tufs = tufs | FS_TMK;
+		break;
+	case MTSE_IOERR:				// IO error
+		tuer = tuer | ER_VPE;			// flag error
+		if (tu_stopioe) {
+			return(SCPE_IOERR);
+		}
+		break;
+	case MTSE_INVRL:				// invalid rec lnt
+		tuer = tuer | ER_VPE;			// flag error
+		return SCPE_MTRLNT;
+	case MTSE_RECE:					// record in error
+		tuer = tuer | ER_CRC;			// set crc err
+		break;
+	case MTSE_EOM:					// end of medium
+		tuer = tuer | ER_OPI;			// incomplete
+		break;
+	case MTSE_BOT:					// reverse into BOT
+		break;
+	case MTSE_WRP:					// write protect
+		tuer = tuer | ER_NXF;			// can't execute
+		break;
+	}
+
+	return(SCPE_OK);
+}
+
+
+t_stat
+tu_svc(UNIT *uptr)
+{
+	int32 i;
+	int32 f;
+	int32 t;
+	int32 fc;
+	int32 wc;
+	int32 fmt;
+	int32 drv;
+	uint32 ba;
+	t_mtrlnt tbc;
+	t_stat st;
+	t_stat r = SCPE_OK;
+
+	drv = uptr - tu_dev.units;			// get drive #
+	if (uptr->USTAT & FS_REW) {			// rewind or unload?
+		sim_tape_rewind(uptr);			// rewind tape
+		uptr->USTAT = 0;			// clear status
+		tufs |= FS_ATA | FS_SSC;
+		update_tucs(CS1_SC, drv);		// update status
+		return(SCPE_OK);
+	}
+
+	f   = GET_FNC(tucs1);				// get command
+	fmt = GET_FMT(tutc);				// get format
+	ba  = (tubae << 16) | tuba;			// get byte addr
+	wc = 0200000 - tuwc;				// get word count
+	fc = 0200000 - tufc;				// get frame count
+
+	uptr->USTAT = 0;				// clear status
+
+	switch (f) {					// case on function
+
+	case FNC_SPACEF:				// space forward
+		do {
+			tufc = (tufc + 1) & 0177777;	// incr fc
+			st = sim_tape_sprecf(uptr, &tbc);
+			if (st) {			// space rec fwd, err?
+				r = tu_map_err(uptr, st);	// map error
+				break;
+			}
+		} while (tufc != 0);
+
+		if (tufc) {
+			tuer |= ER_FCE;
+		} else {
+			tutc &= ~TC_FCS;
+		}
+		tufs |= FS_ATA;
+		break;
+
+	case FNC_SPACER:				// space reverse
+		do {
+			tufc = (tufc + 1) & 0177777;	// incr wc
+			st = sim_tape_sprecr(uptr, &tbc);
+			if (st) {			// space rec rev, err?
+				r = tu_map_err(uptr, st);	// map error
+				break;
+			}
+		} while (tufc != 0);
+
+		if (tufc) {
+			tuer |= ER_FCE;
+		} else {
+			tutc &= ~TC_FCS;
+		}
+		tufs |= FS_ATA;
+		break;
+
+	case FNC_WREOF:					// write end of file
+		if (st = sim_tape_wrtmk(uptr)) {	// write tmk, err?
+			r = tu_map_err(uptr, st);	// map error
+		}
+		tufs |= FS_ATA;
+		break;
+
+	case FNC_ERASE:
+		if (sim_tape_wrp(uptr)) {		// write protected?
+			r = tu_map_err(uptr, MTSE_WRP);	// map error
+		}
+		tufs |= FS_ATA;
+		break;
+
+	case FNC_READF:					// read
+	case FNC_WCHKF:					// wcheck = read
+		tufc = 0;				// clear frame count
+		if (uptr->UDENS == TC_1600 &&
+		    sim_tape_bot(uptr)) {
+			tufs |= FS_ID;			// PE BOT? ID burst
+		}
+
+							// read fwd
+		st = sim_tape_rdrecf(uptr, xbuf, &tbc, MT_MAXFR);
+		if (st) {
+			 r = tu_map_err(uptr, st);	// map error
+			break;				// done
+		}
+
+		t = Map_WriteB(ba, tbc, xbuf, RH);	// copy buf to mem
+		if (t) {
+			tucs2 |= CS2_NEM;		// set nxm err
+		}
+
+		tufc = tbc & 0177777;
+		tuwc = (tuwc + (wc << 1)) & 0177777;
+		ba += (wc << 1);
+		break;
+
+	case FNC_WRITE:					// write
+		fc = wc << 1;
+		t = Map_ReadB(ba, fc, xbuf, RH);	// copy mem to buf
+		if (t) {
+			tucs2 |= CS2_NEM;		// set nxm err
+		}
+
+		st = sim_tape_wrrecf(uptr, xbuf, fc);	// write rec
+		if (st) {				// err?
+			r = tu_map_err(uptr, st);	// map error
+			break;
+		}
+
+		tufc = (tufc + fc) & 0177777;
+		if (tufc == 0) {
+			tutc &= ~TC_FCS;
+		}
+		tuwc = (tuwc + (wc << 1)) & 0177777;
+		ba += (wc << 1);
+		break;
+
+	case FNC_READR:					// read reverse
+	case FNC_WCHKR:					// wcheck = read
+		tufc = 0;				// clear frame count
+							// read rev
+		st = sim_tape_rdrecr(uptr, xbuf, &tbc, MT_MAXFR);
+		if (st) {
+			r = tu_map_err(uptr, st);	// map error
+			break;				// done
+		}
+
+		for (i = 0; i < 4; i++) {
+			xbuf[i] = 0;
+		}
+
+		t = Map_WriteB(ba, tbc, xbuf, RH);	// copy buf to mem
+		if (t) {
+			tucs2 |= CS2_NEM;		// set nxm err
+		}
+
+		tufc = tbc & 0177777;
+		tuwc = (tuwc + (wc << 1)) & 0177777;
+		ba -= (wc << 1);
+		break;
+	}						// end case
+
+	tucs1 = (tucs1 & ~CS1_UAE) | ((ba >> (16 - CS1_V_UAE)) & CS1_UAE);
+	tuba  = (ba & 0177777) & ~BA_MBZ;		// lower 16b
+	tubae = (ba >> 16) & ~AE_MBZ;			// upper 6b
+	tucs1 &= ~CS1_GO;				// clear go
+
+	update_tucs(CS1_DONE, drv);
+
+	return(SCPE_OK);
+}
+
+
 void
 tu_go (int32 drv)
 {

$ 
 


tu_inta() を追加する


$ 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.20
diff -u -r1.20 pdp11_tu.c
--- pdp11_tu.c  12 Dec 2003 05:41:29 -0000      1.20
+++ pdp11_tu.c  12 Dec 2003 05:45:41 -0000
@@ -279,6 +279,7 @@
 
 t_stat tu_rd(int32 *data, int32 PA, int32 access);
 t_stat tu_wr(int32 data, int32 PA, int32 access);
+int32  tu_inta(void);
 t_stat tu_svc(UNIT *uptr);
 t_stat tu_reset(DEVICE *dptr);
 t_stat tu_boot(int32 unitno, DEVICE *dptr);
@@ -375,7 +376,7 @@
        1,              // vectors: number
        IVCL(TU),       // locator
        VEC_TU,         // value
-       { NULL }        // ack routines
+       { &tu_inta }    // ack routines
 };
 
 DEVICE tu_dev = {
@@ -463,6 +464,15 @@
        }
 
        return;
 }
+
+
+int32
+tu_inta(void)
+{
+       tucs1 &= ~CS1_IE;                               // clear int enable
+       tuiff  = 0;                                     // clear CSTB INTR
+       return(VEC_TU);                                 // acknowledge
+}
 
 
$ 


これでデバイスのエミュレーションに関する一通りの実装は終りました。



PREV   NEXT