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