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