added my responsibility for the `cpm' port
[unix-history] / sys / kern / tty_compat.c
CommitLineData
15637ed4
RG
1/*-
2 * Copyright (c) 1982, 1986, 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
600f7f07 33 * from: @(#)tty_compat.c 7.10 (Berkeley) 5/9/91
fde1aeb2 34 * $Id: tty_compat.c,v 1.3 1993/11/25 01:33:26 wollman Exp $
15637ed4
RG
35 */
36
37/*
38 * mapping routines for old line discipline (yuck)
39 */
40#ifdef COMPAT_43
41
42#include "param.h"
43#include "systm.h"
44#include "ioctl.h"
45#include "tty.h"
46#include "termios.h"
47#include "proc.h"
48#include "file.h"
49#include "conf.h"
50#include "dkstat.h"
51#include "kernel.h"
52#include "syslog.h"
53
4c45483e
GW
54static int ttcompatgetflags(struct tty *);
55static void ttcompatsetflags(struct tty *, struct termios *);
56static void ttcompatsetlflags(struct tty *, struct termios *);
57
15637ed4
RG
58int ttydebug = 0;
59
60static struct speedtab compatspeeds[] = {
61#define MAX_SPEED 17
62 115200, 17,
63 57600, 16,
64 38400, 15,
65 19200, 14,
66 9600, 13,
67 4800, 12,
68 2400, 11,
69 1800, 10,
70 1200, 9,
71 600, 8,
72 300, 7,
73 200, 6,
74 150, 5,
75 134, 4,
76 110, 3,
77 75, 2,
78 50, 1,
79 0, 0,
80 -1, -1,
81};
82static int compatspcodes[] = {
83 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
84 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200,
85};
86
87/*ARGSUSED*/
4c45483e 88int
15637ed4
RG
89ttcompat(tp, com, data, flag)
90 register struct tty *tp;
4c45483e 91 int com;
15637ed4 92 caddr_t data;
4c45483e 93 int flag;
15637ed4
RG
94{
95
96 switch (com) {
97 case TIOCGETP: {
98 register struct sgttyb *sg = (struct sgttyb *)data;
99 register u_char *cc = tp->t_cc;
100 register speed;
101
102 speed = ttspeedtab(tp->t_ospeed, compatspeeds);
103 sg->sg_ospeed = (speed == -1) ? MAX_SPEED : speed;
104 if (tp->t_ispeed == 0)
105 sg->sg_ispeed = sg->sg_ospeed;
106 else {
107 speed = ttspeedtab(tp->t_ispeed, compatspeeds);
108 sg->sg_ispeed = (speed == -1) ? MAX_SPEED : speed;
109 }
110 sg->sg_erase = cc[VERASE];
111 sg->sg_kill = cc[VKILL];
112 sg->sg_flags = tp->t_flags = ttcompatgetflags(tp);
113 break;
114 }
115
116 case TIOCSETP:
117 case TIOCSETN: {
118 register struct sgttyb *sg = (struct sgttyb *)data;
119 struct termios term;
120 int speed;
121
122 term = tp->t_termios;
123 if ((speed = sg->sg_ispeed) > MAX_SPEED || speed < 0)
124 term.c_ispeed = speed;
125 else
126 term.c_ispeed = compatspcodes[speed];
127 if ((speed = sg->sg_ospeed) > MAX_SPEED || speed < 0)
128 term.c_ospeed = speed;
129 else
130 term.c_ospeed = compatspcodes[speed];
131 term.c_cc[VERASE] = sg->sg_erase;
132 term.c_cc[VKILL] = sg->sg_kill;
fde1aeb2 133 tp->t_flags = tp->t_flags&0xffff0000UL | sg->sg_flags&0xffff;
15637ed4
RG
134 ttcompatsetflags(tp, &term);
135 return (ttioctl(tp, com == TIOCSETP ? TIOCSETAF : TIOCSETA,
136 (caddr_t)&term, flag));
137 }
138
139 case TIOCGETC: {
140 struct tchars *tc = (struct tchars *)data;
141 register u_char *cc = tp->t_cc;
142
143 tc->t_intrc = cc[VINTR];
144 tc->t_quitc = cc[VQUIT];
145 tc->t_startc = cc[VSTART];
146 tc->t_stopc = cc[VSTOP];
147 tc->t_eofc = cc[VEOF];
148 tc->t_brkc = cc[VEOL];
149 break;
150 }
151 case TIOCSETC: {
152 struct tchars *tc = (struct tchars *)data;
153 register u_char *cc = tp->t_cc;
154
155 cc[VINTR] = tc->t_intrc;
156 cc[VQUIT] = tc->t_quitc;
157 cc[VSTART] = tc->t_startc;
158 cc[VSTOP] = tc->t_stopc;
159 cc[VEOF] = tc->t_eofc;
160 cc[VEOL] = tc->t_brkc;
161 if (tc->t_brkc == -1)
162 cc[VEOL2] = _POSIX_VDISABLE;
163 break;
164 }
165 case TIOCSLTC: {
166 struct ltchars *ltc = (struct ltchars *)data;
167 register u_char *cc = tp->t_cc;
168
169 cc[VSUSP] = ltc->t_suspc;
170 cc[VDSUSP] = ltc->t_dsuspc;
171 cc[VREPRINT] = ltc->t_rprntc;
172 cc[VDISCARD] = ltc->t_flushc;
173 cc[VWERASE] = ltc->t_werasc;
174 cc[VLNEXT] = ltc->t_lnextc;
175 break;
176 }
177 case TIOCGLTC: {
178 struct ltchars *ltc = (struct ltchars *)data;
179 register u_char *cc = tp->t_cc;
180
181 ltc->t_suspc = cc[VSUSP];
182 ltc->t_dsuspc = cc[VDSUSP];
183 ltc->t_rprntc = cc[VREPRINT];
184 ltc->t_flushc = cc[VDISCARD];
185 ltc->t_werasc = cc[VWERASE];
186 ltc->t_lnextc = cc[VLNEXT];
187 break;
188 }
189 case TIOCLBIS:
190 case TIOCLBIC:
191 case TIOCLSET: {
192 struct termios term;
193
194 term = tp->t_termios;
195 if (com == TIOCLSET)
196 tp->t_flags = (tp->t_flags&0xffff) | *(int *)data<<16;
197 else {
198 tp->t_flags =
fde1aeb2
GW
199 (ttcompatgetflags(tp) & 0xffff0000UL)
200 | (tp->t_flags & 0xffff);
15637ed4
RG
201 if (com == TIOCLBIS)
202 tp->t_flags |= *(int *)data<<16;
203 else
204 tp->t_flags &= ~(*(int *)data<<16);
205 }
206 ttcompatsetlflags(tp, &term);
207 return (ttioctl(tp, TIOCSETA, (caddr_t)&term, flag));
208 }
209 case TIOCLGET:
210 tp->t_flags =
fde1aeb2
GW
211 (ttcompatgetflags(tp) & 0xffff0000UL)
212 | (tp->t_flags & 0xffff);
15637ed4
RG
213 *(int *)data = tp->t_flags>>16;
214 if (ttydebug)
215 printf("CLGET: returning %x\n", *(int *)data);
216 break;
217
218 case OTIOCGETD:
219 *(int *)data = tp->t_line ? tp->t_line : 2;
220 break;
221
222 case OTIOCSETD: {
223 int ldisczero = 0;
224
225 return (ttioctl(tp, TIOCSETD,
226 *(int *)data == 2 ? (caddr_t)&ldisczero : data, flag));
227 }
228
229 case OTIOCCONS:
230 *(int *)data = 1;
231 return (ttioctl(tp, TIOCCONS, data, flag));
232
233 default:
234 return (-1);
235 }
236 return (0);
237}
238
4c45483e 239static int
15637ed4
RG
240ttcompatgetflags(tp)
241 register struct tty *tp;
242{
243 register long iflag = tp->t_iflag;
244 register long lflag = tp->t_lflag;
245 register long oflag = tp->t_oflag;
246 register long cflag = tp->t_cflag;
247 register flags = 0;
248
249 if (iflag&IXOFF)
250 flags |= TANDEM;
251 if (iflag&ICRNL || oflag&ONLCR)
252 flags |= CRMOD;
253 if ((cflag&CSIZE) == CS8) {
254 flags |= PASS8;
255 if (iflag&ISTRIP)
256 flags |= ANYP;
257 }
258 else if (cflag&PARENB) {
259 if (iflag&INPCK) {
260 if (cflag&PARODD)
261 flags |= ODDP;
262 else
263 flags |= EVENP;
264 }
265 else
266 flags |= EVENP | ODDP;
267 }
268
269 if ((lflag&ICANON) == 0) {
270 /* fudge */
271 if (iflag&(INPCK|ISTRIP|IXON) || lflag&(IEXTEN|ISIG)
272 || cflag&(CSIZE|PARENB) != CS8)
273 flags |= CBREAK;
274 else
275 flags |= RAW;
276 }
277 if (!(flags&RAW) && !(oflag&OPOST) && cflag&(CSIZE|PARENB) == CS8)
278 flags |= LITOUT;
279 if (oflag&OXTABS)
280 flags |= XTABS;
281 if (lflag&ECHOE)
282 flags |= CRTERA|CRTBS;
283 if (lflag&ECHOKE)
284 flags |= CRTKIL|CRTBS;
285 if (lflag&ECHOPRT)
286 flags |= PRTERA;
287 if (lflag&ECHOCTL)
288 flags |= CTLECH;
289 if ((iflag&IXANY) == 0)
290 flags |= DECCTQ;
291 flags |= lflag&(ECHO|MDMBUF|TOSTOP|FLUSHO|NOHANG|PENDIN|NOFLSH);
292if (ttydebug)
293 printf("getflags: %x\n", flags);
294 return (flags);
295}
296
4c45483e 297static void
15637ed4
RG
298ttcompatsetflags(tp, t)
299 register struct tty *tp;
300 register struct termios *t;
301{
302 register flags = tp->t_flags;
303 register long iflag = t->c_iflag;
304 register long oflag = t->c_oflag;
305 register long lflag = t->c_lflag;
306 register long cflag = t->c_cflag;
307
308 if (flags & RAW) {
309 iflag &= IXOFF|IXANY;
310 lflag &= ~(ECHOCTL|ISIG|ICANON|IEXTEN);
311 } else {
312 iflag |= BRKINT|IXON|IMAXBEL;
313 lflag |= ISIG|IEXTEN|ECHOCTL; /* XXX was echoctl on ? */
314 if (flags & XTABS)
315 oflag |= OXTABS;
316 else
317 oflag &= ~OXTABS;
318 if (flags & CBREAK)
319 lflag &= ~ICANON;
320 else
321 lflag |= ICANON;
322 if (flags&CRMOD) {
323 iflag |= ICRNL;
324 oflag |= ONLCR;
325 } else {
326 iflag &= ~ICRNL;
327 oflag &= ~ONLCR;
328 }
329 }
330 if (flags&ECHO)
331 lflag |= ECHO;
332 else
333 lflag &= ~ECHO;
334
335 cflag &= ~(CSIZE|PARENB);
336 if (flags&(RAW|LITOUT|PASS8)) {
337 cflag |= CS8;
338 if (!(flags&(RAW|PASS8))
339 || (flags&(RAW|PASS8|ANYP)) == (PASS8|ANYP))
340 iflag |= ISTRIP;
341 else
342 iflag &= ~ISTRIP;
343 if (flags&(RAW|LITOUT))
344 oflag &= ~OPOST;
345 else
346 oflag |= OPOST;
347 } else {
348 cflag |= CS7|PARENB;
349 iflag |= ISTRIP;
350 oflag |= OPOST;
351 }
352 if ((flags&(EVENP|ODDP)) == EVENP) {
353 iflag |= INPCK;
354 cflag &= ~PARODD;
355 } else if ((flags&(EVENP|ODDP)) == ODDP) {
356 iflag |= INPCK;
357 cflag |= PARODD;
358 } else
359 iflag &= ~INPCK;
360 if (flags&TANDEM)
361 iflag |= IXOFF;
362 else
363 iflag &= ~IXOFF;
364 t->c_iflag = iflag;
365 t->c_oflag = oflag;
366 t->c_lflag = lflag;
367 t->c_cflag = cflag;
368}
369
4c45483e 370static void
15637ed4
RG
371ttcompatsetlflags(tp, t)
372 register struct tty *tp;
373 register struct termios *t;
374{
375 register flags = tp->t_flags;
376 register long iflag = t->c_iflag;
377 register long oflag = t->c_oflag;
378 register long lflag = t->c_lflag;
379 register long cflag = t->c_cflag;
380
381 if (flags&CRTERA)
382 lflag |= ECHOE;
383 else
384 lflag &= ~ECHOE;
385 if (flags&CRTKIL)
386 lflag |= ECHOKE;
387 else
388 lflag &= ~ECHOKE;
389 if (flags&PRTERA)
390 lflag |= ECHOPRT;
391 else
392 lflag &= ~ECHOPRT;
393 if (flags&CTLECH)
394 lflag |= ECHOCTL;
395 else
396 lflag &= ~ECHOCTL;
397 if ((flags&DECCTQ) == 0)
398 lflag |= IXANY;
399 else
400 lflag &= ~IXANY;
401 lflag &= ~(MDMBUF|TOSTOP|FLUSHO|NOHANG|PENDIN|NOFLSH);
402 lflag |= flags&(MDMBUF|TOSTOP|FLUSHO|NOHANG|PENDIN|NOFLSH);
403
404 cflag &= ~(CSIZE|PARENB);
405 /*
406 * The next if-else statement is copied from above so don't bother
407 * checking it separately. We could avoid fiddlling with the
408 * character size if the mode is already RAW or if neither the
409 * LITOUT bit or the PASS8 bit is being changed, but the delta of
410 * the change is not available here and skipping the RAW case would
411 * make the code different from above.
412 */
413 if (flags&(RAW|LITOUT|PASS8)) {
414 cflag |= CS8;
415 if (!(flags&(RAW|PASS8))
416 || (flags&(RAW|PASS8|ANYP)) == (PASS8|ANYP))
417 iflag |= ISTRIP;
418 else
419 iflag &= ~ISTRIP;
420 if (flags&(RAW|LITOUT))
421 oflag &= ~OPOST;
422 else
423 oflag |= OPOST;
424 } else {
425 cflag |= CS7|PARENB;
426 iflag |= ISTRIP;
427 oflag |= OPOST;
428 }
429 t->c_iflag = iflag;
430 t->c_oflag = oflag;
431 t->c_lflag = lflag;
432 t->c_cflag = cflag;
433}
434#endif /* COMPAT_43 */