diff --git a/PDP11/pdp11_dc.c b/PDP11/pdp11_dc.c index 29c8e10c..1f431322 100644 --- a/PDP11/pdp11_dc.c +++ b/PDP11/pdp11_dc.c @@ -158,7 +158,7 @@ DIB dci_dib = { 2, IVCL (DCI), VEC_AUTO, { &dci_iack, &dco_iack }, IOLN_DC, }; -UNIT dci_unit = { UDATA (&dci_svc, 0, 0), SERIAL_IN_WAIT }; +UNIT dci_unit = { UDATA (&dci_svc, 0, 0), TMLN_SPD_9600_BPS }; REG dci_reg[] = { { BRDATAD (BUF, dci_buf, DEV_RDX, 8, DCX_LINES, "input control/stats register") }, @@ -290,7 +290,7 @@ switch ((PA >> 1) & 03) { /* decode PA<2:1> */ case 01: /* dci buf */ dci_clr_int (ln); *data = dci_buf[ln]; - sim_activate_abs (&dci_unit, dci_unit.wait); + sim_activate_after_abs (&dci_unit, dci_unit.wait); return SCPE_OK; case 02: /* dco csr */ diff --git a/PDP11/pdp11_dl.c b/PDP11/pdp11_dl.c index 4d7ed11e..6dccfb5b 100644 --- a/PDP11/pdp11_dl.c +++ b/PDP11/pdp11_dl.c @@ -123,7 +123,7 @@ DIB dli_dib = { 2, IVCL (DLI), VEC_AUTO, { &dli_iack, &dlo_iack }, IOLN_DL, }; -UNIT dli_unit = { UDATA (&dli_svc, 0, 0), SERIAL_IN_WAIT }; +UNIT dli_unit = { UDATA (&dli_svc, 0, 0), TMLN_SPD_9600_BPS }; REG dli_reg[] = { { BRDATA (BUF, dli_buf, DEV_RDX, 16, DLX_LINES) }, @@ -272,7 +272,7 @@ switch ((PA >> 1) & 03) { /* decode PA<2:1> */ *data = dli_buf[ln] & DLIBUF_RD; dli_csr[ln] &= ~CSR_DONE; /* clr rcv done */ dli_clr_int (ln, DLI_RCI); /* clr rcv int req */ - sim_activate_abs (&dli_unit, dli_unit.wait); + sim_activate_after_abs (&dli_unit, dli_unit.wait); break; case 02: /* tto csr */ diff --git a/PDP11/pdp11_dz.c b/PDP11/pdp11_dz.c index b07cf7c5..91d66e05 100644 --- a/PDP11/pdp11_dz.c +++ b/PDP11/pdp11_dz.c @@ -452,13 +452,15 @@ switch ((PA >> 1) & 03) { /* case on PA<2:1> */ dz_clear (dz, FALSE); if (data & CSR_MSE) /* MSE? start poll */ sim_clock_coschedule (&dz_unit, tmxr_poll); - else dz_csr[dz] &= ~(CSR_SA | CSR_RDONE | CSR_TRDY); + else + dz_csr[dz] &= ~(CSR_SA | CSR_RDONE | CSR_TRDY); if ((data & CSR_RIE) == 0) /* RIE = 0? */ dz_clr_rxint (dz); - else if (((dz_csr[dz] & CSR_IE) == 0) && /* RIE 0->1? */ - ((dz_csr[dz] & CSR_SAE)? - (dz_csr[dz] & CSR_SA): (dz_csr[dz] & CSR_RDONE))) - dz_set_rxint (dz); + else + if (((dz_csr[dz] & CSR_IE) == 0) && /* RIE 0->1? */ + ((dz_csr[dz] & CSR_SAE)? + (dz_csr[dz] & CSR_SA): (dz_csr[dz] & CSR_RDONE))) + dz_set_rxint (dz); if ((data & CSR_TIE) == 0) /* TIE = 0? */ dz_clr_txint (dz); else if (((dz_csr[dz] & CSR_TIE) == 0) && (dz_csr[dz] & CSR_TRDY)) @@ -472,12 +474,11 @@ switch ((PA >> 1) & 03) { /* case on PA<2:1> */ lp = &dz_ldsc[line]; /* get line desc */ if (dz_lpr[dz] & LPR_RCVE) /* rcv enb? on */ lp->rcve = 1; - else lp->rcve = 0; /* else line off */ - if (dz_mctl) { - sprintf(lineconfig, "%s-%s%s%s", LPR_GETSPD(data), LPR_GETCHARSIZE(data), LPR_GETPARITY(data), LPR_GETSTOPBITS(data)); - if (!lp->serconfig || (0 != strcmp(lp->serconfig, lineconfig))) /* config changed? */ - tmxr_set_config_line (lp, lineconfig); /* set it */ - } + else + lp->rcve = 0; /* else line off */ + sprintf(lineconfig, "%s-%s%s%s", LPR_GETSPD(data), LPR_GETCHARSIZE(data), LPR_GETPARITY(data), LPR_GETSTOPBITS(data)); + if (!lp->serconfig || (0 != strcmp(lp->serconfig, lineconfig))) /* config changed? */ + tmxr_set_config_line (lp, lineconfig); /* set it */ tmxr_poll_rx (&dz_desc); /* poll input */ dz_update_rcvi (); /* update rx intr */ break; @@ -578,7 +579,7 @@ for (i = c = 0; (i < DZ_LINES) && (c == 0); i++) { /* loop thru lines */ if (c & SCPE_BREAK) /* break? frame err */ c = RBUF_VALID | RBUF_FRME; if (c) /* or in line # */ - c = c | (i << RBUF_V_RLINE); + c = (c & RBUF_CHAR) | RBUF_VALID | (i << RBUF_V_RLINE); } /* end for */ return (uint16)c; } @@ -608,12 +609,14 @@ for (dz = 0; dz < dz_desc.lines/DZ_LINES; dz++) { /* loop thru muxes */ dz_sae[dz] = 0; /* disable alarm */ } } - else dz_csr[dz] &= ~CSR_RDONE; /* no, clear done */ + else + dz_csr[dz] &= ~CSR_RDONE; /* no, clear done */ if ((dz_csr[dz] & CSR_RIE) && /* int enable */ ((dz_csr[dz] & CSR_SAE)? (dz_csr[dz] & CSR_SA): (dz_csr[dz] & CSR_RDONE))) dz_set_rxint (dz); /* and alm/done? */ - else dz_clr_rxint (dz); /* no, clear int */ + else + dz_clr_rxint (dz); /* no, clear int */ } return; } diff --git a/PDP11/pdp11_vh.c b/PDP11/pdp11_vh.c index 81b1af1b..c06ba4fc 100644 --- a/PDP11/pdp11_vh.c +++ b/PDP11/pdp11_vh.c @@ -168,9 +168,12 @@ extern int32 tmxr_poll, clk_tps; #define LPR_M_DIAG (03) #define LPR_V_CHAR_LGTH (3) #define LPR_M_CHAR_LGTH (03) -#define LPR_PARITY_ENAB (1 << 5) -#define LPR_EVEN_PARITY (1 << 6) -#define LPR_STOP_CODE (1 << 7) +#define LPR_V_PARITY_ENAB (5) +#define LPR_PARITY_ENAB (1 << LPR_V_PARITY_ENAB) +#define LPR_V_EVEN_PARITY (6) +#define LPR_EVEN_PARITY (1 << LPR_V_EVEN_PARITY) +#define LPR_V_STOP_CODE (7) +#define LPR_STOP_CODE (1 << LPR_V_STOP_CODE) #define LPR_V_RX_SPEED (8) #define LPR_M_RX_SPEED (017) #define LPR_V_TX_SPEED (12) @@ -193,6 +196,17 @@ extern int32 tmxr_poll, clk_tps; #define RATE_19200 (14) #define RATE_38400 (15) +static const char *vh_charsizes[] = {"5", "6", "7", "8"}; +static const char *vh_baudrates[] = {"50", "75", "110", "134.5", "150", "300", "600", "1200", + "1800", "2000", "2400", "4800", "7200", "9600", "19200", "38400"}; +static const char *vh_parity[] = {"N", "N", "E", "O"}; +static const char *vh_stopbits[] = {"1", "2", "1", "1.5"}; + +#define LPR_GETSPD(x) vh_baudrates[((x) >> LPR_V_RX_SPEED) & LPR_M_RX_SPEED] +#define LPR_GETCHARSIZE(x) vh_charsizes[((x) >> LPR_V_CHAR_LGTH) & LPR_M_CHAR_LGTH] +#define LPR_GETPARITY(x) vh_parity[(((x) >> LPR_V_PARITY_ENAB) & 1) | (((x) >> (LPR_V_EVEN_PARITY-1)) & 2)] +#define LPR_GETSTOPBITS(x) vh_stopbits[(((x) >> LPR_V_STOP_CODE) & 1) + (((((x) >> LPR_V_CHAR_LGTH) & LPR_M_CHAR_LGTH) == 5) ? 2 : 0)] + /* Line-Status Register (STAT) */ #define STAT_DHUID (1 << 8) /* mode: 0=DHV, 1=DHU */ @@ -338,6 +352,7 @@ static t_stat vh_show_detail (FILE *st, UNIT *uptr, int32 val, void *desc); static t_stat vh_show_rbuf (FILE *st, UNIT *uptr, int32 val, void *desc); static t_stat vh_show_txq (FILE *st, UNIT *uptr, int32 val, void *desc); static t_stat vh_putc (int32 vh, TMLX *lp, int32 chan, int32 data); +static void vh_set_config (TMLX *lp ); static void doDMA (int32 vh, int32 chan); static t_stat vh_setmode (UNIT *uptr, int32 val, char *cptr, void *desc); static t_stat vh_show_vec (FILE *st, UNIT *uptr, int32 val, void *desc); @@ -369,6 +384,8 @@ static UNIT vh_unit[VH_MUXES+1] = { { UDATA (&vh_svc, UNIT_IDLE|UNIT_ATTABLE, 0) }, }; +static UNIT *vh_timer_unit; + static const REG vh_reg[] = { { BRDATAD (CSR, vh_csr, DEV_RDX, 16, VH_MUXES, "control/status register, boards 0 to 3") }, { BRDATAD (TIMER, vh_timer, DEV_RDX, 16, VH_MUXES, "controller timeout, boards 0 to 3") }, @@ -765,22 +782,31 @@ static void vh_getc ( int32 vh ) TMLX *lp; for (i = 0; i < (uint32)VH_LINES; i++) { + if (rbuf_idx[vh] >= (FIFO_ALARM-1)) /* close to fifo capacity? */ + continue; /* don't bother checking for data */ lp = &vh_parm[(vh * VH_LINES) + i]; while ((c = tmxr_getc_ln (lp->tmln)) != 0) { if (c & SCPE_BREAK) { fifo_put (vh, lp, RBUF_FRAME_ERR | RBUF_PUTLINE (i)); - /* BUG: check for overflow above */ } else { c &= bitmask[(lp->lpr >> LPR_V_CHAR_LGTH) & LPR_M_CHAR_LGTH]; fifo_put (vh, lp, RBUF_PUTLINE (i) | c); - /* BUG: check for overflow above */ } } } } +static void vh_set_config ( TMLX *lp ) +{ + char lineconfig[16]; + + sprintf(lineconfig, "%s-%s%s%s", LPR_GETSPD(lp->lpr), LPR_GETCHARSIZE(lp->lpr), LPR_GETPARITY(lp->lpr), LPR_GETSTOPBITS(lp->lpr)); + if (!lp->tmln->serconfig || (0 != strcmp(lp->tmln->serconfig, lineconfig))) /* config changed? */ + tmxr_set_config_line (lp->tmln, lineconfig); /* set it */ +} + /* I/O dispatch routines */ static t_stat vh_rd ( int32 *data, @@ -929,7 +955,7 @@ static t_stat vh_wr ( int32 ldata, break; if ((data == RESET_ABORT) && (vh_csr[vh] & CSR_MASTER_RESET)) { vh_mcount[vh] = 1; - sim_clock_coschedule (&vh_unit[1], tmxr_poll); + sim_clock_coschedule (vh_timer_unit, tmxr_poll); break; } if (vh_unit[vh].flags & UNIT_MODEDHU) { @@ -974,7 +1000,7 @@ static t_stat vh_wr ( int32 ldata, case 2: /* LPR */ if ((data == RESET_ABORT) && (vh_csr[vh] & CSR_MASTER_RESET)) { vh_mcount[vh] = 1; - sim_clock_coschedule (&vh_unit[1], tmxr_poll); + sim_clock_coschedule (vh_timer_unit, tmxr_poll); break; } if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) @@ -989,6 +1015,7 @@ static t_stat vh_wr ( int32 ldata, if (CSR_GETCHAN (vh_csr[vh]) != 0) data &= ~LPR_DISAB_XRPT; lp->lpr = data; + vh_set_config (lp); if (((lp->lpr >> LPR_V_DIAG) & LPR_M_DIAG) == 1) { fifo_put (vh, lp, RBUF_DIAG | @@ -1001,7 +1028,7 @@ static t_stat vh_wr ( int32 ldata, case 3: /* STAT/FIFODATA */ if ((data == RESET_ABORT) && (vh_csr[vh] & CSR_MASTER_RESET)) { vh_mcount[vh] = 1; - sim_clock_coschedule (&vh_unit[1], tmxr_poll); + sim_clock_coschedule (vh_timer_unit, tmxr_poll); break; } if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) @@ -1025,7 +1052,7 @@ static t_stat vh_wr ( int32 ldata, case 4: /* LNCTRL */ if ((data == RESET_ABORT) && (vh_csr[vh] & CSR_MASTER_RESET)) { vh_mcount[vh] = 1; - sim_clock_coschedule (&vh_unit[1], tmxr_poll); + sim_clock_coschedule (vh_timer_unit, tmxr_poll); break; } if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) @@ -1093,7 +1120,7 @@ static t_stat vh_wr ( int32 ldata, case 5: /* TBUFFAD1 */ if ((data == RESET_ABORT) && (vh_csr[vh] & CSR_MASTER_RESET)) { vh_mcount[vh] = 1; - sim_clock_coschedule (&vh_unit[1], tmxr_poll); + sim_clock_coschedule (vh_timer_unit, tmxr_poll); break; } if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) @@ -1109,7 +1136,7 @@ static t_stat vh_wr ( int32 ldata, case 6: /* TBUFFAD2 */ if ((data == RESET_ABORT) && (vh_csr[vh] & CSR_MASTER_RESET)) { vh_mcount[vh] = 1; - sim_clock_coschedule (&vh_unit[1], tmxr_poll); + sim_clock_coschedule (vh_timer_unit, tmxr_poll); break; } if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) @@ -1130,7 +1157,7 @@ static t_stat vh_wr ( int32 ldata, case 7: /* TBUFFCT */ if ((data == RESET_ABORT) && (vh_csr[vh] & CSR_MASTER_RESET)) { vh_mcount[vh] = 1; - sim_clock_coschedule (&vh_unit[1], tmxr_poll); + sim_clock_coschedule (vh_timer_unit, tmxr_poll); break; } if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) @@ -1293,6 +1320,7 @@ static void vh_init_chan ( int32 vh, lp->lpr = (RATE_9600 << LPR_V_TX_SPEED) | (RATE_9600 << LPR_V_RX_SPEED) | (03 << LPR_V_CHAR_LGTH); + vh_set_config ( lp ); lp->lnctrl = 0; lp->lstat &= ~(STAT_MDL | STAT_DHUID | STAT_RI); if (vh_unit[vh].flags & UNIT_MODEDHU) @@ -1366,8 +1394,9 @@ static t_stat vh_reset ( DEVICE *dptr ) for (i = 0; i < vh_desc.lines; i++) vh_parm[i].tmln = &vh_ldsc[i]; vh_dev.numunits = (vh_desc.lines / VH_LINES) + 1; - vh_unit[vh_dev.numunits-1].action = &vh_timersvc; - vh_unit[vh_dev.numunits-1].flags = UNIT_DIS; + vh_timer_unit = &vh_unit[vh_dev.numunits-1]; + vh_timer_unit->action = &vh_timersvc; + vh_timer_unit->flags = UNIT_DIS; for (i = 0; i < vh_desc.lines/VH_LINES; i++) { /* if Unibus, force DHU mode */ if (UNIBUS) diff --git a/sim_tmxr.c b/sim_tmxr.c index a19c8043..68208b79 100644 --- a/sim_tmxr.c +++ b/sim_tmxr.c @@ -1886,6 +1886,8 @@ return; int32 tmxr_rqln (TMLN *lp) { +if ((lp->rxbps && (lp->rxlasttime + (lp->rxdelta + 500)/1000) > sim_os_msec ())) + return 0; return (lp->rxbpi - lp->rxbpr + ((lp->rxbpi < lp->rxbpr)? lp->rxbsz: 0)); } @@ -3840,6 +3842,29 @@ else { if (mux) fprintf (st, "Valid line numbers are from 0 thru %d\n\n", mux->lines-1); } +if (single_line) { /* Single Line Multiplexer */ + fprintf (st, "The input data rate for the $s device can be controlled by\n", dptr->name); + fprintf (st, "specifying SPEED=nnn on the the ATTACH command.\n"); + } +else { + fprintf (st, "The input data rate for all lines or a particular line of a the %s\n", dptr->name); + fprintf (st, "device can be controlled by specifying SPEED=nnn on the the ATTACH command.\n"); + } +fprintf (st, "SPEED values can be any one of:\n\n"); +fprintf (st, " 0 50 75 110 134 150 300 600 1200 1800 2000 2400\n"); +fprintf (st, " 3600 4800 7200 9600 19200 38400 57600 76800 115200\n\n"); +fprintf (st, "A SPEED value of 0 causes input data to be delivered to the simulated\n"); +fprintf (st, "port as fast as it arrives.\n\n"); +fprintf (st, "If a simulated multiplexor devices can programmatically set a serial\n"); +fprintf (st, "port line speed, the programmatically specified speed will take precidence\n"); +fprintf (st, "over any input speed specified on an attach command.\n"); +fprintf (st, "Example:\n\n"); +fprintf (st, " sim> ATTACH %s 1234,SPEED=2400\n", dptr->name); +if (!single_line) + fprintf (st, " sim> ATTACH %s Line=2,SPEED=2400\n", dptr->name); +fprintf (st, "\n"); +fprintf (st, "The SPEED parameter only influences the rate at which data is deliverd\n"); +fprintf (st, "into the simulated multiplexor port. Output data rates are unaffected\n\n"); fprintf (st, "An optional serial port configuration string may be present after the port\n"); fprintf (st, "name. If present, it must be separated from the port name with a semicolon\n"); fprintf (st, "and has this form:\n\n");