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