First Commit of my working state
[simh.git] / PDP18B / pdp18b_stddev.c
CommitLineData
196ba1fc
PH
1/* pdp18b_stddev.c: 18b PDP's standard devices\r
2\r
3 Copyright (c) 1993-2007, 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 ptr paper tape reader\r
27 ptp paper tape punch\r
28 tti keyboard\r
29 tto teleprinter\r
30 clk clock\r
31\r
32 18-Jun-07 RMS Added UNIT_IDLE to console input, clock\r
33 18-Oct-06 RMS Added PDP-15 programmable duplex control\r
34 Fixed handling of non-printable characters in KSR mode\r
35 Changed clock to be free-running\r
36 Fixed out-of-tape behavior for PDP-9 vs PDP-15\r
37 Synced keyboard to clock\r
38 30-Jun-06 RMS Fixed KSR-28 shift tracking\r
39 20-Jun-06 RMS Added KSR ASCII reader support\r
40 13-Jun-06 RMS Fixed Baudot letters/figures inversion for PDP-4\r
41 Fixed PDP-4/PDP-7 default terminal to be local echo\r
42 22-Nov-05 RMS Revised for new terminal processing routines\r
43 28-May-04 RMS Removed SET TTI CTRL-C\r
44 16-Feb-04 RMS Fixed bug in hardware read-in mode bootstrap\r
45 14-Jan-04 RMS Revised IO device call interface\r
46 CAF does not turn off the clock\r
47 29-Dec-03 RMS Added console backpressure support\r
48 26-Jul-03 RMS Increased PTP, TTO timeouts for PDP-15 operating systems\r
49 Added hardware read-in mode support for PDP-7/9/15\r
50 25-Apr-03 RMS Revised for extended file support\r
51 14-Mar-03 RMS Clean up flags on detach\r
52 01-Mar-03 RMS Added SET/SHOW CLK freq, SET TTI CTRL-C\r
53 22-Dec-02 RMS Added break support\r
54 01-Nov-02 RMS Added 7B/8B support to terminal\r
55 05-Oct-02 RMS Added DIBs, device number support, IORS call\r
56 14-Jul-02 RMS Added ASCII reader/punch support (from Hans Pufal)\r
57 30-May-02 RMS Widened POS to 32b\r
58 29-Nov-01 RMS Added read only unit support\r
59 25-Nov-01 RMS Revised interrupt structure\r
60 17-Sep-01 RMS Removed multiconsole support\r
61 07-Sep-01 RMS Added terminal multiplexor support\r
62 17-Jul-01 RMS Moved function prototype\r
63 10-Jun-01 RMS Cleaned up IOT decoding to reflect hardware\r
64 27-May-01 RMS Added multiconsole support\r
65 10-Mar-01 RMS Added funny format loader support\r
66 05-Mar-01 RMS Added clock calibration support\r
67 22-Dec-00 RMS Added PDP-9/15 half duplex support\r
68 30-Nov-00 RMS Fixed PDP-4/7 bootstrap loader for 4K systems\r
69 30-Oct-00 RMS Standardized register naming\r
70 06-Jan-97 RMS Fixed PDP-4 console input\r
71 16-Dec-96 RMS Fixed bug in binary ptr service\r
72*/\r
73\r
74#include "pdp18b_defs.h"\r
75#include <ctype.h>\r
76\r
77#define UNIT_V_RASCII (UNIT_V_UF + 0) /* reader ASCII */\r
78#define UNIT_RASCII (1 << UNIT_V_RASCII)\r
79#define UNIT_V_KASCII (UNIT_V_UF + 1) /* KSR ASCII */\r
80#define UNIT_KASCII (1 << UNIT_V_KASCII)\r
81#define UNIT_V_PASCII (UNIT_V_UF + 0) /* punch ASCII */\r
82#define UNIT_PASCII (1 << UNIT_V_PASCII)\r
83\r
84extern int32 M[];\r
85extern int32 int_hwre[API_HLVL+1], PC, ASW;\r
86extern int32 sim_switches;\r
87extern int32 sim_is_running;\r
88extern UNIT cpu_unit;\r
89\r
90int32 clk_state = 0;\r
91int32 ptr_err = 0, ptr_stopioe = 0, ptr_state = 0;\r
92int32 ptp_err = 0, ptp_stopioe = 0;\r
93int32 tti_2nd = 0; /* 2nd char waiting */\r
94int32 tty_shift = 0; /* KSR28 shift state */\r
95int32 tti_fdpx = 0; /* prog mode full duplex */\r
96int32 clk_tps = 60; /* ticks/second */\r
97int32 tmxr_poll = 16000; /* term mux poll */\r
98uint32 clk_task_last = 0;\r
99uint32 clk_task_timer = 0;\r
100\r
101const int32 asc_to_baud[128] = {\r
102 000,000,000,000,000,000,000,064, /* bell */\r
103 000,000,0110,000,000,0102,000,000, /* lf, cr */\r
104 000,000,000,000,000,000,000,000,\r
105 000,000,000,000,000,000,000,000,\r
106 0104,066,061,045,062,000,053,072, /* space - ' */\r
107 076,051,000,000,046,070,047,067, /* ( - / */\r
108 055,075,071,060,052,041,065,074, /* 0 - 7 */\r
109 054,043,056,057,000,000,000,063, /* 8 - ? */\r
110 000,030,023,016,022,020,026,013, /* @ - G */\r
111 005,014,032,036,011,007,006,003, /* H - O */\r
112 015,035,012,024,001,034,017,031, /* P - W */\r
113 027,025,021,000,000,000,000,000, /* X - _ */\r
114 000,030,023,016,022,020,026,013, /* ` - g */\r
115 005,014,032,036,011,007,006,003, /* h - o */\r
116 015,035,012,024,001,034,017,031, /* p - w */\r
117 027,025,021,000,000,000,000,000 /* x - DEL */\r
118 };\r
119\r
120const char baud_to_asc[64] = {\r
121 0 ,'T',015,'O',' ','H','N','M',\r
122 012,'L','R','G','I','P','C','V',\r
123 'E','Z','D','B','S','Y','F','X',\r
124 'A','W','J', 0 ,'U','Q','K', 0,\r
125 0 ,'5','\r','9',' ','#',',','.',\r
126 012,')','4','&','8','0',':',';',\r
127 '3','"','$','?','\a','6','!','/',\r
128 '-','2','\'',0 ,'7','1','(', 0\r
129 };\r
130\r
131int32 ptr (int32 dev, int32 pulse, int32 dat);\r
132int32 ptp (int32 dev, int32 pulse, int32 dat);\r
133int32 tti (int32 dev, int32 pulse, int32 dat);\r
134int32 tto (int32 dev, int32 pulse, int32 dat);\r
135int32 clk_iors (void);\r
136int32 ptr_iors (void);\r
137int32 ptp_iors (void);\r
138int32 tti_iors (void);\r
139int32 tto_iors (void);\r
140t_stat clk_svc (UNIT *uptr);\r
141t_stat ptr_svc (UNIT *uptr);\r
142t_stat ptp_svc (UNIT *uptr);\r
143t_stat tti_svc (UNIT *uptr);\r
144t_stat tto_svc (UNIT *uptr);\r
145t_stat clk_reset (DEVICE *dptr);\r
146t_stat ptr_reset (DEVICE *dptr);\r
147t_stat ptp_reset (DEVICE *dptr);\r
148t_stat tti_reset (DEVICE *dptr);\r
149t_stat tto_reset (DEVICE *dptr);\r
150t_stat ptr_attach (UNIT *uptr, char *cptr);\r
151t_stat ptp_attach (UNIT *uptr, char *cptr);\r
152t_stat ptr_detach (UNIT *uptr);\r
153t_stat ptp_detach (UNIT *uptr);\r
154t_stat ptr_boot (int32 unitno, DEVICE *dptr);\r
155t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);\r
156t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc);\r
157t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc);\r
158int32 clk_task_upd (t_bool clr);\r
159\r
160extern int32 upd_iors (void);\r
161\r
162/* CLK data structures\r
163\r
164 clk_dev CLK device descriptor\r
165 clk_unit CLK unit\r
166 clk_reg CLK register list\r
167*/\r
168\r
169DIB clk_dib = { 0, 0, &clk_iors, { NULL } };\r
170\r
171UNIT clk_unit = { UDATA (&clk_svc, UNIT_IDLE, 0), 16000 };\r
172\r
173REG clk_reg[] = {\r
174 { FLDATA (INT, int_hwre[API_CLK], INT_V_CLK) },\r
175 { FLDATA (DONE, int_hwre[API_CLK], INT_V_CLK) },\r
176 { FLDATA (ENABLE, clk_state, 0) },\r
177#if defined (PDP15)\r
178 { ORDATA (TASKTIMER, clk_task_timer, 18) },\r
179 { DRDATA (TASKLAST, clk_task_last, 32), REG_HRO },\r
180#endif\r
181 { DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT },\r
182 { DRDATA (TPS, clk_tps, 8), PV_LEFT + REG_HRO },\r
183 { NULL }\r
184 };\r
185\r
186MTAB clk_mod[] = {\r
187 { MTAB_XTD|MTAB_VDV, 50, NULL, "50HZ",\r
188 &clk_set_freq, NULL, NULL },\r
189 { MTAB_XTD|MTAB_VDV, 60, NULL, "60HZ",\r
190 &clk_set_freq, NULL, NULL },\r
191 { MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL,\r
192 NULL, &clk_show_freq, NULL },\r
193 { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_devno },\r
194 { 0 }\r
195 };\r
196\r
197DEVICE clk_dev = {\r
198 "CLK", &clk_unit, clk_reg, clk_mod,\r
199 1, 0, 0, 0, 0, 0,\r
200 NULL, NULL, &clk_reset,\r
201 NULL, NULL, NULL,\r
202 &clk_dib, 0\r
203 };\r
204\r
205/* PTR data structures\r
206\r
207 ptr_dev PTR device descriptor\r
208 ptr_unit PTR unit\r
209 ptr_reg PTR register list\r
210*/\r
211\r
212DIB ptr_dib = { DEV_PTR, 1, &ptr_iors, { &ptr } };\r
213\r
214UNIT ptr_unit = {\r
215 UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),\r
216 SERIAL_IN_WAIT\r
217 };\r
218\r
219REG ptr_reg[] = {\r
220 { ORDATA (BUF, ptr_unit.buf, 18) },\r
221 { FLDATA (INT, int_hwre[API_PTR], INT_V_PTR) },\r
222 { FLDATA (DONE, int_hwre[API_PTR], INT_V_PTR) },\r
223#if defined (IOS_PTRERR)\r
224 { FLDATA (ERR, ptr_err, 0) },\r
225#endif\r
226 { ORDATA (STATE, ptr_state, 5), REG_HRO },\r
227 { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },\r
228 { DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT },\r
229 { FLDATA (STOP_IOE, ptr_stopioe, 0) },\r
230 { NULL }\r
231 };\r
232\r
233MTAB ptr_mod[] = {\r
234 { UNIT_RASCII, UNIT_RASCII, "even parity ASCII", NULL },\r
235 { UNIT_KASCII, UNIT_KASCII, "forced parity ASCII", NULL },\r
236 { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_devno },\r
237 { 0 }\r
238 };\r
239\r
240DEVICE ptr_dev = {\r
241 "PTR", &ptr_unit, ptr_reg, ptr_mod,\r
242 1, 10, 31, 1, 8, 8,\r
243 NULL, NULL, &ptr_reset,\r
244 &ptr_boot, &ptr_attach, &ptr_detach,\r
245 &ptr_dib, 0\r
246 };\r
247\r
248/* PTP data structures\r
249\r
250 ptp_dev PTP device descriptor\r
251 ptp_unit PTP unit\r
252 ptp_reg PTP register list\r
253*/\r
254\r
255DIB ptp_dib = { DEV_PTP, 1, &ptp_iors, { &ptp } };\r
256\r
257UNIT ptp_unit = {\r
258 UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT\r
259 };\r
260\r
261REG ptp_reg[] = {\r
262 { ORDATA (BUF, ptp_unit.buf, 8) },\r
263 { FLDATA (INT, int_hwre[API_PTP], INT_V_PTP) },\r
264 { FLDATA (DONE, int_hwre[API_PTP], INT_V_PTP) },\r
265#if defined (IOS_PTPERR)\r
266 { FLDATA (ERR, ptp_err, 0) },\r
267#endif\r
268 { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },\r
269 { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT },\r
270 { FLDATA (STOP_IOE, ptp_stopioe, 0) },\r
271 { NULL }\r
272 };\r
273\r
274MTAB ptp_mod[] = {\r
275 { UNIT_PASCII, UNIT_PASCII, "7b ASCII", NULL },\r
276 { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_devno },\r
277 { 0 }\r
278 };\r
279\r
280DEVICE ptp_dev = {\r
281 "PTP", &ptp_unit, ptp_reg, ptp_mod,\r
282 1, 10, 31, 1, 8, 8,\r
283 NULL, NULL, &ptp_reset,\r
284 NULL, &ptp_attach, &ptp_detach,\r
285 &ptp_dib, 0\r
286 };\r
287\r
288/* TTI data structures\r
289\r
290 tti_dev TTI device descriptor\r
291 tti_unit TTI unit\r
292 tti_reg TTI register list\r
293*/\r
294\r
295#if defined (KSR28)\r
296#define TTI_WIDTH 5\r
297#define TTI_FIGURES (1 << TTI_WIDTH)\r
298#define TTI_BOTH (1 << (TTI_WIDTH + 1))\r
299#define BAUDOT_LETTERS 037\r
300#define BAUDOT_FIGURES 033\r
301\r
302#else\r
303\r
304#define TTI_WIDTH 8\r
305#endif\r
306\r
307#define TTI_MASK ((1 << TTI_WIDTH) - 1)\r
308#define TTUF_V_HDX (TTUF_V_UF + 0) /* half duplex */\r
309#define TTUF_HDX (1 << TTUF_V_HDX)\r
310\r
311DIB tti_dib = { DEV_TTI, 1, &tti_iors, { &tti } };\r
312\r
313UNIT tti_unit = { UDATA (&tti_svc, UNIT_IDLE+TT_MODE_KSR+TTUF_HDX, 0), 0 };\r
314\r
315REG tti_reg[] = {\r
316 { ORDATA (BUF, tti_unit.buf, TTI_WIDTH) },\r
317#if defined (KSR28)\r
318 { ORDATA (BUF2ND, tti_2nd, TTI_WIDTH), REG_HRO },\r
319#endif\r
320 { FLDATA (INT, int_hwre[API_TTI], INT_V_TTI) },\r
321 { FLDATA (DONE, int_hwre[API_TTI], INT_V_TTI) },\r
322#if defined (PDP15)\r
323 { FLDATA (FDPX, tti_fdpx, 0) },\r
324#endif\r
325 { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT },\r
326 { DRDATA (TIME, tti_unit.wait, 24), PV_LEFT },\r
327 { NULL }\r
328 };\r
329\r
330MTAB tti_mod[] = {\r
331#if !defined (KSR28)\r
332 { TT_MODE, TT_MODE_KSR, "KSR", "KSR", &tty_set_mode },\r
333 { TT_MODE, TT_MODE_7B, "7b", "7B", &tty_set_mode },\r
334 { TT_MODE, TT_MODE_8B, "8b", "8B", &tty_set_mode },\r
335 { TT_MODE, TT_MODE_7P, "7b", NULL, NULL },\r
336#endif\r
337 { TTUF_HDX, 0 , "full duplex", "FDX", NULL },\r
338 { TTUF_HDX, TTUF_HDX, "half duplex", "HDX", NULL },\r
339 { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_devno, NULL },\r
340 { 0 }\r
341 };\r
342\r
343DEVICE tti_dev = {\r
344 "TTI", &tti_unit, tti_reg, tti_mod,\r
345 1, 10, 31, 1, 8, 8,\r
346 NULL, NULL, &tti_reset,\r
347 NULL, NULL, NULL,\r
348 &tti_dib, 0\r
349 };\r
350\r
351/* TTO data structures\r
352\r
353 tto_dev TTO device descriptor\r
354 tto_unit TTO unit\r
355 tto_reg TTO register list\r
356*/\r
357\r
358#if defined (KSR28)\r
359#define TTO_WIDTH 5\r
360#define TTO_FIGURES (1 << TTO_WIDTH)\r
361\r
362#else\r
363\r
364#define TTO_WIDTH 8\r
365#endif\r
366\r
367#define TTO_MASK ((1 << TTO_WIDTH) - 1)\r
368\r
369DIB tto_dib = { DEV_TTO, 1, &tto_iors, { &tto } };\r
370\r
371UNIT tto_unit = { UDATA (&tto_svc, TT_MODE_KSR, 0), 1000 };\r
372\r
373REG tto_reg[] = {\r
374 { ORDATA (BUF, tto_unit.buf, TTO_WIDTH) },\r
375#if defined (KSR28)\r
376 { FLDATA (SHIFT, tty_shift, 0), REG_HRO },\r
377#endif\r
378 { FLDATA (INT, int_hwre[API_TTO], INT_V_TTO) },\r
379 { FLDATA (DONE, int_hwre[API_TTO], INT_V_TTO) },\r
380 { DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT },\r
381 { DRDATA (TIME, tto_unit.wait, 24), PV_LEFT },\r
382 { NULL }\r
383 };\r
384\r
385MTAB tto_mod[] = {\r
386#if !defined (KSR28)\r
387 { TT_MODE, TT_MODE_KSR, "KSR", "KSR", &tty_set_mode },\r
388 { TT_MODE, TT_MODE_7B, "7b", "7B", &tty_set_mode },\r
389 { TT_MODE, TT_MODE_8B, "8b", "8B", &tty_set_mode },\r
390 { TT_MODE, TT_MODE_7P, "7p", "7P", &tty_set_mode },\r
391#endif\r
392 { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_devno },\r
393 { 0 }\r
394 };\r
395\r
396DEVICE tto_dev = {\r
397 "TTO", &tto_unit, tto_reg, tto_mod,\r
398 1, 10, 31, 1, 8, 8,\r
399 NULL, NULL, &tto_reset,\r
400 NULL, NULL, NULL,\r
401 &tto_dib, 0\r
402 };\r
403\r
404/* Clock: IOT routine */\r
405\r
406int32 clk (int32 dev, int32 pulse, int32 dat)\r
407{\r
408if (pulse & 001) { /* CLSF */\r
409 if (TST_INT (CLK)) dat = dat | IOT_SKP;\r
410 }\r
411if (pulse & 004) { /* CLON/CLOF */\r
412 CLR_INT (CLK); /* clear flag */\r
413 if (pulse & 040) clk_state = 1; /* CLON */\r
414 else clk_state = 0; /* CLOF */\r
415 }\r
416return dat;\r
417}\r
418\r
419/* Unit service */\r
420\r
421t_stat clk_svc (UNIT *uptr)\r
422{\r
423int32 t;\r
424\r
425t = sim_rtc_calb (clk_tps); /* calibrate clock */\r
426tmxr_poll = t; /* set mux poll */\r
427sim_activate (&clk_unit, t); /* reactivate unit */\r
428#if defined (PDP15)\r
429clk_task_upd (FALSE); /* update task timer */\r
430#endif\r
431if (clk_state) { /* clock on? */\r
432 M[7] = (M[7] + 1) & DMASK; /* incr counter */\r
433 if (M[7] == 0) SET_INT (CLK); /* ovrflo? set flag */\r
434 }\r
435return SCPE_OK;\r
436}\r
437\r
438#if defined (PDP15)\r
439\r
440/* Task timer update (PDP-15 XVM only)\r
441\r
442 The task timer increments monotonically at 100Khz. Since this can't be\r
443 simulated accurately, updates are done by interpolation since the last\r
444 reading. The timer is also updated at clock events to keep the cycle\r
445 counters from wrapping around more than once between updates. */\r
446\r
447int32 clk_task_upd (t_bool clr)\r
448{\r
449uint32 delta, val, iusec10;\r
450uint32 cur = sim_grtime ();\r
451uint32 old = clk_task_timer;\r
452double usec10;\r
453\r
454if (cur > clk_task_last) delta = cur - clk_task_last;\r
455else delta = clk_task_last - cur;\r
456usec10 = ((((double) delta) * 100000.0) /\r
457 (((double) tmxr_poll) * ((double) clk_tps)));\r
458iusec10 = (int32) usec10;\r
459val = (clk_task_timer + iusec10) & DMASK;\r
460if (clr) clk_task_timer = 0;\r
461else clk_task_timer = val;\r
462clk_task_last = cur;\r
463return ((int32) val);\r
464}\r
465\r
466#endif\r
467\r
468/* IORS service */\r
469\r
470int32 clk_iors (void)\r
471{\r
472return (TST_INT (CLK)? IOS_CLK: 0);\r
473}\r
474\r
475/* Reset routine */\r
476\r
477t_stat clk_reset (DEVICE *dptr)\r
478{\r
479int32 t;\r
480\r
481CLR_INT (CLK); /* clear flag */\r
482if (!sim_is_running) { /* RESET (not CAF)? */\r
483 t = sim_rtc_init (clk_unit.wait); /* init calibration */\r
484 tmxr_poll = t; /* set mux poll */\r
485 sim_activate_abs (&clk_unit, t); /* activate unit */\r
486 clk_state = 0; /* clock off */\r
487 clk_task_timer = 0;\r
488 clk_task_last = 0;\r
489 }\r
490return SCPE_OK;\r
491}\r
492\r
493/* Set frequency */\r
494\r
495t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc)\r
496{\r
497if (cptr) return SCPE_ARG;\r
498if ((val != 50) && (val != 60)) return SCPE_IERR;\r
499clk_tps = val;\r
500return SCPE_OK;\r
501}\r
502\r
503/* Show frequency */\r
504\r
505t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc)\r
506{\r
507fprintf (st, (clk_tps == 50)? "50Hz": "60Hz");\r
508return SCPE_OK;\r
509}\r
510\r
511/* Paper tape reader out-of-tape handling\r
512\r
513 The PDP-4 and PDP-7 readers behaved like most early DEC readers; when\r
514 they ran out of tape, they hung. It was up to the program to sense this\r
515 condition by running a timer.\r
516\r
517 The PDP-9 reader controller synthesized the out of tape condition by\r
518 noticing whether there was a transition on the feed hole within a window.\r
519 The out-of-tape flag was treated like the reader flag in most cases.\r
520\r
521 The PDP-15 reader controller received the out-of-tape flag as a static\r
522 condition from the reader itself and simply reported it via IORS. */\r
523\r
524/* Paper tape reader: IOT routine */\r
525\r
526int32 ptr (int32 dev, int32 pulse, int32 dat)\r
527{\r
528if (pulse & 001) { /* RSF */\r
529 if (TST_INT (PTR)) dat = dat | IOT_SKP;\r
530 }\r
531if (pulse & 002) { /* RRB, RCF */\r
532 CLR_INT (PTR); /* clear flag */\r
533 dat = dat | ptr_unit.buf; /* return buffer */\r
534 }\r
535if (pulse & 004) { /* RSA, RSB */\r
536 ptr_state = (pulse & 040)? 18: 0; /* set mode */\r
537 CLR_INT (PTR); /* clear flag */\r
538#if !defined (PDP15) /* except on PDP15 */\r
539 ptr_err = 0; /* clear error */\r
540#endif\r
541 ptr_unit.buf = 0; /* clear buffer */\r
542 sim_activate (&ptr_unit, ptr_unit.wait);\r
543 }\r
544return dat;\r
545}\r
546\r
547/* Unit service */\r
548\r
549t_stat ptr_svc (UNIT *uptr)\r
550{\r
551int32 temp;\r
552\r
553if ((ptr_unit.flags & UNIT_ATT) == 0) { /* attached? */\r
554#if defined (IOS_PTRERR)\r
555 SET_INT (PTR); /* if err, set flag */\r
556 ptr_err = 1; /* set error */\r
557#endif\r
558 return IORETURN (ptr_stopioe, SCPE_UNATT);\r
559 }\r
560if ((temp = getc (ptr_unit.fileref)) == EOF) { /* end of file? */\r
561#if defined (IOS_PTRERR)\r
562 SET_INT (PTR); /* if err, set flag */\r
563 ptr_err = 1; /* set error */\r
564#endif\r
565 if (feof (ptr_unit.fileref)) {\r
566 if (ptr_stopioe) printf ("PTR end of file\n");\r
567 else return SCPE_OK;\r
568 }\r
569 else perror ("PTR I/O error");\r
570 clearerr (ptr_unit.fileref);\r
571 return SCPE_IOERR;\r
572 }\r
573if (ptr_state == 0) { /* ASCII */\r
574 if (ptr_unit.flags & UNIT_RASCII) { /* want parity? */\r
575 ptr_unit.buf = temp = temp & 0177; /* parity off */\r
576 while (temp = temp & (temp - 1))\r
577 ptr_unit.buf = ptr_unit.buf ^ 0200; /* count bits */\r
578 ptr_unit.buf = ptr_unit.buf ^ 0200; /* set even parity */\r
579 }\r
580 else if (ptr_unit.flags & UNIT_KASCII) /* KSR ASCII? */\r
581 ptr_unit.buf = (temp | 0200) & 0377; /* forced parity */\r
582 else ptr_unit.buf = temp & 0377;\r
583 }\r
584else if (temp & 0200) { /* binary */\r
585 ptr_state = ptr_state - 6;\r
586 ptr_unit.buf = ptr_unit.buf | ((temp & 077) << ptr_state);\r
587 }\r
588if (ptr_state == 0) SET_INT (PTR); /* if done, set flag */\r
589else sim_activate (&ptr_unit, ptr_unit.wait); /* else restart */\r
590ptr_unit.pos = ptr_unit.pos + 1;\r
591return SCPE_OK;\r
592}\r
593\r
594/* Reset routine */\r
595\r
596t_stat ptr_reset (DEVICE *dptr)\r
597{\r
598ptr_state = 0; /* clear state */\r
599ptr_unit.buf = 0;\r
600CLR_INT (PTR); /* clear flag */\r
601#if defined (PDP15) /* PDP15, static err */\r
602if (((ptr_unit.flags & UNIT_ATT) == 0) || feof (ptr_unit.fileref))\r
603 ptr_err = 1;\r
604else\r
605#endif\r
606ptr_err = 0; /* all other, clr err */\r
607sim_cancel (&ptr_unit); /* deactivate unit */\r
608return SCPE_OK;\r
609}\r
610\r
611/* IORS service */\r
612\r
613int32 ptr_iors (void)\r
614{\r
615return ((TST_INT (PTR)? IOS_PTR: 0)\r
616#if defined (IOS_PTRERR)\r
617 | (ptr_err? IOS_PTRERR: 0)\r
618#endif\r
619 );\r
620}\r
621\r
622/* Attach routine */\r
623\r
624t_stat ptr_attach (UNIT *uptr, char *cptr)\r
625{\r
626t_stat reason;\r
627\r
628reason = attach_unit (uptr, cptr);\r
629if (reason != SCPE_OK) return reason;\r
630ptr_err = 0; /* attach clrs error */\r
631ptr_unit.flags = ptr_unit.flags & ~(UNIT_RASCII|UNIT_KASCII);\r
632if (sim_switches & SWMASK ('A'))\r
633 ptr_unit.flags = ptr_unit.flags | UNIT_RASCII;\r
634if (sim_switches & SWMASK ('K'))\r
635 ptr_unit.flags = ptr_unit.flags | UNIT_KASCII;\r
636return SCPE_OK;\r
637}\r
638\r
639/* Detach routine */\r
640\r
641t_stat ptr_detach (UNIT *uptr)\r
642{\r
643#if defined (PDP15)\r
644ptr_err = 1;\r
645#endif\r
646ptr_unit.flags = ptr_unit.flags & ~UNIT_RASCII;\r
647return detach_unit (uptr);\r
648}\r
649\r
650/* Hardware RIM loader routines, PDP-7/9/15 */\r
651\r
652int32 ptr_getw (UNIT *uptr, int32 *hi)\r
653{\r
654int32 word, bits, st, ch;\r
655\r
656word = st = bits = 0;\r
657do {\r
658 if ((ch = getc (uptr->fileref)) == EOF) return -1;\r
659 uptr->pos = uptr->pos + 1;\r
660 if (ch & 0200) {\r
661 word = (word << 6) | (ch & 077);\r
662 bits = (bits << 1) | ((ch >> 6) & 1);\r
663 st++;\r
664 }\r
665 } while (st < 3);\r
666if (hi != NULL) *hi = bits;\r
667return word;\r
668}\r
669\r
670t_stat ptr_rim_load (UNIT *uptr, int32 origin)\r
671{\r
672int32 bits, val;\r
673\r
674for (;;) { /* word loop */\r
675 if ((val = ptr_getw (uptr, &bits)) < 0) return SCPE_FMT;\r
676 if (bits & 1) { /* end of tape? */\r
677 if ((val & 0760000) == OP_JMP) {\r
678 PC = ((origin - 1) & 060000) | (val & 017777);\r
679 return SCPE_OK;\r
680 }\r
681 else if (val == OP_HLT) return STOP_HALT;\r
682 break;\r
683 }\r
684 else if (MEM_ADDR_OK (origin)) M[origin++] = val;\r
685 }\r
686return SCPE_FMT;\r
687}\r
688\r
689#if defined (PDP4) || defined (PDP7)\r
690\r
691/* Bootstrap routine, PDP-4 and PDP-7\r
692\r
693 In a 4K system, the boostrap resides at 7762-7776.\r
694 In an 8K or greater system, the bootstrap resides at 17762-17776.\r
695 Because the program is so small, simple masking can be\r
696 used to remove addr<5> for a 4K system. */\r
697\r
698#define BOOT_START 017577\r
699#define BOOT_FPC 017577 /* funny format loader */\r
700#define BOOT_RPC 017770 /* RIM loader */\r
701#define BOOT_LEN (sizeof (boot_rom) / sizeof (int))\r
702\r
703static const int32 boot_rom[] = {\r
704 0700144, /* rsb */\r
705 0117762, /* ff, jsb r1b */\r
706 0057666, /* dac done 1 */\r
707 0117762, /* jms r1b */\r
708 0057667, /* dac done 2 */\r
709 0117762, /* jms r1b */\r
710 0040007, /* dac conend */\r
711 0057731, /* dac conbeg */\r
712 0440007, /* isz conend */\r
713 0117762, /* blk, jms r1b */\r
714 0057673, /* dac cai */\r
715 0741100, /* spa */\r
716 0617665, /* jmp done */\r
717 0117762, /* jms r1b */\r
718 0057777, /* dac tem1 */\r
719 0317673, /* add cai */\r
720 0057775, /* dac cks */\r
721 0117713, /* jms r1a */\r
722 0140010, /* dzm word */\r
723 0457777, /* cont, isz tem1 */\r
724 0617632, /* jmp cont1 */\r
725 0217775, /* lac cks */\r
726 0740001, /* cma */\r
727 0740200, /* sza */\r
728 0740040, /* hlt */\r
729 0700144, /* rsb */\r
730 0617610, /* jmp blk */\r
731 0117713, /* cont1, jms r1a */\r
732 0057762, /* dac tem2 */\r
733 0117713, /* jms r1a */\r
734 0742010, /* rtl */\r
735 0742010, /* rtl */\r
736 0742010, /* rtl */\r
737 0742010, /* rtl */\r
738 0317762, /* add tem2 */\r
739 0057762, /* dac tem2 */\r
740 0117713, /* jms r1a */\r
741 0742020, /* rtr */\r
742 0317726, /* add cdsp */\r
743 0057713, /* dac r1a */\r
744 0517701, /* and ccma */\r
745 0740020, /* rar */\r
746 0317762, /* add tem2 */\r
747 0437713, /* xct i r1a */\r
748 0617622, /* jmp cont */\r
749 0617672, /* dsptch, jmp code0 */\r
750 0617670, /* jmp code1 */\r
751 0617700, /* jmp code2 */\r
752 0617706, /* jmp code3 */\r
753 0417711, /* xct code4 */\r
754 0617732, /* jmp const */\r
755 0740000, /* nop */\r
756 0740000, /* nop */\r
757 0740000, /* nop */\r
758 0200007, /* done, lac conend */\r
759 0740040, /* xx */\r
760 0740040, /* xx */\r
761 0517727, /* code1, and imsk */\r
762 0337762, /* add i tem2 */\r
763 0300010, /* code0, add word */\r
764 0740040, /* cai, xx */\r
765 0750001, /* clc */\r
766 0357673, /* tad cai */\r
767 0057673, /* dac cai */\r
768 0617621, /* jmp cont-1 */\r
769 0711101, /* code2, spa cla */\r
770 0740001, /* ccma, cma */\r
771 0277762, /* xor i tem2 */\r
772 0300010, /* add word */\r
773 0040010, /* code2a, dac word */\r
774 0617622, /* jmp cont */\r
775 0057711, /* code3, dac code4 */\r
776 0217673, /* lac cai */\r
777 0357701, /* tad ccma */\r
778 0740040, /* code4, xx */\r
779 0617622, /* jmp cont */\r
780 0000000, /* r1a, 0 */\r
781 0700101, /* rsf */\r
782 0617714, /* jmp .-1 */\r
783 0700112, /* rrb */\r
784 0700104, /* rsa */\r
785 0057730, /* dac tem */\r
786 0317775, /* add cks */\r
787 0057775, /* dac cks */\r
788 0217730, /* lac tem */\r
789 0744000, /* cll */\r
790 0637713, /* jmp i r1a */\r
791 0017654, /* cdsp, dsptch */\r
792 0760000, /* imsk, 760000 */\r
793 0000000, /* tem, 0 */\r
794 0000000, /* conbeg, 0 */\r
795 0300010, /* const, add word */\r
796 0060007, /* dac i conend */\r
797 0217731, /* lac conbeg */\r
798 0040010, /* dac index */\r
799 0220007, /* lac i conend */\r
800 0560010, /* con1, sad i index */\r
801 0617752, /* jmp find */\r
802 0560010, /* sad i index */\r
803 0617752, /* jmp find */\r
804 0560010, /* sad i index */\r
805 0617752, /* jmp find */\r
806 0560010, /* sad i index */\r
807 0617752, /* jmp find */\r
808 0560010, /* sad i index */\r
809 0617752, /* jmp find */\r
810 0617737, /* jmp con1 */\r
811 0200010, /* find, lac index */\r
812 0540007, /* sad conend */\r
813 0440007, /* isz conend */\r
814 0617704, /* jmp code2a */\r
815 0000000,\r
816 0000000,\r
817 0000000,\r
818 0000000,\r
819 0000000, /* r1b, 0 */\r
820 0700101, /* rsf */\r
821 0617763, /* jmp .-1 */\r
822 0700112, /* rrb */\r
823 0700144, /* rsb */\r
824 0637762, /* jmp i r1b */\r
825 0700144, /* go, rsb */\r
826 0117762, /* g, jms r1b */\r
827 0057775, /* dac cks */\r
828 0417775, /* xct cks */\r
829 0117762, /* jms r1b */\r
830 0000000, /* cks, 0 */\r
831 0617771 /* jmp g */\r
832 };\r
833\r
834t_stat ptr_boot (int32 unitno, DEVICE *dptr)\r
835{\r
836int32 i, mask, wd;\r
837extern int32 sim_switches;\r
838\r
839#if defined (PDP7)\r
840if (sim_switches & SWMASK ('H')) /* hardware RIM load? */\r
841 return ptr_rim_load (&ptr_unit, ASW);\r
842#endif\r
843if (ptr_dib.dev != DEV_PTR) return STOP_NONSTD; /* non-std addr? */\r
844if (MEMSIZE < 8192) mask = 0767777; /* 4k? */\r
845else mask = 0777777;\r
846for (i = 0; i < BOOT_LEN; i++) {\r
847 wd = boot_rom[i];\r
848 if ((wd >= 0040000) && (wd < 0640000)) wd = wd & mask;\r
849 M[(BOOT_START & mask) + i] = wd;\r
850 }\r
851PC = ((sim_switches & SWMASK ('F'))? BOOT_FPC: BOOT_RPC) & mask;\r
852return SCPE_OK;\r
853}\r
854\r
855#else\r
856\r
857/* PDP-9 and PDP-15 have built-in hardware RIM loaders */\r
858\r
859t_stat ptr_boot (int32 unitno, DEVICE *dptr)\r
860{\r
861return ptr_rim_load (&ptr_unit, ASW);\r
862}\r
863\r
864#endif\r
865\r
866/* Paper tape punch: IOT routine */\r
867\r
868int32 ptp (int32 dev, int32 pulse, int32 dat)\r
869{\r
870if (pulse & 001) { /* PSF */\r
871 if (TST_INT (PTP)) dat = dat | IOT_SKP;\r
872 }\r
873if (pulse & 002) CLR_INT (PTP); /* PCF */\r
874if (pulse & 004) { /* PSA, PSB, PLS */\r
875 CLR_INT (PTP); /* clear flag */\r
876 ptp_unit.buf = (pulse & 040)? /* load punch buf */\r
877 (dat & 077) | 0200: dat & 0377; /* bin or alpha */\r
878 sim_activate (&ptp_unit, ptp_unit.wait); /* activate unit */\r
879 }\r
880return dat;\r
881}\r
882\r
883/* Unit service */\r
884\r
885t_stat ptp_svc (UNIT *uptr)\r
886{\r
887SET_INT (PTP); /* set flag */\r
888if ((ptp_unit.flags & UNIT_ATT) == 0) { /* not attached? */\r
889 ptp_err = 1; /* set error */\r
890 return IORETURN (ptp_stopioe, SCPE_UNATT);\r
891 }\r
892if (ptp_unit.flags & UNIT_PASCII) { /* ASCII mode? */\r
893 ptp_unit.buf = ptp_unit.buf & 0177; /* force 7b */\r
894 if ((ptp_unit.buf == 0) || (ptp_unit.buf == 0177))\r
895 return SCPE_OK; /* skip null, del */\r
896 }\r
897if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) { /* I/O error? */\r
898 ptp_err = 1; /* set error */\r
899 perror ("PTP I/O error");\r
900 clearerr (ptp_unit.fileref);\r
901 return SCPE_IOERR;\r
902 }\r
903ptp_unit.pos = ptp_unit.pos + 1;\r
904return SCPE_OK;\r
905}\r
906\r
907/* IORS service */\r
908\r
909int32 ptp_iors (void)\r
910{\r
911return ((TST_INT (PTP)? IOS_PTP: 0)\r
912#if defined (IOS_PTPERR)\r
913 | (ptp_err? IOS_PTPERR: 0)\r
914#endif\r
915 );\r
916}\r
917\r
918/* Reset routine */\r
919\r
920t_stat ptp_reset (DEVICE *dptr)\r
921{\r
922ptp_unit.buf = 0;\r
923CLR_INT (PTP); /* clear flag */\r
924ptp_err = (ptp_unit.flags & UNIT_ATT)? 0: 1;\r
925sim_cancel (&ptp_unit); /* deactivate unit */\r
926return SCPE_OK;\r
927}\r
928\r
929/* Attach routine */\r
930\r
931t_stat ptp_attach (UNIT *uptr, char *cptr)\r
932{\r
933t_stat reason;\r
934\r
935reason = attach_unit (uptr, cptr);\r
936if (reason != SCPE_OK) return reason;\r
937ptp_err = 0;\r
938ptp_unit.flags = ptp_unit.flags & ~UNIT_PASCII;\r
939if (sim_switches & SWMASK ('A'))\r
940 ptp_unit.flags = ptp_unit.flags | UNIT_PASCII;\r
941return reason;\r
942}\r
943\r
944/* Detach routine */\r
945\r
946t_stat ptp_detach (UNIT *uptr)\r
947{\r
948ptp_err = 1;\r
949ptp_unit.flags = ptp_unit.flags & ~UNIT_PASCII;\r
950return detach_unit (uptr);\r
951}\r
952\r
953/* Terminal input: IOT routine */\r
954\r
955int32 tti (int32 dev, int32 pulse, int32 dat)\r
956{\r
957if (pulse & 001) { /* KSF */\r
958 if (TST_INT (TTI)) dat = dat | IOT_SKP;\r
959 }\r
960if (pulse & 002) { /* KRS/KRB */\r
961 CLR_INT (TTI); /* clear flag */\r
962 dat = dat | tti_unit.buf & TTI_MASK; /* return buffer */\r
963#if defined (PDP15)\r
964 if (pulse & 020) tti_fdpx = 1; /* KRS? */\r
965 else tti_fdpx = 0; /* no, KRB */\r
966#endif\r
967 }\r
968if (pulse & 004) { /* IORS */\r
969 dat = dat | upd_iors ();\r
970 }\r
971return dat;\r
972}\r
973\r
974/* Unit service */\r
975\r
976t_stat tti_svc (UNIT *uptr)\r
977{\r
978#if defined (KSR28) /* Baudot... */\r
979int32 in, c, out;\r
980\r
981sim_activate (uptr, KBD_WAIT (uptr->wait, tmxr_poll)); /* continue poll */\r
982if (tti_2nd) { /* char waiting? */\r
983 uptr->buf = tti_2nd; /* return char */\r
984 tti_2nd = 0; /* not waiting */\r
985 }\r
986else {\r
987 if ((in = sim_poll_kbd ()) < SCPE_KFLAG) return in;\r
988 c = asc_to_baud[in & 0177]; /* translate char */\r
989 if (c == 0) return SCPE_OK; /* untranslatable? */\r
990 if ((c & TTI_BOTH) || /* case insensitive? */\r
991 (((c & TTI_FIGURES)? 1: 0) == tty_shift)) /* right case? */\r
992 uptr->buf = c & TTI_MASK;\r
993 else { /* send case change */\r
994 if (c & TTI_FIGURES) { /* to figures? */\r
995 uptr->buf = BAUDOT_FIGURES;\r
996 tty_shift = 1;\r
997 }\r
998 else { /* no, to letters */\r
999 uptr->buf = BAUDOT_LETTERS;\r
1000 tty_shift = 0;\r
1001 }\r
1002 tti_2nd = c & TTI_MASK; /* save actual char */\r
1003 }\r
1004 if ((uptr->flags & TTUF_HDX) && /* half duplex? */\r
1005 ((out = sim_tt_outcvt (in, TT_GET_MODE (uptr->flags) | TTUF_KSR)) >= 0)) {\r
1006 sim_putchar (out);\r
1007 tto_unit.pos = tto_unit.pos + 1;\r
1008 }\r
1009 }\r
1010\r
1011#else /* ASCII... */\r
1012int32 c, out;\r
1013\r
1014sim_activate (uptr, KBD_WAIT (uptr->wait, tmxr_poll)); /* continue poll */\r
1015if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */\r
1016out = c & 0177; /* mask echo to 7b */\r
1017if (c & SCPE_BREAK) c = 0; /* break? */\r
1018else c = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags) | TTUF_KSR);\r
1019if ((uptr->flags & TTUF_HDX) && !tti_fdpx && out && /* half duplex and */\r
1020 ((out = sim_tt_outcvt (out, TT_GET_MODE (uptr->flags) | TTUF_KSR)) >= 0)) {\r
1021 sim_putchar (out); /* echo */\r
1022 tto_unit.pos = tto_unit.pos + 1;\r
1023 }\r
1024uptr->buf = c; /* got char */\r
1025\r
1026#endif\r
1027uptr->pos = uptr->pos + 1;\r
1028SET_INT (TTI); /* set flag */\r
1029return SCPE_OK;\r
1030}\r
1031\r
1032/* IORS service */\r
1033\r
1034int32 tti_iors (void)\r
1035{\r
1036return (TST_INT (TTI)? IOS_TTI: 0);\r
1037}\r
1038\r
1039/* Reset routine */\r
1040\r
1041t_stat tti_reset (DEVICE *dptr)\r
1042{\r
1043tti_unit.buf = 0; /* clear buffer */\r
1044tti_2nd = 0;\r
1045tty_shift = 0; /* clear state */\r
1046tti_fdpx = 0; /* clear dpx mode */\r
1047CLR_INT (TTI); /* clear flag */\r
1048sim_activate_abs (&tti_unit, KBD_WAIT (tti_unit.wait, tmxr_poll));\r
1049return SCPE_OK;\r
1050}\r
1051\r
1052/* Terminal output: IOT routine */\r
1053\r
1054int32 tto (int32 dev, int32 pulse, int32 dat)\r
1055{\r
1056if (pulse & 001) { /* TSF */\r
1057 if (TST_INT (TTO)) dat = dat | IOT_SKP;\r
1058 }\r
1059if (pulse & 002) CLR_INT (TTO); /* clear flag */\r
1060if (pulse & 004) { /* load buffer */\r
1061 sim_activate (&tto_unit, tto_unit.wait); /* activate unit */\r
1062 tto_unit.buf = dat & TTO_MASK; /* load buffer */\r
1063 }\r
1064return dat;\r
1065}\r
1066\r
1067/* Unit service */\r
1068\r
1069t_stat tto_svc (UNIT *uptr)\r
1070{\r
1071int32 c;\r
1072t_stat r;\r
1073\r
1074#if defined (KSR28) /* Baudot... */\r
1075if (uptr->buf == BAUDOT_FIGURES) /* set figures? */\r
1076 tty_shift = 1;\r
1077else if (uptr->buf == BAUDOT_LETTERS) /* set letters? */\r
1078 tty_shift = 0;\r
1079else {\r
1080 c = baud_to_asc[uptr->buf | (tty_shift << 5)]; /* translate */\r
1081\r
1082#else\r
1083c = sim_tt_outcvt (uptr->buf, TT_GET_MODE (uptr->flags) | TTUF_KSR);\r
1084if (c >= 0) {\r
1085\r
1086#endif\r
1087\r
1088 if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */\r
1089 sim_activate (uptr, uptr->wait); /* retry? */\r
1090 return ((r == SCPE_STALL)? SCPE_OK: r);\r
1091 }\r
1092 }\r
1093SET_INT (TTO); /* set flag */\r
1094uptr->pos = uptr->pos + 1;\r
1095return SCPE_OK;\r
1096}\r
1097\r
1098/* IORS service */\r
1099\r
1100int32 tto_iors (void)\r
1101{\r
1102return (TST_INT (TTO)? IOS_TTO: 0);\r
1103}\r
1104\r
1105/* Reset routine */\r
1106\r
1107t_stat tto_reset (DEVICE *dptr)\r
1108{\r
1109tto_unit.buf = 0; /* clear buffer */\r
1110tty_shift = 0; /* clear state */\r
1111CLR_INT (TTO); /* clear flag */\r
1112sim_cancel (&tto_unit); /* deactivate unit */\r
1113return SCPE_OK;\r
1114}\r
1115\r
1116/* Set mode */\r
1117\r
1118t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc)\r
1119{\r
1120tti_unit.flags = (tti_unit.flags & ~TT_MODE) | val;\r
1121tto_unit.flags = (tto_unit.flags & ~TT_MODE) | val;\r
1122return SCPE_OK;\r
1123}\r