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