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