mirror of
https://github.com/open-simh/simh.git
synced 2026-05-01 14:06:14 +00:00
Notes For V3.5-0
The source set has been extensively overhauled. For correct viewing, set Visual C++ or Emacs to have tab stops every 4 characters. 1. New Features in 3.4-1 1.1 All Ethernet devices - Added Windows user-defined adapter names (from Timothe Litt) 1.2 Interdata, SDS, HP, PDP-8, PDP-18b terminal multiplexors - Added support for SET <unit>n DISCONNECT 1.3 VAX - Added latent QDSS support - Revised autoconfigure to handle QDSS 1.4 PDP-11 - Revised autoconfigure to handle more casees 2. Bugs Fixed in 3.4-1 2.1 SCP and libraries - Trim trailing spaces on all input (for example, attach file names) - Fixed sim_sock spurious SIGPIPE error in Unix/Linux - Fixed sim_tape misallocation of TPC map array for 64b simulators 2.2 1401 - Fixed bug, CPU reset was clearing SSB through SSG 2.3 PDP-11 - Fixed bug in VH vector display routine - Fixed XU runt packet processing (found by Tim Chapman) 2.4 Interdata - Fixed bug in SHOW PAS CONN/STATS - Fixed potential integer overflow exception in divide 2.5 SDS - Fixed bug in SHOW MUX CONN/STATS 2.6 HP - Fixed bug in SHOW MUX CONN/STATS 2.7 PDP-8 - Fixed bug in SHOW TTIX CONN/STATS - Fixed bug in SET/SHOW TTOXn LOG 2.8 PDP-18b - Fixed bug in SHOW TTIX CONN/STATS - Fixed bug in SET/SHOW TTOXn LOG 2.9 Nova, Eclipse - Fixed potential integer overflow exception in divide
This commit is contained in:
committed by
Mark Pizzolato
parent
ec60bbf329
commit
b7c1eae41f
563
SDS/sds_mt.c
563
SDS/sds_mt.c
@@ -1,6 +1,6 @@
|
||||
/* sds_mt.c: SDS 940 magnetic tape simulator
|
||||
|
||||
Copyright (c) 2001-2004, Robert M. Supnik
|
||||
Copyright (c) 2001-2005, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -19,27 +19,27 @@
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
mt 7 track magnetic tape
|
||||
mt 7 track magnetic tape
|
||||
|
||||
07-Dec-04 RMS Added read-only file support
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
28-Mar-03 RMS Added multiformat support
|
||||
28-Feb-03 RMS Revised for magtape library
|
||||
07-Dec-04 RMS Added read-only file support
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
28-Mar-03 RMS Added multiformat support
|
||||
28-Feb-03 RMS Revised for magtape library
|
||||
|
||||
Magnetic tapes are represented as a series of variable 8b records
|
||||
of the form:
|
||||
|
||||
32b record length in bytes - exact number
|
||||
byte 0
|
||||
byte 1
|
||||
:
|
||||
byte n-2
|
||||
byte n-1
|
||||
32b record length in bytes - exact number
|
||||
32b record length in bytes - exact number
|
||||
byte 0
|
||||
byte 1
|
||||
:
|
||||
byte n-2
|
||||
byte n-1
|
||||
32b record length in bytes - exact number
|
||||
|
||||
If the byte count is odd, the record is padded with an extra byte
|
||||
of junk. File marks are represented by a single record length of 0.
|
||||
@@ -49,28 +49,31 @@
|
||||
#include "sds_defs.h"
|
||||
#include "sim_tape.h"
|
||||
|
||||
#define MT_MAXFR (32768 * 4)
|
||||
#define MT_NUMDR 8 /* number drives */
|
||||
#define MT_UNIT 07
|
||||
#define botf u3 /* bot tape flag */
|
||||
#define eotf u4 /* eot tape flag */
|
||||
#define MT_MAXFR (32768 * 4)
|
||||
#define MT_NUMDR 8 /* number drives */
|
||||
#define MT_UNIT 07
|
||||
#define botf u3 /* bot tape flag */
|
||||
#define eotf u4 /* eot tape flag */
|
||||
|
||||
extern uint32 xfr_req;
|
||||
extern int32 stop_invins, stop_invdev, stop_inviop;
|
||||
int32 mt_inst = 0; /* saved instr */
|
||||
int32 mt_eof = 0; /* end of file */
|
||||
int32 mt_gap = 0; /* in gap */
|
||||
int32 mt_skip = 0; /* skip rec */
|
||||
int32 mt_bptr = 0; /* buf ptr */
|
||||
int32 mt_blnt = 0; /* buf length */
|
||||
int32 mt_ctime = 10; /* char time */
|
||||
int32 mt_gtime = 1000; /* gap time */
|
||||
int32 mt_stopioe = 1; /* stop on err */
|
||||
uint8 mtxb[MT_MAXFR]; /* record buffer */
|
||||
DSPT mt_tplt[] = { /* template */
|
||||
{ MT_NUMDR, 0 }, { MT_NUMDR, DEV_MTS },
|
||||
{ MT_NUMDR, DEV_OUT }, { MT_NUMDR, DEV_MTS+DEV_OUT },
|
||||
{ 0, 0 } };
|
||||
int32 mt_inst = 0; /* saved instr */
|
||||
int32 mt_eof = 0; /* end of file */
|
||||
int32 mt_gap = 0; /* in gap */
|
||||
int32 mt_skip = 0; /* skip rec */
|
||||
int32 mt_bptr = 0; /* buf ptr */
|
||||
int32 mt_blnt = 0; /* buf length */
|
||||
int32 mt_ctime = 10; /* char time */
|
||||
int32 mt_gtime = 1000; /* gap time */
|
||||
int32 mt_stopioe = 1; /* stop on err */
|
||||
uint8 mtxb[MT_MAXFR]; /* record buffer */
|
||||
DSPT mt_tplt[] = { /* template */
|
||||
{ MT_NUMDR, 0 },
|
||||
{ MT_NUMDR, DEV_MTS },
|
||||
{ MT_NUMDR, DEV_OUT },
|
||||
{ MT_NUMDR, DEV_MTS+DEV_OUT },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
DEVICE mt_dev;
|
||||
t_stat mt_svc (UNIT *uptr);
|
||||
@@ -86,219 +89,234 @@ void mt_set_err (UNIT *uptr);
|
||||
t_stat mt (uint32 fnc, uint32 inst, uint32 *dat);
|
||||
|
||||
static const char sds_to_bcd[64] = {
|
||||
012, 001, 002, 003, 004, 005, 006, 007,
|
||||
010, 011, 012, 013, 014, 015, 016, 017,
|
||||
060, 061, 062, 063, 064, 065, 066, 067,
|
||||
070, 071, 072, 073, 074, 075, 076, 077,
|
||||
040, 041, 042, 043, 044, 045, 046, 047,
|
||||
050, 051, 052, 053, 054, 055, 056, 057,
|
||||
020, 021, 022, 023, 024, 025, 026, 027,
|
||||
030, 031, 032, 033, 034, 035, 036, 037 };
|
||||
012, 001, 002, 003, 004, 005, 006, 007,
|
||||
010, 011, 012, 013, 014, 015, 016, 017,
|
||||
060, 061, 062, 063, 064, 065, 066, 067,
|
||||
070, 071, 072, 073, 074, 075, 076, 077,
|
||||
040, 041, 042, 043, 044, 045, 046, 047,
|
||||
050, 051, 052, 053, 054, 055, 056, 057,
|
||||
020, 021, 022, 023, 024, 025, 026, 027,
|
||||
030, 031, 032, 033, 034, 035, 036, 037
|
||||
};
|
||||
|
||||
static const char bcd_to_sds[64] = {
|
||||
000, 001, 002, 003, 004, 005, 006, 007,
|
||||
010, 011, 000, 013, 014, 015, 016, 017,
|
||||
060, 061, 062, 063, 064, 065, 066, 067,
|
||||
070, 071, 072, 073, 074, 075, 076, 077,
|
||||
040, 041, 042, 043, 044, 045, 046, 047,
|
||||
050, 051, 052, 053, 054, 055, 056, 057,
|
||||
020, 021, 022, 023, 024, 025, 026, 027,
|
||||
030, 031, 032, 033, 034, 035, 036, 037 };
|
||||
|
||||
000, 001, 002, 003, 004, 005, 006, 007,
|
||||
010, 011, 000, 013, 014, 015, 016, 017,
|
||||
060, 061, 062, 063, 064, 065, 066, 067,
|
||||
070, 071, 072, 073, 074, 075, 076, 077,
|
||||
040, 041, 042, 043, 044, 045, 046, 047,
|
||||
050, 051, 052, 053, 054, 055, 056, 057,
|
||||
020, 021, 022, 023, 024, 025, 026, 027,
|
||||
030, 031, 032, 033, 034, 035, 036, 037
|
||||
};
|
||||
|
||||
/* MT data structures
|
||||
|
||||
mt_dev MT device descriptor
|
||||
mt_unit MT unit descriptor
|
||||
mt_reg MT register list
|
||||
mt_dev MT device descriptor
|
||||
mt_unit MT unit descriptor
|
||||
mt_reg MT register list
|
||||
*/
|
||||
|
||||
DIB mt_dib = { CHAN_W, DEV_MT, XFR_MT0, mt_tplt, &mt };
|
||||
|
||||
UNIT mt_unit[] = {
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) } };
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }
|
||||
};
|
||||
|
||||
REG mt_reg[] = {
|
||||
{ BRDATA (BUF, mtxb, 8, 8, MT_MAXFR) },
|
||||
{ DRDATA (BPTR, mt_bptr, 18), PV_LEFT },
|
||||
{ DRDATA (BLNT, mt_blnt, 18), PV_LEFT },
|
||||
{ FLDATA (XFR, xfr_req, XFR_V_MT0) },
|
||||
{ ORDATA (INST, mt_inst, 24) },
|
||||
{ FLDATA (EOF, mt_eof, 0) },
|
||||
{ FLDATA (GAP, mt_gap, 0) },
|
||||
{ FLDATA (SKIP, mt_skip, 0) },
|
||||
{ DRDATA (CTIME, mt_ctime, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (GTIME, mt_gtime, 24), REG_NZ + PV_LEFT },
|
||||
{ URDATA (POS, mt_unit[0].pos, 10, T_ADDR_W, 0,
|
||||
MT_NUMDR, PV_LEFT | REG_RO) },
|
||||
{ URDATA (BOT, mt_unit[0].botf, 10, 1, 0, MT_NUMDR, REG_RO) },
|
||||
{ URDATA (EOT, mt_unit[0].eotf, 10, 1, 0, MT_NUMDR, REG_RO) },
|
||||
{ FLDATA (STOP_IOE, mt_stopioe, 0) },
|
||||
{ NULL } };
|
||||
{ BRDATA (BUF, mtxb, 8, 8, MT_MAXFR) },
|
||||
{ DRDATA (BPTR, mt_bptr, 18), PV_LEFT },
|
||||
{ DRDATA (BLNT, mt_blnt, 18), PV_LEFT },
|
||||
{ FLDATA (XFR, xfr_req, XFR_V_MT0) },
|
||||
{ ORDATA (INST, mt_inst, 24) },
|
||||
{ FLDATA (EOF, mt_eof, 0) },
|
||||
{ FLDATA (GAP, mt_gap, 0) },
|
||||
{ FLDATA (SKIP, mt_skip, 0) },
|
||||
{ DRDATA (CTIME, mt_ctime, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (GTIME, mt_gtime, 24), REG_NZ + PV_LEFT },
|
||||
{ URDATA (POS, mt_unit[0].pos, 10, T_ADDR_W, 0,
|
||||
MT_NUMDR, PV_LEFT | REG_RO) },
|
||||
{ URDATA (BOT, mt_unit[0].botf, 10, 1, 0, MT_NUMDR, REG_RO) },
|
||||
{ URDATA (EOT, mt_unit[0].eotf, 10, 1, 0, MT_NUMDR, REG_RO) },
|
||||
{ FLDATA (STOP_IOE, mt_stopioe, 0) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB mt_mod[] = {
|
||||
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
|
||||
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
|
||||
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL",
|
||||
&set_chan, &show_chan, NULL },
|
||||
{ 0 } };
|
||||
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
|
||||
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
|
||||
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL",
|
||||
&set_chan, &show_chan, NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE mt_dev = {
|
||||
"MT", mt_unit, mt_reg, mt_mod,
|
||||
MT_NUMDR, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &mt_reset,
|
||||
&mt_boot, &mt_attach, NULL,
|
||||
&mt_dib, DEV_DISABLE };
|
||||
|
||||
"MT", mt_unit, mt_reg, mt_mod,
|
||||
MT_NUMDR, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &mt_reset,
|
||||
&mt_boot, &mt_attach, NULL,
|
||||
&mt_dib, DEV_DISABLE
|
||||
};
|
||||
|
||||
/* Mag tape routine
|
||||
|
||||
conn - inst = EOM0, dat = NULL
|
||||
eom1 - inst = EOM1, dat = NULL
|
||||
sks - inst = SKS, dat = ptr to result
|
||||
disc - inst = device number, dat = NULL
|
||||
wreor - inst = device number, dat = NULL
|
||||
read - inst = device number, dat = ptr to data
|
||||
write - inst = device number, dat = ptr to result
|
||||
conn - inst = EOM0, dat = NULL
|
||||
eom1 - inst = EOM1, dat = NULL
|
||||
sks - inst = SKS, dat = ptr to result
|
||||
disc - inst = device number, dat = NULL
|
||||
wreor - inst = device number, dat = NULL
|
||||
read - inst = device number, dat = ptr to data
|
||||
write - inst = device number, dat = ptr to result
|
||||
*/
|
||||
|
||||
t_stat mt (uint32 fnc, uint32 inst, uint32 *dat)
|
||||
{
|
||||
int32 u = inst & MT_UNIT; /* get unit */
|
||||
UNIT *uptr = mt_dev.units + u; /* get unit ptr */
|
||||
int32 u = inst & MT_UNIT; /* get unit */
|
||||
UNIT *uptr = mt_dev.units + u; /* get unit ptr */
|
||||
int32 t, new_ch;
|
||||
uint8 chr;
|
||||
t_stat r;
|
||||
|
||||
switch (fnc) { /* case function */
|
||||
case IO_CONN: /* connect */
|
||||
new_ch = I_GETEOCH (inst); /* get new chan */
|
||||
if (new_ch != mt_dib.chan) return SCPE_IERR; /* wrong chan? */
|
||||
if (mt_gap) { /* in gap? */
|
||||
mt_gap = 0; /* clr gap flg */
|
||||
sim_cancel (uptr); } /* cancel timer */
|
||||
else if (sim_is_active (uptr)) CRETIOP; /* busy? */
|
||||
uptr->eotf = 0; /* clr eot flag */
|
||||
mt_eof = 0; /* clr eof flag */
|
||||
mt_skip = 0; /* clr skp flag */
|
||||
mt_bptr = mt_blnt = 0; /* init buffer */
|
||||
if ((inst & DEV_MTS)? (CHC_GETCPW (inst) < 2): /* scn & cpw<3? */
|
||||
(inst & CHC_REV)) return STOP_INVIOP; /* rw & rev? */
|
||||
mt_inst = inst; /* save inst */
|
||||
if ((inst & DEV_MTS) && !(inst && DEV_OUT)) /* scanning? */
|
||||
chan_set_flag (mt_dib.chan, CHF_SCAN); /* set chan flg */
|
||||
xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */
|
||||
sim_activate (uptr, mt_gtime); /* start timer */
|
||||
break;
|
||||
switch (fnc) { /* case function */
|
||||
|
||||
case IO_EOM1: /* EOM mode 1 */
|
||||
new_ch = I_GETEOCH (inst); /* get new chan */
|
||||
if (new_ch != mt_dib.chan) CRETIOP; /* wrong chan? */
|
||||
t = inst & 07670; /* get command */
|
||||
if ((t == 04010) && !sim_is_active (uptr)) { /* rewind? */
|
||||
sim_tape_rewind (uptr); /* rewind unit */
|
||||
uptr->eotf = 0; /* clr eot */
|
||||
uptr->botf = 1; } /* set bot */
|
||||
else if ((t == 03610) && sim_is_active (uptr) && /* skip rec? */
|
||||
((mt_inst & DEV_OUT) == 0)) mt_skip = 1; /* set flag */
|
||||
else CRETINS;
|
||||
break;
|
||||
case IO_CONN: /* connect */
|
||||
new_ch = I_GETEOCH (inst); /* get new chan */
|
||||
if (new_ch != mt_dib.chan) return SCPE_IERR; /* wrong chan? */
|
||||
if (mt_gap) { /* in gap? */
|
||||
mt_gap = 0; /* clr gap flg */
|
||||
sim_cancel (uptr); /* cancel timer */
|
||||
}
|
||||
else if (sim_is_active (uptr)) CRETIOP; /* busy? */
|
||||
uptr->eotf = 0; /* clr eot flag */
|
||||
mt_eof = 0; /* clr eof flag */
|
||||
mt_skip = 0; /* clr skp flag */
|
||||
mt_bptr = mt_blnt = 0; /* init buffer */
|
||||
if ((inst & DEV_MTS)? (CHC_GETCPW (inst) < 2): /* scn & cpw<3? */
|
||||
(inst & CHC_REV)) return STOP_INVIOP; /* rw & rev? */
|
||||
mt_inst = inst; /* save inst */
|
||||
if ((inst & DEV_MTS) && !(inst && DEV_OUT)) /* scanning? */
|
||||
chan_set_flag (mt_dib.chan, CHF_SCAN); /* set chan flg */
|
||||
xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */
|
||||
sim_activate (uptr, mt_gtime); /* start timer */
|
||||
break;
|
||||
|
||||
case IO_DISC: /* disconnect */
|
||||
sim_cancel (uptr); /* no more xfr's */
|
||||
if (inst & DEV_OUT) { /* write? */
|
||||
if (r = mt_wrend (inst)) return r; } /* end record */
|
||||
break;
|
||||
case IO_EOM1: /* EOM mode 1 */
|
||||
new_ch = I_GETEOCH (inst); /* get new chan */
|
||||
if (new_ch != mt_dib.chan) CRETIOP; /* wrong chan? */
|
||||
t = inst & 07670; /* get command */
|
||||
if ((t == 04010) && !sim_is_active (uptr)) { /* rewind? */
|
||||
sim_tape_rewind (uptr); /* rewind unit */
|
||||
uptr->eotf = 0; /* clr eot */
|
||||
uptr->botf = 1; /* set bot */
|
||||
}
|
||||
else if ((t == 03610) && sim_is_active (uptr) &&/* skip rec? */
|
||||
((mt_inst & DEV_OUT) == 0)) mt_skip = 1; /* set flag */
|
||||
else CRETINS;
|
||||
break;
|
||||
|
||||
case IO_WREOR: /* write eor */
|
||||
chan_set_flag (mt_dib.chan, CHF_EOR); /* set eor flg */
|
||||
if (r = mt_wrend (inst)) return r; /* end record */
|
||||
mt_gap = 1; /* in gap */
|
||||
sim_activate (uptr, mt_gtime); /* start timer */
|
||||
break;
|
||||
case IO_DISC: /* disconnect */
|
||||
sim_cancel (uptr); /* no more xfr's */
|
||||
if (inst & DEV_OUT) { /* write? */
|
||||
if (r = mt_wrend (inst)) return r; /* end record */
|
||||
}
|
||||
break;
|
||||
|
||||
case IO_SKS: /* SKS */
|
||||
new_ch = I_GETSKCH (inst); /* get chan # */
|
||||
if (new_ch != mt_dib.chan) return SCPE_IERR; /* wrong chan? */
|
||||
if ((inst & (DEV_OUT | DEV_MTS)) == 0) { /* not sks 1n? */
|
||||
t = I_GETSKCND (inst); /* get skip cond */
|
||||
switch (t) { /* case sks cond */
|
||||
case 001: /* sks 1021n */
|
||||
*dat = 1; /* not magpak */
|
||||
break;
|
||||
case 002: /* sks 1041n */
|
||||
if (!(uptr->flags & UNIT_ATT) || /* not ready */
|
||||
sim_is_active (uptr)) *dat = 1;
|
||||
break;
|
||||
case 004: /* sks 1101n */
|
||||
if (!uptr->eotf) *dat = 1; /* not EOT */
|
||||
break;
|
||||
case 010: /* sks 1201n */
|
||||
if (!uptr->botf) *dat = 1; /* not BOT */
|
||||
break;
|
||||
case 013: /* sks 12610 */
|
||||
if (!mt_gap) *dat = 1; /* not in gap */
|
||||
break;
|
||||
case 017: /* sks 13610 */
|
||||
if (!mt_eof) *dat = 1; /* not EOF */
|
||||
break;
|
||||
case 020: /* sks 1401n */
|
||||
if (!sim_tape_wrp (uptr)) *dat = 1; /* not wrp */
|
||||
break;
|
||||
case 031: /* sks 1621n */
|
||||
case 033: /* sks 1661n */
|
||||
*dat = 1; /* not 556bpi */
|
||||
case 035: /* sks 1721n */
|
||||
break; } /* not 800bpi */
|
||||
} /* end if */
|
||||
break;
|
||||
case IO_WREOR: /* write eor */
|
||||
chan_set_flag (mt_dib.chan, CHF_EOR); /* set eor flg */
|
||||
if (r = mt_wrend (inst)) return r; /* end record */
|
||||
mt_gap = 1; /* in gap */
|
||||
sim_activate (uptr, mt_gtime); /* start timer */
|
||||
break;
|
||||
|
||||
case IO_READ: /* read */
|
||||
xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */
|
||||
if (mt_blnt == 0) { /* first read? */
|
||||
r = mt_readrec (uptr); /* get data */
|
||||
if ((r != SCPE_OK) || (mt_blnt == 0)) return r; } /* err, inv reclnt? */
|
||||
uptr->botf = 0; /* off BOT */
|
||||
if (mt_inst & CHC_REV) chr = mtxb[--mt_bptr] & 077; /* get next rev */
|
||||
else chr = mtxb[mt_bptr++] & 077; /* get next fwd */
|
||||
if (!(mt_inst & CHC_BIN)) chr = bcd_to_sds[chr]; /* bcd? */
|
||||
*dat = chr & 077; /* give to chan */
|
||||
if ((mt_inst & CHC_REV)? (mt_bptr <= 0): /* rev or fwd, */
|
||||
(mt_bptr >= mt_blnt)) mt_readend (uptr); /* recd done? */
|
||||
break;
|
||||
case IO_SKS: /* SKS */
|
||||
new_ch = I_GETSKCH (inst); /* get chan # */
|
||||
if (new_ch != mt_dib.chan) return SCPE_IERR; /* wrong chan? */
|
||||
if ((inst & (DEV_OUT | DEV_MTS)) == 0) { /* not sks 1n? */
|
||||
t = I_GETSKCND (inst); /* get skip cond */
|
||||
switch (t) { /* case sks cond */
|
||||
case 001: /* sks 1021n */
|
||||
*dat = 1; /* not magpak */
|
||||
break;
|
||||
case 002: /* sks 1041n */
|
||||
if (!(uptr->flags & UNIT_ATT) || /* not ready */
|
||||
sim_is_active (uptr)) *dat = 1;
|
||||
break;
|
||||
case 004: /* sks 1101n */
|
||||
if (!uptr->eotf) *dat = 1; /* not EOT */
|
||||
break;
|
||||
case 010: /* sks 1201n */
|
||||
if (!uptr->botf) *dat = 1; /* not BOT */
|
||||
break;
|
||||
case 013: /* sks 12610 */
|
||||
if (!mt_gap) *dat = 1; /* not in gap */
|
||||
break;
|
||||
case 017: /* sks 13610 */
|
||||
if (!mt_eof) *dat = 1; /* not EOF */
|
||||
break;
|
||||
case 020: /* sks 1401n */
|
||||
if (!sim_tape_wrp (uptr)) *dat = 1; /* not wrp */
|
||||
break;
|
||||
case 031: /* sks 1621n */
|
||||
case 033: /* sks 1661n */
|
||||
*dat = 1; /* not 556bpi */
|
||||
case 035: /* sks 1721n */
|
||||
break; /* not 800bpi */
|
||||
}
|
||||
} /* end if */
|
||||
break;
|
||||
|
||||
case IO_WRITE: /* write */
|
||||
uptr->botf = 0; /* off BOT */
|
||||
chr = (*dat) & 077;
|
||||
xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */
|
||||
if (!(mt_inst & CHC_BIN)) chr = sds_to_bcd[chr]; /* bcd? */
|
||||
if (mt_bptr < MT_MAXFR) mtxb[mt_bptr++] = chr; /* insert in buf */
|
||||
break;
|
||||
case IO_READ: /* read */
|
||||
xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */
|
||||
if (mt_blnt == 0) { /* first read? */
|
||||
r = mt_readrec (uptr); /* get data */
|
||||
if ((r != SCPE_OK) || (mt_blnt == 0)) return r; /* err, inv reclnt? */
|
||||
}
|
||||
uptr->botf = 0; /* off BOT */
|
||||
if (mt_inst & CHC_REV) chr = mtxb[--mt_bptr] & 077; /* get next rev */
|
||||
else chr = mtxb[mt_bptr++] & 077; /* get next fwd */
|
||||
if (!(mt_inst & CHC_BIN)) chr = bcd_to_sds[chr];/* bcd? */
|
||||
*dat = chr & 077; /* give to chan */
|
||||
if ((mt_inst & CHC_REV)? (mt_bptr <= 0): /* rev or fwd, */
|
||||
(mt_bptr >= mt_blnt)) mt_readend (uptr); /* recd done? */
|
||||
break;
|
||||
|
||||
default:
|
||||
CRETINS; }
|
||||
case IO_WRITE: /* write */
|
||||
uptr->botf = 0; /* off BOT */
|
||||
chr = (*dat) & 077;
|
||||
xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */
|
||||
if (!(mt_inst & CHC_BIN)) chr = sds_to_bcd[chr];/* bcd? */
|
||||
if (mt_bptr < MT_MAXFR) mtxb[mt_bptr++] = chr; /* insert in buf */
|
||||
break;
|
||||
|
||||
default:
|
||||
CRETINS;
|
||||
}
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Unit service */
|
||||
|
||||
t_stat mt_svc (UNIT *uptr)
|
||||
{
|
||||
if (mt_gap) { /* gap timeout */
|
||||
mt_gap = 0; /* clr gap flg */
|
||||
chan_disc (mt_dib.chan); } /* disc chan */
|
||||
else if (mt_skip) mt_readend (uptr); /* skip record */
|
||||
else { /* normal xfr */
|
||||
xfr_req = xfr_req | XFR_MT0; /* set xfr req */
|
||||
sim_activate (uptr, mt_ctime); } /* reactivate */
|
||||
if (mt_gap) { /* gap timeout */
|
||||
mt_gap = 0; /* clr gap flg */
|
||||
chan_disc (mt_dib.chan); /* disc chan */
|
||||
}
|
||||
else if (mt_skip) mt_readend (uptr); /* skip record */
|
||||
else { /* normal xfr */
|
||||
xfr_req = xfr_req | XFR_MT0; /* set xfr req */
|
||||
sim_activate (uptr, mt_ctime); /* reactivate */
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -307,26 +325,29 @@ return SCPE_OK;
|
||||
t_stat mt_readrec (UNIT *uptr)
|
||||
{
|
||||
t_mtrlnt tbc;
|
||||
t_stat st, r = SCPE_OK;
|
||||
t_stat st;
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */
|
||||
mt_set_err (uptr); /* no, err, disc */
|
||||
return SCPE_UNATT; }
|
||||
if (mt_inst & CHC_REV) /* reverse? */
|
||||
st = sim_tape_rdrecr (uptr, mtxb, &tbc, MT_MAXFR); /* read rec rev */
|
||||
else st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* no, fwd */
|
||||
if (st == MTSE_TMK) { /* tape mark? */
|
||||
mt_eof = 1; /* set eof flag */
|
||||
mtxb[0] = mtxb[1] = 017; /* EOR char */
|
||||
mt_blnt = 2; /* store 2 */
|
||||
return SCPE_OK; }
|
||||
if (st != MTSE_OK) { /* other error? */
|
||||
mt_set_err (uptr); /* err, disc */
|
||||
if (st == MTSE_IOERR) return SCPE_IOERR; /* IO error? */
|
||||
if (st == MTSE_INVRL) return SCPE_MTRLNT; /* inv rec lnt? */
|
||||
if (st == MTSE_EOM) uptr->eotf = 1; /* eom? set eot */
|
||||
return SCPE_OK; }
|
||||
mt_blnt = tbc; /* set buf lnt */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */
|
||||
mt_set_err (uptr); /* no, err, disc */
|
||||
return SCPE_UNATT;
|
||||
}
|
||||
if (mt_inst & CHC_REV) /* reverse? */
|
||||
st = sim_tape_rdrecr (uptr, mtxb, &tbc, MT_MAXFR); /* read rec rev */
|
||||
else st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* no, fwd */
|
||||
if (st == MTSE_TMK) { /* tape mark? */
|
||||
mt_eof = 1; /* set eof flag */
|
||||
mtxb[0] = mtxb[1] = 017; /* EOR char */
|
||||
mt_blnt = 2; /* store 2 */
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (st != MTSE_OK) { /* other error? */
|
||||
mt_set_err (uptr); /* err, disc */
|
||||
if (st == MTSE_IOERR) return SCPE_IOERR; /* IO error? */
|
||||
if (st == MTSE_INVRL) return SCPE_MTRLNT; /* inv rec lnt? */
|
||||
if (st == MTSE_EOM) uptr->eotf = 1; /* eom? set eot */
|
||||
return SCPE_OK;
|
||||
}
|
||||
mt_blnt = tbc; /* set buf lnt */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -334,16 +355,17 @@ return SCPE_OK;
|
||||
|
||||
void mt_readend (UNIT *uptr)
|
||||
{
|
||||
sim_cancel (uptr); /* stop timer */
|
||||
mt_skip = 0; /* clr skp flg */
|
||||
chan_set_flag (mt_dib.chan, CHF_EOR); /* end record */
|
||||
if (mt_eof) chan_disc (mt_dib.chan); /* EOF? */
|
||||
sim_cancel (uptr); /* stop timer */
|
||||
mt_skip = 0; /* clr skp flg */
|
||||
chan_set_flag (mt_dib.chan, CHF_EOR); /* end record */
|
||||
if (mt_eof) chan_disc (mt_dib.chan); /* EOF? */
|
||||
else {
|
||||
mt_gap = 1; /* no, in gap */
|
||||
sim_activate (uptr, mt_gtime); } /* start timer */
|
||||
mt_gap = 1; /* no, in gap */
|
||||
sim_activate (uptr, mt_gtime); /* start timer */
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Write complete (end of record or disconnect) */
|
||||
|
||||
t_stat mt_wrend (uint32 dev)
|
||||
@@ -352,40 +374,42 @@ UNIT *uptr = mt_dev.units + (dev & MT_UNIT);
|
||||
t_mtrlnt tbc;
|
||||
t_stat st;
|
||||
|
||||
sim_cancel (uptr); /* no more xfr's */
|
||||
if (mt_bptr == 0) return SCPE_OK; /* buf empty? */
|
||||
if (!(uptr->flags & UNIT_ATT)) { /* attached? */
|
||||
mt_set_err (uptr); /* no, err, disc */
|
||||
return SCPE_UNATT; }
|
||||
if (sim_tape_wrp (uptr)) { /* write lock? */
|
||||
mt_set_err (uptr); /* yes, err, disc */
|
||||
return SCPE_OK; }
|
||||
if (dev & DEV_MTS) { /* erase? */
|
||||
if (mt_inst & CHC_REV) /* reverse? */
|
||||
sim_tape_sprecr (uptr, &tbc); /* backspace */
|
||||
st = sim_tape_wreom (uptr); /* write eom */
|
||||
sim_cancel (uptr); /* no more xfr's */
|
||||
if (mt_bptr == 0) return SCPE_OK; /* buf empty? */
|
||||
if (!(uptr->flags & UNIT_ATT)) { /* attached? */
|
||||
mt_set_err (uptr); /* no, err, disc */
|
||||
return SCPE_UNATT;
|
||||
}
|
||||
if (sim_tape_wrp (uptr)) { /* write lock? */
|
||||
mt_set_err (uptr); /* yes, err, disc */
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (dev & DEV_MTS) { /* erase? */
|
||||
if (mt_inst & CHC_REV) /* reverse? */
|
||||
sim_tape_sprecr (uptr, &tbc); /* backspace */
|
||||
st = sim_tape_wreom (uptr); /* write eom */
|
||||
}
|
||||
else {
|
||||
if ((mt_bptr == 1) && (mtxb[0] == 017) && /* wr eof? */
|
||||
((mt_inst & 01670) == 00050))
|
||||
st = sim_tape_wrtmk (uptr); /* write tape mark */
|
||||
else st = sim_tape_wrrecf (uptr, mtxb, mt_bptr); /* write record */
|
||||
if ((mt_bptr == 1) && (mtxb[0] == 017) && /* wr eof? */
|
||||
((mt_inst & 01670) == 00050))
|
||||
st = sim_tape_wrtmk (uptr); /* write tape mark */
|
||||
else st = sim_tape_wrrecf (uptr, mtxb, mt_bptr); /* write record */
|
||||
}
|
||||
mt_bptr = 0;
|
||||
if (st != MTSE_OK) mt_set_err (uptr); /* error? */
|
||||
if (st != MTSE_OK) mt_set_err (uptr); /* error? */
|
||||
if (st == MTSE_IOERR) return SCPE_IOERR;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Fatal error */
|
||||
|
||||
void mt_set_err (UNIT *uptr)
|
||||
{
|
||||
chan_set_flag (mt_dib.chan, CHF_EOR | CHF_ERR); /* eor, error */
|
||||
chan_disc (mt_dib.chan); /* disconnect */
|
||||
xfr_req = xfr_req & ~XFR_MT0; /* clear xfr */
|
||||
sim_cancel (uptr); /* stop */
|
||||
mt_bptr = 0; /* buf empty */
|
||||
chan_set_flag (mt_dib.chan, CHF_EOR | CHF_ERR); /* eor, error */
|
||||
chan_disc (mt_dib.chan); /* disconnect */
|
||||
xfr_req = xfr_req & ~XFR_MT0; /* clear xfr */
|
||||
sim_cancel (uptr); /* stop */
|
||||
mt_bptr = 0; /* buf empty */
|
||||
return;
|
||||
}
|
||||
/* Reset routine */
|
||||
@@ -394,17 +418,18 @@ t_stat mt_reset (DEVICE *dptr)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
chan_disc (mt_dib.chan); /* disconnect */
|
||||
mt_eof = 0; /* clear state */
|
||||
chan_disc (mt_dib.chan); /* disconnect */
|
||||
mt_eof = 0; /* clear state */
|
||||
mt_gap = 0;
|
||||
mt_skip = 0;
|
||||
mt_inst = 0;
|
||||
mt_bptr = mt_blnt = 0;
|
||||
xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */
|
||||
for (i = 0; i < MT_NUMDR; i++) { /* deactivate */
|
||||
xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */
|
||||
for (i = 0; i < MT_NUMDR; i++) { /* deactivate */
|
||||
sim_cancel (&mt_unit[i]);
|
||||
sim_tape_reset (&mt_unit[i]);
|
||||
mt_unit[i].eotf = 0; }
|
||||
mt_unit[i].eotf = 0;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -433,12 +458,12 @@ t_stat mt_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
extern uint32 P, M[];
|
||||
|
||||
if (unitno) return SCPE_ARG; /* only unit 0 */
|
||||
M[0] = 077777771; /* -7B */
|
||||
M[1] = 007100000; /* LDX 0 */
|
||||
M[2] = 000203610; /* EOM 3610B */
|
||||
M[3] = 003200002; /* WIM 2 */
|
||||
M[4] = 000100002; /* BRU 2 */
|
||||
P = 1; /* start at 1 */
|
||||
if (unitno) return SCPE_ARG; /* only unit 0 */
|
||||
M[0] = 077777771; /* -7B */
|
||||
M[1] = 007100000; /* LDX 0 */
|
||||
M[2] = 000203610; /* EOM 3610B */
|
||||
M[3] = 003200002; /* WIM 2 */
|
||||
M[4] = 000100002; /* BRU 2 */
|
||||
P = 1; /* start at 1 */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user