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