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