sunos32_ioctl.c revision 1.28 1 /* $NetBSD: sunos32_ioctl.c,v 1.28 2008/03/21 21:54:59 ad 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.28 2008/03/21 21:54:59 ad 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 file_t *fp;
437 struct vnode *vp;
438 int error;
439
440 if ((fp = fd_getfile(fd)) == NULL)
441 return EBADF;
442 if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
443 fd_putfile(fd);
444 return EBADF;
445 }
446 error = fp->f_ops->fo_ioctl(fp, cmd, arg);
447 if (error == EIO && cmd == TIOCGPGRP) {
448 vp = (struct vnode *)fp->f_data;
449 if (vp != NULL && vp->v_type == VCHR && major(vp->v_rdev) == 21)
450 error = ENOTTY;
451 }
452 fd_putfile(fd);
453 return error;
454 }
455
456 int
457 sunos32_sys_ioctl(struct lwp *l, const struct sunos32_sys_ioctl_args *uap, register_t *retval)
458 {
459 /* {
460 int fd;
461 netbsd32_u_long com;
462 netbsd32_caddr_t data;
463 } */
464 struct netbsd32_ioctl_args bsd_ua;
465 int error;
466
467 SCARG(&bsd_ua, fd) = SCARG(uap, fd);
468 SCARG(&bsd_ua, com) = SCARG(uap, com);
469 SCARG(&bsd_ua, data) = SCARG(uap, data);
470
471 switch (SCARG(uap, com)) {
472 case _IOR('t', 0, int):
473 SCARG(&bsd_ua, com) = TIOCGETD;
474 break;
475 case _IOW('t', 1, int):
476 {
477 int disc;
478
479 if ((error = copyin(SCARG_P32(uap, data), &disc,
480 sizeof disc)) != 0)
481 return error;
482
483 /* map SunOS NTTYDISC into our termios discipline */
484 if (disc == 2)
485 disc = 0;
486 /* all other disciplines are not supported by NetBSD */
487 if (disc)
488 return ENXIO;
489
490 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCSETD, &disc, l);
491 }
492 case _IOW('t', 101, int): /* sun SUNOS_TIOCSSOFTCAR */
493 {
494 int x; /* unused */
495
496 return copyin(SCARG_P32(uap, data), &x, sizeof x);
497 }
498 case _IOR('t', 100, int): /* sun SUNOS_TIOCSSOFTCAR */
499 {
500 int x = 0;
501
502 return copyout(&x, SCARG_P32(uap, data), sizeof x);
503 }
504 case _IO('t', 36): /* sun TIOCCONS, no parameters */
505 {
506 int on = 1;
507 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCCONS, &on, l);
508 }
509 case _IOW('t', 37, struct sunos_ttysize):
510 {
511 struct winsize ws;
512 struct sunos_ttysize ss;
513
514 if ((error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGWINSZ, &ws, l)) != 0)
515 return (error);
516
517 if ((error = copyin(SCARG_P32(uap, data), &ss, sizeof (ss))) != 0)
518 return error;
519
520 ws.ws_row = ss.ts_row;
521 ws.ws_col = ss.ts_col;
522
523 return (sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCSWINSZ, &ws, l));
524 }
525 case _IOW('t', 38, struct sunos_ttysize):
526 {
527 struct winsize ws;
528 struct sunos_ttysize ss;
529
530 if ((error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGWINSZ, &ws, l)) != 0)
531 return (error);
532
533 ss.ts_row = ws.ws_row;
534 ss.ts_col = ws.ws_col;
535
536 return copyout(&ss, SCARG_P32(uap, data), sizeof (ss));
537 }
538 case _IOW('t', 130, int): /* TIOCSETPGRP: posix variant */
539 SCARG(&bsd_ua, com) = TIOCSPGRP;
540 break;
541 case _IOR('t', 131, int): /* TIOCGETPGRP: posix variant */
542 {
543 /*
544 * sigh, must do error translation on pty devices
545 * (see also kern/tty_pty.c)
546 */
547 int pgrp;
548 error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGPGRP, &pgrp, l);
549 if (error)
550 return (error);
551 return copyout(&pgrp, SCARG_P32(uap, data), sizeof(pgrp));
552 }
553 case _IO('t', 132):
554 SCARG(&bsd_ua, 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 = sunos32_do_ioctl(SCARG(&bsd_ua, fd), 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 = sunos32_do_ioctl(SCARG(&bsd_ua, fd), 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 sunos32_do_ioctl(SCARG(&bsd_ua, fd), 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 sunos32_do_ioctl(SCARG(&bsd_ua, fd), 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 sunos32_do_ioctl(SCARG(&bsd_ua, fd), 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 sunos32_do_ioctl(SCARG(&bsd_ua, fd), 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 sunos32_do_ioctl(SCARG(&bsd_ua, fd), 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 = sunos32_do_ioctl(SCARG(&bsd_ua, fd), 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 = sunos32_do_ioctl(SCARG(&bsd_ua, fd), 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 = sunos32_do_ioctl(SCARG(&bsd_ua, fd), 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 = sunos32_do_ioctl(SCARG(&bsd_ua, fd), 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 sunos32_do_ioctl(SCARG(&bsd_ua, fd), 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 sunos32_do_ioctl(SCARG(&bsd_ua, fd), 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 sunos32_do_ioctl(SCARG(&bsd_ua, fd), 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 = sunos32_do_ioctl(SCARG(&bsd_ua, fd), 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 = sunos32_do_ioctl(SCARG(&bsd_ua, fd), 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, &bsd_ua, 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(struct flock *, struct sunos_flock *);
941 static void sunos_to_bsd_flock(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(struct flock *iflp, struct sunos_flock *oflp)
949 {
950 switch (iflp->l_type) {
951 case F_RDLCK:
952 oflp->l_type = SUNOS_F_RDLCK;
953 break;
954 case F_WRLCK:
955 oflp->l_type = SUNOS_F_WRLCK;
956 break;
957 case F_UNLCK:
958 oflp->l_type = SUNOS_F_UNLCK;
959 break;
960 default:
961 oflp->l_type = -1;
962 break;
963 }
964
965 oflp->l_whence = (short) iflp->l_whence;
966 oflp->l_start = (netbsd32_long) iflp->l_start;
967 oflp->l_len = (netbsd32_long) iflp->l_len;
968 oflp->l_pid = (short) iflp->l_pid;
969 oflp->l_xxx = 0;
970 }
971
972
973 static void
974 sunos_to_bsd_flock(struct sunos_flock *iflp, struct flock *oflp)
975 {
976 switch (iflp->l_type) {
977 case SUNOS_F_RDLCK:
978 oflp->l_type = F_RDLCK;
979 break;
980 case SUNOS_F_WRLCK:
981 oflp->l_type = F_WRLCK;
982 break;
983 case SUNOS_F_UNLCK:
984 oflp->l_type = F_UNLCK;
985 break;
986 default:
987 oflp->l_type = -1;
988 break;
989 }
990
991 oflp->l_whence = iflp->l_whence;
992 oflp->l_start = (off_t) iflp->l_start;
993 oflp->l_len = (off_t) iflp->l_len;
994 oflp->l_pid = (pid_t) iflp->l_pid;
995
996 }
997 static struct {
998 netbsd32_long sun_flg;
999 netbsd32_long bsd_flg;
1000 } sunfcntl_flgtab[] = {
1001 /* F_[GS]ETFLags that differ: */
1002 #define SUN_FSETBLK 0x0010
1003 #define SUN_SHLOCK 0x0080
1004 #define SUN_EXLOCK 0x0100
1005 #define SUN_FNBIO 0x1000
1006 #define SUN_FSYNC 0x2000
1007 #define SUN_NONBLOCK 0x4000
1008 #define SUN_FNOCTTY 0x8000
1009 { SUN_NONBLOCK, O_NONBLOCK },
1010 { SUN_FNBIO, O_NONBLOCK },
1011 { SUN_SHLOCK, O_SHLOCK },
1012 { SUN_EXLOCK, O_EXLOCK },
1013 { SUN_FSYNC, O_FSYNC },
1014 { SUN_FSETBLK, 0 },
1015 { SUN_FNOCTTY, 0 }
1016 };
1017
1018 int
1019 sunos32_sys_fcntl(struct lwp *l, const struct sunos32_sys_fcntl_args *uap, register_t *retval)
1020 {
1021 /* {
1022 syscallarg(int) fd;
1023 syscallarg(int) cmd;
1024 syscallarg(netbsd32_voidp) arg;
1025 } */
1026 struct sys_fcntl_args bsd_ua;
1027 uintptr_t flg;
1028 int n, ret;
1029
1030 SCARG(&bsd_ua, fd) = SCARG(uap, fd);
1031 SCARG(&bsd_ua, cmd) = SCARG(uap, cmd);
1032 SCARG(&bsd_ua, arg) = SCARG_P32(uap, arg);
1033
1034 switch (SCARG(uap, cmd)) {
1035 case F_SETFL:
1036 flg = (intptr_t)SCARG_P32(uap, arg);
1037 n = sizeof(sunfcntl_flgtab) / sizeof(sunfcntl_flgtab[0]);
1038 while (--n >= 0) {
1039 if (flg & sunfcntl_flgtab[n].sun_flg) {
1040 flg &= ~sunfcntl_flgtab[n].sun_flg;
1041 flg |= sunfcntl_flgtab[n].bsd_flg;
1042 }
1043 }
1044 SCARG(&bsd_ua, arg) = (void *)flg;
1045 break;
1046
1047 case F_GETLK:
1048 case F_SETLK:
1049 case F_SETLKW:
1050 {
1051 int error;
1052 struct sunos_flock ifl;
1053 struct flock fl;
1054
1055 error = copyin(SCARG_P32(uap, arg), &ifl, sizeof ifl);
1056 if (error)
1057 return error;
1058 sunos_to_bsd_flock(&ifl, &fl);
1059
1060 error = do_fcntl_lock(SCARG(uap, fd), SCARG(uap, cmd), &fl);
1061 if (error || SCARG(uap, cmd) != F_GETLK)
1062 return error;
1063
1064 bsd_to_sunos_flock(&fl, &ifl);
1065 return copyout(&ifl, SCARG_P32(uap, arg), sizeof ifl);
1066 }
1067 break;
1068 case SUN_F_RGETLK:
1069 case SUN_F_RSETLK:
1070 case SUN_F_CNVT:
1071 case SUN_F_RSETLKW:
1072 return (EOPNOTSUPP);
1073 }
1074
1075 ret = sys_fcntl(l, &bsd_ua, retval);
1076 if (ret != 0)
1077 return ret;
1078
1079 switch (SCARG(uap, cmd)) {
1080 case F_GETFL:
1081 n = sizeof(sunfcntl_flgtab) / sizeof(sunfcntl_flgtab[0]);
1082 ret = *retval;
1083 while (--n >= 0) {
1084 if (ret & sunfcntl_flgtab[n].bsd_flg) {
1085 ret &= ~sunfcntl_flgtab[n].bsd_flg;
1086 ret |= sunfcntl_flgtab[n].sun_flg;
1087 }
1088 }
1089 *retval = ret;
1090 break;
1091 }
1092
1093 return 0;
1094 }
1095