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 * $Id: linux_ioctl.c,v 1.24 1998/06/07 17:11:26 dfr Exp $ 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/fcntl.h> 36 #include <sys/file.h> 37 #include <sys/filedesc.h> 38 #include <sys/filio.h> 39 #include <sys/tty.h> 40 #include <sys/socket.h> 41 #include <net/if.h> 42 #include <net/if_dl.h> 43 #include <net/if_types.h> 44 #include <sys/sockio.h> 45 46 #include <machine/soundcard.h> 47 #include <machine/console.h> 48 49 #include <i386/linux/linux.h> 50 #include <i386/linux/linux_proto.h> 51 52 struct linux_termio { 53 unsigned short c_iflag; 54 unsigned short c_oflag; 55 unsigned short c_cflag; 56 unsigned short c_lflag; 57 unsigned char c_line; 58 unsigned char c_cc[LINUX_NCC]; 59 }; 60 61 62 struct linux_termios { 63 unsigned long c_iflag; 64 unsigned long c_oflag; 65 unsigned long c_cflag; 66 unsigned long c_lflag; 67 unsigned char c_line; 68 unsigned char c_cc[LINUX_NCCS]; 69 }; 70 71 struct linux_winsize { 72 unsigned short ws_row, ws_col; 73 unsigned short ws_xpixel, ws_ypixel; 74 }; 75 76 static struct speedtab sptab[] = { 77 { 0, 0 }, { 50, 1 }, { 75, 2 }, { 110, 3 }, 78 { 134, 4 }, { 135, 4 }, { 150, 5 }, { 200, 6 }, 79 { 300, 7 }, { 600, 8 }, { 1200, 9 }, { 1800, 10 }, 80 { 2400, 11 }, { 4800, 12 }, { 9600, 13 }, 81 { 19200, 14 }, { 38400, 15 }, 82 { 57600, 4097 }, { 115200, 4098 }, {-1, -1 } 83 }; 84 85 struct linux_serial_struct { 86 int type; 87 int line; 88 int port; 89 int irq; 90 int flags; 91 int xmit_fifo_size; 92 int custom_divisor; 93 int baud_base; 94 unsigned short close_delay; 95 char reserved_char[2]; 96 int hub6; 97 unsigned short closing_wait; 98 unsigned short closing_wait2; 99 int reserved[4]; 100 }; 101 102 103 static int 104 linux_to_bsd_speed(int code, struct speedtab *table) 105 { 106 for ( ; table->sp_code != -1; table++) 107 if (table->sp_code == code) 108 return (table->sp_speed); 109 return -1; 110 } 111 112 static int 113 bsd_to_linux_speed(int speed, struct speedtab *table) 114 { 115 for ( ; table->sp_speed != -1; table++) 116 if (table->sp_speed == speed) 117 return (table->sp_code); 118 return -1; 119 } 120 121 static void 122 bsd_to_linux_termios(struct termios *bsd_termios, 123 struct linux_termios *linux_termios) 124 { 125 int i; 126 127 #ifdef DEBUG 128 printf("LINUX: BSD termios structure (input):\n"); 129 printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n", 130 bsd_termios->c_iflag, bsd_termios->c_oflag, 131 bsd_termios->c_cflag, bsd_termios->c_lflag, 132 bsd_termios->c_ispeed, bsd_termios->c_ospeed); 133 printf("c_cc "); 134 for (i=0; i<NCCS; i++) 135 printf("%02x ", bsd_termios->c_cc[i]); 136 printf("\n"); 137 #endif 138 linux_termios->c_iflag = 0; 139 if (bsd_termios->c_iflag & IGNBRK) 140 linux_termios->c_iflag |= LINUX_IGNBRK; 141 if (bsd_termios->c_iflag & BRKINT) 142 linux_termios->c_iflag |= LINUX_BRKINT; 143 if (bsd_termios->c_iflag & IGNPAR) 144 linux_termios->c_iflag |= LINUX_IGNPAR; 145 if (bsd_termios->c_iflag & PARMRK) 146 linux_termios->c_iflag |= LINUX_PARMRK; 147 if (bsd_termios->c_iflag & INPCK) 148 linux_termios->c_iflag |= LINUX_INPCK; 149 if (bsd_termios->c_iflag & ISTRIP) 150 linux_termios->c_iflag |= LINUX_ISTRIP; 151 if (bsd_termios->c_iflag & INLCR) 152 linux_termios->c_iflag |= LINUX_INLCR; 153 if (bsd_termios->c_iflag & IGNCR) 154 linux_termios->c_iflag |= LINUX_IGNCR; 155 if (bsd_termios->c_iflag & ICRNL) 156 linux_termios->c_iflag |= LINUX_ICRNL; 157 if (bsd_termios->c_iflag & IXON) 158 linux_termios->c_iflag |= LINUX_IXANY; 159 if (bsd_termios->c_iflag & IXON) 160 linux_termios->c_iflag |= LINUX_IXON; 161 if (bsd_termios->c_iflag & IXOFF) 162 linux_termios->c_iflag |= LINUX_IXOFF; 163 if (bsd_termios->c_iflag & IMAXBEL) 164 linux_termios->c_iflag |= LINUX_IMAXBEL; 165 166 linux_termios->c_oflag = 0; 167 if (bsd_termios->c_oflag & OPOST) 168 linux_termios->c_oflag |= LINUX_OPOST; 169 if (bsd_termios->c_oflag & ONLCR) 170 linux_termios->c_oflag |= LINUX_ONLCR; 171 if (bsd_termios->c_oflag & OXTABS) 172 linux_termios->c_oflag |= LINUX_XTABS; 173 174 linux_termios->c_cflag = 175 bsd_to_linux_speed(bsd_termios->c_ispeed, sptab); 176 linux_termios->c_cflag |= (bsd_termios->c_cflag & CSIZE) >> 4; 177 if (bsd_termios->c_cflag & CSTOPB) 178 linux_termios->c_cflag |= LINUX_CSTOPB; 179 if (bsd_termios->c_cflag & CREAD) 180 linux_termios->c_cflag |= LINUX_CREAD; 181 if (bsd_termios->c_cflag & PARENB) 182 linux_termios->c_cflag |= LINUX_PARENB; 183 if (bsd_termios->c_cflag & PARODD) 184 linux_termios->c_cflag |= LINUX_PARODD; 185 if (bsd_termios->c_cflag & HUPCL) 186 linux_termios->c_cflag |= LINUX_HUPCL; 187 if (bsd_termios->c_cflag & CLOCAL) 188 linux_termios->c_cflag |= LINUX_CLOCAL; 189 if (bsd_termios->c_cflag & CRTSCTS) 190 linux_termios->c_cflag |= LINUX_CRTSCTS; 191 192 linux_termios->c_lflag = 0; 193 if (bsd_termios->c_lflag & ISIG) 194 linux_termios->c_lflag |= LINUX_ISIG; 195 if (bsd_termios->c_lflag & ICANON) 196 linux_termios->c_lflag |= LINUX_ICANON; 197 if (bsd_termios->c_lflag & ECHO) 198 linux_termios->c_lflag |= LINUX_ECHO; 199 if (bsd_termios->c_lflag & ECHOE) 200 linux_termios->c_lflag |= LINUX_ECHOE; 201 if (bsd_termios->c_lflag & ECHOK) 202 linux_termios->c_lflag |= LINUX_ECHOK; 203 if (bsd_termios->c_lflag & ECHONL) 204 linux_termios->c_lflag |= LINUX_ECHONL; 205 if (bsd_termios->c_lflag & NOFLSH) 206 linux_termios->c_lflag |= LINUX_NOFLSH; 207 if (bsd_termios->c_lflag & TOSTOP) 208 linux_termios->c_lflag |= LINUX_TOSTOP; 209 if (bsd_termios->c_lflag & ECHOCTL) 210 linux_termios->c_lflag |= LINUX_ECHOCTL; 211 if (bsd_termios->c_lflag & ECHOPRT) 212 linux_termios->c_lflag |= LINUX_ECHOPRT; 213 if (bsd_termios->c_lflag & ECHOKE) 214 linux_termios->c_lflag |= LINUX_ECHOKE; 215 if (bsd_termios->c_lflag & FLUSHO) 216 linux_termios->c_lflag |= LINUX_FLUSHO; 217 if (bsd_termios->c_lflag & PENDIN) 218 linux_termios->c_lflag |= LINUX_PENDIN; 219 if (bsd_termios->c_lflag & IEXTEN) 220 linux_termios->c_lflag |= LINUX_IEXTEN; 221 222 for (i=0; i<LINUX_NCCS; i++) 223 linux_termios->c_cc[i] = LINUX_POSIX_VDISABLE; 224 linux_termios->c_cc[LINUX_VINTR] = bsd_termios->c_cc[VINTR]; 225 linux_termios->c_cc[LINUX_VQUIT] = bsd_termios->c_cc[VQUIT]; 226 linux_termios->c_cc[LINUX_VERASE] = bsd_termios->c_cc[VERASE]; 227 linux_termios->c_cc[LINUX_VKILL] = bsd_termios->c_cc[VKILL]; 228 linux_termios->c_cc[LINUX_VEOF] = bsd_termios->c_cc[VEOF]; 229 linux_termios->c_cc[LINUX_VEOL] = bsd_termios->c_cc[VEOL]; 230 linux_termios->c_cc[LINUX_VMIN] = bsd_termios->c_cc[VMIN]; 231 linux_termios->c_cc[LINUX_VTIME] = bsd_termios->c_cc[VTIME]; 232 linux_termios->c_cc[LINUX_VEOL2] = bsd_termios->c_cc[VEOL2]; 233 linux_termios->c_cc[LINUX_VSWTC] = _POSIX_VDISABLE; 234 linux_termios->c_cc[LINUX_VSUSP] = bsd_termios->c_cc[VSUSP]; 235 linux_termios->c_cc[LINUX_VSTART] = bsd_termios->c_cc[VSTART]; 236 linux_termios->c_cc[LINUX_VSTOP] = bsd_termios->c_cc[VSTOP]; 237 linux_termios->c_cc[LINUX_VREPRINT] = bsd_termios->c_cc[VREPRINT]; 238 linux_termios->c_cc[LINUX_VDISCARD] = bsd_termios->c_cc[VDISCARD]; 239 linux_termios->c_cc[LINUX_VWERASE] = bsd_termios->c_cc[VWERASE]; 240 linux_termios->c_cc[LINUX_VLNEXT] = bsd_termios->c_cc[VLNEXT]; 241 242 for (i=0; i<LINUX_NCCS; i++) { 243 if (linux_termios->c_cc[i] == _POSIX_VDISABLE) 244 linux_termios->c_cc[i] = LINUX_POSIX_VDISABLE; 245 } 246 247 linux_termios->c_line = 0; 248 #ifdef DEBUG 249 printf("LINUX: LINUX termios structure (output):\n"); 250 printf("i=%08lx o=%08lx c=%08lx l=%08lx line=%d\n", 251 linux_termios->c_iflag, linux_termios->c_oflag, linux_termios->c_cflag, 252 linux_termios->c_lflag, linux_termios->c_line); 253 printf("c_cc "); 254 for (i=0; i<LINUX_NCCS; i++) 255 printf("%02x ", linux_termios->c_cc[i]); 256 printf("\n"); 257 #endif 258 } 259 260 261 static void 262 linux_to_bsd_termios(struct linux_termios *linux_termios, 263 struct termios *bsd_termios) 264 { 265 int i; 266 #ifdef DEBUG 267 printf("LINUX: LINUX termios structure (input):\n"); 268 printf("i=%08lx o=%08lx c=%08lx l=%08lx line=%d\n", 269 linux_termios->c_iflag, linux_termios->c_oflag, linux_termios->c_cflag, 270 linux_termios->c_lflag, linux_termios->c_line); 271 printf("c_cc "); 272 for (i=0; i<LINUX_NCCS; i++) 273 printf("%02x ", linux_termios->c_cc[i]); 274 printf("\n"); 275 #endif 276 bsd_termios->c_iflag = 0; 277 if (linux_termios->c_iflag & LINUX_IGNBRK) 278 bsd_termios->c_iflag |= IGNBRK; 279 if (linux_termios->c_iflag & LINUX_BRKINT) 280 bsd_termios->c_iflag |= BRKINT; 281 if (linux_termios->c_iflag & LINUX_IGNPAR) 282 bsd_termios->c_iflag |= IGNPAR; 283 if (linux_termios->c_iflag & LINUX_PARMRK) 284 bsd_termios->c_iflag |= PARMRK; 285 if (linux_termios->c_iflag & LINUX_INPCK) 286 bsd_termios->c_iflag |= INPCK; 287 if (linux_termios->c_iflag & LINUX_ISTRIP) 288 bsd_termios->c_iflag |= ISTRIP; 289 if (linux_termios->c_iflag & LINUX_INLCR) 290 bsd_termios->c_iflag |= INLCR; 291 if (linux_termios->c_iflag & LINUX_IGNCR) 292 bsd_termios->c_iflag |= IGNCR; 293 if (linux_termios->c_iflag & LINUX_ICRNL) 294 bsd_termios->c_iflag |= ICRNL; 295 if (linux_termios->c_iflag & LINUX_IXON) 296 bsd_termios->c_iflag |= IXANY; 297 if (linux_termios->c_iflag & LINUX_IXON) 298 bsd_termios->c_iflag |= IXON; 299 if (linux_termios->c_iflag & LINUX_IXOFF) 300 bsd_termios->c_iflag |= IXOFF; 301 if (linux_termios->c_iflag & LINUX_IMAXBEL) 302 bsd_termios->c_iflag |= IMAXBEL; 303 304 bsd_termios->c_oflag = 0; 305 if (linux_termios->c_oflag & LINUX_OPOST) 306 bsd_termios->c_oflag |= OPOST; 307 if (linux_termios->c_oflag & LINUX_ONLCR) 308 bsd_termios->c_oflag |= ONLCR; 309 if (linux_termios->c_oflag & LINUX_XTABS) 310 bsd_termios->c_oflag |= OXTABS; 311 312 bsd_termios->c_cflag = (linux_termios->c_cflag & LINUX_CSIZE) << 4; 313 if (linux_termios->c_cflag & LINUX_CSTOPB) 314 bsd_termios->c_cflag |= CSTOPB; 315 if (linux_termios->c_cflag & LINUX_PARENB) 316 bsd_termios->c_cflag |= PARENB; 317 if (linux_termios->c_cflag & LINUX_PARODD) 318 bsd_termios->c_cflag |= PARODD; 319 if (linux_termios->c_cflag & LINUX_HUPCL) 320 bsd_termios->c_cflag |= HUPCL; 321 if (linux_termios->c_cflag & LINUX_CLOCAL) 322 bsd_termios->c_cflag |= CLOCAL; 323 if (linux_termios->c_cflag & LINUX_CRTSCTS) 324 bsd_termios->c_cflag |= CRTSCTS; 325 326 bsd_termios->c_lflag = 0; 327 if (linux_termios->c_lflag & LINUX_ISIG) 328 bsd_termios->c_lflag |= ISIG; 329 if (linux_termios->c_lflag & LINUX_ICANON) 330 bsd_termios->c_lflag |= ICANON; 331 if (linux_termios->c_lflag & LINUX_ECHO) 332 bsd_termios->c_lflag |= ECHO; 333 if (linux_termios->c_lflag & LINUX_ECHOE) 334 bsd_termios->c_lflag |= ECHOE; 335 if (linux_termios->c_lflag & LINUX_ECHOK) 336 bsd_termios->c_lflag |= ECHOK; 337 if (linux_termios->c_lflag & LINUX_ECHONL) 338 bsd_termios->c_lflag |= ECHONL; 339 if (linux_termios->c_lflag & LINUX_NOFLSH) 340 bsd_termios->c_lflag |= NOFLSH; 341 if (linux_termios->c_lflag & LINUX_TOSTOP) 342 bsd_termios->c_lflag |= TOSTOP; 343 if (linux_termios->c_lflag & LINUX_ECHOCTL) 344 bsd_termios->c_lflag |= ECHOCTL; 345 if (linux_termios->c_lflag & LINUX_ECHOPRT) 346 bsd_termios->c_lflag |= ECHOPRT; 347 if (linux_termios->c_lflag & LINUX_ECHOKE) 348 bsd_termios->c_lflag |= ECHOKE; 349 if (linux_termios->c_lflag & LINUX_FLUSHO) 350 bsd_termios->c_lflag |= FLUSHO; 351 if (linux_termios->c_lflag & LINUX_PENDIN) 352 bsd_termios->c_lflag |= PENDIN; 353 if (linux_termios->c_lflag & IEXTEN) 354 bsd_termios->c_lflag |= IEXTEN; 355 356 for (i=0; i<NCCS; i++) 357 bsd_termios->c_cc[i] = _POSIX_VDISABLE; 358 bsd_termios->c_cc[VINTR] = linux_termios->c_cc[LINUX_VINTR]; 359 bsd_termios->c_cc[VQUIT] = linux_termios->c_cc[LINUX_VQUIT]; 360 bsd_termios->c_cc[VERASE] = linux_termios->c_cc[LINUX_VERASE]; 361 bsd_termios->c_cc[VKILL] = linux_termios->c_cc[LINUX_VKILL]; 362 bsd_termios->c_cc[VEOF] = linux_termios->c_cc[LINUX_VEOF]; 363 bsd_termios->c_cc[VEOL] = linux_termios->c_cc[LINUX_VEOL]; 364 bsd_termios->c_cc[VMIN] = linux_termios->c_cc[LINUX_VMIN]; 365 bsd_termios->c_cc[VTIME] = linux_termios->c_cc[LINUX_VTIME]; 366 bsd_termios->c_cc[VEOL2] = linux_termios->c_cc[LINUX_VEOL2]; 367 bsd_termios->c_cc[VSUSP] = linux_termios->c_cc[LINUX_VSUSP]; 368 bsd_termios->c_cc[VSTART] = linux_termios->c_cc[LINUX_VSTART]; 369 bsd_termios->c_cc[VSTOP] = linux_termios->c_cc[LINUX_VSTOP]; 370 bsd_termios->c_cc[VREPRINT] = linux_termios->c_cc[LINUX_VREPRINT]; 371 bsd_termios->c_cc[VDISCARD] = linux_termios->c_cc[LINUX_VDISCARD]; 372 bsd_termios->c_cc[VWERASE] = linux_termios->c_cc[LINUX_VWERASE]; 373 bsd_termios->c_cc[VLNEXT] = linux_termios->c_cc[LINUX_VLNEXT]; 374 375 for (i=0; i<NCCS; i++) { 376 if (bsd_termios->c_cc[i] == LINUX_POSIX_VDISABLE) 377 bsd_termios->c_cc[i] = _POSIX_VDISABLE; 378 } 379 380 bsd_termios->c_ispeed = bsd_termios->c_ospeed = 381 linux_to_bsd_speed(linux_termios->c_cflag & LINUX_CBAUD, sptab); 382 #ifdef DEBUG 383 printf("LINUX: BSD termios structure (output):\n"); 384 printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n", 385 bsd_termios->c_iflag, bsd_termios->c_oflag, 386 bsd_termios->c_cflag, bsd_termios->c_lflag, 387 bsd_termios->c_ispeed, bsd_termios->c_ospeed); 388 printf("c_cc "); 389 for (i=0; i<NCCS; i++) 390 printf("%02x ", bsd_termios->c_cc[i]); 391 printf("\n"); 392 #endif 393 } 394 395 396 static void 397 bsd_to_linux_termio(struct termios *bsd_termios, 398 struct linux_termio *linux_termio) 399 { 400 struct linux_termios tmios; 401 402 bsd_to_linux_termios(bsd_termios, &tmios); 403 linux_termio->c_iflag = tmios.c_iflag; 404 linux_termio->c_oflag = tmios.c_oflag; 405 linux_termio->c_cflag = tmios.c_cflag; 406 linux_termio->c_lflag = tmios.c_lflag; 407 linux_termio->c_line = tmios.c_line; 408 memcpy(linux_termio->c_cc, tmios.c_cc, LINUX_NCC); 409 } 410 411 static void 412 linux_to_bsd_termio(struct linux_termio *linux_termio, 413 struct termios *bsd_termios) 414 { 415 struct linux_termios tmios; 416 int i; 417 418 tmios.c_iflag = linux_termio->c_iflag; 419 tmios.c_oflag = linux_termio->c_oflag; 420 tmios.c_cflag = linux_termio->c_cflag; 421 tmios.c_lflag = linux_termio->c_lflag; 422 423 for (i=0; i<LINUX_NCCS; i++) 424 tmios.c_cc[i] = LINUX_POSIX_VDISABLE; 425 memcpy(tmios.c_cc, linux_termio->c_cc, LINUX_NCC); 426 427 linux_to_bsd_termios(&tmios, bsd_termios); 428 } 429 430 static void 431 linux_tiocgserial(struct file *fp, struct linux_serial_struct *lss) 432 { 433 if (!fp || !lss) 434 return; 435 436 lss->type = LINUX_PORT_16550A; 437 lss->flags = 0; 438 lss->close_delay = 0; 439 } 440 441 static void 442 linux_tiocsserial(struct file *fp, struct linux_serial_struct *lss) 443 { 444 if (!fp || !lss) 445 return; 446 } 447 448 int 449 linux_ioctl(struct proc *p, struct linux_ioctl_args *args) 450 { 451 struct termios bsd_termios; 452 struct linux_termios linux_termios; 453 struct linux_termio linux_termio; 454 struct filedesc *fdp = p->p_fd; 455 struct file *fp; 456 int (*func)(struct file *fp, u_long com, caddr_t data, struct proc *p); 457 int bsd_line, linux_line; 458 int error; 459 460 #ifdef DEBUG 461 printf("Linux-emul(%ld): ioctl(%d, %04lx, *)\n", 462 (long)p->p_pid, args->fd, args->cmd); 463 #endif 464 if ((unsigned)args->fd >= fdp->fd_nfiles 465 || (fp = fdp->fd_ofiles[args->fd]) == 0) 466 return EBADF; 467 468 if (!fp || (fp->f_flag & (FREAD | FWRITE)) == 0) { 469 return EBADF; 470 } 471 472 func = fp->f_ops->fo_ioctl; 473 switch (args->cmd & 0xffff) { 474 475 case LINUX_TCGETA: 476 if ((error = (*func)(fp, TIOCGETA, (caddr_t)&bsd_termios, p)) != 0) 477 return error; 478 bsd_to_linux_termio(&bsd_termios, &linux_termio); 479 return copyout((caddr_t)&linux_termio, (caddr_t)args->arg, 480 sizeof(linux_termio)); 481 482 case LINUX_TCSETA: 483 linux_to_bsd_termio((struct linux_termio *)args->arg, &bsd_termios); 484 return (*func)(fp, TIOCSETA, (caddr_t)&bsd_termios, p); 485 486 case LINUX_TCSETAW: 487 linux_to_bsd_termio((struct linux_termio *)args->arg, &bsd_termios); 488 return (*func)(fp, TIOCSETAW, (caddr_t)&bsd_termios, p); 489 490 case LINUX_TCSETAF: 491 linux_to_bsd_termio((struct linux_termio *)args->arg, &bsd_termios); 492 return (*func)(fp, TIOCSETAF, (caddr_t)&bsd_termios, p); 493 494 case LINUX_TCGETS: 495 if ((error = (*func)(fp, TIOCGETA, (caddr_t)&bsd_termios, p)) != 0) 496 return error; 497 bsd_to_linux_termios(&bsd_termios, &linux_termios); 498 return copyout((caddr_t)&linux_termios, (caddr_t)args->arg, 499 sizeof(linux_termios)); 500 501 case LINUX_TCSETS: 502 linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios); 503 return (*func)(fp, TIOCSETA, (caddr_t)&bsd_termios, p); 504 505 case LINUX_TCSETSW: 506 linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios); 507 return (*func)(fp, TIOCSETAW, (caddr_t)&bsd_termios, p); 508 509 case LINUX_TCSETSF: 510 linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios); 511 return (*func)(fp, TIOCSETAF, (caddr_t)&bsd_termios, p); 512 513 case LINUX_TIOCGPGRP: 514 args->cmd = TIOCGPGRP; 515 return ioctl(p, (struct ioctl_args *)args); 516 517 case LINUX_TIOCSPGRP: 518 args->cmd = TIOCSPGRP; 519 return ioctl(p, (struct ioctl_args *)args); 520 521 case LINUX_TIOCGWINSZ: 522 args->cmd = TIOCGWINSZ; 523 return ioctl(p, (struct ioctl_args *)args); 524 525 case LINUX_TIOCSWINSZ: 526 args->cmd = TIOCSWINSZ; 527 return ioctl(p, (struct ioctl_args *)args); 528 529 case LINUX_FIONREAD: 530 args->cmd = FIONREAD; 531 return ioctl(p, (struct ioctl_args *)args); 532 533 case LINUX_FIONBIO: 534 args->cmd = FIONBIO; 535 return ioctl(p, (struct ioctl_args *)args); 536 537 case LINUX_FIOASYNC: 538 args->cmd = FIOASYNC; 539 return ioctl(p, (struct ioctl_args *)args); 540 541 case LINUX_FIONCLEX: 542 args->cmd = FIONCLEX; 543 return ioctl(p, (struct ioctl_args *)args); 544 545 case LINUX_FIOCLEX: 546 args->cmd = FIOCLEX; 547 return ioctl(p, (struct ioctl_args *)args); 548 549 case LINUX_TIOCEXCL: 550 args->cmd = TIOCEXCL; 551 return ioctl(p, (struct ioctl_args *)args); 552 553 case LINUX_TIOCNXCL: 554 args->cmd = TIOCNXCL; 555 return ioctl(p, (struct ioctl_args *)args); 556 557 case LINUX_TIOCCONS: 558 args->cmd = TIOCCONS; 559 return ioctl(p, (struct ioctl_args *)args); 560 561 case LINUX_TIOCNOTTY: 562 args->cmd = TIOCNOTTY; 563 return ioctl(p, (struct ioctl_args *)args); 564 565 case LINUX_SIOCGIFCONF: 566 args->cmd = OSIOCGIFCONF; 567 return ioctl(p, (struct ioctl_args *)args); 568 569 case LINUX_SIOCGIFFLAGS: 570 args->cmd = SIOCGIFFLAGS; 571 return ioctl(p, (struct ioctl_args *)args); 572 573 case LINUX_SIOCGIFADDR: 574 args->cmd = OSIOCGIFADDR; 575 return ioctl(p, (struct ioctl_args *)args); 576 577 case LINUX_SIOCGIFDSTADDR: 578 args->cmd = OSIOCGIFDSTADDR; 579 return ioctl(p, (struct ioctl_args *)args); 580 581 case LINUX_SIOCGIFBRDADDR: 582 args->cmd = OSIOCGIFBRDADDR; 583 return ioctl(p, (struct ioctl_args *)args); 584 585 case LINUX_SIOCGIFNETMASK: 586 args->cmd = OSIOCGIFNETMASK; 587 return ioctl(p, (struct ioctl_args *)args); 588 589 /* get hardware address */ 590 case LINUX_SIOCGIFHWADDR: 591 { 592 int ifn; 593 struct ifnet *ifp; 594 struct ifaddr *ifa; 595 struct sockaddr_dl *sdl; 596 struct linux_ifreq *ifr = (struct linux_ifreq *)args->arg; 597 598 /* 599 * Note that we don't actually respect the name in the ifreq structure, as 600 * Linux interface names are all different 601 */ 602 603 for (ifn = 0; ifn < if_index; ifn++) { 604 605 ifp = ifnet_addrs[ifn]->ifa_ifp; /* pointer to interface */ 606 if (ifp->if_type == IFT_ETHER) { /* looks good */ 607 /* walk the address list */ 608 for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa; ifa = TAILQ_NEXT(ifa, ifa_link)) { 609 if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && /* we have an address structure */ 610 (sdl->sdl_family == AF_LINK) && /* it's a link address */ 611 (sdl->sdl_type == IFT_ETHER)) { /* for an ethernet link */ 612 613 return(copyout(LLADDR(sdl), (caddr_t)&ifr->ifr_hwaddr.sa_data, LINUX_IFHWADDRLEN)); 614 } 615 } 616 } 617 } 618 return(ENOENT); /* ??? */ 619 } 620 621 case LINUX_SIOCADDMULTI: 622 args->cmd = SIOCADDMULTI; 623 return ioctl(p, (struct ioctl_args *)args); 624 625 case LINUX_SIOCDELMULTI: 626 args->cmd = SIOCDELMULTI; 627 return ioctl(p, (struct ioctl_args *)args); 628 629 case LINUX_TIOCSETD: 630 switch (args->arg) { 631 case LINUX_N_TTY: 632 bsd_line = TTYDISC; 633 return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p); 634 case LINUX_N_SLIP: 635 bsd_line = SLIPDISC; 636 return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p); 637 case LINUX_N_PPP: 638 bsd_line = PPPDISC; 639 return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p); 640 default: 641 return EINVAL; 642 } 643 644 case LINUX_TIOCGETD: 645 bsd_line = TTYDISC; 646 if (error =(*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p)) 647 return error; 648 switch (bsd_line) { 649 case TTYDISC: 650 linux_line = LINUX_N_TTY; 651 break; 652 case SLIPDISC: 653 linux_line = LINUX_N_SLIP; 654 break; 655 case PPPDISC: 656 linux_line = LINUX_N_PPP; 657 break; 658 default: 659 return EINVAL; 660 } 661 return copyout(&linux_line, (caddr_t)args->arg, 662 sizeof(int)); 663 664 case LINUX_SNDCTL_DSP_GETOPTR : 665 args->cmd = SNDCTL_DSP_GETOPTR; 666 return ioctl(p, (struct ioctl_args *)args); 667 668 case LINUX_SNDCTL_DSP_GETIPTR : 669 args->cmd = SNDCTL_DSP_GETIPTR; 670 return ioctl(p, (struct ioctl_args *)args); 671 672 case LINUX_SNDCTL_DSP_SETTRIGGER: 673 args->cmd = SNDCTL_DSP_SETTRIGGER; 674 return ioctl(p, (struct ioctl_args *)args); 675 676 case LINUX_SNDCTL_DSP_GETCAPS: 677 args->cmd = SNDCTL_DSP_GETCAPS; 678 return ioctl(p, (struct ioctl_args *)args); 679 680 case LINUX_SNDCTL_DSP_RESET: 681 args->cmd = SNDCTL_DSP_RESET; 682 return ioctl(p, (struct ioctl_args *)args); 683 684 case LINUX_SNDCTL_DSP_SYNC: 685 args->cmd = SNDCTL_DSP_SYNC; 686 return ioctl(p, (struct ioctl_args *)args); 687 688 case LINUX_SNDCTL_DSP_SPEED: 689 args->cmd = SNDCTL_DSP_SPEED; 690 return ioctl(p, (struct ioctl_args *)args); 691 692 case LINUX_SNDCTL_DSP_STEREO: 693 args->cmd = SNDCTL_DSP_STEREO; 694 return ioctl(p, (struct ioctl_args *)args); 695 696 case LINUX_SNDCTL_DSP_GETBLKSIZE: 697 /* LINUX_SNDCTL_DSP_SETBLKSIZE */ 698 args->cmd = SNDCTL_DSP_GETBLKSIZE; 699 return ioctl(p, (struct ioctl_args *)args); 700 701 case LINUX_SNDCTL_DSP_SETFMT: 702 args->cmd = SNDCTL_DSP_SETFMT; 703 return ioctl(p, (struct ioctl_args *)args); 704 705 case LINUX_SOUND_PCM_WRITE_CHANNELS: 706 args->cmd = SOUND_PCM_WRITE_CHANNELS; 707 return ioctl(p, (struct ioctl_args *)args); 708 709 case LINUX_SOUND_PCM_WRITE_FILTER: 710 args->cmd = SOUND_PCM_WRITE_FILTER; 711 return ioctl(p, (struct ioctl_args *)args); 712 713 case LINUX_SNDCTL_DSP_POST: 714 args->cmd = SNDCTL_DSP_POST; 715 return ioctl(p, (struct ioctl_args *)args); 716 717 case LINUX_SNDCTL_DSP_SUBDIVIDE: 718 args->cmd = SNDCTL_DSP_SUBDIVIDE; 719 return ioctl(p, (struct ioctl_args *)args); 720 721 case LINUX_SNDCTL_DSP_SETFRAGMENT: 722 args->cmd = SNDCTL_DSP_SETFRAGMENT; 723 return ioctl(p, (struct ioctl_args *)args); 724 725 case LINUX_SNDCTL_DSP_GETFMTS: 726 args->cmd = SNDCTL_DSP_GETFMTS; 727 return ioctl(p, (struct ioctl_args *)args); 728 729 case LINUX_SNDCTL_DSP_GETOSPACE: 730 args->cmd = SNDCTL_DSP_GETOSPACE; 731 return ioctl(p, (struct ioctl_args *)args); 732 733 case LINUX_SNDCTL_DSP_GETISPACE: 734 args->cmd = SNDCTL_DSP_GETISPACE; 735 return ioctl(p, (struct ioctl_args *)args); 736 737 case LINUX_SNDCTL_DSP_NONBLOCK: 738 args->cmd = SNDCTL_DSP_NONBLOCK; 739 return ioctl(p, (struct ioctl_args *)args); 740 741 case LINUX_SOUND_MIXER_WRITE_VOLUME: 742 args->cmd = SOUND_MIXER_WRITE_VOLUME; 743 return ioctl(p, (struct ioctl_args *)args); 744 745 case LINUX_SOUND_MIXER_WRITE_BASS: 746 args->cmd = SOUND_MIXER_WRITE_BASS; 747 return ioctl(p, (struct ioctl_args *)args); 748 749 case LINUX_SOUND_MIXER_WRITE_TREBLE: 750 args->cmd = SOUND_MIXER_WRITE_TREBLE; 751 return ioctl(p, (struct ioctl_args *)args); 752 753 case LINUX_SOUND_MIXER_WRITE_SYNTH: 754 args->cmd = SOUND_MIXER_WRITE_SYNTH; 755 return ioctl(p, (struct ioctl_args *)args); 756 757 case LINUX_SOUND_MIXER_WRITE_PCM: 758 args->cmd = SOUND_MIXER_WRITE_PCM; 759 return ioctl(p, (struct ioctl_args *)args); 760 761 case LINUX_SOUND_MIXER_WRITE_SPEAKER: 762 args->cmd = SOUND_MIXER_WRITE_SPEAKER; 763 return ioctl(p, (struct ioctl_args *)args); 764 765 case LINUX_SOUND_MIXER_WRITE_LINE: 766 args->cmd = SOUND_MIXER_WRITE_LINE; 767 return ioctl(p, (struct ioctl_args *)args); 768 769 case LINUX_SOUND_MIXER_WRITE_MIC: 770 args->cmd = SOUND_MIXER_WRITE_MIC; 771 return ioctl(p, (struct ioctl_args *)args); 772 773 case LINUX_SOUND_MIXER_WRITE_CD: 774 args->cmd = SOUND_MIXER_WRITE_CD; 775 return ioctl(p, (struct ioctl_args *)args); 776 777 case LINUX_SOUND_MIXER_WRITE_IMIX: 778 args->cmd = SOUND_MIXER_WRITE_IMIX; 779 return ioctl(p, (struct ioctl_args *)args); 780 781 case LINUX_SOUND_MIXER_WRITE_ALTPCM: 782 args->cmd = SOUND_MIXER_WRITE_ALTPCM; 783 return ioctl(p, (struct ioctl_args *)args); 784 785 case LINUX_SOUND_MIXER_WRITE_RECLEV: 786 args->cmd = SOUND_MIXER_WRITE_RECLEV; 787 return ioctl(p, (struct ioctl_args *)args); 788 789 case LINUX_SOUND_MIXER_WRITE_IGAIN: 790 args->cmd = SOUND_MIXER_WRITE_IGAIN; 791 return ioctl(p, (struct ioctl_args *)args); 792 793 case LINUX_SOUND_MIXER_WRITE_OGAIN: 794 args->cmd = SOUND_MIXER_WRITE_OGAIN; 795 return ioctl(p, (struct ioctl_args *)args); 796 797 case LINUX_SOUND_MIXER_WRITE_LINE1: 798 args->cmd = SOUND_MIXER_WRITE_LINE1; 799 return ioctl(p, (struct ioctl_args *)args); 800 801 case LINUX_SOUND_MIXER_WRITE_LINE2: 802 args->cmd = SOUND_MIXER_WRITE_LINE2; 803 return ioctl(p, (struct ioctl_args *)args); 804 805 case LINUX_SOUND_MIXER_WRITE_LINE3: 806 args->cmd = SOUND_MIXER_WRITE_LINE3; 807 return ioctl(p, (struct ioctl_args *)args); 808 809 case LINUX_SOUND_MIXER_READ_DEVMASK: 810 args->cmd = SOUND_MIXER_READ_DEVMASK; 811 return ioctl(p, (struct ioctl_args *)args); 812 813 case LINUX_TIOCGSERIAL: 814 linux_tiocgserial(fp, (struct linux_serial_struct *)args->arg); 815 return 0; 816 817 case LINUX_TIOCSSERIAL: 818 linux_tiocsserial(fp, (struct linux_serial_struct *)args->arg); 819 return 0; 820 821 case LINUX_TCFLSH: 822 args->cmd = TIOCFLUSH; 823 switch (args->arg) { 824 case LINUX_TCIFLUSH: 825 args->arg = FREAD; 826 break; 827 case LINUX_TCOFLUSH: 828 args->arg = FWRITE; 829 break; 830 case LINUX_TCIOFLUSH: 831 args->arg = FREAD | FWRITE; 832 break; 833 default: 834 return EINVAL; 835 } 836 return ioctl(p, (struct ioctl_args *)args); 837 838 case LINUX_VT_OPENQRY: 839 840 args->cmd = VT_OPENQRY; 841 return ioctl(p, (struct ioctl_args *)args); 842 843 case LINUX_VT_GETMODE: 844 845 args->cmd = VT_GETMODE; 846 return ioctl(p, (struct ioctl_args *)args); 847 848 case LINUX_VT_SETMODE: 849 850 args->cmd = VT_SETMODE; 851 return ioctl(p, (struct ioctl_args *)args); 852 853 case LINUX_VT_GETSTATE: 854 855 args->cmd = VT_GETACTIVE; 856 return ioctl(p, (struct ioctl_args *)args); 857 858 case LINUX_VT_ACTIVATE: 859 860 args->cmd = VT_ACTIVATE; 861 return ioctl(p, (struct ioctl_args *)args); 862 863 case LINUX_VT_WAITACTIVE: 864 865 args->cmd = VT_WAITACTIVE; 866 return ioctl(p, (struct ioctl_args *)args); 867 868 case LINUX_KDGKBMODE: 869 870 args->cmd = KDGKBMODE; 871 return ioctl(p, (struct ioctl_args *)args); 872 873 case LINUX_KDSKBMODE: 874 { 875 int kbdmode; 876 switch (args->arg) { 877 case LINUX_KBD_RAW: 878 kbdmode = K_RAW; 879 return (*func)(fp, KDSKBMODE, (caddr_t)&kbdmode, p); 880 case LINUX_KBD_XLATE: 881 kbdmode = K_XLATE; 882 return (*func)(fp, KDSKBMODE , (caddr_t)&kbdmode, p); 883 case LINUX_KBD_MEDIUMRAW: 884 kbdmode = K_RAW; 885 return (*func)(fp, KDSKBMODE , (caddr_t)&kbdmode, p); 886 default: 887 return EINVAL; 888 } 889 } 890 } 891 uprintf("LINUX: 'ioctl' fd=%d, typ=0x%x(%c), num=0x%x not implemented\n", 892 args->fd, (u_int)((args->cmd & 0xffff00) >> 8), 893 (int)((args->cmd & 0xffff00) >> 8), (u_int)(args->cmd & 0xff)); 894 return EINVAL; 895 } 896