SDS: Various fixes to asynchronous communication mux

1. In pot_fork, the permanently asserted interrupt, the interrupt bits were assigned in the wrong order -- bit 8 is interrupt 0 and bit 23 is interrupt 017 in each group of 16. Also, the group number was incorrectly calculated -- need to subtract 0200 before dividing by 020.

2. In case 3 of EOM and SKS when in SDS mode, it does not dispatch properly. The device table is set for Genie mode.  Add test for device 077 in SDS mode and switch to device 1, which is Mux in Genie mode.

3. Add test to PIN to verify that scanner is locked before returning PIN data.

4. Mux should not queue a new interrupt for a flag type if it is already queued and pending for a different channel. If do so, when the CPU clears the interrupt, the second interrupt is lost.

5. If POT specifies interrupt but no Tx character present, queue a Tx interrupt immediately if the transmitter is not active. This technique is used by the 940 monitor to start output of the transmit character buffer.

6. Per the 940 reference manual, after servicing the highest priority interrupt on a particular channel, the scanner should look at all other channels before looking for additional interrupt types on the first channel. Change scanner to always resume scan with the Rx interrupt on the next channel from where the scanner paused.

Also removed superfluous trailing blanks from lines in file.
This commit is contained in:
Mark Emmer 2014-03-02 22:26:44 -06:00
parent 5b479c7ab2
commit a07addf5fa
2 changed files with 37 additions and 5 deletions

View file

@ -439,6 +439,8 @@ switch (mod) {
case 3: /* special */
dev = I_GETDEV3 (inst); /* special device */
if (dev == DEV3_SMUX && !(cpu_unit.flags & UNIT_GENIE))
dev = DEV3_GMUX;
if (dev3_dsp[dev]) /* defined? */
return dev3_dsp[dev] (IO_CONN, inst, NULL);
CRETINS;
@ -500,6 +502,8 @@ switch (mod) {
case 3: /* special */
dev = I_GETDEV3 (inst); /* special device */
if (dev == DEV3_SMUX && !(cpu_unit.flags & UNIT_GENIE))
dev = DEV3_GMUX;
if (dev3_dsp[dev])
dev3_dsp[dev] (IO_SKS, inst, dat);
else CRETINS;
@ -547,9 +551,9 @@ return SCPE_OK;
t_stat pot_fork (uint32 num, uint32 *dat)
{
uint32 igrp = SYI_GETGRP (*dat); /* get group */
uint32 fbit = (1 << (VEC_FORK & 017)); /* bit in group */
uint32 fbit = (0100000 >> (VEC_FORK & 017)); /* bit in group */
if (igrp == (VEC_FORK / 020)) { /* right group? */
if (igrp == ((VEC_FORK-0200) / 020)) { /* right group? */
if ((*dat & SYI_ARM) && (*dat & fbit)) /* arm, bit set? */
int_req = int_req | INT_FORK;
if ((*dat & SYI_DIS) && !(*dat & fbit)) /* disarm, bit clr? */

View file

@ -54,6 +54,7 @@
#define MUX_SETFLG(l,x) mux_flags[((l) * MUX_FLAGS) + (x)] = 1
#define MUX_SETINT(x) int_req = int_req | (INT_MUXR >> (x))
#define MUX_CLRINT(x) int_req = int_req & ~(INT_MUXR >> (x))
#define MUX_CHKINT(x) (int_req & (INT_MUXR >> (x)))
/* PIN/POT */
@ -274,7 +275,7 @@ switch (fnc) {
((inst & SKS_DSR) && !(mux_sta[ln] & MUX_SDSR)))
*dat = 0; /* no skip if fail */
}
else CRETINS;
else CRETINS;
default:
return SCPE_IERR;
@ -290,6 +291,8 @@ t_stat pin_mux (uint32 num, uint32 *dat)
uint32 ln = mux_scan >> 2;
uint32 flag = mux_scan & MUX_FLAGMASK;
if (!mux_slck) /* scanner must be locked */
return SCPE_IERR;
mux_scan = mux_scan & MUX_SCANMASK; /* mask scan */
mux_flags[mux_scan] = 0; /* clear flag */
if (flag == MUX_FRCV) { /* rcv event? */
@ -333,6 +336,12 @@ else { /* enabled */
else mux_sta[ln] = mux_sta[ln] & ~MUX_SXIE;
mux_sta[ln] = mux_sta[ln] | MUX_SLNE; /* line is enabled */
mux_ldsc[ln].rcve = 1;
if ((*dat & POT_NOX) && /* if no transmit char && */
(mux_sta[ln] & MUX_SXIE) && /* line enabled && */
!sim_is_active (&muxl_unit[ln])) { /* tx buffer empty */
MUX_SETFLG (ln, MUX_FXMT); /* then set flag to request */
mux_scan_next (); /* a tx interrupt */
}
}
return SCPE_OK;
}
@ -407,7 +416,23 @@ if (mux_sta[ln] & MUX_SXIE) {
return SCPE_OK;
}
/* Kick scanner */
/* Kick scanner
*
* Per 940 Ref Man:
* If more than one raised flag is encountered by the scanner, only
* the one of highest priority will result in an interrupt. The others
* will be ignored until the scanner has completed scanning all other
* channels. The receive flag will be given highest priority, followed
* by the transmit flag, the carrier-on flag, and the carrier-off flag.
*
* To implement, advance mux_scan to last flag of current channel (by
* merging MUX_FLAGMASK) so scan loop commences with receive flag of next
* channel.
*
* When two or more channels are active, do not queue an interrupt
* request if the same interrupt is already requesting. To do so will
* cause an interrupt to be lost.
*/
void mux_scan_next (void)
{
@ -415,9 +440,12 @@ int32 i;
if (mux_slck) /* locked? */
return;
mux_scan |= MUX_FLAGMASK; /* last flag of current ch. */
/* will be Rx flag of next ch. */
for (i = 0; i < MUX_SCANMAX; i++) { /* scan flags */
mux_scan = (mux_scan + 1) & MUX_SCANMASK; /* next flag */
if (mux_flags[mux_scan]) { /* flag set? */
if (mux_flags[mux_scan] && /* flag set */
!MUX_CHKINT (mux_scan & MUX_FLAGMASK)) { /* and not requesting int? */
mux_slck = 1; /* lock scanner */
MUX_SETINT (mux_scan & MUX_FLAGMASK); /* request int */
return;