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