1 /* pdp11_dc.c: PDP-11 DC11 multiple terminal interface simulator
3 Copyright (c) 1993-2008, 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 dci,dco DC11 terminal input/output
28 The simulator supports both hardwired and modem-like behavior. If modem
29 control is not enabled, carrier detect, ring, and carrier change are
33 #if defined (VM_PDP10) /* PDP10 version */
34 #error "DC11 is not supported on the PDP-10!"
36 #elif defined (VM_VAX) /* VAX version */
37 #error "DC11 is not supported on the VAX!"
39 #else /* PDP-11 version */
40 #include "pdp11_defs.h"
45 #define DCX_MASK (DCX_LINES - 1)
47 /* Parity and modem control */
49 #define DCX_V_OPAR (TTUF_V_UF + 0)
50 #define DCX_V_EPAR (TTUF_V_UF + 1)
51 #define DCX_V_MDM (TTUF_V_UF + 2)
52 #define DCX_OPAR (1u << DCX_V_OPAR)
53 #define DCX_EPAR (1u << DCX_V_EPAR)
54 #define DCX_MDM (1u << DCX_V_MDM)
58 #define DCICSR_RD 0173777
59 #define DCICSR_WR 0003533
60 #define DCICSR_DTR 0000001 /* DTR (RW) */
61 #define DCICSR_XBR 0000002 /* xmit brk (RWNI) */
62 #define DCICSR_CDT 0000004 /* car det (RO) */
63 #define DCICSR_PAR 0000040 /* odd par (RO) */
64 #define DCICSR_OVR 0010000 /* overrun (RO) */
65 #define DCICSR_RNG 0020000 /* ring (RO) */
66 #define DCICSR_CCH 0040000 /* car change (RO) */
67 #define DCICSR_ALLERR (DCICSR_OVR|DCICSR_RNG|DCICSR_CCH)
68 #define DCICSR_ERR 0100000 /* error */
69 #define DCOCSR_RD 0100737
70 #define DCOCSR_WR 0000535
71 #define DCOCSR_RTS 0000001 /* req to send (RW) */
72 #define DCOCSR_CTS 0000002 /* clr to send (RO) */
73 #define DCOCSR_MNT 0000004 /* maint (RWNI) */
75 extern int32 int_req
[IPL_HLVL
];
76 extern int32 tmxr_poll
;
78 uint16 dci_csr
[DCX_LINES
] = { 0 }; /* control/status */
79 uint8 dci_buf
[DCX_LINES
] = { 0 };
81 uint16 dco_csr
[DCX_LINES
] = { 0 }; /* control/status */
82 uint8 dco_buf
[DCX_LINES
] = { 0 };
84 TMLN dcx_ldsc
[DCX_LINES
] = { 0 }; /* line descriptors */
85 TMXR dcx_desc
= { DCX_LINES
, 0, 0, dcx_ldsc
}; /* mux descriptor */
87 static const uint8 odd_par
[] = {
88 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 00 */
89 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
90 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 10 */
91 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
92 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 20 */
93 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
94 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 30 */
95 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
96 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 40 */
97 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
98 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 50 */
99 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
100 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 60 */
101 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
102 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 70 */
103 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
104 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 80 */
105 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
106 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 90 */
107 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
108 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* A0 */
109 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
110 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* B0 */
111 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
112 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* C0 */
113 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
114 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* D0 */
115 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
116 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* E0 */
117 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
118 0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* F0 */
119 0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80
122 t_stat
dcx_rd (int32
*data
, int32 PA
, int32 access
);
123 t_stat
dcx_wr (int32 data
, int32 PA
, int32 access
);
124 t_stat
dcx_reset (DEVICE
*dptr
);
125 t_stat
dci_svc (UNIT
*uptr
);
126 t_stat
dco_svc (UNIT
*uptr
);
127 t_stat
dcx_attach (UNIT
*uptr
, char *cptr
);
128 t_stat
dcx_detach (UNIT
*uptr
);
129 t_stat
dcx_summ (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
);
130 t_stat
dcx_show (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
);
131 t_stat
dcx_show_vec (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
);
132 t_stat
dcx_set_lines (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
);
133 t_stat
dcx_show_lines (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
);
134 void dcx_enbdis (int32 dis
);
135 void dci_clr_int (int32 ln
);
136 void dci_set_int (int32 ln
);
137 int32
dci_iack (void);
138 void dco_clr_int (int32 ln
);
139 void dco_set_int (int32 ln
);
140 int32
dco_iack (void);
141 void dcx_reset_ln (int32 ln
);
143 /* DCI data structures
145 dci_dev DCI device descriptor
146 dci_unit DCI unit descriptor
147 dci_reg DCI register list
151 IOBA_DC
, IOLN_DC
, &dcx_rd
, &dcx_wr
,
152 2, IVCL (DCI
), VEC_DCI
, { &dci_iack
, &dco_iack
}
155 UNIT dci_unit
= { UDATA (&dci_svc
, 0, 0), KBD_POLL_WAIT
};
158 { BRDATA (BUF
, dci_buf
, DEV_RDX
, 8, DCX_LINES
) },
159 { BRDATA (CSR
, dci_csr
, DEV_RDX
, 16, DCX_LINES
) },
160 { GRDATA (IREQ
, dci_ireq
, DEV_RDX
, DCX_LINES
, 0) },
161 { DRDATA (LINES
, dcx_desc
.lines
, 6), REG_HRO
},
162 { GRDATA (DEVADDR
, dci_dib
.ba
, DEV_RDX
, 32, 0), REG_HRO
},
163 { GRDATA (DEVIOLN
, dci_dib
.lnt
, DEV_RDX
, 32, 0), REG_HRO
},
164 { GRDATA (DEVVEC
, dci_dib
.vec
, DEV_RDX
, 16, 0), REG_HRO
},
169 { UNIT_ATT
, UNIT_ATT
, "summary", NULL
, NULL
, &dcx_summ
},
170 { MTAB_XTD
| MTAB_VDV
, 1, NULL
, "DISCONNECT",
171 &tmxr_dscln
, NULL
, &dcx_desc
},
172 { MTAB_XTD
| MTAB_VDV
| MTAB_NMO
, 1, "CONNECTIONS", NULL
,
173 NULL
, &dcx_show
, NULL
},
174 { MTAB_XTD
| MTAB_VDV
| MTAB_NMO
, 0, "STATISTICS", NULL
,
175 NULL
, &dcx_show
, NULL
},
176 { MTAB_XTD
|MTAB_VDV
, 0, "ADDRESS", NULL
,
177 &set_addr
, &show_addr
, NULL
},
178 { MTAB_XTD
|MTAB_VDV
, 0, "VECTOR", NULL
,
179 &set_vec
, &dcx_show_vec
, NULL
},
180 { MTAB_XTD
| MTAB_VDV
, 0, "lines", "LINES",
181 &dcx_set_lines
, &dcx_show_lines
},
186 "DCI", &dci_unit
, dci_reg
, dci_mod
,
188 NULL
, NULL
, &dcx_reset
,
189 NULL
, &dcx_attach
, &dcx_detach
,
190 &dci_dib
, DEV_UBUS
| DEV_QBUS
| DEV_DISABLE
| DEV_DIS
193 /* DCO data structures
195 dco_dev DCO device descriptor
196 dco_unit DCO unit descriptor
197 dco_reg DCO register list
201 { UDATA (&dco_svc
, TT_MODE_7P
+DCX_EPAR
+DCX_MDM
, 0), SERIAL_OUT_WAIT
},
202 { UDATA (&dco_svc
, TT_MODE_7P
+DCX_EPAR
+DCX_MDM
, 0), SERIAL_OUT_WAIT
},
203 { UDATA (&dco_svc
, TT_MODE_7P
+DCX_EPAR
+DCX_MDM
, 0), SERIAL_OUT_WAIT
},
204 { UDATA (&dco_svc
, TT_MODE_7P
+DCX_EPAR
+DCX_MDM
, 0), SERIAL_OUT_WAIT
},
205 { UDATA (&dco_svc
, TT_MODE_7P
+DCX_EPAR
+DCX_MDM
, 0), SERIAL_OUT_WAIT
},
206 { UDATA (&dco_svc
, TT_MODE_7P
+DCX_EPAR
+DCX_MDM
, 0), SERIAL_OUT_WAIT
},
207 { UDATA (&dco_svc
, TT_MODE_7P
+DCX_EPAR
+DCX_MDM
, 0), SERIAL_OUT_WAIT
},
208 { UDATA (&dco_svc
, TT_MODE_7P
+DCX_EPAR
+DCX_MDM
, 0), SERIAL_OUT_WAIT
},
209 { UDATA (&dco_svc
, TT_MODE_7P
+DCX_EPAR
+DCX_MDM
, 0), SERIAL_OUT_WAIT
},
210 { UDATA (&dco_svc
, TT_MODE_7P
+DCX_EPAR
+DCX_MDM
, 0), SERIAL_OUT_WAIT
},
211 { UDATA (&dco_svc
, TT_MODE_7P
+DCX_EPAR
+DCX_MDM
, 0), SERIAL_OUT_WAIT
},
212 { UDATA (&dco_svc
, TT_MODE_7P
+DCX_EPAR
+DCX_MDM
, 0), SERIAL_OUT_WAIT
},
213 { UDATA (&dco_svc
, TT_MODE_7P
+DCX_EPAR
+DCX_MDM
, 0), SERIAL_OUT_WAIT
},
214 { UDATA (&dco_svc
, TT_MODE_7P
+DCX_EPAR
+DCX_MDM
, 0), SERIAL_OUT_WAIT
},
215 { UDATA (&dco_svc
, TT_MODE_7P
+DCX_EPAR
+DCX_MDM
, 0), SERIAL_OUT_WAIT
},
216 { UDATA (&dco_svc
, TT_MODE_7P
+DCX_EPAR
+DCX_MDM
, 0), SERIAL_OUT_WAIT
}
220 { BRDATA (BUF
, dco_buf
, DEV_RDX
, 8, DCX_LINES
) },
221 { BRDATA (CSR
, dco_csr
, DEV_RDX
, 16, DCX_LINES
) },
222 { GRDATA (IREQ
, dco_ireq
, DEV_RDX
, DCX_LINES
, 0) },
223 { URDATA (TIME
, dco_unit
[0].wait
, 10, 31, 0,
224 DCX_LINES
, PV_LEFT
) },
229 { TT_MODE
, TT_MODE_UC
, "UC", "UC", NULL
},
230 { TT_MODE
, TT_MODE_7B
, "7b", "7B", NULL
},
231 { TT_MODE
, TT_MODE_8B
, "8b", "8B", NULL
},
232 { TT_MODE
, TT_MODE_7P
, "7p", "7P", NULL
},
233 { DCX_OPAR
+DCX_EPAR
, 0, "no parity", "NOPARITY", NULL
},
234 { DCX_OPAR
+DCX_EPAR
, DCX_OPAR
, "odd parity", "ODDPARITY", NULL
},
235 { DCX_OPAR
+DCX_EPAR
, DCX_EPAR
, "even parity", "EVENPARITY", NULL
},
236 { DCX_MDM
, 0, "no dataset", "NODATASET", NULL
},
237 { DCX_MDM
, DCX_MDM
, "dataset", "DATASET", NULL
},
238 { MTAB_XTD
|MTAB_VUN
, 0, NULL
, "DISCONNECT",
239 &tmxr_dscln
, NULL
, &dcx_desc
},
240 { MTAB_XTD
|MTAB_VUN
|MTAB_NC
, 0, "LOG", "LOG",
241 &tmxr_set_log
, &tmxr_show_log
, &dcx_desc
},
242 { MTAB_XTD
|MTAB_VUN
|MTAB_NC
, 0, NULL
, "NOLOG",
243 &tmxr_set_nolog
, NULL
, &dcx_desc
},
248 "DCO", dco_unit
, dco_reg
, dco_mod
,
249 DCX_LINES
, 10, 31, 1, 8, 8,
250 NULL
, NULL
, &dcx_reset
,
252 NULL
, DEV_UBUS
| DEV_DISABLE
| DEV_DIS
255 /* Terminal input routines */
257 t_stat
dcx_rd (int32
*data
, int32 PA
, int32 access
)
259 int32 ln
= ((PA
- dci_dib
.ba
) >> 3) & DCX_MASK
;
261 switch ((PA
>> 1) & 03) { /* decode PA<2:1> */
263 case 00: /* dci csr */
264 if (dci_csr
[ln
] & DCICSR_ALLERR
)
265 dci_csr
[ln
] |= DCICSR_ERR
;
266 else dci_csr
[ln
] &= ~DCICSR_ERR
;
267 *data
= dci_csr
[ln
] & DCICSR_RD
;
268 dci_csr
[ln
] &= ~(CSR_DONE
|DCICSR_ALLERR
|DCICSR_ERR
);
271 case 01: /* dci buf */
276 case 02: /* dco csr */
277 *data
= dco_csr
[ln
] & DCOCSR_RD
;
280 case 03: /* dco buf */
283 } /* end switch PA */
288 t_stat
dcx_wr (int32 data
, int32 PA
, int32 access
)
290 int32 ln
= ((PA
- dci_dib
.ba
) >> 3) & DCX_MASK
;
291 TMLN
*lp
= &dcx_ldsc
[ln
];
293 switch ((PA
>> 1) & 03) { /* decode PA<2:1> */
295 case 00: /* dci csr */
296 if (access
== WRITEB
) /* byte write? */
298 (dci_csr
[ln
] & 0377) | (data
<< 8):
299 (dci_csr
[ln
] & ~0377) | data
;
300 if ((data
& CSR_IE
) == 0) /* clr ie? */
301 dci_clr_int (ln
); /* clr int req */
302 else if ((dci_csr
[ln
] & (CSR_DONE
+ CSR_IE
)) == CSR_DONE
)
304 if (((data
^ dci_csr
[ln
]) & DCICSR_DTR
) && /* DTR change? */
305 (dco_unit
[ln
].flags
& DCX_MDM
)) { /* modem ctl? */
306 if (data
& DCICSR_DTR
) { /* setting DTR? */
307 if (lp
->conn
) { /* ringing? */
308 dci_csr
[ln
] = (dci_csr
[ln
] & ~DCICSR_RNG
) |
309 (DCICSR_CDT
|DCICSR_CCH
|DCICSR_ERR
);
310 dco_csr
[ln
] |= DCOCSR_CTS
; /* set CDT,CCH,CTS */
311 if (data
& CSR_IE
) /* if ie, req int */
315 else { /* clearing DTR */
316 if (lp
->conn
) { /* connected? */
317 tmxr_linemsg (lp
, "\r\nLine hangup\r\n");
318 tmxr_reset_ln (lp
); /* reset line */
319 if (dci_csr
[ln
] & DCICSR_CDT
) { /* carrier det? */
320 dci_csr
[ln
] |= (DCICSR_CCH
|DCICSR_ERR
);
321 if (data
& CSR_IE
) /* if ie, req int */
325 dci_csr
[ln
] &= ~(DCICSR_CDT
|DCICSR_RNG
);
326 dco_csr
[ln
] &= ~DCOCSR_CTS
; /* clr CDT,RNG,CTS */
328 } /* end DTR chg+modem */
329 dci_csr
[ln
] = (uint16
) ((dci_csr
[ln
] & ~DCICSR_WR
) | (data
& DCICSR_WR
));
332 case 01: /* dci buf */
335 case 02: /* dco csr */
336 if (access
== WRITEB
) /* byte write? */
338 (dco_csr
[ln
] & 0377) | (data
<< 8):
339 (dco_csr
[ln
] & ~0377) | data
;
340 if ((data
& CSR_IE
) == 0) /* clr ie? */
341 dco_clr_int (ln
); /* clr int req */
342 else if ((dco_csr
[ln
] & (CSR_DONE
+ CSR_IE
)) == CSR_DONE
)
344 dco_csr
[ln
] = (uint16
) ((dco_csr
[ln
] & ~DCOCSR_WR
) | (data
& DCOCSR_WR
));
347 case 03: /* dco buf */
349 dco_buf
[ln
] = data
& 0377;
350 dco_csr
[ln
] &= ~CSR_DONE
; /* clr done */
351 dco_clr_int (ln
); /* clr int req */
352 sim_activate (&dco_unit
[ln
], dco_unit
[ln
].wait
);
354 } /* end switch PA */
359 /* Terminal input service */
361 t_stat
dci_svc (UNIT
*uptr
)
365 if ((uptr
->flags
& UNIT_ATT
) == 0) /* attached? */
367 sim_activate (uptr
, tmxr_poll
); /* continue poll */
368 ln
= tmxr_poll_conn (&dcx_desc
); /* look for connect */
369 if (ln
>= 0) { /* got one? */
370 dcx_ldsc
[ln
].rcve
= 1; /* set rcv enb */
371 if (dco_unit
[ln
].flags
& DCX_MDM
) { /* modem control? */
372 if (dci_csr
[ln
] & DCICSR_DTR
) /* DTR already set? */
373 dci_csr
[ln
] |= (DCICSR_CDT
|DCICSR_CCH
|DCICSR_ERR
);
374 else dci_csr
[ln
] |= (DCICSR_RNG
|DCICSR_ERR
); /* no, ring */
375 if (dci_csr
[ln
] & CSR_IE
) /* if ie, */
376 dci_set_int (ln
); /* req int */
378 else dco_csr
[ln
] |= DCOCSR_CTS
; /* just connect */
380 tmxr_poll_rx (&dcx_desc
); /* poll for input */
381 for (ln
= 0; ln
< DCX_LINES
; ln
++) { /* loop thru lines */
382 if (dcx_ldsc
[ln
].conn
) { /* connected? */
383 if ((temp
= tmxr_getc_ln (&dcx_ldsc
[ln
])) && /* get char */
384 !(temp
& SCPE_BREAK
)) { /* not break? */
385 c
= sim_tt_inpcvt (temp
, TT_GET_MODE (dco_unit
[ln
].flags
));
386 if (dci_csr
[ln
] & CSR_DONE
) /* overrun? */
387 dci_csr
[ln
] |= DCICSR_OVR
;
388 else dci_csr
[ln
] |= CSR_DONE
; /* set done */
389 if (dci_csr
[ln
] & CSR_IE
) /* if ie, */
390 dci_set_int (ln
); /* req int */
391 if (dco_unit
[ln
].flags
& DCX_OPAR
) /* odd parity */
392 c
= (c
& 0177) | odd_par
[c
& 0177];
393 else if (dco_unit
[ln
].flags
& DCX_EPAR
) /* even parity */
394 c
= (c
& 0177) | (odd_par
[c
& 0177] ^ 0200);
396 if ((c
& 0200) == odd_par
[c
& 0177]) /* odd par? */
397 dci_csr
[ln
] |= DCICSR_PAR
;
398 else dci_csr
[ln
] &= ~DCICSR_PAR
;
401 else { /* disconnected */
402 if ((dco_unit
[ln
].flags
& DCX_MDM
) && /* modem control? */
403 (dci_csr
[ln
] & DCICSR_CDT
)) { /* carrier detect? */
404 dci_csr
[ln
] |= (DCICSR_CCH
|DCICSR_ERR
); /* carrier change */
405 if (dci_csr
[ln
] & CSR_IE
) /* if ie, */
406 dci_set_int (ln
); /* req int */
408 dci_csr
[ln
] &= ~(DCICSR_CDT
|DCICSR_RNG
); /* clr CDT,RNG,CTS */
409 dco_csr
[ln
] &= ~DCOCSR_CTS
;
415 /* Terminal output service */
417 t_stat
dco_svc (UNIT
*uptr
)
420 int32 ln
= uptr
- dco_unit
; /* line # */
422 if (dcx_ldsc
[ln
].conn
) { /* connected? */
423 if (dcx_ldsc
[ln
].xmte
) { /* tx enabled? */
424 TMLN
*lp
= &dcx_ldsc
[ln
]; /* get line */
425 c
= sim_tt_outcvt (dco_buf
[ln
], TT_GET_MODE (dco_unit
[ln
].flags
));
426 if (c
>= 0) tmxr_putc_ln (lp
, c
); /* output char */
427 tmxr_poll_tx (&dcx_desc
); /* poll xmt */
430 tmxr_poll_tx (&dcx_desc
); /* poll xmt */
431 sim_activate (uptr
, dco_unit
[ln
].wait
); /* wait */
435 dco_csr
[ln
] |= CSR_DONE
; /* set done */
436 if (dco_csr
[ln
] & CSR_IE
) /* ie set? */
437 dco_set_int (ln
); /* req int */
441 /* Interrupt routines */
443 void dci_clr_int (int32 ln
)
445 dci_ireq
&= ~(1 << ln
); /* clr mux rcv int */
446 if (dci_ireq
== 0) /* all clr? */
448 else SET_INT (DCI
); /* no, set intr */
452 void dci_set_int (int32 ln
)
454 dci_ireq
|= (1 << ln
); /* clr mux rcv int */
455 SET_INT (DCI
); /* set master intr */
459 int32
dci_iack (void)
463 for (ln
= 0; ln
< DCX_LINES
; ln
++) { /* find 1st line */
464 if (dci_ireq
& (1 << ln
)) {
465 dci_clr_int (ln
); /* clear intr */
466 return (dci_dib
.vec
+ (ln
* 010)); /* return vector */
472 void dco_clr_int (int32 ln
)
474 dco_ireq
&= ~(1 << ln
); /* clr mux rcv int */
475 if (dco_ireq
== 0) /* all clr? */
477 else SET_INT (DCO
); /* no, set intr */
481 void dco_set_int (int32 ln
)
483 dco_ireq
|= (1 << ln
); /* clr mux rcv int */
484 SET_INT (DCO
); /* set master intr */
488 int32
dco_iack (void)
492 for (ln
= 0; ln
< DCX_LINES
; ln
++) { /* find 1st line */
493 if (dco_ireq
& (1 << ln
)) {
494 dco_clr_int (ln
); /* clear intr */
495 return (dci_dib
.vec
+ (ln
* 010) + 4); /* return vector */
503 t_stat
dcx_reset (DEVICE
*dptr
)
507 dcx_enbdis (dptr
->flags
& DEV_DIS
); /* sync enables */
508 sim_cancel (&dci_unit
); /* assume stop */
509 if (dci_unit
.flags
& UNIT_ATT
) /* if attached, */
510 sim_activate (&dci_unit
, tmxr_poll
); /* activate */
511 for (ln
= 0; ln
< DCX_LINES
; ln
++) /* for all lines */
513 return auto_config (dci_dev
.name
, dcx_desc
.lines
); /* auto config */
516 /* Reset individual line */
518 void dcx_reset_ln (int32 ln
)
520 dci_buf
[ln
] = 0; /* clear buf */
522 dco_buf
[ln
] = 0; /* clear buf */
523 dco_csr
[ln
] = CSR_DONE
;
524 sim_cancel (&dco_unit
[ln
]); /* deactivate */
530 /* Attach master unit */
532 t_stat
dcx_attach (UNIT
*uptr
, char *cptr
)
536 r
= tmxr_attach (&dcx_desc
, uptr
, cptr
); /* attach */
537 if (r
!= SCPE_OK
) /* error? */
539 sim_activate (uptr
, tmxr_poll
); /* start poll */
543 /* Detach master unit */
545 t_stat
dcx_detach (UNIT
*uptr
)
550 r
= tmxr_detach (&dcx_desc
, uptr
); /* detach */
551 for (i
= 0; i
< DCX_LINES
; i
++) /* all lines, */
552 dcx_ldsc
[i
].rcve
= 0; /* disable rcv */
553 sim_cancel (uptr
); /* stop poll */
557 /* Show summary processor */
559 t_stat
dcx_summ (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
)
563 for (i
= t
= 0; i
< DCX_LINES
; i
++) t
= t
+ (dcx_ldsc
[i
].conn
!= 0);
564 if (t
== 1) fprintf (st
, "1 connection");
565 else fprintf (st
, "%d connections", t
);
569 /* SHOW CONN/STAT processor */
571 t_stat
dcx_show (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
)
575 for (i
= t
= 0; i
< DCX_LINES
; i
++) t
= t
+ (dcx_ldsc
[i
].conn
!= 0);
577 for (i
= 0; i
< DCX_LINES
; i
++) {
578 if (dcx_ldsc
[i
].conn
) {
579 if (val
) tmxr_fconns (st
, &dcx_ldsc
[i
], i
);
580 else tmxr_fstats (st
, &dcx_ldsc
[i
], i
);
584 else fprintf (st
, "all disconnected\n");
588 /* Enable/disable device */
590 void dcx_enbdis (int32 dis
)
593 dci_dev
.flags
= dco_dev
.flags
| DEV_DIS
;
594 dco_dev
.flags
= dco_dev
.flags
| DEV_DIS
;
597 dci_dev
.flags
= dci_dev
.flags
& ~DEV_DIS
;
598 dco_dev
.flags
= dco_dev
.flags
& ~DEV_DIS
;
603 /* SHOW VECTOR processor */
605 t_stat
dcx_show_vec (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
)
607 return show_vec (st
, uptr
, dcx_desc
.lines
* 2, desc
);
610 /* Change number of lines */
612 t_stat
dcx_set_lines (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
617 if (cptr
== NULL
) return SCPE_ARG
;
618 newln
= get_uint (cptr
, 10, DCX_LINES
, &r
);
619 if ((r
!= SCPE_OK
) || (newln
== dcx_desc
.lines
)) return r
;
620 if (newln
== 0) return SCPE_ARG
;
621 if (newln
< dcx_desc
.lines
) {
622 for (i
= newln
, t
= 0; i
< dcx_desc
.lines
; i
++) t
= t
| dcx_ldsc
[i
].conn
;
623 if (t
&& !get_yn ("This will disconnect users; proceed [N]?", FALSE
))
625 for (i
= newln
; i
< dcx_desc
.lines
; i
++) {
626 if (dcx_ldsc
[i
].conn
) {
627 tmxr_linemsg (&dcx_ldsc
[i
], "\r\nOperator disconnected line\r\n");
628 tmxr_reset_ln (&dcx_ldsc
[i
]); /* reset line */
630 dco_unit
[i
].flags
|= UNIT_DIS
;
635 for (i
= dcx_desc
.lines
; i
< newln
; i
++) {
636 dco_unit
[i
].flags
&= ~UNIT_DIS
;
640 dcx_desc
.lines
= newln
;
641 dci_dib
.lnt
= newln
* 010; /* upd IO page lnt */
642 return auto_config (dci_dev
.name
, newln
); /* auto config */
645 /* Show number of lines */
647 t_stat
dcx_show_lines (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
)
649 fprintf (st
, "lines=%d", dcx_desc
.lines
);