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