PDP11, VAX: MUX input rate limiting works correctly with input arriving on multiple lines concurrently.
This commit is contained in:
parent
d66b5a4671
commit
0938d31e59
10 changed files with 89 additions and 20 deletions
|
@ -290,7 +290,9 @@ switch ((PA >> 1) & 03) { /* decode PA<2:1> */
|
|||
case 01: /* dci buf */
|
||||
dci_clr_int (ln);
|
||||
*data = dci_buf[ln];
|
||||
sim_activate_after_abs (&dci_unit, dci_unit.wait);
|
||||
/* Rechedule the next poll preceisely so that
|
||||
the programmed input speed is observed. */
|
||||
sim_clock_coschedule_abs (&dci_unit, tmxr_poll);
|
||||
return SCPE_OK;
|
||||
|
||||
case 02: /* dco csr */
|
||||
|
@ -387,7 +389,6 @@ int32 ln, c, temp;
|
|||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
||||
return SCPE_OK;
|
||||
sim_clock_coschedule (uptr, tmxr_poll); /* continue poll */
|
||||
ln = tmxr_poll_conn (&dcx_desc); /* look for connect */
|
||||
if (ln >= 0) { /* got one? */
|
||||
dcx_ldsc[ln].rcve = 1; /* set rcv enb */
|
||||
|
@ -432,7 +433,7 @@ for (ln = 0; ln < DCX_LINES; ln++) { /* loop thru lines */
|
|||
dco_csr[ln] &= ~DCOCSR_CTS;
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
return sim_clock_coschedule (uptr, tmxr_poll); /* continue poll */
|
||||
}
|
||||
|
||||
/* Terminal output service */
|
||||
|
@ -531,7 +532,7 @@ int32 ln;
|
|||
dcx_enbdis (dptr->flags & DEV_DIS); /* sync enables */
|
||||
sim_cancel (&dci_unit); /* assume stop */
|
||||
if (dci_unit.flags & UNIT_ATT) /* if attached, */
|
||||
sim_activate (&dci_unit, tmxr_poll); /* activate */
|
||||
sim_clock_coschedule (&dci_unit, tmxr_poll); /* activate */
|
||||
for (ln = 0; ln < DCX_LINES; ln++) /* for all lines */
|
||||
dcx_reset_ln (ln);
|
||||
return auto_config (dci_dev.name, dcx_desc.lines); /* auto config */
|
||||
|
|
|
@ -272,7 +272,9 @@ 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_after_abs (&dli_unit, dli_unit.wait);
|
||||
/* Rechedule the next poll preceisely so that
|
||||
the programmed input speed is observed. */
|
||||
sim_clock_coschedule_abs (&dli_unit, tmxr_poll);
|
||||
break;
|
||||
|
||||
case 02: /* tto csr */
|
||||
|
@ -377,7 +379,6 @@ sim_debug(DBG_TRC, &dli_dev, "dli_svc()\n");
|
|||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
||||
return SCPE_OK;
|
||||
sim_clock_coschedule (uptr, tmxr_poll); /* continue poll */
|
||||
ln = tmxr_poll_conn (&dlx_desc); /* look for connect */
|
||||
if (ln >= 0) { /* got one? rcv enb */
|
||||
dlx_ldsc[ln].rcve = 1;
|
||||
|
@ -418,7 +419,8 @@ for (ln = 0; ln < DLX_LINES; ln++) { /* loop thru lines */
|
|||
/* clr CDT,RNG,CTS */
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
return sim_clock_coschedule (uptr, tmxr_poll); /* continue poll */
|
||||
|
||||
}
|
||||
|
||||
/* Terminal output service */
|
||||
|
@ -532,7 +534,7 @@ sim_debug(DBG_TRC, dptr, "dlx_reset()\n");
|
|||
dlx_enbdis (dptr->flags & DEV_DIS); /* sync enables */
|
||||
sim_cancel (&dli_unit); /* assume stop */
|
||||
if (dli_unit.flags & UNIT_ATT) /* if attached, */
|
||||
sim_activate (&dli_unit, tmxr_poll); /* activate */
|
||||
sim_clock_coschedule (&dli_unit, tmxr_poll); /* activate */
|
||||
for (ln = 0; ln < DLX_LINES; ln++) /* for all lines */
|
||||
dlx_reset_ln (ln);
|
||||
return auto_config (dli_dev.name, dlx_desc.lines); /* auto config */
|
||||
|
|
|
@ -392,9 +392,9 @@ switch ((PA >> 1) & 03) { /* case on PA<2:1> */
|
|||
tmxr_poll_rx (&dz_desc); /* poll input */
|
||||
dz_update_rcvi (); /* update rx intr */
|
||||
if (dz_rbuf[dz]) {
|
||||
/* Schedule the next poll somewhat preceisely so that
|
||||
/* Rechedule the next poll preceisely so that
|
||||
the programmed input speed is observed. */
|
||||
sim_activate_after_abs (&dz_unit, dz_ldsc[(dz * DZ_LINES) + (dz_rbuf[dz]>>RBUF_V_RLINE) & 07].rxdelta + dz_wait);
|
||||
sim_clock_coschedule_abs (&dz_unit, tmxr_poll);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -681,9 +681,9 @@ static int32 fifo_get ( int32 vh )
|
|||
}
|
||||
}
|
||||
}
|
||||
/* Schedule the next poll somewhat preceisely so that the
|
||||
/* Reschedule the next poll preceisely so that the
|
||||
programmed input speed is observed. */
|
||||
sim_activate_after_abs (&vh_unit[0], vh_parm[(vh * VH_LINES) + RBUF_GETLINE(data)].tmln->rxdelta + vh_wait);
|
||||
sim_clock_coschedule_abs (&vh_unit[0], tmxr_poll);
|
||||
return (data & 0177777);
|
||||
}
|
||||
/* TX Q manipulation */
|
||||
|
|
|
@ -129,7 +129,8 @@
|
|||
#include "sim_serial.h"
|
||||
#include "sim_timer.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#ifdef __HAIKU__
|
||||
#define nice(n) ({})
|
||||
#endif
|
||||
|
@ -1938,7 +1939,7 @@ if (!sim_rem_master_mode) {
|
|||
(sim_con_ldsc.serport == 0)) { /* and not serial? */
|
||||
if (c && sim_con_ldsc.rxbps) /* got something && rate limiting? */
|
||||
sim_con_ldsc.rxnexttime = /* compute next input time */
|
||||
sim_gtime () + ((sim_con_ldsc.rxdelta * sim_timer_inst_per_sec ())/sim_con_ldsc.rxbpsfactor);
|
||||
floor (sim_gtime () + ((sim_con_ldsc.rxdelta * sim_timer_inst_per_sec ())/sim_con_ldsc.rxbpsfactor));
|
||||
return c; /* in-window */
|
||||
}
|
||||
if (!sim_con_ldsc.conn) { /* no telnet or serial connection? */
|
||||
|
|
|
@ -488,6 +488,7 @@ struct sim_unit {
|
|||
int32 u6; /* device specific */
|
||||
void *up7; /* device specific */
|
||||
void *up8; /* device specific */
|
||||
void *tmxr; /* TMXR linkage */
|
||||
#ifdef SIM_ASYNCH_IO
|
||||
void (*a_check_completion)(struct sim_unit *);
|
||||
t_bool (*a_is_active)(struct sim_unit *);
|
||||
|
|
12
sim_timer.c
12
sim_timer.c
|
@ -1578,6 +1578,12 @@ t_stat sim_clock_coschedule (UNIT *uptr, int32 interval)
|
|||
return sim_clock_coschedule_tmr (uptr, 0, interval);
|
||||
}
|
||||
|
||||
t_stat sim_clock_coschedule_abs (UNIT *uptr, int32 interval)
|
||||
{
|
||||
sim_cancel (uptr);
|
||||
return sim_clock_coschedule_tmr (uptr, 0, interval);
|
||||
}
|
||||
|
||||
t_stat sim_clock_coschedule_tmr (UNIT *uptr, int32 tmr, int32 interval)
|
||||
{
|
||||
if (NULL == sim_clock_unit[tmr])
|
||||
|
@ -1616,3 +1622,9 @@ else
|
|||
}
|
||||
}
|
||||
|
||||
t_stat sim_clock_coschedule_tmr_abs (UNIT *uptr, int32 tmr, int32 interval)
|
||||
{
|
||||
sim_cancel (uptr);
|
||||
return sim_clock_coschedule_tmr (uptr, tmr, interval);
|
||||
}
|
||||
|
||||
|
|
|
@ -122,7 +122,9 @@ t_stat sim_timer_change_asynch (void);
|
|||
t_stat sim_timer_activate_after (UNIT *uptr, int32 usec_delay);
|
||||
t_stat sim_register_clock_unit (UNIT *uptr);
|
||||
t_stat sim_clock_coschedule (UNIT *uptr, int32 interval);
|
||||
t_stat sim_clock_coschedule_abs (UNIT *uptr, int32 interval);
|
||||
t_stat sim_clock_coschedule_tmr (UNIT *uptr, int32 tmr, int32 interval);
|
||||
t_stat sim_clock_coschedule_tmr_abs (UNIT *uptr, int32 tmr, int32 interval);
|
||||
double sim_timer_inst_per_sec (void);
|
||||
t_bool sim_timer_idle_capable (uint32 *host_ms_sleep_1, uint32 *host_tick_ms);
|
||||
|
||||
|
|
52
sim_tmxr.c
52
sim_tmxr.c
|
@ -340,6 +340,7 @@
|
|||
#include "scp.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
|
||||
/* Telnet protocol constants - negatives are for init'ing signed char data */
|
||||
|
||||
|
@ -1565,7 +1566,7 @@ if ((lp->conn && lp->rcve) && /* conn & enb & */
|
|||
if (lp->rxbpi == lp->rxbpr) /* empty? zero ptrs */
|
||||
lp->rxbpi = lp->rxbpr = 0;
|
||||
if (val && lp->rxbps)
|
||||
lp->rxnexttime = sim_gtime () + ((lp->rxdelta * sim_timer_inst_per_sec ())/lp->rxbpsfactor);
|
||||
lp->rxnexttime = floor (sim_gtime () + ((lp->rxdelta * sim_timer_inst_per_sec ())/lp->rxbpsfactor));
|
||||
tmxr_debug_return(lp, val);
|
||||
return val;
|
||||
}
|
||||
|
@ -1884,13 +1885,20 @@ return;
|
|||
|
||||
/* Return count of available characters for line */
|
||||
|
||||
int32 tmxr_rqln (TMLN *lp)
|
||||
int32 tmxr_rqln_bare (TMLN *lp, t_bool speed)
|
||||
{
|
||||
if ((lp->rxbps) && (sim_gtime () < lp->rxnexttime)) /* rate limiting and too soon */
|
||||
if ((speed) &&
|
||||
(lp->rxbps) &&
|
||||
(sim_gtime () < lp->rxnexttime)) /* rate limiting and too soon */
|
||||
return 0;
|
||||
return (lp->rxbpi - lp->rxbpr + ((lp->rxbpi < lp->rxbpr)? lp->rxbsz: 0));
|
||||
}
|
||||
|
||||
int32 tmxr_rqln (TMLN *lp)
|
||||
{
|
||||
return tmxr_rqln_bare (lp, TRUE);
|
||||
}
|
||||
|
||||
|
||||
/* Store character in line buffer
|
||||
|
||||
|
@ -3505,6 +3513,7 @@ if (r != SCPE_OK) /* error? */
|
|||
mp->uptr = uptr; /* save unit for polling */
|
||||
uptr->filename = tmxr_mux_attach_string (uptr->filename, mp);/* save */
|
||||
uptr->flags = uptr->flags | UNIT_ATT; /* no more errors */
|
||||
uptr->tmxr = (void *)mp;
|
||||
if ((mp->lines > 1) ||
|
||||
((mp->master == 0) &&
|
||||
(mp->ldsc[0].connecting == 0) &&
|
||||
|
@ -3703,6 +3712,7 @@ if (!(uptr->flags & UNIT_ATT)) /* attached? */
|
|||
tmxr_close_master (mp); /* close master socket */
|
||||
free (uptr->filename); /* free setup string */
|
||||
uptr->filename = NULL;
|
||||
uptr->tmxr = NULL;
|
||||
mp->last_poll_time = 0;
|
||||
for (i=0; i < mp->lines; i++) {
|
||||
UNIT *uptr = mp->ldsc[i].uptr ? mp->ldsc[i].uptr : mp->uptr;
|
||||
|
@ -3762,8 +3772,19 @@ t_stat tmxr_clock_coschedule (UNIT *uptr, int32 interval)
|
|||
return tmxr_clock_coschedule_tmr (uptr, 0, interval);
|
||||
}
|
||||
|
||||
t_stat tmxr_clock_coschedule_abs (UNIT *uptr, int32 interval)
|
||||
{
|
||||
sim_cancel (uptr);
|
||||
return tmxr_clock_coschedule_tmr (uptr, 0, interval);
|
||||
}
|
||||
|
||||
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
t_stat tmxr_clock_coschedule_tmr (UNIT *uptr, int32 tmr, int32 interval)
|
||||
{
|
||||
TMXR *mp = (TMXR *)uptr->tmxr;
|
||||
double sim_gtime_now = sim_gtime ();
|
||||
|
||||
#if defined(SIM_ASYNCH_IO) && defined(SIM_ASYNCH_MUX)
|
||||
if ((!(uptr->dynflags & UNIT_TM_POLL)) ||
|
||||
(!sim_asynch_enabled)) {
|
||||
|
@ -3771,10 +3792,35 @@ if ((!(uptr->dynflags & UNIT_TM_POLL)) ||
|
|||
}
|
||||
return SCPE_OK;
|
||||
#else
|
||||
if (mp) {
|
||||
int32 i, soon = interval;
|
||||
|
||||
for (i = 0; i < mp->lines; i++) {
|
||||
TMLN *lp = &mp->ldsc[i];
|
||||
|
||||
if (tmxr_rqln_bare (lp, FALSE)) {
|
||||
int32 due;
|
||||
|
||||
if (lp->rxbps)
|
||||
due = (int32)(lp->rxnexttime - sim_gtime_now);
|
||||
else
|
||||
due = (int32)((uptr->wait * sim_timer_inst_per_sec ())/TMXR_RX_BPS_UNIT_SCALE);
|
||||
soon = MIN(soon, due);
|
||||
}
|
||||
}
|
||||
if (soon != interval)
|
||||
return _sim_activate (uptr, soon);
|
||||
}
|
||||
return sim_clock_coschedule_tmr (uptr, tmr, interval);
|
||||
#endif
|
||||
}
|
||||
|
||||
t_stat tmxr_clock_coschedule_tmr_abs (UNIT *uptr, int32 tmr, int32 interval)
|
||||
{
|
||||
sim_cancel (uptr);
|
||||
return tmxr_clock_coschedule_tmr (uptr, tmr, interval);
|
||||
}
|
||||
|
||||
/* Generic Multiplexer attach help */
|
||||
|
||||
t_stat tmxr_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
|
||||
|
|
10
sim_tmxr.h
10
sim_tmxr.h
|
@ -275,7 +275,9 @@ t_stat tmxr_activate (UNIT *uptr, int32 interval);
|
|||
t_stat tmxr_activate_after (UNIT *uptr, int32 usecs_walltime);
|
||||
t_stat tmxr_activate_after_abs (UNIT *uptr, int32 usecs_walltime);
|
||||
t_stat tmxr_clock_coschedule (UNIT *uptr, int32 interval);
|
||||
t_stat tmxr_clock_coschedule_abs (UNIT *uptr, int32 interval);
|
||||
t_stat tmxr_clock_coschedule_tmr (UNIT *uptr, int32 tmr, int32 interval);
|
||||
t_stat tmxr_clock_coschedule_tmr_abs (UNIT *uptr, int32 tmr, int32 interval);
|
||||
t_stat tmxr_change_async (void);
|
||||
t_stat tmxr_locate_line_send (const char *dev_line, SEND **snd);
|
||||
t_stat tmxr_locate_line_expect (const char *dev_line, EXPECT **exp);
|
||||
|
@ -294,15 +296,17 @@ void _tmxr_debug (uint32 dbits, TMLN *lp, const char *msg, char *buf, int bufsiz
|
|||
|
||||
#if defined(SIM_ASYNCH_IO) && defined(SIM_ASYNCH_MUX)
|
||||
#define tmxr_attach(mp, uptr, cptr) tmxr_attach_ex(mp, uptr, cptr, TRUE)
|
||||
#else
|
||||
#define tmxr_attach(mp, uptr, cptr) tmxr_attach_ex(mp, uptr, cptr, FALSE)
|
||||
#endif
|
||||
#if (!defined(NOT_MUX_USING_CODE))
|
||||
#define sim_activate tmxr_activate
|
||||
#define sim_activate_after tmxr_activate_after
|
||||
#define sim_activate_after_abs tmxr_activate_after_abs
|
||||
#define sim_clock_coschedule tmxr_clock_coschedule
|
||||
#define sim_clock_coschedule_abs tmxr_clock_coschedule_abs
|
||||
#define sim_clock_coschedule_tmr tmxr_clock_coschedule_tmr
|
||||
#endif
|
||||
#else
|
||||
#define tmxr_attach(mp, uptr, cptr) tmxr_attach_ex(mp, uptr, cptr, FALSE)
|
||||
#define sim_clock_coschedule_tmr_abs tmxr_clock_coschedule_tmr_abs
|
||||
#endif
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue