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/cdio.h> 35 #include <sys/dvdio.h> 36 #include <sys/consio.h> 37 #include <sys/ctype.h> 38 #include <sys/disklabel.h> 39 #include <sys/fcntl.h> 40 #include <sys/file.h> 41 #include <sys/filedesc.h> 42 #include <sys/filio.h> 43 #include <sys/kbio.h> 44 #include <sys/linker_set.h> 45 #include <sys/malloc.h> 46 #include <sys/proc.h> 47 #include <sys/socket.h> 48 #include <sys/sockio.h> 49 #include <sys/soundcard.h> 50 #include <sys/tty.h> 51 #include <sys/uio.h> 52 #include <net/if.h> 53 #include <net/if_dl.h> 54 #include <net/if_types.h> 55 56 #include <machine/../linux/linux.h> 57 #include <machine/../linux/linux_proto.h> 58 59 #include <compat/linux/linux_ioctl.h> 60 #include <compat/linux/linux_mib.h> 61 #include <compat/linux/linux_util.h> 62 63 static linux_ioctl_function_t linux_ioctl_cdrom; 64 static linux_ioctl_function_t linux_ioctl_console; 65 static linux_ioctl_function_t linux_ioctl_disk; 66 static linux_ioctl_function_t linux_ioctl_socket; 67 static linux_ioctl_function_t linux_ioctl_sound; 68 static linux_ioctl_function_t linux_ioctl_termio; 69 static linux_ioctl_function_t linux_ioctl_private; 70 static linux_ioctl_function_t linux_ioctl_special; 71 72 static struct linux_ioctl_handler cdrom_handler = 73 { linux_ioctl_cdrom, LINUX_IOCTL_CDROM_MIN, LINUX_IOCTL_CDROM_MAX }; 74 static struct linux_ioctl_handler console_handler = 75 { linux_ioctl_console, LINUX_IOCTL_CONSOLE_MIN, LINUX_IOCTL_CONSOLE_MAX }; 76 static struct linux_ioctl_handler disk_handler = 77 { linux_ioctl_disk, LINUX_IOCTL_DISK_MIN, LINUX_IOCTL_DISK_MAX }; 78 static struct linux_ioctl_handler socket_handler = 79 { linux_ioctl_socket, LINUX_IOCTL_SOCKET_MIN, LINUX_IOCTL_SOCKET_MAX }; 80 static struct linux_ioctl_handler sound_handler = 81 { linux_ioctl_sound, LINUX_IOCTL_SOUND_MIN, LINUX_IOCTL_SOUND_MAX }; 82 static struct linux_ioctl_handler termio_handler = 83 { linux_ioctl_termio, LINUX_IOCTL_TERMIO_MIN, LINUX_IOCTL_TERMIO_MAX }; 84 static struct linux_ioctl_handler private_handler = 85 { linux_ioctl_private, LINUX_IOCTL_PRIVATE_MIN, LINUX_IOCTL_PRIVATE_MAX }; 86 87 DATA_SET(linux_ioctl_handler_set, cdrom_handler); 88 DATA_SET(linux_ioctl_handler_set, console_handler); 89 DATA_SET(linux_ioctl_handler_set, disk_handler); 90 DATA_SET(linux_ioctl_handler_set, socket_handler); 91 DATA_SET(linux_ioctl_handler_set, sound_handler); 92 DATA_SET(linux_ioctl_handler_set, termio_handler); 93 DATA_SET(linux_ioctl_handler_set, private_handler); 94 95 struct handler_element 96 { 97 TAILQ_ENTRY(handler_element) list; 98 int (*func)(struct thread *, struct linux_ioctl_args *); 99 int low, high, span; 100 }; 101 102 static TAILQ_HEAD(, handler_element) handlers = 103 TAILQ_HEAD_INITIALIZER(handlers); 104 105 static int 106 linux_ioctl_disk(struct thread *td, struct linux_ioctl_args *args) 107 { 108 struct file *fp; 109 int error; 110 struct disklabel dl; 111 112 if ((error = fget(td, args->fd, &fp)) != 0) 113 return (error); 114 switch (args->cmd & 0xffff) { 115 case LINUX_BLKGETSIZE: 116 error = fo_ioctl(fp, DIOCGDINFO, (caddr_t)&dl, td); 117 fdrop(fp, td); 118 if (error) 119 return (error); 120 return (copyout(&(dl.d_secperunit), (caddr_t)args->arg, 121 sizeof(dl.d_secperunit))); 122 } 123 fdrop(fp, td); 124 return (ENOIOCTL); 125 } 126 127 /* 128 * termio related ioctls 129 */ 130 131 struct linux_termio { 132 unsigned short c_iflag; 133 unsigned short c_oflag; 134 unsigned short c_cflag; 135 unsigned short c_lflag; 136 unsigned char c_line; 137 unsigned char c_cc[LINUX_NCC]; 138 }; 139 140 struct linux_termios { 141 unsigned int c_iflag; 142 unsigned int c_oflag; 143 unsigned int c_cflag; 144 unsigned int c_lflag; 145 #ifdef __alpha__ 146 unsigned char c_cc[LINUX_NCCS]; 147 unsigned char c_line; 148 unsigned int c_ispeed; 149 unsigned int c_ospeed; 150 #else 151 unsigned char c_line; 152 unsigned char c_cc[LINUX_NCCS]; 153 #endif 154 }; 155 156 struct linux_winsize { 157 unsigned short ws_row, ws_col; 158 unsigned short ws_xpixel, ws_ypixel; 159 }; 160 161 static struct speedtab sptab[] = { 162 { B0, LINUX_B0 }, { B50, LINUX_B50 }, 163 { B75, LINUX_B75 }, { B110, LINUX_B110 }, 164 { B134, LINUX_B134 }, { B150, LINUX_B150 }, 165 { B200, LINUX_B200 }, { B300, LINUX_B300 }, 166 { B600, LINUX_B600 }, { B1200, LINUX_B1200 }, 167 { B1800, LINUX_B1800 }, { B2400, LINUX_B2400 }, 168 { B4800, LINUX_B4800 }, { B9600, LINUX_B9600 }, 169 { B19200, LINUX_B19200 }, { B38400, LINUX_B38400 }, 170 { B57600, LINUX_B57600 }, { B115200, LINUX_B115200 }, 171 {-1, -1 } 172 }; 173 174 struct linux_serial_struct { 175 int type; 176 int line; 177 int port; 178 int irq; 179 int flags; 180 int xmit_fifo_size; 181 int custom_divisor; 182 int baud_base; 183 unsigned short close_delay; 184 char reserved_char[2]; 185 int hub6; 186 unsigned short closing_wait; 187 unsigned short closing_wait2; 188 int reserved[4]; 189 }; 190 191 static int 192 linux_to_bsd_speed(int code, struct speedtab *table) 193 { 194 for ( ; table->sp_code != -1; table++) 195 if (table->sp_code == code) 196 return (table->sp_speed); 197 return -1; 198 } 199 200 static int 201 bsd_to_linux_speed(int speed, struct speedtab *table) 202 { 203 for ( ; table->sp_speed != -1; table++) 204 if (table->sp_speed == speed) 205 return (table->sp_code); 206 return -1; 207 } 208 209 static void 210 bsd_to_linux_termios(struct termios *bios, struct linux_termios *lios) 211 { 212 int i; 213 214 #ifdef DEBUG 215 if (ldebug(ioctl)) { 216 printf("LINUX: BSD termios structure (input):\n"); 217 printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n", 218 bios->c_iflag, bios->c_oflag, bios->c_cflag, bios->c_lflag, 219 bios->c_ispeed, bios->c_ospeed); 220 printf("c_cc "); 221 for (i=0; i<NCCS; i++) 222 printf("%02x ", bios->c_cc[i]); 223 printf("\n"); 224 } 225 #endif 226 227 lios->c_iflag = 0; 228 if (bios->c_iflag & IGNBRK) 229 lios->c_iflag |= LINUX_IGNBRK; 230 if (bios->c_iflag & BRKINT) 231 lios->c_iflag |= LINUX_BRKINT; 232 if (bios->c_iflag & IGNPAR) 233 lios->c_iflag |= LINUX_IGNPAR; 234 if (bios->c_iflag & PARMRK) 235 lios->c_iflag |= LINUX_PARMRK; 236 if (bios->c_iflag & INPCK) 237 lios->c_iflag |= LINUX_INPCK; 238 if (bios->c_iflag & ISTRIP) 239 lios->c_iflag |= LINUX_ISTRIP; 240 if (bios->c_iflag & INLCR) 241 lios->c_iflag |= LINUX_INLCR; 242 if (bios->c_iflag & IGNCR) 243 lios->c_iflag |= LINUX_IGNCR; 244 if (bios->c_iflag & ICRNL) 245 lios->c_iflag |= LINUX_ICRNL; 246 if (bios->c_iflag & IXON) 247 lios->c_iflag |= LINUX_IXON; 248 if (bios->c_iflag & IXANY) 249 lios->c_iflag |= LINUX_IXANY; 250 if (bios->c_iflag & IXOFF) 251 lios->c_iflag |= LINUX_IXOFF; 252 if (bios->c_iflag & IMAXBEL) 253 lios->c_iflag |= LINUX_IMAXBEL; 254 255 lios->c_oflag = 0; 256 if (bios->c_oflag & OPOST) 257 lios->c_oflag |= LINUX_OPOST; 258 if (bios->c_oflag & ONLCR) 259 lios->c_oflag |= LINUX_ONLCR; 260 if (bios->c_oflag & OXTABS) 261 lios->c_oflag |= LINUX_XTABS; 262 263 lios->c_cflag = bsd_to_linux_speed(bios->c_ispeed, sptab); 264 lios->c_cflag |= (bios->c_cflag & CSIZE) >> 4; 265 if (bios->c_cflag & CSTOPB) 266 lios->c_cflag |= LINUX_CSTOPB; 267 if (bios->c_cflag & CREAD) 268 lios->c_cflag |= LINUX_CREAD; 269 if (bios->c_cflag & PARENB) 270 lios->c_cflag |= LINUX_PARENB; 271 if (bios->c_cflag & PARODD) 272 lios->c_cflag |= LINUX_PARODD; 273 if (bios->c_cflag & HUPCL) 274 lios->c_cflag |= LINUX_HUPCL; 275 if (bios->c_cflag & CLOCAL) 276 lios->c_cflag |= LINUX_CLOCAL; 277 if (bios->c_cflag & CRTSCTS) 278 lios->c_cflag |= LINUX_CRTSCTS; 279 280 lios->c_lflag = 0; 281 if (bios->c_lflag & ISIG) 282 lios->c_lflag |= LINUX_ISIG; 283 if (bios->c_lflag & ICANON) 284 lios->c_lflag |= LINUX_ICANON; 285 if (bios->c_lflag & ECHO) 286 lios->c_lflag |= LINUX_ECHO; 287 if (bios->c_lflag & ECHOE) 288 lios->c_lflag |= LINUX_ECHOE; 289 if (bios->c_lflag & ECHOK) 290 lios->c_lflag |= LINUX_ECHOK; 291 if (bios->c_lflag & ECHONL) 292 lios->c_lflag |= LINUX_ECHONL; 293 if (bios->c_lflag & NOFLSH) 294 lios->c_lflag |= LINUX_NOFLSH; 295 if (bios->c_lflag & TOSTOP) 296 lios->c_lflag |= LINUX_TOSTOP; 297 if (bios->c_lflag & ECHOCTL) 298 lios->c_lflag |= LINUX_ECHOCTL; 299 if (bios->c_lflag & ECHOPRT) 300 lios->c_lflag |= LINUX_ECHOPRT; 301 if (bios->c_lflag & ECHOKE) 302 lios->c_lflag |= LINUX_ECHOKE; 303 if (bios->c_lflag & FLUSHO) 304 lios->c_lflag |= LINUX_FLUSHO; 305 if (bios->c_lflag & PENDIN) 306 lios->c_lflag |= LINUX_PENDIN; 307 if (bios->c_lflag & IEXTEN) 308 lios->c_lflag |= LINUX_IEXTEN; 309 310 for (i=0; i<LINUX_NCCS; i++) 311 lios->c_cc[i] = LINUX_POSIX_VDISABLE; 312 lios->c_cc[LINUX_VINTR] = bios->c_cc[VINTR]; 313 lios->c_cc[LINUX_VQUIT] = bios->c_cc[VQUIT]; 314 lios->c_cc[LINUX_VERASE] = bios->c_cc[VERASE]; 315 lios->c_cc[LINUX_VKILL] = bios->c_cc[VKILL]; 316 lios->c_cc[LINUX_VEOF] = bios->c_cc[VEOF]; 317 lios->c_cc[LINUX_VEOL] = bios->c_cc[VEOL]; 318 lios->c_cc[LINUX_VMIN] = bios->c_cc[VMIN]; 319 lios->c_cc[LINUX_VTIME] = bios->c_cc[VTIME]; 320 lios->c_cc[LINUX_VEOL2] = bios->c_cc[VEOL2]; 321 lios->c_cc[LINUX_VSUSP] = bios->c_cc[VSUSP]; 322 lios->c_cc[LINUX_VSTART] = bios->c_cc[VSTART]; 323 lios->c_cc[LINUX_VSTOP] = bios->c_cc[VSTOP]; 324 lios->c_cc[LINUX_VREPRINT] = bios->c_cc[VREPRINT]; 325 lios->c_cc[LINUX_VDISCARD] = bios->c_cc[VDISCARD]; 326 lios->c_cc[LINUX_VWERASE] = bios->c_cc[VWERASE]; 327 lios->c_cc[LINUX_VLNEXT] = bios->c_cc[VLNEXT]; 328 329 for (i=0; i<LINUX_NCCS; i++) { 330 if (lios->c_cc[i] == _POSIX_VDISABLE) 331 lios->c_cc[i] = LINUX_POSIX_VDISABLE; 332 } 333 lios->c_line = 0; 334 335 #ifdef DEBUG 336 if (ldebug(ioctl)) { 337 printf("LINUX: LINUX termios structure (output):\n"); 338 printf("i=%08x o=%08x c=%08x l=%08x line=%d\n", 339 lios->c_iflag, lios->c_oflag, lios->c_cflag, 340 lios->c_lflag, (int)lios->c_line); 341 printf("c_cc "); 342 for (i=0; i<LINUX_NCCS; i++) 343 printf("%02x ", lios->c_cc[i]); 344 printf("\n"); 345 } 346 #endif 347 } 348 349 static void 350 linux_to_bsd_termios(struct linux_termios *lios, struct termios *bios) 351 { 352 int i; 353 354 #ifdef DEBUG 355 if (ldebug(ioctl)) { 356 printf("LINUX: LINUX termios structure (input):\n"); 357 printf("i=%08x o=%08x c=%08x l=%08x line=%d\n", 358 lios->c_iflag, lios->c_oflag, lios->c_cflag, 359 lios->c_lflag, (int)lios->c_line); 360 printf("c_cc "); 361 for (i=0; i<LINUX_NCCS; i++) 362 printf("%02x ", lios->c_cc[i]); 363 printf("\n"); 364 } 365 #endif 366 367 bios->c_iflag = 0; 368 if (lios->c_iflag & LINUX_IGNBRK) 369 bios->c_iflag |= IGNBRK; 370 if (lios->c_iflag & LINUX_BRKINT) 371 bios->c_iflag |= BRKINT; 372 if (lios->c_iflag & LINUX_IGNPAR) 373 bios->c_iflag |= IGNPAR; 374 if (lios->c_iflag & LINUX_PARMRK) 375 bios->c_iflag |= PARMRK; 376 if (lios->c_iflag & LINUX_INPCK) 377 bios->c_iflag |= INPCK; 378 if (lios->c_iflag & LINUX_ISTRIP) 379 bios->c_iflag |= ISTRIP; 380 if (lios->c_iflag & LINUX_INLCR) 381 bios->c_iflag |= INLCR; 382 if (lios->c_iflag & LINUX_IGNCR) 383 bios->c_iflag |= IGNCR; 384 if (lios->c_iflag & LINUX_ICRNL) 385 bios->c_iflag |= ICRNL; 386 if (lios->c_iflag & LINUX_IXON) 387 bios->c_iflag |= IXON; 388 if (lios->c_iflag & LINUX_IXANY) 389 bios->c_iflag |= IXANY; 390 if (lios->c_iflag & LINUX_IXOFF) 391 bios->c_iflag |= IXOFF; 392 if (lios->c_iflag & LINUX_IMAXBEL) 393 bios->c_iflag |= IMAXBEL; 394 395 bios->c_oflag = 0; 396 if (lios->c_oflag & LINUX_OPOST) 397 bios->c_oflag |= OPOST; 398 if (lios->c_oflag & LINUX_ONLCR) 399 bios->c_oflag |= ONLCR; 400 if (lios->c_oflag & LINUX_XTABS) 401 bios->c_oflag |= OXTABS; 402 403 bios->c_cflag = (lios->c_cflag & LINUX_CSIZE) << 4; 404 if (lios->c_cflag & LINUX_CSTOPB) 405 bios->c_cflag |= CSTOPB; 406 if (lios->c_cflag & LINUX_CREAD) 407 bios->c_cflag |= CREAD; 408 if (lios->c_cflag & LINUX_PARENB) 409 bios->c_cflag |= PARENB; 410 if (lios->c_cflag & LINUX_PARODD) 411 bios->c_cflag |= PARODD; 412 if (lios->c_cflag & LINUX_HUPCL) 413 bios->c_cflag |= HUPCL; 414 if (lios->c_cflag & LINUX_CLOCAL) 415 bios->c_cflag |= CLOCAL; 416 if (lios->c_cflag & LINUX_CRTSCTS) 417 bios->c_cflag |= CRTSCTS; 418 419 bios->c_lflag = 0; 420 if (lios->c_lflag & LINUX_ISIG) 421 bios->c_lflag |= ISIG; 422 if (lios->c_lflag & LINUX_ICANON) 423 bios->c_lflag |= ICANON; 424 if (lios->c_lflag & LINUX_ECHO) 425 bios->c_lflag |= ECHO; 426 if (lios->c_lflag & LINUX_ECHOE) 427 bios->c_lflag |= ECHOE; 428 if (lios->c_lflag & LINUX_ECHOK) 429 bios->c_lflag |= ECHOK; 430 if (lios->c_lflag & LINUX_ECHONL) 431 bios->c_lflag |= ECHONL; 432 if (lios->c_lflag & LINUX_NOFLSH) 433 bios->c_lflag |= NOFLSH; 434 if (lios->c_lflag & LINUX_TOSTOP) 435 bios->c_lflag |= TOSTOP; 436 if (lios->c_lflag & LINUX_ECHOCTL) 437 bios->c_lflag |= ECHOCTL; 438 if (lios->c_lflag & LINUX_ECHOPRT) 439 bios->c_lflag |= ECHOPRT; 440 if (lios->c_lflag & LINUX_ECHOKE) 441 bios->c_lflag |= ECHOKE; 442 if (lios->c_lflag & LINUX_FLUSHO) 443 bios->c_lflag |= FLUSHO; 444 if (lios->c_lflag & LINUX_PENDIN) 445 bios->c_lflag |= PENDIN; 446 if (lios->c_lflag & LINUX_IEXTEN) 447 bios->c_lflag |= IEXTEN; 448 449 for (i=0; i<NCCS; i++) 450 bios->c_cc[i] = _POSIX_VDISABLE; 451 bios->c_cc[VINTR] = lios->c_cc[LINUX_VINTR]; 452 bios->c_cc[VQUIT] = lios->c_cc[LINUX_VQUIT]; 453 bios->c_cc[VERASE] = lios->c_cc[LINUX_VERASE]; 454 bios->c_cc[VKILL] = lios->c_cc[LINUX_VKILL]; 455 bios->c_cc[VEOF] = lios->c_cc[LINUX_VEOF]; 456 bios->c_cc[VEOL] = lios->c_cc[LINUX_VEOL]; 457 bios->c_cc[VMIN] = lios->c_cc[LINUX_VMIN]; 458 bios->c_cc[VTIME] = lios->c_cc[LINUX_VTIME]; 459 bios->c_cc[VEOL2] = lios->c_cc[LINUX_VEOL2]; 460 bios->c_cc[VSUSP] = lios->c_cc[LINUX_VSUSP]; 461 bios->c_cc[VSTART] = lios->c_cc[LINUX_VSTART]; 462 bios->c_cc[VSTOP] = lios->c_cc[LINUX_VSTOP]; 463 bios->c_cc[VREPRINT] = lios->c_cc[LINUX_VREPRINT]; 464 bios->c_cc[VDISCARD] = lios->c_cc[LINUX_VDISCARD]; 465 bios->c_cc[VWERASE] = lios->c_cc[LINUX_VWERASE]; 466 bios->c_cc[VLNEXT] = lios->c_cc[LINUX_VLNEXT]; 467 468 for (i=0; i<NCCS; i++) { 469 if (bios->c_cc[i] == LINUX_POSIX_VDISABLE) 470 bios->c_cc[i] = _POSIX_VDISABLE; 471 } 472 473 bios->c_ispeed = bios->c_ospeed = 474 linux_to_bsd_speed(lios->c_cflag & LINUX_CBAUD, sptab); 475 476 #ifdef DEBUG 477 if (ldebug(ioctl)) { 478 printf("LINUX: BSD termios structure (output):\n"); 479 printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n", 480 bios->c_iflag, bios->c_oflag, bios->c_cflag, bios->c_lflag, 481 bios->c_ispeed, bios->c_ospeed); 482 printf("c_cc "); 483 for (i=0; i<NCCS; i++) 484 printf("%02x ", bios->c_cc[i]); 485 printf("\n"); 486 } 487 #endif 488 } 489 490 static void 491 bsd_to_linux_termio(struct termios *bios, struct linux_termio *lio) 492 { 493 struct linux_termios lios; 494 495 bsd_to_linux_termios(bios, &lios); 496 lio->c_iflag = lios.c_iflag; 497 lio->c_oflag = lios.c_oflag; 498 lio->c_cflag = lios.c_cflag; 499 lio->c_lflag = lios.c_lflag; 500 lio->c_line = lios.c_line; 501 #ifdef __alpha__ 502 lio->c_cc[LINUX__VINTR] = lios.c_cc[LINUX_VINTR]; 503 lio->c_cc[LINUX__VQUIT] = lios.c_cc[LINUX_VQUIT]; 504 lio->c_cc[LINUX__VERASE] = lios.c_cc[LINUX_VERASE]; 505 lio->c_cc[LINUX__VKILL] = lios.c_cc[LINUX_VKILL]; 506 lio->c_cc[LINUX__VEOF] = 507 lios.c_cc[(lios.c_lflag & ICANON) ? LINUX_VEOF : LINUX_VMIN]; 508 lio->c_cc[LINUX__VEOL] = 509 lios.c_cc[(lios.c_lflag & ICANON) ? LINUX_VEOL : LINUX_VTIME]; 510 lio->c_cc[LINUX__VEOL2] = lios.c_cc[LINUX_VEOL2]; 511 lio->c_cc[LINUX__VSWTC] = lios.c_cc[LINUX_VSWTC]; 512 #else 513 memcpy(lio->c_cc, lios.c_cc, LINUX_NCC); 514 #endif 515 } 516 517 static void 518 linux_to_bsd_termio(struct linux_termio *lio, struct termios *bios) 519 { 520 struct linux_termios lios; 521 int i; 522 523 lios.c_iflag = lio->c_iflag; 524 lios.c_oflag = lio->c_oflag; 525 lios.c_cflag = lio->c_cflag; 526 lios.c_lflag = lio->c_lflag; 527 #ifdef __alpha__ 528 for (i=0; i<LINUX_NCCS; i++) 529 lios.c_cc[i] = LINUX_POSIX_VDISABLE; 530 lios.c_cc[LINUX_VINTR] = lio->c_cc[LINUX__VINTR]; 531 lios.c_cc[LINUX_VQUIT] = lio->c_cc[LINUX__VQUIT]; 532 lios.c_cc[LINUX_VERASE] = lio->c_cc[LINUX__VERASE]; 533 lios.c_cc[LINUX_VKILL] = lio->c_cc[LINUX__VKILL]; 534 lios.c_cc[LINUX_VEOL2] = lio->c_cc[LINUX__VEOL2]; 535 lios.c_cc[LINUX_VSWTC] = lio->c_cc[LINUX__VSWTC]; 536 lios.c_cc[(lio->c_lflag & ICANON) ? LINUX_VEOF : LINUX_VMIN] = 537 lio->c_cc[LINUX__VEOF]; 538 lios.c_cc[(lio->c_lflag & ICANON) ? LINUX_VEOL : LINUX_VTIME] = 539 lio->c_cc[LINUX__VEOL]; 540 #else 541 for (i=LINUX_NCC; i<LINUX_NCCS; i++) 542 lios.c_cc[i] = LINUX_POSIX_VDISABLE; 543 memcpy(lios.c_cc, lio->c_cc, LINUX_NCC); 544 #endif 545 linux_to_bsd_termios(&lios, bios); 546 } 547 548 static int 549 linux_ioctl_termio(struct thread *td, struct linux_ioctl_args *args) 550 { 551 struct termios bios; 552 struct linux_termios lios; 553 struct linux_termio lio; 554 struct file *fp; 555 int error; 556 557 if ((error = fget(td, args->fd, &fp)) != 0) 558 return (error); 559 560 switch (args->cmd & 0xffff) { 561 562 case LINUX_TCGETS: 563 error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td); 564 if (error) 565 break; 566 bsd_to_linux_termios(&bios, &lios); 567 error = copyout(&lios, (caddr_t)args->arg, sizeof(lios)); 568 break; 569 570 case LINUX_TCSETS: 571 error = copyin((caddr_t)args->arg, &lios, sizeof(lios)); 572 if (error) 573 break; 574 linux_to_bsd_termios(&lios, &bios); 575 error = (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td)); 576 break; 577 578 case LINUX_TCSETSW: 579 error = copyin((caddr_t)args->arg, &lios, sizeof(lios)); 580 if (error) 581 break; 582 linux_to_bsd_termios(&lios, &bios); 583 error = (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td)); 584 break; 585 586 case LINUX_TCSETSF: 587 error = copyin((caddr_t)args->arg, &lios, sizeof(lios)); 588 if (error) 589 break; 590 linux_to_bsd_termios(&lios, &bios); 591 error = (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td)); 592 break; 593 594 case LINUX_TCGETA: 595 error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td); 596 if (error) 597 break; 598 bsd_to_linux_termio(&bios, &lio); 599 error = (copyout(&lio, (caddr_t)args->arg, sizeof(lio))); 600 break; 601 602 case LINUX_TCSETA: 603 error = copyin((caddr_t)args->arg, &lio, sizeof(lio)); 604 if (error) 605 break; 606 linux_to_bsd_termio(&lio, &bios); 607 error = (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td)); 608 break; 609 610 case LINUX_TCSETAW: 611 error = copyin((caddr_t)args->arg, &lio, sizeof(lio)); 612 if (error) 613 break; 614 linux_to_bsd_termio(&lio, &bios); 615 error = (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td)); 616 break; 617 618 case LINUX_TCSETAF: 619 error = copyin((caddr_t)args->arg, &lio, sizeof(lio)); 620 if (error) 621 break; 622 linux_to_bsd_termio(&lio, &bios); 623 error = (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td)); 624 break; 625 626 /* LINUX_TCSBRK */ 627 628 case LINUX_TCXONC: { 629 switch (args->arg) { 630 case LINUX_TCOOFF: 631 args->cmd = TIOCSTOP; 632 break; 633 case LINUX_TCOON: 634 args->cmd = TIOCSTART; 635 break; 636 case LINUX_TCIOFF: 637 case LINUX_TCION: { 638 int c; 639 struct write_args wr; 640 error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td); 641 if (error) 642 break; 643 fdrop(fp, td); 644 c = (args->arg == LINUX_TCIOFF) ? VSTOP : VSTART; 645 c = bios.c_cc[c]; 646 if (c != _POSIX_VDISABLE) { 647 wr.fd = args->fd; 648 wr.buf = &c; 649 wr.nbyte = sizeof(c); 650 return (write(td, &wr)); 651 } else 652 return (0); 653 } 654 default: 655 fdrop(fp, td); 656 return (EINVAL); 657 } 658 args->arg = 0; 659 error = (ioctl(td, (struct ioctl_args *)args)); 660 break; 661 } 662 663 case LINUX_TCFLSH: { 664 args->cmd = TIOCFLUSH; 665 switch (args->arg) { 666 case LINUX_TCIFLUSH: 667 args->arg = FREAD; 668 break; 669 case LINUX_TCOFLUSH: 670 args->arg = FWRITE; 671 break; 672 case LINUX_TCIOFLUSH: 673 args->arg = FREAD | FWRITE; 674 break; 675 default: 676 fdrop(fp, td); 677 return (EINVAL); 678 } 679 error = (ioctl(td, (struct ioctl_args *)args)); 680 break; 681 } 682 683 case LINUX_TIOCEXCL: 684 args->cmd = TIOCEXCL; 685 error = (ioctl(td, (struct ioctl_args *)args)); 686 break; 687 688 case LINUX_TIOCNXCL: 689 args->cmd = TIOCNXCL; 690 error = (ioctl(td, (struct ioctl_args *)args)); 691 break; 692 693 /* LINUX_TIOCSCTTY */ 694 695 case LINUX_TIOCGPGRP: 696 args->cmd = TIOCGPGRP; 697 error = (ioctl(td, (struct ioctl_args *)args)); 698 break; 699 700 case LINUX_TIOCSPGRP: 701 args->cmd = TIOCSPGRP; 702 error = (ioctl(td, (struct ioctl_args *)args)); 703 break; 704 705 /* LINUX_TIOCOUTQ */ 706 /* LINUX_TIOCSTI */ 707 708 case LINUX_TIOCGWINSZ: 709 args->cmd = TIOCGWINSZ; 710 error = (ioctl(td, (struct ioctl_args *)args)); 711 break; 712 713 case LINUX_TIOCSWINSZ: 714 args->cmd = TIOCSWINSZ; 715 error = (ioctl(td, (struct ioctl_args *)args)); 716 break; 717 718 case LINUX_TIOCMGET: 719 args->cmd = TIOCMGET; 720 error = (ioctl(td, (struct ioctl_args *)args)); 721 break; 722 723 case LINUX_TIOCMBIS: 724 args->cmd = TIOCMBIS; 725 error = (ioctl(td, (struct ioctl_args *)args)); 726 break; 727 728 case LINUX_TIOCMBIC: 729 args->cmd = TIOCMBIC; 730 error = (ioctl(td, (struct ioctl_args *)args)); 731 break; 732 733 case LINUX_TIOCMSET: 734 args->cmd = TIOCMSET; 735 error = (ioctl(td, (struct ioctl_args *)args)); 736 break; 737 738 /* TIOCGSOFTCAR */ 739 /* TIOCSSOFTCAR */ 740 741 case LINUX_FIONREAD: /* LINUX_TIOCINQ */ 742 args->cmd = FIONREAD; 743 error = (ioctl(td, (struct ioctl_args *)args)); 744 break; 745 746 /* LINUX_TIOCLINUX */ 747 748 case LINUX_TIOCCONS: 749 args->cmd = TIOCCONS; 750 error = (ioctl(td, (struct ioctl_args *)args)); 751 break; 752 753 case LINUX_TIOCGSERIAL: { 754 struct linux_serial_struct lss; 755 lss.type = LINUX_PORT_16550A; 756 lss.flags = 0; 757 lss.close_delay = 0; 758 error = copyout(&lss, (caddr_t)args->arg, sizeof(lss)); 759 break; 760 } 761 762 case LINUX_TIOCSSERIAL: { 763 struct linux_serial_struct lss; 764 error = copyin((caddr_t)args->arg, &lss, sizeof(lss)); 765 if (error) 766 break; 767 /* XXX - It really helps to have an implementation that 768 * does nothing. NOT! 769 */ 770 error = 0; 771 break; 772 } 773 774 /* LINUX_TIOCPKT */ 775 776 case LINUX_FIONBIO: 777 args->cmd = FIONBIO; 778 error = (ioctl(td, (struct ioctl_args *)args)); 779 break; 780 781 case LINUX_TIOCNOTTY: 782 args->cmd = TIOCNOTTY; 783 error = (ioctl(td, (struct ioctl_args *)args)); 784 break; 785 786 case LINUX_TIOCSETD: { 787 int line; 788 switch (args->arg) { 789 case LINUX_N_TTY: 790 line = TTYDISC; 791 break; 792 case LINUX_N_SLIP: 793 line = SLIPDISC; 794 break; 795 case LINUX_N_PPP: 796 line = PPPDISC; 797 break; 798 default: 799 fdrop(fp, td); 800 return (EINVAL); 801 } 802 error = (fo_ioctl(fp, TIOCSETD, (caddr_t)&line, td)); 803 break; 804 } 805 806 case LINUX_TIOCGETD: { 807 int linux_line; 808 int bsd_line = TTYDISC; 809 error = fo_ioctl(fp, TIOCGETD, (caddr_t)&bsd_line, td); 810 if (error) 811 return (error); 812 switch (bsd_line) { 813 case TTYDISC: 814 linux_line = LINUX_N_TTY; 815 break; 816 case SLIPDISC: 817 linux_line = LINUX_N_SLIP; 818 break; 819 case PPPDISC: 820 linux_line = LINUX_N_PPP; 821 break; 822 default: 823 fdrop(fp, td); 824 return (EINVAL); 825 } 826 error = (copyout(&linux_line, (caddr_t)args->arg, sizeof(int))); 827 break; 828 } 829 830 /* LINUX_TCSBRKP */ 831 /* LINUX_TIOCTTYGSTRUCT */ 832 833 case LINUX_FIONCLEX: 834 args->cmd = FIONCLEX; 835 error = (ioctl(td, (struct ioctl_args *)args)); 836 break; 837 838 case LINUX_FIOCLEX: 839 args->cmd = FIOCLEX; 840 error = (ioctl(td, (struct ioctl_args *)args)); 841 break; 842 843 case LINUX_FIOASYNC: 844 args->cmd = FIOASYNC; 845 error = (ioctl(td, (struct ioctl_args *)args)); 846 break; 847 848 /* LINUX_TIOCSERCONFIG */ 849 /* LINUX_TIOCSERGWILD */ 850 /* LINUX_TIOCSERSWILD */ 851 /* LINUX_TIOCGLCKTRMIOS */ 852 /* LINUX_TIOCSLCKTRMIOS */ 853 854 default: 855 error = ENOIOCTL; 856 break; 857 } 858 859 fdrop(fp, td); 860 return (error); 861 } 862 863 /* 864 * CDROM related ioctls 865 */ 866 867 struct linux_cdrom_msf 868 { 869 u_char cdmsf_min0; 870 u_char cdmsf_sec0; 871 u_char cdmsf_frame0; 872 u_char cdmsf_min1; 873 u_char cdmsf_sec1; 874 u_char cdmsf_frame1; 875 }; 876 877 struct linux_cdrom_tochdr 878 { 879 u_char cdth_trk0; 880 u_char cdth_trk1; 881 }; 882 883 union linux_cdrom_addr 884 { 885 struct { 886 u_char minute; 887 u_char second; 888 u_char frame; 889 } msf; 890 int lba; 891 }; 892 893 struct linux_cdrom_tocentry 894 { 895 u_char cdte_track; 896 u_char cdte_adr:4; 897 u_char cdte_ctrl:4; 898 u_char cdte_format; 899 union linux_cdrom_addr cdte_addr; 900 u_char cdte_datamode; 901 }; 902 903 struct linux_cdrom_subchnl 904 { 905 u_char cdsc_format; 906 u_char cdsc_audiostatus; 907 u_char cdsc_adr:4; 908 u_char cdsc_ctrl:4; 909 u_char cdsc_trk; 910 u_char cdsc_ind; 911 union linux_cdrom_addr cdsc_absaddr; 912 union linux_cdrom_addr cdsc_reladdr; 913 }; 914 915 struct l_dvd_layer { 916 u_char book_version:4; 917 u_char book_type:4; 918 u_char min_rate:4; 919 u_char disc_size:4; 920 u_char layer_type:4; 921 u_char track_path:1; 922 u_char nlayers:2; 923 u_char track_density:4; 924 u_char linear_density:4; 925 u_char bca:1; 926 u_int32_t start_sector; 927 u_int32_t end_sector; 928 u_int32_t end_sector_l0; 929 }; 930 931 struct l_dvd_physical { 932 u_char type; 933 u_char layer_num; 934 struct l_dvd_layer layer[4]; 935 }; 936 937 struct l_dvd_copyright { 938 u_char type; 939 u_char layer_num; 940 u_char cpst; 941 u_char rmi; 942 }; 943 944 struct l_dvd_disckey { 945 u_char type; 946 l_uint agid:2; 947 u_char value[2048]; 948 }; 949 950 struct l_dvd_bca { 951 u_char type; 952 l_int len; 953 u_char value[188]; 954 }; 955 956 struct l_dvd_manufact { 957 u_char type; 958 u_char layer_num; 959 l_int len; 960 u_char value[2048]; 961 }; 962 963 typedef union { 964 u_char type; 965 struct l_dvd_physical physical; 966 struct l_dvd_copyright copyright; 967 struct l_dvd_disckey disckey; 968 struct l_dvd_bca bca; 969 struct l_dvd_manufact manufact; 970 } l_dvd_struct; 971 972 typedef u_char l_dvd_key[5]; 973 typedef u_char l_dvd_challenge[10]; 974 975 struct l_dvd_lu_send_agid { 976 u_char type; 977 l_uint agid:2; 978 }; 979 980 struct l_dvd_host_send_challenge { 981 u_char type; 982 l_uint agid:2; 983 l_dvd_challenge chal; 984 }; 985 986 struct l_dvd_send_key { 987 u_char type; 988 l_uint agid:2; 989 l_dvd_key key; 990 }; 991 992 struct l_dvd_lu_send_challenge { 993 u_char type; 994 l_uint agid:2; 995 l_dvd_challenge chal; 996 }; 997 998 struct l_dvd_lu_send_title_key { 999 u_char type; 1000 l_uint agid:2; 1001 l_dvd_key title_key; 1002 l_int lba; 1003 l_uint cpm:1; 1004 l_uint cp_sec:1; 1005 l_uint cgms:2; 1006 }; 1007 1008 struct l_dvd_lu_send_asf { 1009 u_char type; 1010 l_uint agid:2; 1011 l_uint asf:1; 1012 }; 1013 1014 struct l_dvd_host_send_rpcstate { 1015 u_char type; 1016 u_char pdrc; 1017 }; 1018 1019 struct l_dvd_lu_send_rpcstate { 1020 u_char type:2; 1021 u_char vra:3; 1022 u_char ucca:3; 1023 u_char region_mask; 1024 u_char rpc_scheme; 1025 }; 1026 1027 typedef union { 1028 u_char type; 1029 struct l_dvd_lu_send_agid lsa; 1030 struct l_dvd_host_send_challenge hsc; 1031 struct l_dvd_send_key lsk; 1032 struct l_dvd_lu_send_challenge lsc; 1033 struct l_dvd_send_key hsk; 1034 struct l_dvd_lu_send_title_key lstk; 1035 struct l_dvd_lu_send_asf lsasf; 1036 struct l_dvd_host_send_rpcstate hrpcs; 1037 struct l_dvd_lu_send_rpcstate lrpcs; 1038 } l_dvd_authinfo; 1039 1040 static void 1041 bsd_to_linux_msf_lba(u_char af, union msf_lba *bp, union linux_cdrom_addr *lp) 1042 { 1043 if (af == CD_LBA_FORMAT) 1044 lp->lba = bp->lba; 1045 else { 1046 lp->msf.minute = bp->msf.minute; 1047 lp->msf.second = bp->msf.second; 1048 lp->msf.frame = bp->msf.frame; 1049 } 1050 } 1051 1052 static void 1053 set_linux_cdrom_addr(union linux_cdrom_addr *addr, int format, int lba) 1054 { 1055 if (format == LINUX_CDROM_MSF) { 1056 addr->msf.frame = lba % 75; 1057 lba /= 75; 1058 lba += 2; 1059 addr->msf.second = lba % 60; 1060 addr->msf.minute = lba / 60; 1061 } else 1062 addr->lba = lba; 1063 } 1064 1065 static int 1066 linux_to_bsd_dvd_struct(l_dvd_struct *lp, struct dvd_struct *bp) 1067 { 1068 bp->format = lp->type; 1069 switch (bp->format) { 1070 case DVD_STRUCT_PHYSICAL: 1071 if (bp->layer_num >= 4) 1072 return (EINVAL); 1073 bp->layer_num = lp->physical.layer_num; 1074 break; 1075 case DVD_STRUCT_COPYRIGHT: 1076 bp->layer_num = lp->copyright.layer_num; 1077 break; 1078 case DVD_STRUCT_DISCKEY: 1079 bp->agid = lp->disckey.agid; 1080 break; 1081 case DVD_STRUCT_BCA: 1082 case DVD_STRUCT_MANUFACT: 1083 break; 1084 default: 1085 return (EINVAL); 1086 } 1087 return (0); 1088 } 1089 1090 static int 1091 bsd_to_linux_dvd_struct(struct dvd_struct *bp, l_dvd_struct *lp) 1092 { 1093 switch (bp->format) { 1094 case DVD_STRUCT_PHYSICAL: { 1095 struct dvd_layer *blp = (struct dvd_layer *)bp->data; 1096 struct l_dvd_layer *llp = &lp->physical.layer[bp->layer_num]; 1097 memset(llp, 0, sizeof(*llp)); 1098 llp->book_version = blp->book_version; 1099 llp->book_type = blp->book_type; 1100 llp->min_rate = blp->max_rate; 1101 llp->disc_size = blp->disc_size; 1102 llp->layer_type = blp->layer_type; 1103 llp->track_path = blp->track_path; 1104 llp->nlayers = blp->nlayers; 1105 llp->track_density = blp->track_density; 1106 llp->linear_density = blp->linear_density; 1107 llp->bca = blp->bca; 1108 llp->start_sector = blp->start_sector; 1109 llp->end_sector = blp->end_sector; 1110 llp->end_sector_l0 = blp->end_sector_l0; 1111 break; 1112 } 1113 case DVD_STRUCT_COPYRIGHT: 1114 lp->copyright.cpst = bp->cpst; 1115 lp->copyright.rmi = bp->rmi; 1116 break; 1117 case DVD_STRUCT_DISCKEY: 1118 memcpy(lp->disckey.value, bp->data, sizeof(lp->disckey.value)); 1119 break; 1120 case DVD_STRUCT_BCA: 1121 lp->bca.len = bp->length; 1122 memcpy(lp->bca.value, bp->data, sizeof(lp->bca.value)); 1123 break; 1124 case DVD_STRUCT_MANUFACT: 1125 lp->manufact.len = bp->length; 1126 memcpy(lp->manufact.value, bp->data, 1127 sizeof(lp->manufact.value)); 1128 /* lp->manufact.layer_num is unused in linux (redhat 7.0) */ 1129 break; 1130 default: 1131 return (EINVAL); 1132 } 1133 return (0); 1134 } 1135 1136 static int 1137 linux_to_bsd_dvd_authinfo(l_dvd_authinfo *lp, int *bcode, 1138 struct dvd_authinfo *bp) 1139 { 1140 switch (lp->type) { 1141 case LINUX_DVD_LU_SEND_AGID: 1142 *bcode = DVDIOCREPORTKEY; 1143 bp->format = DVD_REPORT_AGID; 1144 bp->agid = lp->lsa.agid; 1145 break; 1146 case LINUX_DVD_HOST_SEND_CHALLENGE: 1147 *bcode = DVDIOCSENDKEY; 1148 bp->format = DVD_SEND_CHALLENGE; 1149 bp->agid = lp->hsc.agid; 1150 memcpy(bp->keychal, lp->hsc.chal, 10); 1151 break; 1152 case LINUX_DVD_LU_SEND_KEY1: 1153 *bcode = DVDIOCREPORTKEY; 1154 bp->format = DVD_REPORT_KEY1; 1155 bp->agid = lp->lsk.agid; 1156 break; 1157 case LINUX_DVD_LU_SEND_CHALLENGE: 1158 *bcode = DVDIOCREPORTKEY; 1159 bp->format = DVD_REPORT_CHALLENGE; 1160 bp->agid = lp->lsc.agid; 1161 break; 1162 case LINUX_DVD_HOST_SEND_KEY2: 1163 *bcode = DVDIOCSENDKEY; 1164 bp->format = DVD_SEND_KEY2; 1165 bp->agid = lp->hsk.agid; 1166 memcpy(bp->keychal, lp->hsk.key, 5); 1167 break; 1168 case LINUX_DVD_LU_SEND_TITLE_KEY: 1169 *bcode = DVDIOCREPORTKEY; 1170 bp->format = DVD_REPORT_TITLE_KEY; 1171 bp->agid = lp->lstk.agid; 1172 bp->lba = lp->lstk.lba; 1173 break; 1174 case LINUX_DVD_LU_SEND_ASF: 1175 *bcode = DVDIOCREPORTKEY; 1176 bp->format = DVD_REPORT_ASF; 1177 bp->agid = lp->lsasf.agid; 1178 break; 1179 case LINUX_DVD_INVALIDATE_AGID: 1180 *bcode = DVDIOCREPORTKEY; 1181 bp->format = DVD_INVALIDATE_AGID; 1182 bp->agid = lp->lsa.agid; 1183 break; 1184 case LINUX_DVD_LU_SEND_RPC_STATE: 1185 *bcode = DVDIOCREPORTKEY; 1186 bp->format = DVD_REPORT_RPC; 1187 break; 1188 case LINUX_DVD_HOST_SEND_RPC_STATE: 1189 *bcode = DVDIOCSENDKEY; 1190 bp->format = DVD_SEND_RPC; 1191 bp->region = lp->hrpcs.pdrc; 1192 break; 1193 default: 1194 return (EINVAL); 1195 } 1196 return (0); 1197 } 1198 1199 static int 1200 bsd_to_linux_dvd_authinfo(struct dvd_authinfo *bp, l_dvd_authinfo *lp) 1201 { 1202 switch (lp->type) { 1203 case LINUX_DVD_LU_SEND_AGID: 1204 lp->lsa.agid = bp->agid; 1205 break; 1206 case LINUX_DVD_HOST_SEND_CHALLENGE: 1207 lp->type = LINUX_DVD_LU_SEND_KEY1; 1208 break; 1209 case LINUX_DVD_LU_SEND_KEY1: 1210 memcpy(lp->lsk.key, bp->keychal, sizeof(lp->lsk.key)); 1211 break; 1212 case LINUX_DVD_LU_SEND_CHALLENGE: 1213 memcpy(lp->lsc.chal, bp->keychal, sizeof(lp->lsc.chal)); 1214 break; 1215 case LINUX_DVD_HOST_SEND_KEY2: 1216 lp->type = LINUX_DVD_AUTH_ESTABLISHED; 1217 break; 1218 case LINUX_DVD_LU_SEND_TITLE_KEY: 1219 memcpy(lp->lstk.title_key, bp->keychal, 1220 sizeof(lp->lstk.title_key)); 1221 lp->lstk.cpm = bp->cpm; 1222 lp->lstk.cp_sec = bp->cp_sec; 1223 lp->lstk.cgms = bp->cgms; 1224 break; 1225 case LINUX_DVD_LU_SEND_ASF: 1226 lp->lsasf.asf = bp->asf; 1227 break; 1228 case LINUX_DVD_INVALIDATE_AGID: 1229 break; 1230 case LINUX_DVD_LU_SEND_RPC_STATE: 1231 lp->lrpcs.type = bp->reg_type; 1232 lp->lrpcs.vra = bp->vend_rsts; 1233 lp->lrpcs.ucca = bp->user_rsts; 1234 lp->lrpcs.region_mask = bp->region; 1235 lp->lrpcs.rpc_scheme = bp->rpc_scheme; 1236 break; 1237 case LINUX_DVD_HOST_SEND_RPC_STATE: 1238 break; 1239 default: 1240 return (EINVAL); 1241 } 1242 return (0); 1243 } 1244 1245 static int 1246 linux_ioctl_cdrom(struct thread *td, struct linux_ioctl_args *args) 1247 { 1248 struct file *fp; 1249 int error; 1250 1251 if ((error = fget(td, args->fd, &fp)) != 0) 1252 return (error); 1253 switch (args->cmd & 0xffff) { 1254 1255 case LINUX_CDROMPAUSE: 1256 args->cmd = CDIOCPAUSE; 1257 error = (ioctl(td, (struct ioctl_args *)args)); 1258 break; 1259 1260 case LINUX_CDROMRESUME: 1261 args->cmd = CDIOCRESUME; 1262 error = (ioctl(td, (struct ioctl_args *)args)); 1263 break; 1264 1265 case LINUX_CDROMPLAYMSF: 1266 args->cmd = CDIOCPLAYMSF; 1267 error = (ioctl(td, (struct ioctl_args *)args)); 1268 break; 1269 1270 case LINUX_CDROMPLAYTRKIND: 1271 args->cmd = CDIOCPLAYTRACKS; 1272 error = (ioctl(td, (struct ioctl_args *)args)); 1273 break; 1274 1275 case LINUX_CDROMREADTOCHDR: { 1276 struct ioc_toc_header th; 1277 struct linux_cdrom_tochdr lth; 1278 error = fo_ioctl(fp, CDIOREADTOCHEADER, (caddr_t)&th, td); 1279 if (!error) { 1280 lth.cdth_trk0 = th.starting_track; 1281 lth.cdth_trk1 = th.ending_track; 1282 copyout(<h, (caddr_t)args->arg, sizeof(lth)); 1283 } 1284 break; 1285 } 1286 1287 case LINUX_CDROMREADTOCENTRY: { 1288 struct linux_cdrom_tocentry lte, *ltep = 1289 (struct linux_cdrom_tocentry *)args->arg; 1290 struct ioc_read_toc_single_entry irtse; 1291 irtse.address_format = ltep->cdte_format; 1292 irtse.track = ltep->cdte_track; 1293 error = fo_ioctl(fp, CDIOREADTOCENTRY, (caddr_t)&irtse, td); 1294 if (!error) { 1295 lte = *ltep; 1296 lte.cdte_ctrl = irtse.entry.control; 1297 lte.cdte_adr = irtse.entry.addr_type; 1298 bsd_to_linux_msf_lba(irtse.address_format, 1299 &irtse.entry.addr, <e.cdte_addr); 1300 copyout(<e, (caddr_t)args->arg, sizeof(lte)); 1301 } 1302 break; 1303 } 1304 1305 case LINUX_CDROMSTOP: 1306 args->cmd = CDIOCSTOP; 1307 error = (ioctl(td, (struct ioctl_args *)args)); 1308 break; 1309 1310 case LINUX_CDROMSTART: 1311 args->cmd = CDIOCSTART; 1312 error = (ioctl(td, (struct ioctl_args *)args)); 1313 break; 1314 1315 case LINUX_CDROMEJECT: 1316 args->cmd = CDIOCEJECT; 1317 error = (ioctl(td, (struct ioctl_args *)args)); 1318 break; 1319 1320 /* LINUX_CDROMVOLCTRL */ 1321 1322 case LINUX_CDROMSUBCHNL: { 1323 struct linux_cdrom_subchnl sc; 1324 struct ioc_read_subchannel bsdsc; 1325 struct cd_sub_channel_info *bsdinfo; 1326 caddr_t sg = stackgap_init(); 1327 bsdinfo = (struct cd_sub_channel_info*)stackgap_alloc(&sg, 1328 sizeof(struct cd_sub_channel_info)); 1329 bsdsc.address_format = CD_LBA_FORMAT; 1330 bsdsc.data_format = CD_CURRENT_POSITION; 1331 bsdsc.track = 0; 1332 bsdsc.data_len = sizeof(struct cd_sub_channel_info); 1333 bsdsc.data = bsdinfo; 1334 error = fo_ioctl(fp, CDIOCREADSUBCHANNEL, (caddr_t)&bsdsc, td); 1335 if (error) 1336 break; 1337 error = copyin((caddr_t)args->arg, &sc, 1338 sizeof(struct linux_cdrom_subchnl)); 1339 if (error) 1340 break; 1341 sc.cdsc_audiostatus = bsdinfo->header.audio_status; 1342 sc.cdsc_adr = bsdinfo->what.position.addr_type; 1343 sc.cdsc_ctrl = bsdinfo->what.position.control; 1344 sc.cdsc_trk = bsdinfo->what.position.track_number; 1345 sc.cdsc_ind = bsdinfo->what.position.index_number; 1346 set_linux_cdrom_addr(&sc.cdsc_absaddr, sc.cdsc_format, 1347 bsdinfo->what.position.absaddr.lba); 1348 set_linux_cdrom_addr(&sc.cdsc_reladdr, sc.cdsc_format, 1349 bsdinfo->what.position.reladdr.lba); 1350 error = copyout(&sc, (caddr_t)args->arg, 1351 sizeof(struct linux_cdrom_subchnl)); 1352 break; 1353 } 1354 1355 /* LINUX_CDROMREADMODE2 */ 1356 /* LINUX_CDROMREADMODE1 */ 1357 /* LINUX_CDROMREADAUDIO */ 1358 /* LINUX_CDROMEJECT_SW */ 1359 /* LINUX_CDROMMULTISESSION */ 1360 /* LINUX_CDROM_GET_UPC */ 1361 1362 case LINUX_CDROMRESET: 1363 args->cmd = CDIOCRESET; 1364 error = (ioctl(td, (struct ioctl_args *)args)); 1365 break; 1366 1367 /* LINUX_CDROMVOLREAD */ 1368 /* LINUX_CDROMREADRAW */ 1369 /* LINUX_CDROMREADCOOKED */ 1370 /* LINUX_CDROMSEEK */ 1371 /* LINUX_CDROMPLAYBLK */ 1372 /* LINUX_CDROMREADALL */ 1373 /* LINUX_CDROMCLOSETRAY */ 1374 /* LINUX_CDROMLOADFROMSLOT */ 1375 /* LINUX_CDROMGETSPINDOWN */ 1376 /* LINUX_CDROMSETSPINDOWN */ 1377 /* LINUX_CDROM_SET_OPTIONS */ 1378 /* LINUX_CDROM_CLEAR_OPTIONS */ 1379 /* LINUX_CDROM_SELECT_SPEED */ 1380 /* LINUX_CDROM_SELECT_DISC */ 1381 /* LINUX_CDROM_MEDIA_CHANGED */ 1382 /* LINUX_CDROM_DRIVE_STATUS */ 1383 /* LINUX_CDROM_DISC_STATUS */ 1384 /* LINUX_CDROM_CHANGER_NSLOTS */ 1385 /* LINUX_CDROM_LOCKDOOR */ 1386 /* LINUX_CDROM_DEBUG */ 1387 /* LINUX_CDROM_GET_CAPABILITY */ 1388 /* LINUX_CDROMAUDIOBUFSIZ */ 1389 1390 case LINUX_DVD_READ_STRUCT: { 1391 l_dvd_struct lds; 1392 struct dvd_struct bds; 1393 1394 error = copyin((caddr_t)args->arg, &lds, sizeof(l_dvd_struct)); 1395 if (error) 1396 break; 1397 error = linux_to_bsd_dvd_struct(&lds, &bds); 1398 if (error) 1399 break; 1400 error = fo_ioctl(fp, DVDIOCREADSTRUCTURE, (caddr_t)&bds, td); 1401 if (error) 1402 break; 1403 error = bsd_to_linux_dvd_struct(&bds, &lds); 1404 if (error) 1405 break; 1406 error = copyout(&lds, (caddr_t)args->arg, 1407 sizeof(l_dvd_struct)); 1408 break; 1409 } 1410 1411 /* LINUX_DVD_WRITE_STRUCT */ 1412 1413 case LINUX_DVD_AUTH: { 1414 l_dvd_authinfo lda; 1415 struct dvd_authinfo bda; 1416 int bcode; 1417 1418 error = copyin((caddr_t)args->arg, &lda, 1419 sizeof(l_dvd_authinfo)); 1420 if (error) 1421 break; 1422 error = linux_to_bsd_dvd_authinfo(&lda, &bcode, &bda); 1423 if (error) 1424 break; 1425 error = fo_ioctl(fp, bcode, (caddr_t)&bda, td); 1426 if (error) { 1427 if (lda.type == LINUX_DVD_HOST_SEND_KEY2) { 1428 lda.type = LINUX_DVD_AUTH_FAILURE; 1429 copyout(&lda, (caddr_t)args->arg, 1430 sizeof(l_dvd_authinfo)); 1431 } 1432 break; 1433 } 1434 error = bsd_to_linux_dvd_authinfo(&bda, &lda); 1435 if (error) 1436 break; 1437 error = copyout(&lda, (caddr_t)args->arg, 1438 sizeof(l_dvd_authinfo)); 1439 break; 1440 } 1441 1442 /* LINUX_CDROM_SEND_PACKET */ 1443 /* LINUX_CDROM_NEXT_WRITABLE */ 1444 /* LINUX_CDROM_LAST_WRITTEN */ 1445 1446 default: 1447 error = ENOIOCTL; 1448 break; 1449 } 1450 1451 fdrop(fp, td); 1452 return (error); 1453 } 1454 1455 /* 1456 * Sound related ioctls 1457 */ 1458 1459 static u_int32_t dirbits[4] = { IOC_VOID, IOC_IN, IOC_OUT, IOC_INOUT }; 1460 1461 #define SETDIR(c) (((c) & ~IOC_DIRMASK) | dirbits[args->cmd >> 30]) 1462 1463 static int 1464 linux_ioctl_sound(struct thread *td, struct linux_ioctl_args *args) 1465 { 1466 1467 switch (args->cmd & 0xffff) { 1468 1469 case LINUX_SOUND_MIXER_WRITE_VOLUME: 1470 args->cmd = SETDIR(SOUND_MIXER_WRITE_VOLUME); 1471 return (ioctl(td, (struct ioctl_args *)args)); 1472 1473 case LINUX_SOUND_MIXER_WRITE_BASS: 1474 args->cmd = SETDIR(SOUND_MIXER_WRITE_BASS); 1475 return (ioctl(td, (struct ioctl_args *)args)); 1476 1477 case LINUX_SOUND_MIXER_WRITE_TREBLE: 1478 args->cmd = SETDIR(SOUND_MIXER_WRITE_TREBLE); 1479 return (ioctl(td, (struct ioctl_args *)args)); 1480 1481 case LINUX_SOUND_MIXER_WRITE_SYNTH: 1482 args->cmd = SETDIR(SOUND_MIXER_WRITE_SYNTH); 1483 return (ioctl(td, (struct ioctl_args *)args)); 1484 1485 case LINUX_SOUND_MIXER_WRITE_PCM: 1486 args->cmd = SETDIR(SOUND_MIXER_WRITE_PCM); 1487 return (ioctl(td, (struct ioctl_args *)args)); 1488 1489 case LINUX_SOUND_MIXER_WRITE_SPEAKER: 1490 args->cmd = SETDIR(SOUND_MIXER_WRITE_SPEAKER); 1491 return (ioctl(td, (struct ioctl_args *)args)); 1492 1493 case LINUX_SOUND_MIXER_WRITE_LINE: 1494 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE); 1495 return (ioctl(td, (struct ioctl_args *)args)); 1496 1497 case LINUX_SOUND_MIXER_WRITE_MIC: 1498 args->cmd = SETDIR(SOUND_MIXER_WRITE_MIC); 1499 return (ioctl(td, (struct ioctl_args *)args)); 1500 1501 case LINUX_SOUND_MIXER_WRITE_CD: 1502 args->cmd = SETDIR(SOUND_MIXER_WRITE_CD); 1503 return (ioctl(td, (struct ioctl_args *)args)); 1504 1505 case LINUX_SOUND_MIXER_WRITE_IMIX: 1506 args->cmd = SETDIR(SOUND_MIXER_WRITE_IMIX); 1507 return (ioctl(td, (struct ioctl_args *)args)); 1508 1509 case LINUX_SOUND_MIXER_WRITE_ALTPCM: 1510 args->cmd = SETDIR(SOUND_MIXER_WRITE_ALTPCM); 1511 return (ioctl(td, (struct ioctl_args *)args)); 1512 1513 case LINUX_SOUND_MIXER_WRITE_RECLEV: 1514 args->cmd = SETDIR(SOUND_MIXER_WRITE_RECLEV); 1515 return (ioctl(td, (struct ioctl_args *)args)); 1516 1517 case LINUX_SOUND_MIXER_WRITE_IGAIN: 1518 args->cmd = SETDIR(SOUND_MIXER_WRITE_IGAIN); 1519 return (ioctl(td, (struct ioctl_args *)args)); 1520 1521 case LINUX_SOUND_MIXER_WRITE_OGAIN: 1522 args->cmd = SETDIR(SOUND_MIXER_WRITE_OGAIN); 1523 return (ioctl(td, (struct ioctl_args *)args)); 1524 1525 case LINUX_SOUND_MIXER_WRITE_LINE1: 1526 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE1); 1527 return (ioctl(td, (struct ioctl_args *)args)); 1528 1529 case LINUX_SOUND_MIXER_WRITE_LINE2: 1530 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE2); 1531 return (ioctl(td, (struct ioctl_args *)args)); 1532 1533 case LINUX_SOUND_MIXER_WRITE_LINE3: 1534 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE3); 1535 return (ioctl(td, (struct ioctl_args *)args)); 1536 1537 case LINUX_OSS_GETVERSION: { 1538 int version = linux_get_oss_version(td->td_proc); 1539 return (copyout(&version, (caddr_t)args->arg, sizeof(int))); 1540 } 1541 1542 case LINUX_SOUND_MIXER_READ_DEVMASK: 1543 args->cmd = SOUND_MIXER_READ_DEVMASK; 1544 return (ioctl(td, (struct ioctl_args *)args)); 1545 1546 case LINUX_SOUND_MIXER_WRITE_RECSRC: 1547 args->cmd = SETDIR(SOUND_MIXER_WRITE_RECSRC); 1548 return (ioctl(td, (struct ioctl_args *)args)); 1549 1550 case LINUX_SNDCTL_DSP_RESET: 1551 args->cmd = SNDCTL_DSP_RESET; 1552 return (ioctl(td, (struct ioctl_args *)args)); 1553 1554 case LINUX_SNDCTL_DSP_SYNC: 1555 args->cmd = SNDCTL_DSP_SYNC; 1556 return (ioctl(td, (struct ioctl_args *)args)); 1557 1558 case LINUX_SNDCTL_DSP_SPEED: 1559 args->cmd = SNDCTL_DSP_SPEED; 1560 return (ioctl(td, (struct ioctl_args *)args)); 1561 1562 case LINUX_SNDCTL_DSP_STEREO: 1563 args->cmd = SNDCTL_DSP_STEREO; 1564 return (ioctl(td, (struct ioctl_args *)args)); 1565 1566 case LINUX_SNDCTL_DSP_GETBLKSIZE: /* LINUX_SNDCTL_DSP_SETBLKSIZE */ 1567 args->cmd = SNDCTL_DSP_GETBLKSIZE; 1568 return (ioctl(td, (struct ioctl_args *)args)); 1569 1570 case LINUX_SNDCTL_DSP_SETFMT: 1571 args->cmd = SNDCTL_DSP_SETFMT; 1572 return (ioctl(td, (struct ioctl_args *)args)); 1573 1574 case LINUX_SOUND_PCM_WRITE_CHANNELS: 1575 args->cmd = SOUND_PCM_WRITE_CHANNELS; 1576 return (ioctl(td, (struct ioctl_args *)args)); 1577 1578 case LINUX_SOUND_PCM_WRITE_FILTER: 1579 args->cmd = SOUND_PCM_WRITE_FILTER; 1580 return (ioctl(td, (struct ioctl_args *)args)); 1581 1582 case LINUX_SNDCTL_DSP_POST: 1583 args->cmd = SNDCTL_DSP_POST; 1584 return (ioctl(td, (struct ioctl_args *)args)); 1585 1586 case LINUX_SNDCTL_DSP_SUBDIVIDE: 1587 args->cmd = SNDCTL_DSP_SUBDIVIDE; 1588 return (ioctl(td, (struct ioctl_args *)args)); 1589 1590 case LINUX_SNDCTL_DSP_SETFRAGMENT: 1591 args->cmd = SNDCTL_DSP_SETFRAGMENT; 1592 return (ioctl(td, (struct ioctl_args *)args)); 1593 1594 case LINUX_SNDCTL_DSP_GETFMTS: 1595 args->cmd = SNDCTL_DSP_GETFMTS; 1596 return (ioctl(td, (struct ioctl_args *)args)); 1597 1598 case LINUX_SNDCTL_DSP_GETOSPACE: 1599 args->cmd = SNDCTL_DSP_GETOSPACE; 1600 return (ioctl(td, (struct ioctl_args *)args)); 1601 1602 case LINUX_SNDCTL_DSP_GETISPACE: 1603 args->cmd = SNDCTL_DSP_GETISPACE; 1604 return (ioctl(td, (struct ioctl_args *)args)); 1605 1606 case LINUX_SNDCTL_DSP_NONBLOCK: 1607 args->cmd = SNDCTL_DSP_NONBLOCK; 1608 return (ioctl(td, (struct ioctl_args *)args)); 1609 1610 case LINUX_SNDCTL_DSP_GETCAPS: 1611 args->cmd = SNDCTL_DSP_GETCAPS; 1612 return (ioctl(td, (struct ioctl_args *)args)); 1613 1614 case LINUX_SNDCTL_DSP_SETTRIGGER: /* LINUX_SNDCTL_GETTRIGGER */ 1615 args->cmd = SNDCTL_DSP_SETTRIGGER; 1616 return (ioctl(td, (struct ioctl_args *)args)); 1617 1618 case LINUX_SNDCTL_DSP_GETIPTR: 1619 args->cmd = SNDCTL_DSP_GETIPTR; 1620 return (ioctl(td, (struct ioctl_args *)args)); 1621 1622 case LINUX_SNDCTL_DSP_GETOPTR: 1623 args->cmd = SNDCTL_DSP_GETOPTR; 1624 return (ioctl(td, (struct ioctl_args *)args)); 1625 1626 case LINUX_SNDCTL_DSP_GETODELAY: 1627 args->cmd = SNDCTL_DSP_GETODELAY; 1628 return (ioctl(td, (struct ioctl_args *)args)); 1629 1630 case LINUX_SNDCTL_SEQ_RESET: 1631 args->cmd = SNDCTL_SEQ_RESET; 1632 return (ioctl(td, (struct ioctl_args *)args)); 1633 1634 case LINUX_SNDCTL_SEQ_SYNC: 1635 args->cmd = SNDCTL_SEQ_SYNC; 1636 return (ioctl(td, (struct ioctl_args *)args)); 1637 1638 case LINUX_SNDCTL_SYNTH_INFO: 1639 args->cmd = SNDCTL_SYNTH_INFO; 1640 return (ioctl(td, (struct ioctl_args *)args)); 1641 1642 case LINUX_SNDCTL_SEQ_CTRLRATE: 1643 args->cmd = SNDCTL_SEQ_CTRLRATE; 1644 return (ioctl(td, (struct ioctl_args *)args)); 1645 1646 case LINUX_SNDCTL_SEQ_GETOUTCOUNT: 1647 args->cmd = SNDCTL_SEQ_GETOUTCOUNT; 1648 return (ioctl(td, (struct ioctl_args *)args)); 1649 1650 case LINUX_SNDCTL_SEQ_GETINCOUNT: 1651 args->cmd = SNDCTL_SEQ_GETINCOUNT; 1652 return (ioctl(td, (struct ioctl_args *)args)); 1653 1654 case LINUX_SNDCTL_SEQ_PERCMODE: 1655 args->cmd = SNDCTL_SEQ_PERCMODE; 1656 return (ioctl(td, (struct ioctl_args *)args)); 1657 1658 case LINUX_SNDCTL_FM_LOAD_INSTR: 1659 args->cmd = SNDCTL_FM_LOAD_INSTR; 1660 return (ioctl(td, (struct ioctl_args *)args)); 1661 1662 case LINUX_SNDCTL_SEQ_TESTMIDI: 1663 args->cmd = SNDCTL_SEQ_TESTMIDI; 1664 return (ioctl(td, (struct ioctl_args *)args)); 1665 1666 case LINUX_SNDCTL_SEQ_RESETSAMPLES: 1667 args->cmd = SNDCTL_SEQ_RESETSAMPLES; 1668 return (ioctl(td, (struct ioctl_args *)args)); 1669 1670 case LINUX_SNDCTL_SEQ_NRSYNTHS: 1671 args->cmd = SNDCTL_SEQ_NRSYNTHS; 1672 return (ioctl(td, (struct ioctl_args *)args)); 1673 1674 case LINUX_SNDCTL_SEQ_NRMIDIS: 1675 args->cmd = SNDCTL_SEQ_NRMIDIS; 1676 return (ioctl(td, (struct ioctl_args *)args)); 1677 1678 case LINUX_SNDCTL_MIDI_INFO: 1679 args->cmd = SNDCTL_MIDI_INFO; 1680 return (ioctl(td, (struct ioctl_args *)args)); 1681 1682 case LINUX_SNDCTL_SEQ_TRESHOLD: 1683 args->cmd = SNDCTL_SEQ_TRESHOLD; 1684 return (ioctl(td, (struct ioctl_args *)args)); 1685 1686 case LINUX_SNDCTL_SYNTH_MEMAVL: 1687 args->cmd = SNDCTL_SYNTH_MEMAVL; 1688 return (ioctl(td, (struct ioctl_args *)args)); 1689 1690 } 1691 1692 return (ENOIOCTL); 1693 } 1694 1695 /* 1696 * Console related ioctls 1697 */ 1698 1699 #define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG) 1700 1701 static int 1702 linux_ioctl_console(struct thread *td, struct linux_ioctl_args *args) 1703 { 1704 struct file *fp; 1705 int error; 1706 1707 if ((error = fget(td, args->fd, &fp)) != 0) 1708 return (error); 1709 switch (args->cmd & 0xffff) { 1710 1711 case LINUX_KIOCSOUND: 1712 args->cmd = KIOCSOUND; 1713 error = (ioctl(td, (struct ioctl_args *)args)); 1714 break; 1715 1716 case LINUX_KDMKTONE: 1717 args->cmd = KDMKTONE; 1718 error = (ioctl(td, (struct ioctl_args *)args)); 1719 break; 1720 1721 case LINUX_KDGETLED: 1722 args->cmd = KDGETLED; 1723 error = (ioctl(td, (struct ioctl_args *)args)); 1724 break; 1725 1726 case LINUX_KDSETLED: 1727 args->cmd = KDSETLED; 1728 error = (ioctl(td, (struct ioctl_args *)args)); 1729 break; 1730 1731 case LINUX_KDSETMODE: 1732 args->cmd = KDSETMODE; 1733 error = (ioctl(td, (struct ioctl_args *)args)); 1734 break; 1735 1736 case LINUX_KDGETMODE: 1737 args->cmd = KDGETMODE; 1738 error = (ioctl(td, (struct ioctl_args *)args)); 1739 break; 1740 1741 case LINUX_KDGKBMODE: 1742 args->cmd = KDGKBMODE; 1743 error = (ioctl(td, (struct ioctl_args *)args)); 1744 break; 1745 1746 case LINUX_KDSKBMODE: { 1747 int kbdmode; 1748 switch (args->arg) { 1749 case LINUX_KBD_RAW: 1750 kbdmode = K_RAW; 1751 break; 1752 case LINUX_KBD_XLATE: 1753 kbdmode = K_XLATE; 1754 break; 1755 case LINUX_KBD_MEDIUMRAW: 1756 kbdmode = K_RAW; 1757 break; 1758 default: 1759 fdrop(fp, td); 1760 return (EINVAL); 1761 } 1762 error = (fo_ioctl(fp, KDSKBMODE, (caddr_t)&kbdmode, td)); 1763 break; 1764 } 1765 1766 case LINUX_VT_OPENQRY: 1767 args->cmd = VT_OPENQRY; 1768 error = (ioctl(td, (struct ioctl_args *)args)); 1769 break; 1770 1771 case LINUX_VT_GETMODE: 1772 args->cmd = VT_GETMODE; 1773 error = (ioctl(td, (struct ioctl_args *)args)); 1774 break; 1775 1776 case LINUX_VT_SETMODE: { 1777 struct vt_mode *mode; 1778 args->cmd = VT_SETMODE; 1779 mode = (struct vt_mode *)args->arg; 1780 if (!ISSIGVALID(mode->frsig) && ISSIGVALID(mode->acqsig)) 1781 mode->frsig = mode->acqsig; 1782 error = (ioctl(td, (struct ioctl_args *)args)); 1783 break; 1784 } 1785 1786 case LINUX_VT_GETSTATE: 1787 args->cmd = VT_GETACTIVE; 1788 error = (ioctl(td, (struct ioctl_args *)args)); 1789 break; 1790 1791 case LINUX_VT_RELDISP: 1792 args->cmd = VT_RELDISP; 1793 error = (ioctl(td, (struct ioctl_args *)args)); 1794 break; 1795 1796 case LINUX_VT_ACTIVATE: 1797 args->cmd = VT_ACTIVATE; 1798 error = (ioctl(td, (struct ioctl_args *)args)); 1799 break; 1800 1801 case LINUX_VT_WAITACTIVE: 1802 args->cmd = VT_WAITACTIVE; 1803 error = (ioctl(td, (struct ioctl_args *)args)); 1804 break; 1805 1806 default: 1807 error = ENOIOCTL; 1808 break; 1809 } 1810 1811 fdrop(fp, td); 1812 return (error); 1813 } 1814 1815 /* 1816 * Criteria for interface name translation 1817 */ 1818 #define IFP_IS_ETH(ifp) (ifp->if_type == IFT_ETHER) 1819 1820 /* 1821 * Interface function used by linprocfs (at the time of writing). It's not 1822 * used by the Linuxulator itself. 1823 */ 1824 int 1825 linux_ifname(struct ifnet *ifp, char *buffer, size_t buflen) 1826 { 1827 struct ifnet *ifscan; 1828 int ethno; 1829 1830 /* Short-circuit non ethernet interfaces */ 1831 if (!IFP_IS_ETH(ifp)) 1832 return (snprintf(buffer, buflen, "%s%d", ifp->if_name, 1833 ifp->if_unit)); 1834 1835 /* Determine the (relative) unit number for ethernet interfaces */ 1836 ethno = 0; 1837 TAILQ_FOREACH(ifscan, &ifnet, if_link) { 1838 if (ifscan == ifp) 1839 return (snprintf(buffer, buflen, "eth%d", ethno)); 1840 if (IFP_IS_ETH(ifscan)) 1841 ethno++; 1842 } 1843 1844 return (0); 1845 } 1846 1847 /* 1848 * Translate a Linux interface name to a FreeBSD interface name, 1849 * and return the associated ifnet structure 1850 * bsdname and lxname need to be least IFNAMSIZ bytes long, but 1851 * can point to the same buffer. 1852 */ 1853 1854 static struct ifnet * 1855 ifname_linux_to_bsd(const char *lxname, char *bsdname) 1856 { 1857 struct ifnet *ifp; 1858 int len, unit; 1859 char *ep; 1860 int is_eth, index; 1861 1862 for (len = 0; len < LINUX_IFNAMSIZ; ++len) 1863 if (!isalpha(lxname[len])) 1864 break; 1865 if (len == 0 || len == LINUX_IFNAMSIZ) 1866 return (NULL); 1867 unit = (int)strtoul(lxname + len, &ep, 10); 1868 if (ep == NULL || ep == lxname + len || ep >= lxname + LINUX_IFNAMSIZ) 1869 return (NULL); 1870 index = 0; 1871 is_eth = (len == 3 && !strncmp(lxname, "eth", len)) ? 1 : 0; 1872 TAILQ_FOREACH(ifp, &ifnet, if_link) { 1873 /* 1874 * Allow Linux programs to use FreeBSD names. Don't presume 1875 * we never have an interface named "eth", so don't make 1876 * the test optional based on is_eth. 1877 */ 1878 if (ifp->if_unit == unit && ifp->if_name[len] == '\0' && 1879 strncmp(ifp->if_name, lxname, len) == 0) 1880 break; 1881 if (is_eth && IFP_IS_ETH(ifp) && unit == index++) 1882 break; 1883 } 1884 if (ifp != NULL) 1885 snprintf(bsdname, IFNAMSIZ, "%s%d", ifp->if_name, ifp->if_unit); 1886 return (ifp); 1887 } 1888 1889 /* 1890 * Implement the SIOCGIFCONF ioctl 1891 */ 1892 1893 static int 1894 linux_ifconf(struct thread *td, struct ifconf *uifc) 1895 { 1896 struct ifconf ifc; 1897 struct l_ifreq ifr; 1898 struct ifnet *ifp; 1899 struct ifaddr *ifa; 1900 struct iovec iov; 1901 struct uio uio; 1902 int error, ethno; 1903 1904 error = copyin(uifc, &ifc, sizeof ifc); 1905 if (error != 0) 1906 return (error); 1907 1908 /* much easier to use uiomove than keep track ourselves */ 1909 iov.iov_base = ifc.ifc_buf; 1910 iov.iov_len = ifc.ifc_len; 1911 uio.uio_iov = &iov; 1912 uio.uio_iovcnt = 1; 1913 uio.uio_offset = 0; 1914 uio.uio_resid = ifc.ifc_len; 1915 uio.uio_segflg = UIO_USERSPACE; 1916 uio.uio_rw = UIO_READ; 1917 uio.uio_td = td; 1918 1919 /* Keep track of eth interfaces */ 1920 ethno = 0; 1921 1922 /* Return all AF_INET addresses of all interfaces */ 1923 TAILQ_FOREACH(ifp, &ifnet, if_link) { 1924 if (uio.uio_resid <= 0) 1925 break; 1926 1927 bzero(&ifr, sizeof ifr); 1928 if (IFP_IS_ETH(ifp)) 1929 snprintf(ifr.ifr_name, LINUX_IFNAMSIZ, "eth%d", 1930 ethno++); 1931 else 1932 snprintf(ifr.ifr_name, LINUX_IFNAMSIZ, "%s%d", 1933 ifp->if_name, ifp->if_unit); 1934 1935 /* Walk the address list */ 1936 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 1937 struct sockaddr *sa = ifa->ifa_addr; 1938 1939 if (uio.uio_resid <= 0) 1940 break; 1941 1942 if (sa->sa_family == AF_INET) { 1943 ifr.ifr_addr.sa_family = LINUX_AF_INET; 1944 memcpy(ifr.ifr_addr.sa_data, sa->sa_data, 1945 sizeof(ifr.ifr_addr.sa_data)); 1946 1947 error = uiomove((caddr_t)&ifr, sizeof ifr, 1948 &uio); 1949 if (error != 0) 1950 return (error); 1951 } 1952 } 1953 } 1954 1955 ifc.ifc_len -= uio.uio_resid; 1956 error = copyout(&ifc, uifc, sizeof ifc); 1957 1958 return (error); 1959 } 1960 1961 static int 1962 linux_gifflags(struct thread *td, struct ifnet *ifp, struct l_ifreq *ifr) 1963 { 1964 l_short flags; 1965 1966 flags = ifp->if_flags; 1967 /* these flags have no Linux equivalent */ 1968 flags &= ~(IFF_SMART|IFF_OACTIVE|IFF_SIMPLEX| 1969 IFF_LINK0|IFF_LINK1|IFF_LINK2); 1970 /* Linux' multicast flag is in a different bit */ 1971 if (flags & IFF_MULTICAST) { 1972 flags &= ~IFF_MULTICAST; 1973 flags |= 0x1000; 1974 } 1975 1976 return (copyout(&flags, &ifr->ifr_flags, sizeof flags)); 1977 } 1978 1979 #define ARPHRD_ETHER 1 1980 #define ARPHRD_LOOPBACK 772 1981 1982 static int 1983 linux_gifhwaddr(struct ifnet *ifp, struct l_ifreq *ifr) 1984 { 1985 struct ifaddr *ifa; 1986 struct sockaddr_dl *sdl; 1987 struct l_sockaddr lsa; 1988 1989 if (ifp->if_type == IFT_LOOP) { 1990 bzero(&lsa, sizeof lsa); 1991 lsa.sa_family = ARPHRD_LOOPBACK; 1992 return (copyout(&lsa, &ifr->ifr_hwaddr, sizeof lsa)); 1993 } 1994 1995 if (ifp->if_type != IFT_ETHER) 1996 return (ENOENT); 1997 1998 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 1999 sdl = (struct sockaddr_dl*)ifa->ifa_addr; 2000 if (sdl != NULL && (sdl->sdl_family == AF_LINK) && 2001 (sdl->sdl_type == IFT_ETHER)) { 2002 bzero(&lsa, sizeof lsa); 2003 lsa.sa_family = ARPHRD_ETHER; 2004 bcopy(LLADDR(sdl), lsa.sa_data, LINUX_IFHWADDRLEN); 2005 return (copyout(&lsa, &ifr->ifr_hwaddr, sizeof lsa)); 2006 } 2007 } 2008 2009 return (ENOENT); 2010 } 2011 2012 /* 2013 * Socket related ioctls 2014 */ 2015 2016 static int 2017 linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args) 2018 { 2019 char lifname[LINUX_IFNAMSIZ], ifname[IFNAMSIZ]; 2020 struct ifnet *ifp; 2021 struct file *fp; 2022 int error, type; 2023 2024 KASSERT(LINUX_IFNAMSIZ == IFNAMSIZ, 2025 ("%s(): LINUX_IFNAMSIZ != IFNAMSIZ", __func__)); 2026 2027 ifp = NULL; 2028 error = 0; 2029 2030 mtx_lock(&Giant); 2031 if ((error = fget(td, args->fd, &fp)) != 0) { 2032 mtx_unlock(&Giant); 2033 return (error); 2034 } 2035 type = fp->f_type; 2036 fdrop(fp, td); 2037 mtx_unlock(&Giant); 2038 2039 if (type != DTYPE_SOCKET) { 2040 /* not a socket - probably a tap / vmnet device */ 2041 switch (args->cmd) { 2042 case LINUX_SIOCGIFADDR: 2043 case LINUX_SIOCSIFADDR: 2044 case LINUX_SIOCGIFFLAGS: 2045 return (linux_ioctl_special(td, args)); 2046 default: 2047 return (ENOIOCTL); 2048 } 2049 } 2050 2051 switch (args->cmd & 0xffff) { 2052 2053 case LINUX_FIOGETOWN: 2054 case LINUX_FIOSETOWN: 2055 case LINUX_SIOCADDMULTI: 2056 case LINUX_SIOCATMARK: 2057 case LINUX_SIOCDELMULTI: 2058 case LINUX_SIOCGIFCONF: 2059 case LINUX_SIOCGPGRP: 2060 case LINUX_SIOCSPGRP: 2061 /* these ioctls don't take an interface name */ 2062 #ifdef DEBUG 2063 printf("%s(): ioctl %d\n", __func__, 2064 args->cmd & 0xffff); 2065 #endif 2066 break; 2067 2068 case LINUX_SIOCGIFFLAGS: 2069 case LINUX_SIOCGIFADDR: 2070 case LINUX_SIOCSIFADDR: 2071 case LINUX_SIOCGIFDSTADDR: 2072 case LINUX_SIOCGIFBRDADDR: 2073 case LINUX_SIOCGIFNETMASK: 2074 case LINUX_SIOCSIFNETMASK: 2075 case LINUX_SIOCGIFMTU: 2076 case LINUX_SIOCSIFMTU: 2077 case LINUX_SIOCSIFNAME: 2078 case LINUX_SIOCGIFHWADDR: 2079 case LINUX_SIOCSIFHWADDR: 2080 case LINUX_SIOCDEVPRIVATE: 2081 case LINUX_SIOCDEVPRIVATE+1: 2082 /* copy in the interface name and translate it. */ 2083 error = copyin((char *)args->arg, lifname, LINUX_IFNAMSIZ); 2084 if (error != 0) 2085 return (error); 2086 #ifdef DEBUG 2087 printf("%s(): ioctl %d on %.*s\n", __func__, 2088 args->cmd & 0xffff, LINUX_IFNAMSIZ, lifname); 2089 #endif 2090 ifp = ifname_linux_to_bsd(lifname, ifname); 2091 if (ifp == NULL) 2092 return (EINVAL); 2093 /* 2094 * We need to copy it back out in case we pass the 2095 * request on to our native ioctl(), which will expect 2096 * the ifreq to be in user space and have the correct 2097 * interface name. 2098 */ 2099 error = copyout(ifname, (char *)args->arg, IFNAMSIZ); 2100 if (error != 0) 2101 return (error); 2102 #ifdef DEBUG 2103 printf("%s(): %s translated to %s\n", __func__, 2104 lifname, ifname); 2105 #endif 2106 break; 2107 2108 default: 2109 return (ENOIOCTL); 2110 } 2111 2112 switch (args->cmd & 0xffff) { 2113 2114 case LINUX_FIOSETOWN: 2115 args->cmd = FIOSETOWN; 2116 error = ioctl(td, (struct ioctl_args *)args); 2117 break; 2118 2119 case LINUX_SIOCSPGRP: 2120 args->cmd = SIOCSPGRP; 2121 error = ioctl(td, (struct ioctl_args *)args); 2122 break; 2123 2124 case LINUX_FIOGETOWN: 2125 args->cmd = FIOGETOWN; 2126 error = ioctl(td, (struct ioctl_args *)args); 2127 break; 2128 2129 case LINUX_SIOCGPGRP: 2130 args->cmd = SIOCGPGRP; 2131 error = ioctl(td, (struct ioctl_args *)args); 2132 break; 2133 2134 case LINUX_SIOCATMARK: 2135 args->cmd = SIOCATMARK; 2136 error = ioctl(td, (struct ioctl_args *)args); 2137 break; 2138 2139 /* LINUX_SIOCGSTAMP */ 2140 2141 case LINUX_SIOCGIFCONF: 2142 error = linux_ifconf(td, (struct ifconf *)args->arg); 2143 break; 2144 2145 case LINUX_SIOCGIFFLAGS: 2146 args->cmd = SIOCGIFFLAGS; 2147 error = linux_gifflags(td, ifp, (struct l_ifreq *)args->arg); 2148 break; 2149 2150 case LINUX_SIOCGIFADDR: 2151 args->cmd = OSIOCGIFADDR; 2152 error = ioctl(td, (struct ioctl_args *)args); 2153 break; 2154 2155 case LINUX_SIOCSIFADDR: 2156 /* XXX probably doesn't work, included for completeness */ 2157 args->cmd = SIOCSIFADDR; 2158 error = ioctl(td, (struct ioctl_args *)args); 2159 break; 2160 2161 case LINUX_SIOCGIFDSTADDR: 2162 args->cmd = OSIOCGIFDSTADDR; 2163 error = ioctl(td, (struct ioctl_args *)args); 2164 break; 2165 2166 case LINUX_SIOCGIFBRDADDR: 2167 args->cmd = OSIOCGIFBRDADDR; 2168 error = ioctl(td, (struct ioctl_args *)args); 2169 break; 2170 2171 case LINUX_SIOCGIFNETMASK: 2172 args->cmd = OSIOCGIFNETMASK; 2173 error = ioctl(td, (struct ioctl_args *)args); 2174 break; 2175 2176 case LINUX_SIOCSIFNETMASK: 2177 error = ENOIOCTL; 2178 break; 2179 2180 case LINUX_SIOCGIFMTU: 2181 args->cmd = SIOCGIFMTU; 2182 error = ioctl(td, (struct ioctl_args *)args); 2183 break; 2184 2185 case LINUX_SIOCSIFMTU: 2186 args->cmd = SIOCSIFMTU; 2187 error = ioctl(td, (struct ioctl_args *)args); 2188 break; 2189 2190 case LINUX_SIOCSIFNAME: 2191 error = ENOIOCTL; 2192 break; 2193 2194 case LINUX_SIOCGIFHWADDR: 2195 error = linux_gifhwaddr(ifp, (struct l_ifreq *)args->arg); 2196 break; 2197 2198 case LINUX_SIOCSIFHWADDR: 2199 error = ENOIOCTL; 2200 break; 2201 2202 case LINUX_SIOCADDMULTI: 2203 args->cmd = SIOCADDMULTI; 2204 error = ioctl(td, (struct ioctl_args *)args); 2205 break; 2206 2207 case LINUX_SIOCDELMULTI: 2208 args->cmd = SIOCDELMULTI; 2209 error = ioctl(td, (struct ioctl_args *)args); 2210 break; 2211 2212 /* 2213 * XXX This is slightly bogus, but these ioctls are currently 2214 * XXX only used by the aironet (if_an) network driver. 2215 */ 2216 case LINUX_SIOCDEVPRIVATE: 2217 args->cmd = SIOCGPRIVATE_0; 2218 error = ioctl(td, (struct ioctl_args *)args); 2219 break; 2220 2221 case LINUX_SIOCDEVPRIVATE+1: 2222 args->cmd = SIOCGPRIVATE_1; 2223 error = ioctl(td, (struct ioctl_args *)args); 2224 break; 2225 } 2226 2227 if (ifp != NULL) 2228 /* restore the original interface name */ 2229 copyout(lifname, (char *)args->arg, LINUX_IFNAMSIZ); 2230 2231 #ifdef DEBUG 2232 printf("%s(): returning %d\n", __func__, error); 2233 #endif 2234 return (error); 2235 } 2236 2237 /* 2238 * Device private ioctl handler 2239 */ 2240 static int 2241 linux_ioctl_private(struct thread *td, struct linux_ioctl_args *args) 2242 { 2243 struct file *fp; 2244 int error, type; 2245 2246 mtx_lock(&Giant); 2247 if ((error = fget(td, args->fd, &fp)) != 0) { 2248 mtx_unlock(&Giant); 2249 return (error); 2250 } 2251 type = fp->f_type; 2252 fdrop(fp, td); 2253 mtx_unlock(&Giant); 2254 if (type == DTYPE_SOCKET) 2255 return (linux_ioctl_socket(td, args)); 2256 return (ENOIOCTL); 2257 } 2258 2259 /* 2260 * Special ioctl handler 2261 */ 2262 static int 2263 linux_ioctl_special(struct thread *td, struct linux_ioctl_args *args) 2264 { 2265 int error; 2266 2267 switch (args->cmd) { 2268 case LINUX_SIOCGIFADDR: 2269 args->cmd = SIOCGIFADDR; 2270 error = ioctl(td, (struct ioctl_args *)args); 2271 break; 2272 case LINUX_SIOCSIFADDR: 2273 args->cmd = SIOCSIFADDR; 2274 error = ioctl(td, (struct ioctl_args *)args); 2275 break; 2276 case LINUX_SIOCGIFFLAGS: 2277 args->cmd = SIOCGIFFLAGS; 2278 error = ioctl(td, (struct ioctl_args *)args); 2279 break; 2280 default: 2281 error = ENOIOCTL; 2282 } 2283 2284 return (error); 2285 } 2286 2287 /* 2288 * main ioctl syscall function 2289 */ 2290 2291 int 2292 linux_ioctl(struct thread *td, struct linux_ioctl_args *args) 2293 { 2294 struct file *fp; 2295 struct handler_element *he; 2296 int error, cmd; 2297 2298 #ifdef DEBUG 2299 if (ldebug(ioctl)) 2300 printf(ARGS(ioctl, "%d, %04lx, *"), args->fd, 2301 (unsigned long)args->cmd); 2302 #endif 2303 2304 if ((error = fget(td, args->fd, &fp)) != 0) 2305 return (error); 2306 if ((fp->f_flag & (FREAD|FWRITE)) == 0) { 2307 fdrop(fp, td); 2308 return (EBADF); 2309 } 2310 2311 /* Iterate over the ioctl handlers */ 2312 cmd = args->cmd & 0xffff; 2313 TAILQ_FOREACH(he, &handlers, list) { 2314 if (cmd >= he->low && cmd <= he->high) { 2315 error = (*he->func)(td, args); 2316 if (error != ENOIOCTL) { 2317 fdrop(fp, td); 2318 return (error); 2319 } 2320 } 2321 } 2322 fdrop(fp, td); 2323 2324 printf("linux: 'ioctl' fd=%d, cmd=0x%x ('%c',%d) not implemented\n", 2325 args->fd, (int)(args->cmd & 0xffff), 2326 (int)(args->cmd & 0xff00) >> 8, (int)(args->cmd & 0xff)); 2327 2328 return (EINVAL); 2329 } 2330 2331 int 2332 linux_ioctl_register_handler(struct linux_ioctl_handler *h) 2333 { 2334 struct handler_element *he, *cur; 2335 2336 if (h == NULL || h->func == NULL) 2337 return (EINVAL); 2338 2339 /* 2340 * Reuse the element if the handler is already on the list, otherwise 2341 * create a new element. 2342 */ 2343 TAILQ_FOREACH(he, &handlers, list) { 2344 if (he->func == h->func) 2345 break; 2346 } 2347 if (he == NULL) { 2348 MALLOC(he, struct handler_element *, sizeof(*he), 2349 M_LINUX, M_WAITOK); 2350 he->func = h->func; 2351 } else 2352 TAILQ_REMOVE(&handlers, he, list); 2353 2354 /* Initialize range information. */ 2355 he->low = h->low; 2356 he->high = h->high; 2357 he->span = h->high - h->low + 1; 2358 2359 /* Add the element to the list, sorted on span. */ 2360 TAILQ_FOREACH(cur, &handlers, list) { 2361 if (cur->span > he->span) { 2362 TAILQ_INSERT_BEFORE(cur, he, list); 2363 return (0); 2364 } 2365 } 2366 TAILQ_INSERT_TAIL(&handlers, he, list); 2367 2368 return (0); 2369 } 2370 2371 int 2372 linux_ioctl_unregister_handler(struct linux_ioctl_handler *h) 2373 { 2374 struct handler_element *he; 2375 2376 if (h == NULL || h->func == NULL) 2377 return (EINVAL); 2378 2379 TAILQ_FOREACH(he, &handlers, list) { 2380 if (he->func == h->func) { 2381 TAILQ_REMOVE(&handlers, he, list); 2382 FREE(he, M_LINUX); 2383 return (0); 2384 } 2385 } 2386 2387 return (EINVAL); 2388 } 2389