1 /* hp2100_mpx.c: HP 12792C 8-Channel Asynchronous Multiplexer simulator
2 
3    Copyright (c) 2008-2021, J. David Bryan
4 
5    Permission is hereby granted, free of charge, to any person obtaining a
6    copy of this software and associated documentation files (the "Software"),
7    to deal in the Software without restriction, including without limitation
8    the rights to use, copy, modify, merge, publish, distribute, sublicense,
9    and/or sell copies of the Software, and to permit persons to whom the
10    Software is furnished to do so, subject to the following conditions:
11 
12    The above copyright notice and this permission notice shall be included in
13    all copies or substantial portions of the Software.
14 
15    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18    THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19    IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20    CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 
22    Except as contained in this notice, the name of the author shall not be
23    used in advertising or otherwise to promote the sale, use or other dealings
24    in this Software without prior written authorization from the author.
25 
26    MPX          12792C 8-Channel Asynchronous Multiplexer
27 
28    01-Apr-21    JDB     Removed REG_FIT from register definitions (obsolete)
29    07-Feb-21    JDB     Changed buffer register macros from BRDATA to CRDATA
30    31-Dec-20    JDB     Added CNTLR_OPCODE, map_opcode declarations
31                         Changed uint16 uses to uint32 or HP_WORD
32    26-Dec-20    JDB     Added LOCALACK/REMOTEACK unit option
33                         Moved REALTIME/FASTTIME to device option
34                         FASTTIME now uses fast controller times
35                         Added FASTTIME variables to the register list
36                         Poll for ACK after ENQ is now adaptive
37    09-Dec-20    JDB     Replaced "io_assert" with "io_assert_ENF"
38    02-Dec-20    JDB     RESET no longer presets the interface
39    28-Mar-19    JDB     Revised for serial port support
40                         Moved SET DISCONNECT command from device to unit
41    18-Mar-19    JDB     Reordered SCP includes
42    23-Jan-19    JDB     Removed DEV_MUX to avoid TMXR debug flags
43    10-Jul-18    JDB     Revised I/O model
44    01-Nov-17    JDB     Fixed serial output buffer overflow handling
45    26-Jul-17    JDB     Changed BITFIELD macros to field constructors
46    22-Apr-17    JDB     Corrected missing compound statements
47    15-Mar-17    JDB     Trace flags are now global
48                         Changed DEBUG_PRI calls to tprintfs
49    10-Mar-17    JDB     Added IOBUS to the debug table
50    17_Jan_17    JDB     Changed "hp_---sc" and "hp_---dev" to "hp_---_dib"
51    02-Aug-16    JDB     Burst-fill only the first receive buffer in fast mode
52    28-Jul-16    JDB     Fixed buffer ready check at read completion
53                         Fixed terminate on character counts > 254
54    13-May-16    JDB     Modified for revised SCP API function parameter types
55    24-Dec-14    JDB     Added casts for explicit downward conversions
56    10-Jan-13    MP      Added DEV_MUX and additional DEVICE field values
57    28-Dec-12    JDB     Allow direct attach to the poll unit only when restoring
58    10-Feb-12    JDB     Deprecated DEVNO in favor of SC
59                         Removed DEV_NET to allow restoration of listening port
60    28-Mar-11    JDB     Tidied up signal handling
61    26-Oct-10    JDB     Changed I/O signal handler for revised signal model
62    25-Nov-08    JDB     Revised for new multiplexer library SHOW routines
63    14-Nov-08    JDB     Cleaned up VC++ size mismatch warnings for zero assignments
64    03-Oct-08    JDB     Fixed logic for ENQ/XOFF transmit wait
65    07-Sep-08    JDB     Changed Telnet poll to connect immediately after reset or attach
66    10-Aug-08    JDB     Added REG_FIT to register variables < 32-bit size
67    26-Jun-08    JDB     Rewrote device I/O to model backplane signals
68    26-May-08    JDB     Created MPX device
69 
70    References:
71      - HP 12792B 8-Channel Asynchronous Multiplexer Subsystem Installation and Reference Manual
72           (12792-90020, July 1984)
73      - HP 12792B/C 8-Channel Asynchronous Multiplexer Subsystem User's Manual
74           (5955-8867, June 1993)
75      - HP 12792B/C 8-Channel Asynchronous Multiplexer Subsystem Configuration Guide
76           (5955-8868, June 1993)
77      - HP 1000 series 8-channel Multiplexer Firmware External Reference Specification
78           (October 19, 1982)
79      - HP 12792/12040 Multiplexer Firmware Source
80           (24999-18312, revision C)
81      - Zilog Components Data Book
82           (00-2034-04, 1985)
83 
84 
85    The 12792A/B/C/D was an eight-line asynchronous serial multiplexer that
86    connected terminals, modems, serial line printers, and "black box" devices
87    that used the RS-232 standard to the CPU.  It used an on-board microprocessor
88    and provided input and output buffering to support block-mode reads from HP
89    264x and 262x terminals at speeds up to 19.2K baud.  The card handled
90    character editing, echoing, ENQ/ACK handshaking, and read terminator
91    detection, substantially reducing the load on the CPU over the earlier 12920
92    multiplexer.  It was supported by HP under RTE-MIII, RTE-IVB, and RTE-6/VM.
93    Under simulation, it connects with HP terminal emulators via Telnet or serial
94    ports.
95 
96    The single interface card contained a Z80 CPU, DMA controller, CTC, four
97    two-channel SIO UARTs, 16K of RAM, 8K of ROM, and I/O backplane latches and
98    control circuitry.  The card executed a high-level command set, and data
99    transfer to and from the CPU was via the on-board DMA controller and the DCPC
100    in the CPU.
101 
102    The 12792 for the M/E/F series and the 12040 multiplexer for the A/L series
103    differed only in backplane design.  Early ROMs were card-specific, but later
104    ones were interchangeable; the code would determine whether it was executing
105    on an MEF card or an AL card.
106 
107    Four major firmware revisions were made.  These were labelled "A", "B", "C",
108    and "D".  The A, B, and C revisions were interchangeable from the perspective
109    of the OS driver; the D was different and required an updated driver.
110    Specifically:
111 
112      Op. Sys.  Driver  Part Number           Rev
113      --------  ------  --------------------  ---
114      RTE-MIII  DVM00   12792-16002 Rev.2032   A
115      RTE-IVB   DVM00   12792-16002 Rev.5000  ABC
116 
117      RTE-6/VM  DVM00   12792-16002 Rev.5000  ABC
118      RTE-6/VM  DV800   92084-15068 Rev.6000   D
119 
120      RTE-A     IDM00   92077-16754 Rev.5020  ABC
121      RTE-A     ID800   92077-16887 Rev.6200   D
122 
123    Revisions A-C have an upward-compatible command set that partitions each OS
124    request into several sub-commands.  Each command is initiated by setting the
125    control flip-flop on the card, which causes a non-maskable interrupt (NMI) on
126    the card's Z80 processor.
127 
128    The D-revision firmware uses a completely different command set.  The
129    commands are slightly modified versions of the original EXEC calls (read,
130    write, and control) and are generally passed to the card directly for action.
131 
132    This simulation supports the C revision.  D-revision support may be added
133    later.
134 
135    Twelve programmable baud rates are supported by the multiplexer.  A device
136    mode specifies whether the multiplexer operates in real-time or optimized
137    ("fast") timing mode.  In the former, character send and receive events and
138    microprocessor actions occur at approximately the same rate (in machine
139    instructions) as in hardware.  The latter mode increases the rate to the
140    maximum values consistent with correct operation in RTE.
141 
142    Two additional improvements are implemented when the device is in fast timing
143    mode:
144 
145      1. Buffered characters are transferred in blocks.
146 
147      2. BS and DEL respond visually more like prior RTE terminal drivers.
148 
149    HP terminals required ENQ/ACK handshaking to operate reliably at speeds above
150    2400 baud.  In simulation, a unit mode specifies whether ENQ/ACK handshaking
151    is passed through to the terminal or is done locally without involving the
152    client.
153 
154    HP did not offer a functional diagnostic for the 12792.  Instead, a Z80
155    program that tested the operation of the hardware was downloaded to the card,
156    and a "go/no-go" status was returned to indicate the hardware condition.
157    Because this is a functional simulation of the multiplexer and not a Z80
158    emulation, the diagnostic cannot be used to test the implementation.
159 
160 
161    The interface responds to I/O instructions as follows.  Commands are either
162    one or two words in length.  The one-word format is:
163 
164       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
165      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
166      | 0   1 |    command opcode     |       command parameter       |
167      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
168 
169    The two-word format is:
170 
171       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
172      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
173      | 1   1 |    command opcode     |            port key           |
174      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
175      |                       command parameter                       |
176      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
177 
178    Commands are sent to the card via an OTA/B.  Issuing an STC SC,C causes the
179    mux to accept the word (STC causes a NMI on the card).  If the command uses
180    one word, command execution will commence, and the flag will set on
181    completion.  If the command uses two words, the flag will be set, indicating
182    that the second word should be output via an OTA/B.  Command execution will
183    commence upon receipt, and the flag will set on completion.
184 
185    A command consists of an opcode in the high byte, and a port key or command
186    parameter in the low byte.  Undefined commands are treated as NOPs.
187 
188    The commands implemented by firmware revision are:
189 
190      Rev  Opc  Param  Operation
191      ---  ---  -----  ------------------------------
192      ABC  100    -    No operation
193      ABC  101    -    Reset to power-on defaults
194      ABC  102    -    Enable unsolicited input
195      ABC  103    1    Disable unsolicited interrupts
196      ABC  103    2    Abort DMA transfer
197      ABC  104    -    Acknowledge
198      ABC  105   key   Cancel first receive buffer
199      ABC  106   key   Cancel all received buffers
200      ABC  107    -    Fast binary read
201 
202      -BC  140   chr   VCP put byte
203      -BC  141    -    VCP put buffer
204      -BC  142    -    VCP get byte
205      -BC  143    -    VCP get buffer
206      -BC  144    -    Exit VCP mode
207      -BC  157    -    Enter VCP mode
208 
209      Rev  Cmd  Value  Operation
210      ---  ---  -----  ------------------------------
211      ABC  300    -    No operation
212      ABC  301   key   Request write buffer
213      ABC  302   key   Write data to buffer
214      ABC  303   key   Set port key
215      ABC  304   key   Set receive type
216      ABC  305   key   Set character count
217      ABC  306   key   Set flow control
218      ABC  307   key   Read data from buffer
219      ABC  310    -    Download executable
220 
221      -BC  311   key   Connect line
222      -BC  312   key   Disconnect line
223      -BC  315   key   Get modem/port status
224      -BC  316   key   Enable/disable modem loopback
225      -BC  320   key   Terminate active receive buffer
226 
227 
228    Output Data Word formats (OTA and OTB):
229 
230       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
231      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
232      | 0   1 | 0   0   0 | 0   0   0 | 0   0   0   0   0   0   0   0 |  opcode 100
233      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
234 
235    No Operation.  This command does nothing other than set the flag.  The status
236    return value is zero.
237 
238 
239       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
240      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
241      | 0   1 | 0   0   0 | 0   0   1 | 0   0   0   0   0   0   0   0 |  opcode 101
242      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
243 
244    Reset.  This command reboots the card by branching to the power-on code, just
245    as if a hardware microprocessor reset had been done.  All mux port parameters
246    are defaulted to their power up values.
247 
248    The status return value is 100000, which indicates to the A/L-Series that the
249    card self-test is OK.
250 
251 
252       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
253      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
254      | 0   1 | 0   0   0 | 0   1   0 | 0   0   0   0   0   0   0   0 |  opcode 102
255      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
256 
257    Enable Unsolicited Interrupts.  This command enables certain multiplexer
258    conditions to generate an interrupt.  Note that this command will NOT set the
259    device flag to acknowledge the command.  Instead, the flag will set when the
260    card has an unsolicited input available for the host.
261 
262 
263       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
264      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
265      | 0   1 | 0   0   0 | 0   1   1 | 0   0   0   0   0   0   0   1 |  opcode 103.1
266      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
267 
268    Disable Unsolicited Interrupts.  This command inhibits multiplexer conditions
269    from generating an interrupt.  The status return value is zero.
270 
271 
272       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
273      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
274      | 0   1 | 0   0   0 | 0   1   1 | 0   0   0   0   0   0   1   0 |  opcode 103.2
275      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
276 
277    Abort DMA Transfer.  This command sends a RESET command (hex C3) to the DMA
278    chip, which forcibly terminates the transfer.  For a write transfer, the
279    partial buffer obtained is discarded (never sent over the serial line).  For
280    a read transfer, the remainder of the read buffer is discarded.
281 
282    The status return value is zero.
283 
284 
285       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
286      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
287      | 0   1 | 0   0   0 | 1   0   0 | 0   0   0   0   0   0   0   0 |  opcode 104
288      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
289 
290    Acknowledge.  This command acknowledges an unsolicited interrupt from the
291    card.  In response, the card supplies the second status word and sets the
292    flag.  An Acknowledge must be the only command sent in response to the first
293    status word of an unsolicited interrupt.  The mux will discard commands until
294    an Acknowledge is seen.
295 
296 
297       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
298      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
299      | 0   1 | 0   0   0 | 1   0   1 |           port key            |  opcode 105
300      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
301 
302    Cancel First Receive Buffer.  This command clears the first receive buffer
303    associated with the specified port key, e.g., in response to a timeout,
304    Control-D, etc.  The status return value is zero.
305 
306 
307       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
308      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
309      | 0   1 | 0   0   0 | 1   1   0 |           port key            |  opcode 106
310      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
311 
312    Cancel All Receive Buffers.  This command clears both pending receive
313    buffers associated with the specified port key, e.g., in response to a
314    timeout, Control-D, etc.  The status return value is zero.
315 
316 
317       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
318      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
319      | 0   1 | 0   0   0 | 1   1   1 | 0   0   0   0   0   0   0   0 |  opcode 107
320      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
321 
322    Fast Binary Read.  The card sets the flag and then sends an "ESC e" to port
323    0.  Each pair of characters presented on port 0 are sent to the host, and the
324    flag is set.  The card waits until the last pair was retrieved via an LIA/B
325    SC before sending the next pair.
326 
327    The card remains in this loop until it receives a hardware reset via CRS
328    assertion.  No status word is returned.
329 
330 
331       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
332      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
333      | 0   1 | 1   0   0 | 0   0   0 |       output character        |  opcode 140
334      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
335 
336    VCP Put Byte.  The character supplied is output to port 0, and the flag is
337    set.  The status return value is zero.
338 
339 
340       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
341      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
342      | 0   1 | 1   0   0 | 0   0   1 | 0   0   0   0   0   0   0   0 |  opcode 141
343      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
344 
345    VCP Put Buffer.  Because the VCP Put Byte command actually outputs the
346    character, rather than buffering it, this command does nothing other than set
347    the flag.  The status return value is zero.
348 
349 
350       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
351      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
352      | 0   1 | 1   0   0 | 0   1   0 | 0   0   0   0   0   0   0   0 |  opcode 142
353      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
354 
355    VCP Get Byte.  A character is read from port 0, echoed, and returned in the
356    lower byte of the status return value.  The flag is set.
357 
358 
359       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
360      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
361      | 0   1 | 1   0   0 | 0   1   1 | 0   0   0   0   0   0   0   0 |  opcode 143
362      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
363 
364    VCP Get Buffer.  The value 80, representing the buffer length, is returned in
365    the lower byte of the status return value, and the flag is set.
366 
367 
368       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
369      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
370      | 0   1 | 1   0   0 | 1   0   0 | 0   0   0   0   0   0   0   0 |  opcode 144
371      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
372 
373    Exit VCP Mode.  The card leaves VCP mode (in which all other ports are
374    frozen) and sets the flag.  The status return value is zero.
375 
376 
377       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
378      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
379      | 0   1 | 1   0   0 | 1   0   1 | 0   0   0   0   0   0   0   0 |  opcode 145
380      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
381 
382    Enter VCP Mode.  The card enters VCP mode (in which all other ports are
383    frozen) and sets the flag.  The status return value is zero.
384 
385 
386       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
387      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
388      | 1   1 | 0   0   0 | 0   0   0 |           port key            |  opcode 301
389      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
390      |                requested buffer size in bytes                 |
391      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
392 
393    Request Write Buffer.  If a write buffer is available, the status return
394    value will be the number of bytes in the buffer (fixed at 254).  If a buffer
395    is not available, the status return value will be zero, and an unsolicited
396    input will occur if enabled when a write buffer of at least the requested
397    size becomes available.
398 
399    Note that the requested size need not include space for a terminating CR/LF.
400 
401 
402       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
403      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
404      | 1   1 | 0   0   0 | 0   1   0 |           port key            |  opcode 302
405      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
406      | -   - | E | C | P |               write length                |
407      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
408 
409    Where:
410 
411      E = disable ENQ/ACK for this write only
412      C = add CR/LF if the last character is not '_'
413      P = write is a partial transfer (no CR/LF at end)
414 
415    Write Data to Buffer.  The write length specifies the number of bytes to
416    transfer into the write buffer.  If the C bit is 1, the P bit is 0, and the
417    final character is an underscore, then the underscore is not transferred.
418    Otherwise, a CR/LF is appended to the buffer.  If the P bit is 1, then this
419    transfer represents only part of the output line, so the underscore and CR/LF
420    check is not done.  A write length of zero is legal and will result in only a
421    CR/LF (if enabled).
422 
423    After the second command word is sent, the device flag will be set when the
424    card is ready for the first data word (two packed bytes).  Data is output to
425    the card via an OTA/B SC,C.  The device flag will set when the next word may
426    be sent.
427 
428    To conclude the transfer, one more word is sent to the card with an OTA/B
429    SC,C. The value is ignored.  The device flag will set to acknowledge the
430    termination.  No status word is returned.
431 
432 
433       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
434      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
435      | 1   1 | 0   0   0 | 0   0   0 |           port key            |  opcode 303
436      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
437      | bits  | M | G | stop  |  par  | E |   baud rate   | port num  |
438      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
439 
440    Where:
441 
442      M = hardwired/modem (0/1) port
443      G = port is connected to baud-rate generator 0/1
444      E = disable/enable (0/1) ENQ/ACK handshake
445 
446    Bits per character:
447 
448      00 = 5 bits per character
449      01 = 7 bits per character
450      10 = 6 bits per character
451      11 = 8 bits per character
452 
453    Stop bits:
454 
455      00 = (reserved)
456      01 = 1 stop bit
457      10 = 1.5 stop bits
458      11 = 2 stop bits
459 
460    Parity:
461 
462      00 = no parity
463      01 = odd parity
464      10 = no parity
465      11 = even parity
466 
467    Baud rate:
468 
469       0 = no change
470       1 = 50 baud
471       2 = 75 baud
472       3 = 110 baud
473       4 = 134.5 baud
474       5 = 150 baud
475       6 = 300 baud
476       7 = 1200 baud
477       8 = 1800 baud
478       9 = 2400 baud
479      10 = 4800 baud
480      11 = 9600 baud
481      12 = 19200 baud
482      13 = (reserved)
483      14 = (reserved)
484      15 = (reserved)
485 
486    Set Port Key.  If the port is configured as a modem port, the systems modem
487    on port 7 is initialized (once) to no editing, no echo, and terminate on CR,
488    and a poll is started that outputs a '?' and CR once per second.  The systems
489    modem responds with status information for each of the modem ports.
490 
491    No check is made for duplicate port keys.
492 
493    The baud rate generator specified in the command is programmed to the rate
494    specified.  This will affect all other ports on the same generator (as set by
495    the wiring in the connector hood).  If the common ports are not programmed to
496    the same rate, then the last port set will determine the rate for all.
497 
498    The status return value is zero for revision A firmware and the date code of
499    the firmware for revision B and C firmware.  Revision C returns 2416 decimal
500    (ERS says "hex," but the firmware shows decimal).
501 
502 
503       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
504      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
505      | 1   1 | 0   0   0 | 1   0   0 |           port key            |  opcode 304
506      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
507      | -   -   -   -   -   -   -   - | C | R | T | D | N | K | E | H |
508      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
509 
510    Where:
511 
512      C = end transfer on CR
513      R = end transfer on RS
514      T = end transfer on EOT
515      D = end transfer on DC2
516      N = end transfer on count
517      K = end transfer on character
518      E = enable input editing (BS and DEL)
519      H = enable input echo
520 
521    Set Receive Type.  Sets the conditions for the next data read.  The N and K
522    bits are mutually exclusive.  The firmware actually only checks the K bit.
523    If it is not set, then N (end on count) is assumed.
524 
525    The power-on configuration for each port is bits 7, 2, 1, and 0 on (echo,
526    edit, and end on CR).
527 
528    The status return value is zero.
529 
530 
531       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
532      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
533      | 1   1 | 0   0   0 | 1   0   1 |           port key            |  opcode 305
534      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
535      |                   character count in bytes                    |
536      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
537 
538    Set Character Count.  Specifies the length of reads that end on a character
539    count.  The status return value is zero.
540 
541 
542       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
543      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
544      | 1   1 | 0   0   0 | 1   1   0 |           port key            |  opcode 306
545      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
546      | -   -   -   -   -   -   -   -   -   -   -   -   -   - | F | X |
547      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
548 
549    Where:
550 
551      F = force an XON if currently XOFF
552      X = enable XON/XOFF handshaking
553 
554    Set Flow Control.  Note that an XON received before an XOFF is not
555    interpreted as a handshake character.  A XON received after an XOFF is
556    stripped and causes transmission to resume.  The status return value is zero.
557 
558 
559       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
560      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
561      | 1   1 | 0   0   0 | 1   1   1 |           port key            |  opcode 307
562      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
563      |                     read length in bytes                      |
564      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
565 
566    Read Data From Buffer.  After the second command word is sent, the device
567    flag will be set when the first data word (two packed bytes) is ready.  Data
568    is input from the card via an LIA SC,C.  The device flag will set when the
569    next word is available.
570 
571    To conclude the transfer, a word is sent to the card with an OTA/B SC,C. The
572    value is ignored.  The device flag will set to acknowledge the termination.
573    No status word is returned.
574 
575    Odd-byte transfers have the low byte of the last word set to a blank.  A read
576    of less than the number of characters in the buffer will return the remaining
577    characters when the next read is performed.
578 
579 
580       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
581      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
582      | 1   1 | 0   0   1 | 0   0   0 |           port key            |  opcode 310
583      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
584      |                   size of download in bytes                   |
585      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
586 
587    Download Executable.  Each word of the program to be downloaded is sent with
588    an OTA/B SC,C and is acknowledged by the device flag.  All card operations
589    are suspended while download is in progress.  At completion, the program is
590    executed.  No status word is returned.
591 
592 
593       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
594      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
595      | 1   1 | 0   0   1 | 0   0   1 |           port key            |  opcode 311
596      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
597      | -   -   -   -   -   -   -   -   -   - | G | M | B | D | I | S |
598      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
599 
600    Where:
601 
602      G = guard tone off/on (0/1)
603      M = mode is 212/V.22 (0/1)
604      B = 10 bits/9 bits (0/1)
605      D = originate/answer (0/1)
606      I = manual/automatic (0/1) dial
607      S = low/high (0/1) speed
608 
609    Connect Line.  The status return value is 140000 if no modem is installed and
610    000000 otherwise.
611 
612 
613       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
614      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
615      | 1   1 | 0   0   1 | 0   1   0 |           port key            |  opcode 312
616      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
617      | -   -   -   -   -   -   -   -   -   -   -   -   -   -   - | A |
618      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
619 
620    Where:
621 
622      A = enable/disable auto-answer (0/1)
623 
624    Disconnect Line.  The status return value is 140000 if no modem is installed
625    and 000000 otherwise.
626 
627 
628       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
629      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
630      | 1   1 | 0   0   1 | 1   0   1 |           port key            |  opcode 315
631      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
632      | -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   - |
633      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
634 
635    Get Modem/Port Status.  The status return value has the modem status in the
636    lower byte and a zero in the upper byte.  If the systems modem card cage is
637    not present, the return status value is 000200B.
638 
639 
640       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
641      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
642      | 1   1 | 0   0   1 | 1   1   0 |           port key            |  opcode 316
643      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
644      | -   -   -   -   -   -   -   -   -   -   -   -   - | S | T | E |
645      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
646 
647    Where:
648 
649      S = low/high (0/1) speed
650      T = analog/remote digital (0/1)
651      E = disable/enable (0/1) loop test
652 
653    Enable/Disable Modem Loopback.  The status return value is 140000 if no modem
654    is installed and 000000 otherwise.
655 
656 
657       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
658      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
659      | 1   1 | 0   1   0 | 0   0   0 |           port key            |  opcode 320
660      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
661      | -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   - |
662      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
663 
664    Terminate Active Receive Buffer.  The active buffer is terminated immediately
665    with the characters that have already been received.  If this is the first
666    buffer, a "Read buffer available" unsolicited input will be posted.  A
667    subsequent read request will return the characters.
668 
669    If the active buffer is empty, the port is configured temporarily to
670    terminate after one character is received (i.e., the equivalent of a Set
671    Character Count command is done).  Upon receipt of the character, the port
672    character length is reset to 254.
673 
674    The status return value is zero.
675 
676 
677 
678    When the flag sets for command completion, status or data may be read from
679    the card via an LIA/B.  If additional status or data words are expected, the
680    flag will set when they are available.  If bit 15 of the status word is set,
681    the card has experienced a power fail reset.
682 
683    Upon detecting certain conditions, and if enabled by command 102, the card
684    can send unsolicited inputs to the host.  The card notifies the host that an
685    unsolicited input is available by presenting the first status word and
686    setting the flag.  After sending the unsolicited input, the mux disables
687    unsolicited inputs to the host until they are enabled again.  The host reads
688    the status with an LIA/B and acknowledges the unsolicited input with an
689    Acknowledge command.  In response, the card outputs the second word of status
690    and sets the flag again.  The host reads the second word with an LIA/B.  The
691    content of the second status word depends on the reason supplied in the first
692    word.
693 
694 
695    Input Data Word format (LIA, LIB, MIA, and MIB):
696 
697       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
698      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
699      | -   - |        reason         |           port key            |
700      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
701      |                     buffer size in bytes                      | code 001
702      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
703      | -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   - | code 002
704      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
705      | -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   - | code 003
706      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
707      | -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   - | code 004
708      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
709      | - | P | F |  ETC  |       count of characters received        | code 005
710      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
711 
712    Reason:
713 
714      001 = Write buffer available
715      002 = Modem line connected
716      003 = Modem line disconnected
717      004 = Break received
718      005 = Read buffer available
719 
720    Where:
721 
722      P = parity error or buffer overflow occurred
723      F = buffer full before end of text character seen
724 
725    End of text character seen:
726 
727      00 = EOT
728      01 = CR
729      10 = DC2
730      11 = RS
731 
732    A parity error detected during reception sets the P and F bits and
733    immediately terminates the buffer, generating a "read buffer available"
734    interrupt.  A buffer full condition (characters received with both read
735    buffers terminated) sets the P bit for the next interrupt return.  Receiving
736    the 254th character will set the F bit and terminate the read buffer.
737 
738 
739    If the systems modem card cage is present, the Get Modem/Port Status command
740    returns modem status.
741 
742    Input Data Word format (LIA, LIB, MIA, and MIB):
743 
744       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
745      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
746      | -   -   -   -   -   -   -   - | M | T | P | -   -   - | S | C |
747      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
748 
749    Where:
750 
751      M = systems modem present/absent (0/1)
752      T = systems modem OK/timed out (0/1)
753      P = modem present/absent (0/1)
754      S = low/high (0/1) speed
755      C = line disconnected/connected (0/1)
756 
757 
758    At power up, as a result of a PRESET (CRS), or as a result of a programmed
759    Reset, the card resets the microprocessor, which programs its peripherals to
760    their default values, returns a status word of 100000B, and sets the flag.
761    The RTE driver interprets bits 15-14 = 10 to indicate that the card has been
762    reset.
763 
764    On power up, all port keys are defaulted to the reserved value 255.
765 
766    If a command is sent that uses a port key that has not been defined (either
767    due to a programming error or a card reset without a subsequent Set Key
768    command), the card returns a status word of 135320B (hex BAD0) and sets the
769    flag.
770 
771 
772    Implementation notes:
773 
774     1. The 12792 had two baud-rate generators that were assigned to lines by the
775        wiring configuration in the I/O cable connector hood.  Two of the four
776        CTC counters were used to implement the BRGs for all eight lines.  Only
777        subsets of the configurable rates were allowed for lines connected to the
778        same BRG, and assigning mutually incompatible rates caused corruption of
779        the rates on lines assigned earlier.  Under simulation, any baud rate may
780        be assigned to any line without interaction, and assignments of lines to
781        BRGs is not implemented.
782 
783     2. Revisions B and C added support for the 37214A Systems Modem subsystem
784        and the RTE-A Virtual Control Panel (VCP).  Under simulation, the modem
785        commands return status codes indicating that no modems are present, and
786        the VCP commands are not implemented.
787 */
788 
789 
790 
791 #include <ctype.h>
792 
793 #include "sim_defs.h"
794 #include "sim_tmxr.h"
795 
796 #include "hp2100_defs.h"
797 #include "hp2100_io.h"
798 
799 
800 
801 /* Bitfield constructors.
802 
803    Most of the control and status words used by the multiplexer are encoded into
804    fields of varying lengths.  Traditionally, field accessors have been defined
805    as macro definitions of numeric values.  For example, a flag in bit 15 and a
806    two-bit field occupying bits 12-11 would be defined as:
807 
808      #define CHAR_ECHO      0100000u
809      #define CHAR_SIZE      0014000u
810      #define SIZE_A         0004000u
811      #define SIZE_B         0010000u
812 
813      #define CHAR_SHIFT     11
814      #define GET_SIZE(v)    (((v) & CHAR_SIZE) >> CHAR_SHIFT)
815 
816    A drawback is that mental conversion is necessary to determine the affected
817    bits for, e.g., CHAR_SIZE.  It would be better if the bit numbers were
818    explicit.  This is what the bitfield constructors attempt to do.
819 
820    Four constructors are provided:
821 
822      BIT(n)     -- a value corresponding to bit number "n".
823      FIELD(h,l) -- a mask corresponding to bits "h" through "l" inclusive.
824 
825      FIELD_TO(h,l,v) -- a value extracted from field "h" through "l" of word "v".
826      TO_FIELD(h,l,v) -- a value "v" aligned to a field in bits "h" through "l".
827 
828    With these constructors, the above definitions would be rewritten as follows:
829 
830      #define CHAR_ECHO      BIT (15)
831      #define CHAR_SIZE      FIELD (12, 11)
832      #define SIZE_A         TO_FIELD (12, 11, 1)
833      #define SIZE_B         TO_FIELD (12, 11, 2)
834 
835      #define GET_SIZE(v)    FIELD_TO (12, 11, v)
836 
837    With optimization, the above macro expansions reduce to the equivalent
838    numeric values.  Hopefully, these will be easier to maintain than octal
839    literals.
840 */
841 
842 #undef BIT                                      /* undefine any prior sim_defs.h usage */
843 #undef FIELD                                    /* undefine any prior sim_defs.h usage */
844 #undef FIELD_TO                                 /* undefine any prior sim_defs.h usage */
845 #undef TO_FIELD                                 /* undefine any prior sim_defs.h usage */
846 
847 #define BIT(b)              (1u << (b))
848 #define FIELD(h,l)          (BIT ((h) - (l) + 1) - 1u << (l))
849 
850 #define FIELD_TO(h,l,v)     (((unsigned) (v) & FIELD (h, l)) >> (l))
851 #define TO_FIELD(h,l,v)     ((unsigned) (v) << (l) & FIELD (h, l))
852 
853 
854 /* Program limits */
855 
856 #define MPX_PORTS           8                   /* number of visible units */
857 #define MPX_CNTLS           2                   /* number of control units */
858 
859 #define RD_BUF_SIZE         514                 /* read buffer size */
860 #define WR_BUF_SIZE         514                 /* write buffer size */
861 
862 #define RD_BUF_LIMIT        254                 /* read buffer limit */
863 #define WR_BUF_LIMIT        254                 /* write buffer limit */
864 
865 
866 /* Program constants */
867 
868 #define MPX_DATE_CODE       2416                /* date code for C firmware */
869 
870 #define KEY_DEFAULT         255                 /* default port key */
871 
872 
873 /* Character constants */
874 
875 #define NUL                 '\000'
876 #define EOT                 '\004'
877 #define ENQ                 '\005'
878 #define ACK                 '\006'
879 #define BS                  '\010'
880 #define LF                  '\012'
881 #define CR                  '\015'
882 #define DC1                 '\021'
883 #define DC2                 '\022'
884 #define DC3                 '\023'
885 #define ESC                 '\033'
886 #define RS                  '\036'
887 #define DEL                 '\177'
888 
889 #define XON                 DC1
890 #define XOFF                DC3
891 
892 
893 /* Common per-port multiplexer state variables */
894 
895 #define rate_index          u3                  /* index into baud rate timing array */
896 
897 
898 /* Device flags */
899 
900 #define DEV_REV_D           BIT (DEV_V_UF + 0)  /* firmware revision D (not implemented) */
901 #define DEV_REALTIME        BIT (DEV_V_UF + 1)  /* timing mode is realistic */
902 
903 
904 /* Unit flags */
905 
906 #define UNIT_LOCALACK       BIT (UNIT_V_UF + 0) /* ENQ/ACK mode is local */
907 #define UNIT_CAPSLOCK       BIT (UNIT_V_UF + 1) /* caps lock is down */
908 
909 
910 /* Unit references */
911 
912 #define mpx_cntl            mpx_unit [MPX_PORTS + 0]    /* controller unit */
913 #define mpx_poll            mpx_unit [MPX_PORTS + 1]    /* polling unit */
914 
915 
916 /* Unit activation reasons.
917 
918    The simulation models the execution delays of the on-board microprocessor as
919    timed events that are scheduled by controller unit command phase transitions.
920    When a line or controller unit is scheduled, the activation reason determines
921    the length of the delay before service entry.  The delays are stored in an
922    array indexed by the activation reason.  Separate delays are specified
923    for realistic and optimized timing.
924 
925    The array contains these elements:
926 
927      Send      -- the time to transmit a character via the UART
928      Receive   -- the time to receive a character via the UART
929      Backplane -- the time from DMA output to SRQ for a data word
930      Parameter -- the time from STC to STF for the first word of a two-word command
931      Command   -- the time from STC to STF for one or two-word command execution
932      Status    -- the time from the Enable Interrupts command to the status check
933 
934    The sending and receiving times for realistic mode are calculated from the
935    configured baud rate at each activation, so they do not appear in the delay
936    array below.
937 */
938 
939 typedef enum {
940     Send,                                       /* character transmission */
941     Receive,                                    /* character reception */
942     Backplane,                                  /* backplane data transfer */
943     Parameter,                                  /* parameter reception */
944     Command,                                    /* command execution */
945     Status                                      /* status check */
946     } ACTIVATION;
947 
948 typedef enum {                                  /* the device timing modes */
949     Fast_Time,                                  /*   optimized timing */
950     Real_Time                                   /*   realistic timing */
951     } DEVICE_MODE;
952 
953 
954 static int32 fast_times [6] = {                 /* initial fast timing delays, indexed by ACTIVATION */
955 /*  Send      Receive   Backplane  Parameter  Command   Status  */
956 /*  --------  --------  ---------  ---------  --------  ------- */
957     uS (200), uS (200), uS (1.25), uS (10),   uS (50),  uS (20)
958     };
959 
960 static int32 times [2] [6] = {                  /* timing delays, indexed by DEVICE_MODES and ACTIVATION */
961 /*      Send    Receive   Backplane  Parameter  Command   Status  */
962 /*    --------  --------  ---------  ---------  --------  ------- */
963     { uS (200), uS (200), uS (1.25), uS (10),   uS  (50), uS (20) },  /* Fast_Time timing */
964     {    0,        0,     uS (1.25), uS (25),   uS (400), uS (50) }   /* Real_Time timing */
965     };
966 
967 
968 /* Multiplexer baud rate service times.
969 
970    Rates correspond to the baud rate code specified in the Set Port Key command.
971    Baud rate setting 0 means "don't change" and is handled by the command
972    executor.  Baud rate settings 13-15 are marked as "reserved" in the user
973    manual, but the firmware defines these as 38400, 9600, and 9600 baud,
974    respectively.
975 */
976 
977 static const int32 rates [] = {
978 /*   (unused)       50          75         110        134.5        150         300         1200    */
979 /*     1800        2400        4800        9600       19200       38400       9600         9600    */
980 /*  ----------  ----------  ----------  ---------- ----------- ----------- -----------  ---------- */
981         0,      mS (200.0), mS (133.3), mS (90.91), mS (74.39), mS (66.67), mS (33.34), mS (8.334),
982     mS (5.556), mS (4.166), mS (2.084), mS (1.042), mS (0.521), mS (0.260), mS (1.042), mS (1.042)
983     };
984 
985 
986 /* Microprocessor controller opcodes */
987 
988 typedef enum {
989     No_Operation,                               /* (0100)   No operation */
990     Reset_Firmware,                             /* (0101)   Reset firmware to power-on defaults */
991     Enable_UI,                                  /* (0102)   Enable unsolicited interrupts */
992     Abort_DMA_Transfer,                         /* (0103.2) Abort DMA Transfer */
993     Acknowledge,                                /* (0104)   Acknowledge */
994     Cancel_First,                               /* (0105)   Cancel first receive buffer */
995     Cancel_All,                                 /* (0106)   Cancel all received buffers */
996     Fast_Binary_Read,                           /* (0107)   Fast binary read */
997     Disable_UI,                                 /* (0103.1) Disable interrupts */
998 
999     VCP_Put_Byte,                               /* (0140)   VCP put byte */
1000     VCP_Put_Buffer,                             /* (0141)   VCP put buffer */
1001     VCP_Get_Byte,                               /* (0142)   VCP get byte */
1002     VCP_Get_Buffer,                             /* (0143)   VCP get buffer */
1003     VCP_Exit_Mode,                              /* (0144)   Exit VCP mode */
1004     VCP_Enter_Mode,                             /* (0157)   Enter VCP mode */
1005 
1006     Request_Write_Buffer,                       /* (0301)   Request write buffer */
1007     Write_Data,                                 /* (0302)   Write data to buffer */
1008     Set_Port_Key,                               /* (0303)   Set port key */
1009     Set_Receive_Type,                           /* (0304)   Set receive type */
1010     Set_Character_Count,                        /* (0305)   Set character count */
1011     Set_Flow_Control,                           /* (0306)   Set flow control */
1012     Read_Data,                                  /* (0307)   Read data from buffer */
1013     Download_Executable,                        /* (0310)   Download executable */
1014     Connect_Line,                               /* (0311)   Connect line */
1015     Disconnect_Line,                            /* (0312)   Disconnect line */
1016     Get_Status,                                 /* (0315)   Get modem/port status */
1017     Set_Modem_Loopback,                         /* (0316)   Enable/disable modem loopback */
1018     Terminate_Receive_Buffer,                   /* (0320)   Terminate active receive buffer */
1019     } CNTLR_OPCODE;
1020 
1021 
1022 static const char *const fmt_command [] = {     /* command names, indexed by CNTLR_OPCODE */
1023     "No Operation",                             /*   100 */
1024     "Reset Firmware",                           /*   101 */
1025     "Enable Unsolicited Interrupts",            /*   102 */
1026     "Abort DMA Transfer",                       /*   103 subopcode 2 */
1027     "Acknowledge",                              /*   104 */
1028     "Cancel First Receive Buffer",              /*   105 */
1029     "Cancel All Received Buffers",              /*   106 */
1030     "Fast Binary Read",                         /*   107 */
1031     "Disable Unsolicited Interrupts",           /*   103 subopcode 1 */
1032 
1033     "VCP Put Byte",                             /*   140 */
1034     "VCP Put Buffer",                           /*   141 */
1035     "VCP Get Byte",                             /*   142 */
1036     "VCP Get Buffer",                           /*   143 */
1037     "Exit VCP Mode",                            /*   144 */
1038     "Enter VCP Mode",                           /*   157 */
1039 
1040     "Request Write Buffer",                     /*   301 */
1041     "Write Data to Buffer",                     /*   302 */
1042     "Set Port Key",                             /*   303 */
1043     "Set Receive Type",                         /*   304 */
1044     "Set Character Count",                      /*   305 */
1045     "Set Flow Control",                         /*   306 */
1046     "Read Data from Buffer",                    /*   307 */
1047     "Download Executable",                      /*   310 */
1048     "Connect Line",                             /*   311 */
1049     "Disconnect Line",                          /*   312 */
1050     "Get Modem/Port Status",                    /*   315 */
1051     "Set Modem Loopback",                       /*   316 */
1052     "Terminate Receive Buffer"                  /*   320 */
1053     };
1054 
1055 
1056 /* Multiplexer command field encoders */
1057 
1058 #define CN_OPCODE(w)        FIELD_TO (15, 8, w)
1059 #define CN_KEY(w)           FIELD_TO ( 7, 0, w)
1060 
1061 /* One-word command codes */
1062 
1063 #define CMD_NOP             0100u               /* No operation */
1064 #define CMD_RESET           0101u               /* Reset firmware to power-on defaults */
1065 #define CMD_ENABLE_UI       0102u               /* Enable unsolicited interrupts */
1066 #define CMD_DISABLE         0103u               /* Disable interrupts / Abort DMA Transfer */
1067 #define CMD_ACK             0104u               /* Acknowledge */
1068 #define CMD_CANCEL          0105u               /* Cancel first receive buffer */
1069 #define CMD_CANCEL_ALL      0106u               /* Cancel all received buffers */
1070 #define CMD_BINARY_READ     0107u               /* Fast binary read */
1071 
1072 #define CMD_VCP_PUT         0140u               /* VCP put byte */
1073 #define CMD_VCP_PUT_BUF     0141u               /* VCP put buffer */
1074 #define CMD_VCP_GET         0142u               /* VCP get byte */
1075 #define CMD_VCP_GET_BUF     0143u               /* VCP get buffer */
1076 #define CMD_VCP_EXIT        0144u               /* Exit VCP mode */
1077 #define CMD_VCP_ENTER       0157u               /* Enter VCP mode */
1078 
1079 /* One-word subcommand codes */
1080 
1081 #define SUBCMD_UI           1                   /* Disable unsolicited interrupts */
1082 #define SUBCMD_DMA          2                   /* Abort DMA transfer */
1083 
1084 /* Two-word command codes */
1085 
1086 #define CMD_REQ_WRITE       0301u               /* Request write buffer */
1087 #define CMD_WRITE           0302u               /* Write data to buffer */
1088 #define CMD_SET_KEY         0303u               /* Set port key */
1089 #define CMD_SET_RCV         0304u               /* Set receive type */
1090 #define CMD_SET_COUNT       0305u               /* Set character count */
1091 #define CMD_SET_FLOW        0306u               /* Set flow control */
1092 #define CMD_READ            0307u               /* Read data from buffer */
1093 #define CMD_DL_EXEC         0310u               /* Download executable */
1094 
1095 #define CMD_CN_LINE         0311u               /* Connect line */
1096 #define CMD_DC_LINE         0312u               /* Disconnect line */
1097 #define CMD_GET_STATUS      0315u               /* Get modem/port status */
1098 #define CMD_LOOPBACK        0316u               /* Enable/disable modem loopback */
1099 #define CMD_TERM_BUF        0320u               /* Terminate active receive buffer */
1100 
1101 #define CMD_HAS_PARAM(w)    ((CN_OPCODE (w) & 0200u) != 0)  /* two-word commands have the high bit set */
1102 
1103 
1104 /* Input status.
1105 
1106    The CPU inputs status from the interface with the LIA, LIB, MIA, and MIB
1107    instructions.  The format is not encoded but is instead dependent on the
1108    command executed.  Commands that complete normally return 0.
1109 */
1110 
1111 #define ST_OK               0000000u            /* Command OK */
1112 #define ST_DIAG_OK          0000015u            /* Diagnostic passes */
1113 #define ST_VCP_SIZE         0000120u            /* VCP buffer size = 80 chars */
1114 #define ST_NO_SYSMDM        0000200u            /* No systems modem card */
1115 #define ST_TEST_OK          0100000u            /* Self test OK */
1116 #define ST_NO_MODEM         0140000u            /* No modem card on port */
1117 #define ST_BAD_KEY          0135320u            /* Bad port key = 0xBAD0 */
1118 
1119 
1120 /* Write data to buffer (302) command parameter.
1121 
1122       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
1123      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1124      | -   - | E | C | P |               write length                | 302
1125      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1126 */
1127 
1128 #define WR_NO_ENQACK        BIT (13)            /* Write: no ENQ/ACK this xfer */
1129 #define WR_ADD_CRLF         BIT (12)            /* Write: add CR/LF if not '_' */
1130 #define WR_PARTIAL          BIT (11)            /* Write: write is partial */
1131 
1132 #define WR_LENGTH(w)        FIELD_TO (10, 0, w) /* Write: write length in bytes */
1133 
1134 static const BITSET_NAME write_names [] = {     /* Write Data to Buffer parameter */
1135     "disable ENQ/ACK",                          /*   bit 13 */
1136     "add CR/LF",                                /*   bit 12 */
1137     "partial write"                             /*   bit 11 */
1138     };
1139 
1140 static const BITSET_FORMAT write_format =       /* names, offset, direction, alternates, bar */
1141     { FMT_INIT (write_names, 11, msb_first, no_alt, no_bar) };
1142 
1143 
1144 /* Set port key (303) command parameter.
1145 
1146       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
1147      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1148      | bits  | M | G | stop  |  par  | E |   baud rate   |   port    |
1149      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1150 */
1151 
1152 #define SK_BPC_MASK         FIELD (15, 14)              /* Set key: bits per character */
1153 #define   SK_BPC_5          TO_FIELD (15, 14, 0)        /*   5 bits per character */
1154 #define   SK_BPC_7          TO_FIELD (15, 14, 1)        /*   7 bits per character */
1155 #define   SK_BPC_6          TO_FIELD (15, 14, 2)        /*   6 bits per character */
1156 #define   SK_BPC_8          TO_FIELD (15, 14, 3)        /*   8 bits per character */
1157 #define SK_MODEM            BIT (13)                    /* Set key: hardwired or modem */
1158 #define SK_BRG              BIT (12)                    /* Set key: baud rate generator 0/1 */
1159 #define SK_STOPBITS_MASK    FIELD (11, 10)              /* Set key: stop bits */
1160 #define   SK_STOP_1         TO_FIELD (11, 10, 1)        /*   1 stop bit */
1161 #define   SK_STOP_15        TO_FIELD (11, 10, 2)        /*   1.5 stop bits */
1162 #define   SK_STOP_2         TO_FIELD (11, 10, 3)        /*   2 stop bits */
1163 #define SK_PARITY_MASK      FIELD (9, 8)                /* Set key: parity select */
1164 #define   SK_PARITY_NONE    TO_FIELD (9, 8, 0)          /*   no parity */
1165 #define   SK_PARITY_ODD     TO_FIELD (9, 8, 1)          /*   odd parity */
1166 #define   SK_PARITY_EVEN    TO_FIELD (9, 8, 3)          /*   even parity */
1167 #define SK_ENQACK           BIT (7)                     /* Set key: disable or enable ENQ/ACK */
1168 #define SK_BAUDRATE_MASK    FIELD (6, 3)                /* Set key: port baud rate */
1169 #define   SK_BAUD_NOCHG     TO_FIELD (6, 3,  0)         /*   no change */
1170 #define   SK_BAUD_50        TO_FIELD (6, 3,  1)         /*   50 port baud rate */
1171 #define   SK_BAUD_75        TO_FIELD (6, 3,  2)         /*   75 port baud rate */
1172 #define   SK_BAUD_110       TO_FIELD (6, 3,  3)         /*   110 port baud rate */
1173 #define   SK_BAUD_1345      TO_FIELD (6, 3,  4)         /*   134.5 port baud rate */
1174 #define   SK_BAUD_150       TO_FIELD (6, 3,  5)         /*   150 port baud rate */
1175 #define   SK_BAUD_300       TO_FIELD (6, 3,  6)         /*   300 port baud rate */
1176 #define   SK_BAUD_1200      TO_FIELD (6, 3,  7)         /*   1200 port baud rate */
1177 #define   SK_BAUD_1800      TO_FIELD (6, 3,  8)         /*   1800 port baud rate */
1178 #define   SK_BAUD_2400      TO_FIELD (6, 3,  9)         /*   2400 port baud rate */
1179 #define   SK_BAUD_4800      TO_FIELD (6, 3, 10)         /*   4800 port baud rate */
1180 #define   SK_BAUD_9600      TO_FIELD (6, 3, 11)         /*   9600 port baud rate */
1181 #define   SK_BAUD_19200     TO_FIELD (6, 3, 12)         /*   19200 port baud rate */
1182 #define SK_PORT_MASK        FIELD (2, 0)                /* Set key: port number */
1183 
1184 #define GET_BPC(w)          FIELD_TO (15, 14, w)
1185 #define GET_STOPBITS(w)     FIELD_TO (11, 10, w)
1186 #define GET_PARITY(w)       FIELD_TO ( 9,  8, w)
1187 #define GET_BAUDRATE(w)     FIELD_TO ( 6,  3, w)
1188 #define GET_PORT(w)         FIELD_TO ( 2,  0, w)
1189 
1190 #define SK_BRG_1            SK_BRG
1191 #define SK_BRG_0            0
1192 
1193 #define SK_PWRUP_0          (SK_BPC_8 | SK_BRG_0 | SK_STOP_1 | SK_BAUD_9600)
1194 #define SK_PWRUP_1          (SK_BPC_8 | SK_BRG_1 | SK_STOP_1 | SK_BAUD_9600)
1195 
1196 static const BITSET_NAME set_key_names [] = {   /* Set Port Key parameter */
1197     "\1modem port\0hardwired port",             /*   bit 13 */
1198     "\1BRG 1\0BRG 0",                           /*   bit 12 */
1199     NULL,                                       /*   bit 11 */
1200     NULL,                                       /*   bit 10 */
1201     NULL,                                       /*   bit  9 */
1202     NULL,                                       /*   bit  8 */
1203     "\1enable ENQ/ACK\0disable ENQ/ACK"         /*   bit  7 */
1204     };
1205 
1206 static const BITSET_FORMAT set_key_format =     /* names, offset, direction, alternates, bar */
1207     { FMT_INIT (set_key_names, 7, msb_first, has_alt, append_bar) };
1208 
1209 static const uint32 bits_per_char [4] = {       /* bits per character, indexed by SK_BPC encoding */
1210     5, 7, 6, 8
1211     };
1212 
1213 static const char *stop_bits [4] = {            /* stop bits, indexed by SK_STOPBITS encoding */
1214     "(reserved)",
1215     "1 stop bit",
1216     "1.5 stop bits",
1217     "2 stop bits"
1218     };
1219 
1220 static const char *parity [4] = {               /* parity, indexed by SK_PARITY encoding */
1221     "no",
1222     "odd",
1223     "no",
1224     "even"
1225     };
1226 
1227 static const char *baud [16] = {                /* baud rate, indexed by SK_BAUDRATE encoding */
1228     "no change",
1229     "50 baud",
1230     "75 baud",
1231     "110 baud",
1232     "134.5 baud",
1233     "150 baud",
1234     "300 baud",
1235     "1200 baud",
1236     "1800 baud",
1237     "2400 baud",
1238     "4800 baud",
1239     "9600 baud",
1240     "19200 baud",
1241     "(reserved)",
1242     "(reserved)",
1243     "(reserved)"
1244     };
1245 
1246 
1247 /* Set receive type (304) command parameter.
1248 
1249       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
1250      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1251      | -   -   -   -   -   -   -   - | C | R | T | D | N | K | E | H |
1252      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1253 */
1254 
1255 #define RT_END_ON_CR        BIT (7)             /* Receive type: end xfer on CR */
1256 #define RT_END_ON_RS        BIT (6)             /* Receive type: end xfer on RS */
1257 #define RT_END_ON_EOT       BIT (5)             /* Receive type: end xfer on EOT */
1258 #define RT_END_ON_DC2       BIT (4)             /* Receive type: end xfer on DC2 */
1259 #define RT_END_ON_CNT       BIT (3)             /* Receive type: end xfer on count */
1260 #define RT_END_ON_CHAR      BIT (2)             /* Receive type: end xfer on character */
1261 #define RT_ENAB_EDIT        BIT (1)             /* Receive type: enable input editing */
1262 #define RT_ENAB_ECHO        BIT (0)             /* Receive type: enable input echoing */
1263 
1264 #define RT_PWRUP            (RT_END_ON_CR | RT_END_ON_CHAR | RT_ENAB_EDIT | RT_ENAB_ECHO)
1265 
1266 static const BITSET_NAME set_receive_names [] = {       /* Set Receive Type parameter */
1267     "CR",                                               /*   bit  7 */
1268     "RS",                                               /*   bit  6 */
1269     "EOT",                                              /*   bit  5 */
1270     "DC2",                                              /*   bit  4 */
1271     "count",                                            /*   bit  3 */
1272     "character",                                        /*   bit  2 */
1273     "enable editing",                                   /*   bit  1 */
1274     "enable echo"                                       /*   bit  0 */
1275     };
1276 
1277 static const BITSET_FORMAT set_receive_format =       /* names, offset, direction, alternates, bar */
1278     { FMT_INIT (set_receive_names, 0, msb_first, no_alt, no_bar) };
1279 
1280 
1281 /* Set flow control (306) command parameter.
1282 
1283       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
1284      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1285      | -   -   -   -   -   -   -   -   -   -   -   -   -   - | F | X |
1286      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1287 */
1288 
1289 #define FC_FORCE_XON        BIT (1)             /* Flow control: force XON */
1290 #define FC_XONXOFF          BIT (0)             /* Flow control: enable XON/XOFF */
1291 
1292 static const BITSET_NAME set_flow_names [] = {  /* Set Flow Control parameter */
1293     "force XON if XOFF",                        /*   bit 1 */
1294     "enable XON/XOFF handshake"                 /*   bit 0 */
1295     };
1296 
1297 static const BITSET_FORMAT set_flow_format =       /* names, offset, direction, alternates, bar */
1298     { FMT_INIT (set_flow_names, 0, msb_first, no_alt, no_bar) };
1299 
1300 
1301 /* Connect line (311) command parameter.
1302 
1303       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
1304      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1305      | -   -   -   -   -   -   -   -   -   - | G | M | B | D | I | S |
1306      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1307 */
1308 
1309 #define CL_GUARD            BIT (5)             /* Connect line: guard tone off or on */
1310 #define CL_STANDARD         BIT (4)             /* Connect line: standard 212 or V.22 */
1311 #define CL_BITS             BIT (3)             /* Connect line: bits 10 or 9 */
1312 #define CL_MODE             BIT (2)             /* Connect line: mode originate or answer */
1313 #define CL_DIAL             BIT (1)             /* Connect line: dial manual or automatic */
1314 #define CL_SPEED            BIT (0)             /* Connect line: speed low or high */
1315 
1316 
1317 /* Disconnect line (312) command parameter.
1318 
1319       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
1320      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1321      | -   -   -   -   -   -   -   -   -   -   -   -   -   -   - | A |
1322      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1323 */
1324 
1325 #define DL_AUTO_ANSWER      BIT (0)             /* Disconnect line: auto-answer enable or disable */
1326 
1327 
1328 /* Enable/disable modem loopback (316) command parameter.
1329 
1330       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
1331      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1332      | -   -   -   -   -   -   -   -   -   -   -   -   - | S | T | E |
1333      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1334 */
1335 
1336 #define LB_SPEED            BIT (2)             /* Loopback test: speed low or high */
1337 #define LB_MODE             BIT (1)             /* Loopback test: mode analog or digital */
1338 #define LB_TEST             BIT (0)             /* Loopback test: test disable or enable */
1339 
1340 
1341 /* Unsolicited interrupts.
1342 
1343       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
1344      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1345      | -   - |        reason         |           port key            |
1346      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1347      |                     additional parameter                      |
1348      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1349 */
1350 
1351 #define UI_REASON_MASK      FIELD (13, 8)       /* Unsolicited interrupt reason */
1352 #define   UI_WRBUF_AVAIL    TO_FIELD (13, 8, 1) /*   Write buffer available */
1353 #define   UI_LINE_CONN      TO_FIELD (13, 8, 2) /*   Modem line connected */
1354 #define   UI_LINE_DISC      TO_FIELD (13, 8, 3) /*   Modem line disconnected */
1355 #define   UI_BRK_RECD       TO_FIELD (13, 8, 4) /*   Break received */
1356 #define   UI_RDBUF_AVAIL    TO_FIELD (13, 8, 5) /*   Read buffer available */
1357 #define UI_PORT_KEY_MASK    FIELD (7, 0)        /* Unsolicited interrupt port key */
1358 
1359 #define UI_REASON_SHIFT     8                   /* Unsolicited interrupt reason alignment shift */
1360 
1361 #define GET_UIREASON(w)     FIELD_TO (13, 8, w)
1362 #define GET_UIPORT(w)       FIELD_TO ( 7, 0, w)
1363 
1364 static const char *const ui_names [] = {        /* unsolicited interrupt reason names */
1365     NULL,                                       /*   0 */
1366     "Write Buffer Available",                   /*   1 */
1367     "Modem Line Connected",                     /*   2 */
1368     "Modem Line Disconnected",                  /*   3 */
1369     "Break Received",                           /*   4 */
1370     "Read Buffer Available"                     /*   5 */
1371     };
1372 
1373 
1374 /* Read buffer available reception status.
1375 
1376    The reception status for Reason 005 is in this format:
1377 
1378       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
1379      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1380      | - | P | F |  ETC  |       count of characters received        |
1381      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1382 */
1383 
1384 #define RS_OVERFLOW         BIT (14)                    /* Reception status: buffer overflow occurred */
1385 #define RS_PARTIAL          BIT (13)                    /* Reception status: buffer is partial */
1386 #define RS_ETC_RS           TO_FIELD (12, 11, 3)        /* Reception status: terminated by RS */
1387 #define RS_ETC_DC2          TO_FIELD (12, 11, 2)        /* Reception status: terminated by DC2 */
1388 #define RS_ETC_CR           TO_FIELD (12, 11, 1)        /* Reception status: terminated by CR */
1389 #define RS_ETC_EOT          TO_FIELD (12, 11, 0)        /* Reception status: terminated by EOT */
1390 #define RS_CHAR_COUNT_MASK  FIELD (10, 0)               /* Reception status: character count mask */
1391 
1392 #define GET_ETC(w)          FIELD_TO (12, 11, w)
1393 #define GET_READCOUNT(w)    FIELD_TO (10,  0, w)
1394 
1395 #define RS_NO_ETC           D16_UMAX                    /* a value indicating that no ETC condition exists */
1396 
1397 static const BITSET_NAME buffer_names [] = {    /* Read Buffer Available status */
1398     "parity error",                             /*   bit 14 */
1399     "buffer full"                               /*   bit 13 */
1400     };
1401 
1402 static const BITSET_FORMAT buffer_format =      /* names, offset, direction, alternates, bar */
1403     { FMT_INIT (buffer_names, 13, msb_first, no_alt, append_bar) };
1404 
1405 static const char *end_of_text [4] = {          /* end of text character, indexed by RS_ETC encoding */
1406     "EOT",
1407     "CR",
1408     "DC2",
1409     "RS"
1410     };
1411 
1412 
1413 /* Get modem/port status (315) values.
1414 
1415       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
1416      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1417      | -   -   -   -   -   -   -   - | M | T | P | -   -   - | S | C |
1418      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1419 */
1420 
1421 #define GS_NO_SYSMDM        BIT (7)             /* Get status: systems modem present or absent */
1422 #define GS_SYSMDM_TO        BIT (6)             /* Get status: systems modem OK or timed out */
1423 #define GS_NO_MODEM         BIT (5)             /* Get status: modem present or absent */
1424 #define GS_SPEED            BIT (1)             /* Get status: speed low or high */
1425 #define GS_LINE             BIT (0)             /* Get status: line disconnected or connected */
1426 
1427 
1428 /* Per-port internal state flags.
1429 
1430       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
1431      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1432      | -   -   -   - | A | X | B | H | W | O | F | E | f | e | K | D |
1433      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1434 
1435    Where:
1436 
1437      A = a Terminate Receive Buffer command has reset the termination count
1438      X = an incoming XOFF character has stopped the transmission
1439      B = an incoming BREAK was detected
1440      H = a read buffer is now available
1441      W = a write buffer has been requested but is not available
1442      O = a read buffer has overflowed
1443      F = a read buffer is currently filling
1444      E = a read buffer is currently emptying
1445      f = a write buffer is currently filling
1446      e = a write buffer is currently emptying
1447      K = waiting for an ACK in response to ENQ
1448      D = do an ENQ/ACK handshake after the output limit has been reached
1449 */
1450 
1451 #define FL_ALERT            BIT (11)            /* Port flags: alert for terminate recv buffer */
1452 #define FL_XOFF             BIT (10)            /* Port flags: XOFF stopped transmission */
1453 #define FL_BREAK            BIT ( 9)            /* Port flags: UI / break detected */
1454 #define FL_HAVEBUF          BIT ( 8)            /* Port flags: UI / read buffer available */
1455 #define FL_WANTBUF          BIT ( 7)            /* Port flags: UI / write buffer available */
1456 #define FL_RDOVFLOW         BIT ( 6)            /* Port flags: read buffers overflowed */
1457 #define FL_RDFILL           BIT ( 5)            /* Port flags: read buffer is filling */
1458 #define FL_RDEMPT           BIT ( 4)            /* Port flags: read buffer is emptying */
1459 #define FL_WRFILL           BIT ( 3)            /* Port flags: write buffer is filling */
1460 #define FL_WREMPT           BIT ( 2)            /* Port flags: write buffer is emptying */
1461 #define FL_WAITACK          BIT ( 1)            /* Port flags: ENQ sent, waiting for ACK */
1462 #define FL_DO_ENQACK        BIT ( 0)            /* Port flags: do ENQ/ACK handshake */
1463 
1464 #define FL_RDFLAGS          (FL_RDEMPT | FL_RDFILL | FL_RDOVFLOW)
1465 #define FL_WRFLAGS          (FL_WREMPT | FL_WRFILL)
1466 #define FL_UI_PENDING       (FL_WANTBUF | FL_HAVEBUF | FL_BREAK)
1467 
1468 #define ACK_LIMIT           1000                /* poll timeout for ACK response */
1469 #define ENQ_LIMIT             80                /* output chars before ENQ */
1470 
1471 
1472 /* Multiplexer interface states */
1473 
1474 typedef enum {                                  /* controller execution states */
1475     Idle_State,                                 /*   idle */
1476     Command_State,                              /*   waiting for a command word */
1477     Parameter_State,                            /*   waiting for a parameter word */
1478     Execution_State                             /*   executing a command */
1479     } CNTLR_STATE;
1480 
1481 static const char *state_name [] = {            /* controller state names, indexed by CNTLR_STATE */
1482     "Idle",
1483     "Command",
1484     "Parameter",
1485     "Execution"
1486     };
1487 
1488 static HP_WORD mpx_ibuf = 0;                    /* status/data in */
1489 static HP_WORD mpx_obuf = 0;                    /* command/data out */
1490 
1491 static CNTLR_STATE  mpx_state   = Idle_State;   /* current controller state */
1492 static CNTLR_OPCODE mpx_cmd     = No_Operation; /* current command */
1493 static uint32       mpx_param   = 0;            /* current parameter */
1494 static uint32       mpx_port    = 0;            /* current port number for R/W */
1495 static uint32       mpx_portkey = 0;            /* current port's key */
1496 static int32        mpx_iolen   = 0;            /* length of current I/O xfer */
1497 
1498 static t_bool mpx_has_param = FALSE;            /* current command has a parameter */
1499 static t_bool mpx_uien      = FALSE;            /* unsolicited interrupts enabled */
1500 static uint32 mpx_uicode    = 0;                /* unsolicited interrupt reason and port */
1501 
1502 typedef struct {
1503     FLIP_FLOP  control;                         /* control flip-flop */
1504     FLIP_FLOP  flag;                            /* flag flip-flop */
1505     FLIP_FLOP  flag_buffer;                     /* flag buffer flip-flop */
1506     } CARD_STATE;
1507 
1508 static CARD_STATE mpx;                          /* per-card state */
1509 
1510 
1511 /* Multiplexer per-line state */
1512 
1513 static uint32 mpx_key      [MPX_PORTS];         /* port keys */
1514 static uint32 mpx_config   [MPX_PORTS];         /* port configuration */
1515 static uint32 mpx_rcvtype  [MPX_PORTS];         /* receive type */
1516 static uint32 mpx_charcnt  [MPX_PORTS];         /* current character count */
1517 static uint32 mpx_termcnt  [MPX_PORTS];         /* termination character count */
1518 static uint32 mpx_flowcntl [MPX_PORTS];         /* flow control */
1519 static uint32 mpx_enq_cntr [MPX_PORTS];         /* ENQ character counter */
1520 static uint32 mpx_ack_wait [MPX_PORTS];         /* ACK wait timer */
1521 static uint32 mpx_flags    [MPX_PORTS];         /* line state flags */
1522 
1523 
1524 /* Multiplexer buffer selectors */
1525 
1526 typedef enum {                                  /* I/O operations */
1527     ioread,
1528     iowrite
1529     } IO_OPER;
1530 
1531 typedef enum {                                  /* buffer selectors */
1532     get,
1533     put
1534     } BUF_SELECT;
1535 
1536 static const char * const io_op [] = {          /* operation names, indexed by IO_OPER */
1537     "read",
1538     "write"
1539     };
1540 
1541 static const uint32 buf_size [] = {             /* buffer sizes, indexed by IO_OPER */
1542     RD_BUF_SIZE,
1543     WR_BUF_SIZE
1544     };
1545 
1546 static uint32 emptying_flags [2];               /* buffer emptying flags [IO_OPER] */
1547 static uint32 filling_flags  [2];               /* buffer filling  flags [IO_OPER] */
1548 
1549 
1550 /* Multiplexer per-line buffers */
1551 
1552 typedef uint32 BUF_INDEX [MPX_PORTS] [2];               /* buffer index (read and write) */
1553 
1554 static BUF_INDEX mpx_put;                               /* read/write buffer add index */
1555 static BUF_INDEX mpx_sep;                               /* read/write buffer separator index */
1556 static BUF_INDEX mpx_get;                               /* read/write buffer remove index */
1557 
1558 static uint8 mpx_rbuf [MPX_PORTS] [RD_BUF_SIZE];        /* read buffer */
1559 static uint8 mpx_wbuf [MPX_PORTS] [WR_BUF_SIZE];        /* write buffer */
1560 
1561 
1562 /* Multiplexer local SCP support routines */
1563 
1564 static IO_INTERFACE mpx_interface;
1565 
1566 static t_stat set_mode      (UNIT *uptr, int32 val,   char  *cptr, void *desc);
1567 static t_stat set_revision  (UNIT *uptr, int32 val,   char  *cptr, void *desc);
1568 static t_stat show_mode     (FILE *st,   UNIT  *uptr, int32 value, void *desc);
1569 static t_stat show_revision (FILE *st,   UNIT  *uptr, int32 value, void *desc);
1570 static t_stat show_status   (FILE *st,   UNIT  *uptr, int32 value, void *desc);
1571 
1572 static t_stat mpx_reset (DEVICE *dptr);
1573 
1574 static t_stat mpx_attach (UNIT *uptr, char *cptr);
1575 static t_stat mpx_detach (UNIT *uptr);
1576 
1577 
1578 /* Multiplexer local utility routines */
1579 
1580 static t_stat cntl_service (UNIT *uptr);
1581 static t_stat line_service (UNIT *uptr);
1582 static t_stat poll_service (UNIT *uptr);
1583 
1584 static int32        activate_unit    (UNIT *uptr, ACTIVATION reason);
1585 static t_bool       exec_command     (void);
1586 static void         poll_connection  (void);
1587 static void         controller_reset (void);
1588 static int32        key_to_port      (uint32 key);
1589 static CNTLR_OPCODE map_opcode       (uint32 command);
1590 
1591 static void   buf_init   (IO_OPER rw, uint32 port);
1592 static uint8  buf_get    (IO_OPER rw, uint32 port);
1593 static void   buf_put    (IO_OPER rw, uint32 port, uint8 ch);
1594 static void   buf_remove (IO_OPER rw, uint32 port);
1595 static void   buf_term   (IO_OPER rw, uint32 port, uint8 header);
1596 static void   buf_free   (IO_OPER rw, uint32 port);
1597 static void   buf_cancel (IO_OPER rw, uint32 port, BUF_SELECT which);
1598 static uint32 buf_len    (IO_OPER rw, uint32 port, BUF_SELECT which);
1599 static uint32 buf_avail  (IO_OPER rw, uint32 port);
1600 
1601 
1602 /* Multiplexer SCP data structures */
1603 
1604 DEVICE mpx_dev;                                 /* incomplete device structure */
1605 
1606 
1607 /* Terminal multiplexer library descriptors */
1608 
1609 static int32 mpx_order [MPX_PORTS] = {          /* line connection order */
1610     -1                                          /*   use the default order */
1611     };
1612 
1613 static TMLN mpx_ldsc [MPX_PORTS] = {            /* line descriptors */
1614     { 0 }
1615     };
1616 
1617 static TMXR mpx_desc = {                        /* multiplexer descriptor */
1618     MPX_PORTS,                                  /*   number of terminal lines */
1619     0,                                          /*   listening port (reserved) */
1620     0,                                          /*   master socket  (reserved) */
1621     mpx_ldsc,                                   /*   line descriptor array */
1622     mpx_order,                                  /*   line connection order */
1623     &mpx_dev                                    /*   multiplexer device */
1624     };
1625 
1626 
1627 /* Device information block */
1628 
1629 static DIB mpx_dib = {
1630     &mpx_interface,                                     /* the device's I/O interface function pointer */
1631     NULL,                                               /* the power state function pointer */
1632     MPX,                                                /* the device's select code (02-77) */
1633     0,                                                  /* the card index */
1634     "12792C 8-Channel Asynchronous Multiplexer",        /* the card description */
1635     NULL                                                /* the ROM description */
1636     };
1637 
1638 
1639 /* Unit list.
1640 
1641    The first eight units correspond to the eight multiplexer line ports.  These
1642    handle character I/O via the multiplexer library.  A ninth unit acts as the
1643    card controller, executing commands and transferring data to and from the I/O
1644    buffers.  A tenth unit is responsible for polling for connections and line
1645    I/O.  It also holds the master socket for Telnet connections.
1646 
1647    The character I/O service routines run only when there are characters to read
1648    or write.  They operate at the approximate baud rates of the terminals (in
1649    CPU instructions per second) in order to be compatible with the OS drivers.
1650    The controller service routine runs only when a command is executing or a
1651    data transfer to or from the CPU is in progress.  The poll service must run
1652    continuously, but it may operate much more slowly, as the only requirement is
1653    that it must not present a perceptible lag to human input.  To be compatible
1654    with CPU idling, it is co-scheduled with the master poll timer, which uses a
1655    ten millisecond period.
1656 
1657    The controller and poll units are hidden by disabling them, so as to present
1658    a logical picture of the multiplexer to the user.
1659 */
1660 
1661 #define POLL_FLAGS          (UNIT_ATTABLE | UNIT_DIS)
1662 
1663 static UNIT mpx_unit [] = {
1664     { UDATA (&line_service, UNIT_LOCALACK, 0)             },    /* terminal I/O line 0 */
1665     { UDATA (&line_service, UNIT_LOCALACK, 0)             },    /* terminal I/O line 1 */
1666     { UDATA (&line_service, UNIT_LOCALACK, 0)             },    /* terminal I/O line 2 */
1667     { UDATA (&line_service, UNIT_LOCALACK, 0)             },    /* terminal I/O line 3 */
1668     { UDATA (&line_service, UNIT_LOCALACK, 0)             },    /* terminal I/O line 4 */
1669     { UDATA (&line_service, UNIT_LOCALACK, 0)             },    /* terminal I/O line 5 */
1670     { UDATA (&line_service, UNIT_LOCALACK, 0)             },    /* terminal I/O line 6 */
1671     { UDATA (&line_service, UNIT_LOCALACK, 0)             },    /* terminal I/O line 7 */
1672     { UDATA (&cntl_service, UNIT_DIS,      0)             },    /* controller unit */
1673     { UDATA (&poll_service, POLL_FLAGS,    0), POLL_FIRST }     /* poll unit */
1674     };
1675 
1676 
1677 /* Register list */
1678 
1679 static REG mpx_reg [] = {
1680 /*    Macro   Name      Location                       Radix  Width  Offset           Depth             Flags  */
1681 /*    ------  --------  -----------------------------  -----  -----  ------  ------------------------  ------- */
1682     { DRDATA (STATE,    mpx_state,                              3)                                             },
1683     { ORDATA (IBUF,     mpx_ibuf,                              16),                                    REG_X   },
1684     { ORDATA (OBUF,     mpx_obuf,                              16),                                    REG_X   },
1685 
1686     { ORDATA (CMD,      mpx_cmd,                                8)                                             },
1687     { ORDATA (PARAM,    mpx_param,                             16)                                             },
1688     { FLDATA (HASPARM,  mpx_has_param,                                  0)                                     },
1689 
1690     { DRDATA (PORT,     mpx_port,                               8),                                    PV_LEFT },
1691     { DRDATA (PORTKEY,  mpx_portkey,                            8),                                    PV_LEFT },
1692     { DRDATA (IOLEN,    mpx_iolen,                             16),                                    PV_LEFT },
1693 
1694     { FLDATA (UIEN,     mpx_uien,                                       0)                                     },
1695     { GRDATA (UIPORT,   mpx_uicode,                     10,     3,      0)                                     },
1696     { GRDATA (UICODE,   mpx_uicode,                     10,     3,      8)                                     },
1697 
1698     { BRDATA (KEYS,     mpx_key,                        10,     8,           MPX_PORTS)                        },
1699     { BRDATA (PCONFIG,  mpx_config,                      8,    16,           MPX_PORTS)                        },
1700     { BRDATA (RCVTYPE,  mpx_rcvtype,                     2,    16,           MPX_PORTS)                        },
1701     { BRDATA (CHARCNT,  mpx_charcnt,                     8,    16,           MPX_PORTS)                        },
1702     { BRDATA (TERMCNT,  mpx_termcnt,                     8,    16,           MPX_PORTS)                        },
1703     { BRDATA (FLOWCNTL, mpx_flowcntl,                    8,    16,           MPX_PORTS)                        },
1704 
1705     { BRDATA (ENQCNTR,  mpx_enq_cntr,                   10,     7,           MPX_PORTS)                        },
1706     { BRDATA (ACKWAIT,  mpx_ack_wait,                   10,    10,           MPX_PORTS)                        },
1707     { BRDATA (PFLAGS,   mpx_flags,                       2,    12,           MPX_PORTS)                        },
1708 
1709     { CRDATA (RBUF,     mpx_rbuf,                        8,     8,           MPX_PORTS * RD_BUF_SIZE), REG_A   },
1710     { CRDATA (WBUF,     mpx_wbuf,                        8,     8,           MPX_PORTS * WR_BUF_SIZE), REG_A   },
1711 
1712     { CRDATA (GET,      mpx_get,                        10,    10,           MPX_PORTS * 2)                    },
1713     { CRDATA (SEP,      mpx_sep,                        10,    10,           MPX_PORTS * 2)                    },
1714     { CRDATA (PUT,      mpx_put,                        10,    10,           MPX_PORTS * 2)                    },
1715 
1716     { FLDATA (CTL,      mpx.control,                            0)                                             },
1717     { FLDATA (FLG,      mpx.flag,                               0)                                             },
1718     { FLDATA (FBF,      mpx.flag_buffer,                        0)                                             },
1719 
1720     { DRDATA (TTIME,    times [Fast_Time] [Send],              24),                                    PV_LEFT },
1721     { DRDATA (RTIME,    times [Fast_Time] [Receive],           24),                                    PV_LEFT },
1722     { DRDATA (DTIME,    times [Fast_Time] [Backplane],         24),                                    PV_LEFT },
1723     { DRDATA (PTIME,    times [Fast_Time] [Parameter],         24),                                    PV_LEFT },
1724     { DRDATA (CTIME,    times [Fast_Time] [Command],           24),                                    PV_LEFT },
1725     { DRDATA (STIME,    times [Fast_Time] [Status],            24),                                    PV_LEFT },
1726 
1727     { BRDATA (CONNORD,  mpx_order,                      10,    32,           MPX_PORTS),               REG_HRO },
1728 
1729       DIB_REGS (mpx_dib),
1730 
1731     { NULL }
1732     };
1733 
1734 
1735 /* Modifier list */
1736 
1737 static MTAB mpx_mod [] = {
1738 /*    Mask Value     Match Value    Print String        Match String  Validation  Display  Descriptor */
1739 /*    -------------  -------------  ------------------  ------------  ----------  -------  ---------- */
1740     { UNIT_LOCALACK, UNIT_LOCALACK, "local ENQ/ACK",    "LOCALACK",   NULL,       NULL,    NULL       },
1741     { UNIT_LOCALACK, 0,             "remote ENQ/ACK",   "REMOTEACK",  NULL,       NULL,    NULL       },
1742 
1743     { UNIT_CAPSLOCK, UNIT_CAPSLOCK, "CAPS LOCK down",   "CAPSLOCK",   NULL,       NULL,    NULL       },
1744     { UNIT_CAPSLOCK, 0,             "CAPS LOCK up",     "NOCAPSLOCK", NULL,       NULL,    NULL       },
1745 
1746 /*    Entry Flags           Value       Print String   Match String  Validation         Display             Descriptor         */
1747 /*    --------------------  ----------  -------------  ------------  -----------------  ------------------  ------------------ */
1748     { MTAB_XUN | MTAB_NC,   0,          "LOG",         "LOG",        &tmxr_set_log,     &tmxr_show_log,     (void *) &mpx_desc },
1749     { MTAB_XUN | MTAB_NC,   0,          NULL,          "NOLOG",      &tmxr_set_nolog,   NULL,               (void *) &mpx_desc },
1750     { MTAB_XUN,             0,          NULL,          "DISCONNECT", &tmxr_dscln,       NULL,               (void *) &mpx_desc },
1751 
1752     { MTAB_XDV,             0,          "REV",         NULL,         &set_revision,     &show_revision,     NULL               },
1753 
1754     { MTAB_XDV,             Fast_Time,  NULL,          "FASTTIME",   &set_mode,         NULL,               (void *) &mpx_dev  },
1755     { MTAB_XDV,             Real_Time,  NULL,          "REALTIME",   &set_mode,         NULL,               (void *) &mpx_dev  },
1756     { MTAB_XDV,             0,          "MODES",       NULL,         NULL,              &show_mode,         (void *) &mpx_dev  },
1757 
1758     { MTAB_XDV,             0,          "",            NULL,         NULL,              &show_status,       (void *) &mpx_desc },
1759     { MTAB_XDV | MTAB_NMO,  1,          "CONNECTIONS", NULL,         NULL,              &tmxr_show_cstat,   (void *) &mpx_desc },
1760     { MTAB_XDV | MTAB_NMO,  0,          "STATISTICS",  NULL,         NULL,              &tmxr_show_cstat,   (void *) &mpx_desc },
1761     { MTAB_XDV | MTAB_NMO,  0,          "LINEORDER",   "LINEORDER",  &tmxr_set_lnorder, &tmxr_show_lnorder, (void *) &mpx_desc },
1762 
1763     { MTAB_XDV,              1u,        "SC",          "SC",         &hp_set_dib,       &hp_show_dib,       (void *) &mpx_dib  },
1764     { MTAB_XDV | MTAB_NMO,  ~1u,        "DEVNO",       "DEVNO",      &hp_set_dib,       &hp_show_dib,       (void *) &mpx_dib  },
1765 
1766     { 0 }
1767     };
1768 
1769 
1770 /* Debugging trace list */
1771 
1772 static DEBTAB mpx_deb [] = {
1773     { "CMD",   TRACE_CMD   },                   /* trace interface or controller commands */
1774     { "INCO",  TRACE_INCO, },                   /* trace interface or controller command initiations and completions */
1775     { "CSRW",  TRACE_CSRW  },                   /* trace interface control, status, read, and write actions */
1776     { "STATE", TRACE_STATE },                   /* trace state changes */
1777     { "SERV",  TRACE_SERV  },                   /* trace unit service scheduling calls and entries */
1778     { "PSERV", TRACE_PSERV },                   /* trace periodic unit service scheduling calls and entries */
1779     { "XFER",  TRACE_XFER  },                   /* trace data receptions and transmissions */
1780     { "BUF",   TRACE_FIFO  },                   /* trace FIFO data buffer reads and writes */
1781     { "IOBUS", TRACE_IOBUS },                   /* trace I/O bus signals and data words received and returned */
1782     { NULL,    0           }
1783     };
1784 
1785 
1786 /* Device descriptor */
1787 
1788 DEVICE mpx_dev = {
1789     "MPX",                                      /* device name */
1790     mpx_unit,                                   /* unit array */
1791     mpx_reg,                                    /* register array */
1792     mpx_mod,                                    /* modifier array */
1793     MPX_PORTS + MPX_CNTLS,                      /* number of units */
1794     10,                                         /* address radix */
1795     31,                                         /* address width */
1796     1,                                          /* address increment */
1797     8,                                          /* data radix */
1798     8,                                          /* data width */
1799     &tmxr_ex,                                   /* examine routine */
1800     &tmxr_dep,                                  /* deposit routine */
1801     &mpx_reset,                                 /* reset routine */
1802     NULL,                                       /* boot routine */
1803     &mpx_attach,                                /* attach routine */
1804     &mpx_detach,                                /* detach routine */
1805     &mpx_dib,                                   /* device information block */
1806     DEV_DISABLE | DEV_DEBUG,                    /* device flags */
1807     0,                                          /* debug control flags */
1808     mpx_deb,                                    /* debug flag name table */
1809     NULL,                                       /* memory size change routine */
1810     NULL,                                       /* logical device name */
1811     NULL,                                       /* help routine */
1812     NULL,                                       /* help attach routine*/
1813     NULL                                        /* help context */
1814     };
1815 
1816 
1817 
1818 /* Interface local SCP support routines */
1819 
1820 
1821 
1822 /* Multiplexer interface.
1823 
1824    Commands are sent to the card via an OTA/B.  Issuing an STC SC,C causes the
1825    mux to accept the word (STC causes a NMI on the card).  If the command uses
1826    one word, command execution will commence, and the flag will set on
1827    completion.  If the command uses two words, the flag will be set, indicating
1828    that the second word should be output via an OTA/B.  Command execution will
1829    commence upon receipt, and the flag will set on completion.
1830 
1831    When the flag sets for command completion, status or data may be read from
1832    the card via an LIA/B.  If additional status or data words are expected, the
1833    flag will set when they are available.
1834 
1835    A command consists of an opcode in the high byte, and a port key or command
1836    parameter in the low byte.  Undefined commands are treated as NOPs.
1837 
1838    The card firmware executes commands as part of a twelve-event round-robin
1839    scheduling poll.  The card NMI service routine simply sets a flag that is
1840    interrogated during polling.  The poll sequence is advanced after each
1841    command.  This implies that successive commands incur a delay of at least one
1842    poll-loop's execution time.  On an otherwise quiescent card, this delay is
1843    approximately 460 Z80 instructions, or about 950 usec.  The average command
1844    initiation time is half of that, or roughly 425 usec.
1845 
1846    If a detected command requires a second word, the card sits in a tight loop,
1847    waiting for the OTx that indicates that the parameter is available.  Command
1848    initiation from parameter receipt is about 25 usec.
1849 
1850    For reads and writes to card buffers, the on-board DMA controller is used.
1851    The CPU uses DCPC to handle the transfer, but the data transfer time is
1852    limited by the Z80 DMA, which can process a word in about 1.25 usec.
1853 
1854    For most cards, the hardware POPIO signal sets the flag buffer and flag
1855    flip-flops, while CRS clears the control flip-flop.  For this card, the
1856    control and flags are cleared together by CRS, and POPIO is not used.
1857 
1858 
1859    Implementation notes:
1860 
1861     1. "Enable unsolicited input" is the only command that does not set the
1862        device flag upon completion.  Therefore, the CPU has no way of knowing
1863        when the command has completed.  Because the command in the input latch
1864        is recorded in the NMI handler, but actual execution only begins when the
1865        scheduler polls for the command indication, it is possible for another
1866        command to be sent to the card before the "Enable unsolicited input"
1867        command is recognized.  In this case, the second command overwrites the
1868        first and is executed by the scheduler poll.  Under simulation, this
1869        condition occurs when the OTx and STC processors are entered with
1870        mpx_state = Command_State.
1871 
1872     2. The "Fast binary read" command inhibits all other commands until the card
1873        is reset.
1874 */
1875 
mpx_interface(const DIB * dibptr,INBOUND_SET inbound_signals,HP_WORD inbound_value)1876 static SIGNALS_VALUE mpx_interface (const DIB *dibptr, INBOUND_SET inbound_signals, HP_WORD inbound_value)
1877 {
1878 static const char * const input_state  [] = { "Status",  "Invalid status",   "Parameter", "Data" };
1879 static const char * const output_state [] = { "Command", "Command override", "Parameter", "Data" };
1880 ACTIVATION reason;
1881 
1882 INBOUND_SIGNAL signal;
1883 INBOUND_SET    working_set = inbound_signals;
1884 SIGNALS_VALUE  outbound    = { ioNONE, 0 };
1885 t_bool         irq_enabled = FALSE;
1886 
1887 while (working_set) {                                   /* while signals remain */
1888     signal = IONEXTSIG (working_set);                   /*   isolate the next signal */
1889 
1890     switch (signal) {                                   /* dispatch the I/O signal */
1891 
1892         case ioCLF:                                     /* Clear Flag flip-flop */
1893             mpx.flag_buffer = CLEAR;                    /* reset the flag buffer */
1894             mpx.flag        = CLEAR;                    /*   and flag flip-flops */
1895             break;
1896 
1897 
1898         case ioSTF:                                     /* Set Flag flip-flop */
1899             mpx.flag_buffer = SET;                      /* set the flag buffer flip-flop */
1900             break;
1901 
1902 
1903         case ioENF:                                     /* Enable Flag */
1904             if (mpx.flag_buffer == SET)                 /* if the flag buffer flip-flop is set */
1905                 mpx.flag = SET;                         /*   then set the flag flip-flop */
1906             break;
1907 
1908 
1909         case ioSFC:                                     /* Skip if Flag is Clear */
1910             if (mpx.flag == CLEAR)                      /* if the flag flip-flop is clear */
1911                 outbound.signals |= ioSKF;              /*   then assert the Skip on Flag signal */
1912             break;
1913 
1914 
1915         case ioSFS:                                     /* Skip if Flag is Set */
1916             if (mpx.flag == SET)                        /* if the flag flip-flop is set */
1917                 outbound.signals |= ioSKF;              /*   then assert the Skip on Flag signal */
1918             break;
1919 
1920 
1921         case ioIOI:                                     /* I/O data input */
1922             outbound.value = mpx_ibuf;                  /* return info */
1923 
1924             tprintf (mpx_dev, TRACE_CSRW, "%s is %06o\n",
1925                      input_state [mpx_state], mpx_ibuf);
1926 
1927             if (mpx_state == Execution_State)           /* if this is input data word */
1928                 activate_unit (&mpx_cntl, Backplane);   /*   then continue transmission */
1929             break;
1930 
1931 
1932         case ioIOO:                                     /* I/O data output */
1933             mpx_obuf = inbound_value;                   /* save word */
1934 
1935             tprintf (mpx_dev, TRACE_CSRW, "%s is %06o\n",
1936                      output_state [mpx_state], mpx_obuf);
1937 
1938             if (mpx_state == Parameter_State)           /* if this is a parameter word */
1939                 activate_unit (&mpx_cntl, Command);     /*   then schedule the command now */
1940 
1941             else if (mpx_state == Execution_State)      /* else if this is output data word */
1942                 activate_unit (&mpx_cntl, Backplane);   /*   then do transmission */
1943             break;
1944 
1945 
1946         case ioCRS:                                     /* Control Reset */
1947             controller_reset ();                        /* reset firmware to power-on defaults */
1948             mpx_obuf = 0;                               /* clear output buffer */
1949 
1950             mpx.control     = CLEAR;                    /* clear control */
1951             mpx.flag_buffer = CLEAR;                    /* clear flag buffer */
1952             mpx.flag        = CLEAR;                    /* clear flag */
1953             break;
1954 
1955 
1956         case ioCLC:                                     /* Clear Control flip-flop */
1957             mpx.control = CLEAR;                        /* clear control */
1958             break;
1959 
1960 
1961         case ioSTC:                                     /* Set Control flip-flop */
1962             mpx.control = SET;                          /* set control */
1963 
1964             if (mpx_cmd == Fast_Binary_Read)            /* if currently executing a Fast Binary Read */
1965                 break;                                  /*   then further command execution is inhibited */
1966 
1967             mpx_cmd = map_opcode (mpx_obuf);            /* get command opcode */
1968             mpx_portkey = CN_KEY (mpx_obuf);            /* get port key */
1969 
1970             mpx_has_param = CMD_HAS_PARAM (mpx_obuf);   /* set TRUE if the command has a parameter */
1971 
1972             if (mpx_state == Command_State)             /* already scheduled? */
1973                 sim_cancel (&mpx_cntl);                 /* cancel to get full delay */
1974 
1975             else {                                      /* otherwise */
1976                 tprintf (mpx_dev, TRACE_STATE, "Controller transitioned from %s state to %s state\n",
1977                          state_name [mpx_state], state_name [Command_State]);
1978 
1979                 mpx_state = Command_State;              /*   set the command state */
1980                 }
1981 
1982             if (mpx_has_param)                          /* if the command needs a parameter */
1983                 reason = Parameter;                     /*   then specify the parameter delay */
1984             else                                        /* otherwise */
1985                 reason = Command;                       /*   specify the command delay */
1986 
1987             tprintf (mpx_dev, TRACE_INCO, "%s command key %d initiated\n",
1988                      fmt_command [mpx_cmd], mpx_portkey);
1989 
1990             activate_unit (&mpx_cntl, reason);          /* schedule command or parameter */
1991             break;
1992 
1993 
1994         case ioEDT:                                     /* end data transfer */
1995             tprintf (mpx_dev, TRACE_INCO, "DCPC transfer completed\n");
1996             break;
1997 
1998 
1999         case ioSIR:                                     /* Set Interrupt Request */
2000             if (mpx.control & mpx.flag)                 /* if the control and flag flip-flops are set */
2001                 outbound.signals |= cnVALID;            /*   then deny PRL */
2002             else                                        /* otherwise */
2003                 outbound.signals |= cnPRL | cnVALID;    /*   conditionally assert PRL */
2004 
2005             if (mpx.control & mpx.flag & mpx.flag_buffer)   /* if the control, flag, and flag buffer flip-flops are set */
2006                 outbound.signals |= cnIRQ;                  /*   then conditionally assert IRQ */
2007 
2008             if (mpx.flag == SET)                        /* if the flag flip-flop is set */
2009                 outbound.signals |= ioSRQ;              /*   then assert SRQ */
2010             break;
2011 
2012 
2013         case ioIAK:                                     /* Interrupt Acknowledge */
2014             mpx.flag_buffer = CLEAR;                    /* clear the flag buffer flip-flop */
2015             break;
2016 
2017 
2018         case ioIEN:                                     /* Interrupt Enable */
2019             irq_enabled = TRUE;                         /* permit IRQ to be asserted */
2020             break;
2021 
2022 
2023         case ioPRH:                                         /* Priority High */
2024             if (irq_enabled && outbound.signals & cnIRQ)    /* if IRQ is enabled and conditionally asserted */
2025                 outbound.signals |= ioIRQ | ioFLG;          /*   then assert IRQ and FLG */
2026 
2027             if (not irq_enabled || outbound.signals & cnPRL)    /* if IRQ is disabled or PRL is conditionally asserted */
2028                 outbound.signals |= ioPRL;                      /*   then assert it unconditionally */
2029             break;
2030 
2031 
2032         case ioPON:                                     /* not used by this interface */
2033         case ioPOPIO:                                   /* not used by this interface */
2034             break;
2035         }
2036 
2037     IOCLEARSIG (working_set, signal);                   /* remove the current signal from the set */
2038     }                                                   /*   and continue until all signals are processed */
2039 
2040 return outbound;                                        /* return the outbound signals and value */
2041 }
2042 
2043 
2044 /* Multiplexer controller service.
2045 
2046    The controller service handles commands and data transfers to and from the
2047    CPU.  The delay in scheduling the controller service represents the firmware
2048    command or data execution time.  The controller may be in one of four states
2049    upon entry: Idle_State, first word of command received (Command_State),
2050    command parameter received (Parameter_State), or data transfer
2051    (Execution_State).
2052 
2053    Entry in the command state causes execution of one-word commands and
2054    solicitation of command parameters for two-word commands, which are executed
2055    when entering in the parameter state.
2056 
2057    Entry in the data transfer state for terminal read and write commands moves
2058    one word between the CPU and a read or write buffer.  For writes, the write
2059    buffer is filled with words from the CPU.  Once the indicated number of words
2060    have been transferred, the appropriate line service is scheduled to send the
2061    characters.  For reads, characters are unloaded from the read buffer to the
2062    CPU; an odd-length transfer is padded with a blank.  A read of fewer
2063    characters than are present in the buffer will return the remaining
2064    characters when the next read is performed.
2065 
2066    Each read or write is terminated by the CPU sending one additional word (the
2067    RTE drivers send -1).  The command completes when this word is acknowledged
2068    by the card setting the device flag.  For zero-length writes, this additional
2069    word will be the only word sent.
2070 
2071    Data transfer is also used by the "Fast Binary Read" and "Download
2072    Executable" commands.  During a Fast Binary Read, port 0 is polled for input,
2073    and each pair of bytes is packed into a 16-bit data word for retrieval by the
2074    CPU.  The CPU responds to the resulting data flag by executing an LIA or LIB
2075    instruction to obtain the word.  The process then repeats until the
2076    multiplexer is reset by asserting CRS to the interface.
2077 
2078    In hardware, the Download Executable command transfers a Z80 machine program
2079    from the CPU to the on-board microprocessor.  The firmware jumps to location
2080    5100 hex in the downloaded program upon completion of reception.  It is the
2081    responsibility of the program to return to the multiplexer firmware and to
2082    return to the CPU whatever status is appropriate when it is done.  Under
2083    simulation, we simply "sink" the program and return status compatible with
2084    the multiplexer diagnostic program to simulate a passing test.
2085 
2086    Entry in the idle state checks for unsolicited interrupts.  UIs are sent to
2087    the host when the controller is idle, UIs have been enabled, and a UI
2088    condition exists.  If a UI is not acknowledged, it will remain pending and
2089    will be reissued the next time the controller is idle and UIs have been
2090    enabled.
2091 
2092    UI conditions are kept in the per-port flags.  The UI conditions are write
2093    buffer available, read buffer available, break received, modem line
2094    connected, and modem line disconnected.  The latter two conditions are not
2095    implemented in this simulation.  If a break condition occurs at the same time
2096    as a read buffer completion, the break has priority; the buffer UI will occur
2097    after the break UI is acknowledged.
2098 
2099    The firmware checks for UI condition flags as part of the scheduler polling
2100    loop.  Under simulation, though, UIs can occur only in two places: the point
2101    of origin (e.g., termination of a read buffer), or the "Enable unsolicited
2102    input" command executor.  UIs will be generated at the point of origin only
2103    if the simulator is idle.  If the simulator is not idle, it is assumed that
2104    UIs have been disabled to execute the current command and will be reenabled
2105    when the command sequence is complete.
2106 
2107    When the multiplexer is reset, and before the port keys are set, all ports
2108    enter "echoplex" mode.  In this mode, characters received are echoed back as
2109    a functional test.  Each port terminates buffers on CR reception.  We detect
2110    this condition, cancel the buffer, and discard the buffer termination UI.
2111 
2112 
2113    Implementation notes:
2114 
2115     1. The firmware transfers the full amount requested by the CPU, even if the
2116        transfer is longer than the buffer.  Also, zero-length transfers program
2117        the card DMA chip to transfer 0 bytes; this results in a transfer of 217
2118        bytes, per the Zilog databook.  Under simulation, writes beyond the
2119        buffer are accepted from the CPU but discarded, and reads beyond the
2120        buffer return blanks.
2121 
2122     2. While the Fast Binary Read command is executing, this service routine is
2123        entered repeatedly.  On each entry, the "have a buffer" and "want a
2124        buffer" flags for port 0 respectively indicate the transfer state, as
2125        follows:
2126 
2127          00 = waiting for the first byte of the word
2128          01 = waiting for the second byte of the word
2129          11 = complete word has been retrieved
2130 
2131     3. We should never return from this routine in the "cmd" state, so debugging
2132        will report "internal error!" if we do.
2133 */
2134 
cntl_service(UNIT * uptr)2135 static t_stat cntl_service (UNIT *uptr)
2136 {
2137 static const char *trace_formats [2] [4] = {                /* trace formats, indexed by parameter and state */
2138     { "%s command%.0u status %06o completed\n",             /*   one-word commands */
2139       "%s command%.0u invalid state\n",
2140       "%s command%.0u waiting for parameter\n",
2141       "%s command%.0u executing\n" },
2142 
2143     { "%s command parameter %06o status %06o completed\n",  /*   two-word commands */
2144       "%s command invalid state\n",
2145       "%s command waiting for parameter\n",
2146       "%s command parameter %06o executing\n" }
2147     };
2148 
2149 int32       byte;
2150 uint8       ch;
2151 uint32      i;
2152 t_bool      add_crlf;
2153 t_bool      set_flag = TRUE;
2154 CNTLR_STATE last_state = mpx_state;
2155 
2156 tprintf (mpx_dev, TRACE_SERV, "Controller service entered in the %s state\n",
2157          state_name [mpx_state]);
2158 
2159 switch (mpx_state) {                                                /* dispatch on current state */
2160 
2161     case Idle_State:                                                /* controller idle */
2162         set_flag = FALSE;                                           /* assume no UI */
2163 
2164         if (mpx_uicode) {                                                   /* unacknowledged UI? */
2165             if (mpx_uien) {                                                 /* interrupts enabled? */
2166                 mpx_port = GET_UIPORT (mpx_uicode);                         /* get port number */
2167                 mpx_portkey = mpx_key [mpx_port];                           /* get port key */
2168                 mpx_ibuf = (HP_WORD) (mpx_uicode & UI_REASON_MASK | mpx_portkey);   /* report UI reason and port key */
2169                 set_flag = TRUE;                                            /* reissue host interrupt */
2170                 mpx_uien = FALSE;                                           /* disable UI */
2171 
2172                 tprintf (mpx_dev, TRACE_CMD, "Port %d key %d %s unsolicited interrupt reissued\n",
2173                          mpx_port, mpx_portkey, ui_names [GET_UIREASON (mpx_uicode)]);
2174                 }
2175             }
2176 
2177         else                                                        /* no unacknowledged UI */
2178             for (i = 0; i < MPX_PORTS; i++)                         /* check all ports for UIs */
2179                 if (mpx_flags [i] & FL_UI_PENDING) {                /* pending UI? */
2180                     mpx_portkey = mpx_key [i];                      /* get port key */
2181 
2182                     if (mpx_portkey == KEY_DEFAULT) {               /* key defined? */
2183                         if (mpx_flags [i] & FL_HAVEBUF)             /* no, is this read buffer avail? */
2184                             buf_cancel (ioread, i, get);            /* cancel buffer */
2185 
2186                         mpx_flags [i] &= ~FL_UI_PENDING;            /* cancel pending UI */
2187                         }
2188 
2189                     else if (mpx_uien) {                            /* interrupts enabled? */
2190                         if ((mpx_flags [i] & FL_WANTBUF) &&         /* port wants a write buffer? */
2191                             (buf_avail (iowrite, i) > 0))           /*   and one is available? */
2192                             mpx_uicode = UI_WRBUF_AVAIL;            /* set UI reason */
2193 
2194                         else if (mpx_flags [i] & FL_BREAK)          /* received a line BREAK? */
2195                             mpx_uicode = UI_BRK_RECD;               /* set UI reason */
2196 
2197                         else if (mpx_flags [i] & FL_HAVEBUF)        /* have a read buffer ready? */
2198                             mpx_uicode = UI_RDBUF_AVAIL;            /* set UI reason */
2199 
2200                         if (mpx_uicode) {                                       /* UI to send? */
2201                             mpx_port = i;                                       /* set port number for Acknowledge */
2202                             mpx_ibuf = (HP_WORD) (mpx_uicode | mpx_portkey);    /* merge UI reason and port key */
2203                             mpx_uicode = mpx_uicode | mpx_port;                 /* save UI reason and port */
2204                             set_flag = TRUE;                                    /* interrupt host */
2205                             mpx_uien = FALSE;                                   /* disable UI */
2206 
2207                             tprintf (mpx_dev, TRACE_CMD, "Port %d key %d %s unsolicited interrupt generated\n",
2208                                      mpx_port, mpx_portkey, ui_names [GET_UIREASON (mpx_uicode)]);
2209 
2210                             break;                                  /* quit after first UI */
2211                             }
2212                         }
2213                     }
2214         break;
2215 
2216 
2217     case Command_State:                                 /* command state */
2218         mpx_param = 0;                                  /* clear the parameter for single-word commands */
2219 
2220         if (mpx_has_param)                              /* if the command needs a parameter */
2221             mpx_state = Parameter_State;                /*   then look for it before executing */
2222         else                                            /* otherwise */
2223             set_flag = exec_command ();                 /*   the command is ready to execute */
2224         break;
2225 
2226 
2227     case Parameter_State:                               /* parameter get state */
2228         mpx_param = mpx_obuf;                           /* save parameter */
2229         set_flag = exec_command ();                     /* execute two-word command */
2230         break;
2231 
2232 
2233     case Execution_State:                               /* execution state */
2234         switch (mpx_cmd) {
2235 
2236             case Fast_Binary_Read:                      /* fast binary read */
2237                 set_flag = FALSE;                       /* suppress setting the device flag */
2238 
2239                 if (mpx_flags [0] & FL_HAVEBUF)         /* if the data word has been retrieved */
2240                     mpx_flags [0] = 0;                  /*   then reset the state to wait for the first byte */
2241 
2242                 else {                                  /* otherwise we're waiting for a byte (or two) */
2243                     tmxr_poll_rx (&mpx_desc);           /*   so poll for input */
2244 
2245                     while (tmxr_rqln (&mpx_ldsc [0]) > 0) {     /* if bytes are available */
2246                         byte = tmxr_getc_ln (&mpx_ldsc [0]);    /*   then get a byte */
2247 
2248                         if (mpx_flags [0] & FL_WANTBUF) {               /* if the first byte has been stored */
2249                             mpx_ibuf = mpx_ibuf | LOWER_BYTE (byte);    /*   then merge the second byte */
2250 
2251                             mpx_flags [0] |= FL_HAVEBUF;    /* mark the buffer as ready for pickup */
2252                             set_flag = TRUE;                /*   and set the device flag */
2253                             }
2254 
2255                         else {                              /* otherwise this is the first byte */
2256                             mpx_ibuf = TO_WORD (byte, 0);   /*   so put it in the top half of the word */
2257                             mpx_flags [0] |= FL_WANTBUF;    /*     and wait for the second byte to arrive */
2258                             }
2259                         }
2260                      }
2261 
2262                 if (not set_flag)                       /* if the data word is not complete */
2263                     activate_unit (uptr, Receive);      /*   then reschedule our service */
2264                 break;
2265 
2266 
2267             case Write_Data:                                /* transfer data to buffer */
2268                 if (mpx_iolen <= 0) {                       /* last (or only) entry? */
2269                     mpx_state = Idle_State;                 /* idle controller */
2270 
2271                     if (mpx_iolen < 0)                      /* tie-off for buffer complete? */
2272                         break;                              /* we're done */
2273                     }
2274 
2275                 add_crlf = ((mpx_param &                    /* CRLF should be added */
2276                              (WR_ADD_CRLF | WR_PARTIAL)) == WR_ADD_CRLF);
2277 
2278                 for (i = 0; i < 2; i++)                     /* output one or two chars */
2279                     if (mpx_iolen > 0) {                    /* more to do? */
2280                         if (i)                              /* high or low byte? */
2281                             ch = LOWER_BYTE (mpx_obuf);     /* low byte */
2282                         else
2283                             ch = UPPER_BYTE (mpx_obuf);     /* high byte */
2284 
2285                         if ((mpx_iolen == 1) &&             /* final char? */
2286                             (ch == '_') && add_crlf) {      /* underscore and asking for CRLF? */
2287 
2288                             add_crlf = FALSE;               /* suppress CRLF */
2289 
2290                             tprintf (mpx_dev, TRACE_XFER, "Port %d character '_' suppressed CR/LF\n", mpx_port);
2291                             }
2292 
2293                         else if (buf_len (iowrite, mpx_port, put) < WR_BUF_LIMIT)
2294                             buf_put (iowrite, mpx_port, ch);    /* add char to buffer if space avail */
2295 
2296                         mpx_iolen = mpx_iolen - 1;              /* drop remaining count */
2297                         }
2298 
2299                 if (mpx_iolen == 0)  {                      /* buffer done? */
2300                     if (add_crlf) {                         /* want CRLF? */
2301                         buf_put (iowrite, mpx_port, CR);    /* add CR to buffer */
2302                         buf_put (iowrite, mpx_port, LF);    /* add LF to buffer */
2303                         }
2304 
2305                     buf_term (iowrite, mpx_port, UPPER_BYTE (mpx_param));   /* terminate buffer */
2306                     mpx_iolen = -1;                                         /* mark as done */
2307                     }
2308 
2309                 activate_unit (&mpx_unit [mpx_port], Send); /* start line service */
2310                 break;
2311 
2312 
2313             case Read_Data:                                         /* transfer data from buffer */
2314                 if (mpx_iolen < 0) {                                /* input complete? */
2315                     if (mpx_obuf == 0177777) {                      /* "tie-off" word received? */
2316                         if (buf_len (ioread, mpx_port, get) == 0) { /* buffer now empty? */
2317                             buf_free (ioread, mpx_port);            /* free buffer */
2318 
2319                             if ((buf_avail (ioread, mpx_port) == 1) &&  /* one buffer remaining? */
2320                                 not (mpx_flags [mpx_port] & FL_RDFILL)) /*   and not filling it? */
2321                                 mpx_flags [mpx_port] |= FL_HAVEBUF;     /* indicate buffer availability */
2322                             }
2323 
2324                         mpx_ibuf = ST_OK;               /* clear the status word */
2325                         mpx_state = Idle_State;         /*   and idle the controller */
2326                         }
2327 
2328                     else
2329                         set_flag = FALSE;               /* ignore word */
2330                     break;
2331                     }
2332 
2333                 for (i = 0; i < 2; i++)                             /* input one or two chars */
2334                     if (mpx_iolen > 0) {                            /* more to transfer? */
2335                         if (buf_len (ioread, mpx_port, get) > 0)    /* more chars available? */
2336                             ch = buf_get (ioread, mpx_port);        /* get char from buffer */
2337                         else                                        /* buffer exhausted */
2338                             ch = ' ';                               /* pad with blank */
2339 
2340                         if (i)                                      /* high or low byte? */
2341                             mpx_ibuf = mpx_ibuf | ch;               /* low byte */
2342                         else
2343                             mpx_ibuf = TO_WORD (ch, 0);             /* high byte */
2344 
2345                         mpx_iolen = mpx_iolen - 1;                  /* drop count */
2346                         }
2347 
2348                     else                                /* odd number of chars */
2349                         mpx_ibuf = mpx_ibuf | ' ';      /* pad last with blank */
2350 
2351                 if (mpx_iolen == 0)                     /* end of host xfer? */
2352                     mpx_iolen = -1;                     /* mark as done */
2353                 break;
2354 
2355 
2356             case Download_Executable:                   /* sink data from host */
2357                 if (mpx_iolen <= 0) {                   /* final entry? */
2358                     mpx_state = Idle_State;             /* idle controller */
2359                     mpx_ibuf = ST_DIAG_OK;              /* return diag passed status */
2360                     }
2361 
2362                 else {
2363                     if (mpx_iolen > 0)                  /* more from host? */
2364                         mpx_iolen = mpx_iolen - 2;      /* sink two bytes */
2365 
2366                     if (mpx_iolen <= 0)                     /* finished download? */
2367                         activate_unit (&mpx_cntl, Command); /* schedule completion */
2368                     }
2369                 break;
2370 
2371 
2372             default:                                    /* no other entries allowed */
2373                 return SCPE_IERR;                       /* simulator error! */
2374             }
2375         break;
2376     }
2377 
2378 
2379 if (last_state != mpx_state) {                          /* if a state change occurred */
2380     tprintf (mpx_dev, TRACE_INCO, trace_formats [mpx_has_param] [mpx_state],
2381              fmt_command [mpx_cmd],
2382              (mpx_has_param ? mpx_param : 0),
2383              mpx_ibuf);
2384 
2385     tprintf (mpx_dev, TRACE_STATE, "Controller transitioned from %s state to %s state\n",
2386              state_name [last_state], state_name [mpx_state]);
2387     }
2388 
2389 if (set_flag) {
2390     mpx.flag_buffer = SET;                              /* set the flag buffer */
2391     io_assert_ENF (&mpx_dib);                           /*   and flag flip-flops */
2392 
2393     tprintf (mpx_dev, TRACE_CSRW, "Device flag set\n");
2394     }
2395 
2396 return SCPE_OK;
2397 }
2398 
2399 
2400 /* Multiplexer line service.
2401 
2402    The line service routine runs only when there are characters to transmit or
2403    receive.  It is scheduled either at a realistic rate corresponding to the
2404    programmed baud rate of the port to be serviced, or at a somewhat faster
2405    optimized rate.  It is entered when a port buffer is ready for output, when
2406    the poll routine determines that there are characters ready for input, or
2407    while waiting for an ACK to complete an ENQ/ACK handshake.  It is stopped
2408    when there are no more characters to output or input.  When a line is
2409    quiescent, this routine does not run.
2410 
2411    "Fast timing" mode enables two optimizations.  First, buffered characters are
2412    transferred in blocks, rather than a character at a time; this reduces line
2413    traffic and decreases simulator overhead (there is only one service routine
2414    entry per block, rather than one per character).  Second, when editing and
2415    echo is enabled, entering BS echoes a backspace, a space, and a backspace,
2416    and entering DEL echoes a backslash, a carriage return, and a line feed,
2417    providing better compatibility with prior RTE terminal drivers.
2418 
2419    Each read and write buffer begins with a reserved header byte that stores
2420    per-buffer information, such as whether handshaking should be suppressed
2421    during output, or the specific cause of termination for input.  Buffer
2422    termination sets the header byte with the appropriate flags.
2423 
2424    For output, a character counter is maintained and is incremented if ENQ/ACK
2425    handshaking is enabled for the current port and request.  If the counter
2426    limit is reached, an ENQ is sent, and a flag is set to suspend transmission
2427    until an ACK is received.  If the last character of the buffer is sent, the
2428    write buffer is freed, and a UI check is made if the controller is idle, in
2429    case a write buffer request is pending.
2430 
2431    For input, the terminal multiplexer library is called to retrieve the waiting
2432    character from the line buffer.  If a received character is not available,
2433    then the port is checked to see if an ACK is expected in reply to an earlier
2434    ENQ.  If so, then the last wait time is doubled, and the service is
2435    rescheduled.  However, if the new wait time is longer than the current poll
2436    time, service rescheduling is abandoned in favor of the normal poll for
2437    received characters.
2438 
2439    If a BREAK was received, break status is set, and the character is discarded
2440    (the current multiplexer library implementation always returns a NUL with a
2441    BREAK indication).  If the character is an XOFF, and XON/XOFF pacing is
2442    enabled, a flag is set, and transmission is suspended until a corresponding
2443    XON is received.  If the character is an ACK and is in response to a
2444    previously sent ENQ, it is discarded, and transmission is reenabled.
2445 
2446    If editing is enabled, a BS will delete the last character in the read
2447    buffer, and a DEL will delete the entire buffer.  Otherwise, buffer
2448    termination conditions are checked (end on character, end on count, or
2449    buffer full), and if observed, the read buffer is terminated, and a read
2450    buffer available UI condition is signalled.
2451 
2452 
2453    Implementation notes:
2454 
2455     1. The firmware echoes an entered BS before checking the buffer count to see
2456        if there are any characters to delete.  Under simulation, we only echo if
2457        the buffer is not empty.
2458 
2459     2. In fast timing mode, burst transfers are used only to fill the first of
2460        the two receive buffers; the second is filled with one character per
2461        service entry.  This allows the CPU time to unload the first buffer
2462        before the second fills up.  Once the first buffer is freed, the routine
2463        shifts back to burst mode to fill the remainder of the second buffer.
2464 
2465     3. The terminal multiplexer library "tmxr_putc_ln" routine returns
2466        SCPE_STALL if it is called when the transmit buffer is full.  When the
2467        last character is added to the buffer, the routine returns SCPE_OK but
2468        also changes the "xmte" field of the terminal multiplexer line (TMLN)
2469        structure from 1 to 0 to indicate that further calls will be rejected.
2470        The "xmte" value is set back to 1 when the transmit buffer empties.
2471 
2472        This presents two approaches to handling buffer overflows: either call
2473        "tmxr_putc_ln" unconditionally and test for SCPE_STALL on return, or call
2474        "tmxr_putc_ln" only if "xmte" is 1.  The former approach adds a new
2475        character to the transmit buffer as soon as space is available, while the
2476        latter adds a new character only when the buffer has completely emptied.
2477        With either approach, transmission must be rescheduled after a delay to
2478        allow the buffer to drain.
2479 
2480        It would seem that the former approach is more attractive, as it would
2481        allow the simulated I/O operation to complete more quickly.  However,
2482        there are two mitigating factors.  First, the library attempts to write
2483        the entire transmit buffer in one host system call, so there is usually
2484        no time difference between freeing one buffer character and freeing the
2485        entire buffer (barring host system buffer congestion).  Second, the
2486        routine increments a "character dropped" counter when returning
2487        SCPE_STALL status.  However, the characters actually would not be lost,
2488        as the SCPE_STALL return would schedule retransmission when buffer space
2489        is available, .  This would lead to erroneous reporting in the SHOW
2490        <unit> STATISTICS command.
2491 
2492        Therefore, we adopt the latter approach and reschedule transmission if
2493        the "xmte" field is 0.  Note that the "tmxr_poll_tx" routine still must
2494        be called in this case, as it is responsible for transmitting the buffer
2495        contents and therefore freeing space in the buffer.
2496 
2497     4. The "tmxr_putc_ln" library routine returns SCPE_LOST if the line is not
2498        connected.  We ignore this error so that an OS may output an
2499        initialization "welcome" message even when the terminal is not connected.
2500        This permits the simulation to continue while ignoring the output.
2501 
2502     5. The serial transmit buffer provided by the terminal multiplexer library
2503        is restricted to one character.  Therefore, attempting to send several
2504        characters in response to input, e.g., echoing "<BS> <space> <BS>" in
2505        response to receiving a <BS>, will fail with SCPE_STALL.  Calling
2506        "tmxr_poll_tx" between characters will not clear the buffer if the line
2507        speed has been set explicitly.
2508 
2509        To avoid having to do our own buffering for echoed characters, we call
2510        the "tmxr_linemsg" routine which loops internally until the characters
2511        have been transmitted.  This is ugly but is a consequence of the buffer
2512        restriction imposed by the TMXR library.
2513 
2514     6. Because ENQ/ACK handshaking is handled entirely on the multiplexer card
2515        with no OS involvement, LOCALACK processing under simulation consists
2516        simply of omitting the handshake even if it is configured by the
2517        multiplexer.
2518 */
2519 
line_service(UNIT * uptr)2520 static t_stat line_service (UNIT *uptr)
2521 {
2522 const int32  port = uptr - mpx_unit;                        /* port number */
2523 const uint32 rt = mpx_rcvtype [port];                       /* receive type for port */
2524 const uint32 data_bits = 5 + GET_BPC (mpx_config [port]);   /* number of data bits */
2525 const uint32 data_mask = (1u << data_bits) - 1;             /* mask for data bits */
2526 uint32 buffer_count, write_count;
2527 int32  chx;
2528 uint8  ch = 0;
2529 uint32 termination = RS_NO_ETC;                         /* initialize to "no end of text character seen" */
2530 t_bool xmit_loop = not (mpx_flags [port] & (FL_WAITACK | FL_XOFF)); /* bypass if output is suspended */
2531 t_stat status = SCPE_OK;
2532 
2533 
2534 tprintf (mpx_dev, TRACE_SERV, "Port %d service entered\n", port);
2535 
2536 
2537 /* Transmission service */
2538 
2539 write_count = buf_len (iowrite, port, get);             /* get the output buffer length */
2540 
2541 if (mpx_ldsc [port].xmte == 0)                          /* if the transmit buffer is full */
2542     tprintf (mpx_dev, TRACE_XFER, "Port %d transmission stalled for full buffer\n",
2543              port);
2544 
2545 else while (xmit_loop && write_count > 0) {             /* otherwise loop while characters are available to output */
2546     if (not (mpx_flags [port] & FL_WREMPT)) {           /* if the buffer has not started emptying */
2547         chx = TO_WORD (buf_get (iowrite, port), 0);     /*   then get the header value and position it */
2548 
2549         if (uptr->flags & UNIT_LOCALACK                 /* if configured for local ENQ/ACK */
2550           || chx & WR_NO_ENQACK                         /*   or ENQ/ACK is suppressed for this write */
2551           || not (mpx_config [port] & SK_ENQACK))       /*   or the port is not configured for ENQ/ACK */
2552             mpx_flags [port] &= ~FL_DO_ENQACK;          /*     then clear the operation flag */
2553         else                                            /* otherwise */
2554             mpx_flags [port] |= FL_DO_ENQACK;           /*   set the flag to do ENQ/ACK */
2555 
2556         continue;                                       /* continue with the first output character */
2557         }
2558 
2559     else if (mpx_enq_cntr [port] >= ENQ_LIMIT) {        /* otherwise if the terminal is ready for an ENQ */
2560         ch = ENQ;                                       /*   then send one */
2561         status = tmxr_putc_ln (&mpx_ldsc [port], ch);   /*     to the multiplexer port */
2562 
2563         if (status == SCPE_OK || status == SCPE_LOST) { /* if transmission succeeded or was ignored */
2564             mpx_enq_cntr [port] = 0;                    /*   then clear the ENQ counter */
2565             mpx_ack_wait [port] = 0;                    /*     and the ACK wait timer */
2566 
2567             mpx_flags [port] |= FL_WAITACK;             /* set the "waiting for ACK" flag */
2568 
2569             uptr->wait = activate_unit (uptr, Receive); /* schedule the ACK reception */
2570             }
2571 
2572         xmit_loop = FALSE;                              /* stop further transmission until ACK is received */
2573         }
2574 
2575     else {                                              /* otherwise */
2576         ch = buf_get (iowrite, port) & data_mask;       /*   get the next character and mask to the bit width */
2577 
2578         status = tmxr_putc_ln (&mpx_ldsc [port], ch);   /* transmit the character */
2579 
2580         if (status == SCPE_OK || status == SCPE_LOST) { /* if transmission succeeded or was ignored */
2581             write_count = write_count - 1;              /*   then count the character */
2582 
2583             if (mpx_flags [port] & FL_DO_ENQACK)        /* if ENQ/ACK handshaking is enabled */
2584                 mpx_enq_cntr [port] += 1;               /*   then bump the character counter */
2585 
2586             xmit_loop = (not (mpx_dev.flags & DEV_REALTIME) /* continue transmission if enabled */
2587                           && mpx_ldsc [port].xmte != 0);    /*   and buffer space is available */
2588             }
2589 
2590         else                                            /* otherwise transmission failed */
2591             xmit_loop = FALSE;                          /*   so give up on further transfers */
2592         }
2593 
2594     if (status == SCPE_OK)                              /* if transmission succeeded */
2595         tprintf (mpx_dev, TRACE_XFER, "Port %d character %s transmitted\n",
2596                  port, fmt_char (ch));
2597 
2598     else {                                              /* otherwise report the failure */
2599         tprintf (mpx_dev, TRACE_XFER, "Port %d character %s transmission failed with status %d\n",
2600                  port, fmt_char (ch), status);
2601 
2602         if (status == SCPE_LOST)                        /* if the line is not connected */
2603             status = SCPE_OK;                           /*   then ignore the output */
2604         }
2605 
2606     if (write_count == 0) {                             /* if the buffer is now empty */
2607         buf_free (iowrite, port);                       /*   then free it */
2608 
2609         write_count = buf_len (iowrite, port, get);     /* get the next output buffer length */
2610 
2611         if (mpx_state == Idle_State)                    /* if the controller is idle */
2612             cntl_service (&mpx_cntl);                   /*   then check for an unsolicited interrupt */
2613         }
2614     }
2615 
2616 
2617 /* Reception service */
2618 
2619 buffer_count = buf_avail (ioread, port);                /* get the number of available read buffers */
2620 
2621 if (mpx_flags [port] & FL_RDFILL)                       /* if filling the current buffer */
2622     buffer_count = buffer_count + 1;                    /*   then include it in the count */
2623 
2624 while (TRUE) {                                          /* loop while there are characters to read */
2625     chx = tmxr_getc_ln (&mpx_ldsc [port]);              /* get a new character */
2626 
2627     if (chx == 0)                                           /* if no character is present */
2628         if (mpx_flags [port] & FL_WAITACK && ch != ENQ) {   /*   then if the port has been waiting for an ACK */
2629             tmxr_poll_rx (&mpx_desc);                       /*     then poll the port to see if it has arrived early */
2630 
2631             chx = tmxr_getc_ln (&mpx_ldsc [port]);      /* try to pick up the ACK */
2632 
2633             if (chx == 0) {                             /* if an ACK is expected but has not arrived */
2634                 uptr->wait = uptr->wait * 2;            /*   then double the wait time for the next check */
2635 
2636                 if (uptr->wait < mpx_poll.wait) {       /* if the new wait is shorter than the standard poll wait */
2637                     sim_activate (uptr, uptr->wait);    /*   then reschedule the line service */
2638 
2639                     tprintf (mpx_dev, TRACE_SERV, "Port %d delay %d service rescheduled for ACK\n",
2640                              port, uptr->wait);
2641                     }
2642 
2643                 else                                    /* otherwise */
2644                     uptr->wait = 0;                     /*   wait for the standard poll service */
2645 
2646                 break;                                  /* quit the reception loop */
2647                 }
2648             }
2649 
2650         else                                            /* otherwise no ACK is expected */
2651             break;                                      /*   so quit the reception loop */
2652 
2653     if (chx & SCPE_BREAK) {                             /* if a BREAK was detected */
2654         mpx_flags [port] |= FL_BREAK;                   /*   then set break status */
2655 
2656         tprintf (mpx_dev, TRACE_XFER, "Break detected\n");
2657 
2658         if (mpx_state == Idle_State)                    /* if the controller is idle */
2659             cntl_service (&mpx_cntl);                   /*   then generate the Break Received interrupt */
2660 
2661         continue;                                       /* discard the NUL that accompanied the BREAK */
2662         }
2663 
2664     ch = (uint8) (chx & data_mask);                     /* mask the character to the data bits */
2665 
2666     if (ch == XOFF                                      /* if the character is an XOFF */
2667       && mpx_flowcntl [port] & FC_XONXOFF) {            /*   and XON/XOFF handshaking is enabled */
2668         mpx_flags [port] |= FL_XOFF;                    /*     then suspend transmission */
2669 
2670         tprintf (mpx_dev, TRACE_XFER, "Port %d character XOFF suspends transmission\n", port);
2671 
2672         continue;                                       /* continue with the next character */
2673         }
2674 
2675     else if (ch == XON                                  /* otherwise if the character is an XON */
2676       && mpx_flags [port] & FL_XOFF) {                  /*   and transmission is currently suspended */
2677         mpx_flags [port] &= ~FL_XOFF;                   /*     then resume sending */
2678 
2679         tprintf (mpx_dev, TRACE_XFER, "Port %d character XON resumes transmission\n", port);
2680 
2681         continue;                                       /* continue with the next character */
2682         }
2683 
2684     tprintf (mpx_dev, TRACE_XFER, "Port %d character %s received\n",
2685              port, fmt_char (ch));
2686 
2687     if (ch == ACK && mpx_flags [port] & FL_WAITACK) {       /* if it's an ACK and the port is waiting for it */
2688         mpx_flags [port] = mpx_flags [port] & ~FL_WAITACK;  /*   then clear the wait flag */
2689         uptr->wait = 0;                                     /*     and the event timer */
2690 
2691         break;                                          /* end reception for this cycle */
2692         }
2693 
2694     else if (buffer_count == 0                          /* otherwise if there are no free buffers available */
2695       && not (mpx_flags [port] & FL_RDFILL))            /*   and the last buffer is not filling */
2696         mpx_flags [port] |= FL_RDOVFLOW;                /*     then set the buffer overflow flag */
2697 
2698     else {                                              /* otherwise a buffer is available */
2699         if (rt & RT_ENAB_EDIT)                          /* if editing is enabled */
2700             if (ch == BS) {                             /*   then if the character is a backspace */
2701                 if (buf_len (ioread, port, put) > 0)    /*     then if the buffer is not empty */
2702                     buf_remove (ioread, port);          /*       then remove the last character */
2703 
2704                 if (rt & RT_ENAB_ECHO) {                    /* if echo is enabled */
2705                     tmxr_putc_ln (&mpx_ldsc [port], BS);    /*   then echo the BS */
2706 
2707                     if (not (mpx_dev.flags & DEV_REALTIME))     /* if the mode is not real-time */
2708                         tmxr_linemsg (&mpx_ldsc [port], " \b"); /*   then also echo a space and and a BS */
2709                     }
2710 
2711                 continue;                               /* continue with the next character */
2712                 }
2713 
2714             else if (ch == DEL) {                       /* otherwise if the character is a DEL */
2715                 buf_cancel (ioread, port, put);         /*   then cancel the current buffer */
2716 
2717                 if (rt & RT_ENAB_ECHO) {                        /* if echo is enabled */
2718                     if (not (mpx_dev.flags & DEV_REALTIME))     /*   then if the mode is not real-time */
2719                         tmxr_putc_ln (&mpx_ldsc [port], '\\');  /*     then echo a backslash */
2720 
2721                     tmxr_linemsg (&mpx_ldsc [port], "\r\n");    /* echo a CR and a LF */
2722                     }
2723 
2724                 continue;                               /* continue with the next character */
2725                 }
2726 
2727         if (uptr->flags & UNIT_CAPSLOCK)                /* if the CAPS LOCK key is down */
2728             ch = (uint8) toupper (ch);                  /*   then convert lower to upper case */
2729 
2730         if (rt & RT_ENAB_ECHO)                          /* if echo is enabled */
2731             tmxr_putc_ln (&mpx_ldsc [port], ch);        /*   then echo the character */
2732 
2733         if (rt & RT_END_ON_CHAR)                            /* if end-on-character is enabled */
2734             if (ch == CR && rt & RT_END_ON_CR) {            /*   then if the end-on-CR condition is satisfied */
2735                 if (rt & RT_ENAB_ECHO)                      /*     then if echo is enabled */
2736                     tmxr_linemsg (&mpx_ldsc [port], "\n");  /*       then send a LF */
2737 
2738                 termination = RS_ETC_CR;                /* set the termination condition */
2739                 }
2740 
2741             else if (ch == RS && rt & RT_END_ON_RS)     /* otherwise if the end-on-RS condition is satisfied */
2742                 termination = RS_ETC_RS;                /*   then set the termination condition */
2743 
2744             else if (ch == EOT && rt & RT_END_ON_EOT)   /* otherwise if the end-on-EOT condition is satisfied */
2745                 termination = RS_ETC_EOT;               /*   then set the termination condition */
2746 
2747             else if (ch == DC2 && rt & RT_END_ON_DC2)   /* otherwise if the end-on-DC2 condition is satisfied */
2748                 termination = RS_ETC_DC2;               /*   then set the termination condition */
2749 
2750         if (termination == RS_NO_ETC) {                 /* if no termination condition was seen */
2751             buf_put (ioread, port, ch);                 /*   then add the character to the buffer */
2752             mpx_charcnt [port]++;                       /*     and count it */
2753             }
2754 
2755         if (rt & RT_END_ON_CNT                              /* if end-on-count is enabled */
2756           && mpx_charcnt [port] == mpx_termcnt [port]) {    /*   and the termination count has been reached */
2757             termination = 0;                                /*     then set the termination condition */
2758             mpx_charcnt [port] = 0;                         /*       and clear the current character count */
2759 
2760             if (mpx_flags [port] & FL_ALERT) {          /* if the buffer was terminated by explicit command */
2761                 mpx_flags [port] &= ~FL_ALERT;          /*   then clear the alert flag */
2762                 mpx_termcnt [port] = RD_BUF_LIMIT;      /*     and reset the termination character count */
2763                 }
2764             }
2765 
2766         else if (buf_len (ioread, port, put) == RD_BUF_LIMIT)   /* otherwise if the buffer is now full */
2767             termination |= RS_PARTIAL;                          /*   then set the partial-buffer flag */
2768 
2769         if (termination == RS_NO_ETC)                   /* if there is no termination condition */
2770             if (mpx_dev.flags & DEV_REALTIME            /*   then if the mode is real-time */
2771               || buffer_count <= 1)                     /*     or we're filling the last buffer */
2772                 break;                                  /*       then end reception for this cycle */
2773             else                                        /*   otherwise */
2774                 continue;                               /*     continue reception */
2775 
2776         else {                                          /* otherwise a termination condition exists */
2777             if (termination & RS_PARTIAL)               /*   so report if a full buffer caused termination */
2778                 tprintf (mpx_dev, TRACE_XFER, "Port %d read terminated on buffer full\n",
2779                          port);
2780 
2781             else if (rt & RT_END_ON_CHAR)               /*   or if the end-of-text character was seen */
2782                 tprintf (mpx_dev, TRACE_XFER, "Port %d read terminated on character %s\n",
2783                          port, fmt_char (ch));
2784 
2785             else                                        /*   or if the maximum count was received */
2786                 tprintf (mpx_dev, TRACE_XFER, "Port %d read terminated on count %d\n",
2787                          port, mpx_termcnt [port]);
2788 
2789             if (buf_len (ioread, port, put) == 0) {     /* if termination occurred with the no characters stored */
2790                 buf_put (ioread, port, 0);              /*   then do a dummy put to reserve the header */
2791                 buf_remove (ioread, port);              /*     and then back out the character */
2792                 }
2793 
2794             buf_term (ioread, port, UPPER_BYTE (termination));  /* terminate the buffer and set the header */
2795 
2796             if (buf_avail (ioread, port) == 1)          /* if operating on the first read buffer */
2797                 mpx_flags [port] |= FL_HAVEBUF;         /*   then indicate availability of the remaining buffer */
2798 
2799             if (mpx_state == Idle_State)                /* if the controller is idle */
2800                 cntl_service (&mpx_cntl);               /*   then generate the Read Buffer Available interrupt */
2801 
2802             break;                                      /* quit to allow the buffer to be transferred */
2803             }
2804         }
2805     }                                                   /* continue reception while conditions permit */
2806 
2807 
2808 /* Housekeeping */
2809 
2810 tmxr_poll_tx (&mpx_desc);                               /* output any accumulated characters */
2811 
2812 if (write_count > 0                                     /* if there are more characters to transmit */
2813   && not (mpx_flags [port] & (FL_WAITACK | FL_XOFF)))   /*   and transmission is not suspended */
2814     activate_unit (uptr, Send);                         /*     then reschedule the service */
2815 
2816 else if (tmxr_rqln (&mpx_ldsc [port]))                  /* otherwise if there are more characters to receive */
2817     activate_unit (uptr, Receive);                      /*   then reschedule the service */
2818 
2819 else if (uptr->wait == 0)                               /* otherwise if not waiting for an ACK */
2820     tprintf (mpx_dev, TRACE_SERV, "Port %d service stopped\n", port);
2821 
2822 return status;                                          /* return the service status */
2823 }
2824 
2825 
2826 /* Poll service.
2827 
2828    This service routine is used to poll for connections and incoming characters.
2829    It is started when the listening socket or a serial line is attached and is
2830    stopped when the socket and all lines are detached.
2831 
2832    If a Fast Binary Read command is executing, the controller is dedicated to
2833    port 0 until it is reset, and input polling is handled in the controller
2834    service.  Otherwise, each line is then checked for a pending ENQ/ACK
2835    handshake.  If one is pending, the ACK counter is incremented, and if it
2836    times out, another ENQ is sent to avoid stalls.  Lines are also checked for
2837    available characters, and the corresponding line I/O service routine is
2838    scheduled if needed.
2839 */
2840 
poll_service(UNIT * uptr)2841 static t_stat poll_service (UNIT *uptr)
2842 {
2843 uint32 i;
2844 t_stat status = SCPE_OK;
2845 
2846 tprintf (mpx_dev, TRACE_PSERV, "Poll delay %d service entered\n",
2847          uptr->wait);
2848 
2849 poll_connection ();                                     /* check for new connections */
2850 
2851 if (mpx_cmd != Fast_Binary_Read) {                      /* if a fast binary read is not in progress */
2852     tmxr_poll_rx (&mpx_desc);                           /*   then poll for input */
2853 
2854     for (i = 0; i < MPX_PORTS; i++) {                   /* check lines */
2855         if (mpx_flags [i] & FL_WAITACK) {               /* if the port is waiting for an ACK */
2856             mpx_ack_wait [i] = mpx_ack_wait [i] + 1;    /*   then increment the ACK wait timer */
2857 
2858             if (mpx_ack_wait [i] > ACK_LIMIT) {                /* if the wait has timed out */
2859                 status = tmxr_putc_ln (&mpx_ldsc [i], ENQ);    /*   then send the ENQ again */
2860 
2861                 if (status == SCPE_OK) {                /* if the character was accepted */
2862                     tmxr_poll_tx (&mpx_desc);           /*   then transmit it now */
2863                     mpx_ack_wait [i] = 0;               /*     and reset the timer */
2864 
2865                     tprintf (mpx_dev, TRACE_XFER, "Port %d character ENQ retransmitted\n", i);
2866                     }
2867                 }
2868             }
2869 
2870         if (tmxr_rqln (&mpx_ldsc [i]))                  /* chars available? */
2871             activate_unit (&mpx_unit [i], Receive);     /* activate I/O service */
2872         }
2873     }
2874 
2875 if (uptr->wait == POLL_FIRST)                           /* first poll? */
2876     uptr->wait = hp_sync_poll (INITIAL);                /* initial synchronization */
2877 else                                                    /* not first */
2878     uptr->wait = hp_sync_poll (SERVICE);                /* continue synchronization */
2879 
2880 sim_activate (uptr, uptr->wait);                        /* continue polling */
2881 
2882 tprintf (mpx_dev, TRACE_PSERV, "Poll delay %d service rescheduled\n",
2883          uptr->wait);
2884 
2885 return SCPE_OK;
2886 }
2887 
2888 
2889 /* Device reset routine.
2890 
2891    The hardware CRS signal generates a reset signal to the Z80 and its
2892    peripherals.  This causes execution of the power up initialization code.
2893 
2894    The CRS signal also has these hardware effects:
2895 
2896     - clears control
2897     - clears flag
2898     - clears flag buffer
2899     - clears backplane ready
2900     - clears the output buffer register
2901 
2902    If a power-on reset (RESET -P) is being done, the original FASTTIME settings
2903    are restored, in case they have been changed by the user.
2904 
2905 
2906    Implementation notes:
2907 
2908     1. Under simulation, we also clear the input buffer register, even though
2909        the hardware doesn't.
2910 
2911     2. We set up the first poll for connections to occur "immediately" upon
2912        execution, so that clients will be connected before execution begins.
2913        Otherwise, a fast program may access the multiplexer before the poll
2914        service routine activates.
2915 
2916     3. We must set the "emptying_flags" and "filling_flags" values here, because
2917        they cannot be initialized statically, even though the values are
2918        constant.
2919 */
2920 
mpx_reset(DEVICE * dptr)2921 static t_stat mpx_reset (DEVICE *dptr)
2922 {
2923 if (sim_switches & SWMASK ('P')) {                      /* power-on reset? */
2924     emptying_flags [ioread]  = FL_RDEMPT;               /* initialize buffer flags constants */
2925     emptying_flags [iowrite] = FL_WREMPT;
2926     filling_flags  [ioread]  = FL_RDFILL;
2927     filling_flags  [iowrite] = FL_WRFILL;
2928 
2929     memcpy (times [Fast_Time], fast_times, sizeof fast_times);  /* reset the initial fast event delays */
2930 
2931     controller_reset ();                                /* reset the firmware to the power-on defaults */
2932     }
2933 
2934 mpx_ibuf = 0;                                           /* clear input buffer */
2935 
2936 if (mpx_poll.flags & UNIT_ATT) {                        /* network attached? */
2937     mpx_poll.wait = POLL_FIRST;                         /* set up poll */
2938     sim_activate_abs (&mpx_poll, mpx_poll.wait);        /* restart poll immediately */
2939     }
2940 
2941 else
2942     sim_cancel (&mpx_poll);                             /* else stop poll */
2943 
2944 return SCPE_OK;
2945 }
2946 
2947 
2948 /* Attach the multiplexer or a multiplexer line.
2949 
2950    We are called by the ATTACH MPX <netport> command to attach the multiplexer
2951    to the network listening port indicated by <netport> and by ATTACH MPX<n>
2952    <serport> to attach line <n> to serial port <serport>.  For the former, it is
2953    logically the multiplexer device that is attached; however, SIMH only allows
2954    units to be attached.  This makes sense for devices such as tape drives,
2955    where the attached image is a property of a specific drive.  In our case,
2956    though, the listening port is a property of the multiplexer card, not of any
2957    given line.  As ATTACH MPX is equivalent to ATTACH MPX0, the port would, by
2958    default, be attached to the first line and be reported there in a SHOW MPX
2959    command.
2960 
2961    To preserve the logical picture, we attach the listening port to the poll
2962    unit (unit 9), which is normally disabled to inhibit its display.  Serial
2963    ports are attached to line units 0-7.  Attachment is reported by the
2964    "show_status" routine below.
2965 
2966    The connection poll service routine is synchronized with the other input
2967    polling devices in the simulator to facilitate idling.
2968 
2969 
2970    Implementation notes:
2971 
2972     1. If we are being called as part of RESTORE processing, we may see a
2973        request to attach the poll unit (unit 9).  This will occur if the
2974        listening port was attached when the SAVE was done.  If the user attempts
2975        to attach unit 8 (controller) or 9 directly, the command will be rejected
2976        by SCP because the units are disabled.
2977 
2978     2. If the poll unit was attached during a SAVE, it will be enabled as part
2979        of RESTORE processing.  We always unilaterally disable this unit to
2980        ensure that it remains hidden.
2981 
2982     3. ATTACH MPX will pass a pointer unit 0.  This is because SCP treats ATTACH
2983        MPX as equivalent to ATTACH MPX0.  The "tmxr_attach_unit" routine
2984        differentiates these cases by examining the "sim_ref_type" global to see
2985        if a device was referenced and, if so, applying the request to the poll
2986        unit.
2987 */
2988 
mpx_attach(UNIT * uptr,char * cptr)2989 static t_stat mpx_attach (UNIT *uptr, char *cptr)
2990 {
2991 t_stat status;
2992 
2993 status = tmxr_attach_unit (&mpx_desc, &mpx_poll, uptr, cptr);   /* attach the line */
2994 
2995 if (status == SCPE_OK) {                                /* if the attach succeeded */
2996     mpx_poll.wait = POLL_FIRST;                         /*   then set up the poll */
2997     sim_activate (&mpx_poll, mpx_poll.wait);            /*     and start it */
2998 
2999     tprintf (mpx_dev, TRACE_PSERV, "Poll delay %d service scheduled\n",
3000              mpx_poll.wait);
3001 
3002     mpx_poll.flags |= UNIT_DIS;                         /* ensure that the poll unit remains disabled */
3003     }
3004 
3005 return status;                                          /* return the result of the attach */
3006 }
3007 
3008 
3009 /* Detach the multiplexer or a multiplexer line.
3010 
3011    We are called by the DETACH MPX command to detach the listening port and all
3012    Telnet sessions and by the DETACH MPX<n> to detach a serial port from line
3013    <n>.  We will also be called by DETACH ALL, RESTORE, and during simulator
3014    shutdown.  For DETACH ALL and RESTORE, we must not fail the call, or
3015    processing of other units will cease.
3016 
3017    Detaching the listening port will disconnect all active Telnet connections
3018    but will not disturb any lines connected to serial ports.  Therefore, we look
3019    for newly freed lines and clean them up.  If all lines are now free, then we
3020    terminate the poll.
3021 
3022 
3023    Implementation notes:
3024 
3025     1. During simulator shutdown, we will be called for units 0-8 (detach_all in
3026        scp.c calls the detach routines of all units that do NOT have
3027        UNIT_ATTABLE), as well as for unit 9 if it is attached.
3028 
3029     2. A RESTORE command will call us for unit 9 if it is attached.  In this
3030        case, the terminal channels will have already been rescheduled as
3031        appropriate, so canceling them is skipped.
3032 
3033     3. Because DETACH MPX will pass unit 0, the "tmxr_detach_unit" routine
3034        examines the "sim_ref_type" global to see if a device was referenced and,
3035        if so, applies the request to the poll unit.  The routine will reject an
3036        attempt to detach unit 8 (controller) or unit 9 (poll) directly.
3037 */
3038 
mpx_detach(UNIT * uptr)3039 static t_stat mpx_detach (UNIT *uptr)
3040 {
3041 t_stat status;
3042 uint32 line;
3043 
3044 status = tmxr_detach_unit (&mpx_desc, &mpx_poll, uptr); /* detach the line */
3045 
3046 if (status == SCPE_OK) {                                /* if the detach succeeded */
3047     for (line = 0; line < MPX_PORTS; line++)            /*   then look for Telnet connections */
3048         if (tmxr_line_free (&mpx_ldsc [line])) {        /* if the line is now free */
3049             mpx_ldsc [line].rcve = 0;                   /*   then disable reception */
3050             sim_cancel (&mpx_unit [line]);              /*     and cancel any scheduled I/O */
3051             }
3052 
3053     if (tmxr_mux_free (&mpx_desc)) {                    /* if all lines are now free */
3054         sim_cancel (&mpx_poll);                         /*   then stop polling */
3055 
3056         tprintf (mpx_dev, TRACE_PSERV, "Poll service stopped\n");
3057         }
3058     }
3059 
3060 return status;                                          /* return the status of the detach */
3061 }
3062 
3063 
3064 /* Set the device modes.
3065 
3066    The device flag implied by the DEVICE_MODE "value" passed to the routine is
3067    set or cleared in the device specified by the "desc" parameter.  The unit and
3068    character pointers are not used.
3069 */
3070 
set_mode(UNIT * uptr,int32 value,char * cptr,void * desc)3071 static t_stat set_mode (UNIT *uptr, int32 value, char *cptr, void *desc)
3072 {
3073 DEVICE * const dptr = (DEVICE *) desc;                  /* a pointer to the device */
3074 
3075 switch ((DEVICE_MODE) value) {                          /* dispatch based on the mode to set */
3076 
3077     case Fast_Time:                                     /* entering optimized timing mode */
3078         dptr->flags &= ~DEV_REALTIME;                   /*   clears the real-time flag */
3079         break;
3080 
3081 
3082     case Real_Time:                                     /* entering realistic timing mode */
3083         dptr->flags |= DEV_REALTIME;                    /*   sets the real-time flag */
3084         break;
3085     }
3086 
3087 return SCPE_OK;
3088 }
3089 
3090 
3091 /* Set the firmware revision.
3092 
3093    Currently, we support only revision C, so the MTAB entry does not have an
3094    "mstring" entry.  If we add revision D support, an "mstring" entry of "REV"
3095    will enable changing the firmware revision.
3096 */
3097 
set_revision(UNIT * uptr,int32 value,char * cptr,void * desc)3098 static t_stat set_revision (UNIT *uptr, int32 value, char *cptr, void *desc)
3099 {
3100 if (cptr == NULL                                        /* if there is no parameter */
3101   || *cptr < 'C' || *cptr > 'D'                         /*   or it is not C or D */
3102   || *(cptr + 1) != NUL)                                /*   or it is not a single character */
3103     return SCPE_ARG;                                    /*     then the argument is invalid */
3104 
3105 else {                                                  /* otherwise */
3106     if (*cptr == 'C')                                   /* setting revision C? */
3107         mpx_dev.flags = mpx_dev.flags & ~DEV_REV_D;     /* clear 'D' flag */
3108     else if (*cptr == 'D')                              /* setting revision D? */
3109         mpx_dev.flags = mpx_dev.flags | DEV_REV_D;      /* set 'D' flag */
3110 
3111     return SCPE_OK;
3112     }
3113 }
3114 
3115 
3116 /* Show the device modes.
3117 
3118    The output stream and device pointer are passed in the "st" and "desc"
3119    parameters, respectively.  The value and unit pointer are not used.
3120 */
3121 
show_mode(FILE * st,UNIT * uptr,int32 value,void * desc)3122 static t_stat show_mode (FILE *st, UNIT *uptr, int32 value, void *desc)
3123 {
3124 const DEVICE * const dptr = (const DEVICE *) desc;      /* a pointer to the device */
3125 
3126 if (dptr->flags & DEV_REALTIME)                         /* if the real-time flag is set */
3127     fputs ("realistic timing", st);                     /*   then report that we are using realistic timing */
3128 else                                                    /* otherwise */
3129     fputs ("fast timing", st);                          /*   report that we are using optimized timing */
3130 
3131 return SCPE_OK;
3132 }
3133 
3134 
3135 /* Show firmware revision */
3136 
show_revision(FILE * st,UNIT * uptr,int32 value,void * desc)3137 static t_stat show_revision (FILE *st, UNIT *uptr, int32 value, void *desc)
3138 {
3139 if (mpx_dev.flags & DEV_REV_D)
3140     fputs ("12792D", st);
3141 else
3142     fputs ("12792C", st);
3143 
3144 return SCPE_OK;
3145 }
3146 
3147 
3148 /* Show multiplexer status */
3149 
show_status(FILE * st,UNIT * uptr,int32 value,void * desc)3150 static t_stat show_status (FILE *st, UNIT *uptr, int32 value, void *desc)
3151 {
3152 if (mpx_poll.flags & UNIT_ATT)                          /* attached to socket? */
3153     fprintf (st, "attached to port %s, ", mpx_poll.filename);
3154 else
3155     fprintf (st, "not attached, ");
3156 
3157 tmxr_show_summ (st, uptr, value, desc);                 /* report connection count */
3158 
3159 return SCPE_OK;
3160 }
3161 
3162 
3163 
3164 /* Multiplexer local utility routines */
3165 
3166 
3167 /* Activate a port or controller unit.
3168 
3169    The specified unit is activated to receive or send a character or run the
3170    microprocessor controller.  The reason for the activation is specified by the
3171    "reason" parameter.  If the multiplexer is in real-time mode, and a port unit
3172    is being activated to send or receive a character, the delay time will be
3173    zero.  This is an indication that the previously initialized baud rate index
3174    should be used to look up the corresponding character delay used to schedule
3175    the event.  In fast-time mode, the delay time is used as specified.
3176 
3177    If tracing is enabled, the activation is logged to the debug file.
3178 
3179    The activation delay used is returned as the value of the function.
3180 
3181 
3182    Implementation notes:
3183 
3184     1. Testing for FASTTIME vs. REALTIME and using explicit array indices is
3185        faster than calculating the first subscript logically.
3186 */
3187 
activate_unit(UNIT * uptr,ACTIVATION reason)3188 static int32 activate_unit (UNIT *uptr, ACTIVATION reason)
3189 {
3190 int32 delay;
3191 
3192 if (mpx_dev.flags & DEV_REALTIME)                       /* if realistic timing is being used */
3193     delay = times [Real_Time] [reason];                 /*   then get the indicated real-time event delay */
3194 else                                                    /* otherwise */
3195     delay = times [Fast_Time] [reason];                 /*   get the indicated optimized event delay */
3196 
3197 if (delay == 0)                                         /* if the delay is zero */
3198     delay = rates [uptr->rate_index];                   /*   then schedule the realistic data time */
3199 
3200 if (uptr == &mpx_cntl)
3201     tprintf (mpx_dev, TRACE_SERV, "Controller delay %d service scheduled\n",
3202              delay);
3203 
3204 else
3205     tprintf (mpx_dev, TRACE_SERV, "Port %d delay %d service scheduled\n",
3206              (int) (uptr - mpx_unit), delay);
3207 
3208 sim_activate (uptr, delay);                             /* activate the unit */
3209 return delay;                                           /*   and return the activation delay */
3210 }
3211 
3212 
3213 /* Command executor.
3214 
3215    We are called by the controller service routine to process one- and two-word
3216    commands.  For two-word commands, the parameter word is present in mpx_param.
3217    The return value indicates whether the card flag should be set upon
3218    completion.
3219 
3220    Most commands execute and complete directly.  The read and write commands,
3221    however, transition to the execution state to simulate the DMA transfer, and
3222    the "Download executable" command does the same to receive the download from
3223    the CPU.
3224 
3225    Several commands were added for the B firmware revision, and the various
3226    revisions of the RTE drivers sent some commands that were never implemented
3227    in the mux firmware.  The command protocol treated unknown commands as NOPs,
3228    meaning that the command (and parameter, if it was a two-word command) was
3229    absorbed and the card flag was set as though the command completed normally.
3230    This allowed interoperability between firmware and driver revisions.
3231 
3232    Commands that refer to ports do so indirectly by passing a port key, rather
3233    than a port number.  The key-to-port translation is established by the "Set
3234    Port Key" command.  If a key is not found in the table, the command is not
3235    executed, and the status return is ST_BAD_KEY, which in hex is "BAD0".
3236 
3237 
3238    Implementation notes:
3239 
3240     1. The "reset to power-on defaults" command causes the firmware to disable
3241        interrupts and jump to the power-on initialization routine, exactly as
3242        though the Z80 had received a hardware reset.
3243 
3244     2. The "Abort DMA Transfer" command works because STC causes NMI, so the
3245        command is executed even in the middle of a DMA transfer.  The OTx of the
3246        command will be sent to the buffer if a "Write Data to Buffer" command is
3247        in progress, but the STC will cause this routine to be called, which will
3248        cancel the buffer and return the controller to the idle state.  Note that
3249        this command might be sent with no transfer in progress, in which case
3250        nothing is done.
3251 
3252     3. In response to an "Enable Unsolicited Interrupts" command, the controller
3253        service is scheduled to check for a pending UI.  If one is found, the
3254        first UI status word is placed in the input buffer, and an interrupt is
3255        generated by setting the flag.  This causes entry to the driver, which
3256        issues an "Acknowledge" command to obtain the second status word.
3257 
3258        It is possible, however, for the interrupt to be ignored.  For example,
3259        the driver may be waiting for a "Write Buffer Available" UI when it is
3260        called to begin a write to a different port.  If the flag is set by
3261        the UI after RTE has been entered, the interrupt will be held off, and
3262        the STC sc,C instruction that begins the command sequence will clear the
3263        flag, removing the interrupt entirely.  In this case, the controller will
3264        reissue the UI when the next "Enable Unsolicited Interrupts" command is
3265        sent.
3266 
3267        Note that the firmware reissues the same UI, rather than recomputing UIs
3268        and potentially selecting a different one of higher priority.
3269 
3270     4. The "Fast Binary Read" command apparently was intended to facilitate
3271        booting from a 264x tape drive, although no boot loader ROM for the
3272        multiplexer was ever released.  It sends the fast binary read escape
3273        sequence (ESC e) to the terminal and then packs each pair of characters
3274        received into a word and sends it to the CPU, accompanied by the device
3275        flag.
3276 
3277        The multiplexer firmware disables interrupts and then manipulates the SIO
3278        for port 0 directly.  Significantly, it does no interpretation of the
3279        incoming data and sits in an endless I/O loop, so the only way to exit
3280        the command is to reset the card with a CRS (front panel PRESET or CLC 0
3281        instruction execution).  Sending a command will not work; although the
3282        NMI will interrupt the fast binary read, the NMI handler simply sets a
3283        flag that is tested by the scheduler poll.  Because the processor is in
3284        an endless loop, control never returns to the scheduler, so the command
3285        is never seen.
3286 
3287     5. The "Terminate Active Receive Buffer" behavior is a bit tricky.  If the
3288        read buffer has characters, the buffer is terminated as though a
3289        "terminate on count" condition occurred.  If the buffer is empty,
3290        however, a "terminate on count = 1" condition is established.  When a
3291        character is received, the buffer is terminated, and the buffer
3292        termination count is reset to 254.
3293 */
3294 
exec_command(void)3295 static t_bool exec_command (void)
3296 {
3297 int32       port;
3298 uint32      new_rate;
3299 t_bool      set_flag = TRUE;                            /* flag is normally set on completion */
3300 CNTLR_STATE next_state = Idle_State;                    /* command normally executes to completion */
3301 
3302 tprintf (mpx_dev, TRACE_CMD, "%s command key %d executing\n",
3303          fmt_command [mpx_cmd], mpx_portkey);
3304 
3305 mpx_ibuf = ST_OK;                                       /* return status is normally OK */
3306 
3307 switch (mpx_cmd) {
3308 
3309     case No_Operation:                                  /* no operation */
3310         break;                                          /* just ignore */
3311 
3312 
3313     case Reset_Firmware:                                /* reset firmware */
3314         controller_reset ();                            /* reset program variables */
3315         mpx_ibuf = ST_TEST_OK;                          /* return self-test OK code */
3316         break;
3317 
3318 
3319     case Enable_UI:
3320         mpx_uien = TRUE;                                /* enable unsolicited interrupts */
3321         activate_unit (&mpx_cntl, Status);              /*   and schedule controller for UI check */
3322 
3323         set_flag = FALSE;                               /* do not set the flag at completion */
3324         break;
3325 
3326 
3327     case Disable_UI:
3328         mpx_uien = FALSE;                           /* disable unsolicited interrupts */
3329         break;
3330 
3331 
3332     case Abort_DMA_Transfer:
3333         if (mpx_flags [mpx_port] & FL_WRFILL)       /* write buffer xfer in progress? */
3334             buf_cancel (iowrite, mpx_port, put);    /* cancel it */
3335         else if (mpx_flags [mpx_port] & FL_RDEMPT)  /* read buffer xfer in progress? */
3336             buf_cancel (ioread, mpx_port, get);     /* cancel it */
3337         break;
3338 
3339 
3340     case Acknowledge:                                           /* acknowledge unsolicited interrupt */
3341         switch (mpx_uicode & UI_REASON_MASK) {
3342 
3343             case UI_WRBUF_AVAIL:                                /* write buffer notification */
3344                 mpx_flags [mpx_port] &= ~FL_WANTBUF;            /* clear flag */
3345                 mpx_ibuf = WR_BUF_LIMIT;                        /* report write buffer available */
3346 
3347                 tprintf (mpx_dev, TRACE_CMD, "Write buffer size %d\n", mpx_ibuf);
3348                 break;
3349 
3350             case UI_RDBUF_AVAIL:                                /* read buffer notification */
3351                 mpx_flags [mpx_port] &= ~FL_HAVEBUF;            /* clear flag */
3352 
3353                 mpx_ibuf = TO_WORD (buf_get (ioread, mpx_port),         /* get header value and position */
3354                                     buf_len (ioread, mpx_port, get));   /*   and include buffer length */
3355 
3356                 if (mpx_flags [mpx_port] & FL_RDOVFLOW) {       /* did a buffer overflow? */
3357                     mpx_ibuf = mpx_ibuf | RS_OVERFLOW;          /* report it */
3358                     mpx_flags [mpx_port] &= ~FL_RDOVFLOW;       /* clear overflow flag */
3359                     }
3360 
3361                 tprintf (mpx_dev, TRACE_CMD, "Read buffer %s%s termination | size %d\n",
3362                          fmt_bitset (mpx_ibuf, buffer_format),
3363                          end_of_text [GET_ETC (mpx_ibuf)],
3364                          GET_READCOUNT (mpx_ibuf));
3365                 break;
3366 
3367             case UI_BRK_RECD:                                   /* break received */
3368                 mpx_flags [mpx_port] &= ~FL_BREAK;              /* clear flag */
3369                 mpx_ibuf = 0;                                   /* 2nd word is zero */
3370                 break;
3371             }
3372 
3373         mpx_uicode = 0;                                         /* clear notification code */
3374         break;
3375 
3376 
3377     case Cancel_First:                                  /* cancel first read buffer */
3378         port = key_to_port (mpx_portkey);               /* get port */
3379 
3380         if (port >= 0) {                                /* port defined? */
3381             buf_cancel (ioread, port, get);             /* cancel get buffer */
3382 
3383             if (buf_avail (ioread, port) == 2)          /* if all buffers are now clear */
3384                 mpx_charcnt [port] = 0;                 /*   then clear the current character count */
3385 
3386             else if (not (mpx_flags [port] & FL_RDFILL))    /* otherwise if the other buffer is not filling */
3387                 mpx_flags [port] |= FL_HAVEBUF;             /*   then indicate buffer availability */
3388             }
3389         break;
3390 
3391 
3392     case Cancel_All:                                    /* cancel all read buffers */
3393         port = key_to_port (mpx_portkey);               /* get port */
3394 
3395         if (port >= 0) {                                /* port defined? */
3396             buf_init (ioread, port);                    /* reinitialize read buffers */
3397             mpx_charcnt [port] = 0;                     /*   and clear the current character count */
3398             }
3399         break;
3400 
3401 
3402     case Fast_Binary_Read:                              /* fast binary read */
3403         for (port = 0; port < MPX_PORTS; port++)
3404             sim_cancel (&mpx_unit [port]);              /* cancel I/O on all lines */
3405 
3406         mpx_flags [0] = 0;                              /* clear port 0 state flags */
3407         mpx_enq_cntr [0] = 0;                           /* clear port 0 ENQ counter */
3408         mpx_ack_wait [0] = 0;                           /* clear port 0 ACK wait timer */
3409 
3410         tmxr_putc_ln (&mpx_ldsc [0], ESC);              /* send the fast binary read */
3411         tmxr_putc_ln (&mpx_ldsc [0], 'e');              /*   escape sequence to port 0 */
3412         tmxr_poll_tx (&mpx_desc);                       /*     and flush the output */
3413 
3414         next_state = Execution_State;                   /* set execution state */
3415 
3416         activate_unit (&mpx_cntl, Status);              /* schedule the transfer */
3417         break;
3418 
3419 
3420     case Request_Write_Buffer:                          /* request write buffer */
3421         port = key_to_port (mpx_portkey);               /* get port */
3422 
3423         if (port >= 0)                                  /* port defined? */
3424             if (buf_avail (iowrite, port) > 0)          /* is a buffer available? */
3425                 mpx_ibuf = WR_BUF_LIMIT;                /* report write buffer limit */
3426 
3427             else {
3428                 mpx_ibuf = 0;                           /* report none available */
3429                 mpx_flags [port] |= FL_WANTBUF;         /* set buffer request */
3430                 }
3431 
3432 
3433         tprintf (mpx_dev, TRACE_CMD, "Request size %d\n", mpx_param);
3434         break;
3435 
3436 
3437     case Write_Data:                                    /* write to buffer */
3438         port = key_to_port (mpx_portkey);               /* get port */
3439 
3440         if (port >= 0) {                                /* port defined? */
3441             mpx_port = port;                            /* save port number */
3442             mpx_iolen = WR_LENGTH (mpx_param);          /* save request length */
3443             next_state = Execution_State;               /* set execution state */
3444             }
3445 
3446         tprintf (mpx_dev, TRACE_CMD, "Write length %d | %s\n",
3447                  mpx_iolen, fmt_bitset (mpx_param, write_format));
3448         break;
3449 
3450 
3451     case Set_Port_Key:                                  /* set port key and configuration */
3452         port = GET_PORT (mpx_param);                    /* get target port number */
3453         mpx_key [port] = mpx_portkey;                   /* set port key */
3454         mpx_config [port] = mpx_param;                  /* set port configuration word */
3455 
3456         new_rate = GET_BAUDRATE (mpx_param);            /* get the new baud rate code */
3457 
3458         if (new_rate != 0)                              /* if the rate is to be changed */
3459             mpx_unit [port].rate_index = new_rate;      /*   then set the index to the rate code */
3460 
3461         mpx_ibuf = MPX_DATE_CODE;                       /* return firmware date code */
3462 
3463         tprintf (mpx_dev, TRACE_CMD, "Configuration is %s%u bits | %s | %s parity | %s\n",
3464                  fmt_bitset (mpx_param, set_key_format),
3465                  bits_per_char [GET_BPC (mpx_param)],
3466                  stop_bits [GET_STOPBITS (mpx_param)],
3467                  parity [GET_PARITY (mpx_param)],
3468                  baud [GET_BAUDRATE (mpx_param)]);
3469         break;
3470 
3471 
3472     case Set_Receive_Type:                              /* set receive type */
3473         port = key_to_port (mpx_portkey);               /* get port */
3474 
3475         if (port >= 0)                                  /* port defined? */
3476             mpx_rcvtype [port] = mpx_param;             /* save port receive type */
3477 
3478         tprintf (mpx_dev, TRACE_CMD, "End on %s\n",
3479                  fmt_bitset (mpx_param, set_receive_format));
3480         break;
3481 
3482 
3483     case Set_Character_Count:                           /* set character count */
3484         port = key_to_port (mpx_portkey);               /* get port */
3485 
3486         if (port >= 0) {                                /* port defined? */
3487             mpx_termcnt [port] = mpx_param;             /* save port termination character count */
3488             mpx_charcnt [port] = 0;                     /*   and clear the current character count */
3489             }
3490 
3491         tprintf (mpx_dev, TRACE_CMD, "Termination count is %d\n", mpx_param);
3492         break;
3493 
3494 
3495     case Set_Flow_Control:                                  /* set flow control */
3496         port = key_to_port (mpx_portkey);                   /* get port */
3497 
3498         if (port >= 0) {                                    /* port defined? */
3499             mpx_flowcntl [port] = mpx_param & FC_XONXOFF;   /* save port flow control */
3500 
3501             if (mpx_param & FC_FORCE_XON)                   /* force XON? */
3502                 mpx_flags [port] &= ~FL_XOFF;               /* resume transmission if suspended */
3503             }
3504 
3505         tprintf (mpx_dev, TRACE_CMD, "Flow control is %s\n",
3506                  fmt_bitset (mpx_param, set_flow_format));
3507         break;
3508 
3509 
3510     case Read_Data:                                     /* read from buffer */
3511         tprintf (mpx_dev, TRACE_CMD, "Read length %d\n", mpx_param);
3512 
3513         port = key_to_port (mpx_portkey);               /* get port */
3514 
3515         if (port >= 0) {                                /* port defined? */
3516             mpx_port = port;                            /* save port number */
3517             mpx_iolen = mpx_param;                      /* save request length */
3518 
3519             activate_unit (&mpx_cntl, Backplane);       /* schedule the transfer */
3520 
3521             next_state = Execution_State;               /* set execution state */
3522             set_flag = FALSE;                           /* no flag until word ready */
3523             }
3524         break;
3525 
3526 
3527     case Download_Executable:                           /* Download executable */
3528         mpx_iolen = mpx_param;                          /* save request length */
3529         next_state = Execution_State;                   /* set execution state */
3530 
3531         tprintf (mpx_dev, TRACE_CMD, "Download count is %d\n", mpx_iolen);
3532         break;
3533 
3534 
3535     case Connect_Line:                                  /* connect modem line */
3536     case Disconnect_Line:                               /* disconnect modem line */
3537     case Set_Modem_Loopback:                            /* enable/disable modem loopback */
3538         mpx_ibuf = ST_NO_MODEM;                         /* report "no modem installed" */
3539         break;
3540 
3541 
3542     case Get_Status:                                    /* get modem status */
3543         mpx_ibuf = ST_NO_SYSMDM;                        /* report "no systems modem card" */
3544         break;
3545 
3546 
3547     case Terminate_Receive_Buffer:                      /* terminate active receive buffer */
3548         port = key_to_port (mpx_portkey);               /* get port */
3549 
3550         if (port >= 0)                                  /* port defined? */
3551             if (buf_len (ioread, port, put) > 0) {      /* any chars in buffer? */
3552                 buf_term (ioread, port, 0);             /* terminate buffer and set header */
3553                 mpx_charcnt [port] = 0;                 /*   then clear the current character count */
3554 
3555                 if (buf_avail (ioread, port) == 1)      /* first read buffer? */
3556                     mpx_flags [port] |= FL_HAVEBUF;     /* indicate availability */
3557                 }
3558 
3559             else {                                      /* buffer is empty */
3560                 mpx_termcnt [port] = 1;                 /* set to terminate on one char */
3561                 mpx_flags [port] |= FL_ALERT;           /* set alert flag */
3562                 }
3563         break;
3564 
3565 
3566     case VCP_Put_Byte:                                  /* VCP put byte */
3567     case VCP_Put_Buffer:                                /* VCP put buffer */
3568     case VCP_Get_Byte:                                  /* VCP get byte */
3569     case VCP_Get_Buffer:                                /* VCP get buffer */
3570     case VCP_Exit_Mode:                                 /* Exit VCP mode */
3571     case VCP_Enter_Mode:                                /* Enter VCP mode */
3572         break;
3573     }
3574 
3575 mpx_state = next_state;
3576 return set_flag;
3577 }
3578 
3579 
3580 /* Poll for new connections */
3581 
poll_connection(void)3582 static void poll_connection (void)
3583 {
3584 int32 new_line;
3585 
3586 new_line = tmxr_poll_conn (&mpx_desc);                      /* check for new connection */
3587 
3588 if (new_line >= 0)                                          /* new connection established? */
3589     mpx_ldsc [new_line].rcve = 1;                           /* enable line to receive */
3590 
3591 return;
3592 }
3593 
3594 
3595 /* Controller reset.
3596 
3597    This is the card microprocessor reset, not the simulator reset routine.  It
3598    simulates a power-on restart of the Z80 firmware.  When it is called from the
3599    simulator reset routine, that routine will take care of setting the card
3600    flip-flops appropriately.
3601 */
3602 
controller_reset(void)3603 static void controller_reset (void)
3604 {
3605 uint32 i;
3606 
3607 mpx_state = Idle_State;                                 /* idle state */
3608 
3609 mpx_cmd = No_Operation;                                 /* clear command */
3610 mpx_param = 0;                                          /* clear parameter */
3611 mpx_has_param = FALSE;                                  /* reset parameter flag */
3612 mpx_uien = FALSE;                                       /* disable interrupts */
3613 
3614 for (i = 0; i < MPX_PORTS; i++) {                       /* clear per-line variables */
3615     buf_init (iowrite, i);                              /* initialize write buffers */
3616     buf_init (ioread, i);                               /* initialize read buffers */
3617 
3618     mpx_key [i] = KEY_DEFAULT;                          /* clear port key to default */
3619 
3620     if (i == 0)                                         /* default port configurations */
3621         mpx_config [i] = SK_PWRUP_0;                    /* port 0 is separate from 1-7 */
3622     else
3623         mpx_config [i] = SK_PWRUP_1 | i;
3624 
3625     mpx_unit [i].rate_index = GET_BAUDRATE (mpx_config [i]);    /* set the baud rate index */
3626 
3627     mpx_rcvtype  [i] = RT_PWRUP;                        /* power on config for echoplex */
3628     mpx_charcnt  [i] = 0;                               /* clear character count */
3629     mpx_termcnt  [i] = 0;                               /* default termination character count */
3630     mpx_flowcntl [i] = 0;                               /* default flow control */
3631     mpx_flags    [i] = 0;                               /* clear state flags */
3632     mpx_enq_cntr [i] = 0;                               /* clear ENQ counter */
3633     mpx_ack_wait [i] = 0;                               /* clear ACK wait timer */
3634 
3635     sim_cancel (&mpx_unit [i]);                         /* cancel line I/O */
3636     }
3637 
3638 sim_cancel (&mpx_cntl);                                 /* cancel controller */
3639 
3640 return;
3641 }
3642 
3643 
3644 /* Translate port key to port number.
3645 
3646    Port keys are scanned in reverse port order, so if more than one port has the
3647    same port key, commands specifying that key will affect the highest numbered
3648    port.
3649 
3650    If a port key is the reserved value 255, then the port key has not been set.
3651    In this case, set the input buffer to 0xBAD0 and return -1 to indicate
3652    failure.
3653 */
3654 
key_to_port(uint32 key)3655 static int32 key_to_port (uint32 key)
3656 {
3657 int32 i;
3658 
3659 for (i = MPX_PORTS - 1; i >= 0; i--)                    /* scan in reverse order */
3660     if (mpx_key [i] == key)                             /* key found? */
3661         return i;                                       /* return port number */
3662 
3663 mpx_ibuf = ST_BAD_KEY;                                  /* key not found: set status */
3664 return -1;                                              /* return failure code */
3665 }
3666 
3667 
3668 /* Map the command opcode.
3669 
3670    The opcode in the high byte of the supplied "command" parameter is mapped to
3671    a controller opcode and returned to the caller.  If the command opcode is not
3672    defined, the No_Operation code is returned.
3673 
3674    The command opcodes to which the microprocessor controller responds are
3675    disjoint.  This makes it awkward to obtain the command names for tracing, as
3676    well as requiring a series of compare-and-jumps to decode the commands.
3677    Therefore, it is desirable to remap the command opcodes into a contiguous
3678    series of controller opcodes.
3679 
3680    The controller allows 48 one-word (100-series) commands and 48 two-word
3681    (300-series) commands, which would require a 96-way translation table if
3682    implemented directly.  This would be cumbersome.  Instead, we use a 16-way
3683    table for the relatively contiguous two-word command set and rely on direct
3684    mapping for the remaining contiguous subsets of the one-word command set.
3685 
3686    The only difficulty is the "Disable Unsolicited Interrupts" and "Abort DMA
3687    Transfer" commands, which share command opcode 103 and are differentiated by
3688    the key values (1 and 2, respectively).  These must be decoded with explicit
3689    tests.  However, we take advantage of the fact that the microprocessor
3690    firmware only checks for the key value 1 and assumes that any other value is
3691    a request to abort DMA, and that the "Disable Unsolicited Interrupts" command
3692    is issued at every entry into the RTE multiplexer driver and so is very
3693    frequently seen.
3694 
3695 
3696    Implementation notes:
3697 
3698     1.  The resulting map implementation, which looks complex, actually reduces
3699         to quite efficient machine code.
3700 
3701     2. The VCP commands are not actually implemented in the 12792 firmware (they
3702        are reserved for the 12040 A/L-Series multiplexer), so we decode them
3703        last, as that path should never be called.
3704 */
3705 
map_opcode(uint32 command)3706 static CNTLR_OPCODE map_opcode (uint32 command)
3707 {
3708 static const CNTLR_OPCODE remap [] = {          /* translation table for opcodes 301-320 */
3709     Request_Write_Buffer,                       /*   301 = Request write buffer */
3710     Write_Data,                                 /*   302 = Write data to buffer */
3711     Set_Port_Key,                               /*   303 = Set port key */
3712     Set_Receive_Type,                           /*   304 = Set receive type */
3713     Set_Character_Count,                        /*   305 = Set character count */
3714     Set_Flow_Control,                           /*   306 = Set flow control */
3715     Read_Data,                                  /*   307 = Read data from buffer */
3716     Download_Executable,                        /*   310 = Download executable */
3717     Connect_Line,                               /*   311 = Connect line */
3718     Disconnect_Line,                            /*   312 = Disconnect line */
3719     No_Operation,                               /*   313 = (undefined) */
3720     No_Operation,                               /*   314 = (undefined) */
3721     Get_Status,                                 /*   315 = Get modem/port status */
3722     Set_Modem_Loopback,                         /*   316 = Enable/disable modem loopback */
3723     No_Operation,                               /*   317 = (undefined) */
3724     Terminate_Receive_Buffer                    /*   320 = Terminate active receive buffer */
3725     };
3726 
3727 CNTLR_OPCODE opcode;
3728 const uint32 cmd_code = CN_OPCODE (command);
3729 
3730 if (command == TO_WORD (CMD_DISABLE, SUBCMD_UI))        /* if this is the "Disable UI" code */
3731     opcode = Disable_UI;                                /*   then translate it explicitly */
3732 
3733 else if (cmd_code >= CMD_NOP && cmd_code <= CMD_BINARY_READ)        /* otherwise if code is 100-107 */
3734     opcode = (CNTLR_OPCODE) (cmd_code - CMD_NOP) + No_Operation;    /*   then translate it directly */
3735 
3736 else if (cmd_code >= CMD_REQ_WRITE && cmd_code <= CMD_TERM_BUF) /* otherwise if code is 301-320 */
3737     opcode = remap [cmd_code - CMD_REQ_WRITE];                  /*   then translate it via the lookup table */
3738 
3739 else if (cmd_code >= CMD_VCP_PUT && cmd_code <= CMD_VCP_EXIT)           /* otherwise if code is 140-144 */
3740     opcode = (CNTLR_OPCODE) (cmd_code - CMD_VCP_PUT) + VCP_Put_Byte;    /*   then translate it directly */
3741 
3742 else if (cmd_code == CMD_VCP_ENTER)                     /* otherwise if this is the "Enter VCP" code */
3743     opcode = VCP_Enter_Mode;                            /*   then translate it explicitly */
3744 
3745 else                                                    /* otherwise the code is unknown */
3746     opcode = No_Operation;                              /*   so ignore it */
3747 
3748 return opcode;                                          /* return the translated opcode */
3749 }
3750 
3751 
3752 /* Buffer manipulation routines.
3753 
3754    The 12792 hardware provides 16K bytes of RAM to the microprocessor.  From
3755    this pool, the firmware allocates per-port read/write buffers and state
3756    variables, global variables, and the system stack.  Allocations are static
3757    and differ between firmware revisions.
3758 
3759    The A/B/C revisions allocate two 254-byte read buffers and two 254-byte write
3760    buffers per port.  Assuming an idle condition, the first write to a port
3761    transfers characters to the first write buffer.  When the transfer completes,
3762    the SIO begins transmitting.  During transmission, a second write can be
3763    initiated, which transfers characters to the second write buffer.  If a third
3764    write is attempted before the first buffer has been released, it will be
3765    denied until the SIO completes transmission; then, if enabled, an unsolicited
3766    interrupt will occur to announce buffer availability.  The "active" (filling)
3767    buffer alternates between the two.
3768 
3769    At idle, characters received will fill the first read buffer.  When the read
3770    completes according to the previously set termination criteria, an
3771    unsolicited interrupt will occur (if enabled) to announce buffer
3772    availability.  If more characters are received before the first buffer has
3773    been transferred to the CPU, they will fill the second buffer.  If that read
3774    also completes, additional characters will be discarded until the first
3775    buffer has been emptied.  The "active" (emptying) buffer alternates between
3776    the two.
3777 
3778    With this configuration, two one-character writes or reads will allocate both
3779    available buffers, even though each will be essentially empty.
3780 
3781    The D revision allocates one 1024-byte FIFO read buffer and one 892-byte
3782    write buffer per port.  As with the A/B/C revisions, the first write to a
3783    port transfers characters to the write buffer, and serial transmission begins
3784    when the write completes.  However, the write buffer is not a FIFO, so the
3785    host is not permitted another write request until the entire buffer has been
3786    transmitted.
3787 
3788    The read buffer is a FIFO.  Characters received are placed into the FIFO as a
3789    stream.  Unlike the A/B/C revisions, character editing and termination
3790    conditions are not evaluated until the buffer is read.  Therefore, a full
3791    1024 characters may be received before additional characters would be
3792    discarded.
3793 
3794    When the first character is received, an unsolicited interrupt occurs (if
3795    enabled) to announce data reception.  A host read may then be initiated.  The
3796    write buffer is used temporarily to process characters from the read buffer.
3797    Characters are copied from the read to the write buffer while editing as
3798    directed by the configuration accompanying the read request (e.g., deleting
3799    the character preceding a BS, stripping CR/LF, etc.).  When the termination
3800    condition is found, the read command completes.  Incoming characters may be
3801    added to the FIFO while this is occurring.
3802 
3803    In summary, the revision differences in buffer handling are:
3804 
3805      Revisions A/B/C:
3806       - two 254-byte receive buffers
3807       - a buffer is "full" when the terminator character or count is received
3808       - termination type must be established before the corresponding read
3809       - data is echoed as it is received
3810 
3811      Revision D:
3812       - one 1024-byte receive buffer
3813       - buffer is "full" only when 1024 characters are received
3814       - the concept of a buffer terminator does not apply, as the data is not
3815         examined until a read is requested and characters are retrieved from the
3816         FIFO.
3817       - data is not echoed until it is read
3818 
3819    To implement the C revision behavior, while preserving the option of reusing
3820    the buffer handlers for future D revision support, the dual 254-byte buffers
3821    are implemented as a single 514-byte circular FIFO with capacity limited to
3822    254 bytes per buffer.  This reserves space for a CR and LF and for a header
3823    byte in each buffer.  The header byte preserves per-buffer state information.
3824 
3825    In this implementation, the buffer "put" index points at the next free
3826    location, and the buffer "get" index points at the next character to
3827    retrieve.  In addition to "put" and "get" indexes, a third "separator" index
3828    is maintained to divide the FIFO into two areas corresponding to the two
3829    buffers, and a "buffer filling" flag is maintained for each FIFO that is set
3830    by the fill (put) routine and cleared by the terminate buffer routine.
3831 
3832    Graphically, the implementation is as follows for buffer "B[]", get "G", put
3833    "P", and separator "S" indexes:
3834 
3835      1. Initialize:                               2. Fill first buffer:
3836         G = S = P = 0                                B[P] = char; Incr (P)
3837 
3838         |------------------------------|             |---------|--------------------|
3839         G                                            G         P -->
3840         S                                            S
3841         P
3842 
3843      3. Terminate first buffer:                   4. Fill second buffer:
3844         if S == G then S = P else nop                B[P] = char; Incr (P)
3845 
3846         |------------|-----------------|             |------------|------|----------|
3847         G      /---> S                               G            S      P -->
3848         * ----/      P
3849 
3850      5. Terminate second buffer:                  6. Empty first buffer:
3851         if S == G then S = P else nop                char = B[G]; Incr (G)
3852 
3853         |------------|------------|----|             |----|-------|------------|----|
3854         G            S            P                       G -->   S            P
3855 
3856      7. First buffer is empty:                    8. Free first buffer:
3857         G == S                                       if not filling then S = P else nop
3858 
3859         |------------|------------|----|             |------------|------------|----|
3860                      G            P                               G      /---> S
3861                      S                                            * ----/      P
3862 
3863      9. Empty second buffer:                     10. Second buffer empty:
3864         char = B[G]; Incr (G)                        G == S
3865 
3866         |----------------|--------|----|             |-------------------------|----|
3867                          G -->    S                                            G
3868                                   P                                            S
3869                                                                                P
3870     11. Free second buffer:
3871         if not filling then S = P else nop
3872 
3873         |-------------------------|----|
3874                                   G
3875                                   S
3876                                   P
3877 
3878    We also provide the following utility routines:
3879 
3880     - Remove Character: Decr (P)
3881 
3882     - Cancel Buffer: if S == G then P = G else G = S
3883 
3884     - Buffer Length: if S < G then return S + BUFSIZE - G else return S - G
3885 
3886     - Buffers Available: if G == P then return 2 else if G != S != P then return
3887       0 else return 1
3888 
3889    The "buffer filling" flag is necessary for the "free" routine to decide
3890    whether to advance the separator index.  If the first buffer is to be freed,
3891    then G == S and S != P.  If the second buffer is already filled, then S = P.
3892    However, if the buffer is still filling, then S must remain at G.  This
3893    cannot be determined from G, S, and P alone.
3894 
3895    A "buffer emptying" flag is also employed to record whether the per-buffer
3896    header has been obtained.  This allows the buffer length to exclude the
3897    header and reflect only the characters present.
3898 */
3899 
3900 
3901 /* Increment a buffer index with wraparound */
3902 
buf_incr(BUF_INDEX index,uint32 port,IO_OPER rw,int increment)3903 static uint32 buf_incr (BUF_INDEX index, uint32 port, IO_OPER rw, int increment)
3904 {
3905 index [port] [rw] =
3906   (index [port] [rw] + buf_size [rw] + increment) % buf_size [rw];
3907 
3908 return index [port] [rw];
3909 }
3910 
3911 
3912 /* Initialize the buffer.
3913 
3914    Initialization sets the three indexes to zero and clears the buffer state
3915    flags.
3916 */
3917 
buf_init(IO_OPER rw,uint32 port)3918 static void buf_init (IO_OPER rw, uint32 port)
3919 {
3920 mpx_get [port] [rw] = 0;                                /* clear indexes */
3921 mpx_sep [port] [rw] = 0;
3922 mpx_put [port] [rw] = 0;
3923 
3924 if (rw == ioread)
3925     mpx_flags [mpx_port] &= ~(FL_RDFLAGS);              /* clear read buffer flags */
3926 else
3927     mpx_flags [mpx_port] &= ~(FL_WRFLAGS);              /* clear write buffer flags */
3928 return;
3929 }
3930 
3931 
3932 /* Get a character from the buffer.
3933 
3934    The character indicated by the "get" index is retrieved from the buffer, and
3935    the index is incremented with wraparound.  If the buffer is now empty, the
3936    "buffer emptying" flag is cleared.  Otherwise, it is set to indicate that
3937    characters have been removed from the buffer.
3938 */
3939 
buf_get(IO_OPER rw,uint32 port)3940 static uint8 buf_get (IO_OPER rw, uint32 port)
3941 {
3942 uint8 ch;
3943 uint32 index = mpx_get [port] [rw];                     /* current get index */
3944 
3945 if (rw == ioread)
3946     ch = mpx_rbuf [port] [index];                       /* get char from read buffer */
3947 else
3948     ch = mpx_wbuf [port] [index];                       /* get char from write buffer */
3949 
3950 buf_incr (mpx_get, port, rw, +1);                       /* increment circular get index */
3951 
3952 if (mpx_flags [port] & emptying_flags [rw])
3953     tprintf (mpx_dev, TRACE_FIFO, "Port %d character %s get from %s buffer [%d]\n",
3954              port, fmt_char (ch), io_op [rw], index);
3955 else
3956     tprintf (mpx_dev, TRACE_FIFO, "Port %d header %03o get from %s buffer [%d]\n",
3957              port, ch, io_op [rw], index);
3958 
3959 if (mpx_get [port] [rw] == mpx_sep [port] [rw])         /* buffer now empty? */
3960     mpx_flags [port] &= ~emptying_flags [rw];           /* clear "buffer emptying" flag */
3961 else
3962     mpx_flags [port] |= emptying_flags [rw];            /* set "buffer emptying" flag */
3963 
3964 return ch;
3965 }
3966 
3967 
3968 /* Put a character to the buffer.
3969 
3970    The character is written to the buffer in the slot indicated by the "put"
3971    index, and the index is incremented with wraparound.  The first character put
3972    to a new buffer reserves space for the header and sets the "buffer filling"
3973    flag.
3974 */
3975 
buf_put(IO_OPER rw,uint32 port,uint8 ch)3976 static void buf_put (IO_OPER rw, uint32 port, uint8 ch)
3977 {
3978 uint32 index;
3979 
3980 if (not (mpx_flags [port] & filling_flags [rw])) {     /* first put to this buffer? */
3981     mpx_flags [port] |= filling_flags [rw];             /* set buffer filling flag */
3982     index = mpx_put [port] [rw];                        /* get current put index */
3983     buf_incr (mpx_put, port, rw, +1);                   /* reserve space for header */
3984 
3985     tprintf (mpx_dev, TRACE_FIFO, "Port %d reserved header for %s buffer [%d]\n",
3986              port, io_op [rw], index);
3987     }
3988 
3989 index = mpx_put [port] [rw];                            /* get current put index */
3990 
3991 if (rw == ioread)
3992     mpx_rbuf [port] [index] = ch;                       /* put char in read buffer */
3993 else
3994     mpx_wbuf [port] [index] = ch;                       /* put char in write buffer */
3995 
3996 buf_incr (mpx_put, port, rw, +1);                       /* increment circular put index */
3997 
3998 tprintf (mpx_dev, TRACE_FIFO, "Port %d character %s put to %s buffer [%d]\n",
3999          port, fmt_char (ch), io_op [rw], index);
4000 return;
4001 }
4002 
4003 
4004 /* Remove the last character put to the buffer.
4005 
4006    The most-recent character put to the buffer is removed by decrementing the
4007    "put" index with wraparound.
4008 */
4009 
buf_remove(IO_OPER rw,uint32 port)4010 static void buf_remove (IO_OPER rw, uint32 port)
4011 {
4012 uint32 index;
4013 
4014 index = buf_incr (mpx_put, port, rw, -1);               /* decrement circular put index */
4015 
4016 tprintf (mpx_dev, TRACE_FIFO, "Port %d character %s removed from %s buffer [%d]\n",
4017          port, (rw == ioread ? fmt_char (mpx_rbuf [port] [index])
4018                              : fmt_char (mpx_wbuf [port] [index])),
4019          io_op [rw], index);
4020 return;
4021 }
4022 
4023 
4024 /* Terminate the buffer.
4025 
4026    The buffer is marked to indicate that filling is complete and that the next
4027    "put" operation should begin a new buffer.  The header value is stored in
4028    first byte of buffer, which is reserved, and the "buffer filling" flag is
4029    cleared.
4030 */
4031 
buf_term(IO_OPER rw,uint32 port,uint8 header)4032 static void buf_term (IO_OPER rw, uint32 port, uint8 header)
4033 {
4034 uint32 index = mpx_sep [port] [rw];                         /* separator index */
4035 
4036 if (rw == ioread)
4037     mpx_rbuf [port] [index] = header;                       /* put header in read buffer */
4038 else
4039     mpx_wbuf [port] [index] = header;                       /* put header in write buffer */
4040 
4041 mpx_flags [port] = mpx_flags [port] & ~filling_flags [rw];  /* clear filling flag */
4042 
4043 if (mpx_get [port] [rw] == index)                           /* reached separator? */
4044     mpx_sep [port] [rw] = mpx_put [port] [rw];              /* move sep to end of next buffer */
4045 
4046 tprintf (mpx_dev, TRACE_FIFO, "Port %d header %03o terminated %s buffer\n",
4047          port, header, io_op [rw]);
4048 return;
4049 }
4050 
4051 
4052 /* Free the buffer.
4053 
4054    The buffer is marked to indicate that it is available for reuse, and the
4055    "buffer emptying" flag is reset.
4056 */
4057 
buf_free(IO_OPER rw,uint32 port)4058 static void buf_free (IO_OPER rw, uint32 port)
4059 {
4060 if (not (mpx_flags [port] & filling_flags [rw]))            /* not filling next buffer? */
4061     mpx_sep [port] [rw] = mpx_put [port] [rw];              /* move separator to end of next buffer */
4062                                                             /* else it will be moved when terminated */
4063 mpx_flags [port] = mpx_flags [port] & ~emptying_flags [rw]; /* clear emptying flag */
4064 
4065 tprintf (mpx_dev, TRACE_FIFO, "Port %d released %s buffer\n", port, io_op [rw]);
4066 return;
4067 }
4068 
4069 
4070 /* Cancel the selected buffer.
4071 
4072    The selected buffer is marked to indicate that it is empty.  Either the "put"
4073    buffer or the "get" buffer may be selected.
4074 */
4075 
buf_cancel(IO_OPER rw,uint32 port,BUF_SELECT which)4076 static void buf_cancel (IO_OPER rw, uint32 port, BUF_SELECT which)
4077 {
4078 if (which == put) {                                     /* cancel put buffer? */
4079     mpx_put [port] [rw] = mpx_sep [port] [rw];          /* move put back to separator */
4080     mpx_flags [port] &= ~filling_flags [rw];            /* clear filling flag */
4081     }
4082 
4083 else {                                                  /* cancel get buffer */
4084     if (mpx_sep [port] [rw] == mpx_get [port] [rw]) {   /* filling first buffer? */
4085         mpx_put [port] [rw] = mpx_get [port] [rw];      /* cancel first buffer */
4086         mpx_flags [port] &= ~filling_flags [rw];        /* clear filling flag */
4087         }
4088 
4089     else {                                                  /* not filling first buffer */
4090         mpx_get [port] [rw] = mpx_sep [port] [rw];          /* cancel first buffer */
4091 
4092         if (not (mpx_flags [port] & filling_flags [rw]))    /* not filling second buffer? */
4093             mpx_sep [port] [rw] = mpx_put [port] [rw];      /* move separator to end of next buffer */
4094         }
4095 
4096     mpx_flags [port] &= ~emptying_flags [rw];           /* clear emptying flag */
4097     }
4098 
4099 tprintf (mpx_dev, TRACE_FIFO, "Port %d cancelled %s buffer\n", port, io_op [rw]);
4100 return;
4101 }
4102 
4103 
4104 /* Get the buffer length.
4105 
4106    The current length of the selected buffer (put or get) is returned.  For ease
4107    of use, the returned length does NOT include the header byte, i.e., it
4108    reflects only the characters contained in the buffer.
4109 
4110    If the put buffer is selected, and the buffer is filling, or the get buffer
4111    is selected, and the buffer is not emptying, then subtract one from the
4112    length for the allocated header.
4113 */
4114 
buf_len(IO_OPER rw,uint32 port,BUF_SELECT which)4115 static uint32 buf_len (IO_OPER rw, uint32 port, BUF_SELECT which)
4116 {
4117 int32 length;
4118 
4119 if (which == put)
4120     length = mpx_put [port] [rw] - mpx_sep [port] [rw] -        /* calculate length */
4121              ((mpx_flags [port] & filling_flags [rw]) != 0);    /* account for allocated header */
4122 
4123 else {
4124     length = mpx_sep [port] [rw] - mpx_get [port] [rw];         /* calculate length */
4125 
4126     if (length && not (mpx_flags [port] & emptying_flags [rw])) /* not empty and not yet emptying? */
4127         length = length - 1;                                    /* account for allocated header */
4128     }
4129 
4130 if (length < 0)                                                 /* is length negative? */
4131     return length + buf_size [rw];                              /* account for wraparound */
4132 else
4133     return length;
4134 }
4135 
4136 
4137 /* Return the number of free buffers available.
4138 
4139    Either 0, 1, or 2 free buffers will be available.  A buffer is available if
4140    it contains no characters (including the header byte).
4141 */
4142 
buf_avail(IO_OPER rw,uint32 port)4143 static uint32 buf_avail (IO_OPER rw, uint32 port)
4144 {
4145 if (mpx_get [port] [rw] == mpx_put [port] [rw])             /* get and put indexes equal? */
4146     return 2;                                               /* all buffers are free */
4147 
4148 else if ((mpx_get [port] [rw] != mpx_sep [port] [rw]) &&    /* get, separator, and put */
4149          (mpx_sep [port] [rw] != mpx_put [port] [rw]))      /*   all different? */
4150     return 0;                                               /* no buffers are free */
4151 
4152 else
4153     return 1;                                               /* one buffer free */
4154 }
4155