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