B5500: Second release of Burroughs B5500 simulator.

1) Minor cleanup of some instruction execution to better match
     flowcharts.
  2) Changes to allow proper reboot if OS crashed.
  3) Changes to terminal muliplexer to allow for simH expect/send
     to work.
  4) Some corrections to translation table.
  5) Support for new sim_card interface. This includes support for
     stacking of multiple decks on the input stream.
This commit is contained in:
Richard Cornwell 2018-08-05 22:43:59 -04:00
parent 8b1d058a63
commit b4d185f3af
8 changed files with 188 additions and 150 deletions

View file

@ -213,7 +213,7 @@ uint16 l_reg[2]; /* L current syllable pointer */
uint8 ncsf_reg[2]; /* True if normal state */
uint8 salf_reg[2]; /* True if subrogram mode */
uint8 cwmf_reg[2]; /* True if character mode */
uint8 hltf[2]; /* True if processor halted */
uint16 hltf[2]; /* True if processor halted */
uint8 msff_reg[2]; /* Mark stack flag Word mode */
#define TFFF MSFF /* True state in Char mode */
uint8 varf_reg[2]; /* Variant Flag */
@ -926,7 +926,7 @@ void initiate() {
/* Save processor state in case of error or halt */
void storeInterrupt(int forced, int test) {
int f;
t_uint64 temp;
uint16 temp;
if (forced || test)
NCSF = 0;
@ -946,7 +946,7 @@ void storeInterrupt(int forced, int test) {
}
/* Make ILCW */
B = X | ((i)? PRESENT : 0) | FLAG | DFLAG;
next_addr(S); /* Save B */
next_addr(S); /* Save B */
memory_cycle(11);
} else {
if (BROF || test) { /* Push B First */
@ -959,11 +959,11 @@ void storeInterrupt(int forced, int test) {
}
}
AROF = 0;
B = ICW; /* Set ICW into B */
next_addr(S); /* Save B */
B = ICW; /* Set ICW into B */
next_addr(S); /* Save B */
memory_cycle(11);
B = RCW(f); /* Save IRCW */
next_addr(S); /* Save B */
B = RCW(f); /* Save IRCW */
next_addr(S); /* Save B */
memory_cycle(11);
if (CWMF) {
/* Get the correct value of R */
@ -1985,7 +1985,7 @@ sim_instr(void)
int i;
int j;
reason = 0;
reason = SCPE_OK;
hltf[0] = 0;
hltf[1] = 0;
P1_run = 1;
@ -1993,18 +1993,17 @@ sim_instr(void)
while (reason == 0) { /* loop until halted */
if (P1_run == 0)
return SCPE_STOP;
/* System is booting, wait until finished loading */
while (loading) {
sim_interval = -1;
reason = sim_process_event();
if (reason != SCPE_OK) {
if (reason != SCPE_OK)
break; /* process */
}
}
/* Passed time quantum */
if (sim_interval <= 0) { /* event queue? */
reason = sim_process_event();
if (reason != SCPE_OK) {
if (reason != SCPE_OK)
break; /* process */
}
}
if (sim_brk_summ) {
@ -2027,20 +2026,15 @@ sim_instr(void)
}
/* Toggle between two CPU's. */
if (TROF == 0 && NCSF) {
if (Q != 0 || ((cpu_index)? HLTF : IAR) != 0)
storeInterrupt(1,0);
}
if (cpu_index == 0 && P2_run == 1) {
cpu_index = 1;
/* Check if interrupt pending. */
if (TROF == 0 && NCSF && ((Q != 0) || HLTF))
/* Force a SFI */
storeInterrupt(1,0);
} else {
cpu_index = 0;
/* Check if interrupt pending. */
if (TROF == 0 && NCSF && ((Q != 0) ||
(IAR != 0)))
/* Force a SFI */
storeInterrupt(1,0);
}
if (TROF == 0)
next_prog();
@ -2184,17 +2178,12 @@ crf_loop:
Ma = (F - field) & CORE;
memory_cycle(4);
AROF = 0;
if (A & FLAG) {
if ((A & PRESENT) == 0) {
if (NCSF)
Q |= PRES_BIT;
break;
}
GH = 0;
} else {
GH = (A >> 12) & 070;
}
Ma = CF(A);
GH = 0;
if ((A & FLAG) == 0)
GH = (A >> 12) & 070;
else if ((A & PRESENT) == 0 && NCSF)
Q |= PRES_BIT;
break;
case CMOP_RDA: /* Recall Destination Address */
@ -2203,34 +2192,29 @@ crf_loop:
S = (F - field) & CORE;
memory_cycle(3);
BROF = 0;
if (B & FLAG) {
if ((B & PRESENT) == 0) {
if (NCSF)
Q |= PRES_BIT;
break;
}
KV = 0;
} else {
KV = (B >> 12) & 070;
}
S = CF(B);
KV = 0;
if ((B & FLAG) == 0)
KV = (B >> 12) & 070;
else if ((B & PRESENT) == 0 && NCSF)
Q |= PRES_BIT;
break;
case CMOP_RCA: /* Recall Control Address */
AROF = BROF;
A = B; /* Save B temporarly */
A = B; /* Save B temporarly */
atemp = S; /* Save S */
S = (F - field) & CORE;
memory_cycle(3); /* Load word in B */
memory_cycle(3);/* Load word in B */
S = atemp; /* Restore S */
if (B & FLAG) {
if ((B & PRESENT) == 0) {
if (NCSF)
Q |= PRES_BIT;
break;
} else {
C = CF(B);
L = 0;
}
C = CF(B);
L = 0;
} else {
C = CF(B);
L = LF(B) + 1;
@ -2318,9 +2302,10 @@ crf_loop:
A = B;
AROF = BROF;
B = ((t_uint64)(KV & 070) << (FFIELD_V - 3)) | toC(S);
atemp = S;
S = (F - field) & CORE;
memory_cycle(013); /* Store B in S */
S = CF(B);
S = atemp;
B = A;
BROF = AROF;
AROF = 0;
@ -2331,9 +2316,10 @@ crf_loop:
A = B;
AROF = BROF;
B = ((t_uint64)(GH & 070) << (FFIELD_V - 3)) | toC(Ma);
atemp = Ma;
Ma = (F - field) & CORE;
memory_cycle(015); /* Store B in Ma */
Ma = CF(B);
Ma = atemp;
B = A;
BROF = AROF;
AROF = 0;
@ -3652,6 +3638,12 @@ control:
do {
Ma = CF(B);
memory_cycle(5);
if (sim_interval <= 0) { /* event queue? */
reason = sim_process_event();
if (reason != SCPE_OK) {
break; /* process */
}
}
temp = (B & MANT) + (A & MANT);
} while ((temp & EXPO) == 0);
A = FLAG | PRESENT | toC(Ma);
@ -3672,17 +3664,12 @@ control:
R = 0;
F = S; /* Set F and X */
X = toF(S);
if (B & FLAG) {
if ((B & PRESENT) == 0) {
if (NCSF)
Q |= PRES_BIT;
break;
}
KV = 0;
} else {
KV = (uint8)((B >> (FFIELD_V - 3)) & 070);
}
S = CF(B);
KV = 0;
if ((B & FLAG) == 0)
KV = (uint8)((B >> (FFIELD_V - 3)) & 070);
else if ((B & PRESENT) == 0 && NCSF)
Q |= PRES_BIT;
break;
case VARIANT(WMOP_MKS): /* Mark Stack */
@ -3846,6 +3833,8 @@ cpu_reset(DEVICE * dptr)
GH = KV = Q = 0;
hltf[0] = 0;
P1_run = 0;
IAR = 0;
HALT = 0;
idle_addr = 0;
sim_brk_types = sim_brk_dflt = SWMASK('E') | SWMASK('A') | SWMASK('B');
@ -3958,7 +3947,7 @@ cpu_show_hist(FILE * st, UNIT * uptr, int32 val, CONST void *desc)
t_stat r;
t_value sim_eval;
struct InstHistory *h;
static const char flags[] = "ABCNSMV";
CONST static char flags[] = "ABCNSMV";
if (hst_lnt == 0)
return SCPE_NOFNC; /* enabled? */
@ -4008,8 +3997,7 @@ cpu_show_hist(FILE * st, UNIT * uptr, int32 val, CONST void *desc)
fputc(' ', st);
fprint_val(st, h->op, 8, 12, PV_RZRO);
fputc(' ', st);
print_opcode(st, h->op,
((h->flags & F_CWMF) ? char_ops : word_ops));
print_opcode(st, h->op, ((h->flags & F_CWMF) != 0));
fputc(' ', st);
fprint_val(st, h->iar, 8, 16, PV_RZRO);
fputc('\n', st); /* end line */

View file

@ -72,8 +72,7 @@ typedef struct _opcode
}
t_opcode;
extern void print_opcode(FILE * ofile, t_value val, t_opcode *);
extern t_opcode word_ops[], char_ops[];
void print_opcode(FILE * ofile, t_value val, int chr_mode);
t_stat chan_reset(DEVICE *);
t_stat chan_boot(t_uint64);

View file

@ -280,7 +280,7 @@ t_stat dsk_srv(UNIT * uptr)
chan_set_end(chan);
} else
uptr->u5 &= ~(DK_RDCK|DK_RD|DK_WR);
sim_activate(eptr, 500);
sim_activate(eptr, 8000);
return SCPE_OK;
}
sim_activate(uptr, 100);
@ -432,7 +432,7 @@ t_stat esu_srv(UNIT * uptr)
uptr->u5 -= DK_SECT;
}
}
sim_activate(uptr, (uptr->flags & MODIB) ? 200 :100);
sim_activate(uptr, (uptr->flags & MODIB) ? 500 :300);
return SCPE_OK;
}
@ -456,8 +456,14 @@ dsk_boot(int32 unit_num, DEVICE * dptr)
t_uint64 desc;
int i;
for(i = 0; i < 20; i++)
for(i = 0; i < 20; i++) {
esu_unit[i].u5 = 0;
sim_cancel(&esu_unit[i]);
}
dsk_unit[0].u5 = 0;
dsk_unit[1].u5 = 0;
sim_cancel(&dsk_unit[0]);
sim_cancel(&dsk_unit[1]);
desc = (((t_uint64)dev)<<DEV_V)|DEV_IORD|DEV_OPT|020LL;
return chan_boot(desc);

