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