svr4_termios.c revision 80114
1/*
2 * Copyright (c) 1998 Mark Newton
3 * Copyright (c) 1994 Christos Zoulas
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 *    derived from this software without specific prior written permission
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * $FreeBSD: head/sys/compat/svr4/svr4_termios.c 80114 2001-07-22 00:12:22Z assar $
29 */
30
31#include <sys/param.h>
32#include <sys/proc.h>
33#include <sys/systm.h>
34#include <sys/file.h>
35#include <sys/filedesc.h>
36#include <sys/termios.h>
37
38#include <sys/sysproto.h>
39
40#include <compat/svr4/svr4.h>
41#include <compat/svr4/svr4_util.h>
42#include <compat/svr4/svr4_ioctl.h>
43#include <compat/svr4/svr4_termios.h>
44
45#ifndef __CONCAT3
46# if __STDC__
47#  define __CONCAT3(a,b,c)	a ## b ## c
48# else
49#  define __CONCAT3(a,b,c)	a/**/b/**/c
50# endif
51#endif
52
53static u_long bsd_to_svr4_speed __P((u_long, u_long));
54static u_long svr4_to_bsd_speed __P((u_long, u_long));
55static void svr4_to_bsd_termios __P((const struct svr4_termios *,
56				     struct termios *, int));
57static void bsd_to_svr4_termios __P((const struct termios *,
58				     struct svr4_termios *));
59static void svr4_termio_to_termios __P((const struct svr4_termio *,
60					struct svr4_termios *));
61static void svr4_termios_to_termio __P((const struct svr4_termios *,
62					struct svr4_termio *));
63#ifdef DEBUG_SVR4
64static void print_svr4_termios __P((const struct svr4_termios *));
65static void print_bsd_termios __P((const struct termios *));
66#endif /* DEBUG_SVR4 */
67
68#define undefined_char(a,b)				/**/
69#define undefined_flag1(f,a,b)				/**/
70#define undefined_flag2(f,a,b,c1,t1,c2,t2)		/**/
71#define undefined_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4)	/**/
72
73#define svr4_to_bsd_char(a,b) \
74	if (new || __CONCAT3(SVR4_,a,b) < SVR4_NCC) { \
75		if (st->c_cc[__CONCAT3(SVR4_,a,b)] == SVR4_POSIX_VDISABLE) \
76			bt->c_cc[__CONCAT(a,b)] = _POSIX_VDISABLE; \
77		else \
78			bt->c_cc[__CONCAT(a,b)] = st->c_cc[__CONCAT3(SVR4_,a,b)]; \
79	}
80
81#define svr4_to_bsd_flag1(f,a,b) \
82	if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \
83		if (st->f & __CONCAT3(SVR4_,a,b)) \
84			bt->f |= __CONCAT(a,b); \
85		else \
86			bt->f &= ~__CONCAT(a,b); \
87	}
88
89#define svr4_to_bsd_flag2(f,a,b,c1,t1,c2,t2) \
90	if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \
91		bt->f &= ~__CONCAT(a,b); \
92		switch (st->f & __CONCAT3(SVR4_,a,b)) { \
93		case __CONCAT3(SVR4_,c1,t1): bt->f |= __CONCAT(c1,t1); break; \
94		case __CONCAT3(SVR4_,c2,t2): bt->f |= __CONCAT(c2,t2); break; \
95		} \
96	}
97
98#define svr4_to_bsd_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4) \
99	if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \
100		bt->f &= ~__CONCAT(a,b); \
101		switch (st->f & __CONCAT3(SVR4_,a,b)) { \
102		case __CONCAT3(SVR4_,c1,t1): bt->f |= __CONCAT(c1,t1); break; \
103		case __CONCAT3(SVR4_,c2,t2): bt->f |= __CONCAT(c2,t2); break; \
104		case __CONCAT3(SVR4_,c3,t3): bt->f |= __CONCAT(c3,t3); break; \
105		case __CONCAT3(SVR4_,c4,t4): bt->f |= __CONCAT(c4,t4); break; \
106		} \
107	}
108
109
110#define bsd_to_svr4_char(a,b) \
111	if (bt->c_cc[__CONCAT(a,b)] == _POSIX_VDISABLE) \
112		st->c_cc[__CONCAT3(SVR4_,a,b)] = SVR4_POSIX_VDISABLE; \
113	else \
114		st->c_cc[__CONCAT3(SVR4_,a,b)] = bt->c_cc[__CONCAT(a,b)]
115
116#define bsd_to_svr4_flag1(f,a,b) \
117	if (bt->f & __CONCAT(a,b)) \
118		st->f |= __CONCAT3(SVR4_,a,b); \
119	else \
120		st->f &= ~__CONCAT3(SVR4_,a,b)
121
122#define bsd_to_svr4_flag2(f,a,b,c1,t1,c2,t2) \
123	st->f &= ~__CONCAT(a,b); \
124	switch (bt->f & __CONCAT(a,b)) { \
125	case __CONCAT(c1,t1): st->f |= __CONCAT3(SVR4_,c1,t1); break; \
126	case __CONCAT(c2,t2): st->f |= __CONCAT3(SVR4_,c2,t2); break; \
127	}
128
129#define bsd_to_svr4_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4) \
130	st->f &= ~__CONCAT(a,b); \
131	switch (bt->f & __CONCAT(a,b)) { \
132	case __CONCAT(c1,t1): st->f |= __CONCAT3(SVR4_,c1,t1); break; \
133	case __CONCAT(c2,t2): st->f |= __CONCAT3(SVR4_,c2,t2); break; \
134	case __CONCAT(c3,t3): st->f |= __CONCAT3(SVR4_,c3,t3); break; \
135	case __CONCAT(c4,t4): st->f |= __CONCAT3(SVR4_,c4,t4); break; \
136	}
137
138#ifdef DEBUG_SVR4
139static void
140print_svr4_termios(st)
141	const struct svr4_termios *st;
142{
143	int i;
144	DPRINTF(("SVR4\niflag=%lo oflag=%lo cflag=%lo lflag=%lo\n",
145	    st->c_iflag, st->c_oflag, st->c_cflag, st->c_lflag));
146	DPRINTF(("cc: "));
147	for (i = 0; i < SVR4_NCCS; i++)
148		DPRINTF(("%o ", st->c_cc[i]));
149	DPRINTF(("\n"));
150}
151
152
153static void
154print_bsd_termios(bt)
155	const struct termios *bt;
156{
157	int i;
158	uprintf("BSD\niflag=%o oflag=%o cflag=%o lflag=%o\n",
159	    bt->c_iflag, bt->c_oflag, bt->c_cflag, bt->c_lflag);
160	uprintf("cc: ");
161	for (i = 0; i < NCCS; i++)
162		uprintf("%o ", bt->c_cc[i]);
163	uprintf("\n");
164}
165#endif /* DEBUG_SVR4 */
166
167static u_long
168bsd_to_svr4_speed(sp, mask)
169	u_long sp;
170	u_long mask;
171{
172	switch (sp) {
173#undef getval
174#define getval(a,b)	case __CONCAT(a,b):	sp = __CONCAT3(SVR4_,a,b)
175	getval(B,0);
176	getval(B,50);
177	getval(B,75);
178	getval(B,110);
179	getval(B,134);
180	getval(B,150);
181	getval(B,200);
182	getval(B,300);
183	getval(B,600);
184	getval(B,1200);
185	getval(B,1800);
186	getval(B,2400);
187	getval(B,4800);
188	getval(B,9600);
189	getval(B,19200);
190	getval(B,38400);
191	getval(B,57600);
192	getval(B,115200);
193	default: sp = SVR4_B9600;	/* XXX */
194	}
195
196	while ((mask & 1) == 0) {
197		mask >>= 1;
198		sp <<= 1;
199	}
200
201	return sp;
202}
203
204
205static u_long
206svr4_to_bsd_speed(sp, mask)
207	u_long sp;
208	u_long mask;
209{
210	while ((mask & 1) == 0) {
211		mask >>= 1;
212		sp >>= 1;
213	}
214
215	switch (sp & mask) {
216#undef getval
217#define getval(a,b)	case __CONCAT3(SVR4_,a,b):	return __CONCAT(a,b)
218	getval(B,0);
219	getval(B,50);
220	getval(B,75);
221	getval(B,110);
222	getval(B,134);
223	getval(B,150);
224	getval(B,200);
225	getval(B,300);
226	getval(B,600);
227	getval(B,1200);
228	getval(B,1800);
229	getval(B,2400);
230	getval(B,4800);
231	getval(B,9600);
232	getval(B,19200);
233	getval(B,38400);
234	getval(B,57600);
235	getval(B,115200);
236	default: return B9600;	/* XXX */
237	}
238}
239
240
241static void
242svr4_to_bsd_termios(st, bt, new)
243	const struct svr4_termios	*st;
244	struct termios	 		*bt;
245	int				 new;
246{
247	/* control characters */
248	/*
249	 * We process VMIN and VTIME first,
250	 * because they are shared with VEOF and VEOL
251	 */
252	svr4_to_bsd_char(V,MIN);
253	svr4_to_bsd_char(V,TIME);
254
255	svr4_to_bsd_char(V,INTR);
256	svr4_to_bsd_char(V,QUIT);
257	svr4_to_bsd_char(V,ERASE);
258	svr4_to_bsd_char(V,KILL);
259	svr4_to_bsd_char(V,EOF);
260	svr4_to_bsd_char(V,EOL);
261	svr4_to_bsd_char(V,EOL2);
262	undefined_char(V,SWTCH);
263	svr4_to_bsd_char(V,START);
264	svr4_to_bsd_char(V,STOP);
265	svr4_to_bsd_char(V,SUSP);
266	svr4_to_bsd_char(V,DSUSP);
267	svr4_to_bsd_char(V,REPRINT);
268	svr4_to_bsd_char(V,DISCARD);
269	svr4_to_bsd_char(V,WERASE);
270	svr4_to_bsd_char(V,LNEXT);
271
272	/* Input modes */
273	svr4_to_bsd_flag1(c_iflag,I,GNBRK);
274	svr4_to_bsd_flag1(c_iflag,B,RKINT);
275	svr4_to_bsd_flag1(c_iflag,I,GNPAR);
276	svr4_to_bsd_flag1(c_iflag,P,ARMRK);
277	svr4_to_bsd_flag1(c_iflag,I,NPCK);
278	svr4_to_bsd_flag1(c_iflag,I,STRIP);
279	svr4_to_bsd_flag1(c_iflag,I,NLCR);
280	svr4_to_bsd_flag1(c_iflag,I,GNCR);
281	svr4_to_bsd_flag1(c_iflag,I,CRNL);
282	undefined_flag1(c_iflag,I,UCLC);
283	svr4_to_bsd_flag1(c_iflag,I,XON);
284	svr4_to_bsd_flag1(c_iflag,I,XANY);
285	svr4_to_bsd_flag1(c_iflag,I,XOFF);
286	svr4_to_bsd_flag1(c_iflag,I,MAXBEL);
287	undefined_flag1(c_iflag,D,OSMODE);
288
289	/* Output modes */
290	svr4_to_bsd_flag1(c_oflag,O,POST);
291	undefined_flag1(c_oflag,O,LCUC);
292	svr4_to_bsd_flag1(c_oflag,O,NLCR);
293	undefined_flag1(c_oflag,O,CRNL);
294	undefined_flag1(c_oflag,O,NOCR);
295	undefined_flag1(c_oflag,O,NLRET);
296	undefined_flag1(c_oflag,O,FILL);
297	undefined_flag1(c_oflag,O,FDEL);
298	undefined_flag2(c_oflag,N,LDLY,N,L0,N,L1);
299	undefined_flag4(c_oflag,C,RDLY,C,R0,C,R1,C,R2,C,R3);
300	undefined_flag4(c_oflag,T,ABDLY,T,AB0,T,AB1,T,AB2,T,AB3);
301	undefined_flag2(c_oflag,B,SDLY,B,S0,B,S1);
302	undefined_flag2(c_oflag,V,TDLY,V,T0,V,T1);
303	undefined_flag2(c_oflag,F,FDLY,F,F0,F,F1);
304	undefined_flag1(c_oflag,P,AGEOUT);
305	undefined_flag1(c_oflag,W,RAP);
306
307	/* Control modes */
308	bt->c_ospeed = svr4_to_bsd_speed(st->c_cflag, SVR4_CBAUD);
309	svr4_to_bsd_flag4(c_cflag,C,SIZE,C,S5,C,S6,C,S7,C,S8)
310	svr4_to_bsd_flag1(c_cflag,C,STOPB);
311	svr4_to_bsd_flag1(c_cflag,C,READ);
312	svr4_to_bsd_flag1(c_cflag,P,ARENB);
313	svr4_to_bsd_flag1(c_cflag,P,ARODD);
314	svr4_to_bsd_flag1(c_cflag,H,UPCL);
315	svr4_to_bsd_flag1(c_cflag,C,LOCAL);
316	undefined_flag1(c_cflag,R,CV1EN);
317	undefined_flag1(c_cflag,X,MT1EN);
318	undefined_flag1(c_cflag,L,OBLK);
319	undefined_flag1(c_cflag,X,CLUDE);
320	bt->c_ispeed = svr4_to_bsd_speed(st->c_cflag, SVR4_CIBAUD);
321	undefined_flag1(c_cflag,P,AREXT);
322
323	/* line discipline modes */
324	svr4_to_bsd_flag1(c_lflag,I,SIG);
325	svr4_to_bsd_flag1(c_lflag,I,CANON);
326	undefined_flag1(c_lflag,X,CASE);
327	svr4_to_bsd_flag1(c_lflag,E,CHO);
328	svr4_to_bsd_flag1(c_lflag,E,CHOE);
329	svr4_to_bsd_flag1(c_lflag,E,CHOK);
330	svr4_to_bsd_flag1(c_lflag,E,CHONL);
331	svr4_to_bsd_flag1(c_lflag,N,OFLSH);
332	svr4_to_bsd_flag1(c_lflag,T,OSTOP);
333	svr4_to_bsd_flag1(c_lflag,E,CHOCTL);
334	svr4_to_bsd_flag1(c_lflag,E,CHOPRT);
335	svr4_to_bsd_flag1(c_lflag,E,CHOKE);
336	undefined_flag1(c_lflag,D,EFECHO);
337	svr4_to_bsd_flag1(c_lflag,F,LUSHO);
338	svr4_to_bsd_flag1(c_lflag,P,ENDIN);
339	svr4_to_bsd_flag1(c_lflag,I,EXTEN);
340}
341
342
343static void
344bsd_to_svr4_termios(bt, st)
345	const struct termios 	*bt;
346	struct svr4_termios	*st;
347{
348	/* control characters */
349	/*
350	 * We process VMIN and VTIME first,
351	 * because they are shared with VEOF and VEOL
352	 */
353	bsd_to_svr4_char(V,MIN);
354	bsd_to_svr4_char(V,TIME);
355	bsd_to_svr4_char(V,INTR);
356	bsd_to_svr4_char(V,QUIT);
357	bsd_to_svr4_char(V,ERASE);
358	bsd_to_svr4_char(V,KILL);
359	bsd_to_svr4_char(V,EOF);
360	bsd_to_svr4_char(V,EOL);
361	bsd_to_svr4_char(V,EOL2);
362	undefined_char(V,SWTCH);
363	bsd_to_svr4_char(V,START);
364	bsd_to_svr4_char(V,STOP);
365	bsd_to_svr4_char(V,SUSP);
366	bsd_to_svr4_char(V,DSUSP);
367	bsd_to_svr4_char(V,REPRINT);
368	bsd_to_svr4_char(V,DISCARD);
369	bsd_to_svr4_char(V,WERASE);
370	bsd_to_svr4_char(V,LNEXT);
371
372	/* Input modes */
373	bsd_to_svr4_flag1(c_iflag,I,GNBRK);
374	bsd_to_svr4_flag1(c_iflag,B,RKINT);
375	bsd_to_svr4_flag1(c_iflag,I,GNPAR);
376	bsd_to_svr4_flag1(c_iflag,P,ARMRK);
377	bsd_to_svr4_flag1(c_iflag,I,NPCK);
378	bsd_to_svr4_flag1(c_iflag,I,STRIP);
379	bsd_to_svr4_flag1(c_iflag,I,NLCR);
380	bsd_to_svr4_flag1(c_iflag,I,GNCR);
381	bsd_to_svr4_flag1(c_iflag,I,CRNL);
382	undefined_flag1(c_iflag,I,UCLC);
383	bsd_to_svr4_flag1(c_iflag,I,XON);
384	bsd_to_svr4_flag1(c_iflag,I,XANY);
385	bsd_to_svr4_flag1(c_iflag,I,XOFF);
386	bsd_to_svr4_flag1(c_iflag,I,MAXBEL);
387	undefined_flag1(c_iflag,D,OSMODE);
388
389	/* Output modes */
390	bsd_to_svr4_flag1(c_oflag,O,POST);
391	undefined_flag1(c_oflag,O,LCUC);
392	bsd_to_svr4_flag1(c_oflag,O,NLCR);
393	undefined_flag1(c_oflag,O,CRNL);
394	undefined_flag1(c_oflag,O,NOCR);
395	undefined_flag1(c_oflag,O,NLRET);
396	undefined_flag1(c_oflag,O,FILL);
397	undefined_flag1(c_oflag,O,FDEL);
398	undefined_flag2(c_oflag,N,LDLY,N,L0,N,L1);
399	undefined_flag4(c_oflag,C,RDLY,C,R0,C,R1,C,R2,C,R3);
400	undefined_flag4(c_oflag,T,ABDLY,T,AB0,T,AB1,T,AB2,T,AB3);
401	undefined_flag2(c_oflag,B,SDLY,B,S0,B,S1);
402	undefined_flag2(c_oflag,V,TDLY,V,T0,V,T1);
403	undefined_flag2(c_oflag,F,FDLY,F,F0,F,F1);
404	undefined_flag1(c_oflag,P,AGEOUT);
405	undefined_flag1(c_oflag,W,RAP);
406
407	/* Control modes */
408	st->c_cflag &= ~SVR4_CBAUD;
409	st->c_cflag |= bsd_to_svr4_speed(bt->c_ospeed, SVR4_CBAUD);
410	bsd_to_svr4_flag4(c_cflag,C,SIZE,C,S5,C,S6,C,S7,C,S8)
411	bsd_to_svr4_flag1(c_cflag,C,STOPB);
412	bsd_to_svr4_flag1(c_cflag,C,READ);
413	bsd_to_svr4_flag1(c_cflag,P,ARENB);
414	bsd_to_svr4_flag1(c_cflag,P,ARODD);
415	bsd_to_svr4_flag1(c_cflag,H,UPCL);
416	bsd_to_svr4_flag1(c_cflag,C,LOCAL);
417	undefined_flag1(c_cflag,R,CV1EN);
418	undefined_flag1(c_cflag,X,MT1EN);
419	undefined_flag1(c_cflag,L,OBLK);
420	undefined_flag1(c_cflag,X,CLUDE);
421	st->c_cflag &= ~SVR4_CIBAUD;
422	st->c_cflag |= bsd_to_svr4_speed(bt->c_ispeed, SVR4_CIBAUD);
423
424	undefined_flag1(c_oflag,P,AREXT);
425
426	/* line discipline modes */
427	bsd_to_svr4_flag1(c_lflag,I,SIG);
428	bsd_to_svr4_flag1(c_lflag,I,CANON);
429	undefined_flag1(c_lflag,X,CASE);
430	bsd_to_svr4_flag1(c_lflag,E,CHO);
431	bsd_to_svr4_flag1(c_lflag,E,CHOE);
432	bsd_to_svr4_flag1(c_lflag,E,CHOK);
433	bsd_to_svr4_flag1(c_lflag,E,CHONL);
434	bsd_to_svr4_flag1(c_lflag,N,OFLSH);
435	bsd_to_svr4_flag1(c_lflag,T,OSTOP);
436	bsd_to_svr4_flag1(c_lflag,E,CHOCTL);
437	bsd_to_svr4_flag1(c_lflag,E,CHOPRT);
438	bsd_to_svr4_flag1(c_lflag,E,CHOKE);
439	undefined_flag1(c_lflag,D,EFECHO);
440	bsd_to_svr4_flag1(c_lflag,F,LUSHO);
441	bsd_to_svr4_flag1(c_lflag,P,ENDIN);
442	bsd_to_svr4_flag1(c_lflag,I,EXTEN);
443}
444
445
446static void
447svr4_termio_to_termios(t, ts)
448	const struct svr4_termio	*t;
449	struct svr4_termios		*ts;
450{
451	int i;
452
453	ts->c_iflag = (svr4_tcflag_t) t->c_iflag;
454	ts->c_oflag = (svr4_tcflag_t) t->c_oflag;
455	ts->c_cflag = (svr4_tcflag_t) t->c_cflag;
456	ts->c_lflag = (svr4_tcflag_t) t->c_lflag;
457
458	for (i = 0; i < SVR4_NCC; i++)
459		ts->c_cc[i] = (svr4_cc_t) t->c_cc[i];
460}
461
462
463static void
464svr4_termios_to_termio(ts, t)
465	const struct svr4_termios	*ts;
466	struct svr4_termio		*t;
467{
468	int i;
469
470	t->c_iflag = (u_short) ts->c_iflag;
471	t->c_oflag = (u_short) ts->c_oflag;
472	t->c_cflag = (u_short) ts->c_cflag;
473	t->c_lflag = (u_short) ts->c_lflag;
474	t->c_line = 0;	/* XXX */
475
476	for (i = 0; i < SVR4_NCC; i++)
477		t->c_cc[i] = (u_char) ts->c_cc[i];
478}
479
480int
481svr4_term_ioctl(fp, p, retval, fd, cmd, data)
482	struct file *fp;
483	struct proc *p;
484	register_t *retval;
485	int fd;
486	u_long cmd;
487	caddr_t data;
488{
489	struct termios 		bt;
490	struct svr4_termios	st;
491	struct svr4_termio	t;
492	int			error, new;
493
494	*retval = 0;
495
496	DPRINTF(("TERM ioctl %lx\n", cmd));
497
498	switch (cmd) {
499	case SVR4_TCGETA:
500	case SVR4_TCGETS:
501		DPRINTF(("ioctl(TCGET%c);\n", cmd == SVR4_TCGETA ? 'A' : 'S'));
502		if ((error = fo_ioctl(fp, TIOCGETA, (caddr_t) &bt, p)) != 0)
503			return error;
504
505		memset(&st, 0, sizeof(st));
506		bsd_to_svr4_termios(&bt, &st);
507
508#ifdef DEBUG_SVR4
509		print_bsd_termios(&bt);
510		print_svr4_termios(&st);
511#endif /* DEBUG_SVR4 */
512
513		if (cmd == SVR4_TCGETA) {
514		    svr4_termios_to_termio(&st, &t);
515		    return copyout(&t, data, sizeof(t));
516		}
517		else  {
518		    return copyout(&st, data, sizeof(st));
519		}
520
521	case SVR4_TCSETA:
522	case SVR4_TCSETS:
523	case SVR4_TCSETAW:
524	case SVR4_TCSETSW:
525	case SVR4_TCSETAF:
526	case SVR4_TCSETSF:
527	        DPRINTF(("TCSET{A,S,AW,SW,AF,SF}\n"));
528		/* get full BSD termios so we don't lose information */
529		if ((error = fo_ioctl(fp, TIOCGETA, (caddr_t) &bt, p)) != 0)
530			return error;
531
532		switch (cmd) {
533		case SVR4_TCSETS:
534		case SVR4_TCSETSW:
535		case SVR4_TCSETSF:
536			if ((error = copyin(data, &st, sizeof(st))) != 0)
537				return error;
538			new = 1;
539			break;
540
541		case SVR4_TCSETA:
542		case SVR4_TCSETAW:
543		case SVR4_TCSETAF:
544			if ((error = copyin(data, &t, sizeof(t))) != 0)
545				return error;
546
547			svr4_termio_to_termios(&t, &st);
548			new = 0;
549			break;
550
551		default:
552			return EINVAL;
553		}
554
555		svr4_to_bsd_termios(&st, &bt, new);
556
557		switch (cmd) {
558		case SVR4_TCSETA:
559		case SVR4_TCSETS:
560			DPRINTF(("ioctl(TCSET[A|S]);\n"));
561			cmd = TIOCSETA;
562			break;
563		case SVR4_TCSETAW:
564		case SVR4_TCSETSW:
565			DPRINTF(("ioctl(TCSET[A|S]W);\n"));
566			cmd = TIOCSETAW;
567			break;
568		case SVR4_TCSETAF:
569		case SVR4_TCSETSF:
570			DPRINTF(("ioctl(TCSET[A|S]F);\n"));
571			cmd = TIOCSETAF;
572			break;
573		}
574
575#ifdef DEBUG_SVR4
576		print_bsd_termios(&bt);
577		print_svr4_termios(&st);
578#endif /* DEBUG_SVR4 */
579
580		return fo_ioctl(fp, cmd, (caddr_t) &bt, p);
581
582	case SVR4_TIOCGWINSZ:
583	        DPRINTF(("TIOCGWINSZ\n"));
584		{
585			struct svr4_winsize ws;
586
587			error = fo_ioctl(fp, TIOCGWINSZ, (caddr_t) &ws, p);
588			if (error)
589				return error;
590			return copyout(&ws, data, sizeof(ws));
591		}
592
593	case SVR4_TIOCSWINSZ:
594	        DPRINTF(("TIOCSWINSZ\n"));
595		{
596			struct svr4_winsize ws;
597
598			if ((error = copyin(data, &ws, sizeof(ws))) != 0)
599				return error;
600			return fo_ioctl(fp, TIOCSWINSZ, (caddr_t) &ws, p);
601		}
602
603	default:
604	        DPRINTF(("teleport to STREAMS ioctls...\n"));
605		return svr4_stream_ti_ioctl(fp, p, retval, fd, cmd, data);
606	}
607}
608