sunos32_ioctl.c revision 1.25.4.2 1 /* $NetBSD: sunos32_ioctl.c,v 1.25.4.2 2008/01/08 22:10:49 bouyer 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.4.2 2008/01/08 22:10:49 bouyer 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
433 static int
434 sunos32_do_ioctl(int fd, int cmd, void *arg, struct lwp *l)
435 {
436 struct file *fp;
437 struct vnode *vp;
438 int error;
439
440 if ((fp = fd_getfile(l->l_proc->p_fd, fd)) == NULL)
441 return EBADF;
442
443 if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
444 FILE_UNLOCK(fp);
445 return EBADF;
446 }
447
448 FILE_USE(fp);
449 error = fp->f_ops->fo_ioctl(fp, cmd, arg, l);
450 if (error == EIO && cmd == TIOCGPGRP) {
451 vp = (struct vnode *)fp->f_data;
452 if (vp != NULL && vp->v_type == VCHR && major(vp->v_rdev) == 21)
453 error = ENOTTY;
454 }
455 FILE_UNUSE(fp, l);
456 return error;
457 }
458
459 int
460 sunos32_sys_ioctl(struct lwp *l, const struct sunos32_sys_ioctl_args *uap, register_t *retval)
461 {
462 /* {
463 int fd;
464 netbsd32_u_long com;
465 netbsd32_caddr_t data;
466 } */
467 struct netbsd32_ioctl_args bsd_ua;
468 int error;
469
470 SCARG(&bsd_ua, fd) = SCARG(uap, fd);
471 SCARG(&bsd_ua, com) = SCARG(uap, com);
472 SCARG(&bsd_ua, data) = SCARG(uap, data);
473
474 switch (SCARG(uap, com)) {
475 case _IOR('t', 0, int):
476 SCARG(&bsd_ua, com) = TIOCGETD;
477 break;
478 case _IOW('t', 1, int):
479 {
480 int disc;
481
482 if ((error = copyin(SCARG_P32(uap, data), &disc,
483 sizeof disc)) != 0)
484 return error;
485
486 /* map SunOS NTTYDISC into our termios discipline */
487 if (disc == 2)
488 disc = 0;
489 /* all other disciplines are not supported by NetBSD */
490 if (disc)
491 return ENXIO;
492
493 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCSETD, &disc, l);
494 }
495 case _IOW('t', 101, int): /* sun SUNOS_TIOCSSOFTCAR */
496 {
497 int x; /* unused */
498
499 return copyin(SCARG_P32(uap, data), &x, sizeof x);
500 }
501 case _IOR('t', 100, int): /* sun SUNOS_TIOCSSOFTCAR */
502 {
503 int x = 0;
504
505 return copyout(&x, SCARG_P32(uap, data), sizeof x);
506 }
507 case _IO('t', 36): /* sun TIOCCONS, no parameters */
508 {
509 int on = 1;
510 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCCONS, &on, l);
511 }
512 case _IOW('t', 37, struct sunos_ttysize):
513 {
514 struct winsize ws;
515 struct sunos_ttysize ss;
516
517 if ((error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGWINSZ, &ws, l)) != 0)
518 return (error);
519
520 if ((error = copyin(SCARG_P32(uap, data), &ss, sizeof (ss))) != 0)
521 return error;
522
523 ws.ws_row = ss.ts_row;
524 ws.ws_col = ss.ts_col;
525
526 return (sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCSWINSZ, &ws, l));
527 }
528 case _IOW('t', 38, struct sunos_ttysize):
529 {
530 struct winsize ws;
531 struct sunos_ttysize ss;
532
533 if ((error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGWINSZ, &ws, l)) != 0)
534 return (error);
535
536 ss.ts_row = ws.ws_row;
537 ss.ts_col = ws.ws_col;
538
539 return copyout(&ss, SCARG_P32(uap, data), sizeof (ss));
540 }
541 case _IOW('t', 130, int): /* TIOCSETPGRP: posix variant */
542 SCARG(&bsd_ua, com) = TIOCSPGRP;
543 break;
544 case _IOR('t', 131, int): /* TIOCGETPGRP: posix variant */
545 {
546 /*
547 * sigh, must do error translation on pty devices
548 * (see also kern/tty_pty.c)
549 */
550 int pgrp;
551 error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGPGRP, &pgrp, l);
552 if (error)
553 return (error);
554 return copyout(&pgrp, SCARG_P32(uap, data), sizeof(pgrp));
555 }
556 case _IO('t', 132):
557 SCARG(&bsd_ua, com) = TIOCSCTTY;
558 break;
559 case SUNOS_TCGETA:
560 case SUNOS_TCGETS:
561 {
562 struct termios bts;
563 struct sunos_termios sts;
564 struct sunos_termio st;
565
566 if ((error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGETA, &bts, l)) != 0)
567 return error;
568
569 btios2stios (&bts, &sts);
570 if (SCARG(uap, com) == SUNOS_TCGETA) {
571 stios2stio (&sts, &st);
572 return copyout(&st, SCARG_P32(uap, data),
573 sizeof (st));
574 } else
575 return copyout(&sts, SCARG_P32(uap, data),
576 sizeof (sts));
577 /*NOTREACHED*/
578 }
579 case SUNOS_TCSETA:
580 case SUNOS_TCSETAW:
581 case SUNOS_TCSETAF:
582 {
583 struct termios bts;
584 struct sunos_termios sts;
585 struct sunos_termio st;
586
587 if ((error = copyin(SCARG_P32(uap, data), &st,
588 sizeof (st))) != 0)
589 return error;
590
591 /* get full BSD termios so we don't lose information */
592 if ((error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGETA, &bts, l)) != 0)
593 return error;
594
595 /*
596 * convert to sun termios, copy in information from
597 * termio, and convert back, then set new values.
598 */
599 btios2stios(&bts, &sts);
600 stio2stios(&st, &sts);
601 stios2btios(&sts, &bts);
602
603 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), SCARG(uap, com) - SUNOS_TCSETA + TIOCSETA,
604 &bts, l);
605 }
606 case SUNOS_TCSETS:
607 case SUNOS_TCSETSW:
608 case SUNOS_TCSETSF:
609 {
610 struct termios bts;
611 struct sunos_termios sts;
612
613 if ((error = copyin(SCARG_P32(uap, data), &sts,
614 sizeof (sts))) != 0)
615 return error;
616 stios2btios (&sts, &bts);
617 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), SCARG(uap, com) - SUNOS_TCSETS + TIOCSETA,
618 &bts, l);
619 }
620 /*
621 * Pseudo-tty ioctl translations.
622 */
623 case _IOW('t', 32, int): { /* TIOCTCNTL */
624 int error1, on;
625
626 error1 = copyin(SCARG_P32(uap, data), &on, sizeof (on));
627 if (error1)
628 return error1;
629 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCUCNTL, &on, l);
630 }
631 case _IOW('t', 33, int): { /* TIOCSIGNAL */
632 int error1, sig;
633
634 error1 = copyin(SCARG_P32(uap, data), &sig, sizeof (sig));
635 if (error1)
636 return error1;
637 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCSIG, &sig, l);
638 }
639
640 /*
641 * Socket ioctl translations.
642 */
643 #define IFREQ_IN(a) { \
644 struct oifreq ifreq; \
645 error = copyin(SCARG_P32(uap, data), &ifreq, sizeof (ifreq)); \
646 if (error) \
647 return error; \
648 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), a, &ifreq, l); \
649 }
650 #define IFREQ_INOUT(a) { \
651 struct oifreq ifreq; \
652 error = copyin(SCARG_P32(uap, data), &ifreq, sizeof (ifreq)); \
653 if (error) \
654 return error; \
655 if ((error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), a, &ifreq, l)) != 0) \
656 return error; \
657 return copyout(&ifreq, SCARG_P32(uap, data), sizeof (ifreq)); \
658 }
659
660 case _IOW('i', 12, struct oifreq):
661 /* SIOCSIFADDR */
662 break;
663
664 case _IOWR('i', 13, struct oifreq):
665 IFREQ_INOUT(OOSIOCGIFADDR);
666
667 case _IOW('i', 14, struct oifreq):
668 /* SIOCSIFDSTADDR */
669 break;
670
671 case _IOWR('i', 15, struct oifreq):
672 IFREQ_INOUT(OOSIOCGIFDSTADDR);
673
674 case _IOW('i', 16, struct oifreq):
675 /* SIOCSIFFLAGS */
676 break;
677
678 case _IOWR('i', 17, struct oifreq):
679 /* SIOCGIFFLAGS */
680 break;
681
682 case _IOW('i', 21, struct oifreq):
683 IFREQ_IN(SIOCSIFMTU);
684
685 case _IOWR('i', 22, struct oifreq):
686 IFREQ_INOUT(SIOCGIFMTU);
687
688 case _IOWR('i', 23, struct oifreq):
689 IFREQ_INOUT(SIOCGIFBRDADDR);
690
691 case _IOW('i', 24, struct oifreq):
692 IFREQ_IN(SIOCSIFBRDADDR);
693
694 case _IOWR('i', 25, struct oifreq):
695 IFREQ_INOUT(OOSIOCGIFNETMASK);
696
697 case _IOW('i', 26, struct oifreq):
698 IFREQ_IN(SIOCSIFNETMASK);
699
700 case _IOWR('i', 27, struct oifreq):
701 IFREQ_INOUT(SIOCGIFMETRIC);
702
703 case _IOWR('i', 28, struct oifreq):
704 IFREQ_IN(SIOCSIFMETRIC);
705
706 case _IOW('i', 30, struct arpreq):
707 /* SIOCSARP */
708 break;
709
710 case _IOWR('i', 31, struct arpreq):
711 /* SIOCGARP */
712 break;
713
714 case _IOW('i', 32, struct arpreq):
715 /* SIOCDARP */
716 break;
717
718 case _IOW('i', 18, struct oifreq): /* SIOCSIFMEM */
719 case _IOWR('i', 19, struct oifreq): /* SIOCGIFMEM */
720 case _IOW('i', 40, struct oifreq): /* SIOCUPPER */
721 case _IOW('i', 41, struct oifreq): /* SIOCLOWER */
722 case _IOW('i', 44, struct oifreq): /* SIOCSETSYNC */
723 case _IOWR('i', 45, struct oifreq): /* SIOCGETSYNC */
724 case _IOWR('i', 46, struct oifreq): /* SIOCSDSTATS */
725 case _IOWR('i', 47, struct oifreq): /* SIOCSESTATS */
726 case _IOW('i', 48, int): /* SIOCSPROMISC */
727 case _IOW('i', 49, struct oifreq): /* SIOCADDMULTI */
728 case _IOW('i', 50, struct oifreq): /* SIOCDELMULTI */
729 return EOPNOTSUPP;
730
731 case _IOWR('i', 20, struct oifconf): /* SIOCGIFCONF */
732 {
733 struct oifconf ifcf;
734
735 /*
736 * XXX: two more problems
737 * 1. our sockaddr's are variable length, not always sizeof(sockaddr)
738 * 2. this returns a name per protocol, ie. it returns two "lo0"'s
739 */
740 error = copyin(SCARG_P32(uap, data), &ifcf,
741 sizeof (ifcf));
742 if (error)
743 return error;
744 error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), OOSIOCGIFCONF, &ifcf, l);
745 if (error)
746 return error;
747 return copyout(&ifcf, SCARG_P32(uap, data),
748 sizeof (ifcf));
749 }
750
751 /*
752 * Audio ioctl translations.
753 */
754 case _IOR('A', 1, struct sunos_audio_info): /* AUDIO_GETINFO */
755 sunos_au_getinfo:
756 {
757 struct audio_info aui;
758 struct sunos_audio_info sunos_aui;
759
760 error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), AUDIO_GETINFO, &aui, l);
761 if (error)
762 return error;
763
764 sunos_aui.play = *(struct sunos_audio_prinfo *)&aui.play;
765 sunos_aui.record = *(struct sunos_audio_prinfo *)&aui.record;
766
767 /* `avail_ports' is `seek' in BSD */
768 sunos_aui.play.avail_ports = AUDIO_SPEAKER | AUDIO_HEADPHONE;
769 sunos_aui.record.avail_ports = AUDIO_SPEAKER | AUDIO_HEADPHONE;
770
771 sunos_aui.play.waiting = 0;
772 sunos_aui.record.waiting = 0;
773 sunos_aui.play.eof = 0;
774 sunos_aui.record.eof = 0;
775 sunos_aui.monitor_gain = 0; /* aui.__spare; XXX */
776 /*XXXsunos_aui.output_muted = 0;*/
777 /*XXX*/sunos_aui.reserved[0] = 0;
778 /*XXX*/sunos_aui.reserved[1] = 0;
779 /*XXX*/sunos_aui.reserved[2] = 0;
780 /*XXX*/sunos_aui.reserved[3] = 0;
781
782 return copyout(&sunos_aui, SCARG_P32(uap, data),
783 sizeof (sunos_aui));
784 }
785
786 case _IOWR('A', 2, struct sunos_audio_info): /* AUDIO_SETINFO */
787 {
788 struct audio_info aui;
789 struct sunos_audio_info sunos_aui;
790
791 error = copyin(SCARG_P32(uap, data), &sunos_aui,
792 sizeof (sunos_aui));
793 if (error)
794 return error;
795
796 aui.play = *(struct audio_prinfo *)&sunos_aui.play;
797 aui.record = *(struct audio_prinfo *)&sunos_aui.record;
798 /* aui.__spare = sunos_aui.monitor_gain; */
799 aui.blocksize = ~0;
800 aui.hiwat = ~0;
801 aui.lowat = ~0;
802 /* XXX somebody check this please. - is: aui.backlog = ~0; */
803 aui.mode = ~0;
804 /*
805 * The bsd driver does not distinguish between paused and
806 * active. (In the sun driver, not active means samples are
807 * not output at all, but paused means the last streams buffer
808 * is drained and then output stops.) If either are 0, then
809 * when stop output. Otherwise, if either are non-zero,
810 * we resume.
811 */
812 if (sunos_aui.play.pause == 0 || sunos_aui.play.active == 0)
813 aui.play.pause = 0;
814 else if (sunos_aui.play.pause != (u_char)~0 ||
815 sunos_aui.play.active != (u_char)~0)
816 aui.play.pause = 1;
817 if (sunos_aui.record.pause == 0 || sunos_aui.record.active == 0)
818 aui.record.pause = 0;
819 else if (sunos_aui.record.pause != (u_char)~0 ||
820 sunos_aui.record.active != (u_char)~0)
821 aui.record.pause = 1;
822
823 error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), AUDIO_SETINFO, &aui, l);
824 if (error)
825 return error;
826 /* Return new state */
827 goto sunos_au_getinfo;
828 }
829 case _IO('A', 3): /* AUDIO_DRAIN */
830 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), AUDIO_DRAIN, NULL, l);
831 case _IOR('A', 4, int): /* AUDIO_GETDEV */
832 {
833 int devtype = SUNOS_AUDIO_DEV_AMD;
834 return copyout(&devtype, SCARG_P32(uap, data),
835 sizeof (devtype));
836 }
837
838 /*
839 * Selected streams ioctls.
840 */
841 #define SUNOS_S_FLUSHR 1
842 #define SUNOS_S_FLUSHW 2
843 #define SUNOS_S_FLUSHRW 3
844
845 #define SUNOS_S_INPUT 1
846 #define SUNOS_S_HIPRI 2
847 #define SUNOS_S_OUTPUT 4
848 #define SUNOS_S_MSG 8
849
850 case _IO('S', 5): /* I_FLUSH */
851 {
852 int tmp = 0;
853 switch ((intptr_t)SCARG_P32(uap, data)) {
854 case SUNOS_S_FLUSHR: tmp = FREAD;
855 case SUNOS_S_FLUSHW: tmp = FWRITE;
856 case SUNOS_S_FLUSHRW: tmp = FREAD|FWRITE;
857 }
858 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCFLUSH, &tmp, l);
859 }
860 case _IO('S', 9): /* I_SETSIG */
861 {
862 int on = 1;
863 if (((intptr_t)SCARG_P32(uap, data) &
864 (SUNOS_S_HIPRI|SUNOS_S_INPUT)) ==
865 SUNOS_S_HIPRI)
866 return EOPNOTSUPP;
867 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), FIOASYNC, &on, l);
868 }
869 /*
870 * SunOS disk ioctls, taken from arch/sparc/sparc/disksubr.c
871 * (which was from the old sparc/scsi/sun_disklabel.c), and
872 * modified to suite.
873 */
874 case DKIOCGGEOM:
875 {
876 struct disklabel dl;
877
878 error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), DIOCGDINFO, &dl, l);
879 if (error)
880 return (error);
881
882 #define datageom ((struct sun_dkgeom *)SCARG_P32(uap, data))
883 /* XXX can't do memset() on a user address (dsl) */
884 memset(SCARG_P32(uap, data), 0, sizeof(*datageom));
885
886 datageom->sdkc_ncylinders = dl.d_ncylinders;
887 datageom->sdkc_acylinders = dl.d_acylinders;
888 datageom->sdkc_ntracks = dl.d_ntracks;
889 datageom->sdkc_nsectors = dl.d_nsectors;
890 datageom->sdkc_interleave = dl.d_interleave;
891 datageom->sdkc_sparespercyl = dl.d_sparespercyl;
892 datageom->sdkc_rpm = dl.d_rpm;
893 datageom->sdkc_pcylinders = dl.d_ncylinders + dl.d_acylinders;
894 #undef datageom
895 break;
896 }
897
898 case DKIOCINFO:
899 /* Homey don't do DKIOCINFO */
900 /* XXX can't do memset() on a user address (dsl) */
901 memset(SCARG_P32(uap, data), 0, sizeof(struct sun_dkctlr));
902 break;
903
904 case DKIOCGPART:
905 {
906 struct partinfo pi;
907
908 error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), DIOCGPART, &pi, l);
909 if (error)
910 return (error);
911
912 if (pi.disklab->d_secpercyl == 0)
913 return (ERANGE); /* XXX */
914 if (pi.part->p_offset % pi.disklab->d_secpercyl != 0)
915 return (ERANGE); /* XXX */
916 /* XXX can't do direct writes to a user address (dsl) */
917 #define datapart ((struct sun_dkpart *)SCARG_P32(uap, data))
918 datapart->sdkp_cyloffset = pi.part->p_offset / pi.disklab->d_secpercyl;
919 datapart->sdkp_nsectors = pi.part->p_size;
920 #undef datapart
921 }
922
923 }
924 return (netbsd32_ioctl(l, &bsd_ua, retval));
925 }
926
927 /* SunOS fcntl(2) cmds not implemented */
928 #define SUN_F_RGETLK 10
929 #define SUN_F_RSETLK 11
930 #define SUN_F_CNVT 12
931 #define SUN_F_RSETLKW 13
932
933 /* SunOS flock translation */
934 struct sunos_flock {
935 short l_type;
936 short l_whence;
937 netbsd32_long l_start;
938 netbsd32_long l_len;
939 short l_pid;
940 short l_xxx;
941 };
942
943 static void bsd_to_sunos_flock(struct flock *, struct sunos_flock *);
944 static void sunos_to_bsd_flock(struct sunos_flock *, struct flock *);
945
946 #define SUNOS_F_RDLCK 1
947 #define SUNOS_F_WRLCK 2
948 #define SUNOS_F_UNLCK 3
949
950 static void
951 bsd_to_sunos_flock(struct flock *iflp, struct sunos_flock *oflp)
952 {
953 switch (iflp->l_type) {
954 case F_RDLCK:
955 oflp->l_type = SUNOS_F_RDLCK;
956 break;
957 case F_WRLCK:
958 oflp->l_type = SUNOS_F_WRLCK;
959 break;
960 case F_UNLCK:
961 oflp->l_type = SUNOS_F_UNLCK;
962 break;
963 default:
964 oflp->l_type = -1;
965 break;
966 }
967
968 oflp->l_whence = (short) iflp->l_whence;
969 oflp->l_start = (netbsd32_long) iflp->l_start;
970 oflp->l_len = (netbsd32_long) iflp->l_len;
971 oflp->l_pid = (short) iflp->l_pid;
972 oflp->l_xxx = 0;
973 }
974
975
976 static void
977 sunos_to_bsd_flock(struct sunos_flock *iflp, struct flock *oflp)
978 {
979 switch (iflp->l_type) {
980 case SUNOS_F_RDLCK:
981 oflp->l_type = F_RDLCK;
982 break;
983 case SUNOS_F_WRLCK:
984 oflp->l_type = F_WRLCK;
985 break;
986 case SUNOS_F_UNLCK:
987 oflp->l_type = F_UNLCK;
988 break;
989 default:
990 oflp->l_type = -1;
991 break;
992 }
993
994 oflp->l_whence = iflp->l_whence;
995 oflp->l_start = (off_t) iflp->l_start;
996 oflp->l_len = (off_t) iflp->l_len;
997 oflp->l_pid = (pid_t) iflp->l_pid;
998
999 }
1000 static struct {
1001 netbsd32_long sun_flg;
1002 netbsd32_long bsd_flg;
1003 } sunfcntl_flgtab[] = {
1004 /* F_[GS]ETFLags that differ: */
1005 #define SUN_FSETBLK 0x0010
1006 #define SUN_SHLOCK 0x0080
1007 #define SUN_EXLOCK 0x0100
1008 #define SUN_FNBIO 0x1000
1009 #define SUN_FSYNC 0x2000
1010 #define SUN_NONBLOCK 0x4000
1011 #define SUN_FNOCTTY 0x8000
1012 { SUN_NONBLOCK, O_NONBLOCK },
1013 { SUN_FNBIO, O_NONBLOCK },
1014 { SUN_SHLOCK, O_SHLOCK },
1015 { SUN_EXLOCK, O_EXLOCK },
1016 { SUN_FSYNC, O_FSYNC },
1017 { SUN_FSETBLK, 0 },
1018 { SUN_FNOCTTY, 0 }
1019 };
1020
1021 int
1022 sunos32_sys_fcntl(struct lwp *l, const struct sunos32_sys_fcntl_args *uap, register_t *retval)
1023 {
1024 /* {
1025 syscallarg(int) fd;
1026 syscallarg(int) cmd;
1027 syscallarg(netbsd32_voidp) arg;
1028 } */
1029 struct sys_fcntl_args bsd_ua;
1030 uintptr_t flg;
1031 int n, ret;
1032
1033 SCARG(&bsd_ua, fd) = SCARG(uap, fd);
1034 SCARG(&bsd_ua, cmd) = SCARG(uap, cmd);
1035 SCARG(&bsd_ua, arg) = SCARG_P32(uap, arg);
1036
1037 switch (SCARG(uap, cmd)) {
1038 case F_SETFL:
1039 flg = (intptr_t)SCARG_P32(uap, arg);
1040 n = sizeof(sunfcntl_flgtab) / sizeof(sunfcntl_flgtab[0]);
1041 while (--n >= 0) {
1042 if (flg & sunfcntl_flgtab[n].sun_flg) {
1043 flg &= ~sunfcntl_flgtab[n].sun_flg;
1044 flg |= sunfcntl_flgtab[n].bsd_flg;
1045 }
1046 }
1047 SCARG(&bsd_ua, arg) = (void *)flg;
1048 break;
1049
1050 case F_GETLK:
1051 case F_SETLK:
1052 case F_SETLKW:
1053 {
1054 int error;
1055 struct sunos_flock ifl;
1056 struct flock fl;
1057
1058 error = copyin(SCARG_P32(uap, arg), &ifl, sizeof ifl);
1059 if (error)
1060 return error;
1061 sunos_to_bsd_flock(&ifl, &fl);
1062
1063 error = do_fcntl_lock(l, SCARG(uap, fd), SCARG(uap, cmd), &fl);
1064 if (error || SCARG(uap, cmd) != F_GETLK)
1065 return error;
1066
1067 bsd_to_sunos_flock(&fl, &ifl);
1068 return copyout(&ifl, SCARG_P32(uap, arg), sizeof ifl);
1069 }
1070 break;
1071 case SUN_F_RGETLK:
1072 case SUN_F_RSETLK:
1073 case SUN_F_CNVT:
1074 case SUN_F_RSETLKW:
1075 return (EOPNOTSUPP);
1076 }
1077
1078 ret = sys_fcntl(l, &bsd_ua, retval);
1079 if (ret != 0)
1080 return ret;
1081
1082 switch (SCARG(uap, cmd)) {
1083 case F_GETFL:
1084 n = sizeof(sunfcntl_flgtab) / sizeof(sunfcntl_flgtab[0]);
1085 ret = *retval;
1086 while (--n >= 0) {
1087 if (ret & sunfcntl_flgtab[n].bsd_flg) {
1088 ret &= ~sunfcntl_flgtab[n].bsd_flg;
1089 ret |= sunfcntl_flgtab[n].sun_flg;
1090 }
1091 }
1092 *retval = ret;
1093 break;
1094 }
1095
1096 return 0;
1097 }
1098