次にエミュレータエンジンから呼び出される、 入出力操作を司るルーチン 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
+}
$
これでデバイスのエミュレーションに関する一通りの実装は終りました。
|
|