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