1 /* scp_tty.c: Operating system-dependent terminal I/O routines.
2
3 Copyright 1994-1997,
4 Robert M Supnik, Digital Equipment Corporation
5 Commercial use prohibited
6
7 25-Jan-97 RMS Added POSIX terminal I/O support
8 02-Jan-97 RMS Fixed bug in sim_poll_kbd
9
10 ttinit - called once to get initial terminal state
11 ttrunstate - called to put terminal into run state
12 ttcmdstate - called to return terminal to command state
13 ttclose - called once before the simulator exits
14 sim_poll_kbd - poll for keyboard input
15 sim_putchar - output character to terminal
16
17 Versions are included for generic (BSD) UNIX and for VMS.
18 The generic UNIX version works with LINUX.
19 */
20 /* #include <inttypes.h> XXX Solaris 2.6 needs this now?? grrr.... */
21
22 #include "sim_defs.h"
23 int32 sim_int_char = 005; /* interrupt character */
24
25 /* VMS routines */
26
27 #ifdef VMS
28 #define __TTYROUTINES 0
29 #include <descrip.h>
30 #include <ttdef.h>
31 #include <tt2def.h>
32 #include <iodef.h>
33 #include <ssdef.h>
34 #include <starlet.h>
35 #define EFN 0
36 unsigned int32 tty_chan = 0;
37 typedef struct {
38 unsigned short sense_count;
39 unsigned char sense_first_char;
40 unsigned char sense_reserved;
41 unsigned int32 stat;
42 unsigned int32 stat2; } SENSE_BUF;
43 typedef struct {
44 unsigned int16 status;
45 unsigned int16 count;
46 unsigned int32 dev_status; } IOSB;
47 SENSE_BUF cmd_mode = { 0 };
48 SENSE_BUF run_mode = { 0 };
49
ttinit(void)50 t_stat ttinit (void)
51 {
52 unsigned int32 status;
53 IOSB iosb;
54 $DESCRIPTOR (terminal_device, "tt");
55
56 status = sys$assign (&terminal_device, &tty_chan, 0, 0);
57 if (status != SS$_NORMAL) return SCPE_TTIERR;
58 status = sys$qiow (EFN, tty_chan, IO$_SENSEMODE, &iosb, 0, 0,
59 &cmd_mode, sizeof (cmd_mode), 0, 0, 0, 0);
60 if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTIERR;
61 run_mode = cmd_mode;
62 run_mode.stat = cmd_mode.stat | TT$M_NOECHO & ~(TT$M_HOSTSYNC | TT$M_TTSYNC);
63 run_mode.stat2 = cmd_mode.stat2 | TT2$M_PASTHRU;
64 return SCPE_OK;
65 }
66
ttrunstate(void)67 t_stat ttrunstate (void)
68 {
69 unsigned int status;
70 IOSB iosb;
71
72 status = sys$qiow (EFN, tty_chan, IO$_SETMODE, &iosb, 0, 0,
73 &run_mode, sizeof (run_mode), 0, 0, 0, 0);
74 if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTIERR;
75 return SCPE_OK;
76 }
77
ttcmdstate(void)78 t_stat ttcmdstate (void)
79 {
80 unsigned int status;
81 IOSB iosb;
82
83 status = sys$qiow (EFN, tty_chan, IO$_SETMODE, &iosb, 0, 0,
84 &cmd_mode, sizeof (cmd_mode), 0, 0, 0, 0);
85 if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTIERR;
86 return SCPE_OK;
87 }
88
ttclose(void)89 t_stat ttclose (void)
90 {
91 return ttcmdstate ();
92 }
93
sim_poll_kbd(void)94 t_stat sim_poll_kbd (void)
95 {
96 unsigned int status, term[2];
97 unsigned char buf[4];
98 IOSB iosb;
99 SENSE_BUF sense;
100
101 term[0] = 0; term[1] = 0;
102 status = sys$qiow (EFN, tty_chan, IO$_SENSEMODE | IO$M_TYPEAHDCNT, &iosb,
103 0, 0, &sense, 8, 0, term, 0, 0);
104 if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTIERR;
105 if (sense.sense_count == 0) return SCPE_OK;
106 term[0] = 0; term[1] = 0;
107 status = sys$qiow (EFN, tty_chan,
108 IO$_READLBLK | IO$M_NOECHO | IO$M_NOFILTR | IO$M_TIMED | IO$M_TRMNOECHO,
109 &iosb, 0, 0, buf, 1, 0, term, 0, 0);
110 if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_OK;
111 if (buf[0] == sim_int_char) return SCPE_STOP;
112 return (buf[0] | SCPE_KFLAG);
113 }
114
sim_putchar(int32 out)115 t_stat sim_putchar (int32 out)
116 {
117 unsigned int status;
118 char c;
119 IOSB iosb;
120
121 c = out;
122 status = sys$qiow (EFN, tty_chan, IO$_WRITELBLK | IO$M_NOFORMAT,
123 &iosb, 0, 0, &c, 1, 0, 0, 0, 0);
124 if ((status != SS$_NORMAL) || (iosb.status != SS$_NORMAL)) return SCPE_TTOERR;
125 return SCPE_OK;
126 }
127 #endif
128
129 /* Win32 routines */
130
131 #ifdef _WIN32
132 #define __TTYROUTINES 0
133 #include <conio.h>
134
ttinit(void)135 t_stat ttinit (void)
136 {
137 return SCPE_OK;
138 }
139
ttrunstate(void)140 t_stat ttrunstate (void)
141 {
142 return SCPE_OK;
143 }
144
ttcmdstate(void)145 t_stat ttcmdstate (void)
146 {
147 return SCPE_OK;
148 }
149
ttclose(void)150 t_stat ttclose (void)
151 {
152 return SCPE_OK;
153 }
154
sim_poll_kbd(void)155 t_stat sim_poll_kbd (void)
156 {
157 int c;
158
159 if (!kbhit ()) return SCPE_OK;
160 c = _getch ();
161 if ((c & 0177) == '\b') c = 0177;
162 if ((c & 0177) == sim_int_char) return SCPE_STOP;
163 return c | SCPE_KFLAG;
164 }
165
sim_putchar(int32 c)166 t_stat sim_putchar (int32 c)
167 {
168 _putch (c);
169 return SCPE_OK;
170 }
171
172 #endif
173
174 /* BSD UNIX routines */
175
176 #ifdef BSDTTY
177 #define __TTYROUTINES 0
178 #include <sgtty.h>
179 #include <fcntl.h>
180
181 struct sgttyb cmdtty,runtty; /* V6/V7 stty data */
182 struct tchars cmdtchars,runtchars; /* V7 editing */
183 struct ltchars cmdltchars,runltchars; /* 4.2 BSD editing */
184 int cmdfl,runfl; /* TTY flags */
185
ttinit(void)186 t_stat ttinit (void)
187 {
188 cmdfl = fcntl (0, F_GETFL, 0); /* get old flags and status */
189 runfl = cmdfl | FNDELAY;
190 if (ioctl (0, TIOCGETP, &cmdtty) < 0) return SCPE_TTIERR;
191 if (ioctl (0, TIOCGETC, &cmdtchars) < 0) return SCPE_TTIERR;
192 if (ioctl (0, TIOCGLTC, &cmdltchars) < 0) return SCPE_TTIERR;
193 runtty = cmdtty; /* initial run state */
194 runtty.sg_flags = cmdtty.sg_flags & ~(ECHO|CRMOD) | CBREAK;
195 runtchars.t_intrc = sim_int_char; /* interrupt */
196 runtchars.t_quitc = 0xFF; /* no quit */
197 runtchars.t_startc = 0xFF; /* no host sync */
198 runtchars.t_stopc = 0xFF;
199 runtchars.t_eofc = 0xFF;
200 runtchars.t_brkc = 0xFF;
201 runltchars.t_suspc = 0xFF; /* no specials of any kind */
202 runltchars.t_dsuspc = 0xFF;
203 runltchars.t_rprntc = 0xFF;
204 runltchars.t_flushc = 0xFF;
205 runltchars.t_werasc = 0xFF;
206 runltchars.t_lnextc = 0xFF;
207 return SCPE_OK; /* return success */
208 }
209
ttrunstate(void)210 t_stat ttrunstate (void)
211 {
212 runtchars.t_intrc = sim_int_char; /* in case changed */
213 fcntl (0, F_SETFL, runfl); /* non-block mode */
214 if (ioctl (0, TIOCSETP, &runtty) < 0) return SCPE_TTIERR;
215 if (ioctl (0, TIOCSETC, &runtchars) < 0) return SCPE_TTIERR;
216 if (ioctl (0, TIOCSLTC, &runltchars) < 0) return SCPE_TTIERR;
217 return SCPE_OK;
218 }
219
ttcmdstate(void)220 t_stat ttcmdstate (void)
221 {
222 fcntl (0, F_SETFL, cmdfl); /* block mode */
223 if (ioctl (0, TIOCSETP, &cmdtty) < 0) return SCPE_TTIERR;
224 if (ioctl (0, TIOCSETC, &cmdtchars) < 0) return SCPE_TTIERR;
225 if (ioctl (0, TIOCSLTC, &cmdltchars) < 0) return SCPE_TTIERR;
226 return SCPE_OK;
227 }
228
ttclose(void)229 t_stat ttclose (void)
230 {
231 return ttcmdstate ();
232 }
233
sim_poll_kbd(void)234 t_stat sim_poll_kbd (void)
235 {
236 int status;
237 unsigned char buf[1];
238
239 status = read (0, buf, 1);
240 if (status != 1) return SCPE_OK;
241 else return (buf[0] | SCPE_KFLAG);
242 }
243
sim_putchar(int32 out)244 t_stat sim_putchar (int32 out)
245 {
246 char c;
247
248 c = out;
249 write (1, &c, 1);
250 return SCPE_OK;
251 }
252 #endif
253
254 /* POSIX UNIX routines */
255
256 #ifndef __TTYROUTINES
257 #include <unistd.h>
258 #include <termios.h>
259
260 struct termios cmdtty, runtty;
261
ttinit(void)262 t_stat ttinit (void)
263 {
264 if (tcgetattr (0, &cmdtty) < 0) return SCPE_TTIERR; /* get old flags */
265 runtty = cmdtty;
266 runtty.c_lflag = runtty.c_lflag & ~(ECHO | ICANON); /* no echo or edit */
267 runtty.c_oflag = runtty.c_oflag & ~OPOST; /* no output edit */
268 runtty.c_iflag = runtty.c_iflag & ~ICRNL; /* no cr conversion */
269 runtty.c_cc[VINTR] = sim_int_char; /* interrupt */
270 runtty.c_cc[VQUIT] = 0; /* no quit */
271 runtty.c_cc[VERASE] = 0;
272 runtty.c_cc[VKILL] = 0;
273 runtty.c_cc[VEOF] = 0;
274 runtty.c_cc[VEOL] = 0;
275 runtty.c_cc[VSTART] = 0; /* no host sync */
276 runtty.c_cc[VSUSP] = 0;
277 runtty.c_cc[VSTOP] = 0;
278 /* XXX Check if these don't have another name on HP-UX */
279 #ifdef VREPRINT
280 runtty.c_cc[VREPRINT] = 0; /* no specials */
281 #endif
282 #ifdef VDISCARD
283 runtty.c_cc[VDISCARD] = 0;
284 #endif
285 #ifdef VWERASE
286 runtty.c_cc[VWERASE] = 0;
287 #endif
288 #ifdef VLNEXT
289 runtty.c_cc[VLNEXT] = 0;
290 #endif
291 runtty.c_cc[VMIN] = 0; /* no waiting */
292 runtty.c_cc[VTIME] = 0;
293 return SCPE_OK;
294 }
295
ttrunstate(void)296 t_stat ttrunstate (void)
297 {
298 runtty.c_cc[VINTR] = sim_int_char; /* in case changed */
299 if (tcsetattr (0, TCSAFLUSH, &runtty) < 0) return SCPE_TTIERR;
300 return SCPE_OK;
301 }
302
ttcmdstate(void)303 t_stat ttcmdstate (void)
304 {
305 if (tcsetattr (0, TCSAFLUSH, &cmdtty) < 0) return SCPE_TTIERR;
306 return SCPE_OK;
307 }
308
ttclose(void)309 t_stat ttclose (void)
310 {
311 return ttcmdstate ();
312 }
313
sim_poll_kbd(void)314 t_stat sim_poll_kbd (void)
315 {
316 int status;
317 unsigned char buf[1];
318
319 status = read (0, buf, 1);
320 if (status != 1) return SCPE_OK;
321 else return (buf[0] | SCPE_KFLAG);
322 }
323
sim_putchar(int32 out)324 t_stat sim_putchar (int32 out)
325 {
326 char c;
327
328 c = out;
329 write (1, &c, 1);
330 return SCPE_OK;
331 }
332 #endif
333
334