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