HP2100: Add CRCC and LRCC support to the HP 2100 MS simulation. from Dave Bryan

OBSERVATION:  The HP 2100 MS device simulates the HP 7970 B/E magnetic tape
     drives.  The 7970B uses NRZI format, and its associated controller supports
     returning the cyclic redundancy check character and longitudinal redundancy
     check character (CRCC and LRCC) to the CPU.  Typically, these are used only
     by the controller diagnostic, but support is easy to add.

     RESOLUTION:  Modify "hp2100_ms.c" to add a function that calculates CRCC
     and LRCC for reads and writes, and call that function when the CPU requests
     that the controller deliver the values.
This commit is contained in:
Mark Pizzolato 2014-12-22 05:50:32 -08:00
parent afb5d6277d
commit ef0eae135f

View file

@ -1,6 +1,6 @@
/* hp2100_ms.c: HP 2100 13181A/13183A magnetic tape simulator /* hp2100_ms.c: HP 2100 13181A/13183A magnetic tape simulator
Copyright (c) 1993-2013, Robert M. Supnik Copyright (c) 1993-2014, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -26,6 +26,7 @@
MS 13181A 7970B 800bpi nine track magnetic tape MS 13181A 7970B 800bpi nine track magnetic tape
13183A 7970E 1600bpi nine track magnetic tape 13183A 7970E 1600bpi nine track magnetic tape
11-Dec-14 JDB Updated for new erase gap API, added CRCC/LRCC support
10-Jan-13 MP Added DEV_TAPE to DEVICE flags 10-Jan-13 MP Added DEV_TAPE to DEVICE flags
09-May-12 JDB Separated assignments from conditional expressions 09-May-12 JDB Separated assignments from conditional expressions
10-Feb-12 JDB Deprecated DEVNO in favor of SC 10-Feb-12 JDB Deprecated DEVNO in favor of SC
@ -92,8 +93,8 @@
#define UST u4 /* unit status */ #define UST u4 /* unit status */
#define REEL u5 /* tape reel size */ #define REEL u5 /* tape reel size */
#define BPI_13181 800 /* 800 bpi for 13181 cntlr */ #define BPI_13181 MT_DENS_800 /* 800 bpi for 13181 cntlr */
#define BPI_13183 1600 /* 1600 bpi for 13183 cntlr */ #define BPI_13183 MT_DENS_1600 /* 1600 bpi for 13183 cntlr */
#define GAP_13181 48 /* gap is 4.8 inches for 13181 cntlr */ #define GAP_13181 48 /* gap is 4.8 inches for 13181 cntlr */
#define GAP_13183 30 /* gap is 3.0 inches for 13183 cntlr */ #define GAP_13183 30 /* gap is 3.0 inches for 13183 cntlr */
#define TCAP (300 * 12 * 800) /* 300 ft capacity at 800 bpi */ #define TCAP (300 * 12 * 800) /* 300 ft capacity at 800 bpi */
@ -186,6 +187,8 @@ struct {
int32 msd_buf = 0; /* data buffer */ int32 msd_buf = 0; /* data buffer */
uint8 msxb[DBSIZE] = { 0 }; /* data buffer */ uint8 msxb[DBSIZE] = { 0 }; /* data buffer */
t_mtrlnt ms_ptr = 0, ms_max = 0; /* buffer ptrs */ t_mtrlnt ms_ptr = 0, ms_max = 0; /* buffer ptrs */
t_bool ms_crc = FALSE; /* buffer ready for CRC calc */
/* Hardware timing at 45 IPS 13181 13183 /* Hardware timing at 45 IPS 13181 13183
(based on 1580 instr/msec) instr msec SCP instr msec SCP (based on 1580 instr/msec) instr msec SCP instr msec SCP
@ -244,6 +247,7 @@ t_stat ms_show_reelsize (FILE *st, UNIT *uptr, int32 val, void *desc);
void ms_config_timing (void); void ms_config_timing (void);
char *ms_cmd_name (uint32 cmd); char *ms_cmd_name (uint32 cmd);
t_stat ms_clear (void); t_stat ms_clear (void);
static uint32 calc_crc_lrc (uint8 *buffer, t_mtrlnt length);
/* MSD data structures /* MSD data structures
@ -385,6 +389,7 @@ DEVICE msc_dev = {
uint32 msdio (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data) uint32 msdio (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
{ {
uint32 check;
IOSIGNAL signal; IOSIGNAL signal;
IOCYCLE working_set = IOADDSIR (signal_set); /* add ioSIR if needed */ IOCYCLE working_set = IOADDSIR (signal_set); /* add ioSIR if needed */
@ -410,6 +415,12 @@ while (working_set) {
break; break;
case ioIOI: /* I/O data input */ case ioIOI: /* I/O data input */
if (ms_crc) { /* ready for CRC? */
check = calc_crc_lrc (msxb, ms_max); /* calculate CRCC and LRCC */
msd_buf = check >> 8 & 0177400 /* position CRCC in upper byte */
| check & 0377; /* and LRCC in lower byte */
}
stat_data = IORETURN (SCPE_OK, msd_buf); /* merge in return status */ stat_data = IORETURN (SCPE_OK, msd_buf); /* merge in return status */
break; break;
@ -429,6 +440,7 @@ while (working_set) {
break; break;
case ioSTC: /* set control flip-flop */ case ioSTC: /* set control flip-flop */
ms_crc = FALSE; /* reset CRC ready */
msd.control = SET; msd.control = SET;
break; break;
@ -821,8 +833,12 @@ switch (uptr->FNC) { /* case on function */
msc_sta = msc_sta | STA_ODD; msc_sta = msc_sta | STA_ODD;
else msc_sta = msc_sta & ~STA_ODD; else msc_sta = msc_sta & ~STA_ODD;
sim_activate (uptr, msc_itime); /* sched IRG */ sim_activate (uptr, msc_itime); /* sched IRG */
if (uptr->FNC == FNC_RFF) msc_1st = 1; /* diagnostic? */ if (uptr->FNC == FNC_RFF) /* diagnostic? */
else uptr->FNC |= FNC_CMPL; /* set completion */ msc_1st = 1; /* restart */
else {
uptr->FNC |= FNC_CMPL; /* set completion */
ms_crc = TRUE; /* and CRC ready */
}
return SCPE_OK; return SCPE_OK;
case FNC_RFF | FNC_CMPL: /* diagnostic read completion */ case FNC_RFF | FNC_CMPL: /* diagnostic read completion */
@ -870,6 +886,8 @@ switch (uptr->FNC) { /* case on function */
} }
sim_activate (uptr, msc_itime); /* sched IRG */ sim_activate (uptr, msc_itime); /* sched IRG */
uptr->FNC |= FNC_CMPL; /* set completion */ uptr->FNC |= FNC_CMPL; /* set completion */
ms_max = ms_ptr; /* indicate buffer complete */
ms_crc = TRUE; /* and CRC may be generated */
return SCPE_OK; return SCPE_OK;
case FNC_WC | FNC_CMPL: /* write completion */ case FNC_WC | FNC_CMPL: /* write completion */
@ -900,9 +918,8 @@ t_stat ms_write_gap (UNIT *uptr)
{ {
t_stat st; t_stat st;
uint32 gap_len = ms_ctype ? GAP_13183 : GAP_13181; /* establish gap length */ uint32 gap_len = ms_ctype ? GAP_13183 : GAP_13181; /* establish gap length */
uint32 tape_bpi = ms_ctype ? BPI_13183 : BPI_13181; /* establish nominal bpi */
st = sim_tape_wrgap (uptr, gap_len, tape_bpi); /* write gap */ st = sim_tape_wrgap (uptr, gap_len); /* write gap */
if (st != MTSE_OK) if (st != MTSE_OK)
return ms_map_err (uptr, st); /* map error if failure */ return ms_map_err (uptr, st); /* map error if failure */
@ -1027,6 +1044,11 @@ for (i = 0; i < MS_NUMDR; i++) {
sim_tape_reset (uptr); sim_tape_reset (uptr);
sim_cancel (uptr); sim_cancel (uptr);
uptr->UST = 0; uptr->UST = 0;
if (sim_switches & SWMASK ('P')) /* if this is an initialization reset */
sim_tape_set_dens (uptr, /* then tell the tape library the density in use */
ms_ctype ? BPI_13183 : BPI_13181,
NULL, NULL);
} }
return SCPE_OK; return SCPE_OK;
@ -1104,6 +1126,10 @@ for (i = 0; i < MS_NUMDR; i++) {
} }
ms_ctype = (CNTLR_TYPE) val; ms_ctype = (CNTLR_TYPE) val;
ms_config_timing (); /* update for new type */ ms_config_timing (); /* update for new type */
sim_tape_set_dens (uptr, ms_ctype ? BPI_13183 : BPI_13181, /* tell the tape library the density in use */
NULL, NULL);
return SCPE_OK; return SCPE_OK;
} }
@ -1286,3 +1312,52 @@ SR = (SR & IBL_OPT) | IBL_MS | (dev << IBL_V_DEV); /* set SR */
if ((sim_switches & SWMASK ('S')) && AR) SR = SR | 1; /* skip? */ if ((sim_switches & SWMASK ('S')) && AR) SR = SR | 1; /* skip? */
return SCPE_OK; return SCPE_OK;
} }
/* Calculate tape record CRC and LRC characters */
#define E 0400 /* parity bit for odd parity */
#define O 0000 /* parity bit for odd parity */
static const uint16 odd_parity [256] = { /* parity table */
E, O, O, E, O, E, E, O, O, E, E, O, E, O, O, E, /* 000-017 */
O, E, E, O, E, O, O, E, E, O, O, E, O, E, E, O, /* 020-037 */
O, E, E, O, E, O, O, E, E, O, O, E, O, E, E, O, /* 040-067 */
E, O, O, E, O, E, E, O, O, E, E, O, E, O, O, E, /* 060-077 */
O, E, E, O, E, O, O, E, E, O, O, E, O, E, E, O, /* 100-117 */
E, O, O, E, O, E, E, O, O, E, E, O, E, O, O, E, /* 120-137 */
E, O, O, E, O, E, E, O, O, E, E, O, E, O, O, E, /* 140-157 */
O, E, E, O, E, O, O, E, E, O, O, E, O, E, E, O, /* 160-177 */
O, E, E, O, E, O, O, E, E, O, O, E, O, E, E, O, /* 200-217 */
E, O, O, E, O, E, E, O, O, E, E, O, E, O, O, E, /* 220-237 */
E, O, O, E, O, E, E, O, O, E, E, O, E, O, O, E, /* 240-267 */
O, E, E, O, E, O, O, E, E, O, O, E, O, E, E, O, /* 260-277 */
E, O, O, E, O, E, E, O, O, E, E, O, E, O, O, E, /* 300-317 */
O, E, E, O, E, O, O, E, E, O, O, E, O, E, E, O, /* 320-337 */
O, E, E, O, E, O, O, E, E, O, O, E, O, E, E, O, /* 340-357 */
E, O, O, E, O, E, E, O, O, E, E, O, E, O, O, E /* 360-377 */
};
static uint32 calc_crc_lrc (uint8 *buffer, t_mtrlnt length)
{
uint32 i;
uint16 byte, crc, lrc;
lrc = crc = 0;
for (i = 0; i < length; i++) {
byte = odd_parity [buffer [i]] | buffer [i];
crc = crc ^ byte;
lrc = lrc ^ byte;
if (crc & 1)
crc = crc >> 1 ^ 0474;
else
crc = crc >> 1;
}
crc = crc ^ 0727;
lrc = lrc ^ crc;
return (uint32) crc << 16 | lrc;
}