First Commit of my working state
[simh.git] / HP2100 / hp2100_mux.c
1 /* hp2100_mux.c: HP 2100 12920A terminal multiplexor simulator
2
3 Copyright (c) 2002-2008, Robert M Supnik
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 ROBERT M SUPNIK 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 Robert M Supnik 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 Robert M Supnik.
25
26 mux,muxl,muxc 12920A terminal multiplexor
27
28 16-Apr-08 JDB Sync mux poll with console poll for idle compatibility
29 06-Mar-07 JDB Corrected "mux_sta" size from 16 to 21 elements
30 Fixed "muxc_reset" to clear lines 16-20
31 26-Feb-07 JDB Added debug printouts
32 Fixed control card OTx to set current channel number
33 Fixed to set "muxl_ibuf" in response to a transmit interrupt
34 Changed "mux_xbuf", "mux_rbuf" declarations from 8 to 16 bits
35 Fixed to set "mux_rchp" when a line break is received
36 Fixed incorrect "odd_par" table values
37 Reversed test in "RCV_PAR" to return "LIL_PAR" on odd parity
38 Fixed mux reset (ioCRS) to clear port parameters
39 Fixed to use PUT_DCH instead of PUT_CCH for data channel status
40 10-Feb-07 JDB Added DIAG/TERM modifiers to implement diagnostic mode
41 28-Dec-06 JDB Added ioCRS state to I/O decoders
42 02-Jun-06 JDB Fixed compiler warning for mux_ldsc init
43 22-Nov-05 RMS Revised for new terminal processing routines
44 29-Jun-05 RMS Added SET MUXLn DISCONNECT
45 07-Oct-04 JDB Allow enable/disable from any device
46 26-Apr-04 RMS Fixed SFS x,C and SFC x,C
47 Implemented DMA SRQ (follows FLG)
48 05-Jan-04 RMS Revised for tmxr library changes
49 21-Dec-03 RMS Added invalid character screening for TSB (from Mike Gemeny)
50 09-May-03 RMS Added network device flag
51 01-Nov-02 RMS Added 7B/8B support
52 22-Aug-02 RMS Updated for changes to sim_tmxr
53
54 The 12920A consists of three separate devices
55
56 mux scanner (upper data card)
57 muxl lines (lower data card)
58 muxm modem control (control card)
59
60 The lower data card has no CMD flop; the control card has no CMD flop.
61 The upper data card has none of the usual flops.
62
63 Reference:
64 - 12920A Asynchronous Multiplexer Interface Kits Operating and Service
65 Manual (12920-90001, Oct-1972)
66 */
67
68 #include "hp2100_defs.h"
69 #include "sim_sock.h"
70 #include "sim_tmxr.h"
71 #include <ctype.h>
72
73 #define MUX_LINES 16 /* user lines */
74 #define MUX_ILINES 5 /* diag rcv only */
75 #define UNIT_V_MDM (TTUF_V_UF + 0) /* modem control */
76 #define UNIT_V_DIAG (TTUF_V_UF + 1) /* loopback diagnostic */
77 #define UNIT_MDM (1 << UNIT_V_MDM)
78 #define UNIT_DIAG (1 << UNIT_V_DIAG)
79 #define MUXL_WAIT 500
80
81 /* Channel number (OTA upper, LIA lower or upper) */
82
83 #define MUX_V_CHAN 10 /* channel num */
84 #define MUX_M_CHAN 037
85 #define MUX_CHAN(x) (((x) >> MUX_V_CHAN) & MUX_M_CHAN)
86
87 /* OTA, lower = parameters or data */
88
89 #define OTL_P 0100000 /* parameter */
90 #define OTL_TX 0040000 /* transmit */
91 #define OTL_ENB 0020000 /* enable */
92 #define OTL_TPAR 0010000 /* xmt parity */
93 #define OTL_ECHO 0010000 /* rcv echo */
94 #define OTL_DIAG 0004000 /* diagnose */
95 #define OTL_SYNC 0004000 /* sync */
96 #define OTL_V_LNT 8 /* char length */
97 #define OTL_M_LNT 07
98 #define OTL_LNT(x) (((x) >> OTL_V_LNT) & OTL_M_LNT)
99 #define OTL_V_BAUD 0 /* baud rate */
100 #define OTL_M_BAUD 0377
101 #define OTL_BAUD(x) (((x) >> OTL_V_BAUD) & OTL_M_BAUD)
102 #define OTL_CHAR 03777 /* char mask */
103 #define OTL_PAR 0200 /* char parity */
104
105 /* LIA, lower = received data */
106
107 #define LIL_PAR 0100000 /* parity */
108 #define PUT_DCH(x) (((x) & MUX_M_CHAN) << MUX_V_CHAN)
109 #define LIL_CHAR 01777 /* character */
110
111 /* LIA, upper = status */
112
113 #define LIU_SEEK 0100000 /* seeking NI */
114 #define LIU_DG 0000010 /* diagnose */
115 #define LIU_BRK 0000004 /* break */
116 #define LIU_LOST 0000002 /* char lost */
117 #define LIU_TR 0000001 /* trans/rcv */
118
119 /* OTA, control */
120
121 #define OTC_SCAN 0100000 /* scan */
122 #define OTC_UPD 0040000 /* update */
123 #define OTC_V_CHAN 10 /* channel */
124 #define OTC_M_CHAN 017
125 #define OTC_CHAN(x) (((x) >> OTC_V_CHAN) & OTC_M_CHAN)
126 #define OTC_EC2 0000200 /* enable Cn upd */
127 #define OTC_EC1 0000100
128 #define OTC_C2 0000040 /* Cn flops */
129 #define OTC_C1 0000020
130 #define OTC_V_C 4 /* S1 to C1 */
131 #define OTC_ES2 0000010 /* enb comparison */
132 #define OTC_ES1 0000004
133 #define OTC_V_ES 2
134 #define OTC_SS2 0000002 /* SSn flops */
135 #define OTC_SS1 0000001
136 #define OTC_RW (OTC_ES2|OTC_ES1|OTC_SS2|OTC_SS1)
137 #define RTS OCT_C2 /* C2 = rts */
138 #define DTR OTC_C1 /* C1 = dtr */
139
140 /* LIA, control */
141
142 #define LIC_MBO 0140000 /* always set */
143 #define LIC_V_CHAN 10 /* channel */
144 #define LIC_M_CHAN 017
145 #define PUT_CCH(x) (((x) & OTC_M_CHAN) << OTC_V_CHAN)
146 #define LIC_I2 0001000 /* change flags */
147 #define LIC_I1 0000400
148 #define LIC_S2 0000002 /* Sn flops */
149 #define LIC_S1 0000001
150 #define LIC_V_I 8 /* S1 to I1 */
151 #define CDET LIC_S2 /* S2 = cdet */
152 #define DSR LIC_S1 /* S1 = dsr */
153
154 #define LIC_TSTI(ch) (((muxc_lia[ch] ^ muxc_ota[ch]) & \
155 ((muxc_ota[ch] & (OTC_ES2|OTC_ES1)) >> OTC_V_ES)) \
156 << LIC_V_I)
157
158 /* Debug flags */
159
160 #define DEB_CMDS (1 << 0) /* Command initiation and completion */
161 #define DEB_CPU (1 << 1) /* CPU I/O */
162 #define DEB_XFER (1 << 2) /* Socket receive and transmit */
163
164 extern uint32 PC;
165 extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2];
166 extern FILE *sim_deb;
167
168 uint16 mux_sta[MUX_LINES + MUX_ILINES]; /* line status */
169 uint16 mux_rpar[MUX_LINES + MUX_ILINES]; /* rcv param */
170 uint16 mux_xpar[MUX_LINES]; /* xmt param */
171 uint16 mux_rbuf[MUX_LINES + MUX_ILINES]; /* rcv buf */
172 uint16 mux_xbuf[MUX_LINES]; /* xmt buf */
173 uint8 mux_rchp[MUX_LINES + MUX_ILINES]; /* rcv chr pend */
174 uint8 mux_xdon[MUX_LINES]; /* xmt done */
175 uint8 muxc_ota[MUX_LINES]; /* ctrl: Cn,ESn,SSn */
176 uint8 muxc_lia[MUX_LINES]; /* ctrl: Sn */
177 uint32 muxl_ibuf = 0; /* low in: rcv data */
178 uint32 muxl_obuf = 0; /* low out: param */
179 uint32 muxu_ibuf = 0; /* upr in: status */
180 uint32 muxu_obuf = 0; /* upr out: chan */
181 uint32 muxc_chan = 0; /* ctrl chan */
182 uint32 muxc_scan = 0; /* ctrl scan */
183
184 TMLN mux_ldsc[MUX_LINES] = { { 0 } }; /* line descriptors */
185 TMXR mux_desc = { MUX_LINES, 0, 0, mux_ldsc }; /* mux descriptor */
186
187 DEVICE muxl_dev, muxu_dev, muxc_dev;
188 int32 muxlio (int32 inst, int32 IR, int32 dat);
189 int32 muxuio (int32 inst, int32 IR, int32 dat);
190 int32 muxcio (int32 inst, int32 IR, int32 dat);
191 t_stat muxi_svc (UNIT *uptr);
192 t_stat muxo_svc (UNIT *uptr);
193 t_stat muxc_reset (DEVICE *dptr);
194 t_stat mux_attach (UNIT *uptr, char *cptr);
195 t_stat mux_detach (UNIT *uptr);
196 t_stat mux_setdiag (UNIT *uptr, int32 val, char *cptr, void *desc);
197 t_stat mux_summ (FILE *st, UNIT *uptr, int32 val, void *desc);
198 t_stat mux_show (FILE *st, UNIT *uptr, int32 val, void *desc);
199 void mux_data_int (void);
200 void mux_ctrl_int (void);
201 void mux_diag (int32 c);
202
203 static uint8 odd_par[256] = {
204 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 000-017 */
205 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, /* 020-037 */
206 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, /* 040-067 */
207 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 060-077 */
208 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, /* 100-117 */
209 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 120-137 */
210 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 140-157 */
211 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, /* 160-177 */
212 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, /* 200-217 */
213 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 220-237 */
214 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 240-267 */
215 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, /* 260-277 */
216 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, /* 300-317 */
217 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, /* 320-337 */
218 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, /* 340-357 */
219 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1 /* 360-377 */
220 };
221
222 #define RCV_PAR(x) (odd_par[(x) & 0377] ? 0 : LIL_PAR)
223 #define XMT_PAR(x) (odd_par[(x) & 0377] ? 0 : OTL_PAR)
224
225 /* Debug flags table */
226
227 DEBTAB mux_deb[] = {
228 { "CMDS", DEB_CMDS },
229 { "CPU", DEB_CPU },
230 { "XFER", DEB_XFER },
231 { NULL, 0 } };
232
233 DIB mux_dib[] = {
234 { MUXL, 0, 0, 0, 0, 0, &muxlio },
235 { MUXU, 0, 0, 0, 0, 0, &muxuio }
236 };
237
238 #define muxl_dib mux_dib[0]
239 #define muxu_dib mux_dib[1]
240
241 /* MUX data structures
242
243 muxu_dev MUX device descriptor
244 muxu_unit MUX unit descriptor
245 muxu_reg MUX register list
246 muxu_mod MUX modifiers list
247 */
248
249 UNIT muxu_unit = { UDATA (&muxi_svc, UNIT_ATTABLE, 0), POLL_WAIT };
250
251 REG muxu_reg[] = {
252 { ORDATA (IBUF, muxu_ibuf, 16) },
253 { ORDATA (OBUF, muxu_obuf, 16) },
254 { FLDATA (CMD, muxu_dib.cmd, 0), REG_HRO },
255 { FLDATA (CTL, muxu_dib.ctl, 0), REG_HRO },
256 { FLDATA (FLG, muxu_dib.flg, 0), REG_HRO },
257 { FLDATA (FBF, muxu_dib.fbf, 0), REG_HRO },
258 { FLDATA (SRQ, muxu_dib.srq, 0), REG_HRO },
259 { ORDATA (DEVNO, muxu_dib.devno, 6), REG_HRO },
260 { NULL }
261 };
262
263 MTAB muxu_mod[] = {
264 { UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", &mux_setdiag },
265 { UNIT_DIAG, 0, "terminal mode", "TERM", &mux_setdiag },
266 { UNIT_ATT, UNIT_ATT, "connections", NULL, NULL, &mux_summ },
267 { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL,
268 NULL, &mux_show, NULL },
269 { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL,
270 NULL, &mux_show, NULL },
271 { MTAB_XTD|MTAB_VDV, 1, "DEVNO", "DEVNO",
272 &hp_setdev, &hp_showdev, &muxl_dev },
273 { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT",
274 &tmxr_dscln, NULL, &mux_desc },
275 { 0 }
276 };
277
278 DEVICE muxu_dev = {
279 "MUX", &muxu_unit, muxu_reg, muxu_mod,
280 1, 10, 31, 1, 8, 8,
281 &tmxr_ex, &tmxr_dep, &muxc_reset,
282 NULL, &mux_attach, &mux_detach,
283 &muxu_dib, DEV_NET | DEV_DISABLE | DEV_DEBUG,
284 0, mux_deb, NULL, NULL
285 };
286
287 /* MUXL data structures
288
289 muxl_dev MUXL device descriptor
290 muxl_unit MUXL unit descriptor
291 muxl_reg MUXL register list
292 muxl_mod MUXL modifiers list
293 */
294
295 UNIT muxl_unit[] = {
296 { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT },
297 { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT },
298 { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT },
299 { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT },
300 { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT },
301 { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT },
302 { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT },
303 { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT },
304 { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT },
305 { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT },
306 { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT },
307 { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT },
308 { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT },
309 { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT },
310 { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT },
311 { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT },
312 { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT }
313 };
314
315 MTAB muxl_mod[] = {
316 { TT_MODE, TT_MODE_UC, "UC", "UC", NULL },
317 { TT_MODE, TT_MODE_7B, "7b", "7B", NULL },
318 { TT_MODE, TT_MODE_8B, "8b", "8B", NULL },
319 { TT_MODE, TT_MODE_7P, "7p", "7P", NULL },
320 { UNIT_MDM, 0, "no dataset", "NODATASET", NULL },
321 { UNIT_MDM, UNIT_MDM, "dataset", "DATASET", NULL },
322 { MTAB_XTD|MTAB_VUN, 0, NULL, "DISCONNECT",
323 &tmxr_dscln, NULL, &mux_desc },
324 { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG",
325 &tmxr_set_log, &tmxr_show_log, &mux_desc },
326 { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG",
327 &tmxr_set_nolog, NULL, &mux_desc },
328 { MTAB_XTD|MTAB_VDV, 1, "DEVNO", "DEVNO",
329 &hp_setdev, &hp_showdev, &muxl_dev },
330 { 0 }
331 };
332
333 REG muxl_reg[] = {
334 { FLDATA (CMD, muxl_dib.cmd, 0), REG_HRO },
335 { FLDATA (CTL, muxl_dib.ctl, 0) },
336 { FLDATA (FLG, muxl_dib.flg, 0) },
337 { FLDATA (FBF, muxl_dib.fbf, 0) },
338 { FLDATA (SRQ, muxl_dib.srq, 0) },
339 { BRDATA (STA, mux_sta, 8, 16, MUX_LINES + MUX_ILINES) },
340 { BRDATA (RPAR, mux_rpar, 8, 16, MUX_LINES + MUX_ILINES) },
341 { BRDATA (XPAR, mux_xpar, 8, 16, MUX_LINES) },
342 { BRDATA (RBUF, mux_rbuf, 8, 16, MUX_LINES + MUX_ILINES) },
343 { BRDATA (XBUF, mux_xbuf, 8, 16, MUX_LINES) },
344 { BRDATA (RCHP, mux_rchp, 8, 1, MUX_LINES + MUX_ILINES) },
345 { BRDATA (XDON, mux_xdon, 8, 1, MUX_LINES) },
346 { URDATA (TIME, muxl_unit[0].wait, 10, 24, 0,
347 MUX_LINES, REG_NZ + PV_LEFT) },
348 { ORDATA (DEVNO, muxl_dib.devno, 6), REG_HRO },
349 { NULL }
350 };
351
352 DEVICE muxl_dev = {
353 "MUXL", muxl_unit, muxl_reg, muxl_mod,
354 MUX_LINES, 10, 31, 1, 8, 8,
355 NULL, NULL, &muxc_reset,
356 NULL, NULL, NULL,
357 &muxl_dib, DEV_DISABLE
358 };
359
360 /* MUXM data structures
361
362 muxc_dev MUXM device descriptor
363 muxc_unit MUXM unit descriptor
364 muxc_reg MUXM register list
365 muxc_mod MUXM modifiers list
366 */
367
368 DIB muxc_dib = { MUXC, 0, 0, 0, 0, 0, &muxcio };
369
370 UNIT muxc_unit = { UDATA (NULL, 0, 0) };
371
372 REG muxc_reg[] = {
373 { FLDATA (CMD, muxc_dib.cmd, 0), REG_HRO },
374 { FLDATA (CTL, muxc_dib.ctl, 0) },
375 { FLDATA (FLG, muxc_dib.flg, 0) },
376 { FLDATA (FBF, muxc_dib.fbf, 0) },
377 { FLDATA (SRQ, muxc_dib.srq, 0) },
378 { FLDATA (SCAN, muxc_scan, 0) },
379 { ORDATA (CHAN, muxc_chan, 4) },
380 { BRDATA (DSO, muxc_ota, 8, 6, MUX_LINES) },
381 { BRDATA (DSI, muxc_lia, 8, 2, MUX_LINES) },
382 { ORDATA (DEVNO, muxc_dib.devno, 6), REG_HRO },
383 { NULL }
384 };
385
386 MTAB muxc_mod[] = {
387 { MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
388 &hp_setdev, &hp_showdev, &muxc_dev },
389 { 0 }
390 };
391
392 DEVICE muxc_dev = {
393 "MUXM", &muxc_unit, muxc_reg, muxc_mod,
394 1, 10, 31, 1, 8, 8,
395 NULL, NULL, &muxc_reset,
396 NULL, NULL, NULL,
397 &muxc_dib, DEV_DISABLE
398 };
399
400 /* I/O instructions: data cards
401
402 Implementation note: the operating manual says that "at least 100
403 milliseconds of CLC 0s must be programmed" by systems employing the
404 multiplexer to ensure that the multiplexer resets. In practice, such systems
405 issue 128K CLC 0 instructions. As we provide debug logging of multiplexer
406 resets, a CRS counter is used to ensure that only one debug line is printed
407 in response to these 128K CRS invocations.
408 */
409
410 int32 muxlio (int32 inst, int32 IR, int32 dat)
411 {
412 int32 dev, ln;
413 t_bool is_crs;
414 static uint32 crs_count = 0; /* cntr for crs repeat */
415
416 dev = IR & I_DEVMASK; /* get device no */
417 is_crs = FALSE;
418
419 switch (inst) { /* case on opcode */
420
421 case ioFLG: /* flag clear/set */
422 if ((IR & I_HC) == 0) { setFSR (dev); } /* STF */
423 break;
424
425 case ioSFC: /* skip flag clear */
426 if (FLG (dev) == 0) PC = (PC + 1) & VAMASK;
427 break;
428
429 case ioSFS: /* skip flag set */
430 if (FLG (dev) != 0) PC = (PC + 1) & VAMASK;
431 break;
432
433 case ioOTX: /* output */
434 muxl_obuf = dat; /* store data */
435
436 if (DEBUG_PRI (muxu_dev, DEB_CPU))
437 if (dat & OTL_P)
438 fprintf (sim_deb, ">>MUXl OTx: Parameter = %06o\n", dat);
439 else
440 fprintf (sim_deb, ">>MUXl OTx: Data = %06o\n", dat);
441 break;
442
443 case ioLIX: /* load */
444 dat = 0;
445
446 case ioMIX: /* merge */
447 dat = dat | muxl_ibuf;
448
449 if (DEBUG_PRI (muxu_dev, DEB_CPU))
450 fprintf (sim_deb, ">>MUXl LIx: Data = %06o\n", dat);
451 break;
452
453 case ioCRS: /* control reset */
454 is_crs = TRUE;
455
456 if (crs_count) /* already reset? */
457 break; /* skip redundant clear */
458
459 for (ln = 0; ln < MUX_LINES; ln++) { /* clear transmit info */
460 mux_xbuf[ln] = mux_xpar[ln] = 0;
461 muxc_ota[ln] = muxc_lia[ln] = mux_xdon[ln] = 0;
462 }
463
464 for (ln = 0; ln < (MUX_LINES + MUX_ILINES); ln++) {
465 mux_rbuf[ln] = mux_rpar[ln] = 0; /* clear receive info */
466 mux_sta[ln] = mux_rchp[ln] = 0;
467 } /* fall into CLC SC */
468
469 case ioCTL: /* control clear/set */
470 if (IR & I_CTL) { /* CLC */
471 clrCTL (dev);
472
473 if (DEBUG_PRI (muxu_dev, DEB_CMDS))
474 fprintf (sim_deb, ">>MUXl CLC: Data interrupt inhibited\n");
475 }
476 else { /* STC */
477 setCTL (dev); /* set ctl */
478 ln = MUX_CHAN (muxu_obuf); /* get chan # */
479
480 if (muxl_obuf & OTL_TX) { /* transmit? */
481 if (ln < MUX_LINES) { /* line valid? */
482 if (muxl_obuf & OTL_P) { /* parameter? */
483 mux_xpar[ln] = muxl_obuf; /* store param value */
484 if (DEBUG_PRI (muxu_dev, DEB_CMDS))
485 fprintf (sim_deb,
486 ">>MUXl STC: Transmit channel %d parameter %06o stored\n",
487 ln, muxl_obuf);
488 }
489
490 else { /* data */
491 if (mux_xpar[ln] & OTL_TPAR) /* parity requested? */
492 muxl_obuf = /* add parity bit */
493 muxl_obuf & ~OTL_PAR |
494 XMT_PAR(muxl_obuf);
495 mux_xbuf[ln] = muxl_obuf; /* load buffer */
496
497 if (sim_is_active (&muxl_unit[ln])) { /* still working? */
498 mux_sta[ln] = mux_sta[ln] | LIU_LOST; /* char lost */
499 if (DEBUG_PRI (muxu_dev, DEB_CMDS))
500 fprintf (sim_deb,
501 ">>MUXl STC: Transmit channel %d data overrun\n", ln);
502 }
503 else {
504 if (muxu_unit.flags & UNIT_DIAG) /* loopback? */
505 mux_ldsc[ln].conn = 1; /* connect this line */
506 sim_activate (&muxl_unit[ln], muxl_unit[ln].wait);
507 if (DEBUG_PRI (muxu_dev, DEB_CMDS))
508 fprintf (sim_deb,
509 ">>MUXl STC: Transmit channel %d data %06o scheduled\n",
510 ln, muxl_obuf);
511 }
512 }
513 }
514 else if (DEBUG_PRI (muxu_dev, DEB_CMDS)) /* line invalid */
515 fprintf (sim_deb, ">>MUXl STC: Transmit channel %d invalid\n", ln);
516 }
517
518 else /* receive */
519 if (ln < (MUX_LINES + MUX_ILINES)) { /* line valid? */
520 if (muxl_obuf & OTL_P) { /* parameter? */
521 mux_rpar[ln] = muxl_obuf; /* store param value */
522 if (DEBUG_PRI (muxu_dev, DEB_CMDS))
523 fprintf (sim_deb,
524 ">>MUXl STC: Receive channel %d parameter %06o stored\n",
525 ln, muxl_obuf);
526 }
527
528 else if (DEBUG_PRI (muxu_dev, DEB_CMDS)) /* data (invalid action) */
529 fprintf (sim_deb,
530 ">>MUXl STC: Receive channel %d parameter %06o invalid action\n",
531 ln, muxl_obuf);
532 }
533
534 else if (DEBUG_PRI (muxu_dev, DEB_CMDS)) /* line invalid */
535 fprintf (sim_deb, ">>MUXl STC: Receive channel %d invalid\n", ln);
536 } /* end STC */
537 break;
538
539 default:
540 break;
541 }
542
543 if (is_crs) /* control reset? */
544 crs_count = crs_count + 1; /* increment count */
545
546 else if (crs_count) { /* something else */
547 if (DEBUG_PRI (muxu_dev, DEB_CMDS)) /* report reset count */
548 fprintf (sim_deb,
549 ">>MUXl CRS: Multiplexer reset %d times\n", crs_count);
550 crs_count = 0; /* clear counter */
551 }
552
553 if (IR & I_HC) { /* H/C option */
554 clrFSR (dev); /* clear flag */
555 mux_data_int (); /* look for new int */
556 }
557 return dat;
558 }
559
560 int32 muxuio (int32 inst, int32 IR, int32 dat)
561 {
562 switch (inst) { /* case on opcode */
563
564 case ioOTX: /* output */
565 muxu_obuf = dat; /* store data */
566
567 if (DEBUG_PRI (muxu_dev, DEB_CPU))
568 fprintf (sim_deb, ">>MUXu OTx: Data channel = %d\n", MUX_CHAN(dat));
569 break;
570
571 case ioLIX: /* load */
572 dat = 0;
573
574 case ioMIX: /* merge */
575 dat = dat | muxu_ibuf;
576
577 if (DEBUG_PRI (muxu_dev, DEB_CPU))
578 fprintf (sim_deb, ">>MUXu LIx: Status = %06o, channel = %d\n", dat, MUX_CHAN(dat));
579 break;
580
581 default:
582 break;
583 }
584
585 return dat;
586 }
587
588 /* I/O instructions: control card
589
590 In diagnostic mode, the control signals C1 and C2 are looped back to status
591 signals S1 and S2. Changing the control signals may cause an interrupt, so a
592 test is performed after OTx processing.
593 */
594
595 int32 muxcio (int32 inst, int32 IR, int32 dat)
596 {
597 int32 dev, ln, t, old;
598
599 dev = IR & I_DEVMASK; /* get device no */
600 switch (inst) { /* case on opcode */
601
602 case ioFLG: /* flag clear/set */
603 if ((IR & I_HC) == 0) { setFSR (dev); } /* STF */
604 break;
605
606 case ioSFC: /* skip flag clear */
607 if (FLG (dev) == 0) PC = (PC + 1) & VAMASK;
608 break;
609
610 case ioSFS: /* skip flag set */
611 if (FLG (dev) != 0) PC = (PC + 1) & VAMASK;
612 break;
613
614 case ioOTX: /* output */
615 ln = muxc_chan = OTC_CHAN (dat); /* set channel */
616
617 if (dat & OTC_SCAN) muxc_scan = 1; /* set scan flag */
618 else muxc_scan = 0;
619
620 if (dat & OTC_UPD) { /* update? */
621 old = muxc_ota[ln]; /* save prior val */
622 muxc_ota[ln] = /* save ESn,SSn */
623 (muxc_ota[ln] & ~OTC_RW) | (dat & OTC_RW);
624
625 if (dat & OTC_EC2) /* if EC2, upd C2 */
626 muxc_ota[ln] =
627 (muxc_ota[ln] & ~OTC_C2) | (dat & OTC_C2);
628
629 if (dat & OTC_EC1) /* if EC1, upd C1 */
630 muxc_ota[ln] =
631 (muxc_ota[ln] & ~OTC_C1) | (dat & OTC_C1);
632
633 if (muxu_unit.flags & UNIT_DIAG) /* loopback? */
634 muxc_lia[ln ^ 1] = /* set S1, S2 to C1, C2 */
635 (muxc_lia[ln ^ 1] & ~(LIC_S2 | LIC_S1)) |
636 (muxc_ota[ln] & (OTC_C1 | OTC_C2)) >> OTC_V_C;
637
638 else if ((muxl_unit[ln].flags & UNIT_MDM) && /* modem ctrl? */
639 (old & DTR) && /* DTR drop? */
640 !(muxc_ota[ln] & DTR)) {
641 tmxr_linemsg (&mux_ldsc[ln], "\r\nLine hangup\r\n");
642 tmxr_reset_ln (&mux_ldsc[ln]); /* reset line */
643 muxc_lia[ln] = 0; /* dataset off */
644 }
645 } /* end update */
646
647 if (DEBUG_PRI (muxu_dev, DEB_CPU))
648 fprintf (sim_deb, ">>MUXc OTx: Parameter = %06o, channel = %d\n",
649 dat, ln);
650
651 if ((muxu_unit.flags & UNIT_DIAG) && /* loopback? */
652 (!FLG(muxc_dib.devno))) /* flag clear? */
653 mux_ctrl_int (); /* status chg may interrupt */
654 break;
655
656 case ioLIX: /* load */
657 dat = 0;
658
659 case ioMIX: /* merge */
660 t = LIC_MBO | PUT_CCH (muxc_chan) | /* mbo, chan num */
661 LIC_TSTI (muxc_chan) | /* I2, I1 */
662 (muxc_ota[muxc_chan] & (OTC_ES2 | OTC_ES1)) | /* ES2, ES1 */
663 (muxc_lia[muxc_chan] & (LIC_S2 | LIC_S1)); /* S2, S1 */
664 dat = dat | t; /* return status */
665
666 if (DEBUG_PRI (muxu_dev, DEB_CPU))
667 fprintf (sim_deb, ">>MUXc LIx: Status = %06o, channel = %d\n",
668 dat, muxc_chan);
669
670 muxc_chan = (muxc_chan + 1) & LIC_M_CHAN; /* incr channel */
671 break;
672
673 case ioCRS: /* control reset */
674 case ioCTL: /* ctrl clear/set */
675 if (IR & I_CTL) { clrCTL (dev); } /* CLC */
676 else { setCTL (dev); } /* STC */
677 break;
678
679 default:
680 break;
681 }
682
683 if (IR & I_HC) { /* H/C option */
684 clrFSR (dev); /* clear flag */
685 mux_ctrl_int (); /* look for new int */
686 }
687 return dat;
688 }
689
690 /* Unit service - receive side
691
692 Poll for new connections
693 Poll all active lines for input
694 */
695
696 t_stat muxi_svc (UNIT *uptr)
697 {
698 int32 ln, c;
699 t_bool loopback;
700
701 loopback = ((muxu_unit.flags & UNIT_DIAG) != 0); /* diagnostic mode? */
702
703 if (!loopback) { /* terminal mode? */
704 if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */
705 muxu_unit.wait = sync_poll (SERVICE); /* synchronize poll */
706 sim_activate (uptr, muxu_unit.wait); /* continue poll */
707 ln = tmxr_poll_conn (&mux_desc); /* look for connect */
708 if (ln >= 0) { /* got one? */
709 if ((muxl_unit[ln].flags & UNIT_MDM) && /* modem ctrl? */
710 (muxc_ota[ln] & DTR)) /* DTR? */
711 muxc_lia[ln] = muxc_lia[ln] | CDET; /* set cdet */
712 muxc_lia[ln] = muxc_lia[ln] | DSR; /* set dsr */
713 mux_ldsc[ln].rcve = 1; /* rcv enabled */
714 }
715 tmxr_poll_rx (&mux_desc); /* poll for input */
716 }
717
718 for (ln = 0; ln < MUX_LINES; ln++) { /* loop thru lines */
719 if (mux_ldsc[ln].conn) { /* connected? */
720 if (loopback) { /* diagnostic mode? */
721 c = mux_xbuf[ln ^ 1] & OTL_CHAR; /* get char from xmit line */
722 if (c == 0) /* all char bits = 0? */
723 c = c | SCPE_BREAK; /* set break flag */
724 mux_ldsc[ln].conn = 0; /* clear connection */
725 }
726
727 else
728 c = tmxr_getc_ln (&mux_ldsc[ln]); /* get char from Telnet */
729
730 if (c) { /* valid char? */
731 if (c & SCPE_BREAK) { /* break? */
732 mux_sta[ln] = mux_sta[ln] | LIU_BRK;
733 mux_rbuf[ln] = 0; /* no char */
734 }
735 else { /* normal */
736 if (mux_rchp[ln]) /* char already pending? */
737 mux_sta[ln] = mux_sta[ln] | LIU_LOST;
738
739 if (!loopback) { /* terminal mode? */
740 c = sim_tt_inpcvt (c, TT_GET_MODE (muxl_unit[ln].flags));
741 if (mux_rpar[ln] & OTL_ECHO) { /* echo? */
742 TMLN *lp = &mux_ldsc[ln]; /* get line */
743 tmxr_putc_ln (lp, c); /* output char */
744 tmxr_poll_tx (&mux_desc); /* poll xmt */
745 }
746 }
747 mux_rbuf[ln] = c; /* save char */
748 }
749
750 mux_rchp[ln] = 1; /* char pending */
751
752 if (DEBUG_PRI (muxu_dev, DEB_XFER))
753 fprintf (sim_deb, ">>MUXi svc: Line %d character %06o received\n",
754 ln, c);
755
756 if (mux_rpar[ln] & OTL_DIAG) mux_diag (c); /* rcv diag? */
757 } /* end if char */
758 } /* end if connected */
759
760 else /* not connected */
761 if (!loopback) /* terminal mode? */
762 muxc_lia[ln] = 0; /* line disconnected */
763 } /* end for */
764 if (!FLG (muxl_dib.devno)) mux_data_int (); /* scan for data int */
765 if (!FLG (muxc_dib.devno)) mux_ctrl_int (); /* scan modem */
766 return SCPE_OK;
767 }
768
769 /* Unit service - transmit side */
770
771 t_stat muxo_svc (UNIT *uptr)
772 {
773 int32 c, fc, ln, altln;
774 t_bool loopback;
775
776 ln = uptr - muxl_unit; /* line # */
777 altln = ln ^ 1; /* alt. line for diag mode */
778
779 fc = mux_xbuf[ln] & OTL_CHAR; /* full character data */
780 c = fc & 0377; /* Telnet character data */
781
782 loopback = ((muxu_unit.flags & UNIT_DIAG) != 0); /* diagnostic mode? */
783
784 if (mux_ldsc[ln].conn) { /* connected? */
785 if (mux_ldsc[ln].xmte) { /* xmt enabled? */
786 if (loopback) /* diagnostic mode? */
787 mux_ldsc[ln].conn = 0; /* clear connection */
788
789 if ((mux_xbuf[ln] & OTL_SYNC) == 0) { /* start bit 0? */
790 TMLN *lp = &mux_ldsc[ln]; /* get line */
791 c = sim_tt_outcvt (c, TT_GET_MODE (muxl_unit[ln].flags));
792
793 if (mux_xpar[ln] & OTL_DIAG) /* xmt diagnose? */
794 mux_diag (fc); /* before munge */
795
796 if (loopback) { /* diagnostic mode? */
797 mux_ldsc[altln].conn = 1; /* set recv connection */
798 sim_activate (&muxu_unit, 1); /* schedule receive */
799 }
800
801 else { /* no loopback */
802 if (c >= 0) /* valid? */
803 tmxr_putc_ln (lp, c); /* output char */
804 tmxr_poll_tx (&mux_desc); /* poll xmt */
805 }
806 }
807
808 mux_xdon[ln] = 1; /* set for xmit irq */
809
810 if (DEBUG_PRI (muxu_dev, DEB_XFER) && (loopback | (c >= 0)))
811 fprintf (sim_deb, ">>MUXo svc: Line %d character %06o sent\n",
812 ln, (loopback ? fc : c));
813 }
814
815 else { /* buf full */
816 tmxr_poll_tx (&mux_desc); /* poll xmt */
817 sim_activate (uptr, muxl_unit[ln].wait); /* wait */
818 return SCPE_OK;
819 }
820 }
821
822 if (!FLG (muxl_dib.devno)) mux_data_int (); /* scan for int */
823 return SCPE_OK;
824 }
825
826 /* Look for data interrupt */
827
828 void mux_data_int (void)
829 {
830 int32 i;
831
832 for (i = 0; i < MUX_LINES; i++) { /* rcv lines */
833 if ((mux_rpar[i] & OTL_ENB) && mux_rchp[i]) { /* enabled, char? */
834 muxl_ibuf = PUT_DCH (i) | /* lo buf = char */
835 mux_rbuf[i] & LIL_CHAR |
836 RCV_PAR (mux_rbuf[i]);
837 muxu_ibuf = PUT_DCH (i) | mux_sta[i]; /* hi buf = stat */
838 mux_rchp[i] = 0; /* clr char, stat */
839 mux_sta[i] = 0;
840
841 if (DEBUG_PRI (muxu_dev, DEB_CMDS))
842 fprintf (sim_deb, ">>MUXd irq: Receive channel %d interrupt requested\n", i);
843
844 setFSR (muxl_dib.devno); /* interrupt */
845 return;
846 }
847 }
848 for (i = 0; i < MUX_LINES; i++) { /* xmt lines */
849 if ((mux_xpar[i] & OTL_ENB) && mux_xdon[i]) { /* enabled, done? */
850 muxl_ibuf = PUT_DCH (i) | /* lo buf = last rcv char */
851 mux_rbuf[i] & LIL_CHAR |
852 RCV_PAR (mux_rbuf[i]);
853 muxu_ibuf = PUT_DCH (i) | mux_sta[i] | LIU_TR; /* hi buf = stat */
854 mux_xdon[i] = 0; /* clr done, stat */
855 mux_sta[i] = 0;
856
857 if (DEBUG_PRI (muxu_dev, DEB_CMDS))
858 fprintf (sim_deb, ">>MUXd irq: Transmit channel %d interrupt requested\n", i);
859
860 setFSR (muxl_dib.devno); /* interrupt */
861 return;
862 }
863 }
864 for (i = MUX_LINES; i < (MUX_LINES + MUX_ILINES); i++) { /* diag lines */
865 if ((mux_rpar[i] & OTL_ENB) && mux_rchp[i]) { /* enabled, char? */
866 muxl_ibuf = PUT_DCH (i) | /* lo buf = char */
867 mux_rbuf[i] & LIL_CHAR |
868 RCV_PAR (mux_rbuf[i]);
869 muxu_ibuf = PUT_DCH (i) | mux_sta[i] | LIU_DG; /* hi buf = stat */
870 mux_rchp[i] = 0; /* clr char, stat */
871 mux_sta[i] = 0;
872
873 if (DEBUG_PRI (muxu_dev, DEB_CMDS))
874 fprintf (sim_deb, ">>MUXd irq: Receive channel %d interrupt requested\n", i);
875
876 setFSR (muxl_dib.devno);
877 return;
878 }
879 }
880 return;
881 }
882
883 /* Look for control interrupt
884
885 If either of the incoming status bits does not match the stored status, and
886 the corresponding mismatch is enabled, a control interrupt request is
887 generated. Depending on the scan flag, we check either all 16 lines or just
888 the current line. If an interrupt is requested, the channel counter
889 indicates the interrupting channel.
890 */
891
892 void mux_ctrl_int (void)
893 {
894 int32 i, line_count;
895
896 line_count = (muxc_scan ? MUX_LINES : 1); /* check one or all lines */
897
898 for (i = 0; i < line_count; i++) {
899 if (muxc_scan) /* scanning? */
900 muxc_chan = (muxc_chan + 1) & LIC_M_CHAN; /* step channel */
901 if (LIC_TSTI (muxc_chan)) { /* status change? */
902
903 if (DEBUG_PRI (muxu_dev, DEB_CMDS))
904 fprintf (sim_deb,
905 ">>MUXc irq: Control channel %d interrupt requested (poll = %d)\n",
906 muxc_chan, i + 1);
907
908 setFSR (muxc_dib.devno); /* set flag */
909 break;
910 }
911 }
912 return;
913 }
914
915 /* Set diagnostic lines for given character */
916
917 void mux_diag (int32 c)
918 {
919 int32 i;
920
921 for (i = MUX_LINES; i < (MUX_LINES + MUX_ILINES); i++) {
922 if (c & SCPE_BREAK) { /* break? */
923 mux_sta[i] = mux_sta[i] | LIU_BRK;
924 mux_rbuf[i] = 0; /* no char */
925 }
926 else {
927 if (mux_rchp[i]) mux_sta[i] = mux_sta[i] | LIU_LOST;
928 mux_rchp[i] = 1;
929 mux_rbuf[i] = c;
930 }
931 }
932 return;
933 }
934
935 /* Reset an individual line */
936
937 void mux_reset_ln (int32 i)
938 {
939 mux_rbuf[i] = mux_xbuf[i] = 0; /* clear state */
940 mux_rpar[i] = mux_xpar[i] = 0;
941 mux_rchp[i] = mux_xdon[i] = 0;
942 mux_sta[i] = 0;
943 muxc_ota[i] = muxc_lia[i] = 0; /* clear modem */
944 if (mux_ldsc[i].conn && /* connected? */
945 ((muxu_unit.flags & UNIT_DIAG) == 0)) /* term mode? */
946 muxc_lia[i] = muxc_lia[i] | DSR | /* cdet, dsr */
947 (muxl_unit[i].flags & UNIT_MDM? CDET: 0);
948 sim_cancel (&muxl_unit[i]);
949 return;
950 }
951
952 /* Reset routine */
953
954 t_stat muxc_reset (DEVICE *dptr)
955 {
956 int32 i;
957
958 if (dptr == &muxc_dev) { /* make all consistent */
959 hp_enbdis_pair (dptr, &muxl_dev);
960 hp_enbdis_pair (dptr, &muxu_dev);
961 }
962 else if (dptr == &muxl_dev) {
963 hp_enbdis_pair (dptr, &muxc_dev);
964 hp_enbdis_pair (dptr, &muxu_dev);
965 }
966 else {
967 hp_enbdis_pair (dptr, &muxc_dev);
968 hp_enbdis_pair (dptr, &muxl_dev);
969 }
970 muxl_dib.cmd = muxl_dib.ctl = 0; /* init lower */
971 muxl_dib.flg = muxl_dib.fbf = muxl_dib.srq = 1;
972 muxu_dib.cmd = muxu_dib.ctl = 0; /* upper not */
973 muxu_dib.flg = muxu_dib.fbf = muxu_dib.srq = 0; /* implemented */
974 muxc_dib.cmd = muxc_dib.ctl = 0; /* init ctrl */
975 muxc_dib.flg = muxc_dib.fbf = muxc_dib.srq = 1;
976 muxc_chan = muxc_scan = 0; /* init modem scan */
977 if (muxu_unit.flags & UNIT_ATT) { /* master att? */
978 if (!sim_is_active (&muxu_unit)) {
979 muxu_unit.wait = sync_poll (INITIAL); /* synchronize poll */
980 sim_activate (&muxu_unit, muxu_unit.wait); /* activate */
981 }
982 }
983 else sim_cancel (&muxu_unit); /* else stop */
984 for (i = 0; i < MUX_LINES; i++) mux_reset_ln (i); /* reset lines 0-15 */
985 for (i = MUX_LINES; i < (MUX_LINES + MUX_ILINES); i++) /* reset lines 16-20 */
986 mux_rbuf[i] = mux_rpar[i] = mux_sta[i] = mux_rchp[i] = 0;
987 return SCPE_OK;
988 }
989
990 /* Attach master unit */
991
992 t_stat mux_attach (UNIT *uptr, char *cptr)
993 {
994 t_stat r;
995
996 if (muxu_unit.flags & UNIT_DIAG) /* diag mode? */
997 return SCPE_NOFNC; /* command not allowed */
998
999 r = tmxr_attach (&mux_desc, uptr, cptr); /* attach */
1000 if (r != SCPE_OK) return r; /* error */
1001 muxu_unit.wait = sync_poll (INITIAL); /* synchronize poll */
1002 sim_activate (uptr, muxu_unit.wait); /* start poll */
1003 return SCPE_OK;
1004 }
1005
1006 /* Detach master unit */
1007
1008 t_stat mux_detach (UNIT *uptr)
1009 {
1010 int32 i;
1011 t_stat r;
1012
1013 r = tmxr_detach (&mux_desc, uptr); /* detach */
1014 for (i = 0; i < MUX_LINES; i++) mux_ldsc[i].rcve = 0; /* disable rcv */
1015 sim_cancel (uptr); /* stop poll */
1016 return r;
1017 }
1018
1019 /* Diagnostic/normal mode routine
1020
1021 Diagnostic testing wants to exercise as much of the regular simulation code
1022 as possible to ensure good test coverage. Normally, input polling and output
1023 transmission only occurs on connected lines. In diagnostic mode, line
1024 connection flags are set selectively to enable processing on the lines under
1025 test. The alternative to this would require duplicating the send/receive
1026 code; the diagnostic would then test the copy but not the actual code used
1027 for normal character transfers, which is undesirable.
1028
1029 Therefore, to enable diagnostic mode, we must force a disconnect of the
1030 master socket and any connected Telnet lines, which clears the connection
1031 flags on all lines. Then we set the "transmission enabled" flags on all
1032 lines to enable output character processing for the diagnostic. (Normally,
1033 all of the flags are set when the multiplexer is first attached. Until then,
1034 the enable flags default to "not enabled," so we enable them explicitly
1035 here.)
1036 */
1037
1038 t_stat mux_setdiag (UNIT *uptr, int32 val, char *cptr, void *desc)
1039 {
1040 int32 ln;
1041
1042 if (val) { /* set diag? */
1043 mux_detach (uptr); /* detach lines */
1044 for (ln = 0; ln < MUX_LINES; ln++) /* enable transmission */
1045 mux_ldsc[ln].xmte = 1; /* on all lines */
1046 }
1047 else { /* set term */
1048 for (ln = 0; ln < MUX_LINES; ln++) /* clear connections */
1049 mux_ldsc[ln].conn = 0; /* on all lines */
1050 }
1051 return SCPE_OK;
1052 }
1053
1054 /* Show summary processor */
1055
1056 t_stat mux_summ (FILE *st, UNIT *uptr, int32 val, void *desc)
1057 {
1058 int32 i, t;
1059
1060 if (muxu_unit.flags & UNIT_DIAG) /* diag mode? */
1061 return SCPE_NOFNC; /* command not allowed */
1062
1063 for (i = t = 0; i < MUX_LINES; i++) t = t + (mux_ldsc[i].conn != 0);
1064 if (t == 1) fprintf (st, "1 connection");
1065 else fprintf (st, "%d connections", t);
1066 return SCPE_OK;
1067 }
1068
1069 /* SHOW CONN/STAT processor */
1070
1071 t_stat mux_show (FILE *st, UNIT *uptr, int32 val, void *desc)
1072 {
1073 int32 i, t;
1074
1075 if (muxu_unit.flags & UNIT_DIAG) /* diag mode? */
1076 return SCPE_NOFNC; /* command not allowed */
1077
1078 for (i = t = 0; i < MUX_LINES; i++) t = t + (mux_ldsc[i].conn != 0);
1079 if (t) {
1080 for (i = 0; i < MUX_LINES; i++) {
1081 if (mux_ldsc[i].conn) {
1082 if (val) tmxr_fconns (st, &mux_ldsc[i], i);
1083 else tmxr_fstats (st, &mux_ldsc[i], i);
1084 }
1085 }
1086 }
1087 else fprintf (st, "all disconnected\n");
1088 return SCPE_OK;
1089 }