PDP11,VAX: Fixed data overrun due to lost interrupts whith idle enabled; fixed garbage got after EOF due to unnecesary interrupt.

This commit is contained in:
Jordi Guillaumes i Pons 2014-02-28 18:58:20 +01:00
parent 9f0261be11
commit 8c9a76bf5a

View file

@ -422,6 +422,7 @@ static int32 spinDown = 2000000; /* blower spin-down time
static int EOFcard = 0; /* played special card yet? */ static int EOFcard = 0; /* played special card yet? */
static t_bool eofPending = FALSE; /* Manual EOF switch pressed */ static t_bool eofPending = FALSE; /* Manual EOF switch pressed */
static int32 cpm = DFLT_CPM; /* reader rate: cards per minute */ static int32 cpm = DFLT_CPM; /* reader rate: cards per minute */
static int schedule_svc=0; /* Re-schedule service if true */
/* card image in various formats */ /* card image in various formats */
static int16 hcard[82]; /* Hollerith format */ static int16 hcard[82]; /* Hollerith format */
static char ccard[82]; /* DEC compressed format */ static char ccard[82]; /* DEC compressed format */
@ -443,6 +444,7 @@ DEVICE cr_dev;
static void setupCardFile (UNIT *, int32); static void setupCardFile (UNIT *, int32);
t_stat cr_rd (int32 *, int32, int32); t_stat cr_rd (int32 *, int32, int32);
t_stat cr_wr (int32, int32, int32); t_stat cr_wr (int32, int32, int32);
int32 cr_intac(void);
t_stat cr_svc (UNIT *); t_stat cr_svc (UNIT *);
t_stat cr_reset (DEVICE *); t_stat cr_reset (DEVICE *);
t_stat cr_attach (UNIT *, char *); t_stat cr_attach (UNIT *, char *);
@ -474,7 +476,7 @@ char *cr_description (DEVICE *dptr);
#define IOLN_CR 010 #define IOLN_CR 010
static DIB cr_dib = { IOBA_AUTO, IOLN_CR, &cr_rd, &cr_wr, static DIB cr_dib = { IOBA_AUTO, IOLN_CR, &cr_rd, &cr_wr,
1, IVCL (CR), VEC_AUTO, { NULL } }; 1, IVCL (CR), VEC_AUTO, { cr_intac } };
static UNIT cr_unit = { static UNIT cr_unit = {
UDATA (&cr_svc, UDATA (&cr_svc,
@ -615,7 +617,7 @@ static t_bool fileEOF ( UNIT *uptr,
int col; int col;
if (DEBUG_PRS (cr_dev)) if (DEBUG_PRS (cr_dev))
fprintf (sim_deb, "hopper empty\n"); fprintf (sim_deb, "hopper empty-eof\n");
if (!EOFcard && (uptr->flags & UNIT_AUTOEOF) && !ferror(uptr->fileref)) { if (!EOFcard && (uptr->flags & UNIT_AUTOEOF) && !ferror(uptr->fileref)) {
EOFcard = -1; EOFcard = -1;
@ -635,6 +637,7 @@ static t_bool fileEOF ( UNIT *uptr,
cdst |= CDCSR_HOPPER; cdst |= CDCSR_HOPPER;
return (TRUE); return (TRUE);
} }
/* Not auto EOF, or EOF already handled. This is an attempt to read /* Not auto EOF, or EOF already handled. This is an attempt to read
* with an empty hopper. Report a pick, read or stacker check as well * with an empty hopper. Report a pick, read or stacker check as well
* as hopper empty to indicate that no data was transfered. One might * as hopper empty to indicate that no data was transfered. One might
@ -1021,22 +1024,36 @@ t_stat cr_wr ( int32 data,
data = (crs & ~0377) | (data & 0377); data = (crs & ~0377) | (data & 0377);
if (!(data & CSR_IE)) if (!(data & CSR_IE))
CLR_INT (CR); CLR_INT (CR);
int curr_crs = crs; /* Save current crs to recover status */
crs = (crs & ~CRCSR_RW) | (data & CRCSR_RW); crs = (crs & ~CRCSR_RW) | (data & CRCSR_RW);
/* Clear status bits after CSR load */ /* Clear status bits after CSR load */
crs &= ~(CSR_ERR | CRCSR_ONLINE | CRCSR_CRDDONE | CRCSR_TIMERR); crs &= ~(CSR_ERR | CRCSR_ONLINE | CRCSR_CRDDONE | CRCSR_TIMERR);
if (crs & CRCSR_OFFLINE) if (crs & CRCSR_OFFLINE)
crs |= CSR_ERR; crs |= CSR_ERR;
if (DEBUG_PRS (cr_dev)) /*
fprintf (sim_deb, "cr_wr data %06o crs %06o\n", * Read card requested:
data, crs); * Check if there was any error which required an operator
* intervention, and if so, reassert the corresponding
* error bits and assert interrupt.
* (Expected by the VMS CRDRIVER)
*/
if (data & CSR_GO) { if (data & CSR_GO) {
if (blowerState != BLOW_ON) { if (curr_crs & (CRCSR_SUPPLY | CRCSR_RDCHK | CRCSR_OFFLINE)) {
blowerState = BLOW_START; crs |= CSR_ERR | (curr_crs & (CRCSR_SUPPLY | CRCSR_RDCHK |
sim_activate_after (&cr_unit, spinUp); CRCSR_OFFLINE));
if (crs & CSR_IE) SET_INT(CR);
} else { } else {
sim_activate_after (&cr_unit, cr_unit.wait); if (blowerState != BLOW_ON) {
blowerState = BLOW_START;
sim_activate_after (&cr_unit, spinUp);
} else {
sim_activate_after (&cr_unit, cr_unit.wait);
}
} }
} }
if (DEBUG_PRS (cr_dev))
fprintf (sim_deb, "cr_wr data %06o crs %06o\n",
data, crs);
} else { /* CD11 */ } else { /* CD11 */
if (access == WRITEB) if (access == WRITEB)
data = (PA & 1)? (((data & 0xff)<<8) | (cdst & 0x00ff)): data = (PA & 1)? (((data & 0xff)<<8) | (cdst & 0x00ff)):
@ -1148,6 +1165,24 @@ t_stat cr_wr ( int32 data,
return (SCPE_OK); return (SCPE_OK);
} }
/*
* Interrupt acknowledge routine
* Reschedule service routine if needed (based on
* schedule_svc flag).
* Do the actual scheduling just for the CR11 (VAX/PDP11). The PDP10 does
* not seem to call this entry point.
*/
int32 cr_intac() {
if CR11_CTL(&cr_unit) {
if (schedule_svc) {
sim_activate_after (&cr_unit, cr_unit.wait);
schedule_svc = 0;
}
}
return cr_dib.vec; /* Constant interrupt vector */
}
/* /*
Enter the service routine once for each column read from the card. Enter the service routine once for each column read from the card.
CR state bits drive this primarily (see _BUSY and _CRDDONE). However, CR state bits drive this primarily (see _BUSY and _CRDDONE). However,
@ -1222,14 +1257,27 @@ t_stat cr_svc ( UNIT *uptr )
* The card read routine set the appropriate error bits. Shutdown. * The card read routine set the appropriate error bits. Shutdown.
*/ */
if (!readRtn (uptr, hcard, ccard, acard)) { if (!readRtn (uptr, hcard, ccard, acard)) {
blowerState = BLOW_STOP;
if (CD11_CTL(uptr)) { if (CD11_CTL(uptr)) {
readFault: readFault:
blowerState = BLOW_STOP;
cdst |= CDCSR_RDY; cdst |= CDCSR_RDY;
if (cdst & (CDCSR_RDRCHK | CDCSR_HOPPER)) if (cdst & (CDCSR_RDRCHK | CDCSR_HOPPER))
cdst |= CSR_ERR | CDCSR_OFFLINE; cdst |= CSR_ERR | CDCSR_OFFLINE;
if (cdst & CSR_IE) if (cdst & CSR_IE)
SET_INT (CR); SET_INT (CR);
} else {
/*
* CR11 handling: assert SUPPLY and ERROR bits,
* put de device offline and DO NOT TRIGGER AN INTERRUPT
* (if the interrupt is asserted RSX and VMS will get 80
* bytes of garbage, and RSX could crash).
*/
if (crs & (CRCSR_RDCHK | CRCSR_SUPPLY)) {
crs |= CSR_ERR | CRCSR_OFFLINE;
crs &= ~(CRCSR_ONLINE | CRCSR_BUSY | CRCSR_CRDDONE);
CLR_INT(CR);
}
} }
sim_activate_after (uptr, spinDown); sim_activate_after (uptr, spinDown);
return (SCPE_OK); return (SCPE_OK);
@ -1265,9 +1313,11 @@ readFault:
eofPending = FALSE; eofPending = FALSE;
} }
} }
if (EOFcard) if (EOFcard)
EOFcard = 1; EOFcard = 1;
if (CD11_CTL(uptr)) { if (CD11_CTL(uptr)) {
/* Handle read check: punches in col 0 or 81/last (DEC only did 80 cols, but...) */ /* Handle read check: punches in col 0 or 81/last (DEC only did 80 cols, but...) */
if ((uptr->flags & UNIT_RDCHECK) && if ((uptr->flags & UNIT_RDCHECK) &&
@ -1358,7 +1408,15 @@ incremented properly. If this causes problems, I'll fix it.
currCol++; /* advance the column counter */ currCol++; /* advance the column counter */
/* Schedule next service cycle */ /* Schedule next service cycle */
sim_activate_after (uptr, uptr->wait); /* CR11 (VAX/PDP11): just raise the schedule_svc flag; the intack
* routine will do the actual rescheduling.
* CD11/20 (PDP10): Do the rescheduling (the intack seems to do nothing)
*/
if (CD11_CTL(uptr)) {
sim_activate_after(uptr, uptr->wait);
} else {
schedule_svc = 1;
}
return (SCPE_OK); return (SCPE_OK);
} }