xref: /netbsd-src/sys/compat/sunos32/sunos32_ioctl.c (revision 3b01aba77a7a698587faaae455bbfe740923c1f5)
1 /*	$NetBSD: sunos32_ioctl.c,v 1.6 2001/06/14 20:32:45 thorpej Exp $	*/
2 /* from: NetBSD: sunos_ioctl.c,v 1.35 2001/02/03 22:20:02 mrg Exp 	*/
3 
4 /*
5  * Copyright (c) 2001 Matthew R. Green
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 /*
33  * Copyright (c) 1993 Markus Wild.
34  * All rights reserved.
35  *
36  * Redistribution and use in source and binary forms, with or without
37  * modification, are permitted provided that the following conditions
38  * are met:
39  * 1. Redistributions of source code must retain the above copyright
40  *    notice, this list of conditions and the following disclaimer.
41  * 2. The name of the author may not be used to endorse or promote products
42  *    derived from this software without specific prior written permission
43  *
44  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
45  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
46  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
47  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
48  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
49  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
50  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
51  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
52  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
53  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54  *
55  * loosely from: Header: sunos_ioctl.c,v 1.7 93/05/28 04:40:43 torek Exp
56  */
57 
58 #if defined(_KERNEL_OPT)
59 #include "opt_compat_netbsd32.h"
60 #include "opt_execfmt.h"
61 #endif
62 
63 #include <sys/param.h>
64 #include <sys/proc.h>
65 #include <sys/systm.h>
66 #include <sys/file.h>
67 #include <sys/filedesc.h>
68 #include <sys/ioctl.h>
69 #include <sys/termios.h>
70 #include <sys/tty.h>
71 #include <sys/socket.h>
72 #include <sys/audioio.h>
73 #include <sys/vnode.h>
74 #include <sys/mount.h>
75 #include <sys/disklabel.h>
76 #include <sys/syscallargs.h>
77 
78 #include <miscfs/specfs/specdev.h>
79 
80 #include <net/if.h>
81 
82 #include <dev/sun/disklabel.h>
83 
84 #include <compat/sunos/sunos.h>
85 #include <compat/sunos/sunos_syscallargs.h>
86 #include <compat/netbsd32/netbsd32.h>
87 #include <compat/netbsd32/netbsd32_syscallargs.h>
88 #include <compat/sunos32/sunos32.h>
89 #include <compat/sunos32/sunos32_syscallargs.h>
90 #include <compat/common/compat_util.h>
91 
92 /*
93  * SunOS ioctl calls.
94  * This file is something of a hodge-podge.
95  * Support gets added as things turn up....
96  */
97 
98 static struct speedtab sptab[] = {
99 	{ 0, 0 },
100 	{ 50, 1 },
101 	{ 75, 2 },
102 	{ 110, 3 },
103 	{ 134, 4 },
104 	{ 135, 4 },
105 	{ 150, 5 },
106 	{ 200, 6 },
107 	{ 300, 7 },
108 	{ 600, 8 },
109 	{ 1200, 9 },
110 	{ 1800, 10 },
111 	{ 2400, 11 },
112 	{ 4800, 12 },
113 	{ 9600, 13 },
114 	{ 19200, 14 },
115 	{ 38400, 15 },
116 	{ -1, -1 }
117 };
118 
119 static netbsd32_u_long s2btab[] = {
120 	0,
121 	50,
122 	75,
123 	110,
124 	134,
125 	150,
126 	200,
127 	300,
128 	600,
129 	1200,
130 	1800,
131 	2400,
132 	4800,
133 	9600,
134 	19200,
135 	38400,
136 };
137 
138 static void stios2btios __P((struct sunos_termios *, struct termios *));
139 static void btios2stios __P((struct termios *, struct sunos_termios *));
140 static void stios2stio __P((struct sunos_termios *, struct sunos_termio *));
141 static void stio2stios __P((struct sunos_termio *, struct sunos_termios *));
142 
143 /*
144  * These two conversion functions have mostly been done
145  * with some perl cut&paste, then hand-edited to comment
146  * out what doesn't exist under NetBSD.
147  * A note from Markus's code:
148  *	(l & BITMASK1) / BITMASK1 * BITMASK2  is translated
149  *	optimally by gcc m68k, much better than any ?: stuff.
150  *	Code may vary with different architectures of course.
151  *
152  * I don't know what optimizer you used, but seeing divu's and
153  * bfextu's in the m68k assembly output did not encourage me...
154  * as well, gcc on the sparc definitely generates much better
155  * code with `?:'.
156  */
157 
158 static void
159 stios2btios(st, bt)
160 	struct sunos_termios *st;
161 	struct termios *bt;
162 {
163 	netbsd32_u_long l, r;
164 
165 	l = st->c_iflag;
166 	r = 	((l & 0x00000001) ? IGNBRK	: 0);
167 	r |=	((l & 0x00000002) ? BRKINT	: 0);
168 	r |=	((l & 0x00000004) ? IGNPAR	: 0);
169 	r |=	((l & 0x00000008) ? PARMRK	: 0);
170 	r |=	((l & 0x00000010) ? INPCK	: 0);
171 	r |=	((l & 0x00000020) ? ISTRIP	: 0);
172 	r |= 	((l & 0x00000040) ? INLCR	: 0);
173 	r |=	((l & 0x00000080) ? IGNCR	: 0);
174 	r |=	((l & 0x00000100) ? ICRNL	: 0);
175 	/*	((l & 0x00000200) ? IUCLC	: 0) */
176 	r |=	((l & 0x00000400) ? IXON	: 0);
177 	r |=	((l & 0x00000800) ? IXANY	: 0);
178 	r |=	((l & 0x00001000) ? IXOFF	: 0);
179 	r |=	((l & 0x00002000) ? IMAXBEL	: 0);
180 	bt->c_iflag = r;
181 
182 	l = st->c_oflag;
183 	r = 	((l & 0x00000001) ? OPOST	: 0);
184 	/*	((l & 0x00000002) ? OLCUC	: 0) */
185 	r |=	((l & 0x00000004) ? ONLCR	: 0);
186 	/*	((l & 0x00000008) ? OCRNL	: 0) */
187 	/*	((l & 0x00000010) ? ONOCR	: 0) */
188 	/*	((l & 0x00000020) ? ONLRET	: 0) */
189 	/*	((l & 0x00000040) ? OFILL	: 0) */
190 	/*	((l & 0x00000080) ? OFDEL	: 0) */
191 	/*	((l & 0x00000100) ? NLDLY	: 0) */
192 	/*	((l & 0x00000100) ? NL1		: 0) */
193 	/*	((l & 0x00000600) ? CRDLY	: 0) */
194 	/*	((l & 0x00000200) ? CR1		: 0) */
195 	/*	((l & 0x00000400) ? CR2		: 0) */
196 	/*	((l & 0x00000600) ? CR3		: 0) */
197 	/*	((l & 0x00001800) ? TABDLY	: 0) */
198 	/*	((l & 0x00000800) ? TAB1	: 0) */
199 	/*	((l & 0x00001000) ? TAB2	: 0) */
200 	r |=	((l & 0x00001800) ? OXTABS	: 0);
201 	/*	((l & 0x00002000) ? BSDLY	: 0) */
202 	/*	((l & 0x00002000) ? BS1		: 0) */
203 	/*	((l & 0x00004000) ? VTDLY	: 0) */
204 	/*	((l & 0x00004000) ? VT1		: 0) */
205 	/*	((l & 0x00008000) ? FFDLY	: 0) */
206 	/*	((l & 0x00008000) ? FF1		: 0) */
207 	/*	((l & 0x00010000) ? PAGEOUT	: 0) */
208 	/*	((l & 0x00020000) ? WRAP	: 0) */
209 	bt->c_oflag = r;
210 
211 	l = st->c_cflag;
212 	switch (l & 0x00000030) {
213 	case 0:
214 		r = CS5;
215 		break;
216 	case 0x00000010:
217 		r = CS6;
218 		break;
219 	case 0x00000020:
220 		r = CS7;
221 		break;
222 	case 0x00000030:
223 		r = CS8;
224 		break;
225 	}
226 	r |=	((l & 0x00000040) ? CSTOPB	: 0);
227 	r |=	((l & 0x00000080) ? CREAD	: 0);
228 	r |= 	((l & 0x00000100) ? PARENB	: 0);
229 	r |=	((l & 0x00000200) ? PARODD	: 0);
230 	r |=	((l & 0x00000400) ? HUPCL	: 0);
231 	r |=	((l & 0x00000800) ? CLOCAL	: 0);
232 	/*	((l & 0x00001000) ? LOBLK	: 0) */
233 	r |=	((l & 0x80000000) ? (CRTS_IFLOW|CCTS_OFLOW) : 0);
234 	bt->c_cflag = r;
235 
236 	bt->c_ispeed = bt->c_ospeed = s2btab[l & 0x0000000f];
237 
238 	l = st->c_lflag;
239 	r = 	((l & 0x00000001) ? ISIG	: 0);
240 	r |=	((l & 0x00000002) ? ICANON	: 0);
241 	/*	((l & 0x00000004) ? XCASE	: 0) */
242 	r |=	((l & 0x00000008) ? ECHO	: 0);
243 	r |=	((l & 0x00000010) ? ECHOE	: 0);
244 	r |=	((l & 0x00000020) ? ECHOK	: 0);
245 	r |=	((l & 0x00000040) ? ECHONL	: 0);
246 	r |= 	((l & 0x00000080) ? NOFLSH	: 0);
247 	r |=	((l & 0x00000100) ? TOSTOP	: 0);
248 	r |=	((l & 0x00000200) ? ECHOCTL	: 0);
249 	r |=	((l & 0x00000400) ? ECHOPRT	: 0);
250 	r |=	((l & 0x00000800) ? ECHOKE	: 0);
251 	/*	((l & 0x00001000) ? DEFECHO	: 0) */
252 	r |=	((l & 0x00002000) ? FLUSHO	: 0);
253 	r |=	((l & 0x00004000) ? PENDIN	: 0);
254 	bt->c_lflag = r;
255 
256 	bt->c_cc[VINTR]    = st->c_cc[0]  ? st->c_cc[0]  : _POSIX_VDISABLE;
257 	bt->c_cc[VQUIT]    = st->c_cc[1]  ? st->c_cc[1]  : _POSIX_VDISABLE;
258 	bt->c_cc[VERASE]   = st->c_cc[2]  ? st->c_cc[2]  : _POSIX_VDISABLE;
259 	bt->c_cc[VKILL]    = st->c_cc[3]  ? st->c_cc[3]  : _POSIX_VDISABLE;
260 	bt->c_cc[VEOF]     = st->c_cc[4]  ? st->c_cc[4]  : _POSIX_VDISABLE;
261 	bt->c_cc[VEOL]     = st->c_cc[5]  ? st->c_cc[5]  : _POSIX_VDISABLE;
262 	bt->c_cc[VEOL2]    = st->c_cc[6]  ? st->c_cc[6]  : _POSIX_VDISABLE;
263     /*	bt->c_cc[VSWTCH]   = st->c_cc[7]  ? st->c_cc[7]  : _POSIX_VDISABLE; */
264 	bt->c_cc[VSTART]   = st->c_cc[8]  ? st->c_cc[8]  : _POSIX_VDISABLE;
265 	bt->c_cc[VSTOP]    = st->c_cc[9]  ? st->c_cc[9]  : _POSIX_VDISABLE;
266 	bt->c_cc[VSUSP]    = st->c_cc[10] ? st->c_cc[10] : _POSIX_VDISABLE;
267 	bt->c_cc[VDSUSP]   = st->c_cc[11] ? st->c_cc[11] : _POSIX_VDISABLE;
268 	bt->c_cc[VREPRINT] = st->c_cc[12] ? st->c_cc[12] : _POSIX_VDISABLE;
269 	bt->c_cc[VDISCARD] = st->c_cc[13] ? st->c_cc[13] : _POSIX_VDISABLE;
270 	bt->c_cc[VWERASE]  = st->c_cc[14] ? st->c_cc[14] : _POSIX_VDISABLE;
271 	bt->c_cc[VLNEXT]   = st->c_cc[15] ? st->c_cc[15] : _POSIX_VDISABLE;
272 	bt->c_cc[VSTATUS]  = st->c_cc[16] ? st->c_cc[16] : _POSIX_VDISABLE;
273 
274 	/* if `raw mode', create native VMIN/VTIME from SunOS VEOF/VEOL */
275 	bt->c_cc[VMIN]	   = (bt->c_lflag & ICANON) ? 1 : bt->c_cc[VEOF];
276 	bt->c_cc[VTIME]	   = (bt->c_lflag & ICANON) ? 1 : bt->c_cc[VEOL];
277 }
278 
279 
280 static void
281 btios2stios(bt, st)
282 	struct termios *bt;
283 	struct sunos_termios *st;
284 {
285 	netbsd32_u_long l, r;
286 	int s;
287 
288 	l = bt->c_iflag;
289 	r = 	((l &  IGNBRK) ? 0x00000001	: 0);
290 	r |=	((l &  BRKINT) ? 0x00000002	: 0);
291 	r |=	((l &  IGNPAR) ? 0x00000004	: 0);
292 	r |=	((l &  PARMRK) ? 0x00000008	: 0);
293 	r |=	((l &   INPCK) ? 0x00000010	: 0);
294 	r |=	((l &  ISTRIP) ? 0x00000020	: 0);
295 	r |=	((l &   INLCR) ? 0x00000040	: 0);
296 	r |=	((l &   IGNCR) ? 0x00000080	: 0);
297 	r |=	((l &   ICRNL) ? 0x00000100	: 0);
298 	/*	((l &   IUCLC) ? 0x00000200	: 0) */
299 	r |=	((l &    IXON) ? 0x00000400	: 0);
300 	r |=	((l &   IXANY) ? 0x00000800	: 0);
301 	r |=	((l &   IXOFF) ? 0x00001000	: 0);
302 	r |=	((l & IMAXBEL) ? 0x00002000	: 0);
303 	st->c_iflag = r;
304 
305 	l = bt->c_oflag;
306 	r =	((l &   OPOST) ? 0x00000001	: 0);
307 	/*	((l &   OLCUC) ? 0x00000002	: 0) */
308 	r |=	((l &   ONLCR) ? 0x00000004	: 0);
309 	/*	((l &   OCRNL) ? 0x00000008	: 0) */
310 	/*	((l &   ONOCR) ? 0x00000010	: 0) */
311 	/*	((l &  ONLRET) ? 0x00000020	: 0) */
312 	/*	((l &   OFILL) ? 0x00000040	: 0) */
313 	/*	((l &   OFDEL) ? 0x00000080	: 0) */
314 	/*	((l &   NLDLY) ? 0x00000100	: 0) */
315 	/*	((l &     NL1) ? 0x00000100	: 0) */
316 	/*	((l &   CRDLY) ? 0x00000600	: 0) */
317 	/*	((l &     CR1) ? 0x00000200	: 0) */
318 	/*	((l &     CR2) ? 0x00000400	: 0) */
319 	/*	((l &     CR3) ? 0x00000600	: 0) */
320 	/*	((l &  TABDLY) ? 0x00001800	: 0) */
321 	/*	((l &    TAB1) ? 0x00000800	: 0) */
322 	/*	((l &    TAB2) ? 0x00001000	: 0) */
323 	r |=	((l &  OXTABS) ? 0x00001800	: 0);
324 	/*	((l &   BSDLY) ? 0x00002000	: 0) */
325 	/*	((l &     BS1) ? 0x00002000	: 0) */
326 	/*	((l &   VTDLY) ? 0x00004000	: 0) */
327 	/*	((l &     VT1) ? 0x00004000	: 0) */
328 	/*	((l &   FFDLY) ? 0x00008000	: 0) */
329 	/*	((l &     FF1) ? 0x00008000	: 0) */
330 	/*	((l & PAGEOUT) ? 0x00010000	: 0) */
331 	/*	((l &    WRAP) ? 0x00020000	: 0) */
332 	st->c_oflag = r;
333 
334 	l = bt->c_cflag;
335 	switch (l & CSIZE) {
336 	case CS5:
337 		r = 0;
338 		break;
339 	case CS6:
340 		r = 0x00000010;
341 		break;
342 	case CS7:
343 		r = 0x00000020;
344 		break;
345 	case CS8:
346 		r = 0x00000030;
347 		break;
348 	}
349 	r |=	((l &  CSTOPB) ? 0x00000040	: 0);
350 	r |=	((l &   CREAD) ? 0x00000080	: 0);
351 	r |=	((l &  PARENB) ? 0x00000100	: 0);
352 	r |=	((l &  PARODD) ? 0x00000200	: 0);
353 	r |=	((l &   HUPCL) ? 0x00000400	: 0);
354 	r |=	((l &  CLOCAL) ? 0x00000800	: 0);
355 	/*	((l &   LOBLK) ? 0x00001000	: 0) */
356 	r |=	((l & (CRTS_IFLOW|CCTS_OFLOW)) ? 0x80000000 : 0);
357 	st->c_cflag = r;
358 
359 	l = bt->c_lflag;
360 	r =	((l &    ISIG) ? 0x00000001	: 0);
361 	r |=	((l &  ICANON) ? 0x00000002	: 0);
362 	/*	((l &   XCASE) ? 0x00000004	: 0) */
363 	r |=	((l &    ECHO) ? 0x00000008	: 0);
364 	r |=	((l &   ECHOE) ? 0x00000010	: 0);
365 	r |=	((l &   ECHOK) ? 0x00000020	: 0);
366 	r |=	((l &  ECHONL) ? 0x00000040	: 0);
367 	r |=	((l &  NOFLSH) ? 0x00000080	: 0);
368 	r |=	((l &  TOSTOP) ? 0x00000100	: 0);
369 	r |=	((l & ECHOCTL) ? 0x00000200	: 0);
370 	r |=	((l & ECHOPRT) ? 0x00000400	: 0);
371 	r |=	((l &  ECHOKE) ? 0x00000800	: 0);
372 	/*	((l & DEFECHO) ? 0x00001000	: 0) */
373 	r |=	((l &  FLUSHO) ? 0x00002000	: 0);
374 	r |=	((l &  PENDIN) ? 0x00004000	: 0);
375 	st->c_lflag = r;
376 
377 	s = ttspeedtab(bt->c_ospeed, sptab);
378 	if (s >= 0)
379 		st->c_cflag |= s;
380 
381 	st->c_cc[0] = bt->c_cc[VINTR]   != _POSIX_VDISABLE? bt->c_cc[VINTR]:0;
382 	st->c_cc[1] = bt->c_cc[VQUIT]   != _POSIX_VDISABLE? bt->c_cc[VQUIT]:0;
383 	st->c_cc[2] = bt->c_cc[VERASE]  != _POSIX_VDISABLE? bt->c_cc[VERASE]:0;
384 	st->c_cc[3] = bt->c_cc[VKILL]   != _POSIX_VDISABLE? bt->c_cc[VKILL]:0;
385 	st->c_cc[4] = bt->c_cc[VEOF]    != _POSIX_VDISABLE? bt->c_cc[VEOF]:0;
386 	st->c_cc[5] = bt->c_cc[VEOL]    != _POSIX_VDISABLE? bt->c_cc[VEOL]:0;
387 	st->c_cc[6] = bt->c_cc[VEOL2]   != _POSIX_VDISABLE? bt->c_cc[VEOL2]:0;
388 	st->c_cc[7] = 0;
389 		/*    bt->c_cc[VSWTCH]  != _POSIX_VDISABLE? bt->c_cc[VSWTCH]: */
390 	st->c_cc[8] = bt->c_cc[VSTART]  != _POSIX_VDISABLE? bt->c_cc[VSTART]:0;
391 	st->c_cc[9] = bt->c_cc[VSTOP]   != _POSIX_VDISABLE? bt->c_cc[VSTOP]:0;
392 	st->c_cc[10]= bt->c_cc[VSUSP]   != _POSIX_VDISABLE? bt->c_cc[VSUSP]:0;
393 	st->c_cc[11]= bt->c_cc[VDSUSP]  != _POSIX_VDISABLE? bt->c_cc[VDSUSP]:0;
394 	st->c_cc[12]= bt->c_cc[VREPRINT]!= _POSIX_VDISABLE? bt->c_cc[VREPRINT]:0;
395 	st->c_cc[13]= bt->c_cc[VDISCARD]!= _POSIX_VDISABLE? bt->c_cc[VDISCARD]:0;
396 	st->c_cc[14]= bt->c_cc[VWERASE] != _POSIX_VDISABLE? bt->c_cc[VWERASE]:0;
397 	st->c_cc[15]= bt->c_cc[VLNEXT]  != _POSIX_VDISABLE? bt->c_cc[VLNEXT]:0;
398 	st->c_cc[16]= bt->c_cc[VSTATUS] != _POSIX_VDISABLE? bt->c_cc[VSTATUS]:0;
399 
400 	if (!(bt->c_lflag & ICANON)) {
401 		/* SunOS stores VMIN/VTIME in VEOF/VEOL (if ICANON is off) */
402 		st->c_cc[4] = bt->c_cc[VMIN];
403 		st->c_cc[5] = bt->c_cc[VTIME];
404 	}
405 
406 	st->c_line = 0;
407 }
408 
409 static void
410 stios2stio(ts, t)
411 	struct sunos_termios *ts;
412 	struct sunos_termio *t;
413 {
414 	t->c_iflag = ts->c_iflag;
415 	t->c_oflag = ts->c_oflag;
416 	t->c_cflag = ts->c_cflag;
417 	t->c_lflag = ts->c_lflag;
418 	t->c_line  = ts->c_line;
419 	memcpy(t->c_cc, ts->c_cc, 8);
420 }
421 
422 static void
423 stio2stios(t, ts)
424 	struct sunos_termio *t;
425 	struct sunos_termios *ts;
426 {
427 	ts->c_iflag = t->c_iflag;
428 	ts->c_oflag = t->c_oflag;
429 	ts->c_cflag = t->c_cflag;
430 	ts->c_lflag = t->c_lflag;
431 	ts->c_line  = t->c_line;
432 	memcpy(ts->c_cc, t->c_cc, 8); /* don't touch the upper fields! */
433 }
434 
435 int
436 sunos32_sys_ioctl(p, v, retval)
437 	struct proc *p;
438 	void *v;
439 	register_t *retval;
440 {
441 	struct sunos32_sys_ioctl_args /* {
442 		int	fd;
443 		netbsd32_u_long	com;
444 		netbsd32_caddr_t	data;
445 	} */ *uap = v;
446 	struct filedesc *fdp = p->p_fd;
447 	struct file *fp;
448 	int (*ctl) __P((struct file *, u_long, caddr_t, struct proc *));
449 	int error;
450 
451 	if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
452 		return EBADF;
453 
454 	if ((fp->f_flag & (FREAD|FWRITE)) == 0)
455 		return EBADF;
456 
457 	ctl = fp->f_ops->fo_ioctl;
458 
459 	switch (SCARG(uap, com)) {
460 	case _IOR('t', 0, int):
461 		SCARG(uap, com) = TIOCGETD;
462 		break;
463 	case _IOW('t', 1, int):
464 	    {
465 		int disc;
466 
467 		if ((error = copyin((caddr_t)(u_long)SCARG(uap, data), (caddr_t)&disc,
468 		    sizeof disc)) != 0)
469 			return error;
470 
471 		/* map SunOS NTTYDISC into our termios discipline */
472 		if (disc == 2)
473 			disc = 0;
474 		/* all other disciplines are not supported by NetBSD */
475 		if (disc)
476 			return ENXIO;
477 
478 		return (*ctl)(fp, TIOCSETD, (caddr_t)&disc, p);
479 	    }
480 	case _IOW('t', 101, int):	/* sun SUNOS_TIOCSSOFTCAR */
481 	    {
482 		int x;	/* unused */
483 
484 		return copyin((caddr_t)&x, (caddr_t)(u_long)SCARG(uap, data), sizeof x);
485 	    }
486 	case _IOR('t', 100, int):	/* sun SUNOS_TIOCSSOFTCAR */
487 	    {
488 		int x = 0;
489 
490 		return copyout((caddr_t)&x, (caddr_t)(u_long)SCARG(uap, data), sizeof x);
491 	    }
492 	case _IO('t', 36): 		/* sun TIOCCONS, no parameters */
493 	    {
494 		int on = 1;
495 		return (*ctl)(fp, TIOCCONS, (caddr_t)&on, p);
496 	    }
497 	case _IOW('t', 37, struct sunos_ttysize):
498 	    {
499 		struct winsize ws;
500 		struct sunos_ttysize ss;
501 
502 		if ((error = (*ctl)(fp, TIOCGWINSZ, (caddr_t)&ws, p)) != 0)
503 			return (error);
504 
505 		if ((error = copyin ((caddr_t)(u_long)SCARG(uap, data), &ss, sizeof (ss))) != 0)
506 			return error;
507 
508 		ws.ws_row = ss.ts_row;
509 		ws.ws_col = ss.ts_col;
510 
511 		return ((*ctl)(fp, TIOCSWINSZ, (caddr_t)&ws, p));
512 	    }
513 	case _IOW('t', 38, struct sunos_ttysize):
514 	    {
515 		struct winsize ws;
516 		struct sunos_ttysize ss;
517 
518 		if ((error = (*ctl)(fp, TIOCGWINSZ, (caddr_t)&ws, p)) != 0)
519 			return (error);
520 
521 		ss.ts_row = ws.ws_row;
522 		ss.ts_col = ws.ws_col;
523 
524 		return copyout ((caddr_t)&ss, (caddr_t)(u_long)SCARG(uap, data), sizeof (ss));
525 	    }
526 	case _IOW('t', 130, int):	/* TIOCSETPGRP: posix variant */
527 		SCARG(uap, com) = TIOCSPGRP;
528 		break;
529 	case _IOR('t', 131, int):	/* TIOCGETPGRP: posix variant */
530 	    {
531 		/*
532 		 * sigh, must do error translation on pty devices
533 		 * (see also kern/tty_pty.c)
534 		 */
535 		int pgrp;
536 		struct vnode *vp;
537 		error = (*ctl)(fp, TIOCGPGRP, (caddr_t)&pgrp, p);
538 		if (error) {
539 			vp = (struct vnode *)fp->f_data;
540 			if (error == EIO && vp != NULL &&
541 			    vp->v_type == VCHR && major(vp->v_rdev) == 21)
542 				error = ENOTTY;
543 			return (error);
544 		}
545 		return copyout((caddr_t)&pgrp, (caddr_t)(u_long)SCARG(uap, data), sizeof(pgrp));
546 	    }
547 	case _IO('t', 132):
548 		SCARG(uap, com) = TIOCSCTTY;
549 		break;
550 	case SUNOS_TCGETA:
551 	case SUNOS_TCGETS:
552 	    {
553 		struct termios bts;
554 		struct sunos_termios sts;
555 		struct sunos_termio st;
556 
557 		if ((error = (*ctl)(fp, TIOCGETA, (caddr_t)&bts, p)) != 0)
558 			return error;
559 
560 		btios2stios (&bts, &sts);
561 		if (SCARG(uap, com) == SUNOS_TCGETA) {
562 			stios2stio (&sts, &st);
563 			return copyout((caddr_t)&st, (caddr_t)(u_long)SCARG(uap, data),
564 			    sizeof (st));
565 		} else
566 			return copyout((caddr_t)&sts, (caddr_t)(u_long)SCARG(uap, data),
567 			    sizeof (sts));
568 		/*NOTREACHED*/
569 	    }
570 	case SUNOS_TCSETA:
571 	case SUNOS_TCSETAW:
572 	case SUNOS_TCSETAF:
573 	    {
574 		struct termios bts;
575 		struct sunos_termios sts;
576 		struct sunos_termio st;
577 
578 		if ((error = copyin((caddr_t)(u_long)SCARG(uap, data), (caddr_t)&st,
579 		    sizeof (st))) != 0)
580 			return error;
581 
582 		/* get full BSD termios so we don't lose information */
583 		if ((error = (*ctl)(fp, TIOCGETA, (caddr_t)&bts, p)) != 0)
584 			return error;
585 
586 		/*
587 		 * convert to sun termios, copy in information from
588 		 * termio, and convert back, then set new values.
589 		 */
590 		btios2stios(&bts, &sts);
591 		stio2stios(&st, &sts);
592 		stios2btios(&sts, &bts);
593 
594 		return (*ctl)(fp, SCARG(uap, com) - SUNOS_TCSETA + TIOCSETA,
595 		    (caddr_t)&bts, p);
596 	    }
597 	case SUNOS_TCSETS:
598 	case SUNOS_TCSETSW:
599 	case SUNOS_TCSETSF:
600 	    {
601 		struct termios bts;
602 		struct sunos_termios sts;
603 
604 		if ((error = copyin ((caddr_t)(u_long)SCARG(uap, data), (caddr_t)&sts,
605 		    sizeof (sts))) != 0)
606 			return error;
607 		stios2btios (&sts, &bts);
608 		return (*ctl)(fp, SCARG(uap, com) - SUNOS_TCSETS + TIOCSETA,
609 		    (caddr_t)&bts, p);
610 	    }
611 /*
612  * Pseudo-tty ioctl translations.
613  */
614 	case _IOW('t', 32, int): {	/* TIOCTCNTL */
615 		int error, on;
616 
617 		error = copyin ((caddr_t)(u_long)SCARG(uap, data), (caddr_t)&on, sizeof (on));
618 		if (error)
619 			return error;
620 		return (*ctl)(fp, TIOCUCNTL, (caddr_t)&on, p);
621 	}
622 	case _IOW('t', 33, int): {	/* TIOCSIGNAL */
623 		int error, sig;
624 
625 		error = copyin ((caddr_t)(u_long)SCARG(uap, data), (caddr_t)&sig, sizeof (sig));
626 		if (error)
627 			return error;
628 		return (*ctl)(fp, TIOCSIG, (caddr_t)&sig, p);
629 	}
630 
631 /*
632  * Socket ioctl translations.
633  */
634 #define IFREQ_IN(a) { \
635 	struct ifreq ifreq; \
636 	error = copyin ((caddr_t)(u_long)SCARG(uap, data), (caddr_t)&ifreq, sizeof (ifreq)); \
637 	if (error) \
638 		return error; \
639 	return (*ctl)(fp, a, (caddr_t)&ifreq, p); \
640 }
641 #define IFREQ_INOUT(a) { \
642 	struct ifreq ifreq; \
643 	error = copyin ((caddr_t)(u_long)SCARG(uap, data), (caddr_t)&ifreq, sizeof (ifreq)); \
644 	if (error) \
645 		return error; \
646 	if ((error = (*ctl)(fp, a, (caddr_t)&ifreq, p)) != 0) \
647 		return error; \
648 	return copyout ((caddr_t)&ifreq, (caddr_t)(u_long)SCARG(uap, data), sizeof (ifreq)); \
649 }
650 
651 	case _IOW('i', 12, struct ifreq):
652 		/* SIOCSIFADDR */
653 		break;
654 
655 	case _IOWR('i', 13, struct ifreq):
656 		IFREQ_INOUT(OSIOCGIFADDR);
657 
658 	case _IOW('i', 14, struct ifreq):
659 		/* SIOCSIFDSTADDR */
660 		break;
661 
662 	case _IOWR('i', 15, struct ifreq):
663 		IFREQ_INOUT(OSIOCGIFDSTADDR);
664 
665 	case _IOW('i', 16, struct ifreq):
666 		/* SIOCSIFFLAGS */
667 		break;
668 
669 	case _IOWR('i', 17, struct ifreq):
670 		/* SIOCGIFFLAGS */
671 		break;
672 
673 	case _IOW('i', 21, struct ifreq):
674 		IFREQ_IN(SIOCSIFMTU);
675 
676 	case _IOWR('i', 22, struct ifreq):
677 		IFREQ_INOUT(SIOCGIFMTU);
678 
679 	case _IOWR('i', 23, struct ifreq):
680 		IFREQ_INOUT(SIOCGIFBRDADDR);
681 
682 	case _IOW('i', 24, struct ifreq):
683 		IFREQ_IN(SIOCSIFBRDADDR);
684 
685 	case _IOWR('i', 25, struct ifreq):
686 		IFREQ_INOUT(OSIOCGIFNETMASK);
687 
688 	case _IOW('i', 26, struct ifreq):
689 		IFREQ_IN(SIOCSIFNETMASK);
690 
691 	case _IOWR('i', 27, struct ifreq):
692 		IFREQ_INOUT(SIOCGIFMETRIC);
693 
694 	case _IOWR('i', 28, struct ifreq):
695 		IFREQ_IN(SIOCSIFMETRIC);
696 
697 	case _IOW('i', 30, struct arpreq):
698 		/* SIOCSARP */
699 		break;
700 
701 	case _IOWR('i', 31, struct arpreq):
702 		/* SIOCGARP */
703 		break;
704 
705 	case _IOW('i', 32, struct arpreq):
706 		/* SIOCDARP */
707 		break;
708 
709 	case _IOW('i', 18, struct ifreq):	/* SIOCSIFMEM */
710 	case _IOWR('i', 19, struct ifreq):	/* SIOCGIFMEM */
711 	case _IOW('i', 40, struct ifreq):	/* SIOCUPPER */
712 	case _IOW('i', 41, struct ifreq):	/* SIOCLOWER */
713 	case _IOW('i', 44, struct ifreq):	/* SIOCSETSYNC */
714 	case _IOWR('i', 45, struct ifreq):	/* SIOCGETSYNC */
715 	case _IOWR('i', 46, struct ifreq):	/* SIOCSDSTATS */
716 	case _IOWR('i', 47, struct ifreq):	/* SIOCSESTATS */
717 	case _IOW('i', 48, int):		/* SIOCSPROMISC */
718 	case _IOW('i', 49, struct ifreq):	/* SIOCADDMULTI */
719 	case _IOW('i', 50, struct ifreq):	/* SIOCDELMULTI */
720 		return EOPNOTSUPP;
721 
722 	case _IOWR('i', 20, struct ifconf):	/* SIOCGIFCONF */
723 	    {
724 		struct ifconf ifconf;
725 
726 		/*
727 		 * XXX: two more problems
728 		 * 1. our sockaddr's are variable length, not always sizeof(sockaddr)
729 		 * 2. this returns a name per protocol, ie. it returns two "lo0"'s
730 		 */
731 		error = copyin ((caddr_t)(u_long)SCARG(uap, data), (caddr_t)&ifconf,
732 		    sizeof (ifconf));
733 		if (error)
734 			return error;
735 		error = (*ctl)(fp, OSIOCGIFCONF, (caddr_t)&ifconf, p);
736 		if (error)
737 			return error;
738 		return copyout ((caddr_t)&ifconf, (caddr_t)(u_long)SCARG(uap, data),
739 		    sizeof (ifconf));
740 	    }
741 
742 /*
743  * Audio ioctl translations.
744  */
745 	case _IOR('A', 1, struct sunos_audio_info):	/* AUDIO_GETINFO */
746 	sunos_au_getinfo:
747 	    {
748 		struct audio_info aui;
749 		struct sunos_audio_info sunos_aui;
750 
751 		error = (*ctl)(fp, AUDIO_GETINFO, (caddr_t)&aui, p);
752 		if (error)
753 			return error;
754 
755 		sunos_aui.play = *(struct sunos_audio_prinfo *)&aui.play;
756 		sunos_aui.record = *(struct sunos_audio_prinfo *)&aui.record;
757 
758 		/* `avail_ports' is `seek' in BSD */
759 		sunos_aui.play.avail_ports = AUDIO_SPEAKER | AUDIO_HEADPHONE;
760 		sunos_aui.record.avail_ports = AUDIO_SPEAKER | AUDIO_HEADPHONE;
761 
762 		sunos_aui.play.waiting = 0;
763 		sunos_aui.record.waiting = 0;
764 		sunos_aui.play.eof = 0;
765 		sunos_aui.record.eof = 0;
766 		sunos_aui.monitor_gain = 0; /* aui.__spare; XXX */
767 		/*XXXsunos_aui.output_muted = 0;*/
768 		/*XXX*/sunos_aui.reserved[0] = 0;
769 		/*XXX*/sunos_aui.reserved[1] = 0;
770 		/*XXX*/sunos_aui.reserved[2] = 0;
771 		/*XXX*/sunos_aui.reserved[3] = 0;
772 
773 		return copyout ((caddr_t)&sunos_aui, (caddr_t)(u_long)SCARG(uap, data),
774 				sizeof (sunos_aui));
775 	    }
776 
777 	case _IOWR('A', 2, struct sunos_audio_info):	/* AUDIO_SETINFO */
778 	    {
779 		struct audio_info aui;
780 		struct sunos_audio_info sunos_aui;
781 
782 		error = copyin ((caddr_t)(u_long)SCARG(uap, data), (caddr_t)&sunos_aui,
783 		    sizeof (sunos_aui));
784 		if (error)
785 			return error;
786 
787 		aui.play = *(struct audio_prinfo *)&sunos_aui.play;
788 		aui.record = *(struct audio_prinfo *)&sunos_aui.record;
789 		/* aui.__spare = sunos_aui.monitor_gain; */
790 		aui.blocksize = ~0;
791 		aui.hiwat = ~0;
792 		aui.lowat = ~0;
793 		/* XXX somebody check this please. - is: aui.backlog = ~0; */
794 		aui.mode = ~0;
795 		/*
796 		 * The bsd driver does not distinguish between paused and
797 		 * active. (In the sun driver, not active means samples are
798 		 * not ouput at all, but paused means the last streams buffer
799 		 * is drained and then output stops.)  If either are 0, then
800 		 * when stop output. Otherwise, if either are non-zero,
801 		 * we resume.
802 		 */
803 		if (sunos_aui.play.pause == 0 || sunos_aui.play.active == 0)
804 			aui.play.pause = 0;
805 		else if (sunos_aui.play.pause != (u_char)~0 ||
806 			 sunos_aui.play.active != (u_char)~0)
807 			aui.play.pause = 1;
808 		if (sunos_aui.record.pause == 0 || sunos_aui.record.active == 0)
809 			aui.record.pause = 0;
810 		else if (sunos_aui.record.pause != (u_char)~0 ||
811 			 sunos_aui.record.active != (u_char)~0)
812 			aui.record.pause = 1;
813 
814 		error = (*ctl)(fp, AUDIO_SETINFO, (caddr_t)&aui, p);
815 		if (error)
816 			return error;
817 		/* Return new state */
818 		goto sunos_au_getinfo;
819 	    }
820 	case _IO('A', 3):	/* AUDIO_DRAIN */
821 		return (*ctl)(fp, AUDIO_DRAIN, (void *)0, p);
822 	case _IOR('A', 4, int):	/* AUDIO_GETDEV */
823 	    {
824 		int devtype = SUNOS_AUDIO_DEV_AMD;
825 		return copyout ((caddr_t)&devtype, (caddr_t)(u_long)SCARG(uap, data),
826 				sizeof (devtype));
827 	    }
828 
829 /*
830  * Selected streams ioctls.
831  */
832 #define SUNOS_S_FLUSHR		1
833 #define SUNOS_S_FLUSHW		2
834 #define SUNOS_S_FLUSHRW		3
835 
836 #define SUNOS_S_INPUT		1
837 #define SUNOS_S_HIPRI		2
838 #define SUNOS_S_OUTPUT		4
839 #define SUNOS_S_MSG		8
840 
841 	case _IO('S', 5):	/* I_FLUSH */
842 	    {
843 		int tmp = 0;
844 		switch ((int)(u_long)SCARG(uap, data)) {
845 		case SUNOS_S_FLUSHR:	tmp = FREAD;
846 		case SUNOS_S_FLUSHW:	tmp = FWRITE;
847 		case SUNOS_S_FLUSHRW:	tmp = FREAD|FWRITE;
848 		}
849                 return (*ctl)(fp, TIOCFLUSH, (caddr_t)&tmp, p);
850 	    }
851 	case _IO('S', 9):	/* I_SETSIG */
852 	    {
853 		int on = 1;
854 		if (((int)(u_long)SCARG(uap, data) &
855 			(SUNOS_S_HIPRI|SUNOS_S_INPUT)) ==
856 		    SUNOS_S_HIPRI)
857 			return EOPNOTSUPP;
858                 return (*ctl)(fp, FIOASYNC, (caddr_t)&on, p);
859 	    }
860 	/*
861 	 * SunOS disk ioctls, taken from arch/sparc/sparc/disksubr.c
862 	 * (which was from the old sparc/scsi/sun_disklabel.c), and
863 	 * modified to suite.
864 	 */
865 	case DKIOCGGEOM:
866             {
867 		struct disklabel dl;
868 
869 		error = (*ctl)(fp, DIOCGDINFO, (caddr_t)&dl, p);
870 		if (error)
871 			return (error);
872 
873 #define datageom	((struct sun_dkgeom *)(u_long)SCARG(uap, data))
874 		memset((caddr_t)(u_long)SCARG(uap, data), 0, sizeof(*datageom));
875 
876 		datageom->sdkc_ncylinders = dl.d_ncylinders;
877 		datageom->sdkc_acylinders = dl.d_acylinders;
878 		datageom->sdkc_ntracks = dl.d_ntracks;
879 		datageom->sdkc_nsectors = dl.d_nsectors;
880 		datageom->sdkc_interleave = dl.d_interleave;
881 		datageom->sdkc_sparespercyl = dl.d_sparespercyl;
882 		datageom->sdkc_rpm = dl.d_rpm;
883 		datageom->sdkc_pcylinders = dl.d_ncylinders + dl.d_acylinders;
884 #undef datageom
885 		break;
886 	    }
887 
888 	case DKIOCINFO:
889 		/* Homey don't do DKIOCINFO */
890 		memset((caddr_t)(u_long)SCARG(uap, data), 0, sizeof(struct sun_dkctlr));
891 		break;
892 
893 	case DKIOCGPART:
894             {
895 		struct partinfo pi;
896 
897 		error = (*ctl)(fp, DIOCGPART, (caddr_t)&pi, p);
898 		if (error)
899 			return (error);
900 
901 		if (pi.disklab->d_secpercyl == 0)
902 			return (ERANGE);	/* XXX */
903 		if (pi.part->p_offset % pi.disklab->d_secpercyl != 0)
904 			return (ERANGE);	/* XXX */
905 #define datapart	((struct sun_dkpart *)(u_long)SCARG(uap, data))
906 		datapart->sdkp_cyloffset = pi.part->p_offset / pi.disklab->d_secpercyl;
907 		datapart->sdkp_nsectors = pi.part->p_size;
908 #undef datapart
909 	    }
910 
911 	}
912 	return (netbsd32_ioctl(p, uap, retval));
913 }
914 
915 /* SunOS fcntl(2) cmds not implemented */
916 #define SUN_F_RGETLK	10
917 #define SUN_F_RSETLK	11
918 #define SUN_F_CNVT	12
919 #define SUN_F_RSETLKW	13
920 
921 /* SunOS flock translation */
922 struct sunos_flock {
923 	short	l_type;
924 	short	l_whence;
925 	netbsd32_long	l_start;
926 	netbsd32_long	l_len;
927 	short	l_pid;
928 	short	l_xxx;
929 };
930 
931 static void bsd_to_sunos_flock __P((struct flock *, struct sunos_flock *));
932 static void sunos_to_bsd_flock __P((struct sunos_flock *, struct flock *));
933 
934 #define SUNOS_F_RDLCK	1
935 #define	SUNOS_F_WRLCK	2
936 #define SUNOS_F_UNLCK	3
937 
938 static void
939 bsd_to_sunos_flock(iflp, oflp)
940 	struct flock		*iflp;
941 	struct sunos_flock	*oflp;
942 {
943 	switch (iflp->l_type) {
944 	case F_RDLCK:
945 		oflp->l_type = SUNOS_F_RDLCK;
946 		break;
947 	case F_WRLCK:
948 		oflp->l_type = SUNOS_F_WRLCK;
949 		break;
950 	case F_UNLCK:
951 		oflp->l_type = SUNOS_F_UNLCK;
952 		break;
953 	default:
954 		oflp->l_type = -1;
955 		break;
956 	}
957 
958 	oflp->l_whence = (short) iflp->l_whence;
959 	oflp->l_start = (netbsd32_long) iflp->l_start;
960 	oflp->l_len = (netbsd32_long) iflp->l_len;
961 	oflp->l_pid = (short) iflp->l_pid;
962 	oflp->l_xxx = 0;
963 }
964 
965 
966 static void
967 sunos_to_bsd_flock(iflp, oflp)
968 	struct sunos_flock	*iflp;
969 	struct flock		*oflp;
970 {
971 	switch (iflp->l_type) {
972 	case SUNOS_F_RDLCK:
973 		oflp->l_type = F_RDLCK;
974 		break;
975 	case SUNOS_F_WRLCK:
976 		oflp->l_type = F_WRLCK;
977 		break;
978 	case SUNOS_F_UNLCK:
979 		oflp->l_type = F_UNLCK;
980 		break;
981 	default:
982 		oflp->l_type = -1;
983 		break;
984 	}
985 
986 	oflp->l_whence = iflp->l_whence;
987 	oflp->l_start = (off_t) iflp->l_start;
988 	oflp->l_len = (off_t) iflp->l_len;
989 	oflp->l_pid = (pid_t) iflp->l_pid;
990 
991 }
992 static struct {
993 	netbsd32_long	sun_flg;
994 	netbsd32_long	bsd_flg;
995 } sunfcntl_flgtab[] = {
996 	/* F_[GS]ETFLags that differ: */
997 #define SUN_FSETBLK	0x0010
998 #define SUN_SHLOCK	0x0080
999 #define SUN_EXLOCK	0x0100
1000 #define SUN_FNBIO	0x1000
1001 #define SUN_FSYNC	0x2000
1002 #define SUN_NONBLOCK	0x4000
1003 #define SUN_FNOCTTY	0x8000
1004 	{ SUN_NONBLOCK, O_NONBLOCK },
1005 	{ SUN_FNBIO, O_NONBLOCK },
1006 	{ SUN_SHLOCK, O_SHLOCK },
1007 	{ SUN_EXLOCK, O_EXLOCK },
1008 	{ SUN_FSYNC, O_FSYNC },
1009 	{ SUN_FSETBLK, 0 },
1010 	{ SUN_FNOCTTY, 0 }
1011 };
1012 
1013 int
1014 sunos32_sys_fcntl(p, v, retval)
1015 	struct proc *p;
1016 	void *v;
1017 	register_t *retval;
1018 {
1019 	struct sunos32_sys_fcntl_args /* {
1020 		syscallarg(int) fd;
1021 		syscallarg(int) cmd;
1022 		syscallarg(netbsd32_voidp) arg;
1023 	} */ *uap = v;
1024 	netbsd32_long flg;
1025 	int n, ret;
1026 
1027 	switch (SCARG(uap, cmd)) {
1028 	case F_SETFL:
1029 		flg = (netbsd32_long)SCARG(uap, arg);
1030 		n = sizeof(sunfcntl_flgtab) / sizeof(sunfcntl_flgtab[0]);
1031 		while (--n >= 0) {
1032 			if (flg & sunfcntl_flgtab[n].sun_flg) {
1033 				flg &= ~sunfcntl_flgtab[n].sun_flg;
1034 				flg |= sunfcntl_flgtab[n].bsd_flg;
1035 			}
1036 		}
1037 		SCARG(uap, arg) = (netbsd32_voidp)flg;
1038 		break;
1039 
1040 	case F_GETLK:
1041 	case F_SETLK:
1042 	case F_SETLKW:
1043 		{
1044 			int error;
1045 			struct sunos_flock	 ifl;
1046 			struct flock		*flp, fl;
1047 			caddr_t sg = stackgap_init(p->p_emul);
1048 			struct sys_fcntl_args		fa;
1049 
1050 			SCARG(&fa, fd) = SCARG(uap, fd);
1051 			SCARG(&fa, cmd) = SCARG(uap, cmd);
1052 
1053 			flp = stackgap_alloc(&sg, sizeof(struct flock));
1054 			SCARG(&fa, arg) = (void *) flp;
1055 
1056 			error = copyin((caddr_t)(u_long)SCARG(uap, arg), &ifl, sizeof ifl);
1057 			if (error)
1058 				return error;
1059 
1060 			sunos_to_bsd_flock(&ifl, &fl);
1061 
1062 			error = copyout(&fl, flp, sizeof fl);
1063 			if (error)
1064 				return error;
1065 
1066 			error = sys_fcntl(p, &fa, retval);
1067 			if (error || SCARG(&fa, cmd) != F_GETLK)
1068 				return error;
1069 
1070 			error = copyin(flp, &fl, sizeof fl);
1071 			if (error)
1072 				return error;
1073 
1074 			bsd_to_sunos_flock(&fl, &ifl);
1075 
1076 			return copyout(&ifl, (caddr_t)(u_long)SCARG(uap, arg), sizeof ifl);
1077 		}
1078 		break;
1079 	case SUN_F_RGETLK:
1080 	case SUN_F_RSETLK:
1081 	case SUN_F_CNVT:
1082 	case SUN_F_RSETLKW:
1083 		return (EOPNOTSUPP);
1084 	}
1085 
1086 	ret = netbsd32_fcntl(p, uap, retval);
1087 
1088 	switch (SCARG(uap, cmd)) {
1089 	case F_GETFL:
1090 		n = sizeof(sunfcntl_flgtab) / sizeof(sunfcntl_flgtab[0]);
1091 		while (--n >= 0) {
1092 			if (ret & sunfcntl_flgtab[n].bsd_flg) {
1093 				ret &= ~sunfcntl_flgtab[n].bsd_flg;
1094 				ret |= sunfcntl_flgtab[n].sun_flg;
1095 			}
1096 		}
1097 		break;
1098 	}
1099 
1100 	return (ret);
1101 }
1102