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