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