[Simh] i1401 Bugs: Tape Handling
Bob Abeles
bobabeles at checkerboardsolutions.com
Mon Jul 7 21:33:12 EDT 2008
This collection of patches resolves several problems, mainly with
i1401's magnetic tape handling. With these patches applied, the
Autocoder tape from the "Cincinatti" collection generates a system
tape that in turn assembles the Autocoder. The patches are:
o Strip parity bit before ALT BCD blank test (previously reported)
o Fixed ZA/ZS bug, should not convert source to BCD (previously
reported)
o Fixed end-of-reel indicator implementation
The original 1401 implemented a "tape indicate" latch per tape unit,
i1401 implements a single global end-of-file indicator. i1401 resets
its global end-of-file indicator more often than the original 1401
and under different circumstances.
(This paragraph is my working model for the operation of the 1401's
"end-of-reel" indicator, reconstructed from references.)
The 1401 implements a "tape indicator" latch per tape drive. When a
1401 branch-on-indicator instruction addresses the "end-of-reel"
indicator, the 1401 addresses the "tape indicator" latch in the
currently selected and ready tape drive. The tape drive itself resets
its "tape indicator" latch only when a tape unload occurs. Tape
unload may be initiated by push button control or by the CPU "Rewind
Tape and Unload" instruction. The tape drive sets the "tape
indicator" latch when in write status and the end-of-reel reflective
strip photocell is activated. The CPU resets the "tape indicator"
latch in the selected and ready tape drive when the "end-of-reel"
indicator is tested by a branch-on-indicator instruction. If no tape
drive is selected, or the currently selected tape drive is not ready,
the "end-of-reel" indicator will appear to be off and no "tape
indicator" latch will be reset. The CPU sets the "tape indicator"
latch in the selected and ready tape drive whenever it reads a tape-
mark character in the first character position of a record.
References:
223-6988, "IBM 729 II, IV, V, VI Magnetic Tape Units, CE Instruction-
Reference", IBM 1962, pg. 69
223-6845, "IBM 729 II, III, IV Magnetic Tape Units, CE Manual of
Instruction", IBM 1959, pp. C60-C61, C100, C105, C109, C111-C112
TIE 5-0021, "IBM 1401, 1440 and 1460 Programming and Operating
Techniques", IBM 1964, pg. J-8
A24-3069-2, "Tape Input/Output Instructions, IBM 1401 1460", IBM
1964, pg. F-6
o Added TM detection to tape diagnostic read op
The tape diagnostic read op should detect the presence of a TM as the
first or only character of a record and set the tape drive's
indicator latch as appropriate.
References:
A24-3069-2, "Tape Input/Output Instructions, IBM 1401 1460", IBM
1964, pg. F-5
o Fixed TM detection, TM may be 1st ch in multiple char rec
A tape mark is detected by a read or diagnostic read operation if it
is the first or only character of a record.
References:
A24-3069-2, "Tape Input/Output Instructions, IBM 1401 1460", IBM
1964, pg. F-5
TIE 5-0021, "IBM 1401, 1440 and 1460 Programming and Operating
Techniques", IBM 1964, pg. J-4
o Fixed tape-error indicator set and reset
The tape-error indicator is reset by any tape op.
References:
A24-3069-2, "Tape Input/Output Instructions, IBM 1401 1460", IBM
1964, pg. F-7
TIE 5-0021, "IBM 1401, 1440 and 1460 Programming and Operating
Techniques", IBM 1964, pg. J-8
o Fixed memory leak in tape rewind-unload op
Opportunity fix.
o Fixed TM detect, mask off parity
Similar to "Strip parity bit before ALT BCD blank test" bug. Present
in sim_tape.c, prevents TM detection when TM was written in binary
mode on tape with C track intact. Also affects i7094 simulator.
Patch Follows
--------------------------------------------------------------
BobsG5:~/IBM_1401 babeles$ diff -rc simhv38-0 simh-tapefixes
Only in simh-tapefixes: BIN
diff -rc simhv38-0/I1401/i1401_cpu.c simh-tapefixes/I1401/i1401_cpu.c
*** simhv38-0/I1401/i1401_cpu.c Sat Jul 7 14:39:38 2007
--- simh-tapefixes/I1401/i1401_cpu.c Mon Jul 7 18:13:41 2008
***************
*** 23,34 ****
used in advertising or otherwise to promote the sale, use or
other dealings
in this Software without prior written authorization from
Robert M Supnik.
07-Jul-07 RMS Removed restriction on load-mode binary tape
28-Jun-07 RMS Added support for SS overlap modifiers
22-May-06 RMS Fixed format error in CPU history (found
by Peter Schorn)
06-Mar-06 RMS Fixed bug in divide (found by Van Snyder)
22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
! 01-Sep-05 RMS Removed error stops in MCE
16-Aug-05 RMS Fixed C++ declaration and cast problems
02-Jun-05 RMS Fixed SSB-SSG clearing on RESET
(reported by Ralph Reinke)
--- 23,37 ----
used in advertising or otherwise to promote the sale, use or
other dealings
in this Software without prior written authorization from
Robert M Supnik.
+ 07-Jul-08 REA Fixed end-of-reel indicator implementation
+ 07-Jul-08 REA Added TM detection to tape diagnostic read op
+ 27-Jun-08 REA Fixed ZA/ZS bug, should not convert source
to BCD
07-Jul-07 RMS Removed restriction on load-mode binary tape
28-Jun-07 RMS Added support for SS overlap modifiers
22-May-06 RMS Fixed format error in CPU history (found
by Peter Schorn)
06-Mar-06 RMS Fixed bug in divide (found by Van Snyder)
22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
! 01-Sep-05 RMS Removed error stops in MCE
16-Aug-05 RMS Fixed C++ declaration and cast problems
02-Jun-05 RMS Fixed SSB-SSG clearing on RESET
(reported by Ralph Reinke)
***************
*** 220,228 ****
extern t_stat inq_io (int32 flag, int32 mod);
extern t_stat mt_io (int32 unit, int32 flag, int32 mod);
extern t_stat dp_io (int32 fnc, int32 flag, int32 mod);
! extern t_stat mt_func (int32 unit, int32 mod);
extern t_stat sim_activate (UNIT *uptr, int32 delay);
extern t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
UNIT *uptr, int32 sw);
/* CPU data structures
--- 223,232 ----
extern t_stat inq_io (int32 flag, int32 mod);
extern t_stat mt_io (int32 unit, int32 flag, int32 mod);
extern t_stat dp_io (int32 fnc, int32 flag, int32 mod);
! extern t_stat mt_func (int32 unit, int32 mod, int32 bcd);
extern t_stat sim_activate (UNIT *uptr, int32 delay);
extern t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
UNIT *uptr, int32 sw);
+ extern t_bool mt_testind();
/* CPU data structures
***************
*** 802,807 ****
--- 806,816 ----
case OP_B: /* branch */
if (ilnt == 4) { BRANCH; } /* uncond
branch? */
else if (ilnt == 5) { /* branch
on ind? */
+ if (D == IN_END) { /* test
tape indicator */
+ if (mt_testind())
+ { BRANCH; }
+ else break;
+ }
if (ind[D]) { BRANCH; } /* test
indicator */
if (ind_table[D]) ind[D] = 0; /* reset
if needed */
}
***************
*** 868,874 ****
if (a & WM) wm = M[BS] = (M[BS] & WM) | BCD_ZERO;
else {
a = M[AS]; /* get A
char */
! t = (a & CHAR)? bin_to_bcd[a & DIGIT]: 0;
wm = M[BS] = (M[BS] & WM) | t; /* move
digit */
MM (AS);
}
--- 877,883 ----
if (a & WM) wm = M[BS] = (M[BS] & WM) | BCD_ZERO;
else {
a = M[AS]; /* get A
char */
! t = a & DIGIT; /* isolate
digit bits */
wm = M[BS] = (M[BS] & WM) | t; /* move
digit */
MM (AS);
}
***************
*** 1056,1062 ****
if (ilnt < 4) reason = STOP_INVL; /* too
short? */
else if (ioind != BCD_PERCNT) reason = STOP_INVA;
else if (reason = iomod (ilnt, D, mtf_mod)) break; /*
valid modifier? */
! reason = mt_func (unit, D); /* mt func,
error? */
break; /* can't
branch */
case OP_RF: case OP_PF: /* read,
punch feed */
--- 1065,1071 ----
if (ilnt < 4) reason = STOP_INVL; /* too
short? */
else if (ioind != BCD_PERCNT) reason = STOP_INVA;
else if (reason = iomod (ilnt, D, mtf_mod)) break; /*
valid modifier? */
! reason = mt_func (unit, D, (dev == IO_MT)); /* mt func,
error? */
break; /* can't
branch */
case OP_RF: case OP_PF: /* read,
punch feed */
diff -rc simhv38-0/I1401/i1401_mt.c simh-tapefixes/I1401/i1401_mt.c
*** simhv38-0/I1401/i1401_mt.c Sat Jul 7 14:40:32 2007
--- simh-tapefixes/I1401/i1401_mt.c Mon Jul 7 18:14:01 2008
***************
*** 25,30 ****
--- 25,36 ----
mt 7-track magtape
+ 07-Jul-08 REA Fixed memory leak in tape rewind-unload op
+ 07-Jul-08 REA Fixed tape-error indicator set and reset
+ 07-Jul-08 REA Fixed TM detection, TM may be 1st ch in
multiple char rec
+ 07-Jul-08 REA Fixed end-of-reel indicator implementation
+ 07-Jul-08 REA Added TM detection to tape diagnostic read op
+ 29-Jun-08 REA Strip parity bit before ALT BCD blank test
07-Jul-07 RMS Removed restriction on load-mode binary tape
28-Jun-07 RMS Revised read tape mark behavior based on
real hardware
(found by Van Snyder)
***************
*** 86,95 ****
--- 92,105 ----
extern UNIT cpu_unit;
extern FILE *sim_deb;
+ UNIT *mt_sel = NULL; /* selected
mt unit */
+
t_stat mt_reset (DEVICE *dptr);
t_stat mt_boot (int32 unitno, DEVICE *dptr);
t_stat mt_map_status (t_stat st);
UNIT *get_unit (int32 unit);
+ t_stat mt_attach (UNIT *uptr, char *cp);
+ t_stat mt_detach (UNIT *uptr);
/* MT data structures
***************
*** 115,123 ****
UNIT_ROABLE + UNIT_BCD, 0) }
};
REG mt_reg[] = {
- { FLDATA (END, ind[IN_END], 0) },
{ FLDATA (ERR, ind[IN_TAP], 0) },
{ DRDATA (POS1, mt_unit[1].pos, T_ADDR_W), PV_LEFT + REG_RO },
{ DRDATA (POS2, mt_unit[2].pos, T_ADDR_W), PV_LEFT + REG_RO },
{ DRDATA (POS3, mt_unit[3].pos, T_ADDR_W), PV_LEFT + REG_RO },
--- 125,141 ----
UNIT_ROABLE + UNIT_BCD, 0) }
};
+ #define UNIT_V_IND (MTUF_V_UF + 0) /* tape
indicator latch */
+ #define UNIT_IND (1 << UNIT_V_IND)
+
REG mt_reg[] = {
{ FLDATA (ERR, ind[IN_TAP], 0) },
+ { FLDATA (IND1, mt_unit[1].flags, UNIT_V_IND) },
+ { FLDATA (IND2, mt_unit[2].flags, UNIT_V_IND) },
+ { FLDATA (IND3, mt_unit[3].flags, UNIT_V_IND) },
+ { FLDATA (IND4, mt_unit[4].flags, UNIT_V_IND) },
+ { FLDATA (IND5, mt_unit[5].flags, UNIT_V_IND) },
+ { FLDATA (IND6, mt_unit[6].flags, UNIT_V_IND) },
{ DRDATA (POS1, mt_unit[1].pos, T_ADDR_W), PV_LEFT + REG_RO },
{ DRDATA (POS2, mt_unit[2].pos, T_ADDR_W), PV_LEFT + REG_RO },
{ DRDATA (POS3, mt_unit[3].pos, T_ADDR_W), PV_LEFT + REG_RO },
***************
*** 141,147 ****
"MT", mt_unit, mt_reg, mt_mod,
MT_NUMDR, 10, 31, 1, 8, 8,
NULL, NULL, &mt_reset,
! &mt_boot, &sim_tape_attach, &sim_tape_detach,
NULL, DEV_DEBUG
};
--- 159,165 ----
"MT", mt_unit, mt_reg, mt_mod,
MT_NUMDR, 10, 31, 1, 8, 8,
NULL, NULL, &mt_reset,
! &mt_boot, &mt_attach, &mt_detach,
NULL, DEV_DEBUG
};
***************
*** 154,180 ****
status = status
*/
! t_stat mt_func (int32 unit, int32 mod)
{
! t_mtrlnt tbc;
UNIT *uptr;
t_stat st;
if ((uptr = get_unit (unit)) == NULL) return STOP_INVMTU; /* valid
unit? */
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /*
attached? */
switch (mod) { /* case on
modifier */
case BCD_A: /*
diagnostic read */
if (DEBUG_PRS (mt_dev)) fprintf (sim_deb,
">>MT%d: diagnostic read\n", unit);
! ind[IN_END] = 0; /* clear
end of file */
! st = sim_tape_sprecf (uptr, &tbc); /* space
fwd */
break;
case BCD_B: /*
backspace */
if (DEBUG_PRS (mt_dev)) fprintf (sim_deb,
">>MT%d: backspace\n", unit);
- ind[IN_END] = 0; /* clear
end of file */
st = sim_tape_sprecr (uptr, &tbc); /* space
rev */
break; /* end
case */
--- 172,211 ----
status = status
*/
! t_stat mt_func (int32 unit, int32 mod, int32 bcd)
{
! t_mtrlnt i, tbc;
UNIT *uptr;
t_stat st;
+ ind[IN_TAP] = 0; /* clear
error */
if ((uptr = get_unit (unit)) == NULL) return STOP_INVMTU; /* valid
unit? */
+ mt_sel = uptr; /* select
mt unit */
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /*
attached? */
+
switch (mod) { /* case on
modifier */
case BCD_A: /*
diagnostic read */
if (DEBUG_PRS (mt_dev)) fprintf (sim_deb,
">>MT%d: diagnostic read\n", unit);
! st = sim_tape_rdrecf (uptr, dbuf, &tbc, MT_MAXFR); /* read
rec */
! if (st == MTSE_RECE) ind[IN_TAP] = 1; /* rec in
error? */
! else if (st == MTSE_TMK) { /* tape
mark? */
! tbc = 1; /* one char
read */
! dbuf[0] = BCD_TAPMRK; /* BCD
tapemark */
! }
! else if (st != MTSE_OK) { /* stop on
error */
! if (DEBUG_PRS (mt_dev))
! fprintf (sim_deb, ", stopped by status = %d\n", st);
! break;
! }
! if ((dbuf[0] & CHAR) == BCD_TAPMRK)
! st = MTSE_TMK; /* TM 1st
ch in buf */
break;
case BCD_B: /*
backspace */
if (DEBUG_PRS (mt_dev)) fprintf (sim_deb,
">>MT%d: backspace\n", unit);
st = sim_tape_sprecr (uptr, &tbc); /* space
rev */
break; /* end
case */
***************
*** 200,206 ****
if (DEBUG_PRS (mt_dev)) fprintf (sim_deb,
">>MT%d: rewind and unload\n", unit);
sim_tape_rewind (uptr); /* update
position */
! return detach_unit (uptr); /* detach */
default:
return STOP_INVM;
--- 231,238 ----
if (DEBUG_PRS (mt_dev)) fprintf (sim_deb,
">>MT%d: rewind and unload\n", unit);
sim_tape_rewind (uptr); /* update
position */
! st = mt_detach (uptr); /* detach */
! break;
default:
return STOP_INVM;
***************
*** 233,239 ****
--- 265,274 ----
t_bool passed_eot;
UNIT *uptr;
+ ind[IN_TAP] = 0; /* clear
error */
+
if ((uptr = get_unit (unit)) == NULL) return STOP_INVMTU; /* valid
unit? */
+ mt_sel = uptr; /* select
mt unit */
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /*
attached? */
switch (mod) {
***************
*** 241,252 ****
case BCD_R: /* read */
if (DEBUG_PRS (mt_dev))
fprintf (sim_deb, ">>MT%d: read from %d", unit, BS);
- ind[IN_TAP] = ind[IN_END] = 0; /* clear
error */
wm_seen = 0; /* no word
mk seen */
st = sim_tape_rdrecf (uptr, dbuf, &tbc, MT_MAXFR); /* read
rec */
if (st == MTSE_RECE) ind[IN_TAP] = 1; /* rec in
error? */
else if (st == MTSE_TMK) { /* tape
mark? */
- ind[IN_END] = 1; /* set
indicator */
tbc = 1; /* one
char read */
dbuf[0] = BCD_TAPMRK; /* BCD
tapemark */
}
--- 276,285 ----
***************
*** 255,260 ****
--- 288,295 ----
fprintf (sim_deb, ", stopped by status = %d\n", st);
break;
}
+ if ((dbuf[0] & CHAR) == BCD_TAPMRK)
+ mt_sel->flags |= UNIT_IND; /* TM 1st
ch in buf */
for (i = 0; i < tbc; i++) { /* loop
thru buf */
if (M[BS] == (BCD_GRPMRK + WM)) { /* GWM in
memory? */
if (DEBUG_PRS (mt_dev))
***************
*** 266,272 ****
}
return SCPE_OK; /* done */
}
! t = dbuf[i]; /* get char */
if (!(flag & MD_BIN) && (t == BCD_ALT)) /* BCD
mode alt blank? */
t = BCD_BLANK; /* real
blank */
if (flag & MD_WM) { /* word mk
mode? */
--- 301,307 ----
}
return SCPE_OK; /* done */
}
! t = dbuf[i] & CHAR; /* get char */
if (!(flag & MD_BIN) && (t == BCD_ALT)) /* BCD
mode alt blank? */
t = BCD_BLANK; /* real
blank */
if (flag & MD_WM) { /* word mk
mode? */
***************
*** 302,308 ****
if (M[BS] == (BCD_GRPMRK + WM)) return STOP_MTZ;/* eor? */
if (DEBUG_PRS (mt_dev))
fprintf (sim_deb, ">>MT%d: write from %d", unit, BS);
- ind[IN_TAP] = ind[IN_END] = 0; /* clear
error */
for (tbc = 0; (t = M[BS++]) != (BCD_GRPMRK + WM); ) {
if ((t & WM) && (flag & MD_WM)) /* WM in
wm mode? */
dbuf[tbc++] = BCD_WM;
--- 337,342 ----
***************
*** 360,366 ****
return SCPE_MTRLNT;
case MTSE_TMK: /* end of
file */
! ind[IN_END] = 1; /* set end
mark */
break;
case MTSE_IOERR: /* IO
error */
--- 394,400 ----
return SCPE_MTRLNT;
case MTSE_TMK: /* end of
file */
! mt_sel->flags |= UNIT_IND; /* set
indicate latch */
break;
case MTSE_IOERR: /* IO
error */
***************
*** 380,385 ****
--- 414,432 ----
return SCPE_OK;
}
+ /* Test and reset selected tape drive's indicator latch */
+
+ t_bool mt_testind ()
+ {
+ t_bool v;
+ if (!mt_sel) return FALSE; /* any mt
selected? */
+ if (!(mt_sel->flags & UNIT_ATT)) return FALSE; /*
attached? */
+
+ v = mt_sel->flags & UNIT_IND; /* save
latch */
+ mt_sel->flags &= ~UNIT_IND; /* reset
latch */
+ return (v);
+ }
+
/* Reset routine */
t_stat mt_reset (DEVICE *dptr)
***************
*** 387,396 ****
int32 i;
UNIT *uptr;
! for (i = 0; i < MT_NUMDR; i++) { /* clear
pos flag */
! if (uptr = get_unit (i)) MT_CLR_PNU (uptr);
}
! ind[IN_END] = ind[IN_TAP] = 0; /* clear
indicators */
return SCPE_OK;
}
--- 434,450 ----
int32 i;
UNIT *uptr;
! for (i = 0; i < MT_NUMDR; i++) { /* per
drive resets */
! if (uptr = get_unit (i)) {
! MT_CLR_PNU (uptr); /* clear
pos flag */
! uptr->flags &= ~UNIT_IND; /* clear
ind latch */
}
! }
!
! ind[IN_TAP] = 0; /* clear mt
error ind */
!
! mt_sel = NULL; /* clear
unit select */
!
return SCPE_OK;
}
***************
*** 406,408 ****
--- 460,480 ----
saved_IS = 1;
return SCPE_OK;
}
+
+ /* Attach routine */
+
+ t_stat mt_attach (UNIT *uptr, char *cp)
+ {
+ uptr->flags &= ~UNIT_IND; /* reset
indicator latch */
+
+ return sim_tape_attach(uptr, cp); /* tape
unit attach */
+ }
+
+ /* Detach routine */
+
+ t_stat mt_detach (UNIT *uptr)
+ {
+ uptr->flags &= ~UNIT_IND; /* reset
indicator latch */
+
+ return sim_tape_detach(uptr); /* tape
unit detach */
+ }
diff -rc simhv38-0/sim_tape.c simh-tapefixes/sim_tape.c
*** simhv38-0/sim_tape.c Wed Jan 24 21:58:58 2007
--- simh-tapefixes/sim_tape.c Mon Jul 7 17:15:58 2008
***************
*** 26,31 ****
--- 26,32 ----
Ultimately, this will be a place to hide processing of various
tape formats,
as well as OS-specific direct hardware access.
+ 07-Jul-08 REA Fixed TM detect, mask off parity
23-Jan-07 JDB Fixed backspace over gap at BOT
22-Jan-07 RMS Fixed bug in P7B format read reclnt rev
(found by Rich Cornwell)
15-Dec-06 RMS Added support for small capacity tapes
***************
*** 240,246 ****
break; /* treat
like eor */
}
if ((sbc != 0) && (c & P7B_SOR)) break; /* next
record? */
! if ((c & P7B_DPAR) != P7B_EOF) all_eof = 0;
}
*bc = sbc; /* save
rec lnt */
sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* for
read */
--- 241,247 ----
break; /* treat
like eor */
}
if ((sbc != 0) && (c & P7B_SOR)) break; /* next
record? */
! if ((c & P7B_DATA) != P7B_EOF) all_eof = 0;
}
*bc = sbc; /* save
rec lnt */
sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* for
read */
***************
*** 336,342 ****
if (ferror (uptr->fileref)) /* error? */
return sim_tape_ioerr (uptr);
if (feof (uptr->fileref)) return MTSE_EOM; /* eof? */
! if ((c & P7B_DPAR) != P7B_EOF) all_eof = 0;
if (c & P7B_SOR) break; /* start
of record? */
}
uptr->pos = uptr->pos - sbc; /* update
position */
--- 337,343 ----
if (ferror (uptr->fileref)) /* error? */
return sim_tape_ioerr (uptr);
if (feof (uptr->fileref)) return MTSE_EOM; /* eof? */
! if ((c & P7B_DATA) != P7B_EOF) all_eof = 0;
if (c & P7B_SOR) break; /* start
of record? */
}
uptr->pos = uptr->pos - sbc; /* update
position */
---------------------------------------------------------------
end of patch
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.trailing-edge.com/pipermail/simh/attachments/20080707/44d44791/attachment-0003.html>
More information about the Simh
mailing list