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