View file

@ -76,6 +76,7 @@
#define BufAbnormal 010 /* Abnornmal flag */
#define BufGM 020 /* Buffer term with GM */
#define BufIRQ 040 /* Buffer ready */
#define BufDisco 0100 /* Buffer disconnecting */
/* Not connected line:
BufNotReady.
@ -350,7 +351,7 @@ t_stat dtc_srv(UNIT * uptr)
}
/* Process for each unit */
if (uptr->u5 & DTC_WR) {
if (line > dtc_desc.lines || line == -1) {
if (line > dtc_desc.lines || line == -1 || dtc_lstatus[line] & BufDisco) {
sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm write invalid %d\n",
line);
chan_set_notrdy(chan);
@ -434,7 +435,7 @@ t_stat dtc_srv(UNIT * uptr)
}
if (uptr->u5 & DTC_RD) {
if (line > dtc_desc.lines || line == -1) {
if (line > dtc_desc.lines || line == -1 || dtc_lstatus[line] & BufDisco) {
sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm read nothing %d\n",
line);
chan_set_notrdy(chan);
@ -489,7 +490,7 @@ t_stat dtc_srv(UNIT * uptr)
if (dtc_lstatus[line] & BufAbnormal)
chan_set_wcflg(chan);
if (dtc_ldsc[line].conn == 0) /* connected? */
dtc_lstatus[line] = BufIRQ|BufNotReady;
dtc_lstatus[line] = BufIRQ|BufAbnormal|BufIRQ|BufIdle;
else
dtc_lstatus[line] = BufIRQ|BufIdle;
dtc_bsize[line] = 0;
@ -524,6 +525,7 @@ dtco_srv(UNIT * uptr)
sim_clock_coschedule(uptr, tmxr_poll);
ln = tmxr_poll_conn(&dtc_desc); /* look for connect */
if (ln >= 0) { /* got one? */
dtc_ldsc[ln].rcve = 1;
dtc_blimit[ln] = dtc_bufsize-1;
dtc_lstatus[ln] = BufIRQ|BufAbnormal|BufWriteRdy;
IAR |= IRQ_12;
@ -532,32 +534,43 @@ dtco_srv(UNIT * uptr)
/* For each line that is in idle state enable recieve */
for (ln = 0; ln < dtc_desc.lines; ln++) {
dtc_ldsc[ln].rcve = 0;
if (dtc_ldsc[ln].conn &&
(dtc_lstatus[ln] & BufSMASK) == BufIdle) {
(dtc_lstatus[ln] & BufSMASK) < BufWrite) {
dtc_ldsc[ln].rcve = 1;
}
}
tmxr_poll_rx(&dtc_desc); /* poll for input */
for (ln = 0; ln < DTC_MLINES; ln++) { /* loop thru mux */
/* Check for disconnect */
if (dtc_ldsc[ln].conn == 0) { /* connected? */
if (dtc_ldsc[ln].conn == 0 && (dtc_lstatus[ln] & BufDisco) == 0) { /* connected? */
dtc_ldsc[ln].rcve = 0;
switch(dtc_lstatus[ln] & BufSMASK) {
case BufIdle: /* Idle, throw in EOT */
/* Fall through */
case BufIdle: /* Idle Flag as disconnected */
dtc_lstatus[ln] = BufIRQ|BufAbnormal|BufIdle|BufDisco;
dtc_bsize[ln] = 0;
IAR |= IRQ_12;
sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm disconnect %d idle\n", ln);
break;
case BufWriteRdy: /* Awaiting output, terminate */
dtc_bufptr[ln] = 0;
/* Fall through */
case BufInputBusy: /* reading, terminate with EOT */
dtc_buf[ln][dtc_bufptr[ln]++] = 017;
dtc_bsize[ln] = dtc_bufptr[ln];
dtc_bsize[ln] = dtc_bufptr[ln]+1;
dtc_lstatus[ln] = BufIRQ|BufAbnormal|BufReadRdy;
IAR |= IRQ_12;
sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm disconnect %d write\n", ln);
break;
case BufOutBusy: /* Terminate Output */
dtc_lstatus[ln] = BufIRQ|BufIdle;
dtc_lstatus[ln] = BufIRQ|BufIdle|BufAbnormal;
dtc_bsize[ln] = 0;
IAR |= IRQ_12;
sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm disconnect %d out\n", ln);
break;
default: /* Other cases, ignore until
in better state */
break;
@ -568,23 +581,29 @@ dtco_srv(UNIT * uptr)
switch(dtc_lstatus[ln] & BufSMASK) {
case BufIdle:
/* If we have any data to receive */
if (tmxr_rqln(&dtc_ldsc[ln]) > 0)
dtc_lstatus[ln] = BufInputBusy;
else
if (tmxr_rqln(&dtc_ldsc[ln]) > 0) {
dtc_lstatus[ln] &= ~(BufSMASK);
dtc_lstatus[ln] |= BufInputBusy;
} else
break; /* Nothing to do */
sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm recieve %d idle\n",
ln);
dtc_bufptr[ln] = 0;
dtc_bsize[ln] = 0;
case BufInputBusy:
t = 1;
while (t && tmxr_rqln(&dtc_ldsc[ln]) != 0) {
c = tmxr_getc_ln(&dtc_ldsc[ln]) & 0x7f; /* get char */
/* Fall through */
case BufInputBusy:
t = 1;
while (t) {
c = tmxr_getc_ln(&dtc_ldsc[ln]); /* get char */
if (c == 0)
break;
c &= 0x7f;
c1 = ascii_to_con[c];
switch(c) {
case '\005': /* ^E ENQ who-are-you */
dtc_lstatus[ln] &= ~(BufSMASK);
dtc_lstatus[ln] |= BufIRQ|BufAbnormal|BufWriteRdy;
dtc_lstatus[ln] |= BufIRQ|BufWriteRdy|BufAbnormal;
IAR |= IRQ_12;
sim_debug(DEBUG_DETAIL, &dtc_dev,
"Datacomm recieve ENQ %d\n", ln);
@ -786,15 +805,14 @@ t_stat dtc_setnl (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
newln = (int32) get_uint (cptr, 10, DTC_MLINES, &r);
if ((r != SCPE_OK) || (newln == dtc_desc.lines))
return r;
if ((newln == 0) || (newln >= DTC_MLINES))
if ((newln == 0) || (newln > DTC_MLINES))
return SCPE_ARG;
newln--;
if (newln < dtc_desc.lines) {
for (i = newln, t = 0; i < dtc_desc.lines; i++)
for (i = newln-1, t = 0; i < dtc_desc.lines; i++)
t = t | dtc_ldsc[i].conn;
if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE))
return SCPE_OK;
for (i = newln; i < dtc_desc.lines; i++) {
for (i = newln-1; i < dtc_desc.lines; i++) {
if (dtc_ldsc[i].conn) {
tmxr_linemsg (&dtc_ldsc[i], "\r\nOperator disconnected line\r\n");
tmxr_send_buffered_data (&dtc_ldsc[i]);

View file

@ -570,7 +570,7 @@ mt_attach(UNIT * uptr, CONST char *file)
{
t_stat r;
if ((r = sim_tape_attach(uptr, file)) != SCPE_OK)
if ((r = sim_tape_attach_ex(uptr, file, 0, 0)) != SCPE_OK)
return r;
uptr->u5 |= MT_LOADED|MT_BOT;
sim_activate(uptr, 50000);

View file

@ -136,7 +136,7 @@ const char ascii_to_con[128] = {
/* Control */
-1, -1, -1, -1, -1, -1, -1, -1,
/*sp ! " # $ % & ' */
020, 032, 037, 013, 053, 017, 060, 014, /* 40 - 77 */
020, 032, 037, 013, 053, 034, 060, 014, /* 40 - 77 */
/* ( ) * + , - . / */
075, 055, 054, 072, 033, 040, 073, 021,
/* 0 1 2 3 4 5 6 7 */
@ -150,7 +150,7 @@ const char ascii_to_con[128] = {
/* P Q R S T U V W */
047, 050, 051, 022, 023, 024, 025, 026,
/* X Y Z [ \ ] ^ _ */
027, 030, 031, 075, 036, 055, 057, 000,
027, 030, 031, 074, 036, 036, 057, 000,
/* ` a b c d e f g */
035, 061, 062, 063, 064, 065, 066, 067, /* 140 - 177 */
/* h i j k l m n o */
@ -158,7 +158,7 @@ const char ascii_to_con[128] = {
/* p q r s t u v w */
047, 050, 051, 022, 023, 024, 025, 026,
/* x y z { | } ~ del*/
027, 030, 031, 057, 077, 017, -1, -1
027, 030, 031, 057, 052, 017, -1, -1
};
@ -341,9 +341,10 @@ t_opcode char_ops[] = {
/* Print out an instruction */
void
print_opcode(FILE * of, t_value val, t_opcode * tab)
print_opcode(FILE * of, t_value val, int chr_mode)
{
uint16 op;
t_opcode *tab = (chr_mode) ? char_ops: word_ops;
op = val;
while (tab->name != NULL) {
@ -410,14 +411,14 @@ fprint_sym(FILE * of, t_addr addr, t_value * val, UNIT * uptr, int32 sw)
fputs(" ", of);
for (i = 36; i >= 0; i-=12) {
int op = (int)(inst >> i) & 07777;
print_opcode(of, op, word_ops);
print_opcode(of, op, 0);
}
}
if (sw & SWMASK('C')) { /* Char mode opcodes */
fputs(" ", of);
for (i = 36; i >= 0; i-=12) {
int op = (int)(inst >> i) & 07777;
print_opcode(of, op, char_ops);
print_opcode(of, op, 1);
}
}
if (sw & SWMASK('B')) { /* BCD mode */

View file

@ -35,10 +35,6 @@
#define UNIT_CDP UNIT_ATTABLE | UNIT_DISABLE | MODE_029
#define UNIT_LPR UNIT_ATTABLE | UNIT_DISABLE
/* For Card reader, when set returns end of file at end of deck. */
/* Reset after sent to system */
#define MODE_EOF (0x40 << UNIT_V_CARD_MODE)
#define TMR_RTC 0
@ -84,6 +80,7 @@ DEBTAB cdr_debug[] = {
#if NUM_DEVS_CDR > 0
t_stat cdr_boot(int32, DEVICE *);
t_stat cdr_ini(DEVICE *);
t_stat cdr_srv(UNIT *);
t_stat cdr_attach(UNIT *, CONST char *);
t_stat cdr_detach(UNIT *);
@ -92,6 +89,7 @@ const char *cdr_description(DEVICE *dptr);
#endif
#if NUM_DEVS_CDP > 0
t_stat cdp_ini(DEVICE *);
t_stat cdp_srv(UNIT *);
t_stat cdp_attach(UNIT *, CONST char *);
t_stat cdp_detach(UNIT *);
@ -106,6 +104,7 @@ struct _lpr_data
}
lpr_data[NUM_DEVS_LPR];
t_stat lpr_ini(DEVICE *);
t_stat lpr_srv(UNIT *);
t_stat lpr_attach(UNIT *, CONST char *);
t_stat lpr_detach(UNIT *);
@ -146,16 +145,14 @@ MTAB cdr_mod[] = {
{MTAB_XTD | MTAB_VUN, 0, "FORMAT", "FORMAT",
&sim_card_set_fmt, &sim_card_show_fmt, NULL,
"Sets card format"},
{MODE_EOF, MODE_EOF, "EOF", "EOF", NULL, NULL, NULL,
"Causes EOF to be set when reader empty"},
{0}
};
DEVICE cdr_dev = {
"CR", cdr_unit, NULL, cdr_mod,
NUM_DEVS_CDR, 8, 15, 1, 8, 8,
NULL, NULL, NULL, &cdr_boot, &cdr_attach, &cdr_detach,
NULL, DEV_DISABLE | DEV_DEBUG, 0, cdr_debug,
NULL, NULL, &cdr_ini, &cdr_boot, &cdr_attach, &cdr_detach,
NULL, DEV_DISABLE | DEV_DEBUG | DEV_CARD, 0, cdr_debug,
NULL, NULL, &cdr_help, NULL, NULL,
&cdr_description
};
@ -176,8 +173,8 @@ MTAB cdp_mod[] = {
DEVICE cdp_dev = {
"CP", cdp_unit, NULL, cdp_mod,
NUM_DEVS_CDP, 8, 15, 1, 8, 8,
NULL, NULL, NULL, NULL, &cdp_attach, &cdp_detach,
NULL, DEV_DISABLE | DEV_DEBUG, 0, cdr_debug,
NULL, NULL, &cdp_ini, NULL, &cdp_attach, &cdp_detach,
NULL, DEV_DISABLE | DEV_DEBUG | DEV_CARD, 0, cdr_debug,
NULL, NULL, &cdp_help, NULL, NULL,
&cdp_description
};
@ -202,7 +199,7 @@ MTAB lpr_mod[] = {
DEVICE lpr_dev = {
"LP", lpr_unit, NULL, lpr_mod,
NUM_DEVS_LPR, 8, 15, 1, 8, 8,
NULL, NULL, NULL, NULL, &lpr_attach, &lpr_detach,
NULL, NULL, &lpr_ini, NULL, &lpr_attach, &lpr_detach,
NULL, DEV_DISABLE | DEV_DEBUG, 0, dev_debug,
NULL, NULL, &lpr_help, NULL, NULL,
&lpr_description
@ -217,7 +214,7 @@ UNIT con_unit[] = {
DEVICE con_dev = {
"CON", con_unit, NULL, NULL,
NUM_DEVS_CON, 8, 15, 1, 8, 8,
NULL, NULL, con_ini, NULL, NULL, NULL,
NULL, NULL, &con_ini, NULL, NULL, NULL,
NULL, DEV_DISABLE | DEV_DEBUG, 0, dev_debug,
NULL, NULL, &con_help, NULL, NULL,
&con_description
@ -227,6 +224,17 @@ DEVICE con_dev = {
#if ((NUM_DEVS_CDR > 0) | (NUM_DEVS_CDP > 0))
t_stat
cdr_ini(DEVICE *dptr) {
int i;
for(i = 0; i < NUM_DEVS_CDR; i++) {
cdr_unit[i].u5 = 0;
sim_cancel(&cdr_unit[i]);
}
return SCPE_OK;
}
/*
* Device entry points for card reader.
* And Card punch.
@ -255,15 +263,13 @@ t_stat card_cmd(uint16 cmd, uint16 dev, uint8 chan, uint16 *wc)
/* Check if we ran out of cards */
if (uptr->u5 & URCSTA_EOF) {
/* If end of file, return to system */
if (uptr->flags & MODE_EOF) {
sim_debug(DEBUG_DETAIL, &cdr_dev, "cdr %d %d report eof\n", u,
chan);
chan_set_eof(chan);
uptr->flags &= ~MODE_EOF;
if (sim_card_input_hopper_count(uptr) != 0)
uptr->u5 &= ~URCSTA_EOF;
else {
/* Clear unit ready */
iostatus &= ~(CARD1_FLAG << u);
return SCPE_UNATT;
}
/* Clear unit ready */
iostatus &= ~(CARD1_FLAG << u);
return SCPE_UNATT;
}
if (cmd & URCSTA_BINARY) {
@ -307,6 +313,7 @@ t_stat
cdr_srv(UNIT *uptr) {
int chan = URCSTA_CHMASK & uptr->u5;
int u = (uptr - cdr_unit);
uint16 *image = (uint16 *)(uptr->up7);
if (uptr->u5 & URCSTA_EOF) {
sim_debug(DEBUG_DETAIL, &cdr_dev, "cdr %d %d unready\n", u, chan);
@ -319,32 +326,27 @@ cdr_srv(UNIT *uptr) {
/* Check if new card requested. */
if (uptr->u4 == 0 && uptr->u5 & URCSTA_ACTIVE &&
(uptr->u5 & URCSTA_CARD) == 0) {
switch(sim_read_card(uptr)) {
case SCPE_UNATT:
switch(sim_read_card(uptr, image)) {
case CDSE_EMPTY:
iostatus &= ~(CARD1_FLAG << u);
uptr->u5 &= ~(URCSTA_ACTIVE);
iostatus &= ~(CARD1_FLAG << u);
chan_set_notrdy(chan);
break;
case SCPE_EOF:
case CDSE_EOF:
/* If end of file, return to system */
if (uptr->flags & MODE_EOF) {
sim_debug(DEBUG_DETAIL, &cdr_dev, "cdr %d %d set eof\n", u, chan);
chan_set_eof(chan);
uptr->flags &= ~MODE_EOF;
}
uptr->u5 &= ~(URCSTA_ACTIVE);
uptr->u5 |= URCSTA_EOF;
chan_set_notrdy(chan);
sim_activate(uptr, 500);
break;
case SCPE_IOERR:
case CDSE_ERROR:
chan_set_error(chan);
uptr->u5 &= ~(URCSTA_ACTIVE);
uptr->u5 |= URCSTA_EOF;
chan_set_end(chan);
break;
case SCPE_OK:
case CDSE_OK:
uptr->u5 |= URCSTA_CARD;
sim_activate(uptr, 500);
break;
@ -356,22 +358,18 @@ cdr_srv(UNIT *uptr) {
/* Copy next column over */
if (uptr->u5 & URCSTA_CARD &&
uptr->u4 < ((uptr->u5 & URCSTA_BIN) ? 160 : 80)) {
struct _card_data *data;
uint8 ch = 0;
int u = (uptr - cdr_unit);
data = (struct _card_data *)uptr->up7;
if (uptr->u5 & URCSTA_BIN) {
ch = (data->image[uptr->u4 >> 1] >>
((uptr->u4 & 1)? 0 : 6)) & 077;
ch = (image[uptr->u4 >> 1] >> ((uptr->u4 & 1)? 0 : 6)) & 077;
} else {
ch = sim_hol_to_bcd(data->image[uptr->u4]);
ch = sim_hol_to_bcd(image[uptr->u4]);
/* Remap some characters from 029 to BCL */
switch(ch) {
case 0: ch = 020; break; /* Translate blanks */
case 10: /* Check if 0 punch of 82 punch */
if (data->image[uptr->u4] != 0x200) {
if (image[uptr->u4] != 0x200) {
ch = 0;
if (uptr->u4 == 0)
chan_set_parity(chan);
@ -439,6 +437,8 @@ cdr_attach(UNIT * uptr, CONST char *file)
if ((r = sim_card_attach(uptr, file)) != SCPE_OK)
return r;
if (uptr->up7 == 0)
uptr->up7 = malloc(sizeof(uint16)*80);
uptr->u5 &= URCSTA_BUSY;
uptr->u4 = 0;
uptr->u6 = 0;
@ -451,6 +451,9 @@ cdr_detach(UNIT * uptr)
{
int u = uptr-cdr_unit;
if (uptr->up7 != 0)
free(uptr->up7);
uptr->up7 = 0;
iostatus &= ~(CARD1_FLAG << u);
return sim_card_detach(uptr);
}
@ -462,10 +465,6 @@ cdr_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
fprintf (st, "The system supports up to two card readers, the second one is disabled\n");
fprintf (st, "by default. To have the card reader return the EOF flag when the deck\n");
fprintf (st, "has finished reading do:\n");
fprintf (st, " sim> SET CRn EOF\n");
fprintf (st, "This flag is cleared each time a deck has been read, so it must be set\n");
fprintf (st, "again after each deck. MCP does not require this to be set as long as\n");
fprintf (st, "the deck includes a ?END card\n");
fprint_set_help(st, dptr);
fprint_show_help(st, dptr);
return SCPE_OK;
@ -484,27 +483,39 @@ cdr_description(DEVICE *dptr)
#if NUM_DEVS_CDR > 0 | NUM_DEVS_CDP > 0
/* Handle transfer of data for card punch */
t_stat
cdp_ini(DEVICE *dptr) {
int i;
for(i = 0; i < NUM_DEVS_CDP; i++) {
cdp_unit[i].u5 = 0;
sim_cancel(&cdp_unit[i]);
}
return SCPE_OK;
}
t_stat
cdp_srv(UNIT *uptr) {
int chan = URCSTA_CHMASK & uptr->u5;
int u = (uptr - cdp_unit);
uint16 *image = (uint16 *)(uptr->up7);
if (uptr->u5 & URCSTA_BUSY) {
/* Done waiting, punch card */
if (uptr->u5 & URCSTA_FULL) {
sim_debug(DEBUG_DETAIL, &cdp_dev, "cdp %d %d punch\n", u, chan);
switch(sim_punch_card(uptr, NULL)) {
case SCPE_EOF:
case SCPE_UNATT:
switch(sim_punch_card(uptr, image)) {
case CDSE_EOF:
case CDSE_EMPTY:
sim_debug(DEBUG_DETAIL, &cdp_dev, "cdp %d %d set eof\n", u,
chan);
chan_set_eof(chan);
break;
/* If we get here, something is wrong */
case SCPE_IOERR:
case CDSE_ERROR:
chan_set_error(chan);
break;
case SCPE_OK:
case CDSE_OK:
break;
}
uptr->u5 &= ~URCSTA_FULL;
@ -515,18 +526,15 @@ cdp_srv(UNIT *uptr) {
/* Copy next column over */
if (uptr->u5 & URCSTA_ACTIVE && uptr->u4 < 80) {
struct _card_data *data;
uint8 ch = 0;
data = (struct _card_data *)uptr->up7;
if(chan_read_char(chan, &ch, 0)) {
uptr->u5 |= URCSTA_BUSY|URCSTA_FULL;
uptr->u5 &= ~URCSTA_ACTIVE;
} else {
sim_debug(DEBUG_DATA, &cdp_dev, "cdp %d: Char %d < %02o\n", u,
uptr->u4, ch);
data->image[uptr->u4++] = sim_bcd_to_hol(ch & 077);
image[uptr->u4++] = sim_bcd_to_hol(ch & 077);
}
sim_activate(uptr, 10);
}
@ -547,16 +555,24 @@ cdp_attach(UNIT * uptr, CONST char *file)
if ((r = sim_card_attach(uptr, file)) != SCPE_OK)
return r;
uptr->u5 = 0;
iostatus |= PUNCH_FLAG;
if (uptr->up7 == 0) {
uptr->up7 = calloc(80, sizeof(uint16));
uptr->u5 = 0;
iostatus |= PUNCH_FLAG;
}
return SCPE_OK;
}
t_stat
cdp_detach(UNIT * uptr)
{
uint16 *image = (uint16 *)(uptr->up7);
if (uptr->u5 & URCSTA_FULL)
sim_punch_card(uptr, NULL);
sim_punch_card(uptr, image);
if (uptr->up7 != 0)
free(uptr->up7);
uptr->up7 = 0;
iostatus &= ~PUNCH_FLAG;
return sim_card_detach(uptr);
}
@ -583,6 +599,16 @@ cdp_description(DEVICE *dptr)
/* Line printer routines
*/
t_stat
lpr_ini(DEVICE *dptr) {
int i;
for(i = 0; i < NUM_DEVS_LPR; i++) {
lpr_unit[i].u5 = 0;
sim_cancel(&lpr_unit[i]);
}
return SCPE_OK;
}
#if NUM_DEVS_LPR > 0
t_stat

Binary file not shown.