1 /* pdp11_dz.c: DZ11 terminal multiplexor simulator
3 Copyright (c) 2001-2007, Robert M Supnik
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:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
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.
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.
26 dz DZ11 terminal multiplexor
28 18-Jun-07 RMS Added UNIT_IDLE flag
29 29-Oct-06 RMS Synced poll and clock
30 22-Nov-05 RMS Revised for new terminal processing routines
31 07-Jul-05 RMS Removed extraneous externs
32 15-Jun-05 RMS Revised for new autoconfigure interface
33 04-Apr-04 RMS Added per-line logging
34 05-Jan-04 RMS Revised for tmxr library changes
35 19-May-03 RMS Revised for new conditional compilation scheme
36 09-May-03 RMS Added network device flag
37 22-Dec-02 RMS Added break (framing error) support
38 31-Oct-02 RMS Added 8b support
39 12-Oct-02 RMS Added autoconfigure support
40 29-Sep-02 RMS Fixed bug in set number of lines routine
41 Added variable vector support
43 22-Apr-02 RMS Updated for changes in sim_tmxr
44 28-Apr-02 RMS Fixed interrupt acknowledge, fixed SHOW DZ ADDRESS
45 14-Jan-02 RMS Added multiboard support
46 30-Dec-01 RMS Added show statistics, set disconnect
47 Removed statistics registers
48 03-Dec-01 RMS Modified for extended SET/SHOW
49 09-Nov-01 RMS Added VAX support
50 20-Oct-01 RMS Moved getchar from sim_tmxr, changed interrupt
51 logic to use tmxr_rqln
52 06-Oct-01 RMS Fixed bug in carrier detect logic
53 03-Oct-01 RMS Added support for BSD-style "ringless" modems
54 27-Sep-01 RMS Fixed bug in xmte initialization
55 17-Sep-01 RMS Added separate autodisconnect switch
56 16-Sep-01 RMS Fixed modem control bit offsets
59 #if defined (VM_PDP10) /* PDP10 version */
60 #include "pdp10_defs.h"
61 #define RANK_DZ 0 /* no autoconfig */
65 #elif defined (VM_VAX) /* VAX version */
67 #define DZ_8B_DFLT TT_MODE_8B
68 extern int32 int_req
[IPL_HLVL
];
70 #else /* PDP-11 version */
71 #include "pdp11_defs.h"
72 #define DZ_8B_DFLT TT_MODE_8B
73 extern int32 int_req
[IPL_HLVL
];
79 #if !defined (DZ_MUXES)
82 #if !defined (DZ_LINES)
86 #define DZ_MNOMASK (DZ_MUXES - 1) /* mask for mux no */
87 #define DZ_LNOMASK (DZ_LINES - 1) /* mask for lineno */
88 #define DZ_LMASK ((1 << DZ_LINES) - 1) /* mask of lines */
89 #define DZ_SILO_ALM 16 /* silo alarm level */
91 /* DZCSR - 160100 - control/status register */
93 #define CSR_MAINT 0000010 /* maint - NI */
94 #define CSR_CLR 0000020 /* clear */
95 #define CSR_MSE 0000040 /* master scan enb */
96 #define CSR_RIE 0000100 /* rcv int enb */
97 #define CSR_RDONE 0000200 /* rcv done - RO */
98 #define CSR_V_TLINE 8 /* xmit line - RO */
99 #define CSR_TLINE (DZ_LNOMASK << CSR_V_TLINE)
100 #define CSR_SAE 0010000 /* silo alm enb */
101 #define CSR_SA 0020000 /* silo alm - RO */
102 #define CSR_TIE 0040000 /* xmit int enb */
103 #define CSR_TRDY 0100000 /* xmit rdy - RO */
104 #define CSR_RW (CSR_MSE | CSR_RIE | CSR_SAE | CSR_TIE)
105 #define CSR_MBZ (0004003 | CSR_CLR | CSR_MAINT)
107 #define CSR_GETTL(x) (((x) >> CSR_V_TLINE) & DZ_LNOMASK)
108 #define CSR_PUTTL(x,y) x = ((x) & ~CSR_TLINE) | (((y) & DZ_LNOMASK) << CSR_V_TLINE)
110 /* DZRBUF - 160102 - receive buffer, read only */
112 #define RBUF_CHAR 0000377 /* rcv char */
113 #define RBUF_V_RLINE 8 /* rcv line */
114 #define RBUF_PARE 0010000 /* parity err - NI */
115 #define RBUF_FRME 0020000 /* frame err */
116 #define RBUF_OVRE 0040000 /* overrun err - NI */
117 #define RBUF_VALID 0100000 /* rcv valid */
118 #define RBUF_MBZ 0004000
120 /* DZLPR - 160102 - line parameter register, write only, word access only */
122 #define LPR_V_LINE 0 /* line */
123 #define LPR_LPAR 0007770 /* line pars - NI */
124 #define LPR_RCVE 0010000 /* receive enb */
125 #define LPR_GETLN(x) (((x) >> LPR_V_LINE) & DZ_LNOMASK)
127 /* DZTCR - 160104 - transmission control register */
129 #define TCR_V_XMTE 0 /* xmit enables */
130 #define TCR_V_DTR 8 /* DTRs */
132 /* DZMSR - 160106 - modem status register, read only */
134 #define MSR_V_RI 0 /* ring indicators */
135 #define MSR_V_CD 8 /* carrier detect */
137 /* DZTDR - 160106 - transmit data, write only */
139 #define TDR_CHAR 0000377 /* xmit char */
140 #define TDR_V_TBR 8 /* xmit break - NI */
142 extern int32
IREQ (HLVL
);
143 extern int32 sim_switches
;
144 extern FILE *sim_log
;
145 extern int32 tmxr_poll
; /* calibrated delay */
147 uint16 dz_csr
[DZ_MUXES
] = { 0 }; /* csr */
148 uint16 dz_rbuf
[DZ_MUXES
] = { 0 }; /* rcv buffer */
149 uint16 dz_lpr
[DZ_MUXES
] = { 0 }; /* line param */
150 uint16 dz_tcr
[DZ_MUXES
] = { 0 }; /* xmit control */
151 uint16 dz_msr
[DZ_MUXES
] = { 0 }; /* modem status */
152 uint16 dz_tdr
[DZ_MUXES
] = { 0 }; /* xmit data */
153 uint8 dz_sae
[DZ_MUXES
] = { 0 }; /* silo alarm enabled */
154 uint32 dz_rxi
= 0; /* rcv interrupts */
155 uint32 dz_txi
= 0; /* xmt interrupts */
156 int32 dz_mctl
= 0; /* modem ctrl enabled */
157 int32 dz_auto
= 0; /* autodiscon enabled */
158 TMLN dz_ldsc
[DZ_MUXES
* DZ_LINES
] = { 0 }; /* line descriptors */
159 TMXR dz_desc
= { DZ_MUXES
* DZ_LINES
, 0, 0, dz_ldsc
}; /* mux descriptor */
162 t_stat
dz_rd (int32
*data
, int32 PA
, int32 access
);
163 t_stat
dz_wr (int32 data
, int32 PA
, int32 access
);
164 int32
dz_rxinta (void);
165 int32
dz_txinta (void);
166 t_stat
dz_svc (UNIT
*uptr
);
167 t_stat
dz_reset (DEVICE
*dptr
);
168 t_stat
dz_attach (UNIT
*uptr
, char *cptr
);
169 t_stat
dz_detach (UNIT
*uptr
);
170 t_stat
dz_clear (int32 dz
, t_bool flag
);
171 int32
dz_getc (int32 dz
);
172 void dz_update_rcvi (void);
173 void dz_update_xmti (void);
174 void dz_clr_rxint (int32 dz
);
175 void dz_set_rxint (int32 dz
);
176 void dz_clr_txint (int32 dz
);
177 void dz_set_txint (int32 dz
);
178 t_stat
dz_summ (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
);
179 t_stat
dz_show (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
);
180 t_stat
dz_show_vec (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
);
181 t_stat
dz_setnl (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
);
182 t_stat
dz_set_log (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
);
183 t_stat
dz_set_nolog (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
);
184 t_stat
dz_show_log (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
);
186 /* DZ data structures
188 dz_dev DZ device descriptor
190 dz_reg DZ register list
194 IOBA_DZ
, IOLN_DZ
* DZ_MUXES
, &dz_rd
, &dz_wr
,
195 2, IVCL (DZRX
), VEC_DZRX
, { &dz_rxinta
, &dz_txinta
}
198 UNIT dz_unit
= { UDATA (&dz_svc
, UNIT_IDLE
|UNIT_ATTABLE
|DZ_8B_DFLT
, 0) };
200 REG dz_nlreg
= { DRDATA (NLINES
, dz_desc
.lines
, 6), PV_LEFT
};
203 { BRDATA (CSR
, dz_csr
, DEV_RDX
, 16, DZ_MUXES
) },
204 { BRDATA (RBUF
, dz_rbuf
, DEV_RDX
, 16, DZ_MUXES
) },
205 { BRDATA (LPR
, dz_lpr
, DEV_RDX
, 16, DZ_MUXES
) },
206 { BRDATA (TCR
, dz_tcr
, DEV_RDX
, 16, DZ_MUXES
) },
207 { BRDATA (MSR
, dz_msr
, DEV_RDX
, 16, DZ_MUXES
) },
208 { BRDATA (TDR
, dz_tdr
, DEV_RDX
, 16, DZ_MUXES
) },
209 { BRDATA (SAENB
, dz_sae
, DEV_RDX
, 1, DZ_MUXES
) },
210 { GRDATA (RXINT
, dz_rxi
, DEV_RDX
, DZ_MUXES
, 0) },
211 { GRDATA (TXINT
, dz_txi
, DEV_RDX
, DZ_MUXES
, 0) },
212 { FLDATA (MDMCTL
, dz_mctl
, 0) },
213 { FLDATA (AUTODS
, dz_auto
, 0) },
214 { GRDATA (DEVADDR
, dz_dib
.ba
, DEV_RDX
, 32, 0), REG_HRO
},
215 { GRDATA (DEVVEC
, dz_dib
.vec
, DEV_RDX
, 16, 0), REG_HRO
},
220 { TT_MODE
, TT_MODE_7B
, "7b", "7B", NULL
},
221 { TT_MODE
, TT_MODE_8B
, "8b", "8B", NULL
},
222 { TT_MODE
, TT_MODE_7P
, "7p", "7P", NULL
},
223 { MTAB_XTD
| MTAB_VDV
, 1, NULL
, "DISCONNECT",
224 &tmxr_dscln
, NULL
, &dz_desc
},
225 { UNIT_ATT
, UNIT_ATT
, "connections", NULL
, NULL
, &dz_summ
},
226 { MTAB_XTD
| MTAB_VDV
| MTAB_NMO
, 1, "CONNECTIONS", NULL
,
227 NULL
, &dz_show
, NULL
},
228 { MTAB_XTD
| MTAB_VDV
| MTAB_NMO
, 0, "STATISTICS", NULL
,
229 NULL
, &dz_show
, NULL
},
230 { MTAB_XTD
|MTAB_VDV
, 010, "ADDRESS", "ADDRESS",
231 &set_addr
, &show_addr
, NULL
},
232 { MTAB_XTD
|MTAB_VDV
, 0, "VECTOR", "VECTOR",
233 &set_vec
, &dz_show_vec
, NULL
},
234 #if !defined (VM_PDP10)
235 { MTAB_XTD
| MTAB_VDV
, 0, NULL
, "AUTOCONFIGURE",
236 &set_addr_flt
, NULL
, NULL
},
238 { MTAB_XTD
| MTAB_VDV
| MTAB_VAL
, 0, "lines", "LINES",
239 &dz_setnl
, NULL
, &dz_nlreg
},
240 { MTAB_XTD
| MTAB_VDV
, 0, NULL
, "LOG",
241 &dz_set_log
, NULL
, &dz_desc
},
242 { MTAB_XTD
| MTAB_VDV
, 0, NULL
, "NOLOG",
243 &dz_set_nolog
, NULL
, &dz_desc
},
244 { MTAB_XTD
| MTAB_VDV
| MTAB_NMO
, 0, "LOG", NULL
,
245 NULL
, &dz_show_log
, &dz_desc
},
250 "DZ", &dz_unit
, dz_reg
, dz_mod
,
251 1, DEV_RDX
, 8, 1, DEV_RDX
, 8,
252 &tmxr_ex
, &tmxr_dep
, &dz_reset
,
253 NULL
, &dz_attach
, &dz_detach
,
254 &dz_dib
, DEV_FLTA
| DEV_DISABLE
| DEV_NET
| DEV_UBUS
| DEV_QBUS
257 /* IO dispatch routines, I/O addresses 177601x0 - 177601x7 */
259 t_stat
dz_rd (int32
*data
, int32 PA
, int32 access
)
261 int32 dz
= ((PA
- dz_dib
.ba
) >> 3) & DZ_MNOMASK
; /* get mux num */
263 switch ((PA
>> 1) & 03) { /* case on PA<2:1> */
266 *data
= dz_csr
[dz
] = dz_csr
[dz
] & ~CSR_MBZ
;
270 dz_csr
[dz
] = dz_csr
[dz
] & ~CSR_SA
; /* clr silo alarm */
271 if (dz_csr
[dz
] & CSR_MSE
) { /* scanner on? */
272 dz_rbuf
[dz
] = dz_getc (dz
); /* get top of silo */
273 if (!dz_rbuf
[dz
]) dz_sae
[dz
] = 1; /* empty? re-enable */
274 tmxr_poll_rx (&dz_desc
); /* poll input */
275 dz_update_rcvi (); /* update rx intr */
278 dz_rbuf
[dz
] = 0; /* no data */
279 dz_update_rcvi (); /* no rx intr */
296 t_stat
dz_wr (int32 data
, int32 PA
, int32 access
)
298 int32 dz
= ((PA
- dz_dib
.ba
) >> 3) & DZ_MNOMASK
; /* get mux num */
302 switch ((PA
>> 1) & 03) { /* case on PA<2:1> */
305 if (access
== WRITEB
) data
= (PA
& 1)? /* byte? merge */
306 (dz_csr
[dz
] & 0377) | (data
<< 8):
307 (dz_csr
[dz
] & ~0377) | data
;
308 if (data
& CSR_CLR
) dz_clear (dz
, FALSE
); /* clr? reset */
309 if (data
& CSR_MSE
) /* MSE? start poll */
310 sim_activate (&dz_unit
, clk_cosched (tmxr_poll
));
311 else dz_csr
[dz
] &= ~(CSR_SA
| CSR_RDONE
| CSR_TRDY
);
312 if ((data
& CSR_RIE
) == 0) dz_clr_rxint (dz
); /* RIE = 0? */
313 else if (((dz_csr
[dz
] & CSR_IE
) == 0) && /* RIE 0->1? */
314 ((dz_csr
[dz
] & CSR_SAE
)?
315 (dz_csr
[dz
] & CSR_SA
): (dz_csr
[dz
] & CSR_RDONE
)))
317 if ((data
& CSR_TIE
) == 0) dz_clr_txint (dz
); /* TIE = 0? */
318 else if (((dz_csr
[dz
] & CSR_TIE
) == 0) && (dz_csr
[dz
] & CSR_TRDY
))
320 dz_csr
[dz
] = (dz_csr
[dz
] & ~CSR_RW
) | (data
& CSR_RW
);
325 line
= (dz
* DZ_LINES
) + LPR_GETLN (data
); /* get line num */
326 lp
= &dz_ldsc
[line
]; /* get line desc */
327 if (dz_lpr
[dz
] & LPR_RCVE
) lp
->rcve
= 1; /* rcv enb? on */
328 else lp
->rcve
= 0; /* else line off */
329 tmxr_poll_rx (&dz_desc
); /* poll input */
330 dz_update_rcvi (); /* update rx intr */
334 if (access
== WRITEB
) data
= (PA
& 1)? /* byte? merge */
335 (dz_tcr
[dz
] & 0377) | (data
<< 8):
336 (dz_tcr
[dz
] & ~0377) | data
;
337 if (dz_mctl
) { /* modem ctl? */
338 dz_msr
[dz
] |= ((data
& 0177400) & /* dcd |= dtr & ring */
339 ((dz_msr
[dz
] & DZ_LMASK
) << MSR_V_CD
));
340 dz_msr
[dz
] &= ~(data
>> TCR_V_DTR
); /* ring &= ~dtr */
341 if (dz_auto
) { /* auto disconnect? */
343 drop
= (dz_tcr
[dz
] & ~data
) >> TCR_V_DTR
; /* drop = dtr & ~data */
344 for (i
= 0; i
< DZ_LINES
; i
++) { /* drop hangups */
345 line
= (dz
* DZ_LINES
) + i
; /* get line num */
346 lp
= &dz_ldsc
[line
]; /* get line desc */
347 if (lp
->conn
&& (drop
& (1 << i
))) {
348 tmxr_linemsg (lp
, "\r\nLine hangup\r\n");
349 tmxr_reset_ln (lp
); /* reset line, cdet */
350 dz_msr
[dz
] &= ~(1 << (i
+ MSR_V_CD
));
356 tmxr_poll_tx (&dz_desc
); /* poll output */
357 dz_update_xmti (); /* update int */
361 if (PA
& 1) { /* odd byte? */
362 dz_tdr
[dz
] = (dz_tdr
[dz
] & 0377) | (data
<< 8); /* just save */
366 if (dz_csr
[dz
] & CSR_MSE
) { /* enabled? */
367 line
= (dz
* DZ_LINES
) + CSR_GETTL (dz_csr
[dz
]);
368 lp
= &dz_ldsc
[line
]; /* get line desc */
369 c
= sim_tt_outcvt (dz_tdr
[dz
], TT_GET_MODE (dz_unit
.flags
));
370 if (c
>= 0) tmxr_putc_ln (lp
, c
); /* store char */
371 tmxr_poll_tx (&dz_desc
); /* poll output */
372 dz_update_xmti (); /* update int */
380 /* Unit service routine
382 The DZ11 polls to see if asynchronous activity has occurred and now
383 needs to be processed. The polling interval is controlled by the clock
384 simulator, so for most environments, it is calibrated to real time.
385 Typical polling intervals are 50-60 times per second.
387 The simulator assumes that software enables all of the multiplexors,
391 t_stat
dz_svc (UNIT
*uptr
)
395 for (dz
= t
= 0; dz
< DZ_MUXES
; dz
++) /* check enabled */
396 t
= t
| (dz_csr
[dz
] & CSR_MSE
);
397 if (t
) { /* any enabled? */
398 newln
= tmxr_poll_conn (&dz_desc
); /* poll connect */
399 if ((newln
>= 0) && dz_mctl
) { /* got a live one? */
400 dz
= newln
/ DZ_LINES
; /* get mux num */
401 if (dz_tcr
[dz
] & (1 << (newln
+ TCR_V_DTR
))) /* DTR set? */
402 dz_msr
[dz
] |= (1 << (newln
+ MSR_V_CD
)); /* set cdet */
403 else dz_msr
[dz
] |= (1 << newln
); /* set ring */
405 tmxr_poll_rx (&dz_desc
); /* poll input */
406 dz_update_rcvi (); /* upd rcv intr */
407 tmxr_poll_tx (&dz_desc
); /* poll output */
408 dz_update_xmti (); /* upd xmt intr */
409 sim_activate (uptr
, tmxr_poll
); /* reactivate */
414 /* Get first available character for mux, if any */
416 int32
dz_getc (int32 dz
)
420 for (i
= c
= 0; (i
< DZ_LINES
) && (c
== 0); i
++) { /* loop thru lines */
421 line
= (dz
* DZ_LINES
) + i
; /* get line num */
422 c
= tmxr_getc_ln (&dz_ldsc
[line
]); /* test for input */
423 if (c
& SCPE_BREAK
) c
= RBUF_VALID
| RBUF_FRME
; /* break? frame err */
424 if (c
) c
= c
| (i
<< RBUF_V_RLINE
); /* or in line # */
429 /* Update receive interrupts */
431 void dz_update_rcvi (void)
433 int32 i
, dz
, line
, scnt
[DZ_MUXES
];
436 for (dz
= 0; dz
< DZ_MUXES
; dz
++) { /* loop thru muxes */
437 scnt
[dz
] = 0; /* clr input count */
438 for (i
= 0; i
< DZ_LINES
; i
++) { /* poll lines */
439 line
= (dz
* DZ_LINES
) + i
; /* get line num */
440 lp
= &dz_ldsc
[line
]; /* get line desc */
441 scnt
[dz
] = scnt
[dz
] + tmxr_rqln (lp
); /* sum buffers */
442 if (dz_mctl
&& !lp
->conn
) /* if disconn */
443 dz_msr
[dz
] &= ~(1 << (i
+ MSR_V_CD
)); /* reset car det */
446 for (dz
= 0; dz
< DZ_MUXES
; dz
++) { /* loop thru muxes */
447 if (scnt
[dz
] && (dz_csr
[dz
] & CSR_MSE
)) { /* input & enabled? */
448 dz_csr
[dz
] |= CSR_RDONE
; /* set done */
449 if (dz_sae
[dz
] && (scnt
[dz
] >= DZ_SILO_ALM
)) { /* alm enb & cnt hi? */
450 dz_csr
[dz
] |= CSR_SA
; /* set status */
451 dz_sae
[dz
] = 0; /* disable alarm */
454 else dz_csr
[dz
] &= ~CSR_RDONE
; /* no, clear done */
455 if ((dz_csr
[dz
] & CSR_RIE
) && /* int enable */
456 ((dz_csr
[dz
] & CSR_SAE
)?
457 (dz_csr
[dz
] & CSR_SA
): (dz_csr
[dz
] & CSR_RDONE
)))
458 dz_set_rxint (dz
); /* and alm/done? */
459 else dz_clr_rxint (dz
); /* no, clear int */
464 /* Update transmit interrupts */
466 void dz_update_xmti (void)
468 int32 dz
, linemask
, i
, j
, line
;
470 for (dz
= 0; dz
< DZ_MUXES
; dz
++) { /* loop thru muxes */
471 linemask
= dz_tcr
[dz
] & DZ_LMASK
; /* enabled lines */
472 dz_csr
[dz
] &= ~CSR_TRDY
; /* assume not rdy */
473 j
= CSR_GETTL (dz_csr
[dz
]); /* start at current */
474 for (i
= 0; i
< DZ_LINES
; i
++) { /* loop thru lines */
475 j
= (j
+ 1) & DZ_LNOMASK
; /* next line */
476 line
= (dz
* DZ_LINES
) + j
; /* get line num */
477 if ((linemask
& (1 << j
)) && dz_ldsc
[line
].xmte
) {
478 CSR_PUTTL (dz_csr
[dz
], j
); /* put ln in csr */
479 dz_csr
[dz
] |= CSR_TRDY
; /* set xmt rdy */
483 if ((dz_csr
[dz
] & CSR_TIE
) && (dz_csr
[dz
] & CSR_TRDY
)) /* ready plus int? */
485 else dz_clr_txint (dz
); /* no int req */
490 /* Interrupt routines */
492 void dz_clr_rxint (int32 dz
)
494 dz_rxi
= dz_rxi
& ~(1 << dz
); /* clr mux rcv int */
495 if (dz_rxi
== 0) CLR_INT (DZRX
); /* all clr? */
496 else SET_INT (DZRX
); /* no, set intr */
500 void dz_set_rxint (int32 dz
)
502 dz_rxi
= dz_rxi
| (1 << dz
); /* set mux rcv int */
503 SET_INT (DZRX
); /* set master intr */
507 int32
dz_rxinta (void)
511 for (dz
= 0; dz
< DZ_MUXES
; dz
++) { /* find 1st mux */
512 if (dz_rxi
& (1 << dz
)) {
513 dz_clr_rxint (dz
); /* clear intr */
514 return (dz_dib
.vec
+ (dz
* 010)); /* return vector */
520 void dz_clr_txint (int32 dz
)
522 dz_txi
= dz_txi
& ~(1 << dz
); /* clr mux xmt int */
523 if (dz_txi
== 0) CLR_INT (DZTX
); /* all clr? */
524 else SET_INT (DZTX
); /* no, set intr */
528 void dz_set_txint (int32 dz
)
530 dz_txi
= dz_txi
| (1 << dz
); /* set mux xmt int */
531 SET_INT (DZTX
); /* set master intr */
535 int32
dz_txinta (void)
539 for (dz
= 0; dz
< DZ_MUXES
; dz
++) { /* find 1st mux */
540 if (dz_txi
& (1 << dz
)) {
541 dz_clr_txint (dz
); /* clear intr */
542 return (dz_dib
.vec
+ 4 + (dz
* 010)); /* return vector */
550 t_stat
dz_clear (int32 dz
, t_bool flag
)
554 dz_csr
[dz
] = 0; /* clear CSR */
555 dz_rbuf
[dz
] = 0; /* silo empty */
556 dz_lpr
[dz
] = 0; /* no params */
557 if (flag
) dz_tcr
[dz
] = 0; /* INIT? clr all */
558 else dz_tcr
[dz
] &= ~0377; /* else save dtr */
560 dz_sae
[dz
] = 1; /* alarm on */
561 dz_clr_rxint (dz
); /* clear int */
563 for (i
= 0; i
< DZ_LINES
; i
++) { /* loop thru lines */
564 line
= (dz
* DZ_LINES
) + i
;
565 if (!dz_ldsc
[line
].conn
) dz_ldsc
[line
].xmte
= 1; /* set xmt enb */
566 dz_ldsc
[line
].rcve
= 0; /* clr rcv enb */
571 t_stat
dz_reset (DEVICE
*dptr
)
575 for (i
= 0; i
< DZ_MUXES
; i
++) dz_clear (i
, TRUE
); /* init muxes */
576 dz_rxi
= dz_txi
= 0; /* clr master int */
579 sim_cancel (&dz_unit
); /* stop poll */
580 ndev
= ((dptr
->flags
& DEV_DIS
)? 0: (dz_desc
.lines
/ DZ_LINES
));
581 return auto_config (dptr
->name
, ndev
); /* auto config */
586 t_stat
dz_attach (UNIT
*uptr
, char *cptr
)
589 extern int32 sim_switches
;
591 dz_mctl
= dz_auto
= 0; /* modem ctl off */
592 r
= tmxr_attach (&dz_desc
, uptr
, cptr
); /* attach mux */
593 if (r
!= SCPE_OK
) return r
; /* error? */
594 if (sim_switches
& SWMASK ('M')) { /* modem control? */
596 printf ("Modem control activated\n");
597 if (sim_log
) fprintf (sim_log
, "Modem control activated\n");
598 if (sim_switches
& SWMASK ('A')) { /* autodisconnect? */
600 printf ("Auto disconnect activated\n");
601 if (sim_log
) fprintf (sim_log
, "Auto disconnect activated\n");
609 t_stat
dz_detach (UNIT
*uptr
)
611 return tmxr_detach (&dz_desc
, uptr
);
614 /* Show summary processor */
616 t_stat
dz_summ (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
)
620 for (i
= t
= 0; i
< dz_desc
.lines
; i
++) { /* get num conn */
621 if (dz_ldsc
[i
].conn
) t
= t
+ 1;
623 if (t
== 1) fprintf (st
, "1 connection");
624 else fprintf (st
, "%d connections", t
);
628 /* SHOW CONN/STAT processor */
630 t_stat
dz_show (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
)
634 for (i
= t
= 0; i
< dz_desc
.lines
; i
++) { /* loop thru conn */
635 if (dz_ldsc
[i
].conn
) {
637 if (val
) tmxr_fconns (st
, &dz_ldsc
[i
], i
);
638 else tmxr_fstats (st
, &dz_ldsc
[i
], i
);
641 if (t
== 0) fprintf (st
, "all disconnected\n");
645 /* SET LINES processor */
647 t_stat
dz_setnl (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
649 int32 newln
, i
, t
, ndev
;
652 if (cptr
== NULL
) return SCPE_ARG
;
653 newln
= (int32
) get_uint (cptr
, 10, (DZ_MUXES
* DZ_LINES
), &r
);
654 if ((r
!= SCPE_OK
) || (newln
== dz_desc
.lines
)) return r
;
655 if ((newln
== 0) || (newln
% DZ_LINES
)) return SCPE_ARG
;
656 if (newln
< dz_desc
.lines
) {
657 for (i
= newln
, t
= 0; i
< dz_desc
.lines
; i
++) t
= t
| dz_ldsc
[i
].conn
;
658 if (t
&& !get_yn ("This will disconnect users; proceed [N]?", FALSE
))
660 for (i
= newln
; i
< dz_desc
.lines
; i
++) {
661 if (dz_ldsc
[i
].conn
) {
662 tmxr_linemsg (&dz_ldsc
[i
], "\r\nOperator disconnected line\r\n");
663 tmxr_reset_ln (&dz_ldsc
[i
]); /* reset line */
665 if ((i
% DZ_LINES
) == (DZ_LINES
- 1))
666 dz_clear (i
/ DZ_LINES
, TRUE
); /* reset mux */
669 dz_dib
.lnt
= (newln
/ DZ_LINES
) * IOLN_DZ
; /* set length */
670 dz_desc
.lines
= newln
;
671 ndev
= ((dz_dev
.flags
& DEV_DIS
)? 0: (dz_desc
.lines
/ DZ_LINES
));
672 return auto_config (dz_dev
.name
, ndev
); /* auto config */
675 /* SHOW VECTOR processor */
677 t_stat
dz_show_vec (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
)
679 return show_vec (st
, uptr
, ((dz_desc
.lines
* 2) / DZ_LINES
), desc
);
682 /* SET LOG processor */
684 t_stat
dz_set_log (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
690 if (cptr
== NULL
) return SCPE_ARG
;
691 tptr
= strchr (cptr
, '=');
692 if ((tptr
== NULL
) || (*tptr
== 0)) return SCPE_ARG
;
694 ln
= (int32
) get_uint (cptr
, 10, (DZ_MUXES
* DZ_LINES
), &r
);
695 if ((r
!= SCPE_OK
) || (ln
>= dz_desc
.lines
)) return SCPE_ARG
;
696 return tmxr_set_log (NULL
, ln
, tptr
, desc
);
699 /* SET NOLOG processor */
701 t_stat
dz_set_nolog (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
706 if (cptr
== NULL
) return SCPE_ARG
;
707 ln
= (int32
) get_uint (cptr
, 10, (DZ_MUXES
* DZ_LINES
), &r
);
708 if ((r
!= SCPE_OK
) || (ln
>= dz_desc
.lines
)) return SCPE_ARG
;
709 return tmxr_set_nolog (NULL
, ln
, NULL
, desc
);
712 /* SHOW LOG processor */
714 t_stat
dz_show_log (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
)
718 for (i
= 0; i
< dz_desc
.lines
; i
++) {
719 fprintf (st
, "line %d: ", i
);
720 tmxr_show_log (st
, NULL
, i
, desc
);