1 /* pdp1_stddev.c: PDP-1 standard devices
3 Copyright (c) 1993-2006, Robert M. Supnik
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:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
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.
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.
31 21-Dec-06 RMS Added 16-channel sequence break support
32 29-Oct-03 RMS Added PTR FIODEC-to-ASCII translation (from Phil Budne)
33 07-Sep-03 RMS Changed ioc to ios
34 30-Aug-03 RMS Revised PTR to conform to Maintenance Manual;
35 added deadlock prevention on errors
36 23-Jul-03 RMS Revised to detect I/O wait hang
37 25-Apr-03 RMS Revised for extended file support
38 22-Dec-02 RMS Added break support
39 29-Nov-02 RMS Fixed output flag initialization (found by Derek Peschel)
40 21-Nov-02 RMS Changed typewriter to half duplex (found by Derek Peschel)
41 06-Oct-02 RMS Revised for V2.10
42 30-May-02 RMS Widened POS to 32b
43 29-Nov-01 RMS Added read only unit support
44 07-Sep-01 RMS Moved function prototypes
45 10-Jun-01 RMS Fixed comment
46 30-Oct-00 RMS Standardized device naming
48 Note: PTP timeout must be >10X faster that TTY output timeout for Macro
52 #include "pdp1_defs.h"
54 #define FIODEC_STOP 013 /* stop code */
57 #define UC_V 6 /* upper case */
58 #define UC (1 << UC_V)
59 #define BOTH (1 << (UC_V + 1)) /* both cases */
60 #define CW (1 << (UC_V + 2)) /* char waiting */
62 #define UNIT_V_ASCII (UNIT_V_UF + 0) /* ASCII/binary mode */
63 #define UNIT_ASCII (1 << UNIT_V_ASCII)
64 #define PTR_LEADER 20 /* ASCII leader chars */
68 int32 ptr_stopioe
= 0;
69 int32 ptr_uc
= 0; /* upper/lower case */
70 int32 ptr_hold
= 0; /* holding buffer */
71 int32 ptr_leader
= PTR_LEADER
; /* leader count */
72 int32 ptr_sbs
= 0; /* SBS level */
73 int32 ptp_stopioe
= 0;
74 int32 ptp_sbs
= 0; /* SBS level */
75 int32 tti_hold
= 0; /* tti hold buf */
76 int32 tti_sbs
= 0; /* SBS level */
77 int32 tty_buf
= 0; /* tty buffer */
78 int32 tty_uc
= 0; /* tty uc/lc */
81 extern int32 ios
, ioh
, cpls
, iosta
;
82 extern int32 PF
, IO
, PC
, TA
;
85 int ptr_get_ascii (UNIT
*uptr
);
86 t_stat
ptr_svc (UNIT
*uptr
);
87 t_stat
ptp_svc (UNIT
*uptr
);
88 t_stat
tti_svc (UNIT
*uptr
);
89 t_stat
tto_svc (UNIT
*uptr
);
90 t_stat
ptr_reset (DEVICE
*dptr
);
91 t_stat
ptp_reset (DEVICE
*dptr
);
92 t_stat
tty_reset (DEVICE
*dptr
);
93 t_stat
ptr_boot (int32 unitno
, DEVICE
*dptr
);
94 t_stat
ptr_attach (UNIT
*uptr
, char *cptr
);
96 /* Character translation tables */
98 int32 fiodec_to_ascii
[128] = {
99 ' ', '1', '2', '3', '4', '5', '6', '7', /* lower case */
100 '8', '9', 0, 0, 0, 0, 0, 0,
101 '0', '/', 's', 't', 'u', 'v', 'w', 'x',
102 'y', 'z', 0, ',', 0, 0, '\t', 0,
103 '@', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
104 'q', 'r', 0, 0, '-', ')', '\\', '(',
105 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
106 'h', 'i', '{', '.', '}', '\b', 0, '\r',
107 ' ', '"', '\'', '~', '#', '!', '&', '<', /* upper case */
108 '>', '^', 0, 0, 0, 0, 0, 0,
109 '`', '?', 'S', 'T', 'U', 'V', 'W', 'X',
110 'Y', 'Z', 0, '=', 0, 0, '\t', 0,
111 '_', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
112 'Q', 'R', 0, 0, '+', ']', '|', '[',
113 0, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
114 'H', 'I', '{', '*', '}', '\b', 0, '\r'
117 int32 ascii_to_fiodec
[128] = {
118 0, 0, 0, 0, 0, 0, 0, 0,
119 BOTH
+075, BOTH
+036, 0, 0, 0, BOTH
+077, 0, 0,
120 0, 0, 0, 0, 0, 0, 0, 0,
121 0, 0, 0, 0, 0, 0, 0, 0,
122 BOTH
+0, UC
+005, UC
+001, UC
+004, 0, 0, UC
+006, UC
+002,
123 057, 055, UC
+073, UC
+054, 033, 054, 073, 021,
124 020, 001, 002, 003, 004, 005, 006, 007,
125 010, 011, 0, 0, UC
+007, UC
+033, UC
+010, UC
+021,
126 040, UC
+061, UC
+062, UC
+063, UC
+064, UC
+065, UC
+066, UC
+067,
127 UC
+070, UC
+071, UC
+041, UC
+042, UC
+043, UC
+044, UC
+045, UC
+046,
128 UC
+047, UC
+050, UC
+051, UC
+022, UC
+023, UC
+024, UC
+025, UC
+026,
129 UC
+027, UC
+030, UC
+031, UC
+057, 056, UC
+055, UC
+011, UC
+040,
130 UC
+020, 061, 062, 063, 064, 065, 066, 067,
131 070, 071, 041, 042, 043, 044, 045, 046,
132 047, 050, 051, 022, 023, 024, 025, 026,
133 027, 030, 031, 0, UC
+056, 0, UC
+003, BOTH
+075
136 /* PTR data structures
138 ptr_dev PTR device descriptor
140 ptr_reg PTR register list
144 UDATA (&ptr_svc
, UNIT_SEQ
+UNIT_ATTABLE
+UNIT_ROABLE
, 0),
149 { ORDATA (BUF
, ptr_unit
.buf
, 18) },
150 { FLDATA (UC
, ptr_uc
, UC_V
) },
151 { FLDATA (DONE
, iosta
, IOS_V_PTR
) },
152 { FLDATA (RPLS
, cpls
, CPLS_V_PTR
) },
153 { ORDATA (HOLD
, ptr_hold
, 9), REG_HRO
},
154 { ORDATA (STATE
, ptr_state
, 5), REG_HRO
},
155 { FLDATA (WAIT
, ptr_wait
, 0), REG_HRO
},
156 { DRDATA (POS
, ptr_unit
.pos
, T_ADDR_W
), PV_LEFT
},
157 { DRDATA (TIME
, ptr_unit
.wait
, 24), PV_LEFT
},
158 { DRDATA (LEADER
, ptr_leader
, 6), REG_HRO
},
159 { FLDATA (STOP_IOE
, ptr_stopioe
, 0) },
160 { DRDATA (SBSLVL
, ptr_sbs
, 4), REG_HRO
},
165 { MTAB_XTD
|MTAB_VDV
, 0, "SBSLVL", "SBSLVL",
166 &dev_set_sbs
, &dev_show_sbs
, (void *) &ptr_sbs
},
167 { UNIT_ASCII
, UNIT_ASCII
, "ASCII", "ASCII", NULL
},
168 { UNIT_ASCII
, 0, "FIODEC", "FIODEC", NULL
},
173 "PTR", &ptr_unit
, ptr_reg
, ptr_mod
,
175 NULL
, NULL
, &ptr_reset
,
176 &ptr_boot
, &ptr_attach
, NULL
,
180 /* PTP data structures
182 ptp_dev PTP device descriptor
184 ptp_reg PTP register list
188 UDATA (&ptp_svc
, UNIT_SEQ
+UNIT_ATTABLE
, 0), SERIAL_OUT_WAIT
192 { ORDATA (BUF
, ptp_unit
.buf
, 8) },
193 { FLDATA (DONE
, iosta
, IOS_V_PTP
) },
194 { FLDATA (RPLS
, cpls
, CPLS_V_PTP
) },
195 { DRDATA (POS
, ptp_unit
.pos
, T_ADDR_W
), PV_LEFT
},
196 { DRDATA (TIME
, ptp_unit
.wait
, 24), PV_LEFT
},
197 { FLDATA (STOP_IOE
, ptp_stopioe
, 0) },
198 { DRDATA (SBSLVL
, ptp_sbs
, 4), REG_HRO
},
203 { MTAB_XTD
|MTAB_VDV
, 0, "SBSLVL", "SBSLVL",
204 &dev_set_sbs
, &dev_show_sbs
, (void *) &ptp_sbs
},
209 "PTP", &ptp_unit
, ptp_reg
, ptp_mod
,
211 NULL
, NULL
, &ptp_reset
,
216 /* TTI data structures
218 tti_dev TTI device descriptor
220 tti_reg TTI register list
223 UNIT tti_unit
= { UDATA (&tti_svc
, 0, 0), KBD_POLL_WAIT
};
226 { ORDATA (BUF
, tty_buf
, 6) },
227 { FLDATA (UC
, tty_uc
, UC_V
) },
228 { ORDATA (HOLD
, tti_hold
, 9), REG_HRO
},
229 { FLDATA (DONE
, iosta
, IOS_V_TTI
) },
230 { DRDATA (POS
, tti_unit
.pos
, T_ADDR_W
), PV_LEFT
},
231 { DRDATA (TIME
, tti_unit
.wait
, 24), REG_NZ
+ PV_LEFT
},
232 { DRDATA (SBSLVL
, tti_sbs
, 4), REG_HRO
},
237 { MTAB_XTD
|MTAB_VDV
, 0, "SBSLVL", "SBSLVL",
238 &dev_set_sbs
, &dev_show_sbs
, (void *) &tti_sbs
},
243 "TTI", &tti_unit
, tti_reg
, tti_mod
,
245 NULL
, NULL
, &tty_reset
,
250 /* TTO data structures
252 tto_dev TTO device descriptor
254 tto_reg TTO register list
257 UNIT tto_unit
= { UDATA (&tto_svc
, 0, 0), SERIAL_OUT_WAIT
* 10 };
260 { ORDATA (BUF
, tty_buf
, 6) },
261 { FLDATA (UC
, tty_uc
, UC_V
) },
262 { FLDATA (RPLS
, cpls
, CPLS_V_TTO
) },
263 { FLDATA (DONE
, iosta
, IOS_V_TTO
) },
264 { DRDATA (POS
, tto_unit
.pos
, T_ADDR_W
), PV_LEFT
},
265 { DRDATA (TIME
, tto_unit
.wait
, 24), PV_LEFT
},
266 { DRDATA (SBSLVL
, tto_sbs
, 4), REG_HRO
},
271 { MTAB_XTD
|MTAB_VDV
, 0, "SBSLVL", "SBSLVL",
272 &dev_set_sbs
, &dev_show_sbs
, (void *) &tto_sbs
},
277 "TTO", &tto_unit
, tto_reg
, tto_mod
,
279 NULL
, NULL
, &tty_reset
,
284 /* Paper tape reader: IOT routine. Points to note:
286 - RPA (but not RPB) complements the reader clutch control. Thus,
287 if the reader is running, RPA will stop it.
288 - The status bit indicates data in the reader buffer that has not
289 been transfered to IO. It is cleared by any RB->IO operation,
290 including RRB and the completion pulse.
291 - A reader error on a wait mode operation could hang the simulator.
292 IOH is set; any retry (without RESET) will be NOP'd. Accordingly,
293 the PTR service routine clears IOH on any error during a rpa/rpb i.
296 int32
ptr (int32 inst
, int32 dev
, int32 dat
)
298 if (dev
== 0030) { /* RRB */
299 iosta
= iosta
& ~IOS_PTR
; /* clear status */
300 return ptr_unit
.buf
; /* return data */
302 if (dev
== 0002) ptr_state
= 18; /* RPB, mode = binary */
303 else if (sim_is_active (&ptr_unit
)) { /* RPA, running? */
304 sim_cancel (&ptr_unit
); /* stop reader */
307 else ptr_state
= 0; /* mode = alpha */
308 ptr_unit
.buf
= 0; /* clear buffer */
309 if (inst
& IO_WAIT
) ptr_wait
= 1; /* set ptr wait */
310 else ptr_wait
= 0; /* from IR<5> */
311 if (GEN_CPLS (inst
)) { /* comp pulse? */
313 cpls
= cpls
| CPLS_PTR
;
315 else cpls
= cpls
& ~CPLS_PTR
;
316 sim_activate (&ptr_unit
, ptr_unit
.wait
); /* start reader */
322 t_stat
ptr_svc (UNIT
*uptr
)
326 if ((uptr
->flags
& UNIT_ATT
) == 0) { /* attached? */
327 if (ptr_wait
) ptr_wait
= ioh
= 0; /* if wait, clr ioh */
328 if ((cpls
& CPLS_PTR
) || ptr_stopioe
) return SCPE_UNATT
;
331 if ((uptr
->flags
& UNIT_ASCII
) && (ptr_state
== 0)) /* ASCII mode, alpha read? */
332 temp
= ptr_get_ascii (uptr
); /* get processed char */
333 else if ((temp
= getc (uptr
->fileref
)) != EOF
) /* no, get raw char */
334 uptr
->pos
= uptr
->pos
+ 1; /* if not eof, count */
335 if (temp
== EOF
) { /* end of file? */
336 if (ptr_wait
) ptr_wait
= ioh
= 0; /* if wait, clr ioh */
337 if (feof (uptr
->fileref
)) {
338 if ((cpls
& CPLS_PTR
) || ptr_stopioe
) printf ("PTR end of file\n");
341 else perror ("PTR I/O error");
342 clearerr (uptr
->fileref
);
345 if (ptr_state
== 0) uptr
->buf
= temp
& 0377; /* alpha */
346 else if (temp
& 0200) { /* binary */
347 ptr_state
= ptr_state
- 6;
348 uptr
->buf
= uptr
->buf
| ((temp
& 077) << ptr_state
);
350 if (ptr_state
== 0) { /* done? */
351 if (cpls
& CPLS_PTR
) { /* completion pulse? */
352 iosta
= iosta
& ~IOS_PTR
; /* clear flag */
353 IO
= uptr
->buf
; /* fill IO */
354 ios
= 1; /* restart */
355 cpls
= cpls
& ~CPLS_PTR
;
357 else { /* no, interrupt */
358 iosta
= iosta
| IOS_PTR
; /* set flag */
359 dev_req_int (ptr_sbs
); /* req interrupt */
362 else sim_activate (uptr
, uptr
->wait
); /* get next char */
366 /* Read next ASCII character */
368 int ptr_get_ascii (UNIT
*uptr
)
373 if (ptr_leader
> 0) { /* leader? */
374 ptr_leader
= ptr_leader
- 1; /* count down */
377 if (ptr_hold
& CW
) { /* char waiting? */
378 in
= ptr_hold
& TT_WIDTH
; /* return char */
379 ptr_hold
= 0; /* not waiting */
382 for (;;) { /* until valid char */
383 if ((c
= getc (uptr
->fileref
)) == EOF
) /* get next char, EOF? */
384 return FIODEC_STOP
; /* return STOP */
385 uptr
->pos
= uptr
->pos
+ 1; /* count char */
386 c
= c
& 0177; /* cut to 7b */
387 if (c
== '\n') c
= '\r'; /* NL -> CR */
388 else if (c
== '\r') continue; /* ignore CR */
389 in
= ascii_to_fiodec
[c
]; /* convert char */
390 if ((in
== 0) && (c
!= ' ')) continue; /* ignore unknowns */
391 if ((in
& BOTH
) || ((in
& UC
) == ptr_uc
)) /* case match? */
392 in
= in
& TT_WIDTH
; /* cut to 6b */
393 else { /* no, case shift */
394 ptr_hold
= in
| CW
; /* set char waiting */
395 ptr_uc
= in
& UC
; /* set case */
396 in
= ptr_uc
? FIODEC_UC
: FIODEC_LC
; /* return case */
401 in
= in
* 010040201; /* even parity from */
402 in
= in
| 027555555400; /* HACKMEM 167 */
409 t_stat
ptr_reset (DEVICE
*dptr
)
411 ptr_state
= 0; /* clear state */
416 cpls
= cpls
& ~CPLS_PTR
;
417 iosta
= iosta
& ~IOS_PTR
; /* clear flag */
418 sim_cancel (&ptr_unit
); /* deactivate unit */
424 t_stat
ptr_attach (UNIT
*uptr
, char *cptr
)
426 ptr_leader
= PTR_LEADER
; /* set up leader */
427 return attach_unit (uptr
, cptr
);
430 /* Bootstrap routine */
432 int32
ptr_getw (UNIT
*uptr
)
436 for (i
= word
= 0; i
< 3;) {
437 if ((tmp
= getc (uptr
->fileref
)) == EOF
) return -1;
438 uptr
->pos
= uptr
->pos
+ 1;
440 word
= (word
<< 6) | (tmp
& 077);
447 t_stat
ptr_boot (int32 unitno
, DEVICE
*dptr
)
450 int32 fld
= TA
& EPCMASK
;
453 if ((val
= ptr_getw (&ptr_unit
)) < 0) return SCPE_FMT
;
454 if (((val
& 0760000) == OP_DIO
) || /* DIO? */
455 ((val
& 0760000) == OP_DAC
)) { /* hack - Macro1 err */
456 origin
= val
& DAMASK
;
457 if ((val
= ptr_getw (&ptr_unit
)) < 0) return SCPE_FMT
;
458 M
[fld
| origin
] = val
;
460 else if ((val
& 0760000) == OP_JMP
) { /* JMP? */
461 PC
= fld
| (val
& DAMASK
);
464 else return SCPE_FMT
; /* bad instr */
466 return SCPE_OK
; /* done */
469 /* Paper tape punch: IOT routine */
471 int32
ptp (int32 inst
, int32 dev
, int32 dat
)
473 iosta
= iosta
& ~IOS_PTP
; /* clear flag */
474 ptp_unit
.buf
= (dev
== 0006)? ((dat
>> 12) | 0200): (dat
& 0377);
475 if (GEN_CPLS (inst
)) { /* comp pulse? */
477 cpls
= cpls
| CPLS_PTP
;
479 else cpls
= cpls
& ~CPLS_PTP
;
480 sim_activate (&ptp_unit
, ptp_unit
.wait
); /* start unit */
486 t_stat
ptp_svc (UNIT
*uptr
)
488 if (cpls
& CPLS_PTP
) { /* completion pulse? */
489 ios
= 1; /* restart */
490 cpls
= cpls
& ~CPLS_PTP
;
492 iosta
= iosta
| IOS_PTP
; /* set flag */
493 dev_req_int (ptp_sbs
); /* req interrupt */
494 if ((uptr
->flags
& UNIT_ATT
) == 0) /* not attached? */
495 return IORETURN (ptp_stopioe
, SCPE_UNATT
);
496 if (putc (uptr
->buf
, uptr
->fileref
) == EOF
) { /* I/O error? */
497 perror ("PTP I/O error");
498 clearerr (uptr
->fileref
);
501 uptr
->pos
= uptr
->pos
+ 1;
507 t_stat
ptp_reset (DEVICE
*dptr
)
509 ptp_unit
.buf
= 0; /* clear state */
510 cpls
= cpls
& ~CPLS_PTP
;
511 iosta
= iosta
& ~IOS_PTP
; /* clear flag */
512 sim_cancel (&ptp_unit
); /* deactivate unit */
516 /* Typewriter IOT routines */
518 int32
tti (int32 inst
, int32 dev
, int32 dat
)
520 iosta
= iosta
& ~IOS_TTI
; /* clear flag */
521 if (inst
& (IO_WAIT
| IO_CPLS
)) /* wait or sync? */
522 return (STOP_RSRV
<< IOT_V_REASON
) | (tty_buf
& 077);
523 return tty_buf
& 077;
526 int32
tto (int32 inst
, int32 dev
, int32 dat
)
528 iosta
= iosta
& ~IOS_TTO
; /* clear flag */
529 tty_buf
= dat
& TT_WIDTH
; /* load buffer */
530 if (GEN_CPLS (inst
)) { /* comp pulse? */
532 cpls
= cpls
| CPLS_TTO
;
534 else cpls
= cpls
& ~CPLS_TTO
;
535 sim_activate (&tto_unit
, tto_unit
.wait
); /* activate unit */
539 /* Unit service routines */
541 t_stat
tti_svc (UNIT
*uptr
)
545 sim_activate (uptr
, uptr
->wait
); /* continue poll */
546 if (tti_hold
& CW
) { /* char waiting? */
547 tty_buf
= tti_hold
& TT_WIDTH
; /* return char */
548 tti_hold
= 0; /* not waiting */
551 if ((temp
= sim_poll_kbd ()) < SCPE_KFLAG
) return temp
;
552 if (temp
& SCPE_BREAK
) return SCPE_OK
; /* ignore break */
554 if (temp
== 0177) temp
= '\b'; /* rubout? bs */
555 sim_putchar (temp
); /* echo */
556 if (temp
== '\r') sim_putchar ('\n'); /* cr? add nl */
557 in
= ascii_to_fiodec
[temp
]; /* translate char */
558 if (in
== 0) return SCPE_OK
; /* no xlation? */
559 if ((in
& BOTH
) || ((in
& UC
) == (tty_uc
& UC
)))
560 tty_buf
= in
& TT_WIDTH
;
561 else { /* must shift */
562 tty_uc
= in
& UC
; /* new case */
563 tty_buf
= tty_uc
? FIODEC_UC
: FIODEC_LC
;
564 tti_hold
= in
| CW
; /* set 2nd waiting */
567 iosta
= iosta
| IOS_TTI
; /* set flag */
568 dev_req_int (tti_sbs
); /* req interrupt */
569 PF
= PF
| PF_SS_1
; /* set prog flag 1 */
570 uptr
->pos
= uptr
->pos
+ 1;
574 t_stat
tto_svc (UNIT
*uptr
)
579 if (tty_buf
== FIODEC_UC
) tty_uc
= UC
; /* upper case? */
580 else if (tty_buf
== FIODEC_LC
) tty_uc
= 0; /* lower case? */
582 c
= fiodec_to_ascii
[tty_buf
| tty_uc
]; /* translate */
583 if (c
&& ((r
= sim_putchar_s (c
)) != SCPE_OK
)) { /* output; error? */
584 sim_activate (uptr
, uptr
->wait
); /* retry */
585 return ((r
== SCPE_STALL
)? SCPE_OK
: r
);
588 if (cpls
& CPLS_TTO
) { /* completion pulse? */
589 ios
= 1; /* restart */
590 cpls
= cpls
& ~CPLS_TTO
;
592 iosta
= iosta
| IOS_TTO
; /* set flag */
593 dev_req_int (tto_sbs
); /* req interrupt */
594 uptr
->pos
= uptr
->pos
+ 1;
595 if (c
== '\r') { /* cr? add lf */
597 uptr
->pos
= uptr
->pos
+ 1;
604 t_stat
tty_reset (DEVICE
*dptr
)
606 tty_buf
= 0; /* clear buffer */
607 tty_uc
= 0; /* clear case */
608 tti_hold
= 0; /* clear hold buf */
609 cpls
= cpls
& ~CPLS_TTO
;
610 iosta
= (iosta
& ~IOS_TTI
) | IOS_TTO
; /* clear flag */
611 sim_activate (&tti_unit
, tti_unit
.wait
); /* activate keyboard */
612 sim_cancel (&tto_unit
); /* stop printer */