The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/compat/linux/linux_ioctl.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

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

Cache object: 098a786f11b6b3d495582cfc00381807


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.