First Commit of my working state
[simh.git] / PDP11 / pdp11_dl.c
1 /* pdp11_dl.c: PDP-11 multiple terminal interface simulator
2
3 Copyright (c) 1993-2006, 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 dli,dlo DL11 terminal input/output
27
28 20-May-2008 RMS Added modem control support
29 */
30
31 #if defined (VM_PDP10) /* PDP10 version */
32 #error "DL11 is not supported on the PDP-10!"
33
34 #elif defined (VM_VAX) /* VAX version */
35 #error "DL11 is not supported on the VAX!"
36
37 #else /* PDP-11 version */
38 #include "pdp11_defs.h"
39 #endif
40 #include "sim_sock.h"
41 #include "sim_tmxr.h"
42
43 #define DLX_MASK (DLX_LINES - 1)
44 #define DLI_RCI 0 /* rcv ints */
45 #define DLI_DSI 1 /* dset ints */
46
47 /* Modem control */
48
49 #define DLX_V_MDM (TTUF_V_UF + 0)
50 #define DLX_MDM (1u << DLX_V_MDM)
51
52 /* registers */
53
54 #define DLICSR_DSI 0100000 /* dataset int, RO */
55 #define DLICSR_RNG 0040000 /* ring, RO */
56 #define DLICSR_CTS 0020000 /* CTS, RO */
57 #define DLICSR_CDT 0010000 /* CDT, RO */
58 #define DLICSR_SEC 0002000 /* sec rcv, RONI */
59 #define DLICSR_DSIE 0000040 /* DSI ie, RW */
60 #define DLICSR_SECX 0000010 /* sec xmt, RWNI */
61 #define DLICSR_RTS 0000004 /* RTS, RW */
62 #define DLICSR_DTR 0000002 /* DTR, RW */
63 #define DLICSR_RD (CSR_DONE|CSR_IE) /* DL11C */
64 #define DLICSR_WR (CSR_IE)
65 #define DLICSR_RD_M (DLICSR_DSI|DLICSR_RNG|DLICSR_CTS|DLICSR_CDT|DLICSR_SEC| \
66 CSR_DONE|CSR_IE|DLICSR_DSIE|DLICSR_SECX|DLICSR_RTS|DLICSR_DTR)
67 #define DLICSR_WR_M (CSR_IE|DLICSR_DSIE|DLICSR_SECX|DLICSR_RTS|DLICSR_DTR)
68 #define DLIBUF_ERR 0100000
69 #define DLIBUF_OVR 0040000
70 #define DLIBUF_RBRK 0020000
71 #define DLIBUF_RD (DLIBUF_ERR|DLIBUF_OVR|DLIBUF_RBRK|0377)
72 #define DLOCSR_MNT 0000004 /* maint, RWNI */
73 #define DLOCSR_XBR 0000001 /* xmit brk, RWNI */
74 #define DLOCSR_RD (CSR_DONE|CSR_IE|DLOCSR_MNT|DLOCSR_XBR)
75 #define DLOCSR_WR (CSR_IE|DLOCSR_MNT|DLOCSR_XBR)
76
77 extern int32 int_req[IPL_HLVL];
78 extern int32 tmxr_poll;
79
80 uint16 dli_csr[DLX_LINES] = { 0 }; /* control/status */
81 uint16 dli_buf[DLX_LINES] = { 0 };
82 uint32 dli_ireq[2] = { 0, 0};
83 uint16 dlo_csr[DLX_LINES] = { 0 }; /* control/status */
84 uint8 dlo_buf[DLX_LINES] = { 0 };
85 uint32 dlo_ireq = 0;
86 TMLN dlx_ldsc[DLX_LINES] = { 0 }; /* line descriptors */
87 TMXR dlx_desc = { DLX_LINES, 0, 0, dlx_ldsc }; /* mux descriptor */
88
89 t_stat dlx_rd (int32 *data, int32 PA, int32 access);
90 t_stat dlx_wr (int32 data, int32 PA, int32 access);
91 t_stat dlx_reset (DEVICE *dptr);
92 t_stat dli_svc (UNIT *uptr);
93 t_stat dlo_svc (UNIT *uptr);
94 t_stat dlx_attach (UNIT *uptr, char *cptr);
95 t_stat dlx_detach (UNIT *uptr);
96 t_stat dlx_summ (FILE *st, UNIT *uptr, int32 val, void *desc);
97 t_stat dlx_show (FILE *st, UNIT *uptr, int32 val, void *desc);
98 t_stat dlx_show_vec (FILE *st, UNIT *uptr, int32 val, void *desc);
99 t_stat dlx_set_lines (UNIT *uptr, int32 val, char *cptr, void *desc);
100 t_stat dlx_show_lines (FILE *st, UNIT *uptr, int32 val, void *desc);
101 void dlx_enbdis (int32 dis);
102 void dli_clr_int (int32 ln, uint32 wd);
103 void dli_set_int (int32 ln, uint32 wd);
104 int32 dli_iack (void);
105 void dlo_clr_int (int32 ln);
106 void dlo_set_int (int32 ln);
107 int32 dlo_iack (void);
108 void dlx_reset_ln (int32 ln);
109
110 /* DLI data structures
111
112 dli_dev DLI device descriptor
113 dli_unit DLI unit descriptor
114 dli_reg DLI register list
115 */
116
117 DIB dli_dib = {
118 IOBA_DL, IOLN_DL, &dlx_rd, &dlx_wr,
119 2, IVCL (DLI), VEC_DLI, { &dli_iack, &dlo_iack }
120 };
121
122 UNIT dli_unit = { UDATA (&dli_svc, 0, 0), KBD_POLL_WAIT };
123
124 REG dli_reg[] = {
125 { BRDATA (BUF, dli_buf, DEV_RDX, 16, DLX_LINES) },
126 { BRDATA (CSR, dli_csr, DEV_RDX, 16, DLX_LINES) },
127 { GRDATA (IREQ, dli_ireq[DLI_RCI], DEV_RDX, DLX_LINES, 0) },
128 { GRDATA (DSI, dli_ireq[DLI_DSI], DEV_RDX, DLX_LINES, 0) },
129 { DRDATA (LINES, dlx_desc.lines, 6), REG_HRO },
130 { GRDATA (DEVADDR, dli_dib.ba, DEV_RDX, 32, 0), REG_HRO },
131 { GRDATA (DEVIOLN, dli_dib.lnt, DEV_RDX, 32, 0), REG_HRO },
132 { GRDATA (DEVVEC, dli_dib.vec, DEV_RDX, 16, 0), REG_HRO },
133 { NULL }
134 };
135
136 MTAB dli_mod[] = {
137 { UNIT_ATT, UNIT_ATT, "summary", NULL, NULL, &dlx_summ },
138 { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT",
139 &tmxr_dscln, NULL, &dlx_desc },
140 { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL,
141 NULL, &dlx_show, NULL },
142 { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL,
143 NULL, &dlx_show, NULL },
144 { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL,
145 &set_addr, &show_addr, NULL },
146 { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL,
147 &set_vec, &dlx_show_vec, NULL },
148 { MTAB_XTD | MTAB_VDV, 0, "lines", "LINES",
149 &dlx_set_lines, &dlx_show_lines },
150 { 0 }
151 };
152
153 DEVICE dli_dev = {
154 "DLI", &dli_unit, dli_reg, dli_mod,
155 1, 10, 31, 1, 8, 8,
156 NULL, NULL, &dlx_reset,
157 NULL, &dlx_attach, &dlx_detach,
158 &dli_dib, DEV_UBUS | DEV_QBUS | DEV_DISABLE | DEV_DIS
159 };
160
161 /* DLO data structures
162
163 dlo_dev DLO device descriptor
164 dlo_unit DLO unit descriptor
165 dlo_reg DLO register list
166 */
167
168 UNIT dlo_unit[] = {
169 { UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
170 { UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
171 { UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
172 { UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
173 { UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
174 { UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
175 { UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
176 { UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
177 { UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
178 { UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
179 { UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
180 { UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
181 { UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
182 { UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
183 { UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
184 { UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT }
185 };
186
187 REG dlo_reg[] = {
188 { BRDATA (BUF, dlo_buf, DEV_RDX, 8, DLX_LINES) },
189 { BRDATA (CSR, dlo_csr, DEV_RDX, 16, DLX_LINES) },
190 { GRDATA (IREQ, dlo_ireq, DEV_RDX, DLX_LINES, 0) },
191 { URDATA (TIME, dlo_unit[0].wait, 10, 31, 0,
192 DLX_LINES, PV_LEFT) },
193 { NULL }
194 };
195
196 MTAB dlo_mod[] = {
197 { TT_MODE, TT_MODE_UC, "UC", "UC", NULL },
198 { TT_MODE, TT_MODE_7B, "7b", "7B", NULL },
199 { TT_MODE, TT_MODE_8B, "8b", "8B", NULL },
200 { TT_MODE, TT_MODE_7P, "7p", "7P", NULL },
201 { DLX_MDM, 0, "no dataset", "NODATASET", NULL },
202 { DLX_MDM, DLX_MDM, "dataset", "DATASET", NULL },
203 { MTAB_XTD|MTAB_VUN, 0, NULL, "DISCONNECT",
204 &tmxr_dscln, NULL, &dlx_desc },
205 { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG",
206 &tmxr_set_log, &tmxr_show_log, &dlx_desc },
207 { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG",
208 &tmxr_set_nolog, NULL, &dlx_desc },
209 { 0 }
210 };
211
212 DEVICE dlo_dev = {
213 "DLO", dlo_unit, dlo_reg, dlo_mod,
214 DLX_LINES, 10, 31, 1, 8, 8,
215 NULL, NULL, &dlx_reset,
216 NULL, NULL, NULL,
217 NULL, DEV_UBUS | DEV_QBUS | DEV_DISABLE | DEV_DIS
218 };
219
220 /* Terminal input routines */
221
222 t_stat dlx_rd (int32 *data, int32 PA, int32 access)
223 {
224 int32 ln = ((PA - dli_dib.ba) >> 3) & DLX_MASK;
225
226 switch ((PA >> 1) & 03) { /* decode PA<2:1> */
227
228 case 00: /* tti csr */
229 *data = dli_csr[ln] &
230 ((dlo_unit[ln].flags & DLX_MDM)? DLICSR_RD_M: DLICSR_RD);
231 dli_csr[ln] &= ~DLICSR_DSI; /* clr DSI flag */
232 dli_clr_int (ln, DLI_DSI); /* clr dset int req */
233 return SCPE_OK;
234
235 case 01: /* tti buf */
236 *data = dli_buf[ln] & DLIBUF_RD;
237 dli_csr[ln] &= ~CSR_DONE; /* clr rcv done */
238 dli_clr_int (ln, DLI_RCI); /* clr rcv int req */
239 return SCPE_OK;
240
241 case 02: /* tto csr */
242 *data = dlo_csr[ln] & DLOCSR_RD;
243 return SCPE_OK;
244
245 case 03: /* tto buf */
246 *data = dlo_buf[ln];
247 return SCPE_OK;
248 } /* end switch PA */
249
250 return SCPE_NXM;
251 }
252
253 t_stat dlx_wr (int32 data, int32 PA, int32 access)
254 {
255 int32 ln = ((PA - dli_dib.ba) >> 3) & DLX_MASK;
256 TMLN *lp = &dlx_ldsc[ln];
257
258 switch ((PA >> 1) & 03) { /* decode PA<2:1> */
259
260 case 00: /* tti csr */
261 if (PA & 1) return SCPE_OK; /* odd byte RO */
262 if ((data & CSR_IE) == 0)
263 dli_clr_int (ln, DLI_RCI);
264 else if ((dli_csr[ln] & (CSR_DONE + CSR_IE)) == CSR_DONE)
265 dli_set_int (ln, DLI_RCI);
266 if (dlo_unit[ln].flags & DLX_MDM) { /* modem control */
267 if ((data & DLICSR_DSIE) == 0)
268 dli_clr_int (ln, DLI_DSI);
269 else if ((dli_csr[ln] & (DLICSR_DSI|DLICSR_DSIE)) == DLICSR_DSI)
270 dli_set_int (ln, DLI_DSI);
271 if ((data ^ dli_csr[ln]) & DLICSR_DTR) { /* DTR change? */
272 if ((data & DLICSR_DTR) && lp->conn) { /* setting DTR? */
273 dli_csr[ln] = (dli_csr[ln] & ~DLICSR_RNG) |
274 (DLICSR_CDT|DLICSR_CTS|DLICSR_DSI);
275 if (data & DLICSR_DSIE) /* if ie, req int */
276 dli_set_int (ln, DLI_DSI);
277 } /* end DTR 0->1 + ring */
278 else { /* clearing DTR */
279 if (lp->conn) { /* connected? */
280 tmxr_linemsg (lp, "\r\nLine hangup\r\n");
281 tmxr_reset_ln (lp); /* reset line */
282 if (dli_csr[ln] & DLICSR_CDT) { /* carrier det? */
283 dli_csr[ln] |= DLICSR_DSI;
284 if (data & DLICSR_DSIE) /* if ie, req int */
285 dli_set_int (ln, DLI_DSI);
286 }
287 }
288 dli_csr[ln] &= ~(DLICSR_CDT|DLICSR_RNG|DLICSR_CTS);
289 /* clr CDT,RNG,CTS */
290 } /* end DTR 1->0 */
291 } /* end DTR chg */
292 dli_csr[ln] = (uint16) ((dli_csr[ln] & ~DLICSR_WR_M) | (data & DLICSR_WR_M));
293 } /* end modem */
294 dli_csr[ln] = (uint16) ((dli_csr[ln] & ~DLICSR_WR) | (data & DLICSR_WR));
295 return SCPE_OK;
296
297 case 01: /* tti buf */
298 return SCPE_OK;
299
300 case 02: /* tto csr */
301 if (PA & 1) return SCPE_OK;
302 if ((data & CSR_IE) == 0)
303 dlo_clr_int (ln);
304 else if ((dlo_csr[ln] & (CSR_DONE + CSR_IE)) == CSR_DONE)
305 dlo_set_int (ln);
306 dlo_csr[ln] = (uint16) ((dlo_csr[ln] & ~DLOCSR_WR) | (data & DLOCSR_WR));
307 return SCPE_OK;
308
309 case 03: /* tto buf */
310 if ((PA & 1) == 0)
311 dlo_buf[ln] = data & 0377;
312 dlo_csr[ln] &= ~CSR_DONE;
313 dlo_clr_int (ln);
314 sim_activate (&dlo_unit[ln], dlo_unit[ln].wait);
315 return SCPE_OK;
316 } /* end switch PA */
317
318 return SCPE_NXM;
319 }
320
321 /* Terminal input service */
322
323 t_stat dli_svc (UNIT *uptr)
324 {
325 int32 ln, c, temp;
326
327 if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */
328 sim_activate (uptr, tmxr_poll); /* continue poll */
329 ln = tmxr_poll_conn (&dlx_desc); /* look for connect */
330 if (ln >= 0) { /* got one? rcv enb */
331 dlx_ldsc[ln].rcve = 1;
332 if (dlo_unit[ln].flags & DLX_MDM) { /* modem control? */
333 if (dli_csr[ln] & DLICSR_DTR) /* DTR already set? */
334 dli_csr[ln] |= (DLICSR_CDT|DLICSR_CTS|DLICSR_DSI);
335 else dli_csr[ln] |= (DLICSR_RNG|DLICSR_DSI); /* no, ring */
336 if (dli_csr[ln] & DLICSR_DSIE) /* if ie, */
337 dli_set_int (ln, DLI_DSI); /* req int */
338 } /* end modem */
339 } /* end new conn */
340 tmxr_poll_rx (&dlx_desc); /* poll for input */
341 for (ln = 0; ln < DLX_LINES; ln++) { /* loop thru lines */
342 if (dlx_ldsc[ln].conn) { /* connected? */
343 if (temp = tmxr_getc_ln (&dlx_ldsc[ln])) { /* get char */
344 if (temp & SCPE_BREAK) /* break? */
345 c = DLIBUF_ERR|DLIBUF_RBRK;
346 else c = sim_tt_inpcvt (temp, TT_GET_MODE (dlo_unit[ln].flags));
347 if (dli_csr[ln] & CSR_DONE)
348 c |= DLIBUF_ERR|DLIBUF_OVR;
349 else dli_csr[ln] |= CSR_DONE;
350 if (dli_csr[ln] & CSR_IE)
351 dli_set_int (ln, DLI_RCI);
352 dli_buf[ln] = c;
353 }
354 }
355 else if (dlo_unit[ln].flags & DLX_MDM) { /* discpnn & modem? */
356 if (dli_csr[ln] & DLICSR_CDT) { /* carrier detect? */
357 dli_csr[ln] |= DLICSR_DSI; /* dataset change */
358 if (dli_csr[ln] & DLICSR_DSIE) /* if ie, */
359 dli_set_int (ln, DLI_DSI); /* req int */
360 }
361 dli_csr[ln] &= ~(DLICSR_CDT|DLICSR_RNG|DLICSR_CTS);
362 /* clr CDT,RNG,CTS */
363 }
364 }
365 return SCPE_OK;
366 }
367
368 /* Terminal output service */
369
370 t_stat dlo_svc (UNIT *uptr)
371 {
372 int32 c;
373 int32 ln = uptr - dlo_unit; /* line # */
374
375 if (dlx_ldsc[ln].conn) { /* connected? */
376 if (dlx_ldsc[ln].xmte) { /* tx enabled? */
377 TMLN *lp = &dlx_ldsc[ln]; /* get line */
378 c = sim_tt_outcvt (dlo_buf[ln], TT_GET_MODE (dlo_unit[ln].flags));
379 if (c >= 0) tmxr_putc_ln (lp, c); /* output char */
380 tmxr_poll_tx (&dlx_desc); /* poll xmt */
381 }
382 else {
383 tmxr_poll_tx (&dlx_desc); /* poll xmt */
384 sim_activate (uptr, dlo_unit[ln].wait); /* wait */
385 return SCPE_OK;
386 }
387 }
388 dlo_csr[ln] |= CSR_DONE; /* set done */
389 if (dlo_csr[ln] & CSR_IE)
390 dlo_set_int (ln);
391 return SCPE_OK;
392 }
393
394 /* Interrupt routines */
395
396 void dli_clr_int (int32 ln, uint32 wd)
397 {
398 dli_ireq[wd] &= ~(1 << ln); /* clr rcv/dset int */
399 if ((dli_ireq[DLI_RCI] | dli_ireq[DLI_DSI]) == 0) /* all clr? */
400 CLR_INT (DLI); /* all clr? */
401 else SET_INT (DLI); /* no, set intr */
402 return;
403 }
404
405 void dli_set_int (int32 ln, uint32 wd)
406 {
407 dli_ireq[wd] |= (1 << ln); /* set rcv/dset int */
408 SET_INT (DLI); /* set master intr */
409 return;
410 }
411
412 int32 dli_iack (void)
413 {
414 int32 ln;
415
416 for (ln = 0; ln < DLX_LINES; ln++) { /* find 1st line */
417 if ((dli_ireq[DLI_RCI] | dli_ireq[DLI_DSI]) & (1 << ln)) {
418 dli_clr_int (ln, DLI_RCI); /* clr both req */
419 dli_clr_int (ln, DLI_DSI);
420 return (dli_dib.vec + (ln * 010)); /* return vector */
421 }
422 }
423 return 0;
424 }
425
426 void dlo_clr_int (int32 ln)
427 {
428 dlo_ireq &= ~(1 << ln); /* clr xmit int */
429 if (dlo_ireq == 0) CLR_INT (DLO); /* all clr? */
430 else SET_INT (DLO); /* no, set intr */
431 return;
432 }
433
434 void dlo_set_int (int32 ln)
435 {
436 dlo_ireq |= (1 << ln); /* set xmit int */
437 SET_INT (DLO); /* set master intr */
438 return;
439 }
440
441 int32 dlo_iack (void)
442 {
443 int32 ln;
444
445 for (ln = 0; ln < DLX_LINES; ln++) { /* find 1st line */
446 if (dlo_ireq & (1 << ln)) {
447 dlo_clr_int (ln); /* clear intr */
448 return (dli_dib.vec + (ln * 010) + 4); /* return vector */
449 }
450 }
451 return 0;
452 }
453
454 /* Reset */
455
456 t_stat dlx_reset (DEVICE *dptr)
457 {
458 int32 ln;
459
460 dlx_enbdis (dptr->flags & DEV_DIS); /* sync enables */
461 sim_cancel (&dli_unit); /* assume stop */
462 if (dli_unit.flags & UNIT_ATT) /* if attached, */
463 sim_activate (&dli_unit, tmxr_poll); /* activate */
464 for (ln = 0; ln < DLX_LINES; ln++) /* for all lines */
465 dlx_reset_ln (ln);
466 return auto_config (dli_dev.name, dlx_desc.lines); /* auto config */
467 }
468
469 /* Reset individual line */
470
471 void dlx_reset_ln (int32 ln)
472 {
473 dli_buf[ln] = 0; /* clear buf */
474 if (dlo_unit[ln].flags & DLX_MDM) /* modem */
475 dli_csr[ln] &= DLICSR_DTR; /* dont clr DTR */
476 else dli_csr[ln] = 0;
477 dlo_buf[ln] = 0; /* clear buf */
478 dlo_csr[ln] = CSR_DONE;
479 sim_cancel (&dlo_unit[ln]); /* deactivate */
480 dli_clr_int (ln, DLI_RCI);
481 dli_clr_int (ln, DLI_DSI);
482 dlo_clr_int (ln);
483 return;
484 }
485
486 /* Attach master unit */
487
488 t_stat dlx_attach (UNIT *uptr, char *cptr)
489 {
490 t_stat r;
491
492 r = tmxr_attach (&dlx_desc, uptr, cptr); /* attach */
493 if (r != SCPE_OK) return r; /* error */
494 sim_activate (uptr, tmxr_poll); /* start poll */
495 return SCPE_OK;
496 }
497
498 /* Detach master unit */
499
500 t_stat dlx_detach (UNIT *uptr)
501 {
502 int32 i;
503 t_stat r;
504
505 r = tmxr_detach (&dlx_desc, uptr); /* detach */
506 for (i = 0; i < DLX_LINES; i++) /* all lines, */
507 dlx_ldsc[i].rcve = 0; /* disable rcv */
508 sim_cancel (uptr); /* stop poll */
509 return r;
510 }
511
512 /* Show summary processor */
513
514 t_stat dlx_summ (FILE *st, UNIT *uptr, int32 val, void *desc)
515 {
516 int32 i, t;
517
518 for (i = t = 0; i < DLX_LINES; i++) t = t + (dlx_ldsc[i].conn != 0);
519 if (t == 1) fprintf (st, "1 connection");
520 else fprintf (st, "%d connections", t);
521 return SCPE_OK;
522 }
523
524 /* SHOW CONN/STAT processor */
525
526 t_stat dlx_show (FILE *st, UNIT *uptr, int32 val, void *desc)
527 {
528 int32 i, t;
529
530 for (i = t = 0; i < DLX_LINES; i++) t = t + (dlx_ldsc[i].conn != 0);
531 if (t) {
532 for (i = 0; i < DLX_LINES; i++) {
533 if (dlx_ldsc[i].conn) {
534 if (val) tmxr_fconns (st, &dlx_ldsc[i], i);
535 else tmxr_fstats (st, &dlx_ldsc[i], i);
536 }
537 }
538 }
539 else fprintf (st, "all disconnected\n");
540 return SCPE_OK;
541 }
542
543 /* Enable/disable device */
544
545 void dlx_enbdis (int32 dis)
546 {
547 if (dis) {
548 dli_dev.flags = dlo_dev.flags | DEV_DIS;
549 dlo_dev.flags = dlo_dev.flags | DEV_DIS;
550 }
551 else {
552 dli_dev.flags = dli_dev.flags & ~DEV_DIS;
553 dlo_dev.flags = dlo_dev.flags & ~DEV_DIS;
554 }
555 return;
556 }
557
558 /* SHOW VECTOR processor */
559
560 t_stat dlx_show_vec (FILE *st, UNIT *uptr, int32 val, void *desc)
561 {
562 return show_vec (st, uptr, dlx_desc.lines * 2, desc);
563 }
564
565 /* Change number of lines */
566
567 t_stat dlx_set_lines (UNIT *uptr, int32 val, char *cptr, void *desc)
568 {
569 int32 newln, i, t;
570 t_stat r;
571
572 if (cptr == NULL) return SCPE_ARG;
573 newln = get_uint (cptr, 10, DLX_LINES, &r);
574 if ((r != SCPE_OK) || (newln == dlx_desc.lines)) return r;
575 if (newln == 0) return SCPE_ARG;
576 if (newln < dlx_desc.lines) {
577 for (i = newln, t = 0; i < dlx_desc.lines; i++) t = t | dlx_ldsc[i].conn;
578 if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE))
579 return SCPE_OK;
580 for (i = newln; i < dlx_desc.lines; i++) {
581 if (dlx_ldsc[i].conn) {
582 tmxr_linemsg (&dlx_ldsc[i], "\r\nOperator disconnected line\r\n");
583 tmxr_reset_ln (&dlx_ldsc[i]); /* reset line */
584 }
585 dlo_unit[i].flags |= UNIT_DIS;
586 dlx_reset_ln (i);
587 }
588 }
589 else {
590 for (i = dlx_desc.lines; i < newln; i++) {
591 dlo_unit[i].flags &= ~UNIT_DIS;
592 dlx_reset_ln (i);
593 }
594 }
595 dlx_desc.lines = newln;
596 dli_dib.lnt = newln * 010; /* upd IO page lnt */
597 return auto_config (dli_dev.name, newln); /* auto config */
598 }
599
600 /* Show number of lines */
601
602 t_stat dlx_show_lines (FILE *st, UNIT *uptr, int32 val, void *desc)
603 {
604 fprintf (st, "lines=%d", dlx_desc.lines);
605 return SCPE_OK;
606 }