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