TAPE: Add support for AWS format tape images
Also added extended tape unit test code
This commit is contained in:
parent
d8b6a70c54
commit
e56b5f05e7
4 changed files with 307 additions and 54 deletions
|
@ -213,6 +213,9 @@ Host platforms which have libSDL available can leverage this functionality.
|
||||||
RAW Disk Access (including CDROM)
|
RAW Disk Access (including CDROM)
|
||||||
Virtual Disk Container files, including differencing disks
|
Virtual Disk Container files, including differencing disks
|
||||||
|
|
||||||
|
#### Tape Extensions
|
||||||
|
AWS format tape support
|
||||||
|
|
||||||
#### Embedded ROM support
|
#### Embedded ROM support
|
||||||
Simulators which have boot commands which load constant files as part of
|
Simulators which have boot commands which load constant files as part of
|
||||||
booting have those files imbedded into the simulator executable. The
|
booting have those files imbedded into the simulator executable. The
|
||||||
|
|
|
@ -650,7 +650,8 @@ struct UNIT {
|
||||||
#define UNIT_NO_FIO 0000004 /* fileref is NOT a FILE * */
|
#define UNIT_NO_FIO 0000004 /* fileref is NOT a FILE * */
|
||||||
#define UNIT_DISK_CHK 0000010 /* disk data debug checking (sim_disk) */
|
#define UNIT_DISK_CHK 0000010 /* disk data debug checking (sim_disk) */
|
||||||
#define UNIT_TMR_UNIT 0000020 /* Unit registered as a calibrated timer */
|
#define UNIT_TMR_UNIT 0000020 /* Unit registered as a calibrated timer */
|
||||||
#define UNIT_V_DF_TAPE 6 /* Bit offset for Tape Density reservation */
|
#define UNIT_TAPE_MRK 0000040 /* Tape Unit AWS Tapemark */
|
||||||
|
#define UNIT_V_DF_TAPE 7 /* Bit offset for Tape Density reservation */
|
||||||
#define UNIT_S_DF_TAPE 3 /* Bits Reserved for Tape Density */
|
#define UNIT_S_DF_TAPE 3 /* Bits Reserved for Tape Density */
|
||||||
|
|
||||||
struct BITFIELD {
|
struct BITFIELD {
|
||||||
|
|
313
sim_tape.c
313
sim_tape.c
|
@ -112,6 +112,7 @@ static struct sim_tape_fmt fmts[MTUF_N_FMT] = {
|
||||||
{ "E11", 0, sizeof (t_mtrlnt) - 1, sizeof (t_mtrlnt) },
|
{ "E11", 0, sizeof (t_mtrlnt) - 1, sizeof (t_mtrlnt) },
|
||||||
{ "TPC", UNIT_RO, sizeof (t_tpclnt) - 1, sizeof (t_tpclnt) },
|
{ "TPC", UNIT_RO, sizeof (t_tpclnt) - 1, sizeof (t_tpclnt) },
|
||||||
{ "P7B", 0, 0, 0 },
|
{ "P7B", 0, 0, 0 },
|
||||||
|
{ "AWS", 0, 0, 0 },
|
||||||
/* { "TPF", UNIT_RO, 0 }, */
|
/* { "TPF", UNIT_RO, 0 }, */
|
||||||
{ NULL, 0, 0 }
|
{ NULL, 0, 0 }
|
||||||
};
|
};
|
||||||
|
@ -129,6 +130,7 @@ static const uint32 bpi [] = { /* tape density table, i
|
||||||
|
|
||||||
static t_stat sim_tape_ioerr (UNIT *uptr);
|
static t_stat sim_tape_ioerr (UNIT *uptr);
|
||||||
static t_stat sim_tape_wrdata (UNIT *uptr, uint32 dat);
|
static t_stat sim_tape_wrdata (UNIT *uptr, uint32 dat);
|
||||||
|
static t_stat sim_tape_aws_wrdata (UNIT *uptr, uint8 *buf, t_mtrlnt bc);
|
||||||
static uint32 sim_tape_tpc_map (UNIT *uptr, t_addr *map, uint32 mapsize);
|
static uint32 sim_tape_tpc_map (UNIT *uptr, t_addr *map, uint32 mapsize);
|
||||||
static t_stat sim_tape_scan_tape (UNIT *uptr);
|
static t_stat sim_tape_scan_tape (UNIT *uptr);
|
||||||
static t_addr sim_tape_tpc_fnd (UNIT *uptr, t_addr *map);
|
static t_addr sim_tape_tpc_fnd (UNIT *uptr, t_addr *map);
|
||||||
|
@ -136,7 +138,6 @@ static void sim_tape_data_trace (UNIT *uptr, const uint8 *data, size_t len, cons
|
||||||
static t_stat tape_erase_fwd (UNIT *uptr, t_mtrlnt gap_size);
|
static t_stat tape_erase_fwd (UNIT *uptr, t_mtrlnt gap_size);
|
||||||
static t_stat tape_erase_rev (UNIT *uptr, t_mtrlnt gap_size);
|
static t_stat tape_erase_rev (UNIT *uptr, t_mtrlnt gap_size);
|
||||||
|
|
||||||
|
|
||||||
struct tape_context {
|
struct tape_context {
|
||||||
DEVICE *dptr; /* Device for unit (access to debug flags) */
|
DEVICE *dptr; /* Device for unit (access to debug flags) */
|
||||||
uint32 dbit; /* debugging bit for trace */
|
uint32 dbit; /* debugging bit for trace */
|
||||||
|
@ -469,6 +470,9 @@ DEVICE *dptr;
|
||||||
char gbuf[CBUFSIZE];
|
char gbuf[CBUFSIZE];
|
||||||
t_stat r;
|
t_stat r;
|
||||||
t_bool auto_format = FALSE;
|
t_bool auto_format = FALSE;
|
||||||
|
t_bool had_debug = (sim_deb != NULL);
|
||||||
|
uint32 starting_dctrl = uptr->dctrl;
|
||||||
|
int32 saved_switches = sim_switches;
|
||||||
|
|
||||||
if ((dptr = find_dev_from_unit (uptr)) == NULL)
|
if ((dptr = find_dev_from_unit (uptr)) == NULL)
|
||||||
return SCPE_NOATT;
|
return SCPE_NOATT;
|
||||||
|
@ -487,6 +491,15 @@ r = attach_unit (uptr, (CONST char *)cptr); /* attach unit */
|
||||||
if (r != SCPE_OK) /* error? */
|
if (r != SCPE_OK) /* error? */
|
||||||
return sim_messagef (r, "Can't open tape image: %s\n", cptr);
|
return sim_messagef (r, "Can't open tape image: %s\n", cptr);
|
||||||
|
|
||||||
|
if ((sim_switches & SWMASK ('D')) && !had_debug) {
|
||||||
|
sim_switches |= SWMASK ('E');
|
||||||
|
sim_switches &= ~(SWMASK ('D') | SWMASK ('R') | SWMASK ('F'));
|
||||||
|
sim_set_debon (0, "STDOUT");
|
||||||
|
sim_switches = saved_switches;
|
||||||
|
}
|
||||||
|
if (sim_switches & SWMASK ('D'))
|
||||||
|
uptr->dctrl = MTSE_DBG_STR | MTSE_DBG_DAT;
|
||||||
|
|
||||||
uptr->tape_ctx = ctx = (struct tape_context *)calloc(1, sizeof(struct tape_context));
|
uptr->tape_ctx = ctx = (struct tape_context *)calloc(1, sizeof(struct tape_context));
|
||||||
ctx->dptr = dptr; /* save DEVICE pointer */
|
ctx->dptr = dptr; /* save DEVICE pointer */
|
||||||
ctx->dbit = dbit; /* save debug bit */
|
ctx->dbit = dbit; /* save debug bit */
|
||||||
|
@ -498,12 +511,12 @@ switch (MT_GET_FMT (uptr)) { /* case on format */
|
||||||
objc = sim_tape_tpc_map (uptr, NULL, 0); /* get # objects */
|
objc = sim_tape_tpc_map (uptr, NULL, 0); /* get # objects */
|
||||||
if (objc == 0) { /* tape empty? */
|
if (objc == 0) { /* tape empty? */
|
||||||
sim_tape_detach (uptr);
|
sim_tape_detach (uptr);
|
||||||
return SCPE_FMT; /* yes, complain */
|
r = SCPE_FMT; /* yes, complain */
|
||||||
}
|
}
|
||||||
uptr->filebuf = calloc (objc + 1, sizeof (t_addr));
|
uptr->filebuf = calloc (objc + 1, sizeof (t_addr));
|
||||||
if (uptr->filebuf == NULL) { /* map allocated? */
|
if (uptr->filebuf == NULL) { /* map allocated? */
|
||||||
sim_tape_detach (uptr);
|
sim_tape_detach (uptr);
|
||||||
return SCPE_MEM; /* no, complain */
|
r = SCPE_MEM; /* no, complain */
|
||||||
}
|
}
|
||||||
uptr->hwmark = objc + 1; /* save map size */
|
uptr->hwmark = objc + 1; /* save map size */
|
||||||
sim_tape_tpc_map (uptr, (t_addr *) uptr->filebuf, objc);/* fill map */
|
sim_tape_tpc_map (uptr, (t_addr *) uptr->filebuf, objc);/* fill map */
|
||||||
|
@ -513,6 +526,7 @@ switch (MT_GET_FMT (uptr)) { /* case on format */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (r == SCPE_OK) {
|
||||||
sim_tape_scan_tape (uptr);
|
sim_tape_scan_tape (uptr);
|
||||||
|
|
||||||
sim_tape_rewind (uptr);
|
sim_tape_rewind (uptr);
|
||||||
|
@ -521,8 +535,13 @@ sim_tape_rewind (uptr);
|
||||||
sim_tape_set_async (uptr, completion_delay);
|
sim_tape_set_async (uptr, completion_delay);
|
||||||
#endif
|
#endif
|
||||||
uptr->io_flush = _sim_tape_io_flush;
|
uptr->io_flush = _sim_tape_io_flush;
|
||||||
|
}
|
||||||
|
|
||||||
return SCPE_OK;
|
if ((sim_switches & SWMASK ('D')) && !had_debug)
|
||||||
|
sim_set_deboff (0, "");
|
||||||
|
if (sim_switches & SWMASK ('D'))
|
||||||
|
uptr->dctrl = starting_dctrl;
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Detach tape unit */
|
/* Detach tape unit */
|
||||||
|
@ -549,6 +568,7 @@ if (ctx)
|
||||||
|
|
||||||
sim_tape_clr_async (uptr);
|
sim_tape_clr_async (uptr);
|
||||||
|
|
||||||
|
MT_CLR_INMRK (uptr); /* Not within an AWS tapemark */
|
||||||
r = detach_unit (uptr); /* detach unit */
|
r = detach_unit (uptr); /* detach unit */
|
||||||
if (r != SCPE_OK)
|
if (r != SCPE_OK)
|
||||||
return r;
|
return r;
|
||||||
|
@ -596,8 +616,10 @@ fprintf (st, " -E Must Exist (if not specified an attempt to create
|
||||||
fprintf (st, " virtual tape will be attempted).\n");
|
fprintf (st, " virtual tape will be attempted).\n");
|
||||||
fprintf (st, " -F Open the indicated tape container in a specific format (default\n");
|
fprintf (st, " -F Open the indicated tape container in a specific format (default\n");
|
||||||
fprintf (st, " is SIMH, alternatives are E11, TPC and P7B)\n");
|
fprintf (st, " is SIMH, alternatives are E11, TPC and P7B)\n");
|
||||||
fprintf (st, " -V Display some detailed information about the record structure\n");
|
fprintf (st, " -V Display some summary information about the record structure\n");
|
||||||
fprintf (st, " contained in the tape structure.\n");
|
fprintf (st, " contained in the tape structure.\n");
|
||||||
|
fprintf (st, " -D Causes the internal tape structure information to be displayed\n");
|
||||||
|
fprintf (st, " while the tape image is scanned.\n");
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -607,7 +629,7 @@ struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
|
||||||
|
|
||||||
if (ctx == NULL)
|
if (ctx == NULL)
|
||||||
return;
|
return;
|
||||||
if (sim_deb && (ctx->dptr->dctrl & reason))
|
if (sim_deb && ((uptr->dctrl | ctx->dptr->dctrl) & reason))
|
||||||
sim_data_trace(ctx->dptr, uptr, (detail ? data : NULL), "", len, txt, reason);
|
sim_data_trace(ctx->dptr, uptr, (detail ? data : NULL), "", len, txt, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -708,6 +730,8 @@ t_bool all_eof;
|
||||||
uint32 f = MT_GET_FMT (uptr);
|
uint32 f = MT_GET_FMT (uptr);
|
||||||
t_mtrlnt sbc;
|
t_mtrlnt sbc;
|
||||||
t_tpclnt tpcbc;
|
t_tpclnt tpcbc;
|
||||||
|
t_awshdr awshdr;
|
||||||
|
size_t rdcnt;
|
||||||
t_mtrlnt buffer [256]; /* local tape buffer */
|
t_mtrlnt buffer [256]; /* local tape buffer */
|
||||||
uint32 bufcntr, bufcap; /* buffer counter and capacity */
|
uint32 bufcntr, bufcap; /* buffer counter and capacity */
|
||||||
int32 runaway_counter, sizeof_gap; /* bytes remaining before runaway and bytes per gap */
|
int32 runaway_counter, sizeof_gap; /* bytes remaining before runaway and bytes per gap */
|
||||||
|
@ -897,6 +921,35 @@ else switch (f) { /* otherwise the read me
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MTUF_F_AWS:
|
||||||
|
MT_CLR_INMRK (uptr); /* Not within an AWS tapemark */
|
||||||
|
memset (&awshdr, 0, sizeof (awshdr));
|
||||||
|
rdcnt = sim_fread (&awshdr, sizeof (t_awslnt), 3, uptr->fileref);
|
||||||
|
*bc = awshdr.nxtlen; /* save rec lnt */
|
||||||
|
|
||||||
|
if (ferror (uptr->fileref)) { /* error? */
|
||||||
|
MT_SET_PNU (uptr); /* pos not upd */
|
||||||
|
status = sim_tape_ioerr (uptr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((feof (uptr->fileref)) || /* eof? */
|
||||||
|
(rdcnt < 3)) {
|
||||||
|
MT_SET_PNU (uptr); /* pos not upd */
|
||||||
|
status = MTSE_EOM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
uptr->pos = uptr->pos + sizeof (t_awshdr); /* spc over AWS header */
|
||||||
|
if (awshdr.rectyp == AWS_TMK) /* tape mark? */
|
||||||
|
status = MTSE_TMK;
|
||||||
|
else
|
||||||
|
if (awshdr.rectyp == AWS_REC) /* tape data record */
|
||||||
|
uptr->pos = uptr->pos + awshdr.nxtlen; /* spc over record */
|
||||||
|
else {
|
||||||
|
MT_SET_PNU (uptr); /* pos not upd */
|
||||||
|
status = MTSE_INVRL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
status = MTSE_FMT;
|
status = MTSE_FMT;
|
||||||
}
|
}
|
||||||
|
@ -914,7 +967,7 @@ if (ctx == NULL) /* if not properly attac
|
||||||
|
|
||||||
status = sim_tape_rdlntf (uptr, bc); /* read the record length */
|
status = sim_tape_rdlntf (uptr, bc); /* read the record length */
|
||||||
|
|
||||||
sim_debug (MTSE_DBG_STR, ctx->dptr, "rd_lnt: st: %d, lnt: %d, pos: %" T_ADDR_FMT "u\n", status, *bc, uptr->pos);
|
sim_debug_unit (MTSE_DBG_STR, uptr, "rd_lntf: st: %d, lnt: %d, pos: %" T_ADDR_FMT "u\n", status, *bc, uptr->pos);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -965,6 +1018,8 @@ uint32 f = MT_GET_FMT (uptr);
|
||||||
t_addr ppos;
|
t_addr ppos;
|
||||||
t_mtrlnt sbc;
|
t_mtrlnt sbc;
|
||||||
t_tpclnt tpcbc;
|
t_tpclnt tpcbc;
|
||||||
|
t_awshdr awshdr;
|
||||||
|
size_t rdcnt;
|
||||||
t_mtrlnt buffer [256]; /* local tape buffer */
|
t_mtrlnt buffer [256]; /* local tape buffer */
|
||||||
uint32 bufcntr, bufcap; /* buffer counter and capacity */
|
uint32 bufcntr, bufcap; /* buffer counter and capacity */
|
||||||
int32 runaway_counter, sizeof_gap; /* bytes remaining before runaway and bytes per gap */
|
int32 runaway_counter, sizeof_gap; /* bytes remaining before runaway and bytes per gap */
|
||||||
|
@ -1119,6 +1174,59 @@ else switch (f) { /* otherwise the read me
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MTUF_F_AWS:
|
||||||
|
sbc = 0;
|
||||||
|
while ((sbc == 0) && (status == MTSE_OK)) {
|
||||||
|
if (sim_tape_bot (uptr)) { /* if we start at BOT */
|
||||||
|
status = MTSE_BOT; /* then we're done */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
(void)sim_fseek (uptr->fileref, uptr->pos, SEEK_SET);/* position */
|
||||||
|
memset (&awshdr, 0, sizeof (awshdr));
|
||||||
|
rdcnt = sim_fread (&awshdr, sizeof (t_awslnt), 3, uptr->fileref);
|
||||||
|
*bc = awshdr.prelen; /* save rec lnt */
|
||||||
|
|
||||||
|
if (ferror (uptr->fileref)) { /* error? */
|
||||||
|
status = sim_tape_ioerr (uptr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (feof (uptr->fileref)) { /* eof? */
|
||||||
|
status = MTSE_EOM;
|
||||||
|
if ((uptr->pos > sizeof (t_awshdr)) &&
|
||||||
|
(uptr->pos >= sim_fsize (uptr->fileref)))
|
||||||
|
uptr->pos -= sizeof (t_awshdr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((rdcnt != 3) ||
|
||||||
|
((awshdr.rectyp != AWS_REC) &&
|
||||||
|
(awshdr.rectyp != AWS_TMK))) {
|
||||||
|
status = MTSE_INVRL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sbc = *bc; /* extract the record length */
|
||||||
|
if (MT_TST_INMRK (uptr)) /* already in a tapemark? */
|
||||||
|
awshdr.rectyp = AWS_REC;
|
||||||
|
MT_CLR_INMRK (uptr); /* No longer in a tapemark */
|
||||||
|
if ((awshdr.rectyp != AWS_TMK) ||
|
||||||
|
(awshdr.prelen == 0)) {
|
||||||
|
uptr->pos -= sizeof (t_awshdr); /* position to the start of the record */
|
||||||
|
uptr->pos -= awshdr.prelen; /* Including the data length */
|
||||||
|
|
||||||
|
if (sim_fseek (uptr->fileref, /* seek to the start of the data area; if it fails */
|
||||||
|
uptr->pos + sizeof (t_awshdr),
|
||||||
|
SEEK_SET)) {
|
||||||
|
status = sim_tape_ioerr (uptr); /* then return with I/O error status */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (awshdr.rectyp == AWS_TMK) { /* tape mark? */
|
||||||
|
status = MTSE_TMK;
|
||||||
|
if (awshdr.prelen != 0)
|
||||||
|
MT_SET_INMRK (uptr); /* Flag processing a tapemark header */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
status = MTSE_FMT;
|
status = MTSE_FMT;
|
||||||
}
|
}
|
||||||
|
@ -1136,7 +1244,7 @@ if (ctx == NULL) /* if not properly attac
|
||||||
|
|
||||||
status = sim_tape_rdlntr (uptr, bc); /* read the record length */
|
status = sim_tape_rdlntr (uptr, bc); /* read the record length */
|
||||||
|
|
||||||
sim_debug (MTSE_DBG_STR, ctx->dptr, "rd_lnt: st: %d, lnt: %d, pos: %" T_ADDR_FMT "u\n", status, *bc, uptr->pos);
|
sim_debug_unit (MTSE_DBG_STR, uptr, "rd_lntr: st: %d, lnt: %d, pos: %" T_ADDR_FMT "u\n", status, *bc, uptr->pos);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -1194,7 +1302,7 @@ for ( ; i < rbc; i++) /* fill with 0's */
|
||||||
buf[i] = 0;
|
buf[i] = 0;
|
||||||
if (f == MTUF_F_P7B) /* p7b? strip SOR */
|
if (f == MTUF_F_P7B) /* p7b? strip SOR */
|
||||||
buf[0] = buf[0] & P7B_DPAR;
|
buf[0] = buf[0] & P7B_DPAR;
|
||||||
sim_tape_data_trace(uptr, buf, rbc, "Record Read", ctx->dptr->dctrl & MTSE_DBG_DAT, MTSE_DBG_STR);
|
sim_tape_data_trace(uptr, buf, rbc, "Record Read", (uptr->dctrl | ctx->dptr->dctrl) & MTSE_DBG_DAT, MTSE_DBG_STR);
|
||||||
return (MTR_F (tbc)? MTSE_RECE: MTSE_OK);
|
return (MTR_F (tbc)? MTSE_RECE: MTSE_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1254,7 +1362,7 @@ for ( ; i < rbc; i++) /* fill with 0's */
|
||||||
buf[i] = 0;
|
buf[i] = 0;
|
||||||
if (f == MTUF_F_P7B) /* p7b? strip SOR */
|
if (f == MTUF_F_P7B) /* p7b? strip SOR */
|
||||||
buf[0] = buf[0] & P7B_DPAR;
|
buf[0] = buf[0] & P7B_DPAR;
|
||||||
sim_tape_data_trace(uptr, buf, rbc, "Record Read Reverse", ctx->dptr->dctrl & MTSE_DBG_DAT, MTSE_DBG_STR);
|
sim_tape_data_trace(uptr, buf, rbc, "Record Read Reverse", (uptr->dctrl | ctx->dptr->dctrl) & MTSE_DBG_DAT, MTSE_DBG_STR);
|
||||||
return (MTR_F (tbc)? MTSE_RECE: MTSE_OK);
|
return (MTR_F (tbc)? MTSE_RECE: MTSE_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1289,12 +1397,13 @@ t_stat sim_tape_wrrecf (UNIT *uptr, uint8 *buf, t_mtrlnt bc)
|
||||||
struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
|
struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
|
||||||
uint32 f = MT_GET_FMT (uptr);
|
uint32 f = MT_GET_FMT (uptr);
|
||||||
t_mtrlnt sbc;
|
t_mtrlnt sbc;
|
||||||
|
t_stat status = MTSE_OK;
|
||||||
|
|
||||||
if (ctx == NULL) /* if not properly attached? */
|
if (ctx == NULL) /* if not properly attached? */
|
||||||
return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */
|
return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */
|
||||||
sim_debug_unit (ctx->dbit, uptr, "sim_tape_wrrecf(unit=%d, buf=%p, bc=%d)\n", (int)(uptr-ctx->dptr->units), buf, bc);
|
sim_debug_unit (ctx->dbit, uptr, "sim_tape_wrrecf(unit=%d, buf=%p, bc=%d)\n", (int)(uptr-ctx->dptr->units), buf, bc);
|
||||||
|
|
||||||
sim_tape_data_trace(uptr, buf, bc, "Record Write", ctx->dptr->dctrl & MTSE_DBG_DAT, MTSE_DBG_STR);
|
sim_tape_data_trace(uptr, buf, bc, "Record Write", (uptr->dctrl | ctx->dptr->dctrl) & MTSE_DBG_DAT, MTSE_DBG_STR);
|
||||||
MT_CLR_PNU (uptr);
|
MT_CLR_PNU (uptr);
|
||||||
sbc = MTR_L (bc);
|
sbc = MTR_L (bc);
|
||||||
if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */
|
if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */
|
||||||
|
@ -1331,8 +1440,13 @@ switch (f) { /* case on format */
|
||||||
}
|
}
|
||||||
uptr->pos = uptr->pos + sbc; /* move tape */
|
uptr->pos = uptr->pos + sbc; /* move tape */
|
||||||
break;
|
break;
|
||||||
|
case MTUF_F_AWS: /* AWS */
|
||||||
|
status = sim_tape_aws_wrdata (uptr, buf, bc);
|
||||||
|
if (status != MTSE_OK)
|
||||||
|
return status;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
sim_tape_data_trace(uptr, buf, sbc, "Record Written", ctx->dptr->dctrl & MTSE_DBG_DAT, MTSE_DBG_STR);
|
sim_tape_data_trace(uptr, buf, sbc, "Record Written", (uptr->dctrl | ctx->dptr->dctrl) & MTSE_DBG_DAT, MTSE_DBG_STR);
|
||||||
return MTSE_OK;
|
return MTSE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1345,6 +1459,48 @@ AIO_CALL(TOP_WREC, buf, 0, NULL, 0, bc, 0, 0, NULL, callback);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Write AWS metadata (and possibly data) forward (internal routine) */
|
||||||
|
|
||||||
|
static t_stat sim_tape_aws_wrdata (UNIT *uptr, uint8 *buf, t_mtrlnt bc)
|
||||||
|
{
|
||||||
|
t_awshdr awshdr;
|
||||||
|
size_t rdcnt;
|
||||||
|
t_bool replacing_record;
|
||||||
|
|
||||||
|
memset (&awshdr, 0, sizeof (t_awshdr));
|
||||||
|
if (sim_fseek (uptr->fileref, uptr->pos, SEEK_SET)) /* set pos */
|
||||||
|
return MTSE_IOERR;
|
||||||
|
rdcnt = sim_fread (&awshdr, sizeof (t_awslnt), 3, uptr->fileref);
|
||||||
|
if (ferror (uptr->fileref)) { /* error? */
|
||||||
|
MT_SET_PNU (uptr); /* pos not upd */
|
||||||
|
return sim_tape_ioerr (uptr);
|
||||||
|
}
|
||||||
|
if ((!sim_tape_bot (uptr)) &&
|
||||||
|
(((feof (uptr->fileref)) && (rdcnt < 3)) || /* eof? */
|
||||||
|
((awshdr.rectyp != AWS_REC) && (awshdr.rectyp != AWS_TMK)))) {
|
||||||
|
MT_SET_PNU (uptr); /* pos not upd */
|
||||||
|
return MTSE_INVRL;
|
||||||
|
}
|
||||||
|
if (sim_fseek (uptr->fileref, uptr->pos, SEEK_SET)) /* set pos */
|
||||||
|
return MTSE_IOERR;
|
||||||
|
replacing_record = (awshdr.nxtlen == (t_awslnt)bc) && (awshdr.rectyp == (bc ? AWS_REC : AWS_TMK));
|
||||||
|
awshdr.nxtlen = (t_awslnt)bc;
|
||||||
|
awshdr.rectyp = (bc) ? AWS_REC : AWS_TMK;
|
||||||
|
sim_fwrite (&awshdr, sizeof (t_awslnt), 3, uptr->fileref);
|
||||||
|
if (bc)
|
||||||
|
sim_fwrite (buf, sizeof (uint8), bc, uptr->fileref);
|
||||||
|
uptr->pos += sizeof (awshdr) + bc;
|
||||||
|
if ((!replacing_record) | (bc == 0)) {
|
||||||
|
awshdr.prelen = bc;
|
||||||
|
awshdr.nxtlen = 0;
|
||||||
|
awshdr.rectyp = AWS_TMK;
|
||||||
|
sim_fwrite (&awshdr, sizeof (t_awslnt), 3, uptr->fileref);
|
||||||
|
if (!replacing_record)
|
||||||
|
sim_set_fsize (uptr->fileref, uptr->pos + sizeof (awshdr));
|
||||||
|
}
|
||||||
|
return MTSE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* Write metadata forward (internal routine) */
|
/* Write metadata forward (internal routine) */
|
||||||
|
|
||||||
static t_stat sim_tape_wrdata (UNIT *uptr, uint32 dat)
|
static t_stat sim_tape_wrdata (UNIT *uptr, uint32 dat)
|
||||||
|
@ -1364,7 +1520,7 @@ if (ferror (uptr->fileref)) { /* error? */
|
||||||
MT_SET_PNU (uptr);
|
MT_SET_PNU (uptr);
|
||||||
return sim_tape_ioerr (uptr);
|
return sim_tape_ioerr (uptr);
|
||||||
}
|
}
|
||||||
sim_debug (MTSE_DBG_STR, ctx->dptr, "wr_lnt: lnt: %d, pos: %" T_ADDR_FMT "u\n", dat, uptr->pos);
|
sim_debug_unit (MTSE_DBG_STR, uptr, "wr_lnt: lnt: %d, pos: %" T_ADDR_FMT "u\n", dat, uptr->pos);
|
||||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* move tape */
|
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* move tape */
|
||||||
return MTSE_OK;
|
return MTSE_OK;
|
||||||
}
|
}
|
||||||
|
@ -1382,6 +1538,8 @@ if (MT_GET_FMT (uptr) == MTUF_F_P7B) { /* P7B? */
|
||||||
uint8 buf = P7B_EOF; /* eof mark */
|
uint8 buf = P7B_EOF; /* eof mark */
|
||||||
return sim_tape_wrrecf (uptr, &buf, 1); /* write char */
|
return sim_tape_wrrecf (uptr, &buf, 1); /* write char */
|
||||||
}
|
}
|
||||||
|
if (MT_GET_FMT (uptr) == MTUF_F_AWS) /* AWS? */
|
||||||
|
return sim_tape_aws_wrdata (uptr, NULL, 0);
|
||||||
return sim_tape_wrdata (uptr, MTR_TMK);
|
return sim_tape_wrdata (uptr, MTR_TMK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1404,12 +1562,19 @@ struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
|
||||||
if (ctx == NULL) /* if not properly attached? */
|
if (ctx == NULL) /* if not properly attached? */
|
||||||
return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */
|
return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */
|
||||||
sim_debug_unit (ctx->dbit, uptr, "sim_tape_wreom(unit=%d)\n", (int)(uptr-ctx->dptr->units));
|
sim_debug_unit (ctx->dbit, uptr, "sim_tape_wreom(unit=%d)\n", (int)(uptr-ctx->dptr->units));
|
||||||
|
if (sim_tape_wrp (uptr)) /* write prot? */
|
||||||
|
return MTSE_WRP;
|
||||||
if (MT_GET_FMT (uptr) == MTUF_F_P7B) /* cant do P7B */
|
if (MT_GET_FMT (uptr) == MTUF_F_P7B) /* cant do P7B */
|
||||||
return MTSE_FMT;
|
return MTSE_FMT;
|
||||||
|
if (MT_GET_FMT (uptr) == MTUF_F_AWS) {
|
||||||
|
sim_tape_aws_wrdata (uptr, NULL, 0);
|
||||||
|
sim_set_fsize (uptr->fileref, uptr->pos);
|
||||||
|
result = MTSE_OK;
|
||||||
|
}
|
||||||
|
else {
|
||||||
result = sim_tape_wrdata (uptr, MTR_EOM); /* write the EOM marker */
|
result = sim_tape_wrdata (uptr, MTR_EOM); /* write the EOM marker */
|
||||||
|
|
||||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* restore original tape position */
|
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* restore original tape position */
|
||||||
|
}
|
||||||
MT_SET_PNU (uptr); /* indicate that position was not updated */
|
MT_SET_PNU (uptr); /* indicate that position was not updated */
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -1434,9 +1599,7 @@ t_stat r;
|
||||||
if (ctx == NULL) /* if not properly attached? */
|
if (ctx == NULL) /* if not properly attached? */
|
||||||
return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */
|
return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */
|
||||||
sim_debug_unit (ctx->dbit, uptr, "sim_tape_wreomrw(unit=%d)\n", (int)(uptr-ctx->dptr->units));
|
sim_debug_unit (ctx->dbit, uptr, "sim_tape_wreomrw(unit=%d)\n", (int)(uptr-ctx->dptr->units));
|
||||||
if (MT_GET_FMT (uptr) == MTUF_F_P7B) /* cant do P7B */
|
r = sim_tape_wreom (uptr);
|
||||||
return MTSE_FMT;
|
|
||||||
r = sim_tape_wrdata (uptr, MTR_EOM);
|
|
||||||
if (r == MTSE_OK)
|
if (r == MTSE_OK)
|
||||||
r = sim_tape_rewind (uptr);
|
r = sim_tape_rewind (uptr);
|
||||||
return r;
|
return r;
|
||||||
|
@ -2464,7 +2627,7 @@ return (uptr->capac && (uptr->pos >= uptr->capac))? TRUE: FALSE;
|
||||||
|
|
||||||
t_bool sim_tape_wrp (UNIT *uptr)
|
t_bool sim_tape_wrp (UNIT *uptr)
|
||||||
{
|
{
|
||||||
return ((uptr->flags & MTUF_WRP) || (MT_GET_FMT (uptr) == MTUF_F_TPC))? TRUE: FALSE;
|
return ((uptr->flags & MTUF_WRP) || (uptr->flags & UNIT_RO) || (MT_GET_FMT (uptr) == MTUF_F_TPC))? TRUE: FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process I/O error */
|
/* Process I/O error */
|
||||||
|
@ -2529,7 +2692,7 @@ if ((uptr == NULL) || (uptr->fileref == NULL))
|
||||||
countmap = (uint32 *)calloc (65536, sizeof(*countmap));
|
countmap = (uint32 *)calloc (65536, sizeof(*countmap));
|
||||||
recbuf = (uint8 *)malloc (65536);
|
recbuf = (uint8 *)malloc (65536);
|
||||||
tape_size = (t_addr)sim_fsize (uptr->fileref);
|
tape_size = (t_addr)sim_fsize (uptr->fileref);
|
||||||
sim_debug (MTSE_DBG_STR, dptr, "tpc_map: tape_size: %" T_ADDR_FMT "u\n", tape_size);
|
sim_debug_unit (MTSE_DBG_STR, uptr, "tpc_map: tape_size: %" T_ADDR_FMT "u\n", tape_size);
|
||||||
for (objc = 0, sizec = 0, tpos = 0;; ) {
|
for (objc = 0, sizec = 0, tpos = 0;; ) {
|
||||||
(void)sim_fseek (uptr->fileref, tpos, SEEK_SET);
|
(void)sim_fseek (uptr->fileref, tpos, SEEK_SET);
|
||||||
i = sim_fread (&bc, sizeof (t_tpclnt), 1, uptr->fileref);
|
i = sim_fread (&bc, sizeof (t_tpclnt), 1, uptr->fileref);
|
||||||
|
@ -2541,14 +2704,14 @@ for (objc = 0, sizec = 0, tpos = 0;; ) {
|
||||||
if (map && (objc < mapsize))
|
if (map && (objc < mapsize))
|
||||||
map[objc] = tpos;
|
map[objc] = tpos;
|
||||||
if (bc) {
|
if (bc) {
|
||||||
sim_debug (MTSE_DBG_STR, dptr, "tpc_map: %d byte count at pos: %" T_ADDR_FMT "u\n", bc, tpos);
|
sim_debug_unit (MTSE_DBG_STR, uptr, "tpc_map: %d byte count at pos: %" T_ADDR_FMT "u\n", bc, tpos);
|
||||||
if (map && sim_deb && (dptr->dctrl & MTSE_DBG_STR)) {
|
if (map && sim_deb && (dptr->dctrl & MTSE_DBG_STR)) {
|
||||||
(void)sim_fread (recbuf, 1, bc, uptr->fileref);
|
(void)sim_fread (recbuf, 1, bc, uptr->fileref);
|
||||||
sim_data_trace(dptr, uptr, ((dptr->dctrl & MTSE_DBG_DAT) ? recbuf : NULL), "", bc, "Data Record", MTSE_DBG_STR);
|
sim_data_trace(dptr, uptr, (((uptr->dctrl | dptr->dctrl) & MTSE_DBG_DAT) ? recbuf : NULL), "", bc, "Data Record", MTSE_DBG_STR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
sim_debug (MTSE_DBG_STR, dptr, "tpc_map: tape mark at pos: %" T_ADDR_FMT "u\n", tpos);
|
sim_debug_unit (MTSE_DBG_STR, uptr, "tpc_map: tape mark at pos: %" T_ADDR_FMT "u\n", tpos);
|
||||||
objc++;
|
objc++;
|
||||||
tpos = tpos + ((bc + 1) & ~1) + sizeof (t_tpclnt);
|
tpos = tpos + ((bc + 1) & ~1) + sizeof (t_tpclnt);
|
||||||
if ((bc == 0) && (last_bc == 0)) { /* double tape mark? */
|
if ((bc == 0) && (last_bc == 0)) { /* double tape mark? */
|
||||||
|
@ -2557,13 +2720,13 @@ for (objc = 0, sizec = 0, tpos = 0;; ) {
|
||||||
}
|
}
|
||||||
last_bc = bc;
|
last_bc = bc;
|
||||||
}
|
}
|
||||||
sim_debug (MTSE_DBG_STR, dptr, "tpc_map: objc: %u, different record sizes: %u\n", objc, sizec);
|
sim_debug_unit (MTSE_DBG_STR, uptr, "tpc_map: objc: %u, different record sizes: %u\n", objc, sizec);
|
||||||
for (i=0; i<65535; i++) {
|
for (i=0; i<65535; i++) {
|
||||||
if (countmap[i]) {
|
if (countmap[i]) {
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
sim_debug (MTSE_DBG_STR, dptr, "tpc_map: summary - %u tape marks\n", countmap[i]);
|
sim_debug_unit (MTSE_DBG_STR, uptr, "tpc_map: summary - %u tape marks\n", countmap[i]);
|
||||||
else
|
else
|
||||||
sim_debug (MTSE_DBG_STR, dptr, "tpc_map: summary - %u %d byte record%s\n", countmap[i], (int)i, (countmap[i] > 1) ? "s" : "");
|
sim_debug_unit (MTSE_DBG_STR, uptr, "tpc_map: summary - %u %d byte record%s\n", countmap[i], (int)i, (countmap[i] > 1) ? "s" : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (((last_bc != TPC_EOM) &&
|
if (((last_bc != TPC_EOM) &&
|
||||||
|
@ -2573,24 +2736,24 @@ if (((last_bc != TPC_EOM) &&
|
||||||
((objc == countmap[0]) &&
|
((objc == countmap[0]) &&
|
||||||
(countmap[0] != 2))) { /* Unreasonable format? */
|
(countmap[0] != 2))) { /* Unreasonable format? */
|
||||||
if (last_bc != TPC_EOM)
|
if (last_bc != TPC_EOM)
|
||||||
sim_debug (MTSE_DBG_STR, dptr, "tpc_map: ERROR unexpected EOT byte count: %d\n", last_bc);
|
sim_debug_unit (MTSE_DBG_STR, uptr, "tpc_map: ERROR unexpected EOT byte count: %d\n", last_bc);
|
||||||
if (tpos > tape_size)
|
if (tpos > tape_size)
|
||||||
sim_debug (MTSE_DBG_STR, dptr, "tpc_map: ERROR next record position %" T_ADDR_FMT "u beyond EOT: %" T_ADDR_FMT "u\n", tpos, tape_size);
|
sim_debug_unit (MTSE_DBG_STR, uptr, "tpc_map: ERROR next record position %" T_ADDR_FMT "u beyond EOT: %" T_ADDR_FMT "u\n", tpos, tape_size);
|
||||||
if (objc == countmap[0])
|
if (objc == countmap[0])
|
||||||
sim_debug (MTSE_DBG_STR, dptr, "tpc_map: ERROR tape cnly contains tape marks\n");
|
sim_debug_unit (MTSE_DBG_STR, uptr, "tpc_map: ERROR tape cnly contains tape marks\n");
|
||||||
free (countmap);
|
free (countmap);
|
||||||
free (recbuf);
|
free (recbuf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((last_bc != TPC_EOM) && (tpos > tape_size)) {
|
if ((last_bc != TPC_EOM) && (tpos > tape_size)) {
|
||||||
sim_debug (MTSE_DBG_STR, dptr, "tpc_map: WARNING unexpected EOT byte count: %d, double tape mark before %" T_ADDR_FMT "u provides logical EOT\n", last_bc, leot);
|
sim_debug_unit (MTSE_DBG_STR, uptr, "tpc_map: WARNING unexpected EOT byte count: %d, double tape mark before %" T_ADDR_FMT "u provides logical EOT\n", last_bc, leot);
|
||||||
objc = had_double_tape_mark;
|
objc = had_double_tape_mark;
|
||||||
tpos = leot;
|
tpos = leot;
|
||||||
}
|
}
|
||||||
if (map)
|
if (map)
|
||||||
map[objc] = tpos;
|
map[objc] = tpos;
|
||||||
sim_debug (MTSE_DBG_STR, dptr, "tpc_map: OK objc: %d\n", objc);
|
sim_debug_unit (MTSE_DBG_STR, uptr, "tpc_map: OK objc: %d\n", objc);
|
||||||
free (countmap);
|
free (countmap);
|
||||||
free (recbuf);
|
free (recbuf);
|
||||||
return objc;
|
return objc;
|
||||||
|
@ -2635,6 +2798,7 @@ uint8 *buf = NULL;
|
||||||
uint32 *rec_sizes = NULL;
|
uint32 *rec_sizes = NULL;
|
||||||
t_mtrlnt bc;
|
t_mtrlnt bc;
|
||||||
t_mtrlnt max = MTR_MAXLEN;
|
t_mtrlnt max = MTR_MAXLEN;
|
||||||
|
t_bool prior_was_tapemark = FALSE;
|
||||||
|
|
||||||
if (!(uptr->flags & UNIT_ATT))
|
if (!(uptr->flags & UNIT_ATT))
|
||||||
return SCPE_UNATT;
|
return SCPE_UNATT;
|
||||||
|
@ -2657,10 +2821,15 @@ while (r == SCPE_OK) {
|
||||||
++unique_record_sizes;
|
++unique_record_sizes;
|
||||||
++rec_sizes[bc];
|
++rec_sizes[bc];
|
||||||
r = SCPE_OK;
|
r = SCPE_OK;
|
||||||
|
prior_was_tapemark = FALSE;
|
||||||
break;
|
break;
|
||||||
case MTSE_TMK: /* tape mark */
|
case MTSE_TMK: /* tape mark */
|
||||||
++tapemark_total;
|
++tapemark_total;
|
||||||
|
if (prior_was_tapemark)
|
||||||
|
r = MTSE_LEOT;
|
||||||
|
else
|
||||||
r = SCPE_OK;
|
r = SCPE_OK;
|
||||||
|
prior_was_tapemark = TRUE;
|
||||||
break;
|
break;
|
||||||
case MTSE_INVRL: /* invalid rec lnt */
|
case MTSE_INVRL: /* invalid rec lnt */
|
||||||
case MTSE_FMT: /* invalid format */
|
case MTSE_FMT: /* invalid format */
|
||||||
|
@ -2675,7 +2844,7 @@ while (r == SCPE_OK) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((r != MTSE_EOM) || (sim_switches & SWMASK ('V')) ||
|
if (((r != MTSE_EOM) && (r != MTSE_LEOT)) || (sim_switches & SWMASK ('V')) ||
|
||||||
((uint32)(sim_fsize_ex (uptr->fileref) - (t_offset)uptr->pos) > fmts[MT_GET_FMT (uptr)].eom_remnant) ||
|
((uint32)(sim_fsize_ex (uptr->fileref) - (t_offset)uptr->pos) > fmts[MT_GET_FMT (uptr)].eom_remnant) ||
|
||||||
(unique_record_sizes > 2 * tapemark_seen)) {
|
(unique_record_sizes > 2 * tapemark_seen)) {
|
||||||
uint32 remaining_data = (uint32)(sim_fsize_ex (uptr->fileref) - (t_offset)uptr->pos);
|
uint32 remaining_data = (uint32)(sim_fsize_ex (uptr->fileref) - (t_offset)uptr->pos);
|
||||||
|
@ -2694,7 +2863,7 @@ if ((r != MTSE_EOM) || (sim_switches & SWMASK ('V')) ||
|
||||||
sim_printf ("%8u %u byte records\n", rec_sizes[bc], (uint32)bc);
|
sim_printf ("%8u %u byte records\n", rec_sizes[bc], (uint32)bc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (r != MTSE_EOM)
|
if ((r != MTSE_EOM) && (r != MTSE_LEOT))
|
||||||
sim_printf ("Read Tape Record Returned Unexpected Status: %s\n", sim_tape_error_text (r));
|
sim_printf ("Read Tape Record Returned Unexpected Status: %s\n", sim_tape_error_text (r));
|
||||||
if (remaining_data > fmts[MT_GET_FMT (uptr)].eom_remnant)
|
if (remaining_data > fmts[MT_GET_FMT (uptr)].eom_remnant)
|
||||||
sim_printf ("%u bytes of unexamined data remain in the tape image file\n", remaining_data);
|
sim_printf ("%u bytes of unexamined data remain in the tape image file\n", remaining_data);
|
||||||
|
@ -2728,6 +2897,7 @@ while (r == SCPE_OK) {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
case MTSE_EOM: /* end of medium */
|
case MTSE_EOM: /* end of medium */
|
||||||
|
r = SCPE_OK;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2905,19 +3075,28 @@ static t_bool p7b_parity_inited = FALSE;
|
||||||
static uint8 p7b_odd_parity[64];
|
static uint8 p7b_odd_parity[64];
|
||||||
static uint8 p7b_even_parity[64];
|
static uint8 p7b_even_parity[64];
|
||||||
|
|
||||||
static t_stat create_tape_files (UNIT *uptr, const char *filename, int files, int records)
|
static t_stat create_tape_files (UNIT *uptr, const char *filename, int files, int records, int max_size)
|
||||||
{
|
{
|
||||||
FILE *fSIMH = NULL;
|
FILE *fSIMH = NULL;
|
||||||
FILE *fE11 = NULL;
|
FILE *fE11 = NULL;
|
||||||
FILE *fTPC = NULL;
|
FILE *fTPC = NULL;
|
||||||
FILE *fP7B = NULL;
|
FILE *fP7B = NULL;
|
||||||
|
FILE *fAWS = NULL;
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
t_tpclnt tpclnt;
|
t_tpclnt tpclnt;
|
||||||
t_mtrlnt mtrlnt;
|
t_mtrlnt mtrlnt;
|
||||||
|
t_awslnt awslnt;
|
||||||
|
t_awslnt awslnt_last = 0;
|
||||||
|
t_awslnt awsrec_typ = AWS_REC;
|
||||||
char name[256];
|
char name[256];
|
||||||
t_stat stat = SCPE_OPENERR;
|
t_stat stat = SCPE_OPENERR;
|
||||||
uint8 *buf = NULL;
|
uint8 *buf = NULL;
|
||||||
|
t_stat aws_stat;
|
||||||
|
int32 saved_switches = sim_switches;
|
||||||
|
|
||||||
|
srand (0); /* All devices use the same random sequence for file data */
|
||||||
|
if (max_size == 0)
|
||||||
|
max_size = 65535;
|
||||||
if (!p7b_parity_inited) {
|
if (!p7b_parity_inited) {
|
||||||
for (i=0; i < 64; i++) {
|
for (i=0; i < 64; i++) {
|
||||||
int bit_count = 0;
|
int bit_count = 0;
|
||||||
|
@ -2950,12 +3129,24 @@ sprintf (name, "%s.p7b", filename);
|
||||||
fP7B = fopen (name, "wb");
|
fP7B = fopen (name, "wb");
|
||||||
if (fP7B == NULL)
|
if (fP7B == NULL)
|
||||||
goto Done_Files;
|
goto Done_Files;
|
||||||
|
sprintf (name, "%s.aws", filename);
|
||||||
|
fAWS = fopen (name, "wb");
|
||||||
|
if (fAWS == NULL)
|
||||||
|
goto Done_Files;
|
||||||
|
sprintf (name, "aws %s.aws.tape", filename);
|
||||||
|
(void)remove (name);
|
||||||
|
sim_switches = SWMASK ('F') | (sim_switches & SWMASK ('D')) | SWMASK ('N');
|
||||||
|
if (sim_switches & SWMASK ('D'))
|
||||||
|
uptr->dctrl = MTSE_DBG_STR | MTSE_DBG_DAT;
|
||||||
|
aws_stat = sim_tape_attach_ex (uptr, name, (saved_switches & SWMASK ('D')) ? MTSE_DBG_STR | MTSE_DBG_DAT: 0, 0);
|
||||||
|
sim_switches = saved_switches;
|
||||||
stat = SCPE_OK;
|
stat = SCPE_OK;
|
||||||
for (i=0; i<files; i++) {
|
for (i=0; i<files; i++) {
|
||||||
int rec_size = 1 + (rand () % 65535);
|
int rec_size = 1 + (rand () % max_size);
|
||||||
|
|
||||||
mtrlnt = tpclnt = rec_size;
|
awslnt = mtrlnt = tpclnt = rec_size;
|
||||||
for (j=0; j<records; j++) {
|
for (j=0; j<records; j++) {
|
||||||
|
awsrec_typ = AWS_REC;
|
||||||
if (sim_switches & SWMASK ('V'))
|
if (sim_switches & SWMASK ('V'))
|
||||||
sim_printf ("Writing %d byte record\n", rec_size);
|
sim_printf ("Writing %d byte record\n", rec_size);
|
||||||
for (k=0; k<rec_size; k++)
|
for (k=0; k<rec_size; k++)
|
||||||
|
@ -2963,9 +3154,17 @@ for (i=0; i<files; i++) {
|
||||||
(void)sim_fwrite (&mtrlnt, sizeof (mtrlnt), 1, fSIMH);
|
(void)sim_fwrite (&mtrlnt, sizeof (mtrlnt), 1, fSIMH);
|
||||||
(void)sim_fwrite (&mtrlnt, sizeof (mtrlnt), 1, fE11);
|
(void)sim_fwrite (&mtrlnt, sizeof (mtrlnt), 1, fE11);
|
||||||
(void)sim_fwrite (&tpclnt, sizeof (tpclnt), 1, fTPC);
|
(void)sim_fwrite (&tpclnt, sizeof (tpclnt), 1, fTPC);
|
||||||
|
(void)sim_fwrite (&awslnt, sizeof (awslnt), 1, fAWS);
|
||||||
|
(void)sim_fwrite (&awslnt_last, sizeof (awslnt_last), 1, fAWS);
|
||||||
|
(void)sim_fwrite (&awsrec_typ, sizeof (awsrec_typ), 1, fAWS);
|
||||||
|
awslnt_last = awslnt;
|
||||||
(void)sim_fwrite (buf, 1, rec_size, fSIMH);
|
(void)sim_fwrite (buf, 1, rec_size, fSIMH);
|
||||||
(void)sim_fwrite (buf, 1, rec_size, fE11);
|
(void)sim_fwrite (buf, 1, rec_size, fE11);
|
||||||
(void)sim_fwrite (buf, 1, rec_size, fTPC);
|
(void)sim_fwrite (buf, 1, rec_size, fTPC);
|
||||||
|
(void)sim_fwrite (buf, 1, rec_size, fAWS);
|
||||||
|
stat = sim_tape_wrrecf (uptr, buf, rec_size);
|
||||||
|
if (MTSE_OK != stat)
|
||||||
|
goto Done_Files;
|
||||||
if (rec_size & 1) {
|
if (rec_size & 1) {
|
||||||
(void)sim_fwrite (&tpclnt, 1, 1, fSIMH);
|
(void)sim_fwrite (&tpclnt, 1, 1, fSIMH);
|
||||||
(void)sim_fwrite (&tpclnt, 1, 1, fTPC);
|
(void)sim_fwrite (&tpclnt, 1, 1, fTPC);
|
||||||
|
@ -2977,17 +3176,31 @@ for (i=0; i<files; i++) {
|
||||||
buf[0] |= P7B_SOR;
|
buf[0] |= P7B_SOR;
|
||||||
(void)sim_fwrite (buf, 1, rec_size, fP7B);
|
(void)sim_fwrite (buf, 1, rec_size, fP7B);
|
||||||
}
|
}
|
||||||
mtrlnt = tpclnt = 0;
|
awslnt_last = awslnt;
|
||||||
|
mtrlnt = tpclnt = awslnt = 0;
|
||||||
|
awsrec_typ = AWS_TMK;
|
||||||
(void)sim_fwrite (&mtrlnt, sizeof (mtrlnt), 1, fSIMH);
|
(void)sim_fwrite (&mtrlnt, sizeof (mtrlnt), 1, fSIMH);
|
||||||
(void)sim_fwrite (&mtrlnt, sizeof (mtrlnt), 1, fE11);
|
(void)sim_fwrite (&mtrlnt, sizeof (mtrlnt), 1, fE11);
|
||||||
(void)sim_fwrite (&tpclnt, sizeof (tpclnt), 1, fTPC);
|
(void)sim_fwrite (&tpclnt, sizeof (tpclnt), 1, fTPC);
|
||||||
buf[0] = P7B_SOR | P7B_EOF;
|
buf[0] = P7B_SOR | P7B_EOF;
|
||||||
(void)sim_fwrite (buf, 1, 1, fP7B);
|
(void)sim_fwrite (buf, 1, 1, fP7B);
|
||||||
|
(void)sim_fwrite (&awslnt, sizeof (awslnt), 1, fAWS);
|
||||||
|
(void)sim_fwrite (&awslnt_last, sizeof (awslnt_last), 1, fAWS);
|
||||||
|
(void)sim_fwrite (&awsrec_typ, sizeof (awsrec_typ), 1, fAWS);
|
||||||
|
awslnt_last = 0;
|
||||||
|
stat = sim_tape_wrtmk (uptr);
|
||||||
|
if (MTSE_OK != stat)
|
||||||
|
goto Done_Files;
|
||||||
}
|
}
|
||||||
mtrlnt = tpclnt = 0;
|
mtrlnt = tpclnt = 0;
|
||||||
(void)sim_fwrite (&mtrlnt, sizeof (mtrlnt), 1, fSIMH);
|
(void)sim_fwrite (&mtrlnt, sizeof (mtrlnt), 1, fSIMH);
|
||||||
(void)sim_fwrite (&mtrlnt, sizeof (mtrlnt), 1, fE11);
|
(void)sim_fwrite (&mtrlnt, sizeof (mtrlnt), 1, fE11);
|
||||||
(void)sim_fwrite (&tpclnt, sizeof (tpclnt), 1, fTPC);
|
(void)sim_fwrite (&tpclnt, sizeof (tpclnt), 1, fTPC);
|
||||||
|
awslnt_last = awslnt;
|
||||||
|
awsrec_typ = AWS_TMK;
|
||||||
|
(void)sim_fwrite (&awslnt, sizeof (awslnt), 1, fAWS);
|
||||||
|
(void)sim_fwrite (&awslnt_last, sizeof (awslnt_last), 1, fAWS);
|
||||||
|
(void)sim_fwrite (&awsrec_typ, sizeof (awsrec_typ), 1, fAWS);
|
||||||
mtrlnt = 0xffffffff;
|
mtrlnt = 0xffffffff;
|
||||||
tpclnt = 0xffff;
|
tpclnt = 0xffff;
|
||||||
(void)sim_fwrite (&mtrlnt, sizeof (mtrlnt), 1, fSIMH);
|
(void)sim_fwrite (&mtrlnt, sizeof (mtrlnt), 1, fSIMH);
|
||||||
|
@ -3003,7 +3216,20 @@ if (fTPC)
|
||||||
fclose (fTPC);
|
fclose (fTPC);
|
||||||
if (fP7B)
|
if (fP7B)
|
||||||
fclose (fP7B);
|
fclose (fP7B);
|
||||||
|
if (fAWS)
|
||||||
|
fclose (fAWS);
|
||||||
free (buf);
|
free (buf);
|
||||||
|
sim_tape_detach (uptr);
|
||||||
|
if (stat == SCPE_OK) {
|
||||||
|
char name1[CBUFSIZE], name2[CBUFSIZE];
|
||||||
|
|
||||||
|
sprintf (name1, "\"%s.aws\"", filename);
|
||||||
|
sprintf (name2, "\"%s.aws.tape\"", filename);
|
||||||
|
sim_switches = SWMASK ('F');
|
||||||
|
if (sim_cmp_string (name1, name2))
|
||||||
|
stat = 1;
|
||||||
|
}
|
||||||
|
sim_switches = saved_switches;
|
||||||
return stat;
|
return stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3035,6 +3261,8 @@ sprintf (name, "%s.tpc", filename);
|
||||||
(void)remove (name);
|
(void)remove (name);
|
||||||
sprintf (name, "%s.p7b", filename);
|
sprintf (name, "%s.p7b", filename);
|
||||||
(void)remove (name);
|
(void)remove (name);
|
||||||
|
sprintf (name, "%s.aws", filename);
|
||||||
|
(void)remove (name);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3042,21 +3270,28 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat sim_tape_test (DEVICE *dptr)
|
t_stat sim_tape_test (DEVICE *dptr)
|
||||||
{
|
{
|
||||||
|
int32 saved_switches = sim_switches;
|
||||||
SIM_TEST_INIT;
|
SIM_TEST_INIT;
|
||||||
|
|
||||||
sim_printf ("\nTesting %s device sim_tape APIs\n", sim_uname(dptr->units));
|
sim_printf ("\nTesting %s device sim_tape APIs\n", sim_uname(dptr->units));
|
||||||
|
|
||||||
SIM_TEST(remove_tape_files (dptr->units, "TapeTestFile1"));
|
SIM_TEST(remove_tape_files (dptr->units, "TapeTestFile1"));
|
||||||
|
|
||||||
//SIM_TEST(create_tape_files (dptr->units, "TapeTestFile1", 10, 500));
|
SIM_TEST(create_tape_files (dptr->units, "TapeTestFile1", 2, 4, 4096));
|
||||||
SIM_TEST(create_tape_files (dptr->units, "TapeTestFile1", 7, 100));
|
|
||||||
|
|
||||||
|
sim_switches = saved_switches;
|
||||||
|
SIM_TEST(process_tape_file (dptr->units, "TapeTestFile1", "aws"));
|
||||||
|
|
||||||
|
sim_switches = saved_switches;
|
||||||
SIM_TEST(process_tape_file (dptr->units, "TapeTestFile1", "p7b"));
|
SIM_TEST(process_tape_file (dptr->units, "TapeTestFile1", "p7b"));
|
||||||
|
|
||||||
|
sim_switches = saved_switches;
|
||||||
SIM_TEST(process_tape_file (dptr->units, "TapeTestFile1", "tpc"));
|
SIM_TEST(process_tape_file (dptr->units, "TapeTestFile1", "tpc"));
|
||||||
|
|
||||||
|
sim_switches = saved_switches;
|
||||||
SIM_TEST(process_tape_file (dptr->units, "TapeTestFile1", "e11"));
|
SIM_TEST(process_tape_file (dptr->units, "TapeTestFile1", "e11"));
|
||||||
|
|
||||||
|
sim_switches = saved_switches;
|
||||||
SIM_TEST(process_tape_file (dptr->units, "TapeTestFile1", "simh"));
|
SIM_TEST(process_tape_file (dptr->units, "TapeTestFile1", "simh"));
|
||||||
|
|
||||||
SIM_TEST(remove_tape_files (dptr->units, "TapeTestFile1"));
|
SIM_TEST(remove_tape_files (dptr->units, "TapeTestFile1"));
|
||||||
|
|
22
sim_tape.h
22
sim_tape.h
|
@ -63,6 +63,10 @@ typedef uint32 t_mtrlnt; /* magtape rec lnt */
|
||||||
|
|
||||||
typedef uint16 t_tpclnt; /* magtape rec lnt */
|
typedef uint16 t_tpclnt; /* magtape rec lnt */
|
||||||
|
|
||||||
|
#define TPC_TMK 0x0000 /* tape mark */
|
||||||
|
#define TPC_EOM 0xFFFF /* end of medium */
|
||||||
|
|
||||||
|
|
||||||
/* P7B tape format */
|
/* P7B tape format */
|
||||||
|
|
||||||
#define P7B_SOR 0x80 /* start of record */
|
#define P7B_SOR 0x80 /* start of record */
|
||||||
|
@ -71,8 +75,15 @@ typedef uint16 t_tpclnt; /* magtape rec lnt */
|
||||||
#define P7B_DPAR (P7B_PAR|P7B_DATA) /* data and parity */
|
#define P7B_DPAR (P7B_PAR|P7B_DATA) /* data and parity */
|
||||||
#define P7B_EOF 0x0F /* eof character */
|
#define P7B_EOF 0x0F /* eof character */
|
||||||
|
|
||||||
#define TPC_TMK 0x0000 /* tape mark */
|
/* AWS tape format */
|
||||||
#define TPC_EOM 0xFFFF /* end of medium */
|
typedef uint16 t_awslnt; /* magtape rec lnt */
|
||||||
|
typedef struct {
|
||||||
|
t_awslnt nxtlen;
|
||||||
|
t_awslnt prelen;
|
||||||
|
t_awslnt rectyp;
|
||||||
|
#define AWS_TMK 0x0040
|
||||||
|
#define AWS_REC 0x00A0
|
||||||
|
} t_awshdr;
|
||||||
|
|
||||||
/* Unit flags */
|
/* Unit flags */
|
||||||
|
|
||||||
|
@ -86,7 +97,7 @@ typedef uint16 t_tpclnt; /* magtape rec lnt */
|
||||||
#define MTUF_F_E11 1 /* E11 format */
|
#define MTUF_F_E11 1 /* E11 format */
|
||||||
#define MTUF_F_TPC 2 /* TPC format */
|
#define MTUF_F_TPC 2 /* TPC format */
|
||||||
#define MTUF_F_P7B 3 /* P7B format */
|
#define MTUF_F_P7B 3 /* P7B format */
|
||||||
#define MUTF_F_TDF 4 /* TDF format */
|
#define MTUF_F_AWS 4 /* AWS format */
|
||||||
#define MTUF_V_UF (MTUF_V_FMT + MTUF_W_FMT)
|
#define MTUF_V_UF (MTUF_V_FMT + MTUF_W_FMT)
|
||||||
#define MTUF_PNU (1u << MTUF_V_PNU)
|
#define MTUF_PNU (1u << MTUF_V_PNU)
|
||||||
#define MTUF_WLK (1u << MTUF_V_WLK)
|
#define MTUF_WLK (1u << MTUF_V_WLK)
|
||||||
|
@ -97,11 +108,14 @@ typedef uint16 t_tpclnt; /* magtape rec lnt */
|
||||||
#define MT_F_E11 (MTUF_F_E11 << MTUF_V_FMT)
|
#define MT_F_E11 (MTUF_F_E11 << MTUF_V_FMT)
|
||||||
#define MT_F_TPC (MTUF_F_TPC << MTUF_V_FMT)
|
#define MT_F_TPC (MTUF_F_TPC << MTUF_V_FMT)
|
||||||
#define MT_F_P7B (MTUF_F_P7B << MTUF_V_FMT)
|
#define MT_F_P7B (MTUF_F_P7B << MTUF_V_FMT)
|
||||||
#define MT_F_TDF (MTUF_F_TDF << MTUF_V_FMT)
|
#define MT_F_AWS (MTUF_F_AWS << MTUF_V_FMT)
|
||||||
|
|
||||||
#define MT_SET_PNU(u) (u)->flags = (u)->flags | MTUF_PNU
|
#define MT_SET_PNU(u) (u)->flags = (u)->flags | MTUF_PNU
|
||||||
#define MT_CLR_PNU(u) (u)->flags = (u)->flags & ~MTUF_PNU
|
#define MT_CLR_PNU(u) (u)->flags = (u)->flags & ~MTUF_PNU
|
||||||
#define MT_TST_PNU(u) ((u)->flags & MTUF_PNU)
|
#define MT_TST_PNU(u) ((u)->flags & MTUF_PNU)
|
||||||
|
#define MT_SET_INMRK(u) (u)->dynflags = (u)->dynflags | UNIT_TAPE_MRK
|
||||||
|
#define MT_CLR_INMRK(u) (u)->dynflags = (u)->dynflags & ~UNIT_TAPE_MRK
|
||||||
|
#define MT_TST_INMRK(u) ((u)->dynflags & UNIT_TAPE_MRK)
|
||||||
#define MT_GET_FMT(u) (((u)->flags >> MTUF_V_FMT) & MTUF_M_FMT)
|
#define MT_GET_FMT(u) (((u)->flags >> MTUF_V_FMT) & MTUF_M_FMT)
|
||||||
|
|
||||||
/* sim_tape_position Position Flags */
|
/* sim_tape_position Position Flags */
|
||||||
|
|
Loading…
Add table
Reference in a new issue