mirror of
https://github.com/simh/simh.git
synced 2026-02-10 02:01:05 +00:00
Change to support serial ports on multiplexer devices without any changes to existing multiplexer device emulation code.
Added support for per line tcp listen ports. Added support for per line outgoing tcp/telnet connections. Removed DEV_NET from pdp11_dz and pdp11_vh emulators to allow proper restore of
This commit is contained in:
@@ -29,8 +29,6 @@
|
||||
28-Mar-11 JDB Tidied up signal handling
|
||||
26-Oct-10 JDB Changed I/O signal handler for revised signal model
|
||||
25-Nov-08 JDB Revised for new multiplexer library SHOW routines
|
||||
19-Nov-08 JDB [serial] Removed DEV_NET to allow restoration of listening port
|
||||
17-Oct-08 JDB [serial] Added serial port support
|
||||
11-Sep-08 JDB Fixed STC,C losing interrupt request on BREAK
|
||||
07-Sep-08 JDB Fixed IN_LOOPBACK conflict with netinet/in.h
|
||||
Changed Telnet poll to connect immediately after reset or attach
|
||||
@@ -80,13 +78,13 @@
|
||||
an "external rate" that is equivalent to 9600 baud, as most terminals were
|
||||
set to their maximum speeds.
|
||||
|
||||
We support the 12966A connected to an HP terminal emulator via Telnet or a
|
||||
serial port. Internally, we model the BACI as a terminal multiplexer with
|
||||
one line. The simulation is complicated by the half-duplex nature of the
|
||||
card (there is only one FIFO, used selectively either for transmission or
|
||||
reception) and the double-buffered UART (a Western Digital TR1863A), which
|
||||
has holding registers as well as a shift registers for transmission and
|
||||
reception. We model both sets of device registers.
|
||||
We support the 12966A connected to an HP terminal emulator via Telnet.
|
||||
Internally, we model the BACI as a terminal multiplexer with one line. The
|
||||
simulation is complicated by the half-duplex nature of the card (there is
|
||||
only one FIFO, used selectively either for transmission or reception) and the
|
||||
double-buffered UART (a Western Digital TR1863A), which has holding registers
|
||||
as well as a shift registers for transmission and reception. We model both
|
||||
sets of device registers.
|
||||
|
||||
During an output operation, the first character output to the card passes
|
||||
through the FIFO and into the transmitter holding register. Subsequent
|
||||
@@ -115,12 +113,12 @@
|
||||
as an "optimized (fast) timing" option. Optimization makes three
|
||||
improvements:
|
||||
|
||||
1. On output, characters in the FIFO are emptied into the line buffer as a
|
||||
1. On output, characters in the FIFO are emptied into the Telnet buffer as a
|
||||
block, rather than one character per service call, and on input, all of
|
||||
the characters available in the line buffer are loaded into the FIFO as a
|
||||
block.
|
||||
the characters available in the Telnet buffer are loaded into the FIFO as
|
||||
a block.
|
||||
|
||||
2. The ENQ/ACK handshake is done locally, without involving the terminal
|
||||
2. The ENQ/ACK handshake is done locally, without involving the Telnet
|
||||
client.
|
||||
|
||||
3. Input occurring during an output operation is delayed until the second or
|
||||
@@ -320,7 +318,7 @@
|
||||
/* Unit references */
|
||||
|
||||
#define baci_term baci_unit[0] /* terminal I/O unit */
|
||||
#define baci_poll baci_unit[1] /* line polling unit */
|
||||
#define baci_poll baci_unit[1] /* Telnet polling unit */
|
||||
|
||||
|
||||
/* BACI state variables */
|
||||
@@ -393,11 +391,11 @@ t_stat baci_detach (UNIT *uptr);
|
||||
baci_deb BACI debug list
|
||||
baci_dev BACI device descriptor
|
||||
|
||||
Two units are used: one to handle character I/O via the multiplexer library,
|
||||
and another to poll for connections and input. The character I/O service
|
||||
routine runs only when there are characters to read or write. It operates at
|
||||
the approximate baud rate of the terminal (in CPU instructions per second) in
|
||||
order to be compatible with the OS drivers. The line poll must run
|
||||
Two units are used: one to handle character I/O via the Telnet library, and
|
||||
another to poll for connections and input. The character I/O service routine
|
||||
runs only when there are characters to read or write. It operates at the
|
||||
approximate baud rate of the terminal (in CPU instructions per second) in
|
||||
order to be compatible with the OS drivers. The Telnet poll must run
|
||||
continuously, but it can operate much more slowly, as the only requirement is
|
||||
that it must not present a perceptible lag to human input. To be compatible
|
||||
with CPU idling, it is co-scheduled with the master poll timer, which uses a
|
||||
@@ -406,14 +404,14 @@ t_stat baci_detach (UNIT *uptr);
|
||||
|
||||
DEVICE baci_dev;
|
||||
|
||||
TMLN baci_ldsc = { 0 }; /* line descriptor */
|
||||
TMXR baci_desc = { 1, 0, 0, &baci_ldsc, NULL, &baci_dev }; /* device descriptor */
|
||||
TMLN baci_ldsc = { 0 }; /* line descriptor */
|
||||
TMXR baci_desc = { 1, 0, 0, &baci_ldsc }; /* device descriptor */
|
||||
|
||||
DIB baci_dib = { &baci_io, BACI, 0 };
|
||||
|
||||
UNIT baci_unit[] = {
|
||||
{ UDATA (&baci_term_svc, UNIT_ATTABLE | UNIT_FASTTIME, 0) }, /* terminal I/O unit */
|
||||
{ UDATA (&baci_poll_svc, UNIT_DIS, POLL_FIRST) } /* line poll unit */
|
||||
{ UDATA (&baci_poll_svc, UNIT_DIS, POLL_FIRST) } /* Telnet poll unit */
|
||||
};
|
||||
|
||||
REG baci_reg[] = {
|
||||
@@ -771,7 +769,7 @@ return stat_data;
|
||||
The terminal service routine is used to transmit and receive characters.
|
||||
|
||||
In terminal mode, it is started when a character is ready for output or when
|
||||
the line poll routine determines that there are characters ready for input
|
||||
the Telnet poll routine determines that there are characters ready for input
|
||||
and stopped when there are no more characters to output or input. When the
|
||||
terminal is quiescent, this routine does not run.
|
||||
|
||||
@@ -811,11 +809,11 @@ return stat_data;
|
||||
first character after an ENQ is not an ACK.
|
||||
|
||||
Finally, fast timing enables buffer combining. For output, all characters
|
||||
present in the FIFO are unloaded into the line buffer before initiating a
|
||||
packet send. For input, all characters present in the line buffer are loaded
|
||||
into the FIFO. This reduces network traffic and decreases simulator overhead
|
||||
(there is only one service routine entry per block, rather than one per
|
||||
character).
|
||||
present in the FIFO are unloaded into the Telnet buffer before initiating a
|
||||
packet send. For input, all characters present in the Telnet buffer are
|
||||
loaded into the FIFO. This reduces network traffic and decreases simulator
|
||||
overhead (there is only one service routine entry per block, rather than one
|
||||
per character).
|
||||
|
||||
In fast output mode, it is imperative that not less than 1500 instructions
|
||||
elapse between the first character load to the FIFO and the initiation of
|
||||
@@ -978,11 +976,12 @@ return status;
|
||||
}
|
||||
|
||||
|
||||
/* BACI line poll service.
|
||||
/* BACI Telnet poll service.
|
||||
|
||||
This service routine is used to poll for connections and incoming characters.
|
||||
If characters are available, the terminal I/O service routine is scheduled.
|
||||
It starts when the line is attached and stops when the line is detached.
|
||||
This service routine is used to poll for Telnet connections and incoming
|
||||
characters. If characters are available, the terminal I/O service routine is
|
||||
scheduled. It starts when the socket is attached and stops when the socket
|
||||
is detached.
|
||||
|
||||
As there is only one line, we only poll for a new connection when the line is
|
||||
disconnected.
|
||||
@@ -1029,57 +1028,42 @@ baci_term.wait = service_time (baci_icw); /* set terminal I/O time
|
||||
|
||||
if (baci_term.flags & UNIT_ATT) { /* device attached? */
|
||||
baci_poll.wait = POLL_FIRST; /* set up poll */
|
||||
sim_activate (&baci_poll, baci_poll.wait); /* start line poll immediately */
|
||||
sim_activate (&baci_poll, baci_poll.wait); /* start Telnet poll immediately */
|
||||
}
|
||||
else
|
||||
sim_cancel (&baci_poll); /* else stop line poll */
|
||||
sim_cancel (&baci_poll); /* else stop Telnet poll */
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Attach line */
|
||||
/* Attach controller */
|
||||
|
||||
t_stat baci_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
t_stat status = SCPE_OK;
|
||||
|
||||
if (uptr->flags & UNIT_DIS) /* unit disabled? */
|
||||
return SCPE_UDIS; /* report it */
|
||||
status = tmxr_attach (&baci_desc, uptr, cptr); /* attach to socket */
|
||||
|
||||
status = tmxr_attach (&baci_desc, uptr, cptr); /* try to attach to socket */
|
||||
|
||||
if (status == SCPE_ARG) /* invalid numeric port supplied? */
|
||||
status = tmxr_attach_line (uptr, 0, cptr, &baci_desc); /* try to attach to serial port */
|
||||
|
||||
if (status == SCPE_OK) { /* attach successful? */
|
||||
baci_poll.wait = POLL_FIRST; /* set up poll */
|
||||
sim_activate (&baci_poll, baci_poll.wait); /* start line poll immediately */
|
||||
if (status == SCPE_OK) {
|
||||
baci_poll.wait = POLL_FIRST; /* set up poll */
|
||||
sim_activate (&baci_poll, baci_poll.wait); /* start Telnet poll immediately */
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* Detach line */
|
||||
/* Detach controller */
|
||||
|
||||
t_stat baci_detach (UNIT *uptr)
|
||||
{
|
||||
t_stat status;
|
||||
|
||||
if (uptr->flags & UNIT_DIS) /* unit disabled? */
|
||||
return SCPE_UDIS; /* report it */
|
||||
|
||||
status = tmxr_detach_line (uptr, 0, NULL, &baci_desc); /* attempt to detach serial line */
|
||||
|
||||
if (status == SCPE_UNATT) /* not attached to serial? */
|
||||
status = tmxr_detach (&baci_desc, uptr); /* attempt to detach listening socket */
|
||||
|
||||
status = tmxr_detach (&baci_desc, uptr); /* detach socket */
|
||||
baci_ldsc.rcve = 0; /* disable line reception */
|
||||
sim_cancel (&baci_poll); /* stop line poll */
|
||||
sim_cancel (&baci_poll); /* stop Telnet poll */
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* Local routines */
|
||||
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
27-Oct-10 JDB Revised I/O signal enum values for concurrent signals
|
||||
Revised I/O macros for new signal handling
|
||||
09-Oct-10 JDB Added DA and DC device select code assignments
|
||||
21-Oct-08 JDB [serial] Added "sim_unit_ref" external
|
||||
07-Sep-08 JDB Added POLL_FIRST to indicate immediate connection attempt
|
||||
15-Jul-08 JDB Rearranged declarations with hp2100_cpu.h
|
||||
26-Jun-08 JDB Rewrote device I/O to model backplane signals
|
||||
@@ -457,11 +456,10 @@ extern uint32 dev_prl [2], dev_irq [2], dev_srq [2]; /* I/O signal vectors */
|
||||
|
||||
/* Simulator state */
|
||||
|
||||
extern FILE *sim_deb;
|
||||
extern FILE *sim_log;
|
||||
extern int32 sim_step;
|
||||
extern int32 sim_switches;
|
||||
extern UNITREF sim_unit_ref;
|
||||
extern FILE *sim_deb;
|
||||
extern FILE *sim_log;
|
||||
extern int32 sim_step;
|
||||
extern int32 sim_switches;
|
||||
|
||||
/* CPU functions */
|
||||
|
||||
|
||||
@@ -29,9 +29,7 @@
|
||||
28-Mar-11 JDB Tidied up signal handling
|
||||
26-Oct-10 JDB Changed I/O signal handler for revised signal model
|
||||
25-Nov-08 JDB Revised for new multiplexer library SHOW routines
|
||||
19-Nov-08 JDB [serial] Removed DEV_NET to allow restoration of listening port
|
||||
14-Nov-08 JDB Cleaned up VC++ size mismatch warnings for zero assignments
|
||||
20-Oct-08 JDB [serial] Added serial port support
|
||||
03-Oct-08 JDB Fixed logic for ENQ/XOFF transmit wait
|
||||
07-Sep-08 JDB Changed Telnet poll to connect immediately after reset or attach
|
||||
10-Aug-08 JDB Added REG_FIT to register variables < 32-bit size
|
||||
@@ -59,8 +57,8 @@
|
||||
character editing, echoing, ENQ/ACK handshaking, and read terminator
|
||||
detection, substantially reducing the load on the CPU over the earlier 12920
|
||||
multiplexer. It was supported by HP under RTE-MIII, RTE-IVB, and RTE-6/VM.
|
||||
Under simulation, it connects with HP terminal emulators via Telnet or serial
|
||||
ports.
|
||||
Under simulation, it connects with HP terminal emulators via Telnet to a
|
||||
user-specified port.
|
||||
|
||||
The single interface card contained a Z80 CPU, DMA controller, CTC, four
|
||||
two-channel SIO UARTs, 16K of RAM, 8K of ROM, and I/O backplane latches and
|
||||
@@ -201,7 +199,7 @@
|
||||
#define MPX_CNTLS 2 /* number of control units */
|
||||
|
||||
#define mpx_cntl (mpx_unit [MPX_PORTS + 0]) /* controller unit */
|
||||
#define mpx_poll (mpx_unit [MPX_PORTS + 1]) /* polling unit */
|
||||
#define mpx_poll (mpx_unit [MPX_PORTS + 1]) /* Telnet polling unit */
|
||||
|
||||
|
||||
/* Character constants */
|
||||
@@ -613,16 +611,16 @@ t_stat mpx_show_frev (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
mpx_dev MPX device descriptor
|
||||
|
||||
The first eight units correspond to the eight multiplexer line ports. These
|
||||
handle character I/O via the multiplexer library. A ninth unit acts as the
|
||||
card controller, executing commands and transferring data to and from the I/O
|
||||
buffers. A tenth unit is responsible for polling for connections and line
|
||||
I/O. It also holds the master socket for Telnet connections.
|
||||
handle character I/O via the Telnet library. A ninth unit acts as the card
|
||||
controller, executing commands and transferring data to and from the I/O
|
||||
buffers. A tenth unit is responsible for polling for connections and socket
|
||||
I/O. It also holds the master socket.
|
||||
|
||||
The character I/O service routines run only when there are characters to read
|
||||
or write. They operate at the approximate baud rates of the terminals (in
|
||||
CPU instructions per second) in order to be compatible with the OS drivers.
|
||||
The controller service routine runs only when a command is executing or a
|
||||
data transfer to or from the CPU is in progress. The poll service must run
|
||||
data transfer to or from the CPU is in progress. The Telnet poll must run
|
||||
continuously, but it may operate much more slowly, as the only requirement is
|
||||
that it must not present a perceptible lag to human input. To be compatible
|
||||
with CPU idling, it is co-scheduled with the master poll timer, which uses a
|
||||
@@ -634,9 +632,9 @@ t_stat mpx_show_frev (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
|
||||
DEVICE mpx_dev;
|
||||
|
||||
int32 mpx_order [MPX_PORTS] = { -1 }; /* connection order */
|
||||
TMLN mpx_ldsc [MPX_PORTS] = { { 0 } }; /* line descriptors */
|
||||
TMXR mpx_desc = { MPX_PORTS, 0, 0, mpx_ldsc, mpx_order, &mpx_dev }; /* device descriptor */
|
||||
int32 mpx_order [MPX_PORTS] = { -1 }; /* connection order */
|
||||
TMLN mpx_ldsc [MPX_PORTS] = { { 0 } }; /* line descriptors */
|
||||
TMXR mpx_desc = { MPX_PORTS, 0, 0, mpx_ldsc, mpx_order }; /* device descriptor */
|
||||
|
||||
DIB mpx_dib = { &mpx_io, MPX };
|
||||
|
||||
@@ -650,7 +648,7 @@ UNIT mpx_unit [] = {
|
||||
{ UDATA (&mpx_line_svc, UNIT_FASTTIME, 0) }, /* terminal I/O line 6 */
|
||||
{ UDATA (&mpx_line_svc, UNIT_FASTTIME, 0) }, /* terminal I/O line 7 */
|
||||
{ UDATA (&mpx_cntl_svc, UNIT_DIS, 0) }, /* controller unit */
|
||||
{ UDATA (&mpx_poll_svc, UNIT_ATTABLE | UNIT_DIS, POLL_FIRST) } /* line poll unit */
|
||||
{ UDATA (&mpx_poll_svc, UNIT_ATTABLE | UNIT_DIS, POLL_FIRST) } /* Telnet poll unit */
|
||||
};
|
||||
|
||||
REG mpx_reg [] = {
|
||||
@@ -1604,20 +1602,21 @@ return SCPE_OK;
|
||||
/* Multiplexer line service.
|
||||
|
||||
The line service routine is used to transmit and receive characters. It is
|
||||
started when a buffer is ready for output or when the poll service routine
|
||||
started when a buffer is ready for output or when the Telnet poll routine
|
||||
determines that there are characters ready for input, and it is stopped when
|
||||
there are no more characters to output or input. When a line is quiescent,
|
||||
this routine does not run. Service times are selected to approximate the
|
||||
baud rate setting of the multiplexer port.
|
||||
|
||||
"Fast timing" mode enables three optimizations. First, buffered characters
|
||||
are transferred in blocks, rather than a character at a time; this reduces
|
||||
line traffic and decreases simulator overhead (there is only one service
|
||||
routine entry per block, rather than one per character). Second, ENQ/ACK
|
||||
handshaking is done locally, without involving the client. Third, when
|
||||
editing and echo is enabled, entering BS echoes a backspace, a space, and a
|
||||
backspace, and entering DEL echoes a backslash, a carriage return, and a line
|
||||
feed, providing better compatibility with prior RTE terminal drivers.
|
||||
are transferred via Telnet in blocks, rather than a character at a time; this
|
||||
reduces network traffic and decreases simulator overhead (there is only one
|
||||
service routine entry per block, rather than one per character). Second,
|
||||
ENQ/ACK handshaking is done locally, without involving the Telnet client.
|
||||
Third, when editing and echo is enabled, entering BS echoes a backspace, a
|
||||
space, and a backspace, and entering DEL echoes a backslash, a carriage
|
||||
return, and a line feed, providing better compatibility with prior RTE
|
||||
terminal drivers.
|
||||
|
||||
Each read and write buffer begins with a reserved header byte that stores
|
||||
per-buffer information, such as whether handshaking should be suppressed
|
||||
@@ -1631,7 +1630,7 @@ return SCPE_OK;
|
||||
write buffer is freed, and a UI check is made if the controller is idle, in
|
||||
case a write buffer request is pending.
|
||||
|
||||
For input, the character is retrieved from the line buffer. If a BREAK was
|
||||
For input, the character is retrieved from the Telnet buffer. If a BREAK was
|
||||
received, break status is set, and the character is discarded (the current
|
||||
multiplexer library implementation always returns a NUL with a BREAK
|
||||
indication). If the character is an XOFF, and XON/XOFF pacing is enabled, a
|
||||
@@ -1940,11 +1939,11 @@ return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Poll service.
|
||||
/* Telnet poll service.
|
||||
|
||||
This service routine is used to poll for connections and incoming characters.
|
||||
It is started when the listening socket or a serial line is attached and is
|
||||
stopped when the socket and all lines are detached.
|
||||
This service routine is used to poll for Telnet connections and incoming
|
||||
characters. It starts when the socket is attached and stops when the socket
|
||||
is detached.
|
||||
|
||||
Each line is then checked for a pending ENQ/ACK handshake. If one is
|
||||
pending, the ACK counter is incremented, and if it times out, another ENQ is
|
||||
@@ -2008,10 +2007,10 @@ return SCPE_OK;
|
||||
1. Under simulation, we also clear the input buffer register, even though
|
||||
the hardware doesn't.
|
||||
|
||||
2. We set up the first poll for connections to occur "immediately" upon
|
||||
execution, so that clients will be connected before execution begins.
|
||||
Otherwise, a fast program may access the multiplexer before the poll
|
||||
service routine activates.
|
||||
2. We set up the first poll for Telnet connections to occur "immediately"
|
||||
upon execution, so that clients will be connected before execution
|
||||
begins. Otherwise, a fast program may access the multiplexer before the
|
||||
poll service routine activates.
|
||||
|
||||
3. We must set the "emptying_flags" and "filling_flags" values here, because
|
||||
they cannot be initialized statically, even though the values are
|
||||
@@ -2031,129 +2030,83 @@ IOPRESET (&mpx_dib); /* PRESET device (does n
|
||||
|
||||
mpx_ibuf = 0; /* clear input buffer */
|
||||
|
||||
if (tmxr_mux_free (&mpx_desc)) /* any lines attached? */
|
||||
sim_cancel (&mpx_poll); /* no, so stop poll */
|
||||
else { /* attached or listening */
|
||||
if (mpx_poll.flags & UNIT_ATT) { /* network attached? */
|
||||
mpx_poll.wait = POLL_FIRST; /* set up poll */
|
||||
sim_activate (&mpx_poll, mpx_poll.wait); /* start poll immediately */
|
||||
sim_activate (&mpx_poll, mpx_poll.wait); /* start Telnet poll immediately */
|
||||
}
|
||||
else
|
||||
sim_cancel (&mpx_poll); /* else stop Telnet poll */
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Attach the multiplexer or a line.
|
||||
/* Attach the multiplexer to a Telnet port.
|
||||
|
||||
We are called by the ATTACH MPX <port> command to attach the multiplexer to
|
||||
the listening port indicated by <port> and by ATTACH MPX<n> <ser> to attach
|
||||
line <n> to serial port <ser>. Logically, it is the multiplexer device that
|
||||
is attached; however, SIMH only allows units to be attached. This makes
|
||||
sense for devices such as tape drives, where the attached media is a property
|
||||
of a specific drive. In our case, though, the listening port is a property
|
||||
of the multiplexer card, not of any given serial line.
|
||||
the listening port indicated by <port>. Logically, it is the multiplexer
|
||||
device that is attached; however, SIMH only allows units to be attached.
|
||||
This makes sense for devices such as tape drives, where the attached media is
|
||||
a property of a specific drive. In our case, though, the listening port is a
|
||||
property of the multiplexer card, not of any given serial line. As ATTACH
|
||||
MPX is equivalent to ATTACH MPX0, the port would, by default, be attached to
|
||||
the first serial line and be reported there in a SHOW MPX command.
|
||||
|
||||
To preserve the logical picture, we attach the listening port to the poll
|
||||
unit (unit 9), which is normally disabled to inhibit its display. Serial
|
||||
ports are attached to line units 0-7 normally. Attachment is reported by the
|
||||
"mpx_status" routine below.
|
||||
To preserve the logical picture, we attach the port to the Telnet poll unit,
|
||||
which is normally disabled to inhibit its display. Attaching to a disabled
|
||||
unit is not allowed, so we first enable the unit, then attach it, then
|
||||
disable it again. Attachment is reported by the "mpx_status" routine below.
|
||||
|
||||
The connection poll service routine is synchronized with the other input
|
||||
polling devices in the simulator to facilitate idling.
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. ATTACH MPX will pass a pointer unit 0. This is because the common
|
||||
simulator code treats ATTACH MPX as equivalent to ATTACH MPX0. We
|
||||
differentiate these cases by examining the "sim_unit_ref" global to see
|
||||
if a device was referenced.
|
||||
|
||||
2. Directly attempting to attach to units 8 (controller) or 9 (poll) will be
|
||||
rejected.
|
||||
|
||||
3. If we are being called as part of RESTORE processing, we may see a
|
||||
request to attach the poll unit (unit 9). This will occur if unit 9 was
|
||||
attached when the SAVE was done. In this case, the SIM_SW_REST flag will
|
||||
be set in "sim_switches", and we will allow the call to succeed.
|
||||
|
||||
4. If the poll unit is attached, it will be enabled as part of RESTORE
|
||||
processing. We always unilaterally disable this unit to ensure that it
|
||||
remains hidden.
|
||||
The Telnet poll service routine is synchronized with the other input polling
|
||||
devices in the simulator to facilitate idling.
|
||||
*/
|
||||
|
||||
t_stat mpx_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
t_stat status = SCPE_OK;
|
||||
|
||||
if ((uptr == &mpx_cntl) || /* attaching controller? */
|
||||
(uptr == &mpx_poll) && !(sim_switches & SIM_SW_REST)) /* or poll unit directly? */
|
||||
return SCPE_NOATT; /* disallow */
|
||||
if (uptr != mpx_unit) /* not unit 0? */
|
||||
return SCPE_NOATT; /* can't attach */
|
||||
|
||||
if (sim_unit_ref == ref_dev || (uptr == &mpx_poll)) { /* device attach or poll restore request? */
|
||||
status = tmxr_attach (&mpx_desc, &mpx_poll, cptr); /* attach to socket */
|
||||
mpx_poll.flags = mpx_poll.flags | UNIT_DIS; /* disable unit */
|
||||
}
|
||||
|
||||
else /* line attach request */
|
||||
status = tmxr_attach_line (uptr, 0, cptr, &mpx_desc); /* attach line */
|
||||
mpx_poll.flags = mpx_poll.flags & ~UNIT_DIS; /* enable unit */
|
||||
status = tmxr_attach (&mpx_desc, &mpx_poll, cptr); /* attach to socket */
|
||||
mpx_poll.flags = mpx_poll.flags | UNIT_DIS; /* disable unit */
|
||||
|
||||
if (status == SCPE_OK) {
|
||||
mpx_poll.wait = POLL_FIRST; /* set up poll */
|
||||
sim_activate (&mpx_poll, mpx_poll.wait); /* start poll immediately */
|
||||
mpx_poll.wait = POLL_FIRST; /* set up poll */
|
||||
sim_activate (&mpx_poll, mpx_poll.wait); /* start poll immediately */
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* Detach the multiplexer or a line.
|
||||
/* Detach the multiplexer.
|
||||
|
||||
We are called by the DETACH MPX command to detach the listening port and all
|
||||
Telnet sessions and by the DETACH MPX<n> to detach a serial port from line
|
||||
<n>. We will also be called by DETACH ALL, RESTORE, and during simulator
|
||||
shutdown. For DETACH ALL and RESTORE, we must not fail the call, or
|
||||
processing of other units will cease.
|
||||
|
||||
Implementation notes:
|
||||
Normally, we are called by the DETACH MPX command, which is equivalent to
|
||||
DETACH MPX0. However, we may be called with other units in two cases.
|
||||
|
||||
1. Because DETACH MPX will pass unit 0, we check the "sim_unit_ref" global
|
||||
to see if MPX or MPX0 was specified in the command.
|
||||
|
||||
2. Directly attempting to detach unit 8 (controller) will be rejected. We
|
||||
cannot fail a direct DETACH MPX9 (poll unit), because we cannot tell that
|
||||
case apart from a DETACH ALL (a RESTORE will have the SIM_SW_REST flag
|
||||
set in "sim_switches").
|
||||
|
||||
3. During simulator shutdown, we will be called for units 0-8 (detach_all in
|
||||
scp.c calls the detach routines of all units that do NOT have
|
||||
UNIT_ATTABLE), as well as for unit 9 if it is attached.
|
||||
A DETACH ALL command will call us for unit 9 (the poll unit) if it is
|
||||
attached. Also, during simulator shutdown, we will be called for units 0-8
|
||||
(detach_all in scp.c calls the detach routines of all units that do NOT have
|
||||
UNIT_ATTABLE), as well as for unit 9 if it is attached. In both cases, it is
|
||||
imperative that we return SCPE_OK, otherwise any remaining device detaches
|
||||
will not be performed.
|
||||
*/
|
||||
|
||||
t_stat mpx_detach (UNIT *uptr)
|
||||
{
|
||||
uint32 ln;
|
||||
t_stat status;
|
||||
t_bool mux_free = TRUE;
|
||||
t_stat status = SCPE_OK;
|
||||
int32 i;
|
||||
|
||||
if (uptr == &mpx_cntl) /* detaching controller directly? */
|
||||
return SCPE_NOATT; /* disallow */
|
||||
if ((uptr == mpx_unit) || (uptr == &mpx_poll)) { /* base unit or poll unit? */
|
||||
status = tmxr_detach (&mpx_desc, &mpx_poll); /* detach socket */
|
||||
|
||||
if (sim_unit_ref == ref_dev || uptr == &mpx_poll) /* device detach or detach all request? */
|
||||
status = tmxr_detach (&mpx_desc, &mpx_poll); /* detach socket */
|
||||
for (i = 0; i < MPX_PORTS; i++) {
|
||||
mpx_ldsc [i].rcve = 0; /* disable line reception */
|
||||
sim_cancel (&mpx_unit [i]); /* cancel any scheduled I/O */
|
||||
}
|
||||
|
||||
else /* line detach request */
|
||||
status = tmxr_detach_line (uptr, 0, NULL, &mpx_desc); /* detach line */
|
||||
|
||||
if (status == SCPE_OK) {
|
||||
for (ln = 0; ln < MPX_PORTS; ln++) /* loop through lines */
|
||||
if (tmxr_line_free (&mpx_ldsc[ln])) { /* is line free? */
|
||||
mpx_ldsc[ln].rcve = 0; /* disable rcv as line was reset */
|
||||
sim_cancel (&mpx_unit [ln]); /* cancel any scheduled I/O */
|
||||
}
|
||||
|
||||
else
|
||||
mux_free = FALSE; /* mux isn't free if line is in use */
|
||||
|
||||
if (mux_free && !(mpx_poll.flags & UNIT_ATT)) /* all lines free and not listening? */
|
||||
sim_cancel (&mpx_poll); /* stop poll */
|
||||
sim_cancel (&mpx_poll); /* stop Telnet poll */
|
||||
}
|
||||
|
||||
return status;
|
||||
@@ -2214,7 +2167,7 @@ return SCPE_OK;
|
||||
/* Local routines */
|
||||
|
||||
|
||||
/* Poll for new connections */
|
||||
/* Poll for new Telnet connections */
|
||||
|
||||
static void poll_connection (void)
|
||||
{
|
||||
|
||||
@@ -29,8 +29,6 @@
|
||||
28-Mar-11 JDB Tidied up signal handling
|
||||
26-Oct-10 JDB Changed I/O signal handler for revised signal model
|
||||
25-Nov-08 JDB Revised for new multiplexer library SHOW routines
|
||||
19-Nov-08 JDB [serial] Removed DEV_NET to allow restoration of listening port
|
||||
20-Oct-08 JDB [serial] Added serial port support
|
||||
09-Oct-08 JDB "muxl_unit" defined one too many units (17 instead of 16)
|
||||
10-Sep-08 JDB SHOW MUX CONN/STAT with SET MUX DIAG is no longer disallowed
|
||||
07-Sep-08 JDB Changed Telnet poll to connect immediately after reset or attach
|
||||
@@ -329,7 +327,6 @@ t_stat muxo_svc (UNIT *uptr);
|
||||
t_stat muxc_reset (DEVICE *dptr);
|
||||
t_stat mux_attach (UNIT *uptr, char *cptr);
|
||||
t_stat mux_detach (UNIT *uptr);
|
||||
t_stat muxl_detach (UNIT *uptr);
|
||||
t_stat mux_setdiag (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
|
||||
|
||||
@@ -433,8 +430,8 @@ DEVICE muxl_dev = {
|
||||
NULL, /* deposit routine */
|
||||
&muxc_reset, /* reset routine */
|
||||
NULL, /* boot routine */
|
||||
&mux_attach, /* attach routine */
|
||||
&muxl_detach, /* detach routine */
|
||||
NULL, /* attach routine */
|
||||
NULL, /* detach routine */
|
||||
&muxl_dib, /* device information block */
|
||||
DEV_DISABLE, /* device flags */
|
||||
0, /* debug control flags */
|
||||
@@ -459,9 +456,9 @@ DEVICE muxl_dev = {
|
||||
|
||||
DEVICE muxu_dev;
|
||||
|
||||
int32 mux_order [MUX_LINES] = { -1 }; /* connection order */
|
||||
TMLN mux_ldsc [MUX_LINES] = { { 0 } }; /* line descriptors */
|
||||
TMXR mux_desc = { MUX_LINES, 0, 0, mux_ldsc, mux_order, &muxu_dev }; /* device descriptor */
|
||||
int32 mux_order [MUX_LINES] = { -1 }; /* connection order */
|
||||
TMLN mux_ldsc [MUX_LINES] = { { 0 } }; /* line descriptors */
|
||||
TMXR mux_desc = { MUX_LINES, 0, 0, mux_ldsc, mux_order }; /* device descriptor */
|
||||
|
||||
UNIT muxu_unit = { UDATA (&muxi_svc, UNIT_ATTABLE, 0), POLL_FIRST };
|
||||
|
||||
@@ -923,7 +920,7 @@ while (working_set) {
|
||||
(old & DTR) && /* DTR drop? */
|
||||
!(muxc_ota[ln] & DTR)) {
|
||||
tmxr_linemsg (&mux_ldsc[ln], "\r\nLine hangup\r\n");
|
||||
tmxr_clear_ln (&mux_desc, &mux_ldsc[ln]); /* disconnect line */
|
||||
tmxr_reset_ln (&mux_ldsc[ln]); /* reset line */
|
||||
muxc_lia[ln] = 0; /* dataset off */
|
||||
}
|
||||
} /* end update */
|
||||
@@ -1308,12 +1305,12 @@ IOPRESET (dibptr); /* PRESET device (does n
|
||||
|
||||
muxc_chan = muxc_scan = 0; /* init modem scan */
|
||||
|
||||
if (tmxr_mux_free (&mux_desc)) /* any lines attached? */
|
||||
sim_cancel (&muxu_unit); /* no, so stop poll */
|
||||
else { /* attached or listening */
|
||||
if (muxu_unit.flags & UNIT_ATT) { /* master att? */
|
||||
muxu_unit.wait = POLL_FIRST; /* set up poll */
|
||||
sim_activate (&muxu_unit, muxu_unit.wait); /* start poll immediately */
|
||||
sim_activate (&muxu_unit, muxu_unit.wait); /* start Telnet poll immediately */
|
||||
}
|
||||
else
|
||||
sim_cancel (&muxu_unit); /* else stop */
|
||||
|
||||
for (i = 0; i < MUX_LINES; i++)
|
||||
mux_reset_ln (i); /* reset lines 0-15 */
|
||||
@@ -1325,23 +1322,20 @@ return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Attach master unit or line */
|
||||
/* Attach master unit */
|
||||
|
||||
t_stat mux_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
t_stat status = SCPE_OK;
|
||||
|
||||
if (muxu_unit.flags & UNIT_DIAG) /* diag mode? */
|
||||
return SCPE_NOFNC; /* command not allowed */
|
||||
if (muxu_unit.flags & UNIT_DIAG) /* diag mode? */
|
||||
return SCPE_NOFNC; /* command not allowed */
|
||||
|
||||
if (uptr == &muxu_unit) /* master unit? */
|
||||
status = tmxr_attach (&mux_desc, uptr, cptr); /* attach socket */
|
||||
else
|
||||
status = tmxr_attach_line (uptr, 0, cptr, &mux_desc); /* attach line */
|
||||
status = tmxr_attach (&mux_desc, uptr, cptr); /* attach */
|
||||
|
||||
if (status == SCPE_OK) { /* attach successful? */
|
||||
muxu_unit.wait = POLL_FIRST; /* set up poll */
|
||||
sim_activate (&muxu_unit, muxu_unit.wait); /* start poll immediately */
|
||||
if (status == SCPE_OK) {
|
||||
muxu_unit.wait = POLL_FIRST; /* set up poll */
|
||||
sim_activate (&muxu_unit, muxu_unit.wait); /* start Telnet poll immediately */
|
||||
}
|
||||
|
||||
return status;
|
||||
@@ -1352,45 +1346,13 @@ return status;
|
||||
|
||||
t_stat mux_detach (UNIT *uptr)
|
||||
{
|
||||
uint32 ln;
|
||||
t_stat status;
|
||||
t_bool free = TRUE;
|
||||
int32 i;
|
||||
t_stat r;
|
||||
|
||||
status = tmxr_detach (&mux_desc, uptr); /* detach unit */
|
||||
|
||||
if (status == SCPE_OK) {
|
||||
for (ln = 0; ln < MUX_LINES; ln++) /* loop through lines */
|
||||
if (tmxr_line_free (&mux_ldsc[ln])) /* is line free? */
|
||||
mux_ldsc[ln].rcve = 0; /* yes, so disable rcv as line was reset */
|
||||
else
|
||||
free = FALSE; /* mux isn't free if line is in use */
|
||||
|
||||
if (free) /* all lines free? */
|
||||
sim_cancel (uptr); /* stop poll */
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* Detach line */
|
||||
|
||||
t_stat muxl_detach (UNIT *uptr)
|
||||
{
|
||||
uint32 ln;
|
||||
t_stat status;
|
||||
|
||||
status = tmxr_detach_line (uptr, 0, NULL, &mux_desc); /* detach line */
|
||||
|
||||
if (status == SCPE_OK) {
|
||||
ln = uptr - muxl_unit; /* determine line number */
|
||||
mux_ldsc[ln].rcve = 0; /* disable line reception */
|
||||
|
||||
if (tmxr_mux_free (&mux_desc)) /* all lines free and not listening? */
|
||||
sim_cancel (&muxu_unit); /* stop poll */
|
||||
}
|
||||
|
||||
return status;
|
||||
r = tmxr_detach (&mux_desc, uptr); /* detach */
|
||||
for (i = 0; i < MUX_LINES; i++) mux_ldsc[i].rcve = 0; /* disable rcv */
|
||||
sim_cancel (uptr); /* stop poll */
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
@@ -1405,7 +1367,7 @@ return status;
|
||||
for normal character transfers, which is undesirable.
|
||||
|
||||
Therefore, to enable diagnostic mode, we must force a disconnect of the
|
||||
master socket and all Telnet and serial lines, which clears the connection
|
||||
master socket and any connected Telnet lines, which clears the connection
|
||||
flags on all lines. Then we set the "transmission enabled" flags on all
|
||||
lines to enable output character processing for the diagnostic. (Normally,
|
||||
all of the flags are set when the multiplexer is first attached. Until then,
|
||||
@@ -1418,12 +1380,9 @@ t_stat mux_setdiag (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
int32 ln;
|
||||
|
||||
if (val) { /* set diag? */
|
||||
mux_detach (uptr); /* detach Telnet lines */
|
||||
|
||||
for (ln = 0; ln < MUX_LINES; ln++) {
|
||||
muxl_detach (&muxl_unit[ln]); /* detach all serial lines */
|
||||
mux_ldsc[ln].xmte = 1; /* enable transmission on all lines */
|
||||
}
|
||||
mux_detach (uptr); /* detach lines */
|
||||
for (ln = 0; ln < MUX_LINES; ln++) /* enable transmission */
|
||||
mux_ldsc[ln].xmte = 1; /* on all lines */
|
||||
}
|
||||
else { /* set term */
|
||||
for (ln = 0; ln < MUX_LINES; ln++) /* clear connections */
|
||||
|
||||
Reference in New Issue
Block a user