1 /* 2 * Copyright (c) 1994-1995 S�ren Schmidt 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer 10 * in this position and unchanged. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software withough specific prior written permission 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/sysproto.h> 34 #include <sys/proc.h> 35 #include <sys/cdio.h> 36 #include <sys/fcntl.h> 37 #include <sys/file.h> 38 #include <sys/filedesc.h> 39 #include <sys/filio.h> 40 #include <sys/tty.h> 41 #include <sys/socket.h> 42 #include <net/if.h> 43 #include <net/if_dl.h> 44 #include <net/if_types.h> 45 #include <sys/sockio.h> 46 #include <sys/soundcard.h> 47 48 #include <machine/console.h> 49 50 #include <i386/linux/linux.h> 51 #include <i386/linux/linux_proto.h> 52 #include <i386/linux/linux_util.h> 53 #include <i386/linux/linux_mib.h> 54 55 #define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG) 56 57 struct linux_termio { 58 unsigned short c_iflag; 59 unsigned short c_oflag; 60 unsigned short c_cflag; 61 unsigned short c_lflag; 62 unsigned char c_line; 63 unsigned char c_cc[LINUX_NCC]; 64 }; 65 66 67 struct linux_termios { 68 unsigned int c_iflag; 69 unsigned int c_oflag; 70 unsigned int c_cflag; 71 unsigned int c_lflag; 72 unsigned char c_line; 73 unsigned char c_cc[LINUX_NCCS]; 74 }; 75 76 struct linux_winsize { 77 unsigned short ws_row, ws_col; 78 unsigned short ws_xpixel, ws_ypixel; 79 }; 80 81 static struct speedtab sptab[] = { 82 { B0, LINUX_B0 }, { B50, LINUX_B50 }, 83 { B75, LINUX_B75 }, { B110, LINUX_B110 }, 84 { B134, LINUX_B134 }, { B150, LINUX_B150 }, 85 { B200, LINUX_B200 }, { B300, LINUX_B300 }, 86 { B600, LINUX_B600 }, { B1200, LINUX_B1200 }, 87 { B1800, LINUX_B1800 }, { B2400, LINUX_B2400 }, 88 { B4800, LINUX_B4800 }, { B9600, LINUX_B9600 }, 89 { B19200, LINUX_B19200 }, { B38400, LINUX_B38400 }, 90 { B57600, LINUX_B57600 }, { B115200, LINUX_B115200 }, 91 {-1, -1 } 92 }; 93 94 struct linux_serial_struct { 95 int type; 96 int line; 97 int port; 98 int irq; 99 int flags; 100 int xmit_fifo_size; 101 int custom_divisor; 102 int baud_base; 103 unsigned short close_delay; 104 char reserved_char[2]; 105 int hub6; 106 unsigned short closing_wait; 107 unsigned short closing_wait2; 108 int reserved[4]; 109 }; 110 111 112 static int 113 linux_to_bsd_speed(int code, struct speedtab *table) 114 { 115 for ( ; table->sp_code != -1; table++) 116 if (table->sp_code == code) 117 return (table->sp_speed); 118 return -1; 119 } 120 121 static int 122 bsd_to_linux_speed(int speed, struct speedtab *table) 123 { 124 for ( ; table->sp_speed != -1; table++) 125 if (table->sp_speed == speed) 126 return (table->sp_code); 127 return -1; 128 } 129 130 static void 131 bsd_to_linux_termios(struct termios *bsd_termios, 132 struct linux_termios *linux_termios) 133 { 134 int i; 135 136 #ifdef DEBUG 137 printf("LINUX: BSD termios structure (input):\n"); 138 printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n", 139 bsd_termios->c_iflag, bsd_termios->c_oflag, 140 bsd_termios->c_cflag, bsd_termios->c_lflag, 141 bsd_termios->c_ispeed, bsd_termios->c_ospeed); 142 printf("c_cc "); 143 for (i=0; i<NCCS; i++) 144 printf("%02x ", bsd_termios->c_cc[i]); 145 printf("\n"); 146 #endif 147 linux_termios->c_iflag = 0; 148 if (bsd_termios->c_iflag & IGNBRK) 149 linux_termios->c_iflag |= LINUX_IGNBRK; 150 if (bsd_termios->c_iflag & BRKINT) 151 linux_termios->c_iflag |= LINUX_BRKINT; 152 if (bsd_termios->c_iflag & IGNPAR) 153 linux_termios->c_iflag |= LINUX_IGNPAR; 154 if (bsd_termios->c_iflag & PARMRK) 155 linux_termios->c_iflag |= LINUX_PARMRK; 156 if (bsd_termios->c_iflag & INPCK) 157 linux_termios->c_iflag |= LINUX_INPCK; 158 if (bsd_termios->c_iflag & ISTRIP) 159 linux_termios->c_iflag |= LINUX_ISTRIP; 160 if (bsd_termios->c_iflag & INLCR) 161 linux_termios->c_iflag |= LINUX_INLCR; 162 if (bsd_termios->c_iflag & IGNCR) 163 linux_termios->c_iflag |= LINUX_IGNCR; 164 if (bsd_termios->c_iflag & ICRNL) 165 linux_termios->c_iflag |= LINUX_ICRNL; 166 if (bsd_termios->c_iflag & IXON) 167 linux_termios->c_iflag |= LINUX_IXON; 168 if (bsd_termios->c_iflag & IXANY) 169 linux_termios->c_iflag |= LINUX_IXANY; 170 if (bsd_termios->c_iflag & IXOFF) 171 linux_termios->c_iflag |= LINUX_IXOFF; 172 if (bsd_termios->c_iflag & IMAXBEL) 173 linux_termios->c_iflag |= LINUX_IMAXBEL; 174 175 linux_termios->c_oflag = 0; 176 if (bsd_termios->c_oflag & OPOST) 177 linux_termios->c_oflag |= LINUX_OPOST; 178 if (bsd_termios->c_oflag & ONLCR) 179 linux_termios->c_oflag |= LINUX_ONLCR; 180 if (bsd_termios->c_oflag & OXTABS) 181 linux_termios->c_oflag |= LINUX_XTABS; 182 183 linux_termios->c_cflag = 184 bsd_to_linux_speed(bsd_termios->c_ispeed, sptab); 185 linux_termios->c_cflag |= (bsd_termios->c_cflag & CSIZE) >> 4; 186 if (bsd_termios->c_cflag & CSTOPB) 187 linux_termios->c_cflag |= LINUX_CSTOPB; 188 if (bsd_termios->c_cflag & CREAD) 189 linux_termios->c_cflag |= LINUX_CREAD; 190 if (bsd_termios->c_cflag & PARENB) 191 linux_termios->c_cflag |= LINUX_PARENB; 192 if (bsd_termios->c_cflag & PARODD) 193 linux_termios->c_cflag |= LINUX_PARODD; 194 if (bsd_termios->c_cflag & HUPCL) 195 linux_termios->c_cflag |= LINUX_HUPCL; 196 if (bsd_termios->c_cflag & CLOCAL) 197 linux_termios->c_cflag |= LINUX_CLOCAL; 198 if (bsd_termios->c_cflag & CRTSCTS) 199 linux_termios->c_cflag |= LINUX_CRTSCTS; 200 201 linux_termios->c_lflag = 0; 202 if (bsd_termios->c_lflag & ISIG) 203 linux_termios->c_lflag |= LINUX_ISIG; 204 if (bsd_termios->c_lflag & ICANON) 205 linux_termios->c_lflag |= LINUX_ICANON; 206 if (bsd_termios->c_lflag & ECHO) 207 linux_termios->c_lflag |= LINUX_ECHO; 208 if (bsd_termios->c_lflag & ECHOE) 209 linux_termios->c_lflag |= LINUX_ECHOE; 210 if (bsd_termios->c_lflag & ECHOK) 211 linux_termios->c_lflag |= LINUX_ECHOK; 212 if (bsd_termios->c_lflag & ECHONL) 213 linux_termios->c_lflag |= LINUX_ECHONL; 214 if (bsd_termios->c_lflag & NOFLSH) 215 linux_termios->c_lflag |= LINUX_NOFLSH; 216 if (bsd_termios->c_lflag & TOSTOP) 217 linux_termios->c_lflag |= LINUX_TOSTOP; 218 if (bsd_termios->c_lflag & ECHOCTL) 219 linux_termios->c_lflag |= LINUX_ECHOCTL; 220 if (bsd_termios->c_lflag & ECHOPRT) 221 linux_termios->c_lflag |= LINUX_ECHOPRT; 222 if (bsd_termios->c_lflag & ECHOKE) 223 linux_termios->c_lflag |= LINUX_ECHOKE; 224 if (bsd_termios->c_lflag & FLUSHO) 225 linux_termios->c_lflag |= LINUX_FLUSHO; 226 if (bsd_termios->c_lflag & PENDIN) 227 linux_termios->c_lflag |= LINUX_PENDIN; 228 if (bsd_termios->c_lflag & IEXTEN) 229 linux_termios->c_lflag |= LINUX_IEXTEN; 230 231 for (i=0; i<LINUX_NCCS; i++) 232 linux_termios->c_cc[i] = LINUX_POSIX_VDISABLE; 233 linux_termios->c_cc[LINUX_VINTR] = bsd_termios->c_cc[VINTR]; 234 linux_termios->c_cc[LINUX_VQUIT] = bsd_termios->c_cc[VQUIT]; 235 linux_termios->c_cc[LINUX_VERASE] = bsd_termios->c_cc[VERASE]; 236 linux_termios->c_cc[LINUX_VKILL] = bsd_termios->c_cc[VKILL]; 237 linux_termios->c_cc[LINUX_VEOF] = bsd_termios->c_cc[VEOF]; 238 linux_termios->c_cc[LINUX_VEOL] = bsd_termios->c_cc[VEOL]; 239 linux_termios->c_cc[LINUX_VMIN] = bsd_termios->c_cc[VMIN]; 240 linux_termios->c_cc[LINUX_VTIME] = bsd_termios->c_cc[VTIME]; 241 linux_termios->c_cc[LINUX_VEOL2] = bsd_termios->c_cc[VEOL2]; 242 linux_termios->c_cc[LINUX_VSUSP] = bsd_termios->c_cc[VSUSP]; 243 linux_termios->c_cc[LINUX_VSTART] = bsd_termios->c_cc[VSTART]; 244 linux_termios->c_cc[LINUX_VSTOP] = bsd_termios->c_cc[VSTOP]; 245 linux_termios->c_cc[LINUX_VREPRINT] = bsd_termios->c_cc[VREPRINT]; 246 linux_termios->c_cc[LINUX_VDISCARD] = bsd_termios->c_cc[VDISCARD]; 247 linux_termios->c_cc[LINUX_VWERASE] = bsd_termios->c_cc[VWERASE]; 248 linux_termios->c_cc[LINUX_VLNEXT] = bsd_termios->c_cc[VLNEXT]; 249 250 for (i=0; i<LINUX_NCCS; i++) { 251 if (linux_termios->c_cc[i] == _POSIX_VDISABLE) 252 linux_termios->c_cc[i] = LINUX_POSIX_VDISABLE; 253 } 254 255 linux_termios->c_line = 0; 256 #ifdef DEBUG 257 printf("LINUX: LINUX termios structure (output):\n"); 258 printf("i=%08x o=%08x c=%08x l=%08x line=%d\n", 259 linux_termios->c_iflag, linux_termios->c_oflag, linux_termios->c_cflag, 260 linux_termios->c_lflag, (int)linux_termios->c_line); 261 printf("c_cc "); 262 for (i=0; i<LINUX_NCCS; i++) 263 printf("%02x ", linux_termios->c_cc[i]); 264 printf("\n"); 265 #endif 266 } 267 268 269 static void 270 linux_to_bsd_termios(struct linux_termios *linux_termios, 271 struct termios *bsd_termios) 272 { 273 int i; 274 #ifdef DEBUG 275 printf("LINUX: LINUX termios structure (input):\n"); 276 printf("i=%08x o=%08x c=%08x l=%08x line=%d\n", 277 linux_termios->c_iflag, linux_termios->c_oflag, linux_termios->c_cflag, 278 linux_termios->c_lflag, (int)linux_termios->c_line); 279 printf("c_cc "); 280 for (i=0; i<LINUX_NCCS; i++) 281 printf("%02x ", linux_termios->c_cc[i]); 282 printf("\n"); 283 #endif 284 bsd_termios->c_iflag = 0; 285 if (linux_termios->c_iflag & LINUX_IGNBRK) 286 bsd_termios->c_iflag |= IGNBRK; 287 if (linux_termios->c_iflag & LINUX_BRKINT) 288 bsd_termios->c_iflag |= BRKINT; 289 if (linux_termios->c_iflag & LINUX_IGNPAR) 290 bsd_termios->c_iflag |= IGNPAR; 291 if (linux_termios->c_iflag & LINUX_PARMRK) 292 bsd_termios->c_iflag |= PARMRK; 293 if (linux_termios->c_iflag & LINUX_INPCK) 294 bsd_termios->c_iflag |= INPCK; 295 if (linux_termios->c_iflag & LINUX_ISTRIP) 296 bsd_termios->c_iflag |= ISTRIP; 297 if (linux_termios->c_iflag & LINUX_INLCR) 298 bsd_termios->c_iflag |= INLCR; 299 if (linux_termios->c_iflag & LINUX_IGNCR) 300 bsd_termios->c_iflag |= IGNCR; 301 if (linux_termios->c_iflag & LINUX_ICRNL) 302 bsd_termios->c_iflag |= ICRNL; 303 if (linux_termios->c_iflag & LINUX_IXON) 304 bsd_termios->c_iflag |= IXON; 305 if (linux_termios->c_iflag & LINUX_IXANY) 306 bsd_termios->c_iflag |= IXANY; 307 if (linux_termios->c_iflag & LINUX_IXOFF) 308 bsd_termios->c_iflag |= IXOFF; 309 if (linux_termios->c_iflag & LINUX_IMAXBEL) 310 bsd_termios->c_iflag |= IMAXBEL; 311 312 bsd_termios->c_oflag = 0; 313 if (linux_termios->c_oflag & LINUX_OPOST) 314 bsd_termios->c_oflag |= OPOST; 315 if (linux_termios->c_oflag & LINUX_ONLCR) 316 bsd_termios->c_oflag |= ONLCR; 317 if (linux_termios->c_oflag & LINUX_XTABS) 318 bsd_termios->c_oflag |= OXTABS; 319 320 bsd_termios->c_cflag = (linux_termios->c_cflag & LINUX_CSIZE) << 4; 321 if (linux_termios->c_cflag & LINUX_CSTOPB) 322 bsd_termios->c_cflag |= CSTOPB; 323 if (linux_termios->c_cflag & LINUX_CREAD) 324 bsd_termios->c_cflag |= CREAD; 325 if (linux_termios->c_cflag & LINUX_PARENB) 326 bsd_termios->c_cflag |= PARENB; 327 if (linux_termios->c_cflag & LINUX_PARODD) 328 bsd_termios->c_cflag |= PARODD; 329 if (linux_termios->c_cflag & LINUX_HUPCL) 330 bsd_termios->c_cflag |= HUPCL; 331 if (linux_termios->c_cflag & LINUX_CLOCAL) 332 bsd_termios->c_cflag |= CLOCAL; 333 if (linux_termios->c_cflag & LINUX_CRTSCTS) 334 bsd_termios->c_cflag |= CRTSCTS; 335 336 bsd_termios->c_lflag = 0; 337 if (linux_termios->c_lflag & LINUX_ISIG) 338 bsd_termios->c_lflag |= ISIG; 339 if (linux_termios->c_lflag & LINUX_ICANON) 340 bsd_termios->c_lflag |= ICANON; 341 if (linux_termios->c_lflag & LINUX_ECHO) 342 bsd_termios->c_lflag |= ECHO; 343 if (linux_termios->c_lflag & LINUX_ECHOE) 344 bsd_termios->c_lflag |= ECHOE; 345 if (linux_termios->c_lflag & LINUX_ECHOK) 346 bsd_termios->c_lflag |= ECHOK; 347 if (linux_termios->c_lflag & LINUX_ECHONL) 348 bsd_termios->c_lflag |= ECHONL; 349 if (linux_termios->c_lflag & LINUX_NOFLSH) 350 bsd_termios->c_lflag |= NOFLSH; 351 if (linux_termios->c_lflag & LINUX_TOSTOP) 352 bsd_termios->c_lflag |= TOSTOP; 353 if (linux_termios->c_lflag & LINUX_ECHOCTL) 354 bsd_termios->c_lflag |= ECHOCTL; 355 if (linux_termios->c_lflag & LINUX_ECHOPRT) 356 bsd_termios->c_lflag |= ECHOPRT; 357 if (linux_termios->c_lflag & LINUX_ECHOKE) 358 bsd_termios->c_lflag |= ECHOKE; 359 if (linux_termios->c_lflag & LINUX_FLUSHO) 360 bsd_termios->c_lflag |= FLUSHO; 361 if (linux_termios->c_lflag & LINUX_PENDIN) 362 bsd_termios->c_lflag |= PENDIN; 363 if (linux_termios->c_lflag & LINUX_IEXTEN) 364 bsd_termios->c_lflag |= IEXTEN; 365 366 for (i=0; i<NCCS; i++) 367 bsd_termios->c_cc[i] = _POSIX_VDISABLE; 368 bsd_termios->c_cc[VINTR] = linux_termios->c_cc[LINUX_VINTR]; 369 bsd_termios->c_cc[VQUIT] = linux_termios->c_cc[LINUX_VQUIT]; 370 bsd_termios->c_cc[VERASE] = linux_termios->c_cc[LINUX_VERASE]; 371 bsd_termios->c_cc[VKILL] = linux_termios->c_cc[LINUX_VKILL]; 372 bsd_termios->c_cc[VEOF] = linux_termios->c_cc[LINUX_VEOF]; 373 bsd_termios->c_cc[VEOL] = linux_termios->c_cc[LINUX_VEOL]; 374 bsd_termios->c_cc[VMIN] = linux_termios->c_cc[LINUX_VMIN]; 375 bsd_termios->c_cc[VTIME] = linux_termios->c_cc[LINUX_VTIME]; 376 bsd_termios->c_cc[VEOL2] = linux_termios->c_cc[LINUX_VEOL2]; 377 bsd_termios->c_cc[VSUSP] = linux_termios->c_cc[LINUX_VSUSP]; 378 bsd_termios->c_cc[VSTART] = linux_termios->c_cc[LINUX_VSTART]; 379 bsd_termios->c_cc[VSTOP] = linux_termios->c_cc[LINUX_VSTOP]; 380 bsd_termios->c_cc[VREPRINT] = linux_termios->c_cc[LINUX_VREPRINT]; 381 bsd_termios->c_cc[VDISCARD] = linux_termios->c_cc[LINUX_VDISCARD]; 382 bsd_termios->c_cc[VWERASE] = linux_termios->c_cc[LINUX_VWERASE]; 383 bsd_termios->c_cc[VLNEXT] = linux_termios->c_cc[LINUX_VLNEXT]; 384 385 for (i=0; i<NCCS; i++) { 386 if (bsd_termios->c_cc[i] == LINUX_POSIX_VDISABLE) 387 bsd_termios->c_cc[i] = _POSIX_VDISABLE; 388 } 389 390 bsd_termios->c_ispeed = bsd_termios->c_ospeed = 391 linux_to_bsd_speed(linux_termios->c_cflag & LINUX_CBAUD, sptab); 392 #ifdef DEBUG 393 printf("LINUX: BSD termios structure (output):\n"); 394 printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n", 395 bsd_termios->c_iflag, bsd_termios->c_oflag, 396 bsd_termios->c_cflag, bsd_termios->c_lflag, 397 bsd_termios->c_ispeed, bsd_termios->c_ospeed); 398 printf("c_cc "); 399 for (i=0; i<NCCS; i++) 400 printf("%02x ", bsd_termios->c_cc[i]); 401 printf("\n"); 402 #endif 403 } 404 405 406 static void 407 bsd_to_linux_termio(struct termios *bsd_termios, 408 struct linux_termio *linux_termio) 409 { 410 struct linux_termios tmios; 411 412 bsd_to_linux_termios(bsd_termios, &tmios); 413 linux_termio->c_iflag = tmios.c_iflag; 414 linux_termio->c_oflag = tmios.c_oflag; 415 linux_termio->c_cflag = tmios.c_cflag; 416 linux_termio->c_lflag = tmios.c_lflag; 417 linux_termio->c_line = tmios.c_line; 418 memcpy(linux_termio->c_cc, tmios.c_cc, LINUX_NCC); 419 } 420 421 static void 422 linux_to_bsd_termio(struct linux_termio *linux_termio, 423 struct termios *bsd_termios) 424 { 425 struct linux_termios tmios; 426 int i; 427 428 tmios.c_iflag = linux_termio->c_iflag; 429 tmios.c_oflag = linux_termio->c_oflag; 430 tmios.c_cflag = linux_termio->c_cflag; 431 tmios.c_lflag = linux_termio->c_lflag; 432 433 for (i=LINUX_NCC; i<LINUX_NCCS; i++) 434 tmios.c_cc[i] = LINUX_POSIX_VDISABLE; 435 memcpy(tmios.c_cc, linux_termio->c_cc, LINUX_NCC); 436 437 linux_to_bsd_termios(&tmios, bsd_termios); 438 } 439 440 struct linux_cdrom_msf 441 { 442 u_char cdmsf_min0; 443 u_char cdmsf_sec0; 444 u_char cdmsf_frame0; 445 u_char cdmsf_min1; 446 u_char cdmsf_sec1; 447 u_char cdmsf_frame1; 448 }; 449 450 struct linux_cdrom_tochdr 451 { 452 u_char cdth_trk0; 453 u_char cdth_trk1; 454 }; 455 456 union linux_cdrom_addr 457 { 458 struct { 459 u_char minute; 460 u_char second; 461 u_char frame; 462 } msf; 463 int lba; 464 }; 465 466 struct linux_cdrom_tocentry 467 { 468 u_char cdte_track; 469 u_char cdte_adr:4; 470 u_char cdte_ctrl:4; 471 u_char cdte_format; 472 union linux_cdrom_addr cdte_addr; 473 u_char cdte_datamode; 474 }; 475 476 struct linux_cdrom_subchnl 477 { 478 u_char cdsc_format; 479 u_char cdsc_audiostatus; 480 u_char cdsc_adr:4; 481 u_char cdsc_ctrl:4; 482 u_char cdsc_trk; 483 u_char cdsc_ind; 484 union linux_cdrom_addr cdsc_absaddr; 485 union linux_cdrom_addr cdsc_reladdr; 486 }; 487 488 #if 0 489 static void 490 linux_to_bsd_msf_lba(u_char address_format, 491 union linux_cdrom_addr *lp, union msf_lba *bp) 492 { 493 if (address_format == CD_LBA_FORMAT) 494 bp->lba = lp->lba; 495 else { 496 bp->msf.minute = lp->msf.minute; 497 bp->msf.second = lp->msf.second; 498 bp->msf.frame = lp->msf.frame; 499 } 500 } 501 #endif 502 503 static void 504 bsd_to_linux_msf_lba(u_char address_format, 505 union msf_lba *bp, union linux_cdrom_addr *lp) 506 { 507 if (address_format == CD_LBA_FORMAT) 508 lp->lba = bp->lba; 509 else { 510 lp->msf.minute = bp->msf.minute; 511 lp->msf.second = bp->msf.second; 512 lp->msf.frame = bp->msf.frame; 513 } 514 } 515 516 static void 517 set_linux_cdrom_addr(union linux_cdrom_addr *addr, int format, int lba) 518 { 519 if (format == LINUX_CDROM_MSF) { 520 addr->msf.frame = lba % 75; 521 lba /= 75; 522 lba += 2; 523 addr->msf.second = lba % 60; 524 addr->msf.minute = lba / 60; 525 } 526 else 527 addr->lba = lba; 528 } 529 530 static unsigned dirbits[4] = { IOC_VOID, IOC_IN, IOC_OUT, IOC_INOUT }; 531 532 #define SETDIR(c) (((c) & ~IOC_DIRMASK) | dirbits[args->cmd >> 30]) 533 534 int 535 linux_ioctl(struct proc *p, struct linux_ioctl_args *args) 536 { 537 struct termios bsd_termios; 538 struct linux_termios linux_termios; 539 struct linux_termio linux_termio; 540 struct filedesc *fdp = p->p_fd; 541 struct file *fp; 542 int bsd_line, linux_line; 543 int error; 544 545 #ifdef DEBUG 546 printf("Linux-emul(%ld): ioctl(%d, %04lx, *)\n", 547 (long)p->p_pid, args->fd, args->cmd); 548 #endif 549 if ((unsigned)args->fd >= fdp->fd_nfiles 550 || (fp = fdp->fd_ofiles[args->fd]) == 0) 551 return EBADF; 552 553 if (!fp || (fp->f_flag & (FREAD | FWRITE)) == 0) { 554 return EBADF; 555 } 556 557 switch (args->cmd & 0xffff) { 558 559 case LINUX_TCGETA: 560 if ((error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bsd_termios, p)) != 0) 561 return error; 562 bsd_to_linux_termio(&bsd_termios, &linux_termio); 563 return copyout((caddr_t)&linux_termio, (caddr_t)args->arg, 564 sizeof(linux_termio)); 565 566 case LINUX_TCSETA: 567 error = copyin((caddr_t)args->arg, &linux_termio, sizeof(linux_termio)); 568 if (error) 569 return error; 570 linux_to_bsd_termio(&linux_termio, &bsd_termios); 571 return fo_ioctl(fp, TIOCSETA, (caddr_t)&bsd_termios, p); 572 573 case LINUX_TCSETAW: 574 error = copyin((caddr_t)args->arg, &linux_termio, sizeof(linux_termio)); 575 if (error) 576 return error; 577 linux_to_bsd_termio(&linux_termio, &bsd_termios); 578 return fo_ioctl(fp, TIOCSETAW, (caddr_t)&bsd_termios, p); 579 580 case LINUX_TCSETAF: 581 error = copyin((caddr_t)args->arg, &linux_termio, sizeof(linux_termio)); 582 if (error) 583 return error; 584 linux_to_bsd_termio(&linux_termio, &bsd_termios); 585 return fo_ioctl(fp, TIOCSETAF, (caddr_t)&bsd_termios, p); 586 587 case LINUX_TCGETS: 588 if ((error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bsd_termios, p)) != 0) 589 return error; 590 bsd_to_linux_termios(&bsd_termios, &linux_termios); 591 return copyout((caddr_t)&linux_termios, (caddr_t)args->arg, 592 sizeof(linux_termios)); 593 594 case LINUX_TCSETS: 595 error = copyin((caddr_t)args->arg, &linux_termios, 596 sizeof(linux_termios)); 597 if (error) 598 return error; 599 linux_to_bsd_termios(&linux_termios, &bsd_termios); 600 return fo_ioctl(fp, TIOCSETA, (caddr_t)&bsd_termios, p); 601 602 case LINUX_TCSETSW: 603 error = copyin((caddr_t)args->arg, &linux_termios, 604 sizeof(linux_termios)); 605 if (error) 606 return error; 607 linux_to_bsd_termios(&linux_termios, &bsd_termios); 608 return fo_ioctl(fp, TIOCSETAW, (caddr_t)&bsd_termios, p); 609 610 case LINUX_TCSETSF: 611 error = copyin((caddr_t)args->arg, &linux_termios, 612 sizeof(linux_termios)); 613 if (error) 614 return error; 615 linux_to_bsd_termios(&linux_termios, &bsd_termios); 616 return fo_ioctl(fp, TIOCSETAF, (caddr_t)&bsd_termios, p); 617 618 case LINUX_TIOCGPGRP: 619 args->cmd = TIOCGPGRP; 620 return ioctl(p, (struct ioctl_args *)args); 621 622 case LINUX_TIOCSPGRP: 623 args->cmd = TIOCSPGRP; 624 return ioctl(p, (struct ioctl_args *)args); 625 626 case LINUX_TIOCGWINSZ: 627 args->cmd = TIOCGWINSZ; 628 return ioctl(p, (struct ioctl_args *)args); 629 630 case LINUX_TIOCSWINSZ: 631 args->cmd = TIOCSWINSZ; 632 return ioctl(p, (struct ioctl_args *)args); 633 634 case LINUX_TIOCMGET: 635 args->cmd = TIOCMGET; 636 return ioctl(p, (struct ioctl_args *)args); 637 638 case LINUX_TIOCMBIS: 639 args->cmd = TIOCMBIS; 640 return ioctl(p, (struct ioctl_args *)args); 641 642 case LINUX_TIOCMBIC: 643 args->cmd = TIOCMBIC; 644 return ioctl(p, (struct ioctl_args *)args); 645 646 case LINUX_TIOCMSET: 647 args->cmd = TIOCMSET; 648 return ioctl(p, (struct ioctl_args *)args); 649 650 case LINUX_FIONREAD: 651 args->cmd = FIONREAD; 652 return ioctl(p, (struct ioctl_args *)args); 653 654 case LINUX_FIONBIO: 655 args->cmd = FIONBIO; 656 return ioctl(p, (struct ioctl_args *)args); 657 658 case LINUX_FIOASYNC: 659 args->cmd = FIOASYNC; 660 return ioctl(p, (struct ioctl_args *)args); 661 662 case LINUX_FIONCLEX: 663 args->cmd = FIONCLEX; 664 return ioctl(p, (struct ioctl_args *)args); 665 666 case LINUX_FIOCLEX: 667 args->cmd = FIOCLEX; 668 return ioctl(p, (struct ioctl_args *)args); 669 670 case LINUX_TIOCEXCL: 671 args->cmd = TIOCEXCL; 672 return ioctl(p, (struct ioctl_args *)args); 673 674 case LINUX_TIOCNXCL: 675 args->cmd = TIOCNXCL; 676 return ioctl(p, (struct ioctl_args *)args); 677 678 case LINUX_TIOCCONS: 679 args->cmd = TIOCCONS; 680 return ioctl(p, (struct ioctl_args *)args); 681 682 case LINUX_TIOCNOTTY: 683 args->cmd = TIOCNOTTY; 684 return ioctl(p, (struct ioctl_args *)args); 685 686 case LINUX_SIOCGIFCONF: 687 args->cmd = OSIOCGIFCONF; 688 return ioctl(p, (struct ioctl_args *)args); 689 690 case LINUX_SIOCGIFFLAGS: 691 args->cmd = SIOCGIFFLAGS; 692 return ioctl(p, (struct ioctl_args *)args); 693 694 case LINUX_SIOCGIFADDR: 695 args->cmd = OSIOCGIFADDR; 696 return ioctl(p, (struct ioctl_args *)args); 697 698 case LINUX_SIOCGIFDSTADDR: 699 args->cmd = OSIOCGIFDSTADDR; 700 return ioctl(p, (struct ioctl_args *)args); 701 702 case LINUX_SIOCGIFBRDADDR: 703 args->cmd = OSIOCGIFBRDADDR; 704 return ioctl(p, (struct ioctl_args *)args); 705 706 case LINUX_SIOCGIFNETMASK: 707 args->cmd = OSIOCGIFNETMASK; 708 return ioctl(p, (struct ioctl_args *)args); 709 710 /* get hardware address */ 711 case LINUX_SIOCGIFHWADDR: 712 { 713 int ifn; 714 struct ifnet *ifp; 715 struct ifaddr *ifa; 716 struct sockaddr_dl *sdl; 717 struct linux_ifreq *ifr = (struct linux_ifreq *)args->arg; 718 719 /* 720 * Note that we don't actually respect the name in the ifreq structure, as 721 * Linux interface names are all different 722 */ 723 724 for (ifn = 0; ifn < if_index; ifn++) { 725 726 ifp = ifnet_addrs[ifn]->ifa_ifp; /* pointer to interface */ 727 if (ifp->if_type == IFT_ETHER) { /* looks good */ 728 /* walk the address list */ 729 for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa; ifa = TAILQ_NEXT(ifa, ifa_link)) { 730 if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && /* we have an address structure */ 731 (sdl->sdl_family == AF_LINK) && /* it's a link address */ 732 (sdl->sdl_type == IFT_ETHER)) { /* for an ethernet link */ 733 734 return(copyout(LLADDR(sdl), (caddr_t)&ifr->ifr_hwaddr.sa_data, LINUX_IFHWADDRLEN)); 735 } 736 } 737 } 738 } 739 return(ENOENT); /* ??? */ 740 } 741 742 case LINUX_SIOCADDMULTI: 743 args->cmd = SIOCADDMULTI; 744 return ioctl(p, (struct ioctl_args *)args); 745 746 case LINUX_SIOCDELMULTI: 747 args->cmd = SIOCDELMULTI; 748 return ioctl(p, (struct ioctl_args *)args); 749 750 case LINUX_FIOSETOWN: 751 args->cmd = FIOSETOWN; 752 return ioctl(p, (struct ioctl_args *)args); 753 754 case LINUX_SIOCSPGRP: 755 args->cmd = SIOCSPGRP; 756 return ioctl(p, (struct ioctl_args *)args); 757 758 case LINUX_FIOGETOWN: 759 args->cmd = FIOGETOWN; 760 return ioctl(p, (struct ioctl_args *)args); 761 762 case LINUX_SIOCGPGRP: 763 args->cmd = SIOCGPGRP; 764 return ioctl(p, (struct ioctl_args *)args); 765 766 case LINUX_SIOCATMARK: 767 args->cmd = SIOCATMARK; 768 return ioctl(p, (struct ioctl_args *)args); 769 770 case LINUX_TIOCSETD: 771 switch (args->arg) { 772 case LINUX_N_TTY: 773 bsd_line = TTYDISC; 774 return fo_ioctl(fp, TIOCSETD, (caddr_t)&bsd_line, p); 775 case LINUX_N_SLIP: 776 bsd_line = SLIPDISC; 777 return fo_ioctl(fp, TIOCSETD, (caddr_t)&bsd_line, p); 778 case LINUX_N_PPP: 779 bsd_line = PPPDISC; 780 return fo_ioctl(fp, TIOCSETD, (caddr_t)&bsd_line, p); 781 default: 782 return EINVAL; 783 } 784 785 case LINUX_TIOCGETD: 786 bsd_line = TTYDISC; 787 error = fo_ioctl(fp, TIOCGETD, (caddr_t)&bsd_line, p); 788 if (error) 789 return error; 790 switch (bsd_line) { 791 case TTYDISC: 792 linux_line = LINUX_N_TTY; 793 break; 794 case SLIPDISC: 795 linux_line = LINUX_N_SLIP; 796 break; 797 case PPPDISC: 798 linux_line = LINUX_N_PPP; 799 break; 800 default: 801 return EINVAL; 802 } 803 return copyout(&linux_line, (caddr_t)args->arg, 804 sizeof(int)); 805 806 case LINUX_SNDCTL_SEQ_RESET: 807 args->cmd = SNDCTL_SEQ_RESET; 808 return ioctl(p, (struct ioctl_args *)args); 809 810 case LINUX_SNDCTL_SEQ_SYNC: 811 args->cmd = SNDCTL_SEQ_SYNC; 812 return ioctl(p, (struct ioctl_args *)args); 813 814 case LINUX_SNDCTL_SYNTH_INFO: 815 args->cmd = SNDCTL_SYNTH_INFO; 816 return ioctl(p, (struct ioctl_args *)args); 817 818 case LINUX_SNDCTL_SEQ_CTRLRATE: 819 args->cmd = SNDCTL_SEQ_CTRLRATE; 820 return ioctl(p, (struct ioctl_args *)args); 821 822 case LINUX_SNDCTL_SEQ_GETOUTCOUNT: 823 args->cmd = SNDCTL_SEQ_GETOUTCOUNT; 824 return ioctl(p, (struct ioctl_args *)args); 825 826 case LINUX_SNDCTL_SEQ_GETINCOUNT: 827 args->cmd = SNDCTL_SEQ_GETINCOUNT; 828 return ioctl(p, (struct ioctl_args *)args); 829 830 case LINUX_SNDCTL_SEQ_PERCMODE: 831 args->cmd = SNDCTL_SEQ_PERCMODE; 832 return ioctl(p, (struct ioctl_args *)args); 833 834 case LINUX_SNDCTL_FM_LOAD_INSTR: 835 args->cmd = SNDCTL_FM_LOAD_INSTR; 836 return ioctl(p, (struct ioctl_args *)args); 837 838 case LINUX_SNDCTL_SEQ_TESTMIDI: 839 args->cmd = SNDCTL_SEQ_TESTMIDI; 840 return ioctl(p, (struct ioctl_args *)args); 841 842 case LINUX_SNDCTL_SEQ_RESETSAMPLES: 843 args->cmd = SNDCTL_SEQ_RESETSAMPLES; 844 return ioctl(p, (struct ioctl_args *)args); 845 846 case LINUX_SNDCTL_SEQ_NRSYNTHS: 847 args->cmd = SNDCTL_SEQ_NRSYNTHS; 848 return ioctl(p, (struct ioctl_args *)args); 849 850 case LINUX_SNDCTL_SEQ_NRMIDIS: 851 args->cmd = SNDCTL_SEQ_NRMIDIS; 852 return ioctl(p, (struct ioctl_args *)args); 853 854 case LINUX_SNDCTL_MIDI_INFO: 855 args->cmd = SNDCTL_MIDI_INFO; 856 return ioctl(p, (struct ioctl_args *)args); 857 858 case LINUX_SNDCTL_SEQ_TRESHOLD: 859 args->cmd = SNDCTL_SEQ_TRESHOLD; 860 return ioctl(p, (struct ioctl_args *)args); 861 862 case LINUX_SNDCTL_SYNTH_MEMAVL: 863 args->cmd = SNDCTL_SYNTH_MEMAVL; 864 return ioctl(p, (struct ioctl_args *)args); 865 866 case LINUX_SNDCTL_DSP_GETOPTR : 867 args->cmd = SNDCTL_DSP_GETOPTR; 868 return ioctl(p, (struct ioctl_args *)args); 869 870 case LINUX_SNDCTL_DSP_GETIPTR : 871 args->cmd = SNDCTL_DSP_GETIPTR; 872 return ioctl(p, (struct ioctl_args *)args); 873 874 case LINUX_SNDCTL_DSP_SETTRIGGER: 875 args->cmd = SNDCTL_DSP_SETTRIGGER; 876 return ioctl(p, (struct ioctl_args *)args); 877 878 case LINUX_SNDCTL_DSP_GETCAPS: 879 args->cmd = SNDCTL_DSP_GETCAPS; 880 return ioctl(p, (struct ioctl_args *)args); 881 882 case LINUX_SNDCTL_DSP_RESET: 883 args->cmd = SNDCTL_DSP_RESET; 884 return ioctl(p, (struct ioctl_args *)args); 885 886 case LINUX_SNDCTL_DSP_SYNC: 887 args->cmd = SNDCTL_DSP_SYNC; 888 return ioctl(p, (struct ioctl_args *)args); 889 890 case LINUX_SNDCTL_DSP_SPEED: 891 args->cmd = SNDCTL_DSP_SPEED; 892 return ioctl(p, (struct ioctl_args *)args); 893 894 case LINUX_SNDCTL_DSP_STEREO: 895 args->cmd = SNDCTL_DSP_STEREO; 896 return ioctl(p, (struct ioctl_args *)args); 897 898 case LINUX_SNDCTL_DSP_GETBLKSIZE: 899 /* LINUX_SNDCTL_DSP_SETBLKSIZE */ 900 args->cmd = SNDCTL_DSP_GETBLKSIZE; 901 return ioctl(p, (struct ioctl_args *)args); 902 903 case LINUX_SNDCTL_DSP_SETFMT: 904 args->cmd = SNDCTL_DSP_SETFMT; 905 return ioctl(p, (struct ioctl_args *)args); 906 907 case LINUX_SOUND_PCM_WRITE_CHANNELS: 908 args->cmd = SOUND_PCM_WRITE_CHANNELS; 909 return ioctl(p, (struct ioctl_args *)args); 910 911 case LINUX_SOUND_PCM_WRITE_FILTER: 912 args->cmd = SOUND_PCM_WRITE_FILTER; 913 return ioctl(p, (struct ioctl_args *)args); 914 915 case LINUX_SNDCTL_DSP_POST: 916 args->cmd = SNDCTL_DSP_POST; 917 return ioctl(p, (struct ioctl_args *)args); 918 919 case LINUX_SNDCTL_DSP_SUBDIVIDE: 920 args->cmd = SNDCTL_DSP_SUBDIVIDE; 921 return ioctl(p, (struct ioctl_args *)args); 922 923 case LINUX_SNDCTL_DSP_SETFRAGMENT: 924 args->cmd = SNDCTL_DSP_SETFRAGMENT; 925 return ioctl(p, (struct ioctl_args *)args); 926 927 case LINUX_SNDCTL_DSP_GETFMTS: 928 args->cmd = SNDCTL_DSP_GETFMTS; 929 return ioctl(p, (struct ioctl_args *)args); 930 931 case LINUX_SNDCTL_DSP_GETOSPACE: 932 args->cmd = SNDCTL_DSP_GETOSPACE; 933 return ioctl(p, (struct ioctl_args *)args); 934 935 case LINUX_SNDCTL_DSP_GETISPACE: 936 args->cmd = SNDCTL_DSP_GETISPACE; 937 return ioctl(p, (struct ioctl_args *)args); 938 939 case LINUX_SNDCTL_DSP_NONBLOCK: 940 args->cmd = SNDCTL_DSP_NONBLOCK; 941 return ioctl(p, (struct ioctl_args *)args); 942 943 case LINUX_SOUND_MIXER_WRITE_VOLUME: 944 args->cmd = SETDIR(SOUND_MIXER_WRITE_VOLUME); 945 return ioctl(p, (struct ioctl_args *)args); 946 947 case LINUX_SOUND_MIXER_WRITE_BASS: 948 args->cmd = SETDIR(SOUND_MIXER_WRITE_BASS); 949 return ioctl(p, (struct ioctl_args *)args); 950 951 case LINUX_SOUND_MIXER_WRITE_TREBLE: 952 args->cmd = SETDIR(SOUND_MIXER_WRITE_TREBLE); 953 return ioctl(p, (struct ioctl_args *)args); 954 955 case LINUX_SOUND_MIXER_WRITE_SYNTH: 956 args->cmd = SETDIR(SOUND_MIXER_WRITE_SYNTH); 957 return ioctl(p, (struct ioctl_args *)args); 958 959 case LINUX_SOUND_MIXER_WRITE_PCM: 960 args->cmd = SETDIR(SOUND_MIXER_WRITE_PCM); 961 return ioctl(p, (struct ioctl_args *)args); 962 963 case LINUX_SOUND_MIXER_WRITE_SPEAKER: 964 args->cmd = SETDIR(SOUND_MIXER_WRITE_SPEAKER); 965 return ioctl(p, (struct ioctl_args *)args); 966 967 case LINUX_SOUND_MIXER_WRITE_LINE: 968 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE); 969 return ioctl(p, (struct ioctl_args *)args); 970 971 case LINUX_SOUND_MIXER_WRITE_MIC: 972 args->cmd = SETDIR(SOUND_MIXER_WRITE_MIC); 973 return ioctl(p, (struct ioctl_args *)args); 974 975 case LINUX_SOUND_MIXER_WRITE_CD: 976 args->cmd = SETDIR(SOUND_MIXER_WRITE_CD); 977 return ioctl(p, (struct ioctl_args *)args); 978 979 case LINUX_SOUND_MIXER_WRITE_IMIX: 980 args->cmd = SETDIR(SOUND_MIXER_WRITE_IMIX); 981 return ioctl(p, (struct ioctl_args *)args); 982 983 case LINUX_SOUND_MIXER_WRITE_ALTPCM: 984 args->cmd = SETDIR(SOUND_MIXER_WRITE_ALTPCM); 985 return ioctl(p, (struct ioctl_args *)args); 986 987 case LINUX_SOUND_MIXER_WRITE_RECLEV: 988 args->cmd = SETDIR(SOUND_MIXER_WRITE_RECLEV); 989 return ioctl(p, (struct ioctl_args *)args); 990 991 case LINUX_SOUND_MIXER_WRITE_IGAIN: 992 args->cmd = SETDIR(SOUND_MIXER_WRITE_IGAIN); 993 return ioctl(p, (struct ioctl_args *)args); 994 995 case LINUX_SOUND_MIXER_WRITE_OGAIN: 996 args->cmd = SETDIR(SOUND_MIXER_WRITE_OGAIN); 997 return ioctl(p, (struct ioctl_args *)args); 998 999 case LINUX_SOUND_MIXER_WRITE_LINE1: 1000 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE1); 1001 return ioctl(p, (struct ioctl_args *)args); 1002 1003 case LINUX_SOUND_MIXER_WRITE_LINE2: 1004 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE2); 1005 return ioctl(p, (struct ioctl_args *)args); 1006 1007 case LINUX_SOUND_MIXER_WRITE_LINE3: 1008 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE3); 1009 return ioctl(p, (struct ioctl_args *)args); 1010 1011 case LINUX_SOUND_MIXER_READ_DEVMASK: 1012 args->cmd = SOUND_MIXER_READ_DEVMASK; 1013 return ioctl(p, (struct ioctl_args *)args); 1014 1015 case LINUX_TIOCGSERIAL: { 1016 struct linux_serial_struct lss; 1017 1018 lss.type = LINUX_PORT_16550A; 1019 lss.flags = 0; 1020 lss.close_delay = 0; 1021 return copyout((caddr_t)&lss, (caddr_t)args->arg, sizeof(lss)); 1022 } 1023 1024 case LINUX_TIOCSSERIAL: { 1025 struct linux_serial_struct lss; 1026 1027 error = copyin((caddr_t)args->arg, (caddr_t)&lss, sizeof(lss)); 1028 if (error) 1029 return error; 1030 /* 1031 * XXX - It really helps to have an implementation that does nothing. 1032 * NOT! 1033 */ 1034 return 0; 1035 } 1036 1037 case LINUX_TCXONC: 1038 switch (args->arg) { 1039 case LINUX_TCOOFF: 1040 args->cmd = TIOCSTOP; 1041 break; 1042 case LINUX_TCOON: 1043 args->cmd = TIOCSTART; 1044 break; 1045 case LINUX_TCIOFF: 1046 case LINUX_TCION: { 1047 u_char c; 1048 struct write_args wr; 1049 error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bsd_termios, p); 1050 if (error != 0) 1051 return error; 1052 c = bsd_termios.c_cc[args->arg == LINUX_TCIOFF ? VSTOP : VSTART]; 1053 if (c != _POSIX_VDISABLE) { 1054 wr.fd = args->fd; 1055 wr.buf = &c; 1056 wr.nbyte = sizeof(c); 1057 return write(p, &wr); 1058 } 1059 else 1060 return (0); 1061 } 1062 default: 1063 return EINVAL; 1064 } 1065 args->arg = 0; 1066 return ioctl(p, (struct ioctl_args *)args); 1067 1068 case LINUX_TCFLSH: 1069 args->cmd = TIOCFLUSH; 1070 switch (args->arg) { 1071 case LINUX_TCIFLUSH: 1072 args->arg = FREAD; 1073 break; 1074 case LINUX_TCOFLUSH: 1075 args->arg = FWRITE; 1076 break; 1077 case LINUX_TCIOFLUSH: 1078 args->arg = FREAD | FWRITE; 1079 break; 1080 default: 1081 return EINVAL; 1082 } 1083 return ioctl(p, (struct ioctl_args *)args); 1084 1085 case LINUX_VT_OPENQRY: 1086 1087 args->cmd = VT_OPENQRY; 1088 return ioctl(p, (struct ioctl_args *)args); 1089 1090 case LINUX_VT_GETMODE: 1091 1092 args->cmd = VT_GETMODE; 1093 return ioctl(p, (struct ioctl_args *)args); 1094 1095 case LINUX_VT_SETMODE: 1096 { 1097 struct vt_mode *mode; 1098 args->cmd = VT_SETMODE; 1099 mode = (struct vt_mode *)args->arg; 1100 if (!ISSIGVALID(mode->frsig) && ISSIGVALID(mode->acqsig)) 1101 mode->frsig = mode->acqsig; 1102 return ioctl(p, (struct ioctl_args *)args); 1103 } 1104 1105 case LINUX_VT_GETSTATE: 1106 1107 args->cmd = VT_GETACTIVE; 1108 return ioctl(p, (struct ioctl_args *)args); 1109 1110 case LINUX_VT_RELDISP: 1111 1112 args->cmd = VT_RELDISP; 1113 return ioctl(p, (struct ioctl_args *)args); 1114 1115 case LINUX_VT_ACTIVATE: 1116 1117 args->cmd = VT_ACTIVATE; 1118 return ioctl(p, (struct ioctl_args *)args); 1119 1120 case LINUX_VT_WAITACTIVE: 1121 1122 args->cmd = VT_WAITACTIVE; 1123 return ioctl(p, (struct ioctl_args *)args); 1124 1125 case LINUX_KDGKBMODE: 1126 1127 args->cmd = KDGKBMODE; 1128 return ioctl(p, (struct ioctl_args *)args); 1129 1130 case LINUX_KDSKBMODE: 1131 { 1132 int kbdmode; 1133 switch (args->arg) { 1134 case LINUX_KBD_RAW: 1135 kbdmode = K_RAW; 1136 return fo_ioctl(fp, KDSKBMODE, (caddr_t)&kbdmode, p); 1137 case LINUX_KBD_XLATE: 1138 kbdmode = K_XLATE; 1139 return fo_ioctl(fp, KDSKBMODE , (caddr_t)&kbdmode, p); 1140 case LINUX_KBD_MEDIUMRAW: 1141 kbdmode = K_RAW; 1142 return fo_ioctl(fp, KDSKBMODE , (caddr_t)&kbdmode, p); 1143 default: 1144 return EINVAL; 1145 } 1146 } 1147 1148 case LINUX_KDGETMODE: 1149 args->cmd = KDGETMODE; 1150 return ioctl(p, (struct ioctl_args *)args); 1151 1152 case LINUX_KDSETMODE: 1153 args->cmd = KDSETMODE; 1154 return ioctl(p, (struct ioctl_args *)args); 1155 1156 case LINUX_KDSETLED: 1157 args->cmd = KDSETLED; 1158 return ioctl(p, (struct ioctl_args *)args); 1159 1160 case LINUX_KDGETLED: 1161 args->cmd = KDGETLED; 1162 return ioctl(p, (struct ioctl_args *)args); 1163 1164 case LINUX_KIOCSOUND: 1165 args->cmd = KIOCSOUND; 1166 return ioctl(p, (struct ioctl_args *)args); 1167 1168 case LINUX_KDMKTONE: 1169 args->cmd = KDMKTONE; 1170 return ioctl(p, (struct ioctl_args *)args); 1171 1172 1173 case LINUX_CDROMPAUSE: 1174 args->cmd = CDIOCPAUSE; 1175 return ioctl(p, (struct ioctl_args *)args); 1176 1177 case LINUX_CDROMRESUME: 1178 args->cmd = CDIOCRESUME; 1179 return ioctl(p, (struct ioctl_args *)args); 1180 1181 case LINUX_CDROMPLAYMSF: 1182 args->cmd = CDIOCPLAYMSF; 1183 return ioctl(p, (struct ioctl_args *)args); 1184 1185 case LINUX_CDROMPLAYTRKIND: 1186 args->cmd = CDIOCPLAYTRACKS; 1187 return ioctl(p, (struct ioctl_args *)args); 1188 1189 case LINUX_CDROMSTART: 1190 args->cmd = CDIOCSTART; 1191 return ioctl(p, (struct ioctl_args *)args); 1192 1193 case LINUX_CDROMSTOP: 1194 args->cmd = CDIOCSTOP; 1195 return ioctl(p, (struct ioctl_args *)args); 1196 1197 case LINUX_CDROMEJECT: 1198 args->cmd = CDIOCEJECT; 1199 return ioctl(p, (struct ioctl_args *)args); 1200 1201 case LINUX_CDROMRESET: 1202 args->cmd = CDIOCRESET; 1203 return ioctl(p, (struct ioctl_args *)args); 1204 1205 case LINUX_CDROMREADTOCHDR: { 1206 struct ioc_toc_header th; 1207 struct linux_cdrom_tochdr lth; 1208 error = fo_ioctl(fp, CDIOREADTOCHEADER, (caddr_t)&th, p); 1209 if (!error) { 1210 lth.cdth_trk0 = th.starting_track; 1211 lth.cdth_trk1 = th.ending_track; 1212 copyout((caddr_t)<h, (caddr_t)args->arg, sizeof(lth)); 1213 } 1214 return error; 1215 } 1216 1217 case LINUX_CDROMREADTOCENTRY: { 1218 struct linux_cdrom_tocentry lte, *ltep = 1219 (struct linux_cdrom_tocentry *)args->arg; 1220 struct ioc_read_toc_single_entry irtse; 1221 irtse.address_format = ltep->cdte_format; 1222 irtse.track = ltep->cdte_track; 1223 error = fo_ioctl(fp, CDIOREADTOCENTRY, (caddr_t)&irtse, p); 1224 if (!error) { 1225 lte = *ltep; 1226 lte.cdte_ctrl = irtse.entry.control; 1227 lte.cdte_adr = irtse.entry.addr_type; 1228 bsd_to_linux_msf_lba(irtse.address_format, 1229 &irtse.entry.addr, <e.cdte_addr); 1230 copyout((caddr_t)<e, (caddr_t)args->arg, sizeof(lte)); 1231 } 1232 return error; 1233 } 1234 1235 case LINUX_CDROMSUBCHNL: { 1236 caddr_t sg; 1237 struct linux_cdrom_subchnl sc; 1238 struct ioc_read_subchannel bsdsc; 1239 struct cd_sub_channel_info *bsdinfo; 1240 1241 sg = stackgap_init(); 1242 bsdinfo = (struct cd_sub_channel_info*)stackgap_alloc(&sg, 1243 sizeof(struct cd_sub_channel_info)); 1244 1245 bsdsc.address_format = CD_LBA_FORMAT; 1246 bsdsc.data_format = CD_CURRENT_POSITION; 1247 bsdsc.data_len = sizeof(struct cd_sub_channel_info); 1248 bsdsc.data = bsdinfo; 1249 error = fo_ioctl(fp, CDIOCREADSUBCHANNEL, (caddr_t)&bsdsc, p); 1250 if (error) 1251 return error; 1252 1253 error = copyin((caddr_t)args->arg, (caddr_t)&sc, 1254 sizeof(struct linux_cdrom_subchnl)); 1255 if (error) 1256 return error; 1257 1258 sc.cdsc_audiostatus = bsdinfo->header.audio_status; 1259 sc.cdsc_adr = bsdinfo->what.position.addr_type; 1260 sc.cdsc_ctrl = bsdinfo->what.position.control; 1261 sc.cdsc_trk = bsdinfo->what.position.track_number; 1262 sc.cdsc_ind = bsdinfo->what.position.index_number; 1263 set_linux_cdrom_addr(&sc.cdsc_absaddr, sc.cdsc_format, 1264 bsdinfo->what.position.absaddr.lba); 1265 set_linux_cdrom_addr(&sc.cdsc_reladdr, sc.cdsc_format, 1266 bsdinfo->what.position.reladdr.lba); 1267 error = copyout((caddr_t)&sc, (caddr_t)args->arg, 1268 sizeof(struct linux_cdrom_subchnl)); 1269 return error; 1270 } 1271 1272 case LINUX_OSS_GETVERSION: { 1273 int version; 1274 1275 version = linux_get_oss_version(p); 1276 return copyout((caddr_t)&version, (caddr_t)args->arg, sizeof(int)); 1277 } 1278 1279 } 1280 1281 uprintf("LINUX: 'ioctl' fd=%d, typ=0x%x(%c), num=0x%x not implemented\n", 1282 args->fd, (u_int)((args->cmd & 0xffff00) >> 8), 1283 (int)((args->cmd & 0xffff00) >> 8), (u_int)(args->cmd & 0xff)); 1284 return EINVAL; 1285 } 1286