1 /* $NetBSD: sunos32_ioctl.c,v 1.34 2015/12/11 08:10:43 mlelstv 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 2015/12/11 08:10:43 mlelstv 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, register_t *retval) 456 { 457 /* { 458 int fd; 459 netbsd32_u_long com; 460 netbsd32_caddr_t data; 461 } */ 462 struct netbsd32_ioctl_args bsd_ua; 463 int error; 464 465 SCARG(&bsd_ua, fd) = SCARG(uap, fd); 466 SCARG(&bsd_ua, com) = SCARG(uap, com); 467 SCARG(&bsd_ua, data) = SCARG(uap, data); 468 469 switch (SCARG(uap, com)) { 470 case _IOR('t', 0, int): 471 SCARG(&bsd_ua, com) = TIOCGETD; 472 break; 473 case _IOW('t', 1, int): 474 { 475 int disc; 476 477 if ((error = copyin(SCARG_P32(uap, data), &disc, 478 sizeof disc)) != 0) 479 return error; 480 481 /* map SunOS NTTYDISC into our termios discipline */ 482 if (disc == 2) 483 disc = 0; 484 /* all other disciplines are not supported by NetBSD */ 485 if (disc) 486 return ENXIO; 487 488 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCSETD, &disc, l); 489 } 490 case _IOW('t', 101, int): /* sun SUNOS_TIOCSSOFTCAR */ 491 { 492 int x; /* unused */ 493 494 return copyin(SCARG_P32(uap, data), &x, sizeof x); 495 } 496 case _IOR('t', 100, int): /* sun SUNOS_TIOCSSOFTCAR */ 497 { 498 int x = 0; 499 500 return copyout(&x, SCARG_P32(uap, data), sizeof x); 501 } 502 case _IO('t', 36): /* sun TIOCCONS, no parameters */ 503 { 504 int on = 1; 505 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCCONS, &on, l); 506 } 507 case _IOW('t', 37, struct sunos_ttysize): 508 { 509 struct winsize ws; 510 struct sunos_ttysize ss; 511 512 if ((error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGWINSZ, &ws, l)) != 0) 513 return (error); 514 515 if ((error = copyin(SCARG_P32(uap, data), &ss, sizeof (ss))) != 0) 516 return error; 517 518 ws.ws_row = ss.ts_row; 519 ws.ws_col = ss.ts_col; 520 521 return (sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCSWINSZ, &ws, l)); 522 } 523 case _IOW('t', 38, struct sunos_ttysize): 524 { 525 struct winsize ws; 526 struct sunos_ttysize ss; 527 528 if ((error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGWINSZ, &ws, l)) != 0) 529 return (error); 530 531 ss.ts_row = ws.ws_row; 532 ss.ts_col = ws.ws_col; 533 534 return copyout(&ss, SCARG_P32(uap, data), sizeof (ss)); 535 } 536 case _IOW('t', 130, int): /* TIOCSETPGRP: posix variant */ 537 SCARG(&bsd_ua, com) = TIOCSPGRP; 538 break; 539 case _IOR('t', 131, int): /* TIOCGETPGRP: posix variant */ 540 { 541 /* 542 * sigh, must do error translation on pty devices 543 * (see also kern/tty_pty.c) 544 */ 545 int pgrp; 546 error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGPGRP, &pgrp, l); 547 if (error) 548 return (error); 549 return copyout(&pgrp, SCARG_P32(uap, data), sizeof(pgrp)); 550 } 551 case _IO('t', 132): 552 SCARG(&bsd_ua, com) = TIOCSCTTY; 553 break; 554 case SUNOS_TCGETA: 555 case SUNOS_TCGETS: 556 { 557 struct termios bts; 558 struct sunos_termios sts; 559 struct sunos_termio st; 560 561 if ((error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGETA, &bts, l)) != 0) 562 return error; 563 564 btios2stios (&bts, &sts); 565 if (SCARG(uap, com) == SUNOS_TCGETA) { 566 stios2stio (&sts, &st); 567 return copyout(&st, SCARG_P32(uap, data), 568 sizeof (st)); 569 } else 570 return copyout(&sts, SCARG_P32(uap, data), 571 sizeof (sts)); 572 /*NOTREACHED*/ 573 } 574 case SUNOS_TCSETA: 575 case SUNOS_TCSETAW: 576 case SUNOS_TCSETAF: 577 { 578 struct termios bts; 579 struct sunos_termios sts; 580 struct sunos_termio st; 581 582 if ((error = copyin(SCARG_P32(uap, data), &st, 583 sizeof (st))) != 0) 584 return error; 585 586 /* get full BSD termios so we don't lose information */ 587 if ((error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCGETA, &bts, l)) != 0) 588 return error; 589 590 /* 591 * convert to sun termios, copy in information from 592 * termio, and convert back, then set new values. 593 */ 594 btios2stios(&bts, &sts); 595 stio2stios(&st, &sts); 596 stios2btios(&sts, &bts); 597 598 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), SCARG(uap, com) - SUNOS_TCSETA + TIOCSETA, 599 &bts, l); 600 } 601 case SUNOS_TCSETS: 602 case SUNOS_TCSETSW: 603 case SUNOS_TCSETSF: 604 { 605 struct termios bts; 606 struct sunos_termios sts; 607 608 if ((error = copyin(SCARG_P32(uap, data), &sts, 609 sizeof (sts))) != 0) 610 return error; 611 stios2btios (&sts, &bts); 612 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), SCARG(uap, com) - SUNOS_TCSETS + TIOCSETA, 613 &bts, l); 614 } 615 /* 616 * Pseudo-tty ioctl translations. 617 */ 618 case _IOW('t', 32, int): { /* TIOCTCNTL */ 619 int error1, on; 620 621 error1 = copyin(SCARG_P32(uap, data), &on, sizeof (on)); 622 if (error1) 623 return error1; 624 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCUCNTL, &on, l); 625 } 626 case _IOW('t', 33, int): { /* TIOCSIGNAL */ 627 int error1, sig; 628 629 error1 = copyin(SCARG_P32(uap, data), &sig, sizeof (sig)); 630 if (error1) 631 return error1; 632 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCSIG, &sig, l); 633 } 634 635 /* 636 * Socket ioctl translations. 637 */ 638 #define IFREQ_IN(a) { \ 639 struct oifreq ifreq; \ 640 error = copyin(SCARG_P32(uap, data), &ifreq, sizeof (ifreq)); \ 641 if (error) \ 642 return error; \ 643 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), a, &ifreq, l); \ 644 } 645 #define IFREQ_INOUT(a) { \ 646 struct oifreq ifreq; \ 647 error = copyin(SCARG_P32(uap, data), &ifreq, sizeof (ifreq)); \ 648 if (error) \ 649 return error; \ 650 if ((error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), a, &ifreq, l)) != 0) \ 651 return error; \ 652 return copyout(&ifreq, SCARG_P32(uap, data), sizeof (ifreq)); \ 653 } 654 655 case _IOW('i', 12, struct oifreq): 656 /* SIOCSIFADDR */ 657 break; 658 659 case _IOWR('i', 13, struct oifreq): 660 IFREQ_INOUT(OOSIOCGIFADDR); 661 662 case _IOW('i', 14, struct oifreq): 663 /* SIOCSIFDSTADDR */ 664 break; 665 666 case _IOWR('i', 15, struct oifreq): 667 IFREQ_INOUT(OOSIOCGIFDSTADDR); 668 669 case _IOW('i', 16, struct oifreq): 670 /* SIOCSIFFLAGS */ 671 break; 672 673 case _IOWR('i', 17, struct oifreq): 674 /* SIOCGIFFLAGS */ 675 break; 676 677 case _IOW('i', 21, struct oifreq): 678 IFREQ_IN(SIOCSIFMTU); 679 680 case _IOWR('i', 22, struct oifreq): 681 IFREQ_INOUT(SIOCGIFMTU); 682 683 case _IOWR('i', 23, struct oifreq): 684 IFREQ_INOUT(SIOCGIFBRDADDR); 685 686 case _IOW('i', 24, struct oifreq): 687 IFREQ_IN(SIOCSIFBRDADDR); 688 689 case _IOWR('i', 25, struct oifreq): 690 IFREQ_INOUT(OOSIOCGIFNETMASK); 691 692 case _IOW('i', 26, struct oifreq): 693 IFREQ_IN(SIOCSIFNETMASK); 694 695 case _IOWR('i', 27, struct oifreq): 696 IFREQ_INOUT(SIOCGIFMETRIC); 697 698 case _IOWR('i', 28, struct oifreq): 699 IFREQ_IN(SIOCSIFMETRIC); 700 701 case _IOW('i', 30, struct arpreq): 702 /* SIOCSARP */ 703 break; 704 705 case _IOWR('i', 31, struct arpreq): 706 /* SIOCGARP */ 707 break; 708 709 case _IOW('i', 32, struct arpreq): 710 /* SIOCDARP */ 711 break; 712 713 case _IOW('i', 18, struct oifreq): /* SIOCSIFMEM */ 714 case _IOWR('i', 19, struct oifreq): /* SIOCGIFMEM */ 715 case _IOW('i', 40, struct oifreq): /* SIOCUPPER */ 716 case _IOW('i', 41, struct oifreq): /* SIOCLOWER */ 717 case _IOW('i', 44, struct oifreq): /* SIOCSETSYNC */ 718 case _IOWR('i', 45, struct oifreq): /* SIOCGETSYNC */ 719 case _IOWR('i', 46, struct oifreq): /* SIOCSDSTATS */ 720 case _IOWR('i', 47, struct oifreq): /* SIOCSESTATS */ 721 case _IOW('i', 48, int): /* SIOCSPROMISC */ 722 case _IOW('i', 49, struct oifreq): /* SIOCADDMULTI */ 723 case _IOW('i', 50, struct oifreq): /* SIOCDELMULTI */ 724 return EOPNOTSUPP; 725 726 case _IOWR('i', 20, struct oifconf): /* SIOCGIFCONF */ 727 { 728 struct oifconf ifcf; 729 730 /* 731 * XXX: two more problems 732 * 1. our sockaddr's are variable length, not always sizeof(sockaddr) 733 * 2. this returns a name per protocol, ie. it returns two "lo0"'s 734 */ 735 error = copyin(SCARG_P32(uap, data), &ifcf, 736 sizeof (ifcf)); 737 if (error) 738 return error; 739 error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), OOSIOCGIFCONF, &ifcf, l); 740 if (error) 741 return error; 742 return copyout(&ifcf, SCARG_P32(uap, data), 743 sizeof (ifcf)); 744 } 745 746 /* 747 * Audio ioctl translations. 748 */ 749 case _IOR('A', 1, struct sunos_audio_info): /* AUDIO_GETINFO */ 750 sunos_au_getinfo: 751 { 752 struct audio_info aui; 753 struct sunos_audio_info sunos_aui; 754 755 error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), AUDIO_GETINFO, &aui, l); 756 if (error) 757 return error; 758 759 sunos_aui.play = *(struct sunos_audio_prinfo *)&aui.play; 760 sunos_aui.record = *(struct sunos_audio_prinfo *)&aui.record; 761 762 /* `avail_ports' is `seek' in BSD */ 763 sunos_aui.play.avail_ports = AUDIO_SPEAKER | AUDIO_HEADPHONE; 764 sunos_aui.record.avail_ports = AUDIO_SPEAKER | AUDIO_HEADPHONE; 765 766 sunos_aui.play.waiting = 0; 767 sunos_aui.record.waiting = 0; 768 sunos_aui.play.eof = 0; 769 sunos_aui.record.eof = 0; 770 sunos_aui.monitor_gain = 0; /* aui.__spare; XXX */ 771 /*XXXsunos_aui.output_muted = 0;*/ 772 /*XXX*/sunos_aui.reserved[0] = 0; 773 /*XXX*/sunos_aui.reserved[1] = 0; 774 /*XXX*/sunos_aui.reserved[2] = 0; 775 /*XXX*/sunos_aui.reserved[3] = 0; 776 777 return copyout(&sunos_aui, SCARG_P32(uap, data), 778 sizeof (sunos_aui)); 779 } 780 781 case _IOWR('A', 2, struct sunos_audio_info): /* AUDIO_SETINFO */ 782 { 783 struct audio_info aui; 784 struct sunos_audio_info sunos_aui; 785 786 error = copyin(SCARG_P32(uap, data), &sunos_aui, 787 sizeof (sunos_aui)); 788 if (error) 789 return error; 790 791 aui.play = *(struct audio_prinfo *)&sunos_aui.play; 792 aui.record = *(struct audio_prinfo *)&sunos_aui.record; 793 /* aui.__spare = sunos_aui.monitor_gain; */ 794 aui.blocksize = ~0; 795 aui.hiwat = ~0; 796 aui.lowat = ~0; 797 /* XXX somebody check this please. - is: aui.backlog = ~0; */ 798 aui.mode = ~0; 799 /* 800 * The bsd driver does not distinguish between paused and 801 * active. (In the sun driver, not active means samples are 802 * not output at all, but paused means the last streams buffer 803 * is drained and then output stops.) If either are 0, then 804 * when stop output. Otherwise, if either are non-zero, 805 * we resume. 806 */ 807 if (sunos_aui.play.pause == 0 || sunos_aui.play.active == 0) 808 aui.play.pause = 0; 809 else if (sunos_aui.play.pause != (u_char)~0 || 810 sunos_aui.play.active != (u_char)~0) 811 aui.play.pause = 1; 812 if (sunos_aui.record.pause == 0 || sunos_aui.record.active == 0) 813 aui.record.pause = 0; 814 else if (sunos_aui.record.pause != (u_char)~0 || 815 sunos_aui.record.active != (u_char)~0) 816 aui.record.pause = 1; 817 818 error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), AUDIO_SETINFO, &aui, l); 819 if (error) 820 return error; 821 /* Return new state */ 822 goto sunos_au_getinfo; 823 } 824 case _IO('A', 3): /* AUDIO_DRAIN */ 825 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), AUDIO_DRAIN, NULL, l); 826 case _IOR('A', 4, int): /* AUDIO_GETDEV */ 827 { 828 int devtype = SUNOS_AUDIO_DEV_AMD; 829 return copyout(&devtype, SCARG_P32(uap, data), 830 sizeof (devtype)); 831 } 832 833 /* 834 * Selected streams ioctls. 835 */ 836 #define SUNOS_S_FLUSHR 1 837 #define SUNOS_S_FLUSHW 2 838 #define SUNOS_S_FLUSHRW 3 839 840 #define SUNOS_S_INPUT 1 841 #define SUNOS_S_HIPRI 2 842 #define SUNOS_S_OUTPUT 4 843 #define SUNOS_S_MSG 8 844 845 case _IO('S', 5): /* I_FLUSH */ 846 { 847 int tmp = 0; 848 switch ((intptr_t)SCARG_P32(uap, data)) { 849 case SUNOS_S_FLUSHR: tmp = FREAD; break; 850 case SUNOS_S_FLUSHW: tmp = FWRITE; break; 851 case SUNOS_S_FLUSHRW: tmp = FREAD|FWRITE; break; 852 } 853 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), TIOCFLUSH, &tmp, l); 854 } 855 case _IO('S', 9): /* I_SETSIG */ 856 { 857 int on = 1; 858 if (((intptr_t)SCARG_P32(uap, data) & 859 (SUNOS_S_HIPRI|SUNOS_S_INPUT)) == 860 SUNOS_S_HIPRI) 861 return EOPNOTSUPP; 862 return sunos32_do_ioctl(SCARG(&bsd_ua, fd), FIOASYNC, &on, l); 863 } 864 /* 865 * SunOS disk ioctls, taken from arch/sparc/sparc/disksubr.c 866 * (which was from the old sparc/scsi/sun_disklabel.c), and 867 * modified to suite. 868 */ 869 case SUN_DKIOCGGEOM: 870 { 871 struct disklabel dl; 872 873 error = sunos32_do_ioctl(SCARG(&bsd_ua, fd), DIOCGDINFO, &dl, l); 874 if (error) 875 return (error); 876 877 #define datageom ((struct sun_dkgeom *)SCARG_P32(uap, data)) 878 /* XXX can't do memset() on a user address (dsl) */ 879 memset(SCARG_P32(uap, data), 0, sizeof(*datageom)); 880 881 datageom->sdkc_ncylinders = dl.d_ncylinders; 882 datageom->sdkc_acylinders = dl.d_acylinders; 883 datageom->sdkc_ntracks = dl.d_ntracks; 884 datageom->sdkc_nsectors = dl.d_nsectors; 885 datageom->sdkc_interleave = dl.d_interleave; 886 datageom->sdkc_sparespercyl = dl.d_sparespercyl; 887 datageom->sdkc_rpm = dl.d_rpm; 888 datageom->sdkc_pcylinders = dl.d_ncylinders + dl.d_acylinders; 889 #undef datageom 890 break; 891 } 892 893 case SUN_DKIOCINFO: 894 /* Homey don't do DKIOCINFO */ 895 /* XXX can't do memset() on a user address (dsl) */ 896 memset(SCARG_P32(uap, data), 0, sizeof(struct sun_dkctlr)); 897 break; 898 899 case SUN_DKIOCGPART: 900 { 901 struct partinfo pi; 902 struct disklabel label; 903 int fd = SCARG(&bsd_ua, fd); 904 905 error = sunos32_do_ioctl(fd, DIOCGPARTINFO, &pi, l); 906 if (error) 907 return error; 908 error = sunos32_do_ioctl(fd, DIOCGDINFO, &label, l); 909 if (error) 910 return error; 911 912 if (label.d_secpercyl == 0) 913 return ERANGE; /* XXX */ 914 if (pi.pi_offset % label.d_secpercyl != 0) 915 return ERANGE; /* XXX */ 916 /* XXX can't do direct writes to a user address (dsl) */ 917 #define datapart ((struct sun_dkpart *)SCARG_P32(uap, data)) 918 datapart->sdkp_cyloffset = pi.pi_offset / label.d_secpercyl; 919 datapart->sdkp_nsectors = pi.pi_size; 920 #undef datapart 921 } 922 923 } 924 return (netbsd32_ioctl(l, &bsd_ua, retval)); 925 } 926 927 /* SunOS fcntl(2) cmds not implemented */ 928 #define SUN_F_RGETLK 10 929 #define SUN_F_RSETLK 11 930 #define SUN_F_CNVT 12 931 #define SUN_F_RSETLKW 13 932 933 /* SunOS flock translation */ 934 struct sunos_flock { 935 short l_type; 936 short l_whence; 937 netbsd32_long l_start; 938 netbsd32_long l_len; 939 short l_pid; 940 short l_xxx; 941 }; 942 943 static void bsd_to_sunos_flock(struct flock *, struct sunos_flock *); 944 static void sunos_to_bsd_flock(struct sunos_flock *, struct flock *); 945 946 #define SUNOS_F_RDLCK 1 947 #define SUNOS_F_WRLCK 2 948 #define SUNOS_F_UNLCK 3 949 950 static void 951 bsd_to_sunos_flock(struct flock *iflp, struct sunos_flock *oflp) 952 { 953 switch (iflp->l_type) { 954 case F_RDLCK: 955 oflp->l_type = SUNOS_F_RDLCK; 956 break; 957 case F_WRLCK: 958 oflp->l_type = SUNOS_F_WRLCK; 959 break; 960 case F_UNLCK: 961 oflp->l_type = SUNOS_F_UNLCK; 962 break; 963 default: 964 oflp->l_type = -1; 965 break; 966 } 967 968 oflp->l_whence = (short) iflp->l_whence; 969 oflp->l_start = (netbsd32_long) iflp->l_start; 970 oflp->l_len = (netbsd32_long) iflp->l_len; 971 oflp->l_pid = (short) iflp->l_pid; 972 oflp->l_xxx = 0; 973 } 974 975 976 static void 977 sunos_to_bsd_flock(struct sunos_flock *iflp, struct flock *oflp) 978 { 979 switch (iflp->l_type) { 980 case SUNOS_F_RDLCK: 981 oflp->l_type = F_RDLCK; 982 break; 983 case SUNOS_F_WRLCK: 984 oflp->l_type = F_WRLCK; 985 break; 986 case SUNOS_F_UNLCK: 987 oflp->l_type = F_UNLCK; 988 break; 989 default: 990 oflp->l_type = -1; 991 break; 992 } 993 994 oflp->l_whence = iflp->l_whence; 995 oflp->l_start = (off_t) iflp->l_start; 996 oflp->l_len = (off_t) iflp->l_len; 997 oflp->l_pid = (pid_t) iflp->l_pid; 998 999 } 1000 static struct { 1001 netbsd32_long sun_flg; 1002 netbsd32_long bsd_flg; 1003 } sunfcntl_flgtab[] = { 1004 /* F_[GS]ETFLags that differ: */ 1005 #define SUN_FSETBLK 0x0010 1006 #define SUN_SHLOCK 0x0080 1007 #define SUN_EXLOCK 0x0100 1008 #define SUN_FNBIO 0x1000 1009 #define SUN_FSYNC 0x2000 1010 #define SUN_NONBLOCK 0x4000 1011 #define SUN_FNOCTTY 0x8000 1012 { SUN_NONBLOCK, O_NONBLOCK }, 1013 { SUN_FNBIO, O_NONBLOCK }, 1014 { SUN_SHLOCK, O_SHLOCK }, 1015 { SUN_EXLOCK, O_EXLOCK }, 1016 { SUN_FSYNC, O_FSYNC }, 1017 { SUN_FSETBLK, 0 }, 1018 { SUN_FNOCTTY, 0 } 1019 }; 1020 1021 int 1022 sunos32_sys_fcntl(struct lwp *l, const struct sunos32_sys_fcntl_args *uap, register_t *retval) 1023 { 1024 /* { 1025 syscallarg(int) fd; 1026 syscallarg(int) cmd; 1027 syscallarg(netbsd32_voidp) arg; 1028 } */ 1029 struct sys_fcntl_args bsd_ua; 1030 uintptr_t flg; 1031 int n, ret; 1032 1033 SCARG(&bsd_ua, fd) = SCARG(uap, fd); 1034 SCARG(&bsd_ua, cmd) = SCARG(uap, cmd); 1035 SCARG(&bsd_ua, arg) = SCARG_P32(uap, arg); 1036 1037 switch (SCARG(uap, cmd)) { 1038 case F_SETFL: 1039 flg = (intptr_t)SCARG_P32(uap, arg); 1040 n = sizeof(sunfcntl_flgtab) / sizeof(sunfcntl_flgtab[0]); 1041 while (--n >= 0) { 1042 if (flg & sunfcntl_flgtab[n].sun_flg) { 1043 flg &= ~sunfcntl_flgtab[n].sun_flg; 1044 flg |= sunfcntl_flgtab[n].bsd_flg; 1045 } 1046 } 1047 SCARG(&bsd_ua, arg) = (void *)flg; 1048 break; 1049 1050 case F_GETLK: 1051 case F_SETLK: 1052 case F_SETLKW: 1053 { 1054 int error; 1055 struct sunos_flock ifl; 1056 struct flock fl; 1057 1058 error = copyin(SCARG_P32(uap, arg), &ifl, sizeof ifl); 1059 if (error) 1060 return error; 1061 sunos_to_bsd_flock(&ifl, &fl); 1062 1063 error = do_fcntl_lock(SCARG(uap, fd), SCARG(uap, cmd), &fl); 1064 if (error || SCARG(uap, cmd) != F_GETLK) 1065 return error; 1066 1067 bsd_to_sunos_flock(&fl, &ifl); 1068 return copyout(&ifl, SCARG_P32(uap, arg), sizeof ifl); 1069 } 1070 break; 1071 case SUN_F_RGETLK: 1072 case SUN_F_RSETLK: 1073 case SUN_F_CNVT: 1074 case SUN_F_RSETLKW: 1075 return (EOPNOTSUPP); 1076 } 1077 1078 ret = sys_fcntl(l, &bsd_ua, retval); 1079 if (ret != 0) 1080 return ret; 1081 1082 switch (SCARG(uap, cmd)) { 1083 case F_GETFL: 1084 n = sizeof(sunfcntl_flgtab) / sizeof(sunfcntl_flgtab[0]); 1085 ret = *retval; 1086 while (--n >= 0) { 1087 if (ret & sunfcntl_flgtab[n].bsd_flg) { 1088 ret &= ~sunfcntl_flgtab[n].bsd_flg; 1089 ret |= sunfcntl_flgtab[n].sun_flg; 1090 } 1091 } 1092 *retval = ret; 1093 break; 1094 } 1095 1096 return 0; 1097 } 1098