1 /* 2 * Copyright (c) 1994-1995 S�ren Schmidt 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer 10 * in this position and unchanged. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software withough specific prior written permission 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $Id: linux_ioctl.c,v 1.29 1998/09/30 01:42:53 jfieber Exp $ 29 */ 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/sysproto.h> 34 #include <sys/proc.h> 35 #include <sys/fcntl.h> 36 #include <sys/file.h> 37 #include <sys/filedesc.h> 38 #include <sys/filio.h> 39 #include <sys/tty.h> 40 #include <sys/socket.h> 41 #include <net/if.h> 42 #include <net/if_dl.h> 43 #include <net/if_types.h> 44 #include <sys/sockio.h> 45 46 #include <machine/soundcard.h> 47 #include <machine/console.h> 48 49 #include <i386/linux/linux.h> 50 #include <i386/linux/linux_proto.h> 51 52 #define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG) 53 54 struct linux_termio { 55 unsigned short c_iflag; 56 unsigned short c_oflag; 57 unsigned short c_cflag; 58 unsigned short c_lflag; 59 unsigned char c_line; 60 unsigned char c_cc[LINUX_NCC]; 61 }; 62 63 64 struct linux_termios { 65 unsigned long c_iflag; 66 unsigned long c_oflag; 67 unsigned long c_cflag; 68 unsigned long c_lflag; 69 unsigned char c_line; 70 unsigned char c_cc[LINUX_NCCS]; 71 }; 72 73 struct linux_winsize { 74 unsigned short ws_row, ws_col; 75 unsigned short ws_xpixel, ws_ypixel; 76 }; 77 78 static struct speedtab sptab[] = { 79 { 0, 0 }, { 50, 1 }, { 75, 2 }, { 110, 3 }, 80 { 134, 4 }, { 135, 4 }, { 150, 5 }, { 200, 6 }, 81 { 300, 7 }, { 600, 8 }, { 1200, 9 }, { 1800, 10 }, 82 { 2400, 11 }, { 4800, 12 }, { 9600, 13 }, 83 { 19200, 14 }, { 38400, 15 }, 84 { 57600, 4097 }, { 115200, 4098 }, {-1, -1 } 85 }; 86 87 struct linux_serial_struct { 88 int type; 89 int line; 90 int port; 91 int irq; 92 int flags; 93 int xmit_fifo_size; 94 int custom_divisor; 95 int baud_base; 96 unsigned short close_delay; 97 char reserved_char[2]; 98 int hub6; 99 unsigned short closing_wait; 100 unsigned short closing_wait2; 101 int reserved[4]; 102 }; 103 104 105 static int 106 linux_to_bsd_speed(int code, struct speedtab *table) 107 { 108 for ( ; table->sp_code != -1; table++) 109 if (table->sp_code == code) 110 return (table->sp_speed); 111 return -1; 112 } 113 114 static int 115 bsd_to_linux_speed(int speed, struct speedtab *table) 116 { 117 for ( ; table->sp_speed != -1; table++) 118 if (table->sp_speed == speed) 119 return (table->sp_code); 120 return -1; 121 } 122 123 static void 124 bsd_to_linux_termios(struct termios *bsd_termios, 125 struct linux_termios *linux_termios) 126 { 127 int i; 128 129 #ifdef DEBUG 130 printf("LINUX: BSD termios structure (input):\n"); 131 printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n", 132 bsd_termios->c_iflag, bsd_termios->c_oflag, 133 bsd_termios->c_cflag, bsd_termios->c_lflag, 134 bsd_termios->c_ispeed, bsd_termios->c_ospeed); 135 printf("c_cc "); 136 for (i=0; i<NCCS; i++) 137 printf("%02x ", bsd_termios->c_cc[i]); 138 printf("\n"); 139 #endif 140 linux_termios->c_iflag = 0; 141 if (bsd_termios->c_iflag & IGNBRK) 142 linux_termios->c_iflag |= LINUX_IGNBRK; 143 if (bsd_termios->c_iflag & BRKINT) 144 linux_termios->c_iflag |= LINUX_BRKINT; 145 if (bsd_termios->c_iflag & IGNPAR) 146 linux_termios->c_iflag |= LINUX_IGNPAR; 147 if (bsd_termios->c_iflag & PARMRK) 148 linux_termios->c_iflag |= LINUX_PARMRK; 149 if (bsd_termios->c_iflag & INPCK) 150 linux_termios->c_iflag |= LINUX_INPCK; 151 if (bsd_termios->c_iflag & ISTRIP) 152 linux_termios->c_iflag |= LINUX_ISTRIP; 153 if (bsd_termios->c_iflag & INLCR) 154 linux_termios->c_iflag |= LINUX_INLCR; 155 if (bsd_termios->c_iflag & IGNCR) 156 linux_termios->c_iflag |= LINUX_IGNCR; 157 if (bsd_termios->c_iflag & ICRNL) 158 linux_termios->c_iflag |= LINUX_ICRNL; 159 if (bsd_termios->c_iflag & IXON) 160 linux_termios->c_iflag |= LINUX_IXANY; 161 if (bsd_termios->c_iflag & IXON) 162 linux_termios->c_iflag |= LINUX_IXON; 163 if (bsd_termios->c_iflag & IXOFF) 164 linux_termios->c_iflag |= LINUX_IXOFF; 165 if (bsd_termios->c_iflag & IMAXBEL) 166 linux_termios->c_iflag |= LINUX_IMAXBEL; 167 168 linux_termios->c_oflag = 0; 169 if (bsd_termios->c_oflag & OPOST) 170 linux_termios->c_oflag |= LINUX_OPOST; 171 if (bsd_termios->c_oflag & ONLCR) 172 linux_termios->c_oflag |= LINUX_ONLCR; 173 if (bsd_termios->c_oflag & OXTABS) 174 linux_termios->c_oflag |= LINUX_XTABS; 175 176 linux_termios->c_cflag = 177 bsd_to_linux_speed(bsd_termios->c_ispeed, sptab); 178 linux_termios->c_cflag |= (bsd_termios->c_cflag & CSIZE) >> 4; 179 if (bsd_termios->c_cflag & CSTOPB) 180 linux_termios->c_cflag |= LINUX_CSTOPB; 181 if (bsd_termios->c_cflag & CREAD) 182 linux_termios->c_cflag |= LINUX_CREAD; 183 if (bsd_termios->c_cflag & PARENB) 184 linux_termios->c_cflag |= LINUX_PARENB; 185 if (bsd_termios->c_cflag & PARODD) 186 linux_termios->c_cflag |= LINUX_PARODD; 187 if (bsd_termios->c_cflag & HUPCL) 188 linux_termios->c_cflag |= LINUX_HUPCL; 189 if (bsd_termios->c_cflag & CLOCAL) 190 linux_termios->c_cflag |= LINUX_CLOCAL; 191 if (bsd_termios->c_cflag & CRTSCTS) 192 linux_termios->c_cflag |= LINUX_CRTSCTS; 193 194 linux_termios->c_lflag = 0; 195 if (bsd_termios->c_lflag & ISIG) 196 linux_termios->c_lflag |= LINUX_ISIG; 197 if (bsd_termios->c_lflag & ICANON) 198 linux_termios->c_lflag |= LINUX_ICANON; 199 if (bsd_termios->c_lflag & ECHO) 200 linux_termios->c_lflag |= LINUX_ECHO; 201 if (bsd_termios->c_lflag & ECHOE) 202 linux_termios->c_lflag |= LINUX_ECHOE; 203 if (bsd_termios->c_lflag & ECHOK) 204 linux_termios->c_lflag |= LINUX_ECHOK; 205 if (bsd_termios->c_lflag & ECHONL) 206 linux_termios->c_lflag |= LINUX_ECHONL; 207 if (bsd_termios->c_lflag & NOFLSH) 208 linux_termios->c_lflag |= LINUX_NOFLSH; 209 if (bsd_termios->c_lflag & TOSTOP) 210 linux_termios->c_lflag |= LINUX_TOSTOP; 211 if (bsd_termios->c_lflag & ECHOCTL) 212 linux_termios->c_lflag |= LINUX_ECHOCTL; 213 if (bsd_termios->c_lflag & ECHOPRT) 214 linux_termios->c_lflag |= LINUX_ECHOPRT; 215 if (bsd_termios->c_lflag & ECHOKE) 216 linux_termios->c_lflag |= LINUX_ECHOKE; 217 if (bsd_termios->c_lflag & FLUSHO) 218 linux_termios->c_lflag |= LINUX_FLUSHO; 219 if (bsd_termios->c_lflag & PENDIN) 220 linux_termios->c_lflag |= LINUX_PENDIN; 221 if (bsd_termios->c_lflag & IEXTEN) 222 linux_termios->c_lflag |= LINUX_IEXTEN; 223 224 for (i=0; i<LINUX_NCCS; i++) 225 linux_termios->c_cc[i] = LINUX_POSIX_VDISABLE; 226 linux_termios->c_cc[LINUX_VINTR] = bsd_termios->c_cc[VINTR]; 227 linux_termios->c_cc[LINUX_VQUIT] = bsd_termios->c_cc[VQUIT]; 228 linux_termios->c_cc[LINUX_VERASE] = bsd_termios->c_cc[VERASE]; 229 linux_termios->c_cc[LINUX_VKILL] = bsd_termios->c_cc[VKILL]; 230 linux_termios->c_cc[LINUX_VEOF] = bsd_termios->c_cc[VEOF]; 231 linux_termios->c_cc[LINUX_VEOL] = bsd_termios->c_cc[VEOL]; 232 linux_termios->c_cc[LINUX_VMIN] = bsd_termios->c_cc[VMIN]; 233 linux_termios->c_cc[LINUX_VTIME] = bsd_termios->c_cc[VTIME]; 234 linux_termios->c_cc[LINUX_VEOL2] = bsd_termios->c_cc[VEOL2]; 235 linux_termios->c_cc[LINUX_VSWTC] = _POSIX_VDISABLE; 236 linux_termios->c_cc[LINUX_VSUSP] = bsd_termios->c_cc[VSUSP]; 237 linux_termios->c_cc[LINUX_VSTART] = bsd_termios->c_cc[VSTART]; 238 linux_termios->c_cc[LINUX_VSTOP] = bsd_termios->c_cc[VSTOP]; 239 linux_termios->c_cc[LINUX_VREPRINT] = bsd_termios->c_cc[VREPRINT]; 240 linux_termios->c_cc[LINUX_VDISCARD] = bsd_termios->c_cc[VDISCARD]; 241 linux_termios->c_cc[LINUX_VWERASE] = bsd_termios->c_cc[VWERASE]; 242 linux_termios->c_cc[LINUX_VLNEXT] = bsd_termios->c_cc[VLNEXT]; 243 244 for (i=0; i<LINUX_NCCS; i++) { 245 if (linux_termios->c_cc[i] == _POSIX_VDISABLE) 246 linux_termios->c_cc[i] = LINUX_POSIX_VDISABLE; 247 } 248 249 linux_termios->c_line = 0; 250 #ifdef DEBUG 251 printf("LINUX: LINUX termios structure (output):\n"); 252 printf("i=%08lx o=%08lx c=%08lx l=%08lx line=%d\n", 253 linux_termios->c_iflag, linux_termios->c_oflag, linux_termios->c_cflag, 254 linux_termios->c_lflag, linux_termios->c_line); 255 printf("c_cc "); 256 for (i=0; i<LINUX_NCCS; i++) 257 printf("%02x ", linux_termios->c_cc[i]); 258 printf("\n"); 259 #endif 260 } 261 262 263 static void 264 linux_to_bsd_termios(struct linux_termios *linux_termios, 265 struct termios *bsd_termios) 266 { 267 int i; 268 #ifdef DEBUG 269 printf("LINUX: LINUX termios structure (input):\n"); 270 printf("i=%08lx o=%08lx c=%08lx l=%08lx line=%d\n", 271 linux_termios->c_iflag, linux_termios->c_oflag, linux_termios->c_cflag, 272 linux_termios->c_lflag, linux_termios->c_line); 273 printf("c_cc "); 274 for (i=0; i<LINUX_NCCS; i++) 275 printf("%02x ", linux_termios->c_cc[i]); 276 printf("\n"); 277 #endif 278 bsd_termios->c_iflag = 0; 279 if (linux_termios->c_iflag & LINUX_IGNBRK) 280 bsd_termios->c_iflag |= IGNBRK; 281 if (linux_termios->c_iflag & LINUX_BRKINT) 282 bsd_termios->c_iflag |= BRKINT; 283 if (linux_termios->c_iflag & LINUX_IGNPAR) 284 bsd_termios->c_iflag |= IGNPAR; 285 if (linux_termios->c_iflag & LINUX_PARMRK) 286 bsd_termios->c_iflag |= PARMRK; 287 if (linux_termios->c_iflag & LINUX_INPCK) 288 bsd_termios->c_iflag |= INPCK; 289 if (linux_termios->c_iflag & LINUX_ISTRIP) 290 bsd_termios->c_iflag |= ISTRIP; 291 if (linux_termios->c_iflag & LINUX_INLCR) 292 bsd_termios->c_iflag |= INLCR; 293 if (linux_termios->c_iflag & LINUX_IGNCR) 294 bsd_termios->c_iflag |= IGNCR; 295 if (linux_termios->c_iflag & LINUX_ICRNL) 296 bsd_termios->c_iflag |= ICRNL; 297 if (linux_termios->c_iflag & LINUX_IXON) 298 bsd_termios->c_iflag |= IXANY; 299 if (linux_termios->c_iflag & LINUX_IXON) 300 bsd_termios->c_iflag |= IXON; 301 if (linux_termios->c_iflag & LINUX_IXOFF) 302 bsd_termios->c_iflag |= IXOFF; 303 if (linux_termios->c_iflag & LINUX_IMAXBEL) 304 bsd_termios->c_iflag |= IMAXBEL; 305 306 bsd_termios->c_oflag = 0; 307 if (linux_termios->c_oflag & LINUX_OPOST) 308 bsd_termios->c_oflag |= OPOST; 309 if (linux_termios->c_oflag & LINUX_ONLCR) 310 bsd_termios->c_oflag |= ONLCR; 311 if (linux_termios->c_oflag & LINUX_XTABS) 312 bsd_termios->c_oflag |= OXTABS; 313 314 bsd_termios->c_cflag = (linux_termios->c_cflag & LINUX_CSIZE) << 4; 315 if (linux_termios->c_cflag & LINUX_CSTOPB) 316 bsd_termios->c_cflag |= CSTOPB; 317 if (linux_termios->c_cflag & LINUX_PARENB) 318 bsd_termios->c_cflag |= PARENB; 319 if (linux_termios->c_cflag & LINUX_PARODD) 320 bsd_termios->c_cflag |= PARODD; 321 if (linux_termios->c_cflag & LINUX_HUPCL) 322 bsd_termios->c_cflag |= HUPCL; 323 if (linux_termios->c_cflag & LINUX_CLOCAL) 324 bsd_termios->c_cflag |= CLOCAL; 325 if (linux_termios->c_cflag & LINUX_CRTSCTS) 326 bsd_termios->c_cflag |= CRTSCTS; 327 328 bsd_termios->c_lflag = 0; 329 if (linux_termios->c_lflag & LINUX_ISIG) 330 bsd_termios->c_lflag |= ISIG; 331 if (linux_termios->c_lflag & LINUX_ICANON) 332 bsd_termios->c_lflag |= ICANON; 333 if (linux_termios->c_lflag & LINUX_ECHO) 334 bsd_termios->c_lflag |= ECHO; 335 if (linux_termios->c_lflag & LINUX_ECHOE) 336 bsd_termios->c_lflag |= ECHOE; 337 if (linux_termios->c_lflag & LINUX_ECHOK) 338 bsd_termios->c_lflag |= ECHOK; 339 if (linux_termios->c_lflag & LINUX_ECHONL) 340 bsd_termios->c_lflag |= ECHONL; 341 if (linux_termios->c_lflag & LINUX_NOFLSH) 342 bsd_termios->c_lflag |= NOFLSH; 343 if (linux_termios->c_lflag & LINUX_TOSTOP) 344 bsd_termios->c_lflag |= TOSTOP; 345 if (linux_termios->c_lflag & LINUX_ECHOCTL) 346 bsd_termios->c_lflag |= ECHOCTL; 347 if (linux_termios->c_lflag & LINUX_ECHOPRT) 348 bsd_termios->c_lflag |= ECHOPRT; 349 if (linux_termios->c_lflag & LINUX_ECHOKE) 350 bsd_termios->c_lflag |= ECHOKE; 351 if (linux_termios->c_lflag & LINUX_FLUSHO) 352 bsd_termios->c_lflag |= FLUSHO; 353 if (linux_termios->c_lflag & LINUX_PENDIN) 354 bsd_termios->c_lflag |= PENDIN; 355 if (linux_termios->c_lflag & IEXTEN) 356 bsd_termios->c_lflag |= IEXTEN; 357 358 for (i=0; i<NCCS; i++) 359 bsd_termios->c_cc[i] = _POSIX_VDISABLE; 360 bsd_termios->c_cc[VINTR] = linux_termios->c_cc[LINUX_VINTR]; 361 bsd_termios->c_cc[VQUIT] = linux_termios->c_cc[LINUX_VQUIT]; 362 bsd_termios->c_cc[VERASE] = linux_termios->c_cc[LINUX_VERASE]; 363 bsd_termios->c_cc[VKILL] = linux_termios->c_cc[LINUX_VKILL]; 364 bsd_termios->c_cc[VEOF] = linux_termios->c_cc[LINUX_VEOF]; 365 bsd_termios->c_cc[VEOL] = linux_termios->c_cc[LINUX_VEOL]; 366 bsd_termios->c_cc[VMIN] = linux_termios->c_cc[LINUX_VMIN]; 367 bsd_termios->c_cc[VTIME] = linux_termios->c_cc[LINUX_VTIME]; 368 bsd_termios->c_cc[VEOL2] = linux_termios->c_cc[LINUX_VEOL2]; 369 bsd_termios->c_cc[VSUSP] = linux_termios->c_cc[LINUX_VSUSP]; 370 bsd_termios->c_cc[VSTART] = linux_termios->c_cc[LINUX_VSTART]; 371 bsd_termios->c_cc[VSTOP] = linux_termios->c_cc[LINUX_VSTOP]; 372 bsd_termios->c_cc[VREPRINT] = linux_termios->c_cc[LINUX_VREPRINT]; 373 bsd_termios->c_cc[VDISCARD] = linux_termios->c_cc[LINUX_VDISCARD]; 374 bsd_termios->c_cc[VWERASE] = linux_termios->c_cc[LINUX_VWERASE]; 375 bsd_termios->c_cc[VLNEXT] = linux_termios->c_cc[LINUX_VLNEXT]; 376 377 for (i=0; i<NCCS; i++) { 378 if (bsd_termios->c_cc[i] == LINUX_POSIX_VDISABLE) 379 bsd_termios->c_cc[i] = _POSIX_VDISABLE; 380 } 381 382 bsd_termios->c_ispeed = bsd_termios->c_ospeed = 383 linux_to_bsd_speed(linux_termios->c_cflag & LINUX_CBAUD, sptab); 384 #ifdef DEBUG 385 printf("LINUX: BSD termios structure (output):\n"); 386 printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n", 387 bsd_termios->c_iflag, bsd_termios->c_oflag, 388 bsd_termios->c_cflag, bsd_termios->c_lflag, 389 bsd_termios->c_ispeed, bsd_termios->c_ospeed); 390 printf("c_cc "); 391 for (i=0; i<NCCS; i++) 392 printf("%02x ", bsd_termios->c_cc[i]); 393 printf("\n"); 394 #endif 395 } 396 397 398 static void 399 bsd_to_linux_termio(struct termios *bsd_termios, 400 struct linux_termio *linux_termio) 401 { 402 struct linux_termios tmios; 403 404 bsd_to_linux_termios(bsd_termios, &tmios); 405 linux_termio->c_iflag = tmios.c_iflag; 406 linux_termio->c_oflag = tmios.c_oflag; 407 linux_termio->c_cflag = tmios.c_cflag; 408 linux_termio->c_lflag = tmios.c_lflag; 409 linux_termio->c_line = tmios.c_line; 410 memcpy(linux_termio->c_cc, tmios.c_cc, LINUX_NCC); 411 } 412 413 static void 414 linux_to_bsd_termio(struct linux_termio *linux_termio, 415 struct termios *bsd_termios) 416 { 417 struct linux_termios tmios; 418 int i; 419 420 tmios.c_iflag = linux_termio->c_iflag; 421 tmios.c_oflag = linux_termio->c_oflag; 422 tmios.c_cflag = linux_termio->c_cflag; 423 tmios.c_lflag = linux_termio->c_lflag; 424 425 for (i=0; i<LINUX_NCCS; i++) 426 tmios.c_cc[i] = LINUX_POSIX_VDISABLE; 427 memcpy(tmios.c_cc, linux_termio->c_cc, LINUX_NCC); 428 429 linux_to_bsd_termios(&tmios, bsd_termios); 430 } 431 432 static void 433 linux_tiocgserial(struct file *fp, struct linux_serial_struct *lss) 434 { 435 if (!fp || !lss) 436 return; 437 438 lss->type = LINUX_PORT_16550A; 439 lss->flags = 0; 440 lss->close_delay = 0; 441 } 442 443 static void 444 linux_tiocsserial(struct file *fp, struct linux_serial_struct *lss) 445 { 446 if (!fp || !lss) 447 return; 448 } 449 450 int 451 linux_ioctl(struct proc *p, struct linux_ioctl_args *args) 452 { 453 struct termios bsd_termios; 454 struct linux_termios linux_termios; 455 struct linux_termio linux_termio; 456 struct filedesc *fdp = p->p_fd; 457 struct file *fp; 458 int (*func)(struct file *fp, u_long com, caddr_t data, struct proc *p); 459 int bsd_line, linux_line; 460 int error; 461 462 #ifdef DEBUG 463 printf("Linux-emul(%ld): ioctl(%d, %04lx, *)\n", 464 (long)p->p_pid, args->fd, args->cmd); 465 #endif 466 if ((unsigned)args->fd >= fdp->fd_nfiles 467 || (fp = fdp->fd_ofiles[args->fd]) == 0) 468 return EBADF; 469 470 if (!fp || (fp->f_flag & (FREAD | FWRITE)) == 0) { 471 return EBADF; 472 } 473 474 func = fp->f_ops->fo_ioctl; 475 switch (args->cmd & 0xffff) { 476 477 case LINUX_TCGETA: 478 if ((error = (*func)(fp, TIOCGETA, (caddr_t)&bsd_termios, p)) != 0) 479 return error; 480 bsd_to_linux_termio(&bsd_termios, &linux_termio); 481 return copyout((caddr_t)&linux_termio, (caddr_t)args->arg, 482 sizeof(linux_termio)); 483 484 case LINUX_TCSETA: 485 linux_to_bsd_termio((struct linux_termio *)args->arg, &bsd_termios); 486 return (*func)(fp, TIOCSETA, (caddr_t)&bsd_termios, p); 487 488 case LINUX_TCSETAW: 489 linux_to_bsd_termio((struct linux_termio *)args->arg, &bsd_termios); 490 return (*func)(fp, TIOCSETAW, (caddr_t)&bsd_termios, p); 491 492 case LINUX_TCSETAF: 493 linux_to_bsd_termio((struct linux_termio *)args->arg, &bsd_termios); 494 return (*func)(fp, TIOCSETAF, (caddr_t)&bsd_termios, p); 495 496 case LINUX_TCGETS: 497 if ((error = (*func)(fp, TIOCGETA, (caddr_t)&bsd_termios, p)) != 0) 498 return error; 499 bsd_to_linux_termios(&bsd_termios, &linux_termios); 500 return copyout((caddr_t)&linux_termios, (caddr_t)args->arg, 501 sizeof(linux_termios)); 502 503 case LINUX_TCSETS: 504 linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios); 505 return (*func)(fp, TIOCSETA, (caddr_t)&bsd_termios, p); 506 507 case LINUX_TCSETSW: 508 linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios); 509 return (*func)(fp, TIOCSETAW, (caddr_t)&bsd_termios, p); 510 511 case LINUX_TCSETSF: 512 linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios); 513 return (*func)(fp, TIOCSETAF, (caddr_t)&bsd_termios, p); 514 515 case LINUX_TIOCGPGRP: 516 args->cmd = TIOCGPGRP; 517 return ioctl(p, (struct ioctl_args *)args); 518 519 case LINUX_TIOCSPGRP: 520 args->cmd = TIOCSPGRP; 521 return ioctl(p, (struct ioctl_args *)args); 522 523 case LINUX_TIOCGWINSZ: 524 args->cmd = TIOCGWINSZ; 525 return ioctl(p, (struct ioctl_args *)args); 526 527 case LINUX_TIOCSWINSZ: 528 args->cmd = TIOCSWINSZ; 529 return ioctl(p, (struct ioctl_args *)args); 530 531 case LINUX_FIONREAD: 532 args->cmd = FIONREAD; 533 return ioctl(p, (struct ioctl_args *)args); 534 535 case LINUX_FIONBIO: 536 args->cmd = FIONBIO; 537 return ioctl(p, (struct ioctl_args *)args); 538 539 case LINUX_FIOASYNC: 540 args->cmd = FIOASYNC; 541 return ioctl(p, (struct ioctl_args *)args); 542 543 case LINUX_FIONCLEX: 544 args->cmd = FIONCLEX; 545 return ioctl(p, (struct ioctl_args *)args); 546 547 case LINUX_FIOCLEX: 548 args->cmd = FIOCLEX; 549 return ioctl(p, (struct ioctl_args *)args); 550 551 case LINUX_TIOCEXCL: 552 args->cmd = TIOCEXCL; 553 return ioctl(p, (struct ioctl_args *)args); 554 555 case LINUX_TIOCNXCL: 556 args->cmd = TIOCNXCL; 557 return ioctl(p, (struct ioctl_args *)args); 558 559 case LINUX_TIOCCONS: 560 args->cmd = TIOCCONS; 561 return ioctl(p, (struct ioctl_args *)args); 562 563 case LINUX_TIOCNOTTY: 564 args->cmd = TIOCNOTTY; 565 return ioctl(p, (struct ioctl_args *)args); 566 567 case LINUX_SIOCGIFCONF: 568 args->cmd = OSIOCGIFCONF; 569 return ioctl(p, (struct ioctl_args *)args); 570 571 case LINUX_SIOCGIFFLAGS: 572 args->cmd = SIOCGIFFLAGS; 573 return ioctl(p, (struct ioctl_args *)args); 574 575 case LINUX_SIOCGIFADDR: 576 args->cmd = OSIOCGIFADDR; 577 return ioctl(p, (struct ioctl_args *)args); 578 579 case LINUX_SIOCGIFDSTADDR: 580 args->cmd = OSIOCGIFDSTADDR; 581 return ioctl(p, (struct ioctl_args *)args); 582 583 case LINUX_SIOCGIFBRDADDR: 584 args->cmd = OSIOCGIFBRDADDR; 585 return ioctl(p, (struct ioctl_args *)args); 586 587 case LINUX_SIOCGIFNETMASK: 588 args->cmd = OSIOCGIFNETMASK; 589 return ioctl(p, (struct ioctl_args *)args); 590 591 /* get hardware address */ 592 case LINUX_SIOCGIFHWADDR: 593 { 594 int ifn; 595 struct ifnet *ifp; 596 struct ifaddr *ifa; 597 struct sockaddr_dl *sdl; 598 struct linux_ifreq *ifr = (struct linux_ifreq *)args->arg; 599 600 /* 601 * Note that we don't actually respect the name in the ifreq structure, as 602 * Linux interface names are all different 603 */ 604 605 for (ifn = 0; ifn < if_index; ifn++) { 606 607 ifp = ifnet_addrs[ifn]->ifa_ifp; /* pointer to interface */ 608 if (ifp->if_type == IFT_ETHER) { /* looks good */ 609 /* walk the address list */ 610 for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa; ifa = TAILQ_NEXT(ifa, ifa_link)) { 611 if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && /* we have an address structure */ 612 (sdl->sdl_family == AF_LINK) && /* it's a link address */ 613 (sdl->sdl_type == IFT_ETHER)) { /* for an ethernet link */ 614 615 return(copyout(LLADDR(sdl), (caddr_t)&ifr->ifr_hwaddr.sa_data, LINUX_IFHWADDRLEN)); 616 } 617 } 618 } 619 } 620 return(ENOENT); /* ??? */ 621 } 622 623 case LINUX_SIOCADDMULTI: 624 args->cmd = SIOCADDMULTI; 625 return ioctl(p, (struct ioctl_args *)args); 626 627 case LINUX_SIOCDELMULTI: 628 args->cmd = SIOCDELMULTI; 629 return ioctl(p, (struct ioctl_args *)args); 630 631 case LINUX_FIOSETOWN: 632 args->cmd = FIOSETOWN; 633 return ioctl(p, (struct ioctl_args *)args); 634 635 case LINUX_SIOCSPGRP: 636 args->cmd = SIOCSPGRP; 637 return ioctl(p, (struct ioctl_args *)args); 638 639 case LINUX_FIOGETOWN: 640 args->cmd = FIOGETOWN; 641 return ioctl(p, (struct ioctl_args *)args); 642 643 case LINUX_SIOCGPGRP: 644 args->cmd = SIOCGPGRP; 645 return ioctl(p, (struct ioctl_args *)args); 646 647 case LINUX_SIOCATMARK: 648 args->cmd = SIOCATMARK; 649 return ioctl(p, (struct ioctl_args *)args); 650 651 case LINUX_TIOCSETD: 652 switch (args->arg) { 653 case LINUX_N_TTY: 654 bsd_line = TTYDISC; 655 return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p); 656 case LINUX_N_SLIP: 657 bsd_line = SLIPDISC; 658 return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p); 659 case LINUX_N_PPP: 660 bsd_line = PPPDISC; 661 return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p); 662 default: 663 return EINVAL; 664 } 665 666 case LINUX_TIOCGETD: 667 bsd_line = TTYDISC; 668 if (error =(*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p)) 669 return error; 670 switch (bsd_line) { 671 case TTYDISC: 672 linux_line = LINUX_N_TTY; 673 break; 674 case SLIPDISC: 675 linux_line = LINUX_N_SLIP; 676 break; 677 case PPPDISC: 678 linux_line = LINUX_N_PPP; 679 break; 680 default: 681 return EINVAL; 682 } 683 return copyout(&linux_line, (caddr_t)args->arg, 684 sizeof(int)); 685 686 case LINUX_SNDCTL_SEQ_RESET: 687 args->cmd = SNDCTL_SEQ_RESET; 688 return ioctl(p, (struct ioctl_args *)args); 689 690 case LINUX_SNDCTL_SEQ_SYNC: 691 args->cmd = SNDCTL_SEQ_SYNC; 692 return ioctl(p, (struct ioctl_args *)args); 693 694 case LINUX_SNDCTL_SYNTH_INFO: 695 args->cmd = SNDCTL_SYNTH_INFO; 696 return ioctl(p, (struct ioctl_args *)args); 697 698 case LINUX_SNDCTL_SEQ_CTRLRATE: 699 args->cmd = SNDCTL_SEQ_CTRLRATE; 700 return ioctl(p, (struct ioctl_args *)args); 701 702 case LINUX_SNDCTL_SEQ_GETOUTCOUNT: 703 args->cmd = SNDCTL_SEQ_GETOUTCOUNT; 704 return ioctl(p, (struct ioctl_args *)args); 705 706 case LINUX_SNDCTL_SEQ_GETINCOUNT: 707 args->cmd = SNDCTL_SEQ_GETINCOUNT; 708 return ioctl(p, (struct ioctl_args *)args); 709 710 case LINUX_SNDCTL_SEQ_PERCMODE: 711 args->cmd = SNDCTL_SEQ_PERCMODE; 712 return ioctl(p, (struct ioctl_args *)args); 713 714 case LINUX_SNDCTL_FM_LOAD_INSTR: 715 args->cmd = SNDCTL_FM_LOAD_INSTR; 716 return ioctl(p, (struct ioctl_args *)args); 717 718 case LINUX_SNDCTL_SEQ_TESTMIDI: 719 args->cmd = SNDCTL_SEQ_TESTMIDI; 720 return ioctl(p, (struct ioctl_args *)args); 721 722 case LINUX_SNDCTL_SEQ_RESETSAMPLES: 723 args->cmd = SNDCTL_SEQ_RESETSAMPLES; 724 return ioctl(p, (struct ioctl_args *)args); 725 726 case LINUX_SNDCTL_SEQ_NRSYNTHS: 727 args->cmd = SNDCTL_SEQ_NRSYNTHS; 728 return ioctl(p, (struct ioctl_args *)args); 729 730 case LINUX_SNDCTL_SEQ_NRMIDIS: 731 args->cmd = SNDCTL_SEQ_NRMIDIS; 732 return ioctl(p, (struct ioctl_args *)args); 733 734 case LINUX_SNDCTL_MIDI_INFO: 735 args->cmd = SNDCTL_MIDI_INFO; 736 return ioctl(p, (struct ioctl_args *)args); 737 738 case LINUX_SNDCTL_SEQ_TRESHOLD: 739 args->cmd = SNDCTL_SEQ_TRESHOLD; 740 return ioctl(p, (struct ioctl_args *)args); 741 742 case LINUX_SNDCTL_SYNTH_MEMAVL: 743 args->cmd = SNDCTL_SYNTH_MEMAVL; 744 return ioctl(p, (struct ioctl_args *)args); 745 746 case LINUX_SNDCTL_DSP_GETOPTR : 747 args->cmd = SNDCTL_DSP_GETOPTR; 748 return ioctl(p, (struct ioctl_args *)args); 749 750 case LINUX_SNDCTL_DSP_GETIPTR : 751 args->cmd = SNDCTL_DSP_GETIPTR; 752 return ioctl(p, (struct ioctl_args *)args); 753 754 case LINUX_SNDCTL_DSP_SETTRIGGER: 755 args->cmd = SNDCTL_DSP_SETTRIGGER; 756 return ioctl(p, (struct ioctl_args *)args); 757 758 case LINUX_SNDCTL_DSP_GETCAPS: 759 args->cmd = SNDCTL_DSP_GETCAPS; 760 return ioctl(p, (struct ioctl_args *)args); 761 762 case LINUX_SNDCTL_DSP_RESET: 763 args->cmd = SNDCTL_DSP_RESET; 764 return ioctl(p, (struct ioctl_args *)args); 765 766 case LINUX_SNDCTL_DSP_SYNC: 767 args->cmd = SNDCTL_DSP_SYNC; 768 return ioctl(p, (struct ioctl_args *)args); 769 770 case LINUX_SNDCTL_DSP_SPEED: 771 args->cmd = SNDCTL_DSP_SPEED; 772 return ioctl(p, (struct ioctl_args *)args); 773 774 case LINUX_SNDCTL_DSP_STEREO: 775 args->cmd = SNDCTL_DSP_STEREO; 776 return ioctl(p, (struct ioctl_args *)args); 777 778 case LINUX_SNDCTL_DSP_GETBLKSIZE: 779 /* LINUX_SNDCTL_DSP_SETBLKSIZE */ 780 args->cmd = SNDCTL_DSP_GETBLKSIZE; 781 return ioctl(p, (struct ioctl_args *)args); 782 783 case LINUX_SNDCTL_DSP_SETFMT: 784 args->cmd = SNDCTL_DSP_SETFMT; 785 return ioctl(p, (struct ioctl_args *)args); 786 787 case LINUX_SOUND_PCM_WRITE_CHANNELS: 788 args->cmd = SOUND_PCM_WRITE_CHANNELS; 789 return ioctl(p, (struct ioctl_args *)args); 790 791 case LINUX_SOUND_PCM_WRITE_FILTER: 792 args->cmd = SOUND_PCM_WRITE_FILTER; 793 return ioctl(p, (struct ioctl_args *)args); 794 795 case LINUX_SNDCTL_DSP_POST: 796 args->cmd = SNDCTL_DSP_POST; 797 return ioctl(p, (struct ioctl_args *)args); 798 799 case LINUX_SNDCTL_DSP_SUBDIVIDE: 800 args->cmd = SNDCTL_DSP_SUBDIVIDE; 801 return ioctl(p, (struct ioctl_args *)args); 802 803 case LINUX_SNDCTL_DSP_SETFRAGMENT: 804 args->cmd = SNDCTL_DSP_SETFRAGMENT; 805 return ioctl(p, (struct ioctl_args *)args); 806 807 case LINUX_SNDCTL_DSP_GETFMTS: 808 args->cmd = SNDCTL_DSP_GETFMTS; 809 return ioctl(p, (struct ioctl_args *)args); 810 811 case LINUX_SNDCTL_DSP_GETOSPACE: 812 args->cmd = SNDCTL_DSP_GETOSPACE; 813 return ioctl(p, (struct ioctl_args *)args); 814 815 case LINUX_SNDCTL_DSP_GETISPACE: 816 args->cmd = SNDCTL_DSP_GETISPACE; 817 return ioctl(p, (struct ioctl_args *)args); 818 819 case LINUX_SNDCTL_DSP_NONBLOCK: 820 args->cmd = SNDCTL_DSP_NONBLOCK; 821 return ioctl(p, (struct ioctl_args *)args); 822 823 case LINUX_SOUND_MIXER_WRITE_VOLUME: 824 args->cmd = SOUND_MIXER_WRITE_VOLUME; 825 return ioctl(p, (struct ioctl_args *)args); 826 827 case LINUX_SOUND_MIXER_WRITE_BASS: 828 args->cmd = SOUND_MIXER_WRITE_BASS; 829 return ioctl(p, (struct ioctl_args *)args); 830 831 case LINUX_SOUND_MIXER_WRITE_TREBLE: 832 args->cmd = SOUND_MIXER_WRITE_TREBLE; 833 return ioctl(p, (struct ioctl_args *)args); 834 835 case LINUX_SOUND_MIXER_WRITE_SYNTH: 836 args->cmd = SOUND_MIXER_WRITE_SYNTH; 837 return ioctl(p, (struct ioctl_args *)args); 838 839 case LINUX_SOUND_MIXER_WRITE_PCM: 840 args->cmd = SOUND_MIXER_WRITE_PCM; 841 return ioctl(p, (struct ioctl_args *)args); 842 843 case LINUX_SOUND_MIXER_WRITE_SPEAKER: 844 args->cmd = SOUND_MIXER_WRITE_SPEAKER; 845 return ioctl(p, (struct ioctl_args *)args); 846 847 case LINUX_SOUND_MIXER_WRITE_LINE: 848 args->cmd = SOUND_MIXER_WRITE_LINE; 849 return ioctl(p, (struct ioctl_args *)args); 850 851 case LINUX_SOUND_MIXER_WRITE_MIC: 852 args->cmd = SOUND_MIXER_WRITE_MIC; 853 return ioctl(p, (struct ioctl_args *)args); 854 855 case LINUX_SOUND_MIXER_WRITE_CD: 856 args->cmd = SOUND_MIXER_WRITE_CD; 857 return ioctl(p, (struct ioctl_args *)args); 858 859 case LINUX_SOUND_MIXER_WRITE_IMIX: 860 args->cmd = SOUND_MIXER_WRITE_IMIX; 861 return ioctl(p, (struct ioctl_args *)args); 862 863 case LINUX_SOUND_MIXER_WRITE_ALTPCM: 864 args->cmd = SOUND_MIXER_WRITE_ALTPCM; 865 return ioctl(p, (struct ioctl_args *)args); 866 867 case LINUX_SOUND_MIXER_WRITE_RECLEV: 868 args->cmd = SOUND_MIXER_WRITE_RECLEV; 869 return ioctl(p, (struct ioctl_args *)args); 870 871 case LINUX_SOUND_MIXER_WRITE_IGAIN: 872 args->cmd = SOUND_MIXER_WRITE_IGAIN; 873 return ioctl(p, (struct ioctl_args *)args); 874 875 case LINUX_SOUND_MIXER_WRITE_OGAIN: 876 args->cmd = SOUND_MIXER_WRITE_OGAIN; 877 return ioctl(p, (struct ioctl_args *)args); 878 879 case LINUX_SOUND_MIXER_WRITE_LINE1: 880 args->cmd = SOUND_MIXER_WRITE_LINE1; 881 return ioctl(p, (struct ioctl_args *)args); 882 883 case LINUX_SOUND_MIXER_WRITE_LINE2: 884 args->cmd = SOUND_MIXER_WRITE_LINE2; 885 return ioctl(p, (struct ioctl_args *)args); 886 887 case LINUX_SOUND_MIXER_WRITE_LINE3: 888 args->cmd = SOUND_MIXER_WRITE_LINE3; 889 return ioctl(p, (struct ioctl_args *)args); 890 891 case LINUX_SOUND_MIXER_READ_DEVMASK: 892 args->cmd = SOUND_MIXER_READ_DEVMASK; 893 return ioctl(p, (struct ioctl_args *)args); 894 895 case LINUX_TIOCGSERIAL: 896 linux_tiocgserial(fp, (struct linux_serial_struct *)args->arg); 897 return 0; 898 899 case LINUX_TIOCSSERIAL: 900 linux_tiocsserial(fp, (struct linux_serial_struct *)args->arg); 901 return 0; 902 903 case LINUX_TCFLSH: 904 args->cmd = TIOCFLUSH; 905 switch (args->arg) { 906 case LINUX_TCIFLUSH: 907 args->arg = FREAD; 908 break; 909 case LINUX_TCOFLUSH: 910 args->arg = FWRITE; 911 break; 912 case LINUX_TCIOFLUSH: 913 args->arg = FREAD | FWRITE; 914 break; 915 default: 916 return EINVAL; 917 } 918 return ioctl(p, (struct ioctl_args *)args); 919 920 case LINUX_VT_OPENQRY: 921 922 args->cmd = VT_OPENQRY; 923 return ioctl(p, (struct ioctl_args *)args); 924 925 case LINUX_VT_GETMODE: 926 927 args->cmd = VT_GETMODE; 928 return ioctl(p, (struct ioctl_args *)args); 929 930 case LINUX_VT_SETMODE: 931 { 932 struct vt_mode *mode; 933 args->cmd = VT_SETMODE; 934 mode = (struct vt_mode *)args->arg; 935 if (!ISSIGVALID(mode->frsig) && ISSIGVALID(mode->acqsig)) 936 mode->frsig = mode->acqsig; 937 return ioctl(p, (struct ioctl_args *)args); 938 } 939 940 case LINUX_VT_GETSTATE: 941 942 args->cmd = VT_GETACTIVE; 943 return ioctl(p, (struct ioctl_args *)args); 944 945 case LINUX_VT_ACTIVATE: 946 947 args->cmd = VT_ACTIVATE; 948 return ioctl(p, (struct ioctl_args *)args); 949 950 case LINUX_VT_WAITACTIVE: 951 952 args->cmd = VT_WAITACTIVE; 953 return ioctl(p, (struct ioctl_args *)args); 954 955 case LINUX_KDGKBMODE: 956 957 args->cmd = KDGKBMODE; 958 return ioctl(p, (struct ioctl_args *)args); 959 960 case LINUX_KDSKBMODE: 961 { 962 int kbdmode; 963 switch (args->arg) { 964 case LINUX_KBD_RAW: 965 kbdmode = K_RAW; 966 return (*func)(fp, KDSKBMODE, (caddr_t)&kbdmode, p); 967 case LINUX_KBD_XLATE: 968 kbdmode = K_XLATE; 969 return (*func)(fp, KDSKBMODE , (caddr_t)&kbdmode, p); 970 case LINUX_KBD_MEDIUMRAW: 971 kbdmode = K_RAW; 972 return (*func)(fp, KDSKBMODE , (caddr_t)&kbdmode, p); 973 default: 974 return EINVAL; 975 } 976 } 977 978 case LINUX_KDGETMODE: 979 args->cmd = KDGETMODE; 980 return ioctl(p, (struct ioctl_args *)args); 981 982 case LINUX_KDSETMODE: 983 args->cmd = KDSETMODE; 984 return ioctl(p, (struct ioctl_args *)args); 985 986 case LINUX_KDSETLED: 987 args->cmd = KDSETLED; 988 return ioctl(p, (struct ioctl_args *)args); 989 990 case LINUX_KDGETLED: 991 args->cmd = KDGETLED; 992 return ioctl(p, (struct ioctl_args *)args); 993 994 case LINUX_KIOCSOUND: 995 args->cmd = KIOCSOUND; 996 return ioctl(p, (struct ioctl_args *)args); 997 998 case LINUX_KDMKTONE: 999 args->cmd = KDMKTONE; 1000 return ioctl(p, (struct ioctl_args *)args); 1001 } 1002 1003 uprintf("LINUX: 'ioctl' fd=%d, typ=0x%x(%c), num=0x%x not implemented\n", 1004 args->fd, (u_int)((args->cmd & 0xffff00) >> 8), 1005 (int)((args->cmd & 0xffff00) >> 8), (u_int)(args->cmd & 0xff)); 1006 return EINVAL; 1007 } 1008