TMXR: Fix MUX transmit scheduling when buffer is empty
Also: - Enhance SHOW MUX to support "SHOW MUX <dev>" - Fix potential null pointer dereference with unusual ATTACH combinations - Allow BPS factor to change without specifying an explicit speed.
This commit is contained in:
parent
c73f56cc5a
commit
d3da865e9b
2 changed files with 140 additions and 100 deletions
2
scp.c
2
scp.c
|
@ -1381,7 +1381,7 @@ static const char simh_help[] =
|
|||
"+sh{ow} <unit> {arg,...} show unit parameters\n"
|
||||
"+sh{ow} ethernet show ethernet devices\n"
|
||||
"+sh{ow} serial show serial devices\n"
|
||||
"+sh{ow} multiplexer show open multiplexer devices\n"
|
||||
"+sh{ow} multiplexer {dev} show open multiplexer device info\n"
|
||||
#if defined(USE_SIM_VIDEO)
|
||||
"+sh{ow} video show video capabilities\n"
|
||||
#endif
|
||||
|
|
64
sim_tmxr.c
64
sim_tmxr.c
|
@ -872,6 +872,8 @@ if (mp->port) /* copy port */
|
|||
sprintf (growstring(&tptr, 13 + strlen (mp->port)), "%s%s", mp->port, mp->notelnet ? ";notelnet" : "");
|
||||
if (mp->logfiletmpl[0]) /* logfile info */
|
||||
sprintf (growstring(&tptr, 7 + strlen (mp->logfiletmpl)), ",Log=%s", mp->logfiletmpl);
|
||||
if (mp->buffered)
|
||||
sprintf (growstring(&tptr, 10 + 10), ",Buffered=%d", mp->buffered);
|
||||
while ((*tptr == ',') || (*tptr == ' '))
|
||||
memmove (tptr, tptr+1, strlen(tptr+1)+1);
|
||||
for (i=0; i<mp->lines; ++i) {
|
||||
|
@ -2483,21 +2485,25 @@ t_stat tmxr_set_line_speed (TMLN *lp, CONST char *speed)
|
|||
UNIT *uptr;
|
||||
CONST char *cptr;
|
||||
t_stat r;
|
||||
uint32 rxbps;
|
||||
|
||||
if (!speed || !*speed)
|
||||
return SCPE_2FARG;
|
||||
if (_tmln_speed_delta (speed) < 0)
|
||||
return SCPE_ARG;
|
||||
lp->rxbps = (uint32)strtotv (speed, &cptr, 10);
|
||||
rxbps = (uint32)strtotv (speed, &cptr, 10);
|
||||
if (*cptr == '*') {
|
||||
uint32 bpsfactor = (uint32) get_uint (cptr+1, 10, 32, &r);
|
||||
|
||||
if (r != SCPE_OK)
|
||||
return r;
|
||||
lp->bpsfactor = bpsfactor;
|
||||
if (speed == cptr) /* just changing bps factor? */
|
||||
return SCPE_OK; /* Done now */
|
||||
}
|
||||
lp->rxbps = rxbps; /* use supplied speed */
|
||||
if ((lp->serport) && (lp->bpsfactor != 0.0))
|
||||
lp->bpsfactor = 1.0;
|
||||
lp->bpsfactor = 1.0; /* Ignore bps factor for serial ports */
|
||||
lp->rxdeltausecs = (uint32)(_tmln_speed_delta (speed) / lp->bpsfactor);
|
||||
lp->rxnexttime = 0.0;
|
||||
uptr = lp->uptr;
|
||||
|
@ -3073,6 +3079,8 @@ t_stat tmxr_set_line_unit (TMXR *mp, int line, UNIT *uptr_poll)
|
|||
{
|
||||
if ((line < 0) || (line >= mp->lines))
|
||||
return SCPE_ARG;
|
||||
if (mp->ldsc[line].uptr)
|
||||
mp->ldsc[line].uptr->dynflags &= ~UNIT_TM_POLL;
|
||||
mp->ldsc[line].uptr = uptr_poll;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -3104,6 +3112,8 @@ t_stat tmxr_set_line_output_unit (TMXR *mp, int line, UNIT *uptr_poll)
|
|||
{
|
||||
if ((line < 0) || (line >= mp->lines))
|
||||
return SCPE_ARG;
|
||||
if (mp->ldsc[line].o_uptr)
|
||||
mp->ldsc[line].o_uptr->dynflags &= ~UNIT_TM_POLL;
|
||||
mp->ldsc[line].o_uptr = uptr_poll;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -3857,11 +3867,14 @@ int32 i;
|
|||
if (mp->dptr == NULL) /* has device been set? */
|
||||
mp->dptr = find_dev_from_unit (uptr); /* no, so set device now */
|
||||
|
||||
if (mp->uptr == NULL) /* has polling unit been set? */
|
||||
mp->uptr = uptr; /* save unit for polling */
|
||||
r = tmxr_open_master (mp, cptr); /* open master socket */
|
||||
if (r != SCPE_OK) /* error? */
|
||||
return r;
|
||||
uptr->filename = tmxr_mux_attach_string (uptr->filename, mp);/* save */
|
||||
if (uptr->filename == NULL) /* avoid dangling NULL pointer */
|
||||
uptr->filename = (char *)calloc (1, 1); /* provide an emptry string */
|
||||
uptr->flags = uptr->flags | UNIT_ATT; /* no more errors */
|
||||
uptr->tmxr = (void *)mp;
|
||||
if ((mp->lines > 1) ||
|
||||
|
@ -3910,15 +3923,10 @@ if (tmxr_open_device_count)
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat tmxr_show_open_devices (FILE* st, DEVICE *dptr, UNIT* uptr, int32 val, CONST char* desc)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (0 == tmxr_open_device_count)
|
||||
fprintf(st, "No Attached Multiplexer Devices\n");
|
||||
else {
|
||||
for (i=0; i<tmxr_open_device_count; ++i) {
|
||||
TMXR *mp = tmxr_open_devices[i];
|
||||
t_stat tmxr_show_open_device (FILE* st, TMXR *mp)
|
||||
{
|
||||
int j;
|
||||
TMLN *lp;
|
||||
UNIT *o_uptr = mp->ldsc[0].o_uptr;
|
||||
UNIT *uptr = mp->ldsc[0].uptr;
|
||||
|
@ -4008,7 +4016,35 @@ else {
|
|||
tmxr_fconns (st, lp, -1);
|
||||
tmxr_fstats (st, lp, -1);
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
t_stat tmxr_show_open_devices (FILE* st, DEVICE *dptr, UNIT* uptr, int32 val, CONST char* cptr)
|
||||
{
|
||||
int i;
|
||||
char gbuf[CBUFSIZE];
|
||||
|
||||
cptr = get_glyph (cptr, gbuf, 0);
|
||||
if (*cptr)
|
||||
return SCPE_2MARG;
|
||||
if ((0 == tmxr_open_device_count) &&
|
||||
(gbuf[0] == '\0'))
|
||||
fprintf(st, "No Attached Multiplexer Devices\n");
|
||||
else {
|
||||
for (i=0; i<tmxr_open_device_count; ++i) {
|
||||
TMXR *mp = tmxr_open_devices[i];
|
||||
|
||||
if ((gbuf[0] == '\0') ||
|
||||
(0 == strcmp (gbuf, mp->dptr->name))) {
|
||||
tmxr_show_open_device (st, mp);
|
||||
if (gbuf[0] != '\0')
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((gbuf[0] != '\0') &&
|
||||
(i == tmxr_open_device_count))
|
||||
return sim_messagef (SCPE_ARG, "Multiplexer device %s not found or attached\n", gbuf);
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -4146,13 +4182,17 @@ for (i=0; i<mp->lines; i++) {
|
|||
if ((lp->conn || lp->txbfd) && /* Connected (or buffered)? */
|
||||
(uptr == lp->o_uptr) && /* output completion unit? */
|
||||
(lp->txbps)) { /* while rate limiting */
|
||||
if ((tmxr_tqln(lp)) && /* pending output data? */
|
||||
(lp->txnexttime < sim_gtime_now))
|
||||
if ((tmxr_tqln(lp)) && /* pending output data */
|
||||
(lp->txnexttime < sim_gtime_now))/* that can be transmitted now? */
|
||||
tmxr_send_buffered_data (lp);/* flush it */
|
||||
if (tmxr_tqln(lp) == 0) /* no pending output data */
|
||||
due = interval; /* No rush */
|
||||
else {
|
||||
if (lp->txnexttime > sim_gtime_now)
|
||||
due = (int32)(lp->txnexttime - sim_gtime_now);
|
||||
else
|
||||
due = sim_processing_event ? 1 : 0; /* avoid potential infinite loop if called from service routine */
|
||||
}
|
||||
sooner = MIN(sooner, due);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue