xref: /csrg-svn/sys/kern/tty_compat.c (revision 38594)
1 /*
2  * Copyright (c) 1982, 1986 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  *
6  *	@(#)tty_compat.c	1.4 (Berkeley) 08/13/89
7  */
8 
9 /*
10  * mapping routines for old line discipline (yuck)
11  */
12 #ifdef COMPAT_43
13 
14 #include "param.h"
15 #include "systm.h"
16 #include "user.h"
17 #include "ioctl.h"
18 #include "tty.h"
19 #include "termios.h"
20 #include "proc.h"
21 #include "file.h"
22 #include "conf.h"
23 #include "dkstat.h"
24 #include "uio.h"
25 #include "kernel.h"
26 #include "syslog.h"
27 
28 #include "machine/reg.h"
29 
30 int ttydebug = 0;
31 
32 /* XXX - fold these two tables into one */
33 static struct speedtab compatspeeds[] = {
34 	38400,	15,
35 	19200,	14,
36 	9600,	13,
37 	4800,	12,
38 	2400,	11,
39 	1800,	10,
40 	1200,	9,
41 	600,	8,
42 	300,	7,
43 	200,	6,
44 	150,	5,
45 	134,	4,
46 	110,	3,
47 	75,	2,
48 	50,	1,
49 	0,	0,
50 	-1,	-1,
51 };
52 static int compatspcodes[16] = {
53 	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
54 	1800, 2400, 4800, 9600, 19200, 38400,
55 };
56 
57 /*ARGSUSED*/
58 ttcompat(tp, com, data, flag)
59 	register struct tty *tp;
60 	caddr_t data;
61 {
62 	switch(com) {
63 	case TIOCGETP: {
64 		register struct sgttyb *sg = (struct sgttyb *)data;
65 		register u_char *cc = tp->t_cc;
66 		register speed;
67 
68 		speed = ttspeedtab(tp->t_ospeed, compatspeeds);
69 		sg->sg_ospeed = (speed == -1) ? 15 : speed;
70 		if (tp->t_ispeed == 0)
71 			sg->sg_ispeed = sg->sg_ospeed;
72 		else {
73 			speed = ttspeedtab(tp->t_ispeed, compatspeeds);
74 			sg->sg_ispeed = (speed == -1) ? 15 : speed;
75 		}
76 		sg->sg_erase = cc[VERASE];
77 		sg->sg_kill = cc[VKILL];
78 		sg->sg_flags = ttcompatgetflags(tp);
79 		break;
80 	}
81 
82 	case TIOCSETP:
83 	case TIOCSETN: {
84 		register struct sgttyb *sg = (struct sgttyb *)data;
85 		struct termios term;
86 		int speed;
87 
88 		term = tp->t_termios;
89 		if ((speed = sg->sg_ispeed) > 15 || speed < 0)
90 			term.c_ispeed = speed;
91 		else
92 			term.c_ispeed = compatspcodes[speed];
93 		if ((speed = sg->sg_ospeed) > 15 || speed < 0)
94 			term.c_ospeed = speed;
95 		else
96 			term.c_ospeed = compatspcodes[speed];
97 		term.c_cc[VERASE] = sg->sg_erase;
98 		term.c_cc[VKILL] = sg->sg_kill;
99 		if (sg->sg_erase == -1)
100 			term.c_cc[VERASE2] = _POSIX_VDISABLE;
101 		tp->t_flags = (tp->t_flags&0xffff0000) | sg->sg_flags;
102 		ttcompatsetflags(tp, &term);
103 		return (ttioctl(tp, com == TIOCSETP ? TIOCSETAF : TIOCSETA,
104 			&term, flag));
105 	}
106 
107 	case TIOCGETC: {
108 		struct tchars *tc = (struct tchars *)data;
109 		register u_char *cc = tp->t_cc;
110 
111 		tc->t_intrc = cc[VINTR];
112 		tc->t_quitc = cc[VQUIT];
113 		tc->t_startc = cc[VSTART];
114 		tc->t_stopc = cc[VSTOP];
115 		tc->t_eofc = cc[VEOF];
116 		tc->t_brkc = cc[VEOL];
117 		break;
118 	}
119 	case TIOCSETC: {
120 		struct tchars *tc = (struct tchars *)data;
121 		register u_char *cc = tp->t_cc;
122 
123 		cc[VINTR] = tc->t_intrc;
124 		cc[VQUIT] = tc->t_quitc;
125 		cc[VSTART] = tc->t_startc;
126 		cc[VSTOP] = tc->t_stopc;
127 		cc[VEOF] = tc->t_eofc;
128 		cc[VEOL] = tc->t_brkc;
129 		if (tc->t_brkc == -1)
130 			cc[VEOL2] = _POSIX_VDISABLE;
131 		break;
132 	}
133 	case TIOCSLTC: {
134 		struct ltchars *ltc = (struct ltchars *)data;
135 		register u_char *cc = tp->t_cc;
136 
137 		cc[VSUSP] = ltc->t_suspc;
138 		cc[VDSUSP] = ltc->t_dsuspc;
139 		cc[VREPRINT] = ltc->t_rprntc;
140 		cc[VFLUSHO] = ltc->t_flushc;
141 		cc[VWERASE] = ltc->t_werasc;
142 		cc[VLNEXT] = ltc->t_lnextc;
143 		break;
144 	}
145 	case TIOCGLTC: {
146 		struct ltchars *ltc = (struct ltchars *)data;
147 		register u_char *cc = tp->t_cc;
148 
149 		ltc->t_suspc = cc[VSUSP];
150 		ltc->t_dsuspc = cc[VDSUSP];
151 		ltc->t_rprntc = cc[VREPRINT];
152 		ltc->t_flushc = cc[VFLUSHO];
153 		ltc->t_werasc = cc[VWERASE];
154 		ltc->t_lnextc = cc[VLNEXT];
155 		break;
156 	}
157 	case TIOCLBIS:
158 	case TIOCLBIC:
159 	case TIOCLSET: {
160 		struct termios term;
161 
162 		term = tp->t_termios;
163 		if (com == TIOCLSET)
164 			tp->t_flags = (tp->t_flags&0xffff) | *(int *)data<<16;
165 		else {
166 			tp->t_flags =
167 			 (ttcompatgetflags(tp)&0xffff0000)|(tp->t_flags&0xffff);
168 			if (com == TIOCLBIS)
169 				tp->t_flags |= *(int *)data<<16;
170 			else
171 				tp->t_flags &= ~(*(int *)data<<16);
172 		}
173 		ttcompatsetlflags(tp, &term);
174 		return (ttioctl(tp, TIOCSETA, &term, flag));
175 	}
176 	case TIOCLGET:
177 		*(int *)data = ttcompatgetflags(tp)>>16;
178 		if (ttydebug)
179 			printf("CLGET: returning %x\n", *(int *)data);
180 		break;
181 
182 	case TIOCGETDCOMPAT:
183 		*(int *)data = tp->t_line ? tp->t_line : 2;
184 		break;
185 
186 	case TIOCSETDCOMPAT: {
187 		int ldisczero = 0;
188 
189 		return(ttioctl(tp, TIOCSETD,
190 			*(int *)data == 2 ? (caddr_t)&ldisczero : data, flag));
191 	}
192 
193 	default:
194 		return (-1);
195 	}
196 	return(0);
197 }
198 
199 ttcompatgetflags(tp)
200 	register struct tty *tp;
201 {
202 	register long iflag = tp->t_iflag;
203 	register long lflag = tp->t_lflag;
204 	register long oflag = tp->t_oflag;
205 	register long cflag = tp->t_cflag;
206 	register flags = 0;
207 
208 	if (iflag&IXOFF)
209 		flags |= TANDEM;
210 	if (iflag&ICRNL || oflag&ONLCR)
211 		flags |= CRMOD;
212 	if (cflag&PARENB) {
213 		if (iflag&INPCK) {
214 			if (cflag&PARODD)
215 				flags |= ODDP;
216 			else
217 				flags |= EVENP;
218 		} else
219 			flags |= EVENP | ODDP;
220 	} else {
221 		if ((tp->t_flags&LITOUT) && !(oflag&OPOST))
222 			flags |= LITOUT;
223 		if (tp->t_flags&PASS8)
224 			flags |= PASS8;
225 	}
226 
227 	if ((lflag&ICANON) == 0) {
228 		/* fudge */
229 		if (iflag&IXON || lflag&ISIG || lflag&IEXTEN || cflag&PARENB)
230 			flags |= CBREAK;
231 		else
232 			flags |= RAW;
233 	}
234 	if (oflag&OXTABS)
235 		flags |= XTABS;
236 	if (lflag&ECHOE)
237 		flags |= CRTERA|CRTBS;
238 	if (lflag&ECHOKE)
239 		flags |= CRTKIL|CRTBS;
240 	if (lflag&ECHOPRT)
241 		flags |= PRTERA;
242 	if (lflag&ECHOCTL)
243 		flags |= CTLECH;
244 	if ((iflag&IXANY) == 0)
245 		flags |= DECCTQ;
246 	flags |= lflag&(ECHO|MDMBUF|TOSTOP|FLUSHO|NOHANG|PENDIN|NOFLSH);
247 if (ttydebug)
248 	printf("getflags: %x\n", flags);
249 	return (flags);
250 }
251 
252 ttcompatsetflags(tp, t)
253 	register struct tty *tp;
254 	register struct termios *t;
255 {
256 	register flags = tp->t_flags;
257 	register long iflag = t->c_iflag;
258 	register long oflag = t->c_oflag;
259 	register long lflag = t->c_lflag;
260 	register long cflag = t->c_cflag;
261 
262 	if (flags & RAW) {
263 		iflag &= IXOFF;
264 		oflag &= ~OPOST;
265 		lflag &= ~(ECHOCTL|ISIG|ICANON);
266 	} else {
267 		iflag |= BRKINT|IXON|IEXTEN|IMAXBEL;
268 		oflag |= OPOST;
269 		lflag |= ISIG;
270 		if (flags & XTABS)
271 			oflag |= OXTABS;
272 		else
273 			oflag &= ~OXTABS;
274 		if (flags & CBREAK)
275 			lflag &= ~ICANON;
276 		else
277 			lflag |= ICANON;
278 		if (flags&CRMOD) {
279 			iflag |= ICRNL;
280 			oflag |= ONLCR;
281 		} else {
282 			iflag &= ~ICRNL;
283 			oflag &= ~ONLCR;
284 		}
285 	}
286 	if (flags&ECHO)
287 		lflag |= ECHO;
288 	else
289 		lflag &= ~ECHO;
290 
291 	if (flags&(RAW|LITOUT|PASS8)) {
292 		cflag &= ~(CSIZE|PARENB);
293 		cflag |= CS8;
294 		if ((flags&(RAW|PASS8)) == 0)
295 			iflag |= ISTRIP;
296 	} else {
297 		cflag &= ~CSIZE;
298 		cflag |= CS7|PARENB;
299 	}
300 	if ((flags&(EVENP|ODDP)) == EVENP) {
301 		iflag |= INPCK;
302 		cflag &= ~PARODD;
303 	} else if ((flags&(EVENP|ODDP)) == ODDP) {
304 		iflag |= INPCK;
305 		cflag |= PARODD;
306 	} else
307 		iflag &= ~INPCK;
308 	if (flags&LITOUT)
309 		oflag &= ~OPOST;	/* move earlier ? */
310 	if (flags&TANDEM)
311 		iflag |= IXOFF;
312 	else
313 		iflag &= ~IXOFF;
314 	t->c_iflag = iflag;
315 	t->c_oflag = oflag;
316 	t->c_lflag = lflag;
317 	t->c_cflag = cflag;
318 }
319 
320 ttcompatsetlflags(tp, t)
321 	register struct tty *tp;
322 	register struct termios *t;
323 {
324 	register flags = tp->t_flags;
325 	register long iflag = t->c_iflag;
326 	register long oflag = t->c_oflag;
327 	register long lflag = t->c_lflag;
328 	register long cflag = t->c_cflag;
329 
330 	if (flags&CRTERA)
331 		lflag |= ECHOE;
332 	else
333 		lflag &= ~ECHOE;
334 	if (flags&CRTKIL)
335 		lflag |= ECHOKE;
336 	else
337 		lflag &= ~ECHOKE;
338 	if (flags&PRTERA)
339 		lflag |= ECHOPRT;
340 	else
341 		lflag &= ~ECHOPRT;
342 	if (flags&CTLECH)
343 		lflag |= ECHOCTL;
344 	else
345 		lflag &= ~ECHOCTL;
346 	if ((flags&DECCTQ) == 0)
347 		lflag |= IXANY;
348 	else
349 		lflag &= ~IXANY;
350 	lflag &= ~(MDMBUF|TOSTOP|FLUSHO|NOHANG|PENDIN|NOFLSH);
351 	lflag |= flags&(MDMBUF|TOSTOP|FLUSHO|NOHANG|PENDIN|NOFLSH);
352 	if (flags&(LITOUT|PASS8)) {
353 		iflag &= ~ISTRIP;
354 		cflag &= ~(CSIZE|PARENB);
355 		cflag |= CS8;
356 		if (flags&LITOUT)
357 			oflag &= ~OPOST;
358 		if ((flags&(PASS8|RAW)) == 0)
359 			iflag |= ISTRIP;
360 	} else if ((flags&RAW) == 0) {
361 		cflag &= ~CSIZE;
362 		cflag |= CS7|PARENB;
363 		oflag |= OPOST;
364 	}
365 	t->c_iflag = iflag;
366 	t->c_oflag = oflag;
367 	t->c_lflag = lflag;
368 	t->c_cflag = cflag;
369 }
370 #endif	/* COMPAT_43 */
371