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