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