TAPE: Reworked reverse read of P7B tapes to avoid seeking on every byte

- Added string density support for MTAB generation
This commit is contained in:
Mark Pizzolato 2019-04-05 00:00:24 -07:00
parent 64fa357bf9
commit 436f1dbbbe
2 changed files with 125 additions and 34 deletions

View file

@ -102,7 +102,7 @@
struct sim_tape_fmt { struct sim_tape_fmt {
const char *name; /* name */ const char *name; /* name */
int32 uflags; /* unit flags */ int32 uflags; /* unit flags */
t_addr bot; /* bot test */ t_addr bot; /* bot test */
t_addr eom_remnant; /* potentially unprocessed data */ t_addr eom_remnant; /* potentially unprocessed data */
}; };
@ -1194,34 +1194,50 @@ else switch (f) { /* otherwise the read me
break; break;
case MTUF_F_P7B: case MTUF_F_P7B:
for (sbc = 1, all_eof = 1; (t_addr) sbc <= uptr->pos ; sbc++) { if (1) {
(void)sim_fseek (uptr->fileref, uptr->pos - sbc, SEEK_SET); #define BUF_SZ 512
(void)sim_fread (&c, sizeof (uint8), 1, uptr->fileref); uint8 buf[BUF_SZ];
t_addr buf_offset;
size_t bytes_in_buf = 0;
size_t read_size;
if (ferror (uptr->fileref)) { /* error? */ for (sbc = 1, all_eof = 1; (t_addr) sbc <= uptr->pos ; sbc++) {
status = sim_tape_ioerr (uptr); if (bytes_in_buf == 0) { /* Need to Fill Buffer */
break; if (uptr->pos < BUF_SZ) {
} buf_offset = 0;
else if (feof (uptr->fileref)) { /* eof? */ read_size = (size_t)uptr->pos;
status = MTSE_EOM; }
break; else {
} buf_offset = uptr->pos - (sbc - 1 + BUF_SZ);
else { read_size = BUF_SZ;
}
(void)sim_fseek (uptr->fileref, buf_offset, SEEK_SET);
bytes_in_buf = sim_fread (buf, sizeof (uint8), read_size, uptr->fileref);
if (ferror (uptr->fileref)) { /* error? */
status = sim_tape_ioerr (uptr);
break;
}
if (feof (uptr->fileref)) { /* eof? */
status = MTSE_EOM;
break;
}
}
c = buf[--bytes_in_buf];
if ((c & P7B_DPAR) != P7B_EOF) if ((c & P7B_DPAR) != P7B_EOF)
all_eof = 0; all_eof = 0;
if (c & P7B_SOR) /* start of record? */ if (c & P7B_SOR) /* start of record? */
break; break;
} }
}
if (status == MTSE_OK) { if (status == MTSE_OK) {
uptr->pos = uptr->pos - sbc; /* update position */ uptr->pos = uptr->pos - sbc; /* update position */
*bc = sbc; /* save rec lnt */ *bc = sbc; /* save rec lnt */
(void)sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* for next read */ (void)sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* for next read */
if (all_eof) /* tape mark? */ if (all_eof) /* tape mark? */
status = MTSE_TMK; status = MTSE_TMK;
}
break;
} }
break;
case MTUF_F_AWS: case MTUF_F_AWS:
*bc = sbc = 0; *bc = sbc = 0;
@ -2883,6 +2899,7 @@ if (rec_sizes == NULL) {
r = sim_tape_rewind (uptr); r = sim_tape_rewind (uptr);
while (r == SCPE_OK) { while (r == SCPE_OK) {
pos_f = uptr->pos; pos_f = uptr->pos;
memset (buf_f, 0, max);
r_f = sim_tape_rdrecf (uptr, buf_f, &bc_f, max); r_f = sim_tape_rdrecf (uptr, buf_f, &bc_f, max);
switch (r_f) { switch (r_f) {
case MTSE_OK: /* no error */ case MTSE_OK: /* no error */
@ -2897,6 +2914,7 @@ while (r == SCPE_OK) {
++unique_record_sizes; ++unique_record_sizes;
++rec_sizes[bc_f]; ++rec_sizes[bc_f];
} }
memset (buf_r, 0, max);
r_r = sim_tape_rdrecr (uptr, buf_r, &bc_r, max); r_r = sim_tape_rdrecr (uptr, buf_r, &bc_r, max);
pos_r = uptr->pos; pos_r = uptr->pos;
if (r_r != r_f) { if (r_r != r_f) {
@ -2904,7 +2922,7 @@ while (r == SCPE_OK) {
break; break;
} }
if (bc_f != bc_r) { if (bc_f != bc_r) {
sim_printf ("Forward Record Read record lemgtj: %d, Reverse read record length: %d\n", bc_f, bc_r); sim_printf ("Forward Record Read record length: %d, Reverse read record length: %d\n", bc_f, bc_r);
break; break;
} }
if (0 != memcmp (buf_f, buf_r, bc_f)) { if (0 != memcmp (buf_f, buf_r, bc_f)) {
@ -2965,7 +2983,6 @@ if ((r != MTSE_EOM) || (sim_switches & SWMASK ('V')) ||
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);
} }
/* Try again reading backwards */
if (unique_record_sizes > 2 * tapemark_total) { if (unique_record_sizes > 2 * tapemark_total) {
sim_printf ("An unreasonable number of record sizes(%u) vs tape marks (%u) have been found\n", unique_record_sizes, tapemark_total); sim_printf ("An unreasonable number of record sizes(%u) vs tape marks (%u) have been found\n", unique_record_sizes, tapemark_total);
sim_printf ("The tape format (%s) might not be correct for the '%s' tape image\n", fmts[MT_GET_FMT (uptr)].name, uptr->filename); sim_printf ("The tape format (%s) might not be correct for the '%s' tape image\n", fmts[MT_GET_FMT (uptr)].name, uptr->filename);
@ -3116,6 +3133,45 @@ else { /* otherwise get the den
return SCPE_OK; return SCPE_OK;
} }
/* list supported densities
translates the mask of supported densities to a string list in the form:
"(800|1600|6250)"
this string may be useful to construct a MTAB help string for a
SET <unit> DENSITY= command.
*/
t_stat sim_tape_density_supported (char *string, size_t string_size, int32 valid_bits)
{
uint32 density;
int32 count;
strlcpy (string, "", string_size);
if ((!valid_bits) || (valid_bits >> BPI_COUNT))
return SCPE_ARG;
for (density = count = 0; density < BPI_COUNT; density++) {
if (valid_bits & (1 << density)) {
char density_str[20];
++count;
if (count == 1)
strlcat (string, "{", string_size);
else
strlcat (string, "|", string_size);
sprintf (density_str, "%d", bpi[density]);
strlcat (string, density_str, string_size);
}
}
if ((count == 1) && (string_size > 1))
memmove (string, string + 1, strlen (string));
else
strlcat (string, "}", string_size);
return SCPE_OK;
}
static DEBTAB tape_debug[] = { static DEBTAB tape_debug[] = {
{"TRACE", MTSE_DBG_API, "API Trace"}, {"TRACE", MTSE_DBG_API, "API Trace"},
{"DATA", MTSE_DBG_DAT, "Tape Data"}, {"DATA", MTSE_DBG_DAT, "Tape Data"},
@ -3135,7 +3191,7 @@ 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, int max_size) static t_stat sim_tape_test_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;
@ -3293,7 +3349,7 @@ sim_switches = saved_switches;
return stat; return stat;
} }
static t_stat process_tape_file (UNIT *uptr, const char *filename, const char *format) static t_stat sim_tape_test_process_tape_file (UNIT *uptr, const char *filename, const char *format)
{ {
char args[256]; char args[256];
t_stat stat; t_stat stat;
@ -3309,7 +3365,7 @@ sim_switches = 0;
return SCPE_OK; return SCPE_OK;
} }
static t_stat remove_tape_files (UNIT *uptr, const char *filename) static t_stat sim_tape_test_remove_tape_files (UNIT *uptr, const char *filename)
{ {
char name[256]; char name[256];
@ -3326,6 +3382,38 @@ sprintf (name, "%s.aws", filename);
return SCPE_OK; return SCPE_OK;
} }
static t_stat sim_tape_test_density_string (void)
{
char buf[128];
int32 valid_bits = 0;
t_stat stat;
if ((SCPE_ARG != (stat = sim_tape_density_supported (buf, sizeof (buf), valid_bits))) ||
(strcmp (buf, "")))
return stat;
valid_bits = MT_556_VALID;
if ((SCPE_OK != (stat = sim_tape_density_supported (buf, sizeof (buf), valid_bits))) ||
(strcmp (buf, "556")))
return sim_messagef (SCPE_ARG, "stat was: %s, got string: %s\n", sim_error_text (stat), buf);
valid_bits = MT_800_VALID | MT_1600_VALID;
if ((SCPE_OK != (stat = sim_tape_density_supported (buf, sizeof (buf), valid_bits))) ||
(strcmp (buf, "{800|1600}")))
return sim_messagef (SCPE_ARG, "stat was: %s, got string: %s\n", sim_error_text (stat), buf);
valid_bits = MT_800_VALID | MT_1600_VALID | MT_6250_VALID;
if ((SCPE_OK != (stat = sim_tape_density_supported (buf, sizeof (buf), valid_bits))) ||
(strcmp (buf, "{800|1600|6250}")))
return sim_messagef (SCPE_ARG, "stat was: %s, got string: %s\n", sim_error_text (stat), buf);
valid_bits = MT_200_VALID | MT_800_VALID | MT_1600_VALID | MT_6250_VALID;
if ((SCPE_OK != (stat = sim_tape_density_supported (buf, sizeof (buf), valid_bits))) ||
(strcmp (buf, "{200|800|1600|6250}")))
return sim_messagef (SCPE_ARG, "stat was: %s, got string: %s\n", sim_error_text (stat), buf);
valid_bits = MT_NONE_VALID | MT_800_VALID | MT_1600_VALID | MT_6250_VALID;
if ((SCPE_OK != (stat = sim_tape_density_supported (buf, sizeof (buf), valid_bits))) ||
(strcmp (buf, "{0|800|1600|6250}")))
return sim_messagef (SCPE_ARG, "stat was: %s, got string: %s\n", sim_error_text (stat), buf);
return SCPE_OK;
}
#include <setjmp.h> #include <setjmp.h>
t_stat sim_tape_test (DEVICE *dptr) t_stat sim_tape_test (DEVICE *dptr)
@ -3335,26 +3423,28 @@ 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(sim_tape_test_density_string ());
SIM_TEST(create_tape_files (dptr->units, "TapeTestFile1", 2, 4, 4096)); SIM_TEST(sim_tape_test_remove_tape_files (dptr->units, "TapeTestFile1"));
SIM_TEST(sim_tape_test_create_tape_files (dptr->units, "TapeTestFile1", 2, 5, 4096));
sim_switches = saved_switches; sim_switches = saved_switches;
SIM_TEST(process_tape_file (dptr->units, "TapeTestFile1", "aws")); SIM_TEST(sim_tape_test_process_tape_file (dptr->units, "TapeTestFile1", "aws"));
sim_switches = saved_switches; sim_switches = saved_switches;
SIM_TEST(process_tape_file (dptr->units, "TapeTestFile1", "p7b")); SIM_TEST(sim_tape_test_process_tape_file (dptr->units, "TapeTestFile1", "p7b"));
sim_switches = saved_switches; sim_switches = saved_switches;
SIM_TEST(process_tape_file (dptr->units, "TapeTestFile1", "tpc")); SIM_TEST(sim_tape_test_process_tape_file (dptr->units, "TapeTestFile1", "tpc"));
sim_switches = saved_switches; sim_switches = saved_switches;
SIM_TEST(process_tape_file (dptr->units, "TapeTestFile1", "e11")); SIM_TEST(sim_tape_test_process_tape_file (dptr->units, "TapeTestFile1", "e11"));
sim_switches = saved_switches; sim_switches = saved_switches;
SIM_TEST(process_tape_file (dptr->units, "TapeTestFile1", "simh")); SIM_TEST(sim_tape_test_process_tape_file (dptr->units, "TapeTestFile1", "simh"));
SIM_TEST(remove_tape_files (dptr->units, "TapeTestFile1")); SIM_TEST(sim_tape_test_remove_tape_files (dptr->units, "TapeTestFile1"));
return SCPE_OK; return SCPE_OK;
} }

View file

@ -224,6 +224,7 @@ t_stat sim_tape_set_capac (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat sim_tape_show_capac (FILE *st, UNIT *uptr, int32 val, CONST void *desc); t_stat sim_tape_show_capac (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat sim_tape_set_dens (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat sim_tape_set_dens (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat sim_tape_show_dens (FILE *st, UNIT *uptr, int32 val, CONST void *desc); t_stat sim_tape_show_dens (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat sim_tape_density_supported (char *string, size_t string_size, int32 valid_bits);
t_stat sim_tape_set_asynch (UNIT *uptr, int latency); t_stat sim_tape_set_asynch (UNIT *uptr, int latency);
t_stat sim_tape_clr_asynch (UNIT *uptr); t_stat sim_tape_clr_asynch (UNIT *uptr);
t_stat sim_tape_test (DEVICE *dptr); t_stat sim_tape_test (DEVICE *dptr);