Commit | Line | Data |
---|---|---|
196ba1fc PH |
1 | /* nova_tt1.c: NOVA second terminal simulator\r |
2 | \r | |
3 | Copyright (c) 1993-2008, Robert M. Supnik\r | |
4 | Written by Bruce Ray and used with his gracious permission.\r | |
5 | \r | |
6 | Permission is hereby granted, free of charge, to any person obtaining a\r | |
7 | copy of this software and associated documentation files (the "Software"),\r | |
8 | to deal in the Software without restriction, including without limitation\r | |
9 | the rights to use, copy, modify, merge, publish, distribute, sublicense,\r | |
10 | and/or sell copies of the Software, and to permit persons to whom the\r | |
11 | Software is furnished to do so, subject to the following conditions:\r | |
12 | \r | |
13 | The above copyright notice and this permission notice shall be included in\r | |
14 | all copies or substantial portions of the Software.\r | |
15 | \r | |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r | |
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r | |
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\r | |
19 | ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r | |
20 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r | |
21 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r | |
22 | \r | |
23 | Except as contained in this notice, the name of Robert M Supnik shall not be\r | |
24 | used in advertising or otherwise to promote the sale, use or other dealings\r | |
25 | in this Software without prior written authorization from Robert M Supnik.\r | |
26 | \r | |
27 | tti1 second terminal input\r | |
28 | tto1 second terminal output\r | |
29 | \r | |
30 | 09-May-03 RMS Added network device flag\r | |
31 | 05-Jan-03 RMS Fixed calling sequence for setmod\r | |
32 | 03-Oct-02 RMS Added DIBs\r | |
33 | 22-Aug-02 RMS Updated for changes in sim_tmxr\r | |
34 | 30-May-02 RMS Widened POS to 32b\r | |
35 | 06-Jan-02 RMS Revised enable/disable support\r | |
36 | 30-Dec-01 RMS Added show statistics, set disconnect\r | |
37 | 30-Nov-01 RMS Added extended SET/SHOW support\r | |
38 | 17-Sep-01 RMS Changed to use terminal multiplexor library\r | |
39 | 07-Sep-01 RMS Moved function prototypes\r | |
40 | 31-May-01 RMS Added multiconsole support\r | |
41 | 26-Apr-01 RMS Added device enable/disable support\r | |
42 | */\r | |
43 | \r | |
44 | #include "nova_defs.h"\r | |
45 | #include "sim_sock.h"\r | |
46 | #include "sim_tmxr.h"\r | |
47 | \r | |
48 | #define UNIT_V_DASHER (UNIT_V_UF + 0) /* Dasher mode */\r | |
49 | #define UNIT_DASHER (1 << UNIT_V_DASHER)\r | |
50 | \r | |
51 | extern int32 int_req, dev_busy, dev_done, dev_disable;\r | |
52 | extern int32 tmxr_poll; /* calibrated poll */\r | |
53 | TMLN tt1_ldsc = { 0 }; /* line descriptors */\r | |
54 | TMXR tt_desc = { 1, 0, 0, &tt1_ldsc }; /* mux descriptor */\r | |
55 | \r | |
56 | DEVICE tti1_dev, tto1_dev;\r | |
57 | int32 tti1 (int32 pulse, int32 code, int32 AC);\r | |
58 | int32 tto1 (int32 pulse, int32 code, int32 AC);\r | |
59 | t_stat tti1_svc (UNIT *uptr);\r | |
60 | t_stat tto1_svc (UNIT *uptr);\r | |
61 | t_stat tti1_reset (DEVICE *dptr);\r | |
62 | t_stat tto1_reset (DEVICE *dptr);\r | |
63 | t_stat ttx1_setmod (UNIT *uptr, int32 val, char *cptr, void *desc);\r | |
64 | t_stat tti1_attach (UNIT *uptr, char *cptr);\r | |
65 | t_stat tti1_detach (UNIT *uptr);\r | |
66 | t_stat tti1_summ (FILE *st, UNIT *uptr, int32 val, void *desc);\r | |
67 | t_stat tti1_show (FILE *st, UNIT *uptr, int32 val, void *desc);\r | |
68 | void ttx1_enbdis (int32 dis);\r | |
69 | \r | |
70 | /* TTI1 data structures\r | |
71 | \r | |
72 | tti1_dev TTI1 device descriptor\r | |
73 | tti1_unit TTI1 unit descriptor\r | |
74 | tti1_reg TTI1 register list\r | |
75 | ttx1_mod TTI1/TTO1 modifiers list\r | |
76 | */\r | |
77 | \r | |
78 | DIB tti1_dib = { DEV_TTI1, INT_TTI1, PI_TTI1, &tti1 };\r | |
79 | \r | |
80 | UNIT tti1_unit = { UDATA (&tti1_svc, UNIT_ATTABLE, 0), KBD_POLL_WAIT };\r | |
81 | \r | |
82 | REG tti1_reg[] = {\r | |
83 | { ORDATA (BUF, tti1_unit.buf, 8) },\r | |
84 | { FLDATA (BUSY, dev_busy, INT_V_TTI1) },\r | |
85 | { FLDATA (DONE, dev_done, INT_V_TTI1) },\r | |
86 | { FLDATA (DISABLE, dev_disable, INT_V_TTI1) },\r | |
87 | { FLDATA (INT, int_req, INT_V_TTI1) },\r | |
88 | { DRDATA (POS, tt1_ldsc.rxcnt, 32), PV_LEFT },\r | |
89 | { DRDATA (TIME, tti1_unit.wait, 24), REG_NZ + PV_LEFT },\r | |
90 | { NULL }\r | |
91 | };\r | |
92 | \r | |
93 | MTAB tti1_mod[] = {\r | |
94 | { UNIT_DASHER, 0, "ANSI", "ANSI", &ttx1_setmod },\r | |
95 | { UNIT_DASHER, UNIT_DASHER, "Dasher", "DASHER", &ttx1_setmod },\r | |
96 | { UNIT_ATT, UNIT_ATT, "summary", NULL, NULL, &tti1_summ },\r | |
97 | { MTAB_XTD | MTAB_VDV, 0, NULL, "DISCONNECT",\r | |
98 | &tmxr_dscln, NULL, &tt_desc },\r | |
99 | { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL,\r | |
100 | NULL, &tti1_show, NULL },\r | |
101 | { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL,\r | |
102 | NULL, &tti1_show, NULL },\r | |
103 | { 0 }\r | |
104 | };\r | |
105 | \r | |
106 | DEVICE tti1_dev = {\r | |
107 | "TTI1", &tti1_unit, tti1_reg, tti1_mod,\r | |
108 | 1, 10, 31, 1, 8, 8,\r | |
109 | &tmxr_ex, &tmxr_dep, &tti1_reset,\r | |
110 | NULL, &tti1_attach, &tti1_detach,\r | |
111 | &tti1_dib, DEV_NET | DEV_DISABLE\r | |
112 | };\r | |
113 | \r | |
114 | /* TTO1 data structures\r | |
115 | \r | |
116 | tto1_dev TTO1 device descriptor\r | |
117 | tto1_unit TTO1 unit descriptor\r | |
118 | tto1_reg TTO1 register list\r | |
119 | */\r | |
120 | \r | |
121 | DIB tto1_dib = { DEV_TTO1, INT_TTO1, PI_TTO1, &tto1 };\r | |
122 | \r | |
123 | UNIT tto1_unit = { UDATA (&tto1_svc, 0, 0), SERIAL_OUT_WAIT };\r | |
124 | \r | |
125 | REG tto1_reg[] = {\r | |
126 | { ORDATA (BUF, tto1_unit.buf, 8) },\r | |
127 | { FLDATA (BUSY, dev_busy, INT_V_TTO1) },\r | |
128 | { FLDATA (DONE, dev_done, INT_V_TTO1) },\r | |
129 | { FLDATA (DISABLE, dev_disable, INT_V_TTO1) },\r | |
130 | { FLDATA (INT, int_req, INT_V_TTO1) },\r | |
131 | { DRDATA (POS, tt1_ldsc.txcnt, 32), PV_LEFT },\r | |
132 | { DRDATA (TIME, tto1_unit.wait, 24), PV_LEFT },\r | |
133 | { NULL }\r | |
134 | };\r | |
135 | \r | |
136 | MTAB tto1_mod[] = {\r | |
137 | { UNIT_DASHER, 0, "ANSI", "ANSI", &ttx1_setmod },\r | |
138 | { UNIT_DASHER, UNIT_DASHER, "Dasher", "DASHER", &ttx1_setmod },\r | |
139 | { 0 }\r | |
140 | };\r | |
141 | \r | |
142 | DEVICE tto1_dev = {\r | |
143 | "TTO1", &tto1_unit, tto1_reg, tto1_mod,\r | |
144 | 1, 10, 31, 1, 8, 8,\r | |
145 | NULL, NULL, &tto1_reset,\r | |
146 | NULL, NULL, NULL,\r | |
147 | &tto1_dib, DEV_DISABLE\r | |
148 | };\r | |
149 | \r | |
150 | /* Terminal input: IOT routine */\r | |
151 | \r | |
152 | int32 tti1 (int32 pulse, int32 code, int32 AC)\r | |
153 | {\r | |
154 | int32 iodata;\r | |
155 | \r | |
156 | iodata = (code == ioDIA)? tti1_unit.buf & 0377: 0;\r | |
157 | switch (pulse) { /* decode IR<8:9> */\r | |
158 | \r | |
159 | case iopS: /* start */\r | |
160 | dev_busy = dev_busy | INT_TTI1; /* set busy */\r | |
161 | dev_done = dev_done & ~INT_TTI1; /* clear done, int */\r | |
162 | int_req = int_req & ~INT_TTI1;\r | |
163 | break;\r | |
164 | \r | |
165 | case iopC: /* clear */\r | |
166 | dev_busy = dev_busy & ~INT_TTI1; /* clear busy */\r | |
167 | dev_done = dev_done & ~INT_TTI1; /* clear done, int */\r | |
168 | int_req = int_req & ~INT_TTI1;\r | |
169 | break;\r | |
170 | } /* end switch */\r | |
171 | \r | |
172 | return iodata;\r | |
173 | }\r | |
174 | \r | |
175 | /* Unit service */\r | |
176 | \r | |
177 | t_stat tti1_svc (UNIT *uptr)\r | |
178 | {\r | |
179 | int32 temp, newln;\r | |
180 | \r | |
181 | if (tt1_ldsc.conn) { /* connected? */\r | |
182 | tmxr_poll_rx (&tt_desc); /* poll for input */\r | |
183 | if (temp = tmxr_getc_ln (&tt1_ldsc)) { /* get char */ \r | |
184 | uptr->buf = temp & 0177;\r | |
185 | if ((uptr->flags & UNIT_DASHER) &&\r | |
186 | (uptr->buf == '\r'))\r | |
187 | uptr->buf = '\n'; /* Dasher: cr->nl */\r | |
188 | dev_busy = dev_busy & ~INT_TTI1; /* clear busy */\r | |
189 | dev_done = dev_done | INT_TTI1; /* set done */\r | |
190 | int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);\r | |
191 | }\r | |
192 | sim_activate (uptr, uptr->wait); /* continue poll */\r | |
193 | }\r | |
194 | if (uptr->flags & UNIT_ATT) { /* attached? */\r | |
195 | newln = tmxr_poll_conn (&tt_desc); /* poll connect */\r | |
196 | if (newln >= 0) { /* got one? */\r | |
197 | sim_activate (&tti1_unit, tti1_unit.wait);\r | |
198 | tt1_ldsc.rcve = 1; /* rcv enabled */\r | |
199 | }\r | |
200 | sim_activate (uptr, tmxr_poll); /* sched poll */\r | |
201 | }\r | |
202 | return SCPE_OK;\r | |
203 | }\r | |
204 | \r | |
205 | /* Reset routine */\r | |
206 | \r | |
207 | t_stat tti1_reset (DEVICE *dptr)\r | |
208 | {\r | |
209 | ttx1_enbdis (dptr->flags & DEV_DIS); /* sync devices */\r | |
210 | tti1_unit.buf = 0; /* <not DG compatible> */\r | |
211 | dev_busy = dev_busy & ~INT_TTI1; /* clear busy */\r | |
212 | dev_done = dev_done & ~INT_TTI1; /* clear done, int */\r | |
213 | int_req = int_req & ~INT_TTI1;\r | |
214 | if (tt1_ldsc.conn) { /* if conn, */\r | |
215 | sim_activate (&tti1_unit, tti1_unit.wait); /* activate, */\r | |
216 | tt1_ldsc.rcve = 1; /* enable */\r | |
217 | }\r | |
218 | else if (tti1_unit.flags & UNIT_ATT) /* if attached, */\r | |
219 | sim_activate (&tti1_unit, tmxr_poll); /* activate */\r | |
220 | else sim_cancel (&tti1_unit); /* else stop */\r | |
221 | return SCPE_OK;\r | |
222 | }\r | |
223 | \r | |
224 | /* Terminal output: IOT routine */\r | |
225 | \r | |
226 | int32 tto1 (int32 pulse, int32 code, int32 AC)\r | |
227 | {\r | |
228 | if (code == ioDOA) tto1_unit.buf = AC & 0377;\r | |
229 | switch (pulse) { /* decode IR<8:9> */\r | |
230 | \r | |
231 | case iopS: /* start */\r | |
232 | dev_busy = dev_busy | INT_TTO1; /* set busy */\r | |
233 | dev_done = dev_done & ~INT_TTO1; /* clear done, int */\r | |
234 | int_req = int_req & ~INT_TTO1;\r | |
235 | sim_activate (&tto1_unit, tto1_unit.wait); /* activate unit */\r | |
236 | break;\r | |
237 | \r | |
238 | case iopC: /* clear */\r | |
239 | dev_busy = dev_busy & ~INT_TTO1; /* clear busy */\r | |
240 | dev_done = dev_done & ~INT_TTO1; /* clear done, int */\r | |
241 | int_req = int_req & ~INT_TTO1;\r | |
242 | sim_cancel (&tto1_unit); /* deactivate unit */\r | |
243 | break;\r | |
244 | } /* end switch */\r | |
245 | \r | |
246 | return 0;\r | |
247 | }\r | |
248 | \r | |
249 | /* Unit service */\r | |
250 | \r | |
251 | t_stat tto1_svc (UNIT *uptr)\r | |
252 | {\r | |
253 | int32 c;\r | |
254 | \r | |
255 | dev_busy = dev_busy & ~INT_TTO1; /* clear busy */\r | |
256 | dev_done = dev_done | INT_TTO1; /* set done */\r | |
257 | int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);\r | |
258 | c = tto1_unit.buf & 0177;\r | |
259 | if ((tto1_unit.flags & UNIT_DASHER) && (c == 031)) c = '\b';\r | |
260 | if (tt1_ldsc.conn) { /* connected? */\r | |
261 | if (tt1_ldsc.xmte) { /* tx enabled? */\r | |
262 | tmxr_putc_ln (&tt1_ldsc, c); /* output char */\r | |
263 | tmxr_poll_tx (&tt_desc); /* poll xmt */\r | |
264 | }\r | |
265 | else {\r | |
266 | tmxr_poll_tx (&tt_desc); /* poll xmt */\r | |
267 | sim_activate (&tto1_unit, tmxr_poll); /* wait */\r | |
268 | }\r | |
269 | }\r | |
270 | return SCPE_OK;\r | |
271 | }\r | |
272 | \r | |
273 | /* Reset routine */\r | |
274 | \r | |
275 | t_stat tto1_reset (DEVICE *dptr)\r | |
276 | {\r | |
277 | ttx1_enbdis (dptr->flags & DEV_DIS); /* sync devices */\r | |
278 | tto1_unit.buf = 0; /* <not DG compatible> */\r | |
279 | dev_busy = dev_busy & ~INT_TTO1; /* clear busy */\r | |
280 | dev_done = dev_done & ~INT_TTO1; /* clear done, int */\r | |
281 | int_req = int_req & ~INT_TTO1;\r | |
282 | sim_cancel (&tto1_unit); /* deactivate unit */\r | |
283 | return SCPE_OK;\r | |
284 | }\r | |
285 | \r | |
286 | t_stat ttx1_setmod (UNIT *uptr, int32 val, char *cptr, void *desc)\r | |
287 | {\r | |
288 | tti1_unit.flags = (tti1_unit.flags & ~UNIT_DASHER) | val;\r | |
289 | tto1_unit.flags = (tto1_unit.flags & ~UNIT_DASHER) | val;\r | |
290 | return SCPE_OK;\r | |
291 | }\r | |
292 | \r | |
293 | /* Attach routine */\r | |
294 | \r | |
295 | t_stat tti1_attach (UNIT *uptr, char *cptr)\r | |
296 | {\r | |
297 | t_stat r;\r | |
298 | \r | |
299 | r = tmxr_attach (&tt_desc, uptr, cptr); /* attach */\r | |
300 | if (r != SCPE_OK) return r; /* error */\r | |
301 | sim_activate (uptr, tmxr_poll); /* start poll */\r | |
302 | return SCPE_OK;\r | |
303 | }\r | |
304 | \r | |
305 | /* Detach routine */\r | |
306 | \r | |
307 | t_stat tti1_detach (UNIT *uptr)\r | |
308 | {\r | |
309 | t_stat r;\r | |
310 | \r | |
311 | r = tmxr_detach (&tt_desc, uptr); /* detach */\r | |
312 | tt1_ldsc.rcve = 0; /* disable rcv */\r | |
313 | sim_cancel (uptr); /* stop poll */\r | |
314 | return r;\r | |
315 | }\r | |
316 | \r | |
317 | /* Show summary processor */\r | |
318 | \r | |
319 | t_stat tti1_summ (FILE *st, UNIT *uptr, int32 val, void *desc)\r | |
320 | {\r | |
321 | if (tt1_ldsc.conn) fprintf (st, "connected");\r | |
322 | else fprintf (st, "disconnected");\r | |
323 | return SCPE_OK;\r | |
324 | }\r | |
325 | \r | |
326 | /* SHOW CONN/STAT processor */\r | |
327 | \r | |
328 | t_stat tti1_show (FILE *st, UNIT *uptr, int32 val, void *desc)\r | |
329 | {\r | |
330 | if (val) tmxr_fconns (st, &tt1_ldsc, -1);\r | |
331 | else tmxr_fstats (st, &tt1_ldsc, -1);\r | |
332 | return SCPE_OK;\r | |
333 | }\r | |
334 | \r | |
335 | /* Enable/disable device */\r | |
336 | \r | |
337 | void ttx1_enbdis (int32 dis)\r | |
338 | {\r | |
339 | if (dis) {\r | |
340 | tti1_dev.flags = tto1_dev.flags | DEV_DIS;\r | |
341 | tto1_dev.flags = tto1_dev.flags | DEV_DIS;\r | |
342 | }\r | |
343 | else {\r | |
344 | tti1_dev.flags = tti1_dev.flags & ~DEV_DIS;\r | |
345 | tto1_dev.flags = tto1_dev.flags & ~DEV_DIS;\r | |
346 | }\r | |
347 | return;\r | |
348 | }\r |