xref: /netbsd-src/sys/compat/sunos/sunos_ioctl.c (revision 5f7096188587a2c7c95fa3c69b78e1ec9c7923d0)
1 /*
2  * Copyright (c) 1993 Markus Wild.
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. The name of the author may not be used to endorse or promote products
11  *    derived from this software withough specific prior written permission
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  * loosely from: Header: sun_ioctl.c,v 1.7 93/05/28 04:40:43 torek Exp
25  * $Id: sunos_ioctl.c,v 1.5 1993/11/22 22:54:48 deraadt Exp $
26  */
27 
28 #include <sys/param.h>
29 #include <sys/proc.h>
30 #include <sys/file.h>
31 #include <sys/filedesc.h>
32 #include <sys/ioctl.h>
33 #include <sys/termios.h>
34 #include <sys/tty.h>
35 
36 /*
37  * SunOS ioctl calls.
38  * This file is something of a hodge-podge.
39  * Support gets added as things turn up....
40  */
41 
42 struct sun_ttysize {
43 	int	ts_row;
44 	int	ts_col;
45 };
46 
47 struct sun_termio {
48 	u_short	c_iflag;
49 	u_short	c_oflag;
50 	u_short	c_cflag;
51 	u_short	c_lflag;
52 	char	c_line;
53 	unsigned char c_cc[8];
54 };
55 #define SUN_TCGETA	_IOR('T', 1, struct sun_termio)
56 #define SUN_TCSETA	_IOW('T', 2, struct sun_termio)
57 #define SUN_TCSETAW	_IOW('T', 3, struct sun_termio)
58 #define SUN_TCSETAF	_IOW('T', 4, struct sun_termio)
59 #define SUN_TCSBRK	_IO('T', 5)
60 
61 struct sun_termios {
62 	u_long	c_iflag;
63 	u_long	c_oflag;
64 	u_long	c_cflag;
65 	u_long	c_lflag;
66 	char	c_line;
67 	u_char	c_cc[17];
68 };
69 #define SUN_TCXONC	_IO('T', 6)
70 #define SUN_TCFLSH	_IO('T', 7)
71 #define SUN_TCGETS	_IOR('T', 8, struct sun_termios)
72 #define SUN_TCSETS	_IOW('T', 9, struct sun_termios)
73 #define SUN_TCSETSW	_IOW('T', 10, struct sun_termios)
74 #define SUN_TCSETSF	_IOW('T', 11, struct sun_termios)
75 #define SUN_TCSNDBRK	_IO('T', 12)
76 #define SUN_TCDRAIN	_IO('T', 13)
77 
78 static struct speedtab sptab[] = {
79 	{ 0, 0 },
80 	{ 50, 1 },
81 	{ 75, 2 },
82 	{ 110, 3 },
83 	{ 134, 4 },
84 	{ 135, 4 },
85 	{ 150, 5 },
86 	{ 200, 6 },
87 	{ 300, 7 },
88 	{ 600, 8 },
89 	{ 1200, 9 },
90 	{ 1800, 10 },
91 	{ 2400, 11 },
92 	{ 4800, 12 },
93 	{ 9600, 13 },
94 	{ 19200, 14 },
95 	{ 38400, 15 },
96 	{ -1, -1 }
97 };
98 
99 static u_long s2btab[] = {
100 	0,
101 	50,
102 	75,
103 	110,
104 	134,
105 	150,
106 	200,
107 	300,
108 	600,
109 	1200,
110 	1800,
111 	2400,
112 	4800,
113 	9600,
114 	19200,
115 	38400,
116 };
117 
118 /*
119  * these two conversion functions have mostly been done
120  * with some perl cut&paste, then handedited to comment
121  * out what doesn't exist under NetBSD.
122  * A note from Markus's code:
123  *	(l & BITMASK1) / BITMASK1 * BITMASK2  is translated
124  *	optimally by gcc m68k, much better than any ?: stuff.
125  *	Code may vary with different architectures of course.
126  *
127  * I don't know what optimizer you used, but seeing divu's and
128  * bfextu's in the m68k assembly output did not encourage me...
129  * as well, gcc on the sparc definately generates much better
130  * code with ?:.
131  */
132 
133 static void
134 stios2btios(st, bt)
135 	struct sun_termios *st;
136 	struct termios *bt;
137 {
138 	register u_long l, r;
139 
140 	l = st->c_iflag;
141 	r = 	((l & 0x00000001) ? IGNBRK	: 0);
142 	r |=	((l & 0x00000002) ? BRKINT	: 0);
143 	r |=	((l & 0x00000004) ? IGNPAR	: 0);
144 	r |=	((l & 0x00000008) ? PARMRK	: 0);
145 	r |=	((l & 0x00000010) ? INPCK	: 0);
146 	r |=	((l & 0x00000020) ? ISTRIP	: 0);
147 	r |= 	((l & 0x00000040) ? INLCR	: 0);
148 	r |=	((l & 0x00000080) ? IGNCR	: 0);
149 	r |=	((l & 0x00000100) ? ICRNL	: 0);
150 	/*	((l & 0x00000200) ? IUCLC	: 0) */
151 	r |=	((l & 0x00000400) ? IXON	: 0);
152 	r |=	((l & 0x00000800) ? IXANY	: 0);
153 	r |=	((l & 0x00001000) ? IXOFF	: 0);
154 	r |=	((l & 0x00002000) ? IMAXBEL	: 0);
155 	bt->c_iflag = r;
156 
157 	l = st->c_oflag;
158 	r = 	((l & 0x00000001) ? OPOST	: 0);
159 	/*	((l & 0x00000002) ? OLCUC	: 0) */
160 	r |=	((l & 0x00000004) ? ONLCR	: 0);
161 	/*	((l & 0x00000008) ? OCRNL	: 0) */
162 	/*	((l & 0x00000010) ? ONOCR	: 0) */
163 	/*	((l & 0x00000020) ? ONLRET	: 0) */
164 	/*	((l & 0x00000040) ? OFILL	: 0) */
165 	/*	((l & 0x00000080) ? OFDEL	: 0) */
166 	/*	((l & 0x00000100) ? NLDLY	: 0) */
167 	/*	((l & 0x00000100) ? NL1		: 0) */
168 	/*	((l & 0x00000600) ? CRDLY	: 0) */
169 	/*	((l & 0x00000200) ? CR1		: 0) */
170 	/*	((l & 0x00000400) ? CR2		: 0) */
171 	/*	((l & 0x00000600) ? CR3		: 0) */
172 	/*	((l & 0x00001800) ? TABDLY	: 0) */
173 	/*	((l & 0x00000800) ? TAB1	: 0) */
174 	/*	((l & 0x00001000) ? TAB2	: 0) */
175 	r |=	((l & 0x00001800) ? OXTABS	: 0);
176 	/*	((l & 0x00002000) ? BSDLY	: 0) */
177 	/*	((l & 0x00002000) ? BS1		: 0) */
178 	/*	((l & 0x00004000) ? VTDLY	: 0) */
179 	/*	((l & 0x00004000) ? VT1		: 0) */
180 	/*	((l & 0x00008000) ? FFDLY	: 0) */
181 	/*	((l & 0x00008000) ? FF1		: 0) */
182 	/*	((l & 0x00010000) ? PAGEOUT	: 0) */
183 	/*	((l & 0x00020000) ? WRAP	: 0) */
184 	bt->c_oflag = r;
185 
186 	l = st->c_cflag;
187 	r = 	((l & 0x00000010) ? CS6		: 0);
188 	r |=	((l & 0x00000020) ? CS7		: 0);
189 	r |=	((l & 0x00000030) ? CS8		: 0);
190 	r |=	((l & 0x00000040) ? CSTOPB	: 0);
191 	r |=	((l & 0x00000080) ? CREAD	: 0);
192 	r |= 	((l & 0x00000100) ? PARENB	: 0);
193 	r |=	((l & 0x00000200) ? PARODD	: 0);
194 	r |=	((l & 0x00000400) ? HUPCL	: 0);
195 	r |=	((l & 0x00000800) ? CLOCAL	: 0);
196 	/*	((l & 0x00001000) ? LOBLK	: 0) */
197 	r |=	((l & 0x80000000) ? (CRTS_IFLOW|CCTS_OFLOW) : 0);
198 	bt->c_cflag = r;
199 
200 	bt->c_ispeed = bt->c_ospeed = s2btab[l & 0x0000000f];
201 
202 	l = st->c_lflag;
203 	r = 	((l & 0x00000001) ? ISIG	: 0);
204 	r |=	((l & 0x00000002) ? ICANON	: 0);
205 	/*	((l & 0x00000004) ? XCASE	: 0) */
206 	r |=	((l & 0x00000008) ? ECHO	: 0);
207 	r |=	((l & 0x00000010) ? ECHOE	: 0);
208 	r |=	((l & 0x00000020) ? ECHOK	: 0);
209 	r |=	((l & 0x00000040) ? ECHONL	: 0);
210 	r |= 	((l & 0x00000080) ? NOFLSH	: 0);
211 	r |=	((l & 0x00000100) ? TOSTOP	: 0);
212 	r |=	((l & 0x00000200) ? ECHOCTL	: 0);
213 	r |=	((l & 0x00000400) ? ECHOPRT	: 0);
214 	r |=	((l & 0x00000800) ? ECHOKE	: 0);
215 	/*	((l & 0x00001000) ? DEFECHO	: 0) */
216 	r |=	((l & 0x00002000) ? FLUSHO	: 0);
217 	r |=	((l & 0x00004000) ? PENDIN	: 0);
218 	bt->c_lflag = r;
219 
220 	bt->c_cc[VINTR]    = st->c_cc[0]  ? st->c_cc[0]  : _POSIX_VDISABLE;
221 	bt->c_cc[VQUIT]    = st->c_cc[1]  ? st->c_cc[1]  : _POSIX_VDISABLE;
222 	bt->c_cc[VERASE]   = st->c_cc[2]  ? st->c_cc[2]  : _POSIX_VDISABLE;
223 	bt->c_cc[VKILL]    = st->c_cc[3]  ? st->c_cc[3]  : _POSIX_VDISABLE;
224 	bt->c_cc[VEOF]     = st->c_cc[4]  ? st->c_cc[4]  : _POSIX_VDISABLE;
225 	bt->c_cc[VEOL]     = st->c_cc[5]  ? st->c_cc[5]  : _POSIX_VDISABLE;
226 	bt->c_cc[VEOL2]    = st->c_cc[6]  ? st->c_cc[6]  : _POSIX_VDISABLE;
227     /*	bt->c_cc[VSWTCH]   = st->c_cc[7]  ? st->c_cc[7]  : _POSIX_VDISABLE; */
228 	bt->c_cc[VSTART]   = st->c_cc[8]  ? st->c_cc[8]  : _POSIX_VDISABLE;
229 	bt->c_cc[VSTOP]    = st->c_cc[9]  ? st->c_cc[9]  : _POSIX_VDISABLE;
230 	bt->c_cc[VSUSP]    = st->c_cc[10] ? st->c_cc[10] : _POSIX_VDISABLE;
231 	bt->c_cc[VDSUSP]   = st->c_cc[11] ? st->c_cc[11] : _POSIX_VDISABLE;
232 	bt->c_cc[VREPRINT] = st->c_cc[12] ? st->c_cc[12] : _POSIX_VDISABLE;
233 	bt->c_cc[VDISCARD] = st->c_cc[13] ? st->c_cc[13] : _POSIX_VDISABLE;
234 	bt->c_cc[VWERASE]  = st->c_cc[14] ? st->c_cc[14] : _POSIX_VDISABLE;
235 	bt->c_cc[VLNEXT]   = st->c_cc[15] ? st->c_cc[15] : _POSIX_VDISABLE;
236 	bt->c_cc[VSTATUS]  = st->c_cc[16] ? st->c_cc[16] : _POSIX_VDISABLE;
237 }
238 
239 
240 static void
241 btios2stios(bt, st)
242 	struct termios *bt;
243 	struct sun_termios *st;
244 {
245 	register u_long l, r;
246 
247 	l = bt->c_iflag;
248 	r = 	((l &  IGNBRK) ? 0x00000001	: 0);
249 	r |=	((l &  BRKINT) ? 0x00000002	: 0);
250 	r |=	((l &  IGNPAR) ? 0x00000004	: 0);
251 	r |=	((l &  PARMRK) ? 0x00000008	: 0);
252 	r |=	((l &   INPCK) ? 0x00000010	: 0);
253 	r |=	((l &  ISTRIP) ? 0x00000020	: 0);
254 	r |=	((l &   INLCR) ? 0x00000040	: 0);
255 	r |=	((l &   IGNCR) ? 0x00000080	: 0);
256 	r |=	((l &   ICRNL) ? 0x00000100	: 0);
257 	/*	((l &   IUCLC) ? 0x00000200	: 0) */
258 	r |=	((l &    IXON) ? 0x00000400	: 0);
259 	r |=	((l &   IXANY) ? 0x00000800	: 0);
260 	r |=	((l &   IXOFF) ? 0x00001000	: 0);
261 	r |=	((l & IMAXBEL) ? 0x00002000	: 0);
262 	st->c_iflag = r;
263 
264 	l = bt->c_oflag;
265 	r =	((l &   OPOST) ? 0x00000001	: 0);
266 	/*	((l &   OLCUC) ? 0x00000002	: 0) */
267 	r |=	((l &   ONLCR) ? 0x00000004	: 0);
268 	/*	((l &   OCRNL) ? 0x00000008	: 0) */
269 	/*	((l &   ONOCR) ? 0x00000010	: 0) */
270 	/*	((l &  ONLRET) ? 0x00000020	: 0) */
271 	/*	((l &   OFILL) ? 0x00000040	: 0) */
272 	/*	((l &   OFDEL) ? 0x00000080	: 0) */
273 	/*	((l &   NLDLY) ? 0x00000100	: 0) */
274 	/*	((l &     NL1) ? 0x00000100	: 0) */
275 	/*	((l &   CRDLY) ? 0x00000600	: 0) */
276 	/*	((l &     CR1) ? 0x00000200	: 0) */
277 	/*	((l &     CR2) ? 0x00000400	: 0) */
278 	/*	((l &     CR3) ? 0x00000600	: 0) */
279 	/*	((l &  TABDLY) ? 0x00001800	: 0) */
280 	/*	((l &    TAB1) ? 0x00000800	: 0) */
281 	/*	((l &    TAB2) ? 0x00001000	: 0) */
282 	r |=	((l &  OXTABS) ? 0x00001800	: 0);
283 	/*	((l &   BSDLY) ? 0x00002000	: 0) */
284 	/*	((l &     BS1) ? 0x00002000	: 0) */
285 	/*	((l &   VTDLY) ? 0x00004000	: 0) */
286 	/*	((l &     VT1) ? 0x00004000	: 0) */
287 	/*	((l &   FFDLY) ? 0x00008000	: 0) */
288 	/*	((l &     FF1) ? 0x00008000	: 0) */
289 	/*	((l & PAGEOUT) ? 0x00010000	: 0) */
290 	/*	((l &    WRAP) ? 0x00020000	: 0) */
291 	st->c_oflag = r;
292 
293 	l = bt->c_cflag;
294 	r = 	((l &     CS6) ? 0x00000010	: 0);
295 	r |=	((l &     CS7) ? 0x00000020	: 0);
296 	r |=	((l &     CS8) ? 0x00000030	: 0);
297 	r |=	((l &  CSTOPB) ? 0x00000040	: 0);
298 	r |=	((l &   CREAD) ? 0x00000080	: 0);
299 	r |=	((l &  PARENB) ? 0x00000100	: 0);
300 	r |=	((l &  PARODD) ? 0x00000200	: 0);
301 	r |=	((l &   HUPCL) ? 0x00000400	: 0);
302 	r |=	((l &  CLOCAL) ? 0x00000800	: 0);
303 	/*	((l &   LOBLK) ? 0x00001000	: 0) */
304 	r |=	((l & (CRTS_IFLOW|CCTS_OFLOW)) ? 0x80000000 : 0);
305 	st->c_cflag = r;
306 
307 	l = bt->c_lflag;
308 	r =	((l &    ISIG) ? 0x00000001	: 0);
309 	r |=	((l &  ICANON) ? 0x00000002	: 0);
310 	/*	((l &   XCASE) ? 0x00000004	: 0) */
311 	r |=	((l &    ECHO) ? 0x00000008	: 0);
312 	r |=	((l &   ECHOE) ? 0x00000010	: 0);
313 	r |=	((l &   ECHOK) ? 0x00000020	: 0);
314 	r |=	((l &  ECHONL) ? 0x00000040	: 0);
315 	r |=	((l &  NOFLSH) ? 0x00000080	: 0);
316 	r |=	((l &  TOSTOP) ? 0x00000100	: 0);
317 	r |=	((l & ECHOCTL) ? 0x00000200	: 0);
318 	r |=	((l & ECHOPRT) ? 0x00000400	: 0);
319 	r |=	((l &  ECHOKE) ? 0x00000800	: 0);
320 	/*	((l & DEFECHO) ? 0x00001000	: 0) */
321 	r |=	((l &  FLUSHO) ? 0x00002000	: 0);
322 	r |=	((l &  PENDIN) ? 0x00004000	: 0);
323 	st->c_lflag = r;
324 
325 	l = ttspeedtab(bt->c_ospeed, sptab);
326 	if (l >= 0)
327 		st->c_cflag |= l;
328 
329 	st->c_cc[0] = bt->c_cc[VINTR]   != _POSIX_VDISABLE? bt->c_cc[VINTR]:0;
330 	st->c_cc[1] = bt->c_cc[VQUIT]   != _POSIX_VDISABLE? bt->c_cc[VQUIT]:0;
331 	st->c_cc[2] = bt->c_cc[VERASE]  != _POSIX_VDISABLE? bt->c_cc[VERASE]:0;
332 	st->c_cc[3] = bt->c_cc[VKILL]   != _POSIX_VDISABLE? bt->c_cc[VKILL]:0;
333 	st->c_cc[4] = bt->c_cc[VEOF]    != _POSIX_VDISABLE? bt->c_cc[VEOF]:0;
334 	st->c_cc[5] = bt->c_cc[VEOL]    != _POSIX_VDISABLE? bt->c_cc[VEOL]:0;
335 	st->c_cc[6] = bt->c_cc[VEOL2]   != _POSIX_VDISABLE? bt->c_cc[VEOL2]:0;
336 	st->c_cc[7] = 0;
337 		/*    bt->c_cc[VSWTCH]  != _POSIX_VDISABLE? bt->c_cc[VSWTCH]: */
338 	st->c_cc[8] = bt->c_cc[VSTART]  != _POSIX_VDISABLE? bt->c_cc[VSTART]:0;
339 	st->c_cc[9] = bt->c_cc[VSTOP]   != _POSIX_VDISABLE? bt->c_cc[VSTOP]:0;
340 	st->c_cc[10]= bt->c_cc[VSUSP]   != _POSIX_VDISABLE? bt->c_cc[VSUSP]:0;
341 	st->c_cc[11]= bt->c_cc[VDSUSP]  != _POSIX_VDISABLE? bt->c_cc[VDSUSP]:0;
342 	st->c_cc[12]= bt->c_cc[VREPRINT]!= _POSIX_VDISABLE? bt->c_cc[VREPRINT]:0;
343 	st->c_cc[13]= bt->c_cc[VDISCARD]!= _POSIX_VDISABLE? bt->c_cc[VDISCARD]:0;
344 	st->c_cc[14]= bt->c_cc[VWERASE] != _POSIX_VDISABLE? bt->c_cc[VWERASE]:0;
345 	st->c_cc[15]= bt->c_cc[VLNEXT]  != _POSIX_VDISABLE? bt->c_cc[VLNEXT]:0;
346 	st->c_cc[16]= bt->c_cc[VSTATUS] != _POSIX_VDISABLE? bt->c_cc[VSTATUS]:0;
347 
348 	st->c_line = 0;
349 }
350 
351 static void
352 stios2stio(ts, t)
353 	struct sun_termios *ts;
354 	struct sun_termio *t;
355 {
356 	t->c_iflag = ts->c_iflag;
357 	t->c_oflag = ts->c_oflag;
358 	t->c_cflag = ts->c_cflag;
359 	t->c_lflag = ts->c_lflag;
360 	t->c_line  = ts->c_line;
361 	bcopy(ts->c_cc, t->c_cc, 8);
362 }
363 
364 static void
365 stio2stios(t, ts)
366 	struct sun_termio *t;
367 	struct sun_termios *ts;
368 {
369 	ts->c_iflag = t->c_iflag;
370 	ts->c_oflag = t->c_oflag;
371 	ts->c_cflag = t->c_cflag;
372 	ts->c_lflag = t->c_lflag;
373 	ts->c_line  = t->c_line;
374 	bcopy(t->c_cc, ts->c_cc, 8); /* don't touch the upper fields! */
375 }
376 
377 struct sun_ioctl_args {
378 	int	fd;
379 	int	cmd;
380 	caddr_t	data;
381 };
382 
383 int
384 sun_ioctl(p, uap, retval)
385 	register struct proc *p;
386 	register struct sun_ioctl_args *uap;
387 	int *retval;
388 {
389 	register struct filedesc *fdp = p->p_fd;
390 	register struct file *fp;
391 	register int (*ctl)();
392 	int error;
393 
394 	if ( (unsigned)uap->fd >= fdp->fd_nfiles ||
395 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
396 		return EBADF;
397 
398 	if ((fp->f_flag & (FREAD|FWRITE)) == 0)
399 		return EBADF;
400 
401 	ctl = fp->f_ops->fo_ioctl;
402 
403 	switch (uap->cmd) {
404 	case _IOR('t', 0, int):
405 		uap->cmd = TIOCGETD;
406 		break;
407 	case _IOW('t', 1, int):
408 	    {
409 		int disc;
410 
411 		if ((error = copyin(uap->data, (caddr_t)&disc,
412 		    sizeof disc)) != 0)
413 			return error;
414 
415 		/* map SunOS NTTYDISC into our termios discipline */
416 		if (disc == 2)
417 			disc = 0;
418 		/* all other disciplines are not supported by NetBSD */
419 		if (disc)
420 			return ENXIO;
421 
422 		return (*ctl)(fp, TIOCSETD, (caddr_t)&disc, p);
423 	    }
424 	case _IOW('t', 101, int):	/* sun SUN_TIOCSSOFTCAR */
425 	    {
426 		int x;	/* unused */
427 
428 		return copyin((caddr_t)&x, uap->data, sizeof x);
429 	    }
430 	case _IOR('t', 100, int):	/* sun SUN_TIOCSSOFTCAR */
431 	    {
432 		int x = 0;
433 
434 		return copyout((caddr_t)&x, uap->data, sizeof x);
435 	    }
436 	case _IO('t', 36): 		/* sun TIOCCONS, no parameters */
437 	    {
438 		int on = 1;
439 		return (*ctl)(fp, TIOCCONS, (caddr_t)&on, p);
440 	    }
441 	case _IOW('t', 37, struct sun_ttysize):
442 	    {
443 		struct winsize ws;
444 		struct sun_ttysize ss;
445 
446 		if ((error = (*ctl)(fp, TIOCGWINSZ, (caddr_t)&ws, p)) != 0)
447 			return (error);
448 
449 		if ((error = copyin (uap->data, &ss, sizeof (ss))) != 0)
450 			return error;
451 
452 		ws.ws_row = ss.ts_row;
453 		ws.ws_col = ss.ts_col;
454 
455 		return ((*ctl)(fp, TIOCSWINSZ, (caddr_t)&ws, p));
456 	    }
457 	case _IOW('t', 38, struct sun_ttysize):
458 	    {
459 		struct winsize ws;
460 		struct sun_ttysize ss;
461 
462 		if ((error = (*ctl)(fp, TIOCGWINSZ, (caddr_t)&ws, p)) != 0)
463 			return (error);
464 
465 		ss.ts_row = ws.ws_row;
466 		ss.ts_col = ws.ws_col;
467 
468 		return copyout ((caddr_t)&ss, uap->data, sizeof (ss));
469 	    }
470 	case _IOR('t', 130, int):
471 		uap->cmd = TIOCSPGRP;
472 		break;
473 	case _IOR('t', 131, int):
474 		uap->cmd = TIOCGPGRP;
475 		break;
476 	case _IO('t', 132):
477 		uap->cmd = TIOCSCTTY;
478 		break;
479 	case SUN_TCGETA:
480 	case SUN_TCGETS:
481 	    {
482 		struct termios bts;
483 		struct sun_termios sts;
484 		struct sun_termio st;
485 
486 		if ((error = (*ctl)(fp, TIOCGETA, (caddr_t)&bts, p)) != 0)
487 			return error;
488 
489 		btios2stios (&bts, &sts);
490 		if (uap->cmd == SUN_TCGETA) {
491 			stios2stio (&sts, &st);
492 			return copyout((caddr_t)&st, uap->data, sizeof (st));
493 		} else
494 			return copyout((caddr_t)&sts, uap->data, sizeof (sts));
495 		/*NOTREACHED*/
496 	    }
497 	case SUN_TCSETA:
498 	case SUN_TCSETAW:
499 	case SUN_TCSETAF:
500 	    {
501 		struct termios bts;
502 		struct sun_termios sts;
503 		struct sun_termio st;
504 
505 		if ((error = copyin(uap->data, (caddr_t)&st,
506 		    sizeof (st))) != 0)
507 			return error;
508 
509 		/* get full BSD termios so we don't lose information */
510 		if ((error = (*ctl)(fp, TIOCGETA, (caddr_t)&bts, p)) != 0)
511 			return error;
512 
513 		/*
514 		 * convert to sun termios, copy in information from
515 		 * termio, and convert back, then set new values.
516 		 */
517 		btios2stios(&bts, &sts);
518 		stio2stios(&st, &sts);
519 		stios2btios(&sts, &bts);
520 
521 		return (*ctl)(fp, uap->cmd - SUN_TCSETA + TIOCSETA,
522 		    (caddr_t)&bts, p);
523 	    }
524 	case SUN_TCSETS:
525 	case SUN_TCSETSW:
526 	case SUN_TCSETSF:
527 	    {
528 		struct termios bts;
529 		struct sun_termios sts;
530 
531 		if ((error = copyin (uap->data, (caddr_t)&sts,
532 		    sizeof (sts))) != 0)
533 			return error;
534 		stios2btios (&sts, &bts);
535 		return (*ctl)(fp, uap->cmd - SUN_TCSETS + TIOCSETA,
536 		    (caddr_t)&bts, p);
537 	    }
538 	}
539 	return (ioctl(p, uap, retval));
540 }
541