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_OUT, IOC_IN, 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 (*func)(struct file *fp, u_long com, caddr_t data, struct proc *p); 543 int bsd_line, linux_line; 544 int error; 545 546 #ifdef DEBUG 547 printf("Linux-emul(%ld): ioctl(%d, %04lx, *)\n", 548 (long)p->p_pid, args->fd, args->cmd); 549 #endif 550 if ((unsigned)args->fd >= fdp->fd_nfiles 551 || (fp = fdp->fd_ofiles[args->fd]) == 0) 552 return EBADF; 553 554 if (!fp || (fp->f_flag & (FREAD | FWRITE)) == 0) { 555 return EBADF; 556 } 557 558 func = fp->f_ops->fo_ioctl; 559 switch (args->cmd & 0xffff) { 560 561 case LINUX_TCGETA: 562 if ((error = (*func)(fp, TIOCGETA, (caddr_t)&bsd_termios, p)) != 0) 563 return error; 564 bsd_to_linux_termio(&bsd_termios, &linux_termio); 565 return copyout((caddr_t)&linux_termio, (caddr_t)args->arg, 566 sizeof(linux_termio)); 567 568 case LINUX_TCSETA: 569 error = copyin((caddr_t)args->arg, &linux_termio, sizeof(linux_termio)); 570 if (error) 571 return error; 572 linux_to_bsd_termio(&linux_termio, &bsd_termios); 573 return (*func)(fp, TIOCSETA, (caddr_t)&bsd_termios, p); 574 575 case LINUX_TCSETAW: 576 error = copyin((caddr_t)args->arg, &linux_termio, sizeof(linux_termio)); 577 if (error) 578 return error; 579 linux_to_bsd_termio(&linux_termio, &bsd_termios); 580 return (*func)(fp, TIOCSETAW, (caddr_t)&bsd_termios, p); 581 582 case LINUX_TCSETAF: 583 error = copyin((caddr_t)args->arg, &linux_termio, sizeof(linux_termio)); 584 if (error) 585 return error; 586 linux_to_bsd_termio(&linux_termio, &bsd_termios); 587 return (*func)(fp, TIOCSETAF, (caddr_t)&bsd_termios, p); 588 589 case LINUX_TCGETS: 590 if ((error = (*func)(fp, TIOCGETA, (caddr_t)&bsd_termios, p)) != 0) 591 return error; 592 bsd_to_linux_termios(&bsd_termios, &linux_termios); 593 return copyout((caddr_t)&linux_termios, (caddr_t)args->arg, 594 sizeof(linux_termios)); 595 596 case LINUX_TCSETS: 597 error = copyin((caddr_t)args->arg, &linux_termios, 598 sizeof(linux_termios)); 599 if (error) 600 return error; 601 linux_to_bsd_termios(&linux_termios, &bsd_termios); 602 return (*func)(fp, TIOCSETA, (caddr_t)&bsd_termios, p); 603 604 case LINUX_TCSETSW: 605 error = copyin((caddr_t)args->arg, &linux_termios, 606 sizeof(linux_termios)); 607 if (error) 608 return error; 609 linux_to_bsd_termios(&linux_termios, &bsd_termios); 610 return (*func)(fp, TIOCSETAW, (caddr_t)&bsd_termios, p); 611 612 case LINUX_TCSETSF: 613 error = copyin((caddr_t)args->arg, &linux_termios, 614 sizeof(linux_termios)); 615 if (error) 616 return error; 617 linux_to_bsd_termios(&linux_termios, &bsd_termios); 618 return (*func)(fp, TIOCSETAF, (caddr_t)&bsd_termios, p); 619 620 case LINUX_TIOCGPGRP: 621 args->cmd = TIOCGPGRP; 622 return ioctl(p, (struct ioctl_args *)args); 623 624 case LINUX_TIOCSPGRP: 625 args->cmd = TIOCSPGRP; 626 return ioctl(p, (struct ioctl_args *)args); 627 628 case LINUX_TIOCGWINSZ: 629 args->cmd = TIOCGWINSZ; 630 return ioctl(p, (struct ioctl_args *)args); 631 632 case LINUX_TIOCSWINSZ: 633 args->cmd = TIOCSWINSZ; 634 return ioctl(p, (struct ioctl_args *)args); 635 636 case LINUX_TIOCMGET: 637 args->cmd = TIOCMGET; 638 return ioctl(p, (struct ioctl_args *)args); 639 640 case LINUX_TIOCMBIS: 641 args->cmd = TIOCMBIS; 642 return ioctl(p, (struct ioctl_args *)args); 643 644 case LINUX_TIOCMBIC: 645 args->cmd = TIOCMBIC; 646 return ioctl(p, (struct ioctl_args *)args); 647 648 case LINUX_TIOCMSET: 649 args->cmd = TIOCMSET; 650 return ioctl(p, (struct ioctl_args *)args); 651 652 case LINUX_FIONREAD: 653 args->cmd = FIONREAD; 654 return ioctl(p, (struct ioctl_args *)args); 655 656 case LINUX_FIONBIO: 657 args->cmd = FIONBIO; 658 return ioctl(p, (struct ioctl_args *)args); 659 660 case LINUX_FIOASYNC: 661 args->cmd = FIOASYNC; 662 return ioctl(p, (struct ioctl_args *)args); 663 664 case LINUX_FIONCLEX: 665 args->cmd = FIONCLEX; 666 return ioctl(p, (struct ioctl_args *)args); 667 668 case LINUX_FIOCLEX: 669 args->cmd = FIOCLEX; 670 return ioctl(p, (struct ioctl_args *)args); 671 672 case LINUX_TIOCEXCL: 673 args->cmd = TIOCEXCL; 674 return ioctl(p, (struct ioctl_args *)args); 675 676 case LINUX_TIOCNXCL: 677 args->cmd = TIOCNXCL; 678 return ioctl(p, (struct ioctl_args *)args); 679 680 case LINUX_TIOCCONS: 681 args->cmd = TIOCCONS; 682 return ioctl(p, (struct ioctl_args *)args); 683 684 case LINUX_TIOCNOTTY: 685 args->cmd = TIOCNOTTY; 686 return ioctl(p, (struct ioctl_args *)args); 687 688 case LINUX_SIOCGIFCONF: 689 args->cmd = OSIOCGIFCONF; 690 return ioctl(p, (struct ioctl_args *)args); 691 692 case LINUX_SIOCGIFFLAGS: 693 args->cmd = SIOCGIFFLAGS; 694 return ioctl(p, (struct ioctl_args *)args); 695 696 case LINUX_SIOCGIFADDR: 697 args->cmd = OSIOCGIFADDR; 698 return ioctl(p, (struct ioctl_args *)args); 699 700 case LINUX_SIOCGIFDSTADDR: 701 args->cmd = OSIOCGIFDSTADDR; 702 return ioctl(p, (struct ioctl_args *)args); 703 704 case LINUX_SIOCGIFBRDADDR: 705 args->cmd = OSIOCGIFBRDADDR; 706 return ioctl(p, (struct ioctl_args *)args); 707 708 case LINUX_SIOCGIFNETMASK: 709 args->cmd = OSIOCGIFNETMASK; 710 return ioctl(p, (struct ioctl_args *)args); 711 712 /* get hardware address */ 713 case LINUX_SIOCGIFHWADDR: 714 { 715 int ifn; 716 struct ifnet *ifp; 717 struct ifaddr *ifa; 718 struct sockaddr_dl *sdl; 719 struct linux_ifreq *ifr = (struct linux_ifreq *)args->arg; 720 721 /* 722 * Note that we don't actually respect the name in the ifreq structure, as 723 * Linux interface names are all different 724 */ 725 726 for (ifn = 0; ifn < if_index; ifn++) { 727 728 ifp = ifnet_addrs[ifn]->ifa_ifp; /* pointer to interface */ 729 if (ifp->if_type == IFT_ETHER) { /* looks good */ 730 /* walk the address list */ 731 for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa; ifa = TAILQ_NEXT(ifa, ifa_link)) { 732 if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && /* we have an address structure */ 733 (sdl->sdl_family == AF_LINK) && /* it's a link address */ 734 (sdl->sdl_type == IFT_ETHER)) { /* for an ethernet link */ 735 736 return(copyout(LLADDR(sdl), (caddr_t)&ifr->ifr_hwaddr.sa_data, LINUX_IFHWADDRLEN)); 737 } 738 } 739 } 740 } 741 return(ENOENT); /* ??? */ 742 } 743 744 case LINUX_SIOCADDMULTI: 745 args->cmd = SIOCADDMULTI; 746 return ioctl(p, (struct ioctl_args *)args); 747 748 case LINUX_SIOCDELMULTI: 749 args->cmd = SIOCDELMULTI; 750 return ioctl(p, (struct ioctl_args *)args); 751 752 case LINUX_FIOSETOWN: 753 args->cmd = FIOSETOWN; 754 return ioctl(p, (struct ioctl_args *)args); 755 756 case LINUX_SIOCSPGRP: 757 args->cmd = SIOCSPGRP; 758 return ioctl(p, (struct ioctl_args *)args); 759 760 case LINUX_FIOGETOWN: 761 args->cmd = FIOGETOWN; 762 return ioctl(p, (struct ioctl_args *)args); 763 764 case LINUX_SIOCGPGRP: 765 args->cmd = SIOCGPGRP; 766 return ioctl(p, (struct ioctl_args *)args); 767 768 case LINUX_SIOCATMARK: 769 args->cmd = SIOCATMARK; 770 return ioctl(p, (struct ioctl_args *)args); 771 772 case LINUX_TIOCSETD: 773 switch (args->arg) { 774 case LINUX_N_TTY: 775 bsd_line = TTYDISC; 776 return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p); 777 case LINUX_N_SLIP: 778 bsd_line = SLIPDISC; 779 return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p); 780 case LINUX_N_PPP: 781 bsd_line = PPPDISC; 782 return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p); 783 default: 784 return EINVAL; 785 } 786 787 case LINUX_TIOCGETD: 788 bsd_line = TTYDISC; 789 error =(*func)(fp, TIOCGETD, (caddr_t)&bsd_line, p); 790 if (error) 791 return error; 792 switch (bsd_line) { 793 case TTYDISC: 794 linux_line = LINUX_N_TTY; 795 break; 796 case SLIPDISC: 797 linux_line = LINUX_N_SLIP; 798 break; 799 case PPPDISC: 800 linux_line = LINUX_N_PPP; 801 break; 802 default: 803 return EINVAL; 804 } 805 return copyout(&linux_line, (caddr_t)args->arg, 806 sizeof(int)); 807 808 case LINUX_SNDCTL_SEQ_RESET: 809 args->cmd = SNDCTL_SEQ_RESET; 810 return ioctl(p, (struct ioctl_args *)args); 811 812 case LINUX_SNDCTL_SEQ_SYNC: 813 args->cmd = SNDCTL_SEQ_SYNC; 814 return ioctl(p, (struct ioctl_args *)args); 815 816 case LINUX_SNDCTL_SYNTH_INFO: 817 args->cmd = SNDCTL_SYNTH_INFO; 818 return ioctl(p, (struct ioctl_args *)args); 819 820 case LINUX_SNDCTL_SEQ_CTRLRATE: 821 args->cmd = SNDCTL_SEQ_CTRLRATE; 822 return ioctl(p, (struct ioctl_args *)args); 823 824 case LINUX_SNDCTL_SEQ_GETOUTCOUNT: 825 args->cmd = SNDCTL_SEQ_GETOUTCOUNT; 826 return ioctl(p, (struct ioctl_args *)args); 827 828 case LINUX_SNDCTL_SEQ_GETINCOUNT: 829 args->cmd = SNDCTL_SEQ_GETINCOUNT; 830 return ioctl(p, (struct ioctl_args *)args); 831 832 case LINUX_SNDCTL_SEQ_PERCMODE: 833 args->cmd = SNDCTL_SEQ_PERCMODE; 834 return ioctl(p, (struct ioctl_args *)args); 835 836 case LINUX_SNDCTL_FM_LOAD_INSTR: 837 args->cmd = SNDCTL_FM_LOAD_INSTR; 838 return ioctl(p, (struct ioctl_args *)args); 839 840 case LINUX_SNDCTL_SEQ_TESTMIDI: 841 args->cmd = SNDCTL_SEQ_TESTMIDI; 842 return ioctl(p, (struct ioctl_args *)args); 843 844 case LINUX_SNDCTL_SEQ_RESETSAMPLES: 845 args->cmd = SNDCTL_SEQ_RESETSAMPLES; 846 return ioctl(p, (struct ioctl_args *)args); 847 848 case LINUX_SNDCTL_SEQ_NRSYNTHS: 849 args->cmd = SNDCTL_SEQ_NRSYNTHS; 850 return ioctl(p, (struct ioctl_args *)args); 851 852 case LINUX_SNDCTL_SEQ_NRMIDIS: 853 args->cmd = SNDCTL_SEQ_NRMIDIS; 854 return ioctl(p, (struct ioctl_args *)args); 855 856 case LINUX_SNDCTL_MIDI_INFO: 857 args->cmd = SNDCTL_MIDI_INFO; 858 return ioctl(p, (struct ioctl_args *)args); 859 860 case LINUX_SNDCTL_SEQ_TRESHOLD: 861 args->cmd = SNDCTL_SEQ_TRESHOLD; 862 return ioctl(p, (struct ioctl_args *)args); 863 864 case LINUX_SNDCTL_SYNTH_MEMAVL: 865 args->cmd = SNDCTL_SYNTH_MEMAVL; 866 return ioctl(p, (struct ioctl_args *)args); 867 868 case LINUX_SNDCTL_DSP_GETOPTR : 869 args->cmd = SNDCTL_DSP_GETOPTR; 870 return ioctl(p, (struct ioctl_args *)args); 871 872 case LINUX_SNDCTL_DSP_GETIPTR : 873 args->cmd = SNDCTL_DSP_GETIPTR; 874 return ioctl(p, (struct ioctl_args *)args); 875 876 case LINUX_SNDCTL_DSP_SETTRIGGER: 877 args->cmd = SNDCTL_DSP_SETTRIGGER; 878 return ioctl(p, (struct ioctl_args *)args); 879 880 case LINUX_SNDCTL_DSP_GETCAPS: 881 args->cmd = SNDCTL_DSP_GETCAPS; 882 return ioctl(p, (struct ioctl_args *)args); 883 884 case LINUX_SNDCTL_DSP_RESET: 885 args->cmd = SNDCTL_DSP_RESET; 886 return ioctl(p, (struct ioctl_args *)args); 887 888 case LINUX_SNDCTL_DSP_SYNC: 889 args->cmd = SNDCTL_DSP_SYNC; 890 return ioctl(p, (struct ioctl_args *)args); 891 892 case LINUX_SNDCTL_DSP_SPEED: 893 args->cmd = SNDCTL_DSP_SPEED; 894 return ioctl(p, (struct ioctl_args *)args); 895 896 case LINUX_SNDCTL_DSP_STEREO: 897 args->cmd = SNDCTL_DSP_STEREO; 898 return ioctl(p, (struct ioctl_args *)args); 899 900 case LINUX_SNDCTL_DSP_GETBLKSIZE: 901 /* LINUX_SNDCTL_DSP_SETBLKSIZE */ 902 args->cmd = SNDCTL_DSP_GETBLKSIZE; 903 return ioctl(p, (struct ioctl_args *)args); 904 905 case LINUX_SNDCTL_DSP_SETFMT: 906 args->cmd = SNDCTL_DSP_SETFMT; 907 return ioctl(p, (struct ioctl_args *)args); 908 909 case LINUX_SOUND_PCM_WRITE_CHANNELS: 910 args->cmd = SOUND_PCM_WRITE_CHANNELS; 911 return ioctl(p, (struct ioctl_args *)args); 912 913 case LINUX_SOUND_PCM_WRITE_FILTER: 914 args->cmd = SOUND_PCM_WRITE_FILTER; 915 return ioctl(p, (struct ioctl_args *)args); 916 917 case LINUX_SNDCTL_DSP_POST: 918 args->cmd = SNDCTL_DSP_POST; 919 return ioctl(p, (struct ioctl_args *)args); 920 921 case LINUX_SNDCTL_DSP_SUBDIVIDE: 922 args->cmd = SNDCTL_DSP_SUBDIVIDE; 923 return ioctl(p, (struct ioctl_args *)args); 924 925 case LINUX_SNDCTL_DSP_SETFRAGMENT: 926 args->cmd = SNDCTL_DSP_SETFRAGMENT; 927 return ioctl(p, (struct ioctl_args *)args); 928 929 case LINUX_SNDCTL_DSP_GETFMTS: 930 args->cmd = SNDCTL_DSP_GETFMTS; 931 return ioctl(p, (struct ioctl_args *)args); 932 933 case LINUX_SNDCTL_DSP_GETOSPACE: 934 args->cmd = SNDCTL_DSP_GETOSPACE; 935 return ioctl(p, (struct ioctl_args *)args); 936 937 case LINUX_SNDCTL_DSP_GETISPACE: 938 args->cmd = SNDCTL_DSP_GETISPACE; 939 return ioctl(p, (struct ioctl_args *)args); 940 941 case LINUX_SNDCTL_DSP_NONBLOCK: 942 args->cmd = SNDCTL_DSP_NONBLOCK; 943 return ioctl(p, (struct ioctl_args *)args); 944 945 case LINUX_SOUND_MIXER_WRITE_VOLUME: 946 args->cmd = SETDIR(SOUND_MIXER_WRITE_VOLUME); 947 return ioctl(p, (struct ioctl_args *)args); 948 949 case LINUX_SOUND_MIXER_WRITE_BASS: 950 args->cmd = SETDIR(SOUND_MIXER_WRITE_BASS); 951 return ioctl(p, (struct ioctl_args *)args); 952 953 case LINUX_SOUND_MIXER_WRITE_TREBLE: 954 args->cmd = SETDIR(SOUND_MIXER_WRITE_TREBLE); 955 return ioctl(p, (struct ioctl_args *)args); 956 957 case LINUX_SOUND_MIXER_WRITE_SYNTH: 958 args->cmd = SETDIR(SOUND_MIXER_WRITE_SYNTH); 959 return ioctl(p, (struct ioctl_args *)args); 960 961 case LINUX_SOUND_MIXER_WRITE_PCM: 962 args->cmd = SETDIR(SOUND_MIXER_WRITE_PCM); 963 return ioctl(p, (struct ioctl_args *)args); 964 965 case LINUX_SOUND_MIXER_WRITE_SPEAKER: 966 args->cmd = SETDIR(SOUND_MIXER_WRITE_SPEAKER); 967 return ioctl(p, (struct ioctl_args *)args); 968 969 case LINUX_SOUND_MIXER_WRITE_LINE: 970 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE); 971 return ioctl(p, (struct ioctl_args *)args); 972 973 case LINUX_SOUND_MIXER_WRITE_MIC: 974 args->cmd = SETDIR(SOUND_MIXER_WRITE_MIC); 975 return ioctl(p, (struct ioctl_args *)args); 976 977 case LINUX_SOUND_MIXER_WRITE_CD: 978 args->cmd = SETDIR(SOUND_MIXER_WRITE_CD); 979 return ioctl(p, (struct ioctl_args *)args); 980 981 case LINUX_SOUND_MIXER_WRITE_IMIX: 982 args->cmd = SETDIR(SOUND_MIXER_WRITE_IMIX); 983 return ioctl(p, (struct ioctl_args *)args); 984 985 case LINUX_SOUND_MIXER_WRITE_ALTPCM: 986 args->cmd = SETDIR(SOUND_MIXER_WRITE_ALTPCM); 987 return ioctl(p, (struct ioctl_args *)args); 988 989 case LINUX_SOUND_MIXER_WRITE_RECLEV: 990 args->cmd = SETDIR(SOUND_MIXER_WRITE_RECLEV); 991 return ioctl(p, (struct ioctl_args *)args); 992 993 case LINUX_SOUND_MIXER_WRITE_IGAIN: 994 args->cmd = SETDIR(SOUND_MIXER_WRITE_IGAIN); 995 return ioctl(p, (struct ioctl_args *)args); 996 997 case LINUX_SOUND_MIXER_WRITE_OGAIN: 998 args->cmd = SETDIR(SOUND_MIXER_WRITE_OGAIN); 999 return ioctl(p, (struct ioctl_args *)args); 1000 1001 case LINUX_SOUND_MIXER_WRITE_LINE1: 1002 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE1); 1003 return ioctl(p, (struct ioctl_args *)args); 1004 1005 case LINUX_SOUND_MIXER_WRITE_LINE2: 1006 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE2); 1007 return ioctl(p, (struct ioctl_args *)args); 1008 1009 case LINUX_SOUND_MIXER_WRITE_LINE3: 1010 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE3); 1011 return ioctl(p, (struct ioctl_args *)args); 1012 1013 case LINUX_SOUND_MIXER_READ_DEVMASK: 1014 args->cmd = SOUND_MIXER_READ_DEVMASK; 1015 return ioctl(p, (struct ioctl_args *)args); 1016 1017 case LINUX_TIOCGSERIAL: { 1018 struct linux_serial_struct lss; 1019 1020 lss.type = LINUX_PORT_16550A; 1021 lss.flags = 0; 1022 lss.close_delay = 0; 1023 return copyout((caddr_t)&lss, (caddr_t)args->arg, sizeof(lss)); 1024 } 1025 1026 case LINUX_TIOCSSERIAL: { 1027 struct linux_serial_struct lss; 1028 1029 error = copyin((caddr_t)args->arg, (caddr_t)&lss, sizeof(lss)); 1030 if (error) 1031 return error; 1032 /* 1033 * XXX - It really helps to have an implementation that does nothing. 1034 * NOT! 1035 */ 1036 return 0; 1037 } 1038 1039 case LINUX_TCXONC: 1040 switch (args->arg) { 1041 case LINUX_TCOOFF: 1042 args->cmd = TIOCSTOP; 1043 break; 1044 case LINUX_TCOON: 1045 args->cmd = TIOCSTART; 1046 break; 1047 case LINUX_TCIOFF: 1048 case LINUX_TCION: { 1049 u_char c; 1050 struct write_args wr; 1051 error = (*func)(fp, TIOCGETA, (caddr_t)&bsd_termios, p); 1052 if (error != 0) 1053 return error; 1054 c = bsd_termios.c_cc[args->arg == LINUX_TCIOFF ? VSTOP : VSTART]; 1055 if (c != _POSIX_VDISABLE) { 1056 wr.fd = args->fd; 1057 wr.buf = &c; 1058 wr.nbyte = sizeof(c); 1059 return write(p, &wr); 1060 } 1061 else 1062 return (0); 1063 } 1064 default: 1065 return EINVAL; 1066 } 1067 args->arg = 0; 1068 return ioctl(p, (struct ioctl_args *)args); 1069 1070 case LINUX_TCFLSH: 1071 args->cmd = TIOCFLUSH; 1072 switch (args->arg) { 1073 case LINUX_TCIFLUSH: 1074 args->arg = FREAD; 1075 break; 1076 case LINUX_TCOFLUSH: 1077 args->arg = FWRITE; 1078 break; 1079 case LINUX_TCIOFLUSH: 1080 args->arg = FREAD | FWRITE; 1081 break; 1082 default: 1083 return EINVAL; 1084 } 1085 return ioctl(p, (struct ioctl_args *)args); 1086 1087 case LINUX_VT_OPENQRY: 1088 1089 args->cmd = VT_OPENQRY; 1090 return ioctl(p, (struct ioctl_args *)args); 1091 1092 case LINUX_VT_GETMODE: 1093 1094 args->cmd = VT_GETMODE; 1095 return ioctl(p, (struct ioctl_args *)args); 1096 1097 case LINUX_VT_SETMODE: 1098 { 1099 struct vt_mode *mode; 1100 args->cmd = VT_SETMODE; 1101 mode = (struct vt_mode *)args->arg; 1102 if (!ISSIGVALID(mode->frsig) && ISSIGVALID(mode->acqsig)) 1103 mode->frsig = mode->acqsig; 1104 return ioctl(p, (struct ioctl_args *)args); 1105 } 1106 1107 case LINUX_VT_GETSTATE: 1108 1109 args->cmd = VT_GETACTIVE; 1110 return ioctl(p, (struct ioctl_args *)args); 1111 1112 case LINUX_VT_RELDISP: 1113 1114 args->cmd = VT_RELDISP; 1115 return ioctl(p, (struct ioctl_args *)args); 1116 1117 case LINUX_VT_ACTIVATE: 1118 1119 args->cmd = VT_ACTIVATE; 1120 return ioctl(p, (struct ioctl_args *)args); 1121 1122 case LINUX_VT_WAITACTIVE: 1123 1124 args->cmd = VT_WAITACTIVE; 1125 return ioctl(p, (struct ioctl_args *)args); 1126 1127 case LINUX_KDGKBMODE: 1128 1129 args->cmd = KDGKBMODE; 1130 return ioctl(p, (struct ioctl_args *)args); 1131 1132 case LINUX_KDSKBMODE: 1133 { 1134 int kbdmode; 1135 switch (args->arg) { 1136 case LINUX_KBD_RAW: 1137 kbdmode = K_RAW; 1138 return (*func)(fp, KDSKBMODE, (caddr_t)&kbdmode, p); 1139 case LINUX_KBD_XLATE: 1140 kbdmode = K_XLATE; 1141 return (*func)(fp, KDSKBMODE , (caddr_t)&kbdmode, p); 1142 case LINUX_KBD_MEDIUMRAW: 1143 kbdmode = K_RAW; 1144 return (*func)(fp, KDSKBMODE , (caddr_t)&kbdmode, p); 1145 default: 1146 return EINVAL; 1147 } 1148 } 1149 1150 case LINUX_KDGETMODE: 1151 args->cmd = KDGETMODE; 1152 return ioctl(p, (struct ioctl_args *)args); 1153 1154 case LINUX_KDSETMODE: 1155 args->cmd = KDSETMODE; 1156 return ioctl(p, (struct ioctl_args *)args); 1157 1158 case LINUX_KDSETLED: 1159 args->cmd = KDSETLED; 1160 return ioctl(p, (struct ioctl_args *)args); 1161 1162 case LINUX_KDGETLED: 1163 args->cmd = KDGETLED; 1164 return ioctl(p, (struct ioctl_args *)args); 1165 1166 case LINUX_KIOCSOUND: 1167 args->cmd = KIOCSOUND; 1168 return ioctl(p, (struct ioctl_args *)args); 1169 1170 case LINUX_KDMKTONE: 1171 args->cmd = KDMKTONE; 1172 return ioctl(p, (struct ioctl_args *)args); 1173 1174 1175 case LINUX_CDROMPAUSE: 1176 args->cmd = CDIOCPAUSE; 1177 return ioctl(p, (struct ioctl_args *)args); 1178 1179 case LINUX_CDROMRESUME: 1180 args->cmd = CDIOCRESUME; 1181 return ioctl(p, (struct ioctl_args *)args); 1182 1183 case LINUX_CDROMPLAYMSF: 1184 args->cmd = CDIOCPLAYMSF; 1185 return ioctl(p, (struct ioctl_args *)args); 1186 1187 case LINUX_CDROMPLAYTRKIND: 1188 args->cmd = CDIOCPLAYTRACKS; 1189 return ioctl(p, (struct ioctl_args *)args); 1190 1191 case LINUX_CDROMSTART: 1192 args->cmd = CDIOCSTART; 1193 return ioctl(p, (struct ioctl_args *)args); 1194 1195 case LINUX_CDROMSTOP: 1196 args->cmd = CDIOCSTOP; 1197 return ioctl(p, (struct ioctl_args *)args); 1198 1199 case LINUX_CDROMEJECT: 1200 args->cmd = CDIOCEJECT; 1201 return ioctl(p, (struct ioctl_args *)args); 1202 1203 case LINUX_CDROMRESET: 1204 args->cmd = CDIOCRESET; 1205 return ioctl(p, (struct ioctl_args *)args); 1206 1207 case LINUX_CDROMREADTOCHDR: { 1208 struct ioc_toc_header th; 1209 struct linux_cdrom_tochdr lth; 1210 error = (*func)(fp, CDIOREADTOCHEADER, (caddr_t)&th, p); 1211 if (!error) { 1212 lth.cdth_trk0 = th.starting_track; 1213 lth.cdth_trk1 = th.ending_track; 1214 copyout((caddr_t)<h, (caddr_t)args->arg, sizeof(lth)); 1215 } 1216 return error; 1217 } 1218 1219 case LINUX_CDROMREADTOCENTRY: { 1220 struct linux_cdrom_tocentry lte, *ltep = 1221 (struct linux_cdrom_tocentry *)args->arg; 1222 struct ioc_read_toc_single_entry irtse; 1223 irtse.address_format = ltep->cdte_format; 1224 irtse.track = ltep->cdte_track; 1225 error = (*func)(fp, CDIOREADTOCENTRY, (caddr_t)&irtse, p); 1226 if (!error) { 1227 lte = *ltep; 1228 lte.cdte_ctrl = irtse.entry.control; 1229 lte.cdte_adr = irtse.entry.addr_type; 1230 bsd_to_linux_msf_lba(irtse.address_format, 1231 &irtse.entry.addr, <e.cdte_addr); 1232 copyout((caddr_t)<e, (caddr_t)args->arg, sizeof(lte)); 1233 } 1234 return error; 1235 } 1236 1237 case LINUX_CDROMSUBCHNL: { 1238 caddr_t sg; 1239 struct linux_cdrom_subchnl sc; 1240 struct ioc_read_subchannel bsdsc; 1241 struct cd_sub_channel_info *bsdinfo; 1242 1243 sg = stackgap_init(); 1244 bsdinfo = (struct cd_sub_channel_info*)stackgap_alloc(&sg, 1245 sizeof(struct cd_sub_channel_info)); 1246 1247 bsdsc.address_format = CD_LBA_FORMAT; 1248 bsdsc.data_format = CD_CURRENT_POSITION; 1249 bsdsc.data_len = sizeof(struct cd_sub_channel_info); 1250 bsdsc.data = bsdinfo; 1251 error = (*func)(fp, CDIOCREADSUBCHANNEL, (caddr_t)&bsdsc, p); 1252 if (error) 1253 return error; 1254 1255 error = copyin((caddr_t)args->arg, (caddr_t)&sc, 1256 sizeof(struct linux_cdrom_subchnl)); 1257 if (error) 1258 return error; 1259 1260 sc.cdsc_audiostatus = bsdinfo->header.audio_status; 1261 sc.cdsc_adr = bsdinfo->what.position.addr_type; 1262 sc.cdsc_ctrl = bsdinfo->what.position.control; 1263 sc.cdsc_trk = bsdinfo->what.position.track_number; 1264 sc.cdsc_ind = bsdinfo->what.position.index_number; 1265 set_linux_cdrom_addr(&sc.cdsc_absaddr, sc.cdsc_format, 1266 bsdinfo->what.position.absaddr.lba); 1267 set_linux_cdrom_addr(&sc.cdsc_reladdr, sc.cdsc_format, 1268 bsdinfo->what.position.reladdr.lba); 1269 error = copyout((caddr_t)&sc, (caddr_t)args->arg, 1270 sizeof(struct linux_cdrom_subchnl)); 1271 return error; 1272 } 1273 1274 case LINUX_OSS_GETVERSION: { 1275 int version; 1276 1277 version = linux_get_oss_version(p); 1278 return copyout((caddr_t)&version, (caddr_t)args->arg, sizeof(int)); 1279 } 1280 1281 } 1282 1283 uprintf("LINUX: 'ioctl' fd=%d, typ=0x%x(%c), num=0x%x not implemented\n", 1284 args->fd, (u_int)((args->cmd & 0xffff00) >> 8), 1285 (int)((args->cmd & 0xffff00) >> 8), (u_int)(args->cmd & 0xff)); 1286 return EINVAL; 1287 } 1288