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 * $FreeBSD$ 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/cdio.h> 36 #include <sys/fcntl.h> 37 #include <sys/file.h> 38 #include <sys/filedesc.h> 39 #include <sys/filio.h> 40 #include <sys/linker_set.h> 41 #include <sys/malloc.h> 42 #include <sys/tty.h> 43 #include <sys/socket.h> 44 #include <net/if.h> 45 #include <net/if_dl.h> 46 #include <net/if_types.h> 47 #include <sys/sockio.h> 48 #include <sys/soundcard.h> 49 50 #include <machine/console.h> 51 52 #include <i386/linux/linux.h> 53 #include <i386/linux/linux_ioctl.h> 54 #include <i386/linux/linux_mib.h> 55 #include <i386/linux/linux_proto.h> 56 #include <i386/linux/linux_util.h> 57 58 static linux_ioctl_function_t linux_ioctl_cdrom; 59 static linux_ioctl_function_t linux_ioctl_console; 60 static linux_ioctl_function_t linux_ioctl_socket; 61 static linux_ioctl_function_t linux_ioctl_sound; 62 static linux_ioctl_function_t linux_ioctl_termio; 63 64 static struct linux_ioctl_handler cdrom_handler = 65 { linux_ioctl_cdrom, LINUX_IOCTL_CDROM_MIN, LINUX_IOCTL_CDROM_MAX }; 66 static struct linux_ioctl_handler console_handler = 67 { linux_ioctl_console, LINUX_IOCTL_CONSOLE_MIN, LINUX_IOCTL_CONSOLE_MAX }; 68 static struct linux_ioctl_handler socket_handler = 69 { linux_ioctl_socket, LINUX_IOCTL_SOCKET_MIN, LINUX_IOCTL_SOCKET_MAX }; 70 static struct linux_ioctl_handler sound_handler = 71 { linux_ioctl_sound, LINUX_IOCTL_SOUND_MIN, LINUX_IOCTL_SOUND_MAX }; 72 static struct linux_ioctl_handler termio_handler = 73 { linux_ioctl_termio, LINUX_IOCTL_TERMIO_MIN, LINUX_IOCTL_TERMIO_MAX }; 74 75 DATA_SET(linux_ioctl_handler_set, cdrom_handler); 76 DATA_SET(linux_ioctl_handler_set, console_handler); 77 DATA_SET(linux_ioctl_handler_set, socket_handler); 78 DATA_SET(linux_ioctl_handler_set, sound_handler); 79 DATA_SET(linux_ioctl_handler_set, termio_handler); 80 81 struct handler_element 82 { 83 TAILQ_ENTRY(handler_element) list; 84 int (*func)(struct proc *, struct linux_ioctl_args *); 85 int low, high, span; 86 }; 87 88 static TAILQ_HEAD(, handler_element) handlers = 89 TAILQ_HEAD_INITIALIZER(handlers); 90 91 /* 92 * termio related ioctls 93 */ 94 95 struct linux_termio { 96 unsigned short c_iflag; 97 unsigned short c_oflag; 98 unsigned short c_cflag; 99 unsigned short c_lflag; 100 unsigned char c_line; 101 unsigned char c_cc[LINUX_NCC]; 102 }; 103 104 struct linux_termios { 105 unsigned int c_iflag; 106 unsigned int c_oflag; 107 unsigned int c_cflag; 108 unsigned int c_lflag; 109 unsigned char c_line; 110 unsigned char c_cc[LINUX_NCCS]; 111 }; 112 113 struct linux_winsize { 114 unsigned short ws_row, ws_col; 115 unsigned short ws_xpixel, ws_ypixel; 116 }; 117 118 static struct speedtab sptab[] = { 119 { B0, LINUX_B0 }, { B50, LINUX_B50 }, 120 { B75, LINUX_B75 }, { B110, LINUX_B110 }, 121 { B134, LINUX_B134 }, { B150, LINUX_B150 }, 122 { B200, LINUX_B200 }, { B300, LINUX_B300 }, 123 { B600, LINUX_B600 }, { B1200, LINUX_B1200 }, 124 { B1800, LINUX_B1800 }, { B2400, LINUX_B2400 }, 125 { B4800, LINUX_B4800 }, { B9600, LINUX_B9600 }, 126 { B19200, LINUX_B19200 }, { B38400, LINUX_B38400 }, 127 { B57600, LINUX_B57600 }, { B115200, LINUX_B115200 }, 128 {-1, -1 } 129 }; 130 131 struct linux_serial_struct { 132 int type; 133 int line; 134 int port; 135 int irq; 136 int flags; 137 int xmit_fifo_size; 138 int custom_divisor; 139 int baud_base; 140 unsigned short close_delay; 141 char reserved_char[2]; 142 int hub6; 143 unsigned short closing_wait; 144 unsigned short closing_wait2; 145 int reserved[4]; 146 }; 147 148 static int 149 linux_to_bsd_speed(int code, struct speedtab *table) 150 { 151 for ( ; table->sp_code != -1; table++) 152 if (table->sp_code == code) 153 return (table->sp_speed); 154 return -1; 155 } 156 157 static int 158 bsd_to_linux_speed(int speed, struct speedtab *table) 159 { 160 for ( ; table->sp_speed != -1; table++) 161 if (table->sp_speed == speed) 162 return (table->sp_code); 163 return -1; 164 } 165 166 static void 167 bsd_to_linux_termios(struct termios *bios, struct linux_termios *lios) 168 { 169 int i; 170 171 #ifdef DEBUG 172 printf("LINUX: BSD termios structure (input):\n"); 173 printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n", 174 bios->c_iflag, bios->c_oflag, bios->c_cflag, bios->c_lflag, 175 bios->c_ispeed, bios->c_ospeed); 176 printf("c_cc "); 177 for (i=0; i<NCCS; i++) 178 printf("%02x ", bios->c_cc[i]); 179 printf("\n"); 180 #endif 181 182 lios->c_iflag = 0; 183 if (bios->c_iflag & IGNBRK) 184 lios->c_iflag |= LINUX_IGNBRK; 185 if (bios->c_iflag & BRKINT) 186 lios->c_iflag |= LINUX_BRKINT; 187 if (bios->c_iflag & IGNPAR) 188 lios->c_iflag |= LINUX_IGNPAR; 189 if (bios->c_iflag & PARMRK) 190 lios->c_iflag |= LINUX_PARMRK; 191 if (bios->c_iflag & INPCK) 192 lios->c_iflag |= LINUX_INPCK; 193 if (bios->c_iflag & ISTRIP) 194 lios->c_iflag |= LINUX_ISTRIP; 195 if (bios->c_iflag & INLCR) 196 lios->c_iflag |= LINUX_INLCR; 197 if (bios->c_iflag & IGNCR) 198 lios->c_iflag |= LINUX_IGNCR; 199 if (bios->c_iflag & ICRNL) 200 lios->c_iflag |= LINUX_ICRNL; 201 if (bios->c_iflag & IXON) 202 lios->c_iflag |= LINUX_IXON; 203 if (bios->c_iflag & IXANY) 204 lios->c_iflag |= LINUX_IXANY; 205 if (bios->c_iflag & IXOFF) 206 lios->c_iflag |= LINUX_IXOFF; 207 if (bios->c_iflag & IMAXBEL) 208 lios->c_iflag |= LINUX_IMAXBEL; 209 210 lios->c_oflag = 0; 211 if (bios->c_oflag & OPOST) 212 lios->c_oflag |= LINUX_OPOST; 213 if (bios->c_oflag & ONLCR) 214 lios->c_oflag |= LINUX_ONLCR; 215 if (bios->c_oflag & OXTABS) 216 lios->c_oflag |= LINUX_XTABS; 217 218 lios->c_cflag = bsd_to_linux_speed(bios->c_ispeed, sptab); 219 lios->c_cflag |= (bios->c_cflag & CSIZE) >> 4; 220 if (bios->c_cflag & CSTOPB) 221 lios->c_cflag |= LINUX_CSTOPB; 222 if (bios->c_cflag & CREAD) 223 lios->c_cflag |= LINUX_CREAD; 224 if (bios->c_cflag & PARENB) 225 lios->c_cflag |= LINUX_PARENB; 226 if (bios->c_cflag & PARODD) 227 lios->c_cflag |= LINUX_PARODD; 228 if (bios->c_cflag & HUPCL) 229 lios->c_cflag |= LINUX_HUPCL; 230 if (bios->c_cflag & CLOCAL) 231 lios->c_cflag |= LINUX_CLOCAL; 232 if (bios->c_cflag & CRTSCTS) 233 lios->c_cflag |= LINUX_CRTSCTS; 234 235 lios->c_lflag = 0; 236 if (bios->c_lflag & ISIG) 237 lios->c_lflag |= LINUX_ISIG; 238 if (bios->c_lflag & ICANON) 239 lios->c_lflag |= LINUX_ICANON; 240 if (bios->c_lflag & ECHO) 241 lios->c_lflag |= LINUX_ECHO; 242 if (bios->c_lflag & ECHOE) 243 lios->c_lflag |= LINUX_ECHOE; 244 if (bios->c_lflag & ECHOK) 245 lios->c_lflag |= LINUX_ECHOK; 246 if (bios->c_lflag & ECHONL) 247 lios->c_lflag |= LINUX_ECHONL; 248 if (bios->c_lflag & NOFLSH) 249 lios->c_lflag |= LINUX_NOFLSH; 250 if (bios->c_lflag & TOSTOP) 251 lios->c_lflag |= LINUX_TOSTOP; 252 if (bios->c_lflag & ECHOCTL) 253 lios->c_lflag |= LINUX_ECHOCTL; 254 if (bios->c_lflag & ECHOPRT) 255 lios->c_lflag |= LINUX_ECHOPRT; 256 if (bios->c_lflag & ECHOKE) 257 lios->c_lflag |= LINUX_ECHOKE; 258 if (bios->c_lflag & FLUSHO) 259 lios->c_lflag |= LINUX_FLUSHO; 260 if (bios->c_lflag & PENDIN) 261 lios->c_lflag |= LINUX_PENDIN; 262 if (bios->c_lflag & IEXTEN) 263 lios->c_lflag |= LINUX_IEXTEN; 264 265 for (i=0; i<LINUX_NCCS; i++) 266 lios->c_cc[i] = LINUX_POSIX_VDISABLE; 267 lios->c_cc[LINUX_VINTR] = bios->c_cc[VINTR]; 268 lios->c_cc[LINUX_VQUIT] = bios->c_cc[VQUIT]; 269 lios->c_cc[LINUX_VERASE] = bios->c_cc[VERASE]; 270 lios->c_cc[LINUX_VKILL] = bios->c_cc[VKILL]; 271 lios->c_cc[LINUX_VEOF] = bios->c_cc[VEOF]; 272 lios->c_cc[LINUX_VEOL] = bios->c_cc[VEOL]; 273 lios->c_cc[LINUX_VMIN] = bios->c_cc[VMIN]; 274 lios->c_cc[LINUX_VTIME] = bios->c_cc[VTIME]; 275 lios->c_cc[LINUX_VEOL2] = bios->c_cc[VEOL2]; 276 lios->c_cc[LINUX_VSUSP] = bios->c_cc[VSUSP]; 277 lios->c_cc[LINUX_VSTART] = bios->c_cc[VSTART]; 278 lios->c_cc[LINUX_VSTOP] = bios->c_cc[VSTOP]; 279 lios->c_cc[LINUX_VREPRINT] = bios->c_cc[VREPRINT]; 280 lios->c_cc[LINUX_VDISCARD] = bios->c_cc[VDISCARD]; 281 lios->c_cc[LINUX_VWERASE] = bios->c_cc[VWERASE]; 282 lios->c_cc[LINUX_VLNEXT] = bios->c_cc[VLNEXT]; 283 284 for (i=0; i<LINUX_NCCS; i++) { 285 if (lios->c_cc[i] == _POSIX_VDISABLE) 286 lios->c_cc[i] = LINUX_POSIX_VDISABLE; 287 } 288 lios->c_line = 0; 289 290 #ifdef DEBUG 291 printf("LINUX: LINUX termios structure (output):\n"); 292 printf("i=%08x o=%08x c=%08x l=%08x line=%d\n", lios->c_iflag, 293 lios->c_oflag, lios->c_cflag, lios->c_lflag, (int)lios->c_line); 294 printf("c_cc "); 295 for (i=0; i<LINUX_NCCS; i++) 296 printf("%02x ", lios->c_cc[i]); 297 printf("\n"); 298 #endif 299 } 300 301 static void 302 linux_to_bsd_termios(struct linux_termios *lios, struct termios *bios) 303 { 304 int i; 305 306 #ifdef DEBUG 307 printf("LINUX: LINUX termios structure (input):\n"); 308 printf("i=%08x o=%08x c=%08x l=%08x line=%d\n", lios->c_iflag, 309 lios->c_oflag, lios->c_cflag, lios->c_lflag, (int)lios->c_line); 310 printf("c_cc "); 311 for (i=0; i<LINUX_NCCS; i++) 312 printf("%02x ", lios->c_cc[i]); 313 printf("\n"); 314 #endif 315 316 bios->c_iflag = 0; 317 if (lios->c_iflag & LINUX_IGNBRK) 318 bios->c_iflag |= IGNBRK; 319 if (lios->c_iflag & LINUX_BRKINT) 320 bios->c_iflag |= BRKINT; 321 if (lios->c_iflag & LINUX_IGNPAR) 322 bios->c_iflag |= IGNPAR; 323 if (lios->c_iflag & LINUX_PARMRK) 324 bios->c_iflag |= PARMRK; 325 if (lios->c_iflag & LINUX_INPCK) 326 bios->c_iflag |= INPCK; 327 if (lios->c_iflag & LINUX_ISTRIP) 328 bios->c_iflag |= ISTRIP; 329 if (lios->c_iflag & LINUX_INLCR) 330 bios->c_iflag |= INLCR; 331 if (lios->c_iflag & LINUX_IGNCR) 332 bios->c_iflag |= IGNCR; 333 if (lios->c_iflag & LINUX_ICRNL) 334 bios->c_iflag |= ICRNL; 335 if (lios->c_iflag & LINUX_IXON) 336 bios->c_iflag |= IXON; 337 if (lios->c_iflag & LINUX_IXANY) 338 bios->c_iflag |= IXANY; 339 if (lios->c_iflag & LINUX_IXOFF) 340 bios->c_iflag |= IXOFF; 341 if (lios->c_iflag & LINUX_IMAXBEL) 342 bios->c_iflag |= IMAXBEL; 343 344 bios->c_oflag = 0; 345 if (lios->c_oflag & LINUX_OPOST) 346 bios->c_oflag |= OPOST; 347 if (lios->c_oflag & LINUX_ONLCR) 348 bios->c_oflag |= ONLCR; 349 if (lios->c_oflag & LINUX_XTABS) 350 bios->c_oflag |= OXTABS; 351 352 bios->c_cflag = (lios->c_cflag & LINUX_CSIZE) << 4; 353 if (lios->c_cflag & LINUX_CSTOPB) 354 bios->c_cflag |= CSTOPB; 355 if (lios->c_cflag & LINUX_CREAD) 356 bios->c_cflag |= CREAD; 357 if (lios->c_cflag & LINUX_PARENB) 358 bios->c_cflag |= PARENB; 359 if (lios->c_cflag & LINUX_PARODD) 360 bios->c_cflag |= PARODD; 361 if (lios->c_cflag & LINUX_HUPCL) 362 bios->c_cflag |= HUPCL; 363 if (lios->c_cflag & LINUX_CLOCAL) 364 bios->c_cflag |= CLOCAL; 365 if (lios->c_cflag & LINUX_CRTSCTS) 366 bios->c_cflag |= CRTSCTS; 367 368 bios->c_lflag = 0; 369 if (lios->c_lflag & LINUX_ISIG) 370 bios->c_lflag |= ISIG; 371 if (lios->c_lflag & LINUX_ICANON) 372 bios->c_lflag |= ICANON; 373 if (lios->c_lflag & LINUX_ECHO) 374 bios->c_lflag |= ECHO; 375 if (lios->c_lflag & LINUX_ECHOE) 376 bios->c_lflag |= ECHOE; 377 if (lios->c_lflag & LINUX_ECHOK) 378 bios->c_lflag |= ECHOK; 379 if (lios->c_lflag & LINUX_ECHONL) 380 bios->c_lflag |= ECHONL; 381 if (lios->c_lflag & LINUX_NOFLSH) 382 bios->c_lflag |= NOFLSH; 383 if (lios->c_lflag & LINUX_TOSTOP) 384 bios->c_lflag |= TOSTOP; 385 if (lios->c_lflag & LINUX_ECHOCTL) 386 bios->c_lflag |= ECHOCTL; 387 if (lios->c_lflag & LINUX_ECHOPRT) 388 bios->c_lflag |= ECHOPRT; 389 if (lios->c_lflag & LINUX_ECHOKE) 390 bios->c_lflag |= ECHOKE; 391 if (lios->c_lflag & LINUX_FLUSHO) 392 bios->c_lflag |= FLUSHO; 393 if (lios->c_lflag & LINUX_PENDIN) 394 bios->c_lflag |= PENDIN; 395 if (lios->c_lflag & LINUX_IEXTEN) 396 bios->c_lflag |= IEXTEN; 397 398 for (i=0; i<NCCS; i++) 399 bios->c_cc[i] = _POSIX_VDISABLE; 400 bios->c_cc[VINTR] = lios->c_cc[LINUX_VINTR]; 401 bios->c_cc[VQUIT] = lios->c_cc[LINUX_VQUIT]; 402 bios->c_cc[VERASE] = lios->c_cc[LINUX_VERASE]; 403 bios->c_cc[VKILL] = lios->c_cc[LINUX_VKILL]; 404 bios->c_cc[VEOF] = lios->c_cc[LINUX_VEOF]; 405 bios->c_cc[VEOL] = lios->c_cc[LINUX_VEOL]; 406 bios->c_cc[VMIN] = lios->c_cc[LINUX_VMIN]; 407 bios->c_cc[VTIME] = lios->c_cc[LINUX_VTIME]; 408 bios->c_cc[VEOL2] = lios->c_cc[LINUX_VEOL2]; 409 bios->c_cc[VSUSP] = lios->c_cc[LINUX_VSUSP]; 410 bios->c_cc[VSTART] = lios->c_cc[LINUX_VSTART]; 411 bios->c_cc[VSTOP] = lios->c_cc[LINUX_VSTOP]; 412 bios->c_cc[VREPRINT] = lios->c_cc[LINUX_VREPRINT]; 413 bios->c_cc[VDISCARD] = lios->c_cc[LINUX_VDISCARD]; 414 bios->c_cc[VWERASE] = lios->c_cc[LINUX_VWERASE]; 415 bios->c_cc[VLNEXT] = lios->c_cc[LINUX_VLNEXT]; 416 417 for (i=0; i<NCCS; i++) { 418 if (bios->c_cc[i] == LINUX_POSIX_VDISABLE) 419 bios->c_cc[i] = _POSIX_VDISABLE; 420 } 421 422 bios->c_ispeed = bios->c_ospeed = 423 linux_to_bsd_speed(lios->c_cflag & LINUX_CBAUD, sptab); 424 425 #ifdef DEBUG 426 printf("LINUX: BSD termios structure (output):\n"); 427 printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n", 428 bios->c_iflag, bios->c_oflag, bios->c_cflag, bios->c_lflag, 429 bios->c_ispeed, bios->c_ospeed); 430 printf("c_cc "); 431 for (i=0; i<NCCS; i++) 432 printf("%02x ", bios->c_cc[i]); 433 printf("\n"); 434 #endif 435 } 436 437 static void 438 bsd_to_linux_termio(struct termios *bios, struct linux_termio *lio) 439 { 440 struct linux_termios lios; 441 442 bsd_to_linux_termios(bios, &lios); 443 lio->c_iflag = lios.c_iflag; 444 lio->c_oflag = lios.c_oflag; 445 lio->c_cflag = lios.c_cflag; 446 lio->c_lflag = lios.c_lflag; 447 lio->c_line = lios.c_line; 448 memcpy(lio->c_cc, lios.c_cc, LINUX_NCC); 449 } 450 451 static void 452 linux_to_bsd_termio(struct linux_termio *lio, struct termios *bios) 453 { 454 struct linux_termios lios; 455 int i; 456 457 lios.c_iflag = lio->c_iflag; 458 lios.c_oflag = lio->c_oflag; 459 lios.c_cflag = lio->c_cflag; 460 lios.c_lflag = lio->c_lflag; 461 for (i=LINUX_NCC; i<LINUX_NCCS; i++) 462 lios.c_cc[i] = LINUX_POSIX_VDISABLE; 463 memcpy(lios.c_cc, lio->c_cc, LINUX_NCC); 464 linux_to_bsd_termios(&lios, bios); 465 } 466 467 static int 468 linux_ioctl_termio(struct proc *p, struct linux_ioctl_args *args) 469 { 470 struct termios bios; 471 struct linux_termios lios; 472 struct linux_termio lio; 473 struct file *fp = p->p_fd->fd_ofiles[args->fd]; 474 int error; 475 476 switch (args->cmd & 0xffff) { 477 478 case LINUX_TCGETS: 479 error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, p); 480 if (error) 481 return (error); 482 bsd_to_linux_termios(&bios, &lios); 483 return copyout(&lios, (caddr_t)args->arg, sizeof(lios)); 484 485 case LINUX_TCSETS: 486 error = copyin((caddr_t)args->arg, &lios, sizeof(lios)); 487 if (error) 488 return (error); 489 linux_to_bsd_termios(&lios, &bios); 490 return (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, p)); 491 492 case LINUX_TCSETSW: 493 error = copyin((caddr_t)args->arg, &lios, sizeof(lios)); 494 if (error) 495 return (error); 496 linux_to_bsd_termios(&lios, &bios); 497 return (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, p)); 498 499 case LINUX_TCSETSF: 500 error = copyin((caddr_t)args->arg, &lios, sizeof(lios)); 501 if (error) 502 return (error); 503 linux_to_bsd_termios(&lios, &bios); 504 return (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, p)); 505 506 case LINUX_TCGETA: 507 error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, p); 508 if (error) 509 return (error); 510 bsd_to_linux_termio(&bios, &lio); 511 return (copyout(&lio, (caddr_t)args->arg, sizeof(lio))); 512 513 case LINUX_TCSETA: 514 error = copyin((caddr_t)args->arg, &lio, sizeof(lio)); 515 if (error) 516 return (error); 517 linux_to_bsd_termio(&lio, &bios); 518 return (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, p)); 519 520 case LINUX_TCSETAW: 521 error = copyin((caddr_t)args->arg, &lio, sizeof(lio)); 522 if (error) 523 return (error); 524 linux_to_bsd_termio(&lio, &bios); 525 return (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, p)); 526 527 case LINUX_TCSETAF: 528 error = copyin((caddr_t)args->arg, &lio, sizeof(lio)); 529 if (error) 530 return (error); 531 linux_to_bsd_termio(&lio, &bios); 532 return (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, p)); 533 534 /* LINUX_TCSBRK */ 535 536 case LINUX_TCXONC: { 537 switch (args->arg) { 538 case LINUX_TCOOFF: 539 args->cmd = TIOCSTOP; 540 break; 541 case LINUX_TCOON: 542 args->cmd = TIOCSTART; 543 break; 544 case LINUX_TCIOFF: 545 case LINUX_TCION: { 546 int c; 547 struct write_args wr; 548 error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, p); 549 if (error) 550 return (error); 551 c = (args->arg == LINUX_TCIOFF) ? VSTOP : VSTART; 552 c = bios.c_cc[c]; 553 if (c != _POSIX_VDISABLE) { 554 wr.fd = args->fd; 555 wr.buf = &c; 556 wr.nbyte = sizeof(c); 557 return (write(p, &wr)); 558 } else 559 return (0); 560 } 561 default: 562 return (EINVAL); 563 } 564 args->arg = 0; 565 return (ioctl(p, (struct ioctl_args *)args)); 566 } 567 568 case LINUX_TCFLSH: { 569 args->cmd = TIOCFLUSH; 570 switch (args->arg) { 571 case LINUX_TCIFLUSH: 572 args->arg = FREAD; 573 break; 574 case LINUX_TCOFLUSH: 575 args->arg = FWRITE; 576 break; 577 case LINUX_TCIOFLUSH: 578 args->arg = FREAD | FWRITE; 579 break; 580 default: 581 return (EINVAL); 582 } 583 return (ioctl(p, (struct ioctl_args *)args)); 584 } 585 586 case LINUX_TIOCEXCL: 587 args->cmd = TIOCEXCL; 588 return (ioctl(p, (struct ioctl_args *)args)); 589 590 case LINUX_TIOCNXCL: 591 args->cmd = TIOCNXCL; 592 return (ioctl(p, (struct ioctl_args *)args)); 593 594 /* LINUX_TIOCSCTTY */ 595 596 case LINUX_TIOCGPGRP: 597 args->cmd = TIOCGPGRP; 598 return (ioctl(p, (struct ioctl_args *)args)); 599 600 case LINUX_TIOCSPGRP: 601 args->cmd = TIOCSPGRP; 602 return (ioctl(p, (struct ioctl_args *)args)); 603 604 /* LINUX_TIOCOUTQ */ 605 /* LINUX_TIOCSTI */ 606 607 case LINUX_TIOCGWINSZ: 608 args->cmd = TIOCGWINSZ; 609 return (ioctl(p, (struct ioctl_args *)args)); 610 611 case LINUX_TIOCSWINSZ: 612 args->cmd = TIOCSWINSZ; 613 return (ioctl(p, (struct ioctl_args *)args)); 614 615 case LINUX_TIOCMGET: 616 args->cmd = TIOCMGET; 617 return (ioctl(p, (struct ioctl_args *)args)); 618 619 case LINUX_TIOCMBIS: 620 args->cmd = TIOCMBIS; 621 return (ioctl(p, (struct ioctl_args *)args)); 622 623 case LINUX_TIOCMBIC: 624 args->cmd = TIOCMBIC; 625 return (ioctl(p, (struct ioctl_args *)args)); 626 627 case LINUX_TIOCMSET: 628 args->cmd = TIOCMSET; 629 return (ioctl(p, (struct ioctl_args *)args)); 630 631 /* TIOCGSOFTCAR */ 632 /* TIOCSSOFTCAR */ 633 634 case LINUX_FIONREAD: /* LINUX_TIOCINQ */ 635 args->cmd = FIONREAD; 636 return (ioctl(p, (struct ioctl_args *)args)); 637 638 /* LINUX_TIOCLINUX */ 639 640 case LINUX_TIOCCONS: 641 args->cmd = TIOCCONS; 642 return (ioctl(p, (struct ioctl_args *)args)); 643 644 case LINUX_TIOCGSERIAL: { 645 struct linux_serial_struct lss; 646 lss.type = LINUX_PORT_16550A; 647 lss.flags = 0; 648 lss.close_delay = 0; 649 return copyout(&lss, (caddr_t)args->arg, sizeof(lss)); 650 } 651 652 case LINUX_TIOCSSERIAL: { 653 struct linux_serial_struct lss; 654 error = copyin((caddr_t)args->arg, &lss, sizeof(lss)); 655 if (error) 656 return (error); 657 /* XXX - It really helps to have an implementation that 658 * does nothing. NOT! 659 */ 660 return (0); 661 } 662 663 /* LINUX_TIOCPKT */ 664 665 case LINUX_FIONBIO: 666 args->cmd = FIONBIO; 667 return (ioctl(p, (struct ioctl_args *)args)); 668 669 case LINUX_TIOCNOTTY: 670 args->cmd = TIOCNOTTY; 671 return (ioctl(p, (struct ioctl_args *)args)); 672 673 case LINUX_TIOCSETD: { 674 int line; 675 switch (args->arg) { 676 case LINUX_N_TTY: 677 line = TTYDISC; 678 break; 679 case LINUX_N_SLIP: 680 line = SLIPDISC; 681 break; 682 case LINUX_N_PPP: 683 line = PPPDISC; 684 break; 685 default: 686 return (EINVAL); 687 } 688 return (fo_ioctl(fp, TIOCSETD, (caddr_t)&line, p)); 689 } 690 691 case LINUX_TIOCGETD: { 692 int linux_line; 693 int bsd_line = TTYDISC; 694 error = fo_ioctl(fp, TIOCGETD, (caddr_t)&bsd_line, p); 695 if (error) 696 return (error); 697 switch (bsd_line) { 698 case TTYDISC: 699 linux_line = LINUX_N_TTY; 700 break; 701 case SLIPDISC: 702 linux_line = LINUX_N_SLIP; 703 break; 704 case PPPDISC: 705 linux_line = LINUX_N_PPP; 706 break; 707 default: 708 return (EINVAL); 709 } 710 return (copyout(&linux_line, (caddr_t)args->arg, sizeof(int))); 711 } 712 713 /* LINUX_TCSBRKP */ 714 /* LINUX_TIOCTTYGSTRUCT */ 715 716 case LINUX_FIONCLEX: 717 args->cmd = FIONCLEX; 718 return (ioctl(p, (struct ioctl_args *)args)); 719 720 case LINUX_FIOCLEX: 721 args->cmd = FIOCLEX; 722 return (ioctl(p, (struct ioctl_args *)args)); 723 724 case LINUX_FIOASYNC: 725 args->cmd = FIOASYNC; 726 return (ioctl(p, (struct ioctl_args *)args)); 727 728 /* LINUX_TIOCSERCONFIG */ 729 /* LINUX_TIOCSERGWILD */ 730 /* LINUX_TIOCSERSWILD */ 731 /* LINUX_TIOCGLCKTRMIOS */ 732 /* LINUX_TIOCSLCKTRMIOS */ 733 734 } 735 736 return (ENOIOCTL); 737 } 738 739 /* 740 * CDROM related ioctls 741 */ 742 743 struct linux_cdrom_msf 744 { 745 u_char cdmsf_min0; 746 u_char cdmsf_sec0; 747 u_char cdmsf_frame0; 748 u_char cdmsf_min1; 749 u_char cdmsf_sec1; 750 u_char cdmsf_frame1; 751 }; 752 753 struct linux_cdrom_tochdr 754 { 755 u_char cdth_trk0; 756 u_char cdth_trk1; 757 }; 758 759 union linux_cdrom_addr 760 { 761 struct { 762 u_char minute; 763 u_char second; 764 u_char frame; 765 } msf; 766 int lba; 767 }; 768 769 struct linux_cdrom_tocentry 770 { 771 u_char cdte_track; 772 u_char cdte_adr:4; 773 u_char cdte_ctrl:4; 774 u_char cdte_format; 775 union linux_cdrom_addr cdte_addr; 776 u_char cdte_datamode; 777 }; 778 779 struct linux_cdrom_subchnl 780 { 781 u_char cdsc_format; 782 u_char cdsc_audiostatus; 783 u_char cdsc_adr:4; 784 u_char cdsc_ctrl:4; 785 u_char cdsc_trk; 786 u_char cdsc_ind; 787 union linux_cdrom_addr cdsc_absaddr; 788 union linux_cdrom_addr cdsc_reladdr; 789 }; 790 791 static void 792 bsd_to_linux_msf_lba(u_char af, union msf_lba *bp, union linux_cdrom_addr *lp) 793 { 794 if (af == CD_LBA_FORMAT) 795 lp->lba = bp->lba; 796 else { 797 lp->msf.minute = bp->msf.minute; 798 lp->msf.second = bp->msf.second; 799 lp->msf.frame = bp->msf.frame; 800 } 801 } 802 803 static void 804 set_linux_cdrom_addr(union linux_cdrom_addr *addr, int format, int lba) 805 { 806 if (format == LINUX_CDROM_MSF) { 807 addr->msf.frame = lba % 75; 808 lba /= 75; 809 lba += 2; 810 addr->msf.second = lba % 60; 811 addr->msf.minute = lba / 60; 812 } else 813 addr->lba = lba; 814 } 815 816 static int 817 linux_ioctl_cdrom(struct proc *p, struct linux_ioctl_args *args) 818 { 819 struct file *fp = p->p_fd->fd_ofiles[args->fd]; 820 int error; 821 822 switch (args->cmd & 0xffff) { 823 824 case LINUX_CDROMPAUSE: 825 args->cmd = CDIOCPAUSE; 826 return (ioctl(p, (struct ioctl_args *)args)); 827 828 case LINUX_CDROMRESUME: 829 args->cmd = CDIOCRESUME; 830 return (ioctl(p, (struct ioctl_args *)args)); 831 832 case LINUX_CDROMPLAYMSF: 833 args->cmd = CDIOCPLAYMSF; 834 return (ioctl(p, (struct ioctl_args *)args)); 835 836 case LINUX_CDROMPLAYTRKIND: 837 args->cmd = CDIOCPLAYTRACKS; 838 return (ioctl(p, (struct ioctl_args *)args)); 839 840 case LINUX_CDROMREADTOCHDR: { 841 struct ioc_toc_header th; 842 struct linux_cdrom_tochdr lth; 843 error = fo_ioctl(fp, CDIOREADTOCHEADER, (caddr_t)&th, p); 844 if (!error) { 845 lth.cdth_trk0 = th.starting_track; 846 lth.cdth_trk1 = th.ending_track; 847 copyout(<h, (caddr_t)args->arg, sizeof(lth)); 848 } 849 return (error); 850 } 851 852 case LINUX_CDROMREADTOCENTRY: { 853 struct linux_cdrom_tocentry lte, *ltep = 854 (struct linux_cdrom_tocentry *)args->arg; 855 struct ioc_read_toc_single_entry irtse; 856 irtse.address_format = ltep->cdte_format; 857 irtse.track = ltep->cdte_track; 858 error = fo_ioctl(fp, CDIOREADTOCENTRY, (caddr_t)&irtse, p); 859 if (!error) { 860 lte = *ltep; 861 lte.cdte_ctrl = irtse.entry.control; 862 lte.cdte_adr = irtse.entry.addr_type; 863 bsd_to_linux_msf_lba(irtse.address_format, 864 &irtse.entry.addr, <e.cdte_addr); 865 copyout(<e, (caddr_t)args->arg, sizeof(lte)); 866 } 867 return (error); 868 } 869 870 case LINUX_CDROMSTOP: 871 args->cmd = CDIOCSTOP; 872 return (ioctl(p, (struct ioctl_args *)args)); 873 874 case LINUX_CDROMSTART: 875 args->cmd = CDIOCSTART; 876 return (ioctl(p, (struct ioctl_args *)args)); 877 878 case LINUX_CDROMEJECT: 879 args->cmd = CDIOCEJECT; 880 return (ioctl(p, (struct ioctl_args *)args)); 881 882 /* LINUX_CDROMVOLCTRL */ 883 884 case LINUX_CDROMSUBCHNL: { 885 struct linux_cdrom_subchnl sc; 886 struct ioc_read_subchannel bsdsc; 887 struct cd_sub_channel_info *bsdinfo; 888 caddr_t sg = stackgap_init(); 889 bsdinfo = (struct cd_sub_channel_info*)stackgap_alloc(&sg, 890 sizeof(struct cd_sub_channel_info)); 891 bsdsc.address_format = CD_LBA_FORMAT; 892 bsdsc.data_format = CD_CURRENT_POSITION; 893 bsdsc.track = 0; 894 bsdsc.data_len = sizeof(struct cd_sub_channel_info); 895 bsdsc.data = bsdinfo; 896 error = fo_ioctl(fp, CDIOCREADSUBCHANNEL, (caddr_t)&bsdsc, p); 897 if (error) 898 return (error); 899 error = copyin((caddr_t)args->arg, &sc, 900 sizeof(struct linux_cdrom_subchnl)); 901 if (error) 902 return (error); 903 sc.cdsc_audiostatus = bsdinfo->header.audio_status; 904 sc.cdsc_adr = bsdinfo->what.position.addr_type; 905 sc.cdsc_ctrl = bsdinfo->what.position.control; 906 sc.cdsc_trk = bsdinfo->what.position.track_number; 907 sc.cdsc_ind = bsdinfo->what.position.index_number; 908 set_linux_cdrom_addr(&sc.cdsc_absaddr, sc.cdsc_format, 909 bsdinfo->what.position.absaddr.lba); 910 set_linux_cdrom_addr(&sc.cdsc_reladdr, sc.cdsc_format, 911 bsdinfo->what.position.reladdr.lba); 912 error = copyout(&sc, (caddr_t)args->arg, 913 sizeof(struct linux_cdrom_subchnl)); 914 return (error); 915 } 916 917 /* LINUX_CDROMREADMODE2 */ 918 /* LINUX_CDROMREADMODE1 */ 919 /* LINUX_CDROMREADAUDIO */ 920 /* LINUX_CDROMEJECT_SW */ 921 /* LINUX_CDROMMULTISESSION */ 922 /* LINUX_CDROM_GET_UPC */ 923 924 case LINUX_CDROMRESET: 925 args->cmd = CDIOCRESET; 926 return (ioctl(p, (struct ioctl_args *)args)); 927 928 /* LINUX_CDROMVOLREAD */ 929 /* LINUX_CDROMREADRAW */ 930 /* LINUX_CDROMREADCOOKED */ 931 /* LINUX_CDROMSEEK */ 932 /* LINUX_CDROMPLAYBLK */ 933 /* LINUX_CDROMREADALL */ 934 /* LINUX_CDROMCLOSETRAY */ 935 /* LINUX_CDROMLOADFROMSLOT */ 936 937 } 938 939 return (ENOIOCTL); 940 } 941 942 /* 943 * Sound related ioctls 944 */ 945 946 static unsigned dirbits[4] = { IOC_VOID, IOC_IN, IOC_OUT, IOC_INOUT }; 947 948 #define SETDIR(c) (((c) & ~IOC_DIRMASK) | dirbits[args->cmd >> 30]) 949 950 static int 951 linux_ioctl_sound(struct proc *p, struct linux_ioctl_args *args) 952 { 953 954 switch (args->cmd & 0xffff) { 955 956 case LINUX_SOUND_MIXER_WRITE_VOLUME: 957 args->cmd = SETDIR(SOUND_MIXER_WRITE_VOLUME); 958 return (ioctl(p, (struct ioctl_args *)args)); 959 960 case LINUX_SOUND_MIXER_WRITE_BASS: 961 args->cmd = SETDIR(SOUND_MIXER_WRITE_BASS); 962 return (ioctl(p, (struct ioctl_args *)args)); 963 964 case LINUX_SOUND_MIXER_WRITE_TREBLE: 965 args->cmd = SETDIR(SOUND_MIXER_WRITE_TREBLE); 966 return (ioctl(p, (struct ioctl_args *)args)); 967 968 case LINUX_SOUND_MIXER_WRITE_SYNTH: 969 args->cmd = SETDIR(SOUND_MIXER_WRITE_SYNTH); 970 return (ioctl(p, (struct ioctl_args *)args)); 971 972 case LINUX_SOUND_MIXER_WRITE_PCM: 973 args->cmd = SETDIR(SOUND_MIXER_WRITE_PCM); 974 return (ioctl(p, (struct ioctl_args *)args)); 975 976 case LINUX_SOUND_MIXER_WRITE_SPEAKER: 977 args->cmd = SETDIR(SOUND_MIXER_WRITE_SPEAKER); 978 return (ioctl(p, (struct ioctl_args *)args)); 979 980 case LINUX_SOUND_MIXER_WRITE_LINE: 981 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE); 982 return (ioctl(p, (struct ioctl_args *)args)); 983 984 case LINUX_SOUND_MIXER_WRITE_MIC: 985 args->cmd = SETDIR(SOUND_MIXER_WRITE_MIC); 986 return (ioctl(p, (struct ioctl_args *)args)); 987 988 case LINUX_SOUND_MIXER_WRITE_CD: 989 args->cmd = SETDIR(SOUND_MIXER_WRITE_CD); 990 return (ioctl(p, (struct ioctl_args *)args)); 991 992 case LINUX_SOUND_MIXER_WRITE_IMIX: 993 args->cmd = SETDIR(SOUND_MIXER_WRITE_IMIX); 994 return (ioctl(p, (struct ioctl_args *)args)); 995 996 case LINUX_SOUND_MIXER_WRITE_ALTPCM: 997 args->cmd = SETDIR(SOUND_MIXER_WRITE_ALTPCM); 998 return (ioctl(p, (struct ioctl_args *)args)); 999 1000 case LINUX_SOUND_MIXER_WRITE_RECLEV: 1001 args->cmd = SETDIR(SOUND_MIXER_WRITE_RECLEV); 1002 return (ioctl(p, (struct ioctl_args *)args)); 1003 1004 case LINUX_SOUND_MIXER_WRITE_IGAIN: 1005 args->cmd = SETDIR(SOUND_MIXER_WRITE_IGAIN); 1006 return (ioctl(p, (struct ioctl_args *)args)); 1007 1008 case LINUX_SOUND_MIXER_WRITE_OGAIN: 1009 args->cmd = SETDIR(SOUND_MIXER_WRITE_OGAIN); 1010 return (ioctl(p, (struct ioctl_args *)args)); 1011 1012 case LINUX_SOUND_MIXER_WRITE_LINE1: 1013 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE1); 1014 return (ioctl(p, (struct ioctl_args *)args)); 1015 1016 case LINUX_SOUND_MIXER_WRITE_LINE2: 1017 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE2); 1018 return (ioctl(p, (struct ioctl_args *)args)); 1019 1020 case LINUX_SOUND_MIXER_WRITE_LINE3: 1021 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE3); 1022 return (ioctl(p, (struct ioctl_args *)args)); 1023 1024 case LINUX_OSS_GETVERSION: { 1025 int version = linux_get_oss_version(p); 1026 return (copyout(&version, (caddr_t)args->arg, sizeof(int))); 1027 } 1028 1029 case LINUX_SOUND_MIXER_READ_DEVMASK: 1030 args->cmd = SOUND_MIXER_READ_DEVMASK; 1031 return (ioctl(p, (struct ioctl_args *)args)); 1032 1033 case LINUX_SNDCTL_DSP_RESET: 1034 args->cmd = SNDCTL_DSP_RESET; 1035 return (ioctl(p, (struct ioctl_args *)args)); 1036 1037 case LINUX_SNDCTL_DSP_SYNC: 1038 args->cmd = SNDCTL_DSP_SYNC; 1039 return (ioctl(p, (struct ioctl_args *)args)); 1040 1041 case LINUX_SNDCTL_DSP_SPEED: 1042 args->cmd = SNDCTL_DSP_SPEED; 1043 return (ioctl(p, (struct ioctl_args *)args)); 1044 1045 case LINUX_SNDCTL_DSP_STEREO: 1046 args->cmd = SNDCTL_DSP_STEREO; 1047 return (ioctl(p, (struct ioctl_args *)args)); 1048 1049 case LINUX_SNDCTL_DSP_GETBLKSIZE: /* LINUX_SNDCTL_DSP_SETBLKSIZE */ 1050 args->cmd = SNDCTL_DSP_GETBLKSIZE; 1051 return (ioctl(p, (struct ioctl_args *)args)); 1052 1053 case LINUX_SNDCTL_DSP_SETFMT: 1054 args->cmd = SNDCTL_DSP_SETFMT; 1055 return (ioctl(p, (struct ioctl_args *)args)); 1056 1057 case LINUX_SOUND_PCM_WRITE_CHANNELS: 1058 args->cmd = SOUND_PCM_WRITE_CHANNELS; 1059 return (ioctl(p, (struct ioctl_args *)args)); 1060 1061 case LINUX_SOUND_PCM_WRITE_FILTER: 1062 args->cmd = SOUND_PCM_WRITE_FILTER; 1063 return (ioctl(p, (struct ioctl_args *)args)); 1064 1065 case LINUX_SNDCTL_DSP_POST: 1066 args->cmd = SNDCTL_DSP_POST; 1067 return (ioctl(p, (struct ioctl_args *)args)); 1068 1069 case LINUX_SNDCTL_DSP_SUBDIVIDE: 1070 args->cmd = SNDCTL_DSP_SUBDIVIDE; 1071 return (ioctl(p, (struct ioctl_args *)args)); 1072 1073 case LINUX_SNDCTL_DSP_SETFRAGMENT: 1074 args->cmd = SNDCTL_DSP_SETFRAGMENT; 1075 return (ioctl(p, (struct ioctl_args *)args)); 1076 1077 case LINUX_SNDCTL_DSP_GETFMTS: 1078 args->cmd = SNDCTL_DSP_GETFMTS; 1079 return (ioctl(p, (struct ioctl_args *)args)); 1080 1081 case LINUX_SNDCTL_DSP_GETOSPACE: 1082 args->cmd = SNDCTL_DSP_GETOSPACE; 1083 return (ioctl(p, (struct ioctl_args *)args)); 1084 1085 case LINUX_SNDCTL_DSP_GETISPACE: 1086 args->cmd = SNDCTL_DSP_GETISPACE; 1087 return (ioctl(p, (struct ioctl_args *)args)); 1088 1089 case LINUX_SNDCTL_DSP_NONBLOCK: 1090 args->cmd = SNDCTL_DSP_NONBLOCK; 1091 return (ioctl(p, (struct ioctl_args *)args)); 1092 1093 case LINUX_SNDCTL_DSP_GETCAPS: 1094 args->cmd = SNDCTL_DSP_GETCAPS; 1095 return (ioctl(p, (struct ioctl_args *)args)); 1096 1097 case LINUX_SNDCTL_DSP_SETTRIGGER: /* LINUX_SNDCTL_GETTRIGGER */ 1098 args->cmd = SNDCTL_DSP_SETTRIGGER; 1099 return (ioctl(p, (struct ioctl_args *)args)); 1100 1101 case LINUX_SNDCTL_DSP_GETIPTR: 1102 args->cmd = SNDCTL_DSP_GETIPTR; 1103 return (ioctl(p, (struct ioctl_args *)args)); 1104 1105 case LINUX_SNDCTL_DSP_GETOPTR: 1106 args->cmd = SNDCTL_DSP_GETOPTR; 1107 return (ioctl(p, (struct ioctl_args *)args)); 1108 1109 case LINUX_SNDCTL_DSP_GETODELAY: 1110 args->cmd = SNDCTL_DSP_GETODELAY; 1111 return (ioctl(p, (struct ioctl_args *)args)); 1112 1113 case LINUX_SNDCTL_SEQ_RESET: 1114 args->cmd = SNDCTL_SEQ_RESET; 1115 return (ioctl(p, (struct ioctl_args *)args)); 1116 1117 case LINUX_SNDCTL_SEQ_SYNC: 1118 args->cmd = SNDCTL_SEQ_SYNC; 1119 return (ioctl(p, (struct ioctl_args *)args)); 1120 1121 case LINUX_SNDCTL_SYNTH_INFO: 1122 args->cmd = SNDCTL_SYNTH_INFO; 1123 return (ioctl(p, (struct ioctl_args *)args)); 1124 1125 case LINUX_SNDCTL_SEQ_CTRLRATE: 1126 args->cmd = SNDCTL_SEQ_CTRLRATE; 1127 return (ioctl(p, (struct ioctl_args *)args)); 1128 1129 case LINUX_SNDCTL_SEQ_GETOUTCOUNT: 1130 args->cmd = SNDCTL_SEQ_GETOUTCOUNT; 1131 return (ioctl(p, (struct ioctl_args *)args)); 1132 1133 case LINUX_SNDCTL_SEQ_GETINCOUNT: 1134 args->cmd = SNDCTL_SEQ_GETINCOUNT; 1135 return (ioctl(p, (struct ioctl_args *)args)); 1136 1137 case LINUX_SNDCTL_SEQ_PERCMODE: 1138 args->cmd = SNDCTL_SEQ_PERCMODE; 1139 return (ioctl(p, (struct ioctl_args *)args)); 1140 1141 case LINUX_SNDCTL_FM_LOAD_INSTR: 1142 args->cmd = SNDCTL_FM_LOAD_INSTR; 1143 return (ioctl(p, (struct ioctl_args *)args)); 1144 1145 case LINUX_SNDCTL_SEQ_TESTMIDI: 1146 args->cmd = SNDCTL_SEQ_TESTMIDI; 1147 return (ioctl(p, (struct ioctl_args *)args)); 1148 1149 case LINUX_SNDCTL_SEQ_RESETSAMPLES: 1150 args->cmd = SNDCTL_SEQ_RESETSAMPLES; 1151 return (ioctl(p, (struct ioctl_args *)args)); 1152 1153 case LINUX_SNDCTL_SEQ_NRSYNTHS: 1154 args->cmd = SNDCTL_SEQ_NRSYNTHS; 1155 return (ioctl(p, (struct ioctl_args *)args)); 1156 1157 case LINUX_SNDCTL_SEQ_NRMIDIS: 1158 args->cmd = SNDCTL_SEQ_NRMIDIS; 1159 return (ioctl(p, (struct ioctl_args *)args)); 1160 1161 case LINUX_SNDCTL_MIDI_INFO: 1162 args->cmd = SNDCTL_MIDI_INFO; 1163 return (ioctl(p, (struct ioctl_args *)args)); 1164 1165 case LINUX_SNDCTL_SEQ_TRESHOLD: 1166 args->cmd = SNDCTL_SEQ_TRESHOLD; 1167 return (ioctl(p, (struct ioctl_args *)args)); 1168 1169 case LINUX_SNDCTL_SYNTH_MEMAVL: 1170 args->cmd = SNDCTL_SYNTH_MEMAVL; 1171 return (ioctl(p, (struct ioctl_args *)args)); 1172 1173 } 1174 1175 return (ENOIOCTL); 1176 } 1177 1178 /* 1179 * Console related ioctls 1180 */ 1181 1182 #define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG) 1183 1184 static int 1185 linux_ioctl_console(struct proc *p, struct linux_ioctl_args *args) 1186 { 1187 struct file *fp = p->p_fd->fd_ofiles[args->fd]; 1188 1189 switch (args->cmd & 0xffff) { 1190 1191 case LINUX_KIOCSOUND: 1192 args->cmd = KIOCSOUND; 1193 return (ioctl(p, (struct ioctl_args *)args)); 1194 1195 case LINUX_KDMKTONE: 1196 args->cmd = KDMKTONE; 1197 return (ioctl(p, (struct ioctl_args *)args)); 1198 1199 case LINUX_KDGETLED: 1200 args->cmd = KDGETLED; 1201 return (ioctl(p, (struct ioctl_args *)args)); 1202 1203 case LINUX_KDSETLED: 1204 args->cmd = KDSETLED; 1205 return (ioctl(p, (struct ioctl_args *)args)); 1206 1207 case LINUX_KDSETMODE: 1208 args->cmd = KDSETMODE; 1209 return (ioctl(p, (struct ioctl_args *)args)); 1210 1211 case LINUX_KDGETMODE: 1212 args->cmd = KDGETMODE; 1213 return (ioctl(p, (struct ioctl_args *)args)); 1214 1215 case LINUX_KDGKBMODE: 1216 args->cmd = KDGKBMODE; 1217 return (ioctl(p, (struct ioctl_args *)args)); 1218 1219 case LINUX_KDSKBMODE: { 1220 int kbdmode; 1221 switch (args->arg) { 1222 case LINUX_KBD_RAW: 1223 kbdmode = K_RAW; 1224 break; 1225 case LINUX_KBD_XLATE: 1226 kbdmode = K_XLATE; 1227 break; 1228 case LINUX_KBD_MEDIUMRAW: 1229 kbdmode = K_RAW; 1230 break; 1231 default: 1232 return (EINVAL); 1233 } 1234 return (fo_ioctl(fp, KDSKBMODE, (caddr_t)&kbdmode, p)); 1235 } 1236 1237 case LINUX_VT_OPENQRY: 1238 args->cmd = VT_OPENQRY; 1239 return (ioctl(p, (struct ioctl_args *)args)); 1240 1241 case LINUX_VT_GETMODE: 1242 args->cmd = VT_GETMODE; 1243 return (ioctl(p, (struct ioctl_args *)args)); 1244 1245 case LINUX_VT_SETMODE: { 1246 struct vt_mode *mode; 1247 args->cmd = VT_SETMODE; 1248 mode = (struct vt_mode *)args->arg; 1249 if (!ISSIGVALID(mode->frsig) && ISSIGVALID(mode->acqsig)) 1250 mode->frsig = mode->acqsig; 1251 return (ioctl(p, (struct ioctl_args *)args)); 1252 } 1253 1254 case LINUX_VT_GETSTATE: 1255 args->cmd = VT_GETACTIVE; 1256 return (ioctl(p, (struct ioctl_args *)args)); 1257 1258 case LINUX_VT_RELDISP: 1259 args->cmd = VT_RELDISP; 1260 return (ioctl(p, (struct ioctl_args *)args)); 1261 1262 case LINUX_VT_ACTIVATE: 1263 args->cmd = VT_ACTIVATE; 1264 return (ioctl(p, (struct ioctl_args *)args)); 1265 1266 case LINUX_VT_WAITACTIVE: 1267 args->cmd = VT_WAITACTIVE; 1268 return (ioctl(p, (struct ioctl_args *)args)); 1269 1270 } 1271 1272 return (ENOIOCTL); 1273 } 1274 1275 /* 1276 * Socket related ioctls 1277 */ 1278 1279 static int 1280 linux_ioctl_socket(struct proc *p, struct linux_ioctl_args *args) 1281 { 1282 1283 switch (args->cmd & 0xffff) { 1284 1285 case LINUX_FIOSETOWN: 1286 args->cmd = FIOSETOWN; 1287 return (ioctl(p, (struct ioctl_args *)args)); 1288 1289 case LINUX_SIOCSPGRP: 1290 args->cmd = SIOCSPGRP; 1291 return (ioctl(p, (struct ioctl_args *)args)); 1292 1293 case LINUX_FIOGETOWN: 1294 args->cmd = FIOGETOWN; 1295 return (ioctl(p, (struct ioctl_args *)args)); 1296 1297 case LINUX_SIOCGPGRP: 1298 args->cmd = SIOCGPGRP; 1299 return (ioctl(p, (struct ioctl_args *)args)); 1300 1301 case LINUX_SIOCATMARK: 1302 args->cmd = SIOCATMARK; 1303 return (ioctl(p, (struct ioctl_args *)args)); 1304 1305 /* LINUX_SIOCGSTAMP */ 1306 1307 case LINUX_SIOCGIFCONF: 1308 args->cmd = OSIOCGIFCONF; 1309 return (ioctl(p, (struct ioctl_args *)args)); 1310 1311 case LINUX_SIOCGIFFLAGS: 1312 args->cmd = SIOCGIFFLAGS; 1313 return (ioctl(p, (struct ioctl_args *)args)); 1314 1315 case LINUX_SIOCGIFADDR: 1316 args->cmd = OSIOCGIFADDR; 1317 return (ioctl(p, (struct ioctl_args *)args)); 1318 1319 case LINUX_SIOCGIFDSTADDR: 1320 args->cmd = OSIOCGIFDSTADDR; 1321 return (ioctl(p, (struct ioctl_args *)args)); 1322 1323 case LINUX_SIOCGIFBRDADDR: 1324 args->cmd = OSIOCGIFBRDADDR; 1325 return (ioctl(p, (struct ioctl_args *)args)); 1326 1327 case LINUX_SIOCGIFNETMASK: 1328 args->cmd = OSIOCGIFNETMASK; 1329 return (ioctl(p, (struct ioctl_args *)args)); 1330 1331 case LINUX_SIOCGIFHWADDR: { 1332 int ifn; 1333 struct ifnet *ifp; 1334 struct ifaddr *ifa; 1335 struct sockaddr_dl *sdl; 1336 struct linux_ifreq *ifr = (struct linux_ifreq *)args->arg; 1337 1338 /* Note that we don't actually respect the name in the ifreq 1339 * structure, as Linux interface names are all different. 1340 */ 1341 for (ifn = 0; ifn < if_index; ifn++) { 1342 ifp = ifnet_addrs[ifn]->ifa_ifp; 1343 if (ifp->if_type == IFT_ETHER) { 1344 ifa = TAILQ_FIRST(&ifp->if_addrhead); 1345 while (ifa) { 1346 sdl=(struct sockaddr_dl*)ifa->ifa_addr; 1347 if (sdl != NULL && 1348 (sdl->sdl_family == AF_LINK) && 1349 (sdl->sdl_type == IFT_ETHER)) { 1350 return (copyout(LLADDR(sdl), 1351 &ifr->ifr_hwaddr.sa_data, 1352 LINUX_IFHWADDRLEN)); 1353 } 1354 ifa = TAILQ_NEXT(ifa, ifa_link); 1355 } 1356 } 1357 } 1358 return (ENOENT); 1359 } 1360 1361 case LINUX_SIOCADDMULTI: 1362 args->cmd = SIOCADDMULTI; 1363 return (ioctl(p, (struct ioctl_args *)args)); 1364 1365 case LINUX_SIOCDELMULTI: 1366 args->cmd = SIOCDELMULTI; 1367 return (ioctl(p, (struct ioctl_args *)args)); 1368 1369 } 1370 1371 return (ENOIOCTL); 1372 } 1373 1374 /* 1375 * main ioctl syscall function 1376 */ 1377 1378 int 1379 linux_ioctl(struct proc *p, struct linux_ioctl_args *args) 1380 { 1381 struct filedesc *fdp = p->p_fd; 1382 struct file *fp; 1383 struct handler_element *he; 1384 int error, cmd; 1385 1386 #ifdef DEBUG 1387 printf("Linux-emul(%ld): ioctl(%d, %04lx, *)\n", (long)p->p_pid, 1388 args->fd, args->cmd); 1389 #endif 1390 1391 if ((unsigned)args->fd >= fdp->fd_nfiles) 1392 return (EBADF); 1393 1394 fp = fdp->fd_ofiles[args->fd]; 1395 if (fp == NULL || (fp->f_flag & (FREAD|FWRITE)) == 0) 1396 return (EBADF); 1397 1398 /* Iterate over the ioctl handlers */ 1399 cmd = args->cmd & 0xffff; 1400 TAILQ_FOREACH(he, &handlers, list) { 1401 if (cmd >= he->low && cmd <= he->high) { 1402 error = (*he->func)(p, args); 1403 if (error != ENOIOCTL) 1404 return (error); 1405 } 1406 } 1407 1408 printf("linux: 'ioctl' fd=%d, cmd=%x ('%c',%d) not implemented\n", 1409 args->fd, (int)(args->cmd & 0xffff), 1410 (int)(args->cmd & 0xff00) >> 8, (int)(args->cmd & 0xff)); 1411 1412 return (EINVAL); 1413 } 1414 1415 int 1416 linux_ioctl_register_handler(struct linux_ioctl_handler *h) 1417 { 1418 struct handler_element *he, *cur; 1419 1420 if (h == NULL || h->func == NULL) 1421 return (EINVAL); 1422 1423 /* 1424 * Reuse the element if the handler is already on the list, otherwise 1425 * create a new element. 1426 */ 1427 TAILQ_FOREACH(he, &handlers, list) { 1428 if (he->func == h->func) 1429 break; 1430 } 1431 if (he == NULL) { 1432 MALLOC(he, struct handler_element *, sizeof(*he), 1433 M_LINUX, M_WAITOK); 1434 he->func = h->func; 1435 } else 1436 TAILQ_REMOVE(&handlers, he, list); 1437 1438 /* Initialize range information. */ 1439 he->low = h->low; 1440 he->high = h->high; 1441 he->span = h->high - h->low + 1; 1442 1443 /* Add the element to the list, sorted on span. */ 1444 TAILQ_FOREACH(cur, &handlers, list) { 1445 if (cur->span > he->span) { 1446 TAILQ_INSERT_BEFORE(cur, he, list); 1447 return (0); 1448 } 1449 } 1450 TAILQ_INSERT_TAIL(&handlers, he, list); 1451 1452 return (0); 1453 } 1454 1455 int 1456 linux_ioctl_unregister_handler(struct linux_ioctl_handler *h) 1457 { 1458 struct handler_element *he; 1459 1460 if (h == NULL || h->func == NULL) 1461 return (EINVAL); 1462 1463 TAILQ_FOREACH(he, &handlers, list) { 1464 if (he->func == h->func) { 1465 TAILQ_REMOVE(&handlers, he, list); 1466 FREE(he, M_LINUX); 1467 return (0); 1468 } 1469 } 1470 1471 return (EINVAL); 1472 } 1473 1474 int 1475 linux_ioctl_register_handlers(struct linker_set *s) 1476 { 1477 int error, i; 1478 1479 if (s == NULL) 1480 return (EINVAL); 1481 1482 for (i = 0; i < s->ls_length; i++) { 1483 error = linux_ioctl_register_handler(s->ls_items[i]); 1484 if (error) 1485 return (error); 1486 } 1487 1488 return (0); 1489 } 1490 1491 int 1492 linux_ioctl_unregister_handlers(struct linker_set *s) 1493 { 1494 int error, i; 1495 1496 if (s == NULL) 1497 return (EINVAL); 1498 1499 for (i = 0; i < s->ls_length; i++) { 1500 error = linux_ioctl_unregister_handler(s->ls_items[i]); 1501 if (error) 1502 return (error); 1503 } 1504 1505 return (0); 1506 } 1507