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-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
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 without 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 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/sysproto.h>
   35 #include <sys/cdio.h>
   36 #include <sys/dvdio.h>
   37 #include <sys/conf.h>
   38 #include <sys/disk.h>
   39 #include <sys/consio.h>
   40 #include <sys/ctype.h>
   41 #include <sys/fcntl.h>
   42 #include <sys/file.h>
   43 #include <sys/filedesc.h>
   44 #include <sys/filio.h>
   45 #include <sys/kbio.h>
   46 #include <sys/kernel.h>
   47 #include <sys/linker_set.h>
   48 #include <sys/lock.h>
   49 #include <sys/malloc.h>
   50 #include <sys/proc.h>
   51 #include <sys/sbuf.h>
   52 #include <sys/socket.h>
   53 #include <sys/sockio.h>
   54 #include <sys/soundcard.h>
   55 #include <sys/stdint.h>
   56 #include <sys/sx.h>
   57 #include <sys/tty.h>
   58 #include <sys/uio.h>
   59 #include <net/if.h>
   60 #include <net/if_dl.h>
   61 #include <net/if_types.h>
   62 
   63 #include "opt_compat.h"
   64 
   65 #ifdef COMPAT_LINUX32
   66 #include <machine/../linux32/linux.h>
   67 #include <machine/../linux32/linux32_proto.h>
   68 #else
   69 #include <machine/../linux/linux.h>
   70 #include <machine/../linux/linux_proto.h>
   71 #endif
   72 
   73 #include <compat/linux/linux_ioctl.h>
   74 #include <compat/linux/linux_mib.h>
   75 #include <compat/linux/linux_util.h>
   76 
   77 CTASSERT(LINUX_IFNAMSIZ == IFNAMSIZ);
   78 
   79 static linux_ioctl_function_t linux_ioctl_cdrom;
   80 static linux_ioctl_function_t linux_ioctl_vfat;
   81 static linux_ioctl_function_t linux_ioctl_console;
   82 static linux_ioctl_function_t linux_ioctl_hdio;
   83 static linux_ioctl_function_t linux_ioctl_disk;
   84 static linux_ioctl_function_t linux_ioctl_socket;
   85 static linux_ioctl_function_t linux_ioctl_sound;
   86 static linux_ioctl_function_t linux_ioctl_termio;
   87 static linux_ioctl_function_t linux_ioctl_private;
   88 static linux_ioctl_function_t linux_ioctl_drm;
   89 static linux_ioctl_function_t linux_ioctl_sg;
   90 static linux_ioctl_function_t linux_ioctl_special;
   91 
   92 static struct linux_ioctl_handler cdrom_handler =
   93 { linux_ioctl_cdrom, LINUX_IOCTL_CDROM_MIN, LINUX_IOCTL_CDROM_MAX };
   94 static struct linux_ioctl_handler vfat_handler =
   95 { linux_ioctl_vfat, LINUX_IOCTL_VFAT_MIN, LINUX_IOCTL_VFAT_MAX };
   96 static struct linux_ioctl_handler console_handler =
   97 { linux_ioctl_console, LINUX_IOCTL_CONSOLE_MIN, LINUX_IOCTL_CONSOLE_MAX };
   98 static struct linux_ioctl_handler hdio_handler =
   99 { linux_ioctl_hdio, LINUX_IOCTL_HDIO_MIN, LINUX_IOCTL_HDIO_MAX };
  100 static struct linux_ioctl_handler disk_handler =
  101 { linux_ioctl_disk, LINUX_IOCTL_DISK_MIN, LINUX_IOCTL_DISK_MAX };
  102 static struct linux_ioctl_handler socket_handler =
  103 { linux_ioctl_socket, LINUX_IOCTL_SOCKET_MIN, LINUX_IOCTL_SOCKET_MAX };
  104 static struct linux_ioctl_handler sound_handler =
  105 { linux_ioctl_sound, LINUX_IOCTL_SOUND_MIN, LINUX_IOCTL_SOUND_MAX };
  106 static struct linux_ioctl_handler termio_handler =
  107 { linux_ioctl_termio, LINUX_IOCTL_TERMIO_MIN, LINUX_IOCTL_TERMIO_MAX };
  108 static struct linux_ioctl_handler private_handler =
  109 { linux_ioctl_private, LINUX_IOCTL_PRIVATE_MIN, LINUX_IOCTL_PRIVATE_MAX };
  110 static struct linux_ioctl_handler drm_handler =
  111 { linux_ioctl_drm, LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX };
  112 static struct linux_ioctl_handler sg_handler =
  113 { linux_ioctl_sg, LINUX_IOCTL_SG_MIN, LINUX_IOCTL_SG_MAX };
  114 
  115 DATA_SET(linux_ioctl_handler_set, cdrom_handler);
  116 DATA_SET(linux_ioctl_handler_set, vfat_handler);
  117 DATA_SET(linux_ioctl_handler_set, console_handler);
  118 DATA_SET(linux_ioctl_handler_set, hdio_handler);
  119 DATA_SET(linux_ioctl_handler_set, disk_handler);
  120 DATA_SET(linux_ioctl_handler_set, socket_handler);
  121 DATA_SET(linux_ioctl_handler_set, sound_handler);
  122 DATA_SET(linux_ioctl_handler_set, termio_handler);
  123 DATA_SET(linux_ioctl_handler_set, private_handler);
  124 DATA_SET(linux_ioctl_handler_set, drm_handler);
  125 DATA_SET(linux_ioctl_handler_set, sg_handler);
  126 
  127 struct handler_element
  128 {
  129         TAILQ_ENTRY(handler_element) list;
  130         int     (*func)(struct thread *, struct linux_ioctl_args *);
  131         int     low, high, span;
  132 };
  133 
  134 static TAILQ_HEAD(, handler_element) handlers =
  135         TAILQ_HEAD_INITIALIZER(handlers);
  136 static struct sx linux_ioctl_sx;
  137 SX_SYSINIT(linux_ioctl, &linux_ioctl_sx, "linux ioctl handlers");
  138 
  139 /*
  140  * hdio related ioctls for VMWare support
  141  */
  142 
  143 struct linux_hd_geometry {
  144         u_int8_t        heads;
  145         u_int8_t        sectors;
  146         u_int16_t       cylinders;
  147         u_int32_t       start;
  148 };
  149 
  150 struct linux_hd_big_geometry {
  151         u_int8_t        heads;
  152         u_int8_t        sectors;
  153         u_int32_t       cylinders;
  154         u_int32_t       start;
  155 };
  156 
  157 static int
  158 linux_ioctl_hdio(struct thread *td, struct linux_ioctl_args *args)
  159 {
  160         struct file *fp;
  161         int error;
  162         u_int sectorsize, fwcylinders, fwheads, fwsectors;
  163         off_t mediasize, bytespercyl;
  164 
  165         if ((error = fget(td, args->fd, &fp)) != 0)
  166                 return (error);
  167         switch (args->cmd & 0xffff) {
  168         case LINUX_HDIO_GET_GEO:
  169         case LINUX_HDIO_GET_GEO_BIG:
  170                 error = fo_ioctl(fp, DIOCGMEDIASIZE,
  171                         (caddr_t)&mediasize, td->td_ucred, td);
  172                 if (!error)
  173                         error = fo_ioctl(fp, DIOCGSECTORSIZE,
  174                                 (caddr_t)&sectorsize, td->td_ucred, td);
  175                 if (!error)
  176                         error = fo_ioctl(fp, DIOCGFWHEADS,
  177                                 (caddr_t)&fwheads, td->td_ucred, td);
  178                 if (!error)
  179                         error = fo_ioctl(fp, DIOCGFWSECTORS,
  180                                 (caddr_t)&fwsectors, td->td_ucred, td);
  181                 /*
  182                  * XXX: DIOCGFIRSTOFFSET is not yet implemented, so
  183                  * so pretend that GEOM always says 0. This is NOT VALID
  184                  * for slices or partitions, only the per-disk raw devices.
  185                  */
  186 
  187                 fdrop(fp, td);
  188                 if (error)
  189                         return (error);
  190                 /*
  191                  * 1. Calculate the number of bytes in a cylinder,
  192                  *    given the firmware's notion of heads and sectors
  193                  *    per cylinder.
  194                  * 2. Calculate the number of cylinders, given the total
  195                  *    size of the media.
  196                  * All internal calculations should have 64-bit precision.
  197                  */
  198                 bytespercyl = (off_t) sectorsize * fwheads * fwsectors;
  199                 fwcylinders = mediasize / bytespercyl;
  200 #if defined(DEBUG)
  201                 linux_msg(td, "HDIO_GET_GEO: mediasize %jd, c/h/s %d/%d/%d, "
  202                           "bpc %jd",
  203                           (intmax_t)mediasize, fwcylinders, fwheads, fwsectors, 
  204                           (intmax_t)bytespercyl);
  205 #endif
  206                 if ((args->cmd & 0xffff) == LINUX_HDIO_GET_GEO) {
  207                         struct linux_hd_geometry hdg;
  208 
  209                         hdg.cylinders = fwcylinders;
  210                         hdg.heads = fwheads;
  211                         hdg.sectors = fwsectors;
  212                         hdg.start = 0;
  213                         error = copyout(&hdg, (void *)args->arg, sizeof(hdg));
  214                 } else if ((args->cmd & 0xffff) == LINUX_HDIO_GET_GEO_BIG) {
  215                         struct linux_hd_big_geometry hdbg;
  216 
  217                         hdbg.cylinders = fwcylinders;
  218                         hdbg.heads = fwheads;
  219                         hdbg.sectors = fwsectors;
  220                         hdbg.start = 0;
  221                         error = copyout(&hdbg, (void *)args->arg, sizeof(hdbg));
  222                 }
  223                 return (error);
  224                 break;
  225         default:
  226                 /* XXX */
  227                 linux_msg(td,
  228                         "ioctl fd=%d, cmd=0x%x ('%c',%d) is not implemented",
  229                         args->fd, (int)(args->cmd & 0xffff),
  230                         (int)(args->cmd & 0xff00) >> 8,
  231                         (int)(args->cmd & 0xff));
  232                 break;
  233         }
  234         fdrop(fp, td);
  235         return (ENOIOCTL);
  236 }
  237 
  238 static int
  239 linux_ioctl_disk(struct thread *td, struct linux_ioctl_args *args)
  240 {
  241         struct file *fp;
  242         int error;
  243         u_int sectorsize;
  244         off_t mediasize;
  245 
  246         if ((error = fget(td, args->fd, &fp)) != 0)
  247                 return (error);
  248         switch (args->cmd & 0xffff) {
  249         case LINUX_BLKGETSIZE:
  250                 error = fo_ioctl(fp, DIOCGSECTORSIZE,
  251                     (caddr_t)&sectorsize, td->td_ucred, td);
  252                 if (!error)
  253                         error = fo_ioctl(fp, DIOCGMEDIASIZE,
  254                             (caddr_t)&mediasize, td->td_ucred, td);
  255                 fdrop(fp, td);
  256                 if (error)
  257                         return (error);
  258                 sectorsize = mediasize / sectorsize;
  259                 /*
  260                  * XXX: How do we know we return the right size of integer ?
  261                  */
  262                 return (copyout(&sectorsize, (void *)args->arg,
  263                     sizeof(sectorsize)));
  264                 break;
  265         }
  266         fdrop(fp, td);
  267         return (ENOIOCTL);
  268 }
  269 
  270 /*
  271  * termio related ioctls
  272  */
  273 
  274 struct linux_termio {
  275         unsigned short c_iflag;
  276         unsigned short c_oflag;
  277         unsigned short c_cflag;
  278         unsigned short c_lflag;
  279         unsigned char c_line;
  280         unsigned char c_cc[LINUX_NCC];
  281 };
  282 
  283 struct linux_termios {
  284         unsigned int c_iflag;
  285         unsigned int c_oflag;
  286         unsigned int c_cflag;
  287         unsigned int c_lflag;
  288         unsigned char c_line;
  289         unsigned char c_cc[LINUX_NCCS];
  290 };
  291 
  292 struct linux_winsize {
  293         unsigned short ws_row, ws_col;
  294         unsigned short ws_xpixel, ws_ypixel;
  295 };
  296 
  297 static struct speedtab sptab[] = {
  298         { B0, LINUX_B0 }, { B50, LINUX_B50 },
  299         { B75, LINUX_B75 }, { B110, LINUX_B110 },
  300         { B134, LINUX_B134 }, { B150, LINUX_B150 },
  301         { B200, LINUX_B200 }, { B300, LINUX_B300 },
  302         { B600, LINUX_B600 }, { B1200, LINUX_B1200 },
  303         { B1800, LINUX_B1800 }, { B2400, LINUX_B2400 },
  304         { B4800, LINUX_B4800 }, { B9600, LINUX_B9600 },
  305         { B19200, LINUX_B19200 }, { B38400, LINUX_B38400 },
  306         { B57600, LINUX_B57600 }, { B115200, LINUX_B115200 },
  307         {-1, -1 }
  308 };
  309 
  310 struct linux_serial_struct {
  311         int     type;
  312         int     line;
  313         int     port;
  314         int     irq;
  315         int     flags;
  316         int     xmit_fifo_size;
  317         int     custom_divisor;
  318         int     baud_base;
  319         unsigned short close_delay;
  320         char    reserved_char[2];
  321         int     hub6;
  322         unsigned short closing_wait;
  323         unsigned short closing_wait2;
  324         int     reserved[4];
  325 };
  326 
  327 static int
  328 linux_to_bsd_speed(int code, struct speedtab *table)
  329 {
  330         for ( ; table->sp_code != -1; table++)
  331                 if (table->sp_code == code)
  332                         return (table->sp_speed);
  333         return -1;
  334 }
  335 
  336 static int
  337 bsd_to_linux_speed(int speed, struct speedtab *table)
  338 {
  339         for ( ; table->sp_speed != -1; table++)
  340                 if (table->sp_speed == speed)
  341                         return (table->sp_code);
  342         return -1;
  343 }
  344 
  345 static void
  346 bsd_to_linux_termios(struct termios *bios, struct linux_termios *lios)
  347 {
  348         int i;
  349 
  350 #ifdef DEBUG
  351         if (ldebug(ioctl)) {
  352                 printf("LINUX: BSD termios structure (input):\n");
  353                 printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n",
  354                     bios->c_iflag, bios->c_oflag, bios->c_cflag, bios->c_lflag,
  355                     bios->c_ispeed, bios->c_ospeed);
  356                 printf("c_cc ");
  357                 for (i=0; i<NCCS; i++)
  358                         printf("%02x ", bios->c_cc[i]);
  359                 printf("\n");
  360         }
  361 #endif
  362 
  363         lios->c_iflag = 0;
  364         if (bios->c_iflag & IGNBRK)
  365                 lios->c_iflag |= LINUX_IGNBRK;
  366         if (bios->c_iflag & BRKINT)
  367                 lios->c_iflag |= LINUX_BRKINT;
  368         if (bios->c_iflag & IGNPAR)
  369                 lios->c_iflag |= LINUX_IGNPAR;
  370         if (bios->c_iflag & PARMRK)
  371                 lios->c_iflag |= LINUX_PARMRK;
  372         if (bios->c_iflag & INPCK)
  373                 lios->c_iflag |= LINUX_INPCK;
  374         if (bios->c_iflag & ISTRIP)
  375                 lios->c_iflag |= LINUX_ISTRIP;
  376         if (bios->c_iflag & INLCR)
  377                 lios->c_iflag |= LINUX_INLCR;
  378         if (bios->c_iflag & IGNCR)
  379                 lios->c_iflag |= LINUX_IGNCR;
  380         if (bios->c_iflag & ICRNL)
  381                 lios->c_iflag |= LINUX_ICRNL;
  382         if (bios->c_iflag & IXON)
  383                 lios->c_iflag |= LINUX_IXON;
  384         if (bios->c_iflag & IXANY)
  385                 lios->c_iflag |= LINUX_IXANY;
  386         if (bios->c_iflag & IXOFF)
  387                 lios->c_iflag |= LINUX_IXOFF;
  388         if (bios->c_iflag & IMAXBEL)
  389                 lios->c_iflag |= LINUX_IMAXBEL;
  390 
  391         lios->c_oflag = 0;
  392         if (bios->c_oflag & OPOST)
  393                 lios->c_oflag |= LINUX_OPOST;
  394         if (bios->c_oflag & ONLCR)
  395                 lios->c_oflag |= LINUX_ONLCR;
  396         if (bios->c_oflag & OXTABS)
  397                 lios->c_oflag |= LINUX_XTABS;
  398 
  399         lios->c_cflag = bsd_to_linux_speed(bios->c_ispeed, sptab);
  400         lios->c_cflag |= (bios->c_cflag & CSIZE) >> 4;
  401         if (bios->c_cflag & CSTOPB)
  402                 lios->c_cflag |= LINUX_CSTOPB;
  403         if (bios->c_cflag & CREAD)
  404                 lios->c_cflag |= LINUX_CREAD;
  405         if (bios->c_cflag & PARENB)
  406                 lios->c_cflag |= LINUX_PARENB;
  407         if (bios->c_cflag & PARODD)
  408                 lios->c_cflag |= LINUX_PARODD;
  409         if (bios->c_cflag & HUPCL)
  410                 lios->c_cflag |= LINUX_HUPCL;
  411         if (bios->c_cflag & CLOCAL)
  412                 lios->c_cflag |= LINUX_CLOCAL;
  413         if (bios->c_cflag & CRTSCTS)
  414                 lios->c_cflag |= LINUX_CRTSCTS;
  415 
  416         lios->c_lflag = 0;
  417         if (bios->c_lflag & ISIG)
  418                 lios->c_lflag |= LINUX_ISIG;
  419         if (bios->c_lflag & ICANON)
  420                 lios->c_lflag |= LINUX_ICANON;
  421         if (bios->c_lflag & ECHO)
  422                 lios->c_lflag |= LINUX_ECHO;
  423         if (bios->c_lflag & ECHOE)
  424                 lios->c_lflag |= LINUX_ECHOE;
  425         if (bios->c_lflag & ECHOK)
  426                 lios->c_lflag |= LINUX_ECHOK;
  427         if (bios->c_lflag & ECHONL)
  428                 lios->c_lflag |= LINUX_ECHONL;
  429         if (bios->c_lflag & NOFLSH)
  430                 lios->c_lflag |= LINUX_NOFLSH;
  431         if (bios->c_lflag & TOSTOP)
  432                 lios->c_lflag |= LINUX_TOSTOP;
  433         if (bios->c_lflag & ECHOCTL)
  434                 lios->c_lflag |= LINUX_ECHOCTL;
  435         if (bios->c_lflag & ECHOPRT)
  436                 lios->c_lflag |= LINUX_ECHOPRT;
  437         if (bios->c_lflag & ECHOKE)
  438                 lios->c_lflag |= LINUX_ECHOKE;
  439         if (bios->c_lflag & FLUSHO)
  440                 lios->c_lflag |= LINUX_FLUSHO;
  441         if (bios->c_lflag & PENDIN)
  442                 lios->c_lflag |= LINUX_PENDIN;
  443         if (bios->c_lflag & IEXTEN)
  444                 lios->c_lflag |= LINUX_IEXTEN;
  445 
  446         for (i=0; i<LINUX_NCCS; i++)
  447                 lios->c_cc[i] = LINUX_POSIX_VDISABLE;
  448         lios->c_cc[LINUX_VINTR] = bios->c_cc[VINTR];
  449         lios->c_cc[LINUX_VQUIT] = bios->c_cc[VQUIT];
  450         lios->c_cc[LINUX_VERASE] = bios->c_cc[VERASE];
  451         lios->c_cc[LINUX_VKILL] = bios->c_cc[VKILL];
  452         lios->c_cc[LINUX_VEOF] = bios->c_cc[VEOF];
  453         lios->c_cc[LINUX_VEOL] = bios->c_cc[VEOL];
  454         lios->c_cc[LINUX_VMIN] = bios->c_cc[VMIN];
  455         lios->c_cc[LINUX_VTIME] = bios->c_cc[VTIME];
  456         lios->c_cc[LINUX_VEOL2] = bios->c_cc[VEOL2];
  457         lios->c_cc[LINUX_VSUSP] = bios->c_cc[VSUSP];
  458         lios->c_cc[LINUX_VSTART] = bios->c_cc[VSTART];
  459         lios->c_cc[LINUX_VSTOP] = bios->c_cc[VSTOP];
  460         lios->c_cc[LINUX_VREPRINT] = bios->c_cc[VREPRINT];
  461         lios->c_cc[LINUX_VDISCARD] = bios->c_cc[VDISCARD];
  462         lios->c_cc[LINUX_VWERASE] = bios->c_cc[VWERASE];
  463         lios->c_cc[LINUX_VLNEXT] = bios->c_cc[VLNEXT];
  464 
  465         for (i=0; i<LINUX_NCCS; i++) {
  466                 if (i != LINUX_VMIN && i != LINUX_VTIME &&
  467                     lios->c_cc[i] == _POSIX_VDISABLE)
  468                         lios->c_cc[i] = LINUX_POSIX_VDISABLE;
  469         }
  470         lios->c_line = 0;
  471 
  472 #ifdef DEBUG
  473         if (ldebug(ioctl)) {
  474                 printf("LINUX: LINUX termios structure (output):\n");
  475                 printf("i=%08x o=%08x c=%08x l=%08x line=%d\n",
  476                     lios->c_iflag, lios->c_oflag, lios->c_cflag,
  477                     lios->c_lflag, (int)lios->c_line);
  478                 printf("c_cc ");
  479                 for (i=0; i<LINUX_NCCS; i++)
  480                         printf("%02x ", lios->c_cc[i]);
  481                 printf("\n");
  482         }
  483 #endif
  484 }
  485 
  486 static void
  487 linux_to_bsd_termios(struct linux_termios *lios, struct termios *bios)
  488 {
  489         int i;
  490 
  491 #ifdef DEBUG
  492         if (ldebug(ioctl)) {
  493                 printf("LINUX: LINUX termios structure (input):\n");
  494                 printf("i=%08x o=%08x c=%08x l=%08x line=%d\n",
  495                     lios->c_iflag, lios->c_oflag, lios->c_cflag,
  496                     lios->c_lflag, (int)lios->c_line);
  497                 printf("c_cc ");
  498                 for (i=0; i<LINUX_NCCS; i++)
  499                         printf("%02x ", lios->c_cc[i]);
  500                 printf("\n");
  501         }
  502 #endif
  503 
  504         bios->c_iflag = 0;
  505         if (lios->c_iflag & LINUX_IGNBRK)
  506                 bios->c_iflag |= IGNBRK;
  507         if (lios->c_iflag & LINUX_BRKINT)
  508                 bios->c_iflag |= BRKINT;
  509         if (lios->c_iflag & LINUX_IGNPAR)
  510                 bios->c_iflag |= IGNPAR;
  511         if (lios->c_iflag & LINUX_PARMRK)
  512                 bios->c_iflag |= PARMRK;
  513         if (lios->c_iflag & LINUX_INPCK)
  514                 bios->c_iflag |= INPCK;
  515         if (lios->c_iflag & LINUX_ISTRIP)
  516                 bios->c_iflag |= ISTRIP;
  517         if (lios->c_iflag & LINUX_INLCR)
  518                 bios->c_iflag |= INLCR;
  519         if (lios->c_iflag & LINUX_IGNCR)
  520                 bios->c_iflag |= IGNCR;
  521         if (lios->c_iflag & LINUX_ICRNL)
  522                 bios->c_iflag |= ICRNL;
  523         if (lios->c_iflag & LINUX_IXON)
  524                 bios->c_iflag |= IXON;
  525         if (lios->c_iflag & LINUX_IXANY)
  526                 bios->c_iflag |= IXANY;
  527         if (lios->c_iflag & LINUX_IXOFF)
  528                 bios->c_iflag |= IXOFF;
  529         if (lios->c_iflag & LINUX_IMAXBEL)
  530                 bios->c_iflag |= IMAXBEL;
  531 
  532         bios->c_oflag = 0;
  533         if (lios->c_oflag & LINUX_OPOST)
  534                 bios->c_oflag |= OPOST;
  535         if (lios->c_oflag & LINUX_ONLCR)
  536                 bios->c_oflag |= ONLCR;
  537         if (lios->c_oflag & LINUX_XTABS)
  538                 bios->c_oflag |= OXTABS;
  539 
  540         bios->c_cflag = (lios->c_cflag & LINUX_CSIZE) << 4;
  541         if (lios->c_cflag & LINUX_CSTOPB)
  542                 bios->c_cflag |= CSTOPB;
  543         if (lios->c_cflag & LINUX_CREAD)
  544                 bios->c_cflag |= CREAD;
  545         if (lios->c_cflag & LINUX_PARENB)
  546                 bios->c_cflag |= PARENB;
  547         if (lios->c_cflag & LINUX_PARODD)
  548                 bios->c_cflag |= PARODD;
  549         if (lios->c_cflag & LINUX_HUPCL)
  550                 bios->c_cflag |= HUPCL;
  551         if (lios->c_cflag & LINUX_CLOCAL)
  552                 bios->c_cflag |= CLOCAL;
  553         if (lios->c_cflag & LINUX_CRTSCTS)
  554                 bios->c_cflag |= CRTSCTS;
  555 
  556         bios->c_lflag = 0;
  557         if (lios->c_lflag & LINUX_ISIG)
  558                 bios->c_lflag |= ISIG;
  559         if (lios->c_lflag & LINUX_ICANON)
  560                 bios->c_lflag |= ICANON;
  561         if (lios->c_lflag & LINUX_ECHO)
  562                 bios->c_lflag |= ECHO;
  563         if (lios->c_lflag & LINUX_ECHOE)
  564                 bios->c_lflag |= ECHOE;
  565         if (lios->c_lflag & LINUX_ECHOK)
  566                 bios->c_lflag |= ECHOK;
  567         if (lios->c_lflag & LINUX_ECHONL)
  568                 bios->c_lflag |= ECHONL;
  569         if (lios->c_lflag & LINUX_NOFLSH)
  570                 bios->c_lflag |= NOFLSH;
  571         if (lios->c_lflag & LINUX_TOSTOP)
  572                 bios->c_lflag |= TOSTOP;
  573         if (lios->c_lflag & LINUX_ECHOCTL)
  574                 bios->c_lflag |= ECHOCTL;
  575         if (lios->c_lflag & LINUX_ECHOPRT)
  576                 bios->c_lflag |= ECHOPRT;
  577         if (lios->c_lflag & LINUX_ECHOKE)
  578                 bios->c_lflag |= ECHOKE;
  579         if (lios->c_lflag & LINUX_FLUSHO)
  580                 bios->c_lflag |= FLUSHO;
  581         if (lios->c_lflag & LINUX_PENDIN)
  582                 bios->c_lflag |= PENDIN;
  583         if (lios->c_lflag & LINUX_IEXTEN)
  584                 bios->c_lflag |= IEXTEN;
  585 
  586         for (i=0; i<NCCS; i++)
  587                 bios->c_cc[i] = _POSIX_VDISABLE;
  588         bios->c_cc[VINTR] = lios->c_cc[LINUX_VINTR];
  589         bios->c_cc[VQUIT] = lios->c_cc[LINUX_VQUIT];
  590         bios->c_cc[VERASE] = lios->c_cc[LINUX_VERASE];
  591         bios->c_cc[VKILL] = lios->c_cc[LINUX_VKILL];
  592         bios->c_cc[VEOF] = lios->c_cc[LINUX_VEOF];
  593         bios->c_cc[VEOL] = lios->c_cc[LINUX_VEOL];
  594         bios->c_cc[VMIN] = lios->c_cc[LINUX_VMIN];
  595         bios->c_cc[VTIME] = lios->c_cc[LINUX_VTIME];
  596         bios->c_cc[VEOL2] = lios->c_cc[LINUX_VEOL2];
  597         bios->c_cc[VSUSP] = lios->c_cc[LINUX_VSUSP];
  598         bios->c_cc[VSTART] = lios->c_cc[LINUX_VSTART];
  599         bios->c_cc[VSTOP] = lios->c_cc[LINUX_VSTOP];
  600         bios->c_cc[VREPRINT] = lios->c_cc[LINUX_VREPRINT];
  601         bios->c_cc[VDISCARD] = lios->c_cc[LINUX_VDISCARD];
  602         bios->c_cc[VWERASE] = lios->c_cc[LINUX_VWERASE];
  603         bios->c_cc[VLNEXT] = lios->c_cc[LINUX_VLNEXT];
  604 
  605         for (i=0; i<NCCS; i++) {
  606                 if (i != VMIN && i != VTIME &&
  607                     bios->c_cc[i] == LINUX_POSIX_VDISABLE)
  608                         bios->c_cc[i] = _POSIX_VDISABLE;
  609         }
  610 
  611         bios->c_ispeed = bios->c_ospeed =
  612             linux_to_bsd_speed(lios->c_cflag & LINUX_CBAUD, sptab);
  613 
  614 #ifdef DEBUG
  615         if (ldebug(ioctl)) {
  616                 printf("LINUX: BSD termios structure (output):\n");
  617                 printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n",
  618                     bios->c_iflag, bios->c_oflag, bios->c_cflag, bios->c_lflag,
  619                     bios->c_ispeed, bios->c_ospeed);
  620                 printf("c_cc ");
  621                 for (i=0; i<NCCS; i++)
  622                         printf("%02x ", bios->c_cc[i]);
  623                 printf("\n");
  624         }
  625 #endif
  626 }
  627 
  628 static void
  629 bsd_to_linux_termio(struct termios *bios, struct linux_termio *lio)
  630 {
  631         struct linux_termios lios;
  632 
  633         bsd_to_linux_termios(bios, &lios);
  634         lio->c_iflag = lios.c_iflag;
  635         lio->c_oflag = lios.c_oflag;
  636         lio->c_cflag = lios.c_cflag;
  637         lio->c_lflag = lios.c_lflag;
  638         lio->c_line  = lios.c_line;
  639         memcpy(lio->c_cc, lios.c_cc, LINUX_NCC);
  640 }
  641 
  642 static void
  643 linux_to_bsd_termio(struct linux_termio *lio, struct termios *bios)
  644 {
  645         struct linux_termios lios;
  646         int i;
  647 
  648         lios.c_iflag = lio->c_iflag;
  649         lios.c_oflag = lio->c_oflag;
  650         lios.c_cflag = lio->c_cflag;
  651         lios.c_lflag = lio->c_lflag;
  652         for (i=LINUX_NCC; i<LINUX_NCCS; i++)
  653                 lios.c_cc[i] = LINUX_POSIX_VDISABLE;
  654         memcpy(lios.c_cc, lio->c_cc, LINUX_NCC);
  655         linux_to_bsd_termios(&lios, bios);
  656 }
  657 
  658 static int
  659 linux_ioctl_termio(struct thread *td, struct linux_ioctl_args *args)
  660 {
  661         struct termios bios;
  662         struct linux_termios lios;
  663         struct linux_termio lio;
  664         struct file *fp;
  665         int error;
  666 
  667         if ((error = fget(td, args->fd, &fp)) != 0)
  668                 return (error);
  669 
  670         switch (args->cmd & 0xffff) {
  671 
  672         case LINUX_TCGETS:
  673                 error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td->td_ucred,
  674                     td);
  675                 if (error)
  676                         break;
  677                 bsd_to_linux_termios(&bios, &lios);
  678                 error = copyout(&lios, (void *)args->arg, sizeof(lios));
  679                 break;
  680 
  681         case LINUX_TCSETS:
  682                 error = copyin((void *)args->arg, &lios, sizeof(lios));
  683                 if (error)
  684                         break;
  685                 linux_to_bsd_termios(&lios, &bios);
  686                 error = (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td->td_ucred,
  687                     td));
  688                 break;
  689 
  690         case LINUX_TCSETSW:
  691                 error = copyin((void *)args->arg, &lios, sizeof(lios));
  692                 if (error)
  693                         break;
  694                 linux_to_bsd_termios(&lios, &bios);
  695                 error = (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td->td_ucred,
  696                     td));
  697                 break;
  698 
  699         case LINUX_TCSETSF:
  700                 error = copyin((void *)args->arg, &lios, sizeof(lios));
  701                 if (error)
  702                         break;
  703                 linux_to_bsd_termios(&lios, &bios);
  704                 error = (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td->td_ucred,
  705                     td));
  706                 break;
  707 
  708         case LINUX_TCGETA:
  709                 error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td->td_ucred,
  710                     td);
  711                 if (error)
  712                         break;
  713                 bsd_to_linux_termio(&bios, &lio);
  714                 error = (copyout(&lio, (void *)args->arg, sizeof(lio)));
  715                 break;
  716 
  717         case LINUX_TCSETA:
  718                 error = copyin((void *)args->arg, &lio, sizeof(lio));
  719                 if (error)
  720                         break;
  721                 linux_to_bsd_termio(&lio, &bios);
  722                 error = (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td->td_ucred,
  723                     td));
  724                 break;
  725 
  726         case LINUX_TCSETAW:
  727                 error = copyin((void *)args->arg, &lio, sizeof(lio));
  728                 if (error)
  729                         break;
  730                 linux_to_bsd_termio(&lio, &bios);
  731                 error = (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td->td_ucred,
  732                     td));
  733                 break;
  734 
  735         case LINUX_TCSETAF:
  736                 error = copyin((void *)args->arg, &lio, sizeof(lio));
  737                 if (error)
  738                         break;
  739                 linux_to_bsd_termio(&lio, &bios);
  740                 error = (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td->td_ucred,
  741                     td));
  742                 break;
  743 
  744         /* LINUX_TCSBRK */
  745 
  746         case LINUX_TCXONC: {
  747                 switch (args->arg) {
  748                 case LINUX_TCOOFF:
  749                         args->cmd = TIOCSTOP;
  750                         break;
  751                 case LINUX_TCOON:
  752                         args->cmd = TIOCSTART;
  753                         break;
  754                 case LINUX_TCIOFF:
  755                 case LINUX_TCION: {
  756                         int c;
  757                         struct write_args wr;
  758                         error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios,
  759                             td->td_ucred, td);
  760                         if (error)
  761                                 break;
  762                         fdrop(fp, td);
  763                         c = (args->arg == LINUX_TCIOFF) ? VSTOP : VSTART;
  764                         c = bios.c_cc[c];
  765                         if (c != _POSIX_VDISABLE) {
  766                                 wr.fd = args->fd;
  767                                 wr.buf = &c;
  768                                 wr.nbyte = sizeof(c);
  769                                 return (write(td, &wr));
  770                         } else
  771                                 return (0);
  772                 }
  773                 default:
  774                         fdrop(fp, td);
  775                         return (EINVAL);
  776                 }
  777                 args->arg = 0;
  778                 error = (ioctl(td, (struct ioctl_args *)args));
  779                 break;
  780         }
  781 
  782         case LINUX_TCFLSH: {
  783                 int val;
  784                 switch (args->arg) {
  785                 case LINUX_TCIFLUSH:
  786                         val = FREAD;
  787                         break;
  788                 case LINUX_TCOFLUSH:
  789                         val = FWRITE;
  790                         break;
  791                 case LINUX_TCIOFLUSH:
  792                         val = FREAD | FWRITE;
  793                         break;
  794                 default:
  795                         fdrop(fp, td);
  796                         return (EINVAL);
  797                 }
  798                 error = (fo_ioctl(fp,TIOCFLUSH,(caddr_t)&val,td->td_ucred,td));
  799                 break;
  800         }
  801 
  802         case LINUX_TIOCEXCL:
  803                 args->cmd = TIOCEXCL;
  804                 error = (ioctl(td, (struct ioctl_args *)args));
  805                 break;
  806 
  807         case LINUX_TIOCNXCL:
  808                 args->cmd = TIOCNXCL;
  809                 error = (ioctl(td, (struct ioctl_args *)args));
  810                 break;
  811 
  812         case LINUX_TIOCSCTTY:
  813                 args->cmd = TIOCSCTTY;
  814                 error = (ioctl(td, (struct ioctl_args *)args));
  815                 break;
  816 
  817         case LINUX_TIOCGPGRP:
  818                 args->cmd = TIOCGPGRP;
  819                 error = (ioctl(td, (struct ioctl_args *)args));
  820                 break;
  821 
  822         case LINUX_TIOCSPGRP:
  823                 args->cmd = TIOCSPGRP;
  824                 error = (ioctl(td, (struct ioctl_args *)args));
  825                 break;
  826 
  827         /* LINUX_TIOCOUTQ */
  828         /* LINUX_TIOCSTI */
  829 
  830         case LINUX_TIOCGWINSZ:
  831                 args->cmd = TIOCGWINSZ;
  832                 error = (ioctl(td, (struct ioctl_args *)args));
  833                 break;
  834 
  835         case LINUX_TIOCSWINSZ:
  836                 args->cmd = TIOCSWINSZ;
  837                 error = (ioctl(td, (struct ioctl_args *)args));
  838                 break;
  839 
  840         case LINUX_TIOCMGET:
  841                 args->cmd = TIOCMGET;
  842                 error = (ioctl(td, (struct ioctl_args *)args));
  843                 break;
  844 
  845         case LINUX_TIOCMBIS:
  846                 args->cmd = TIOCMBIS;
  847                 error = (ioctl(td, (struct ioctl_args *)args));
  848                 break;
  849 
  850         case LINUX_TIOCMBIC:
  851                 args->cmd = TIOCMBIC;
  852                 error = (ioctl(td, (struct ioctl_args *)args));
  853                 break;
  854 
  855         case LINUX_TIOCMSET:
  856                 args->cmd = TIOCMSET;
  857                 error = (ioctl(td, (struct ioctl_args *)args));
  858                 break;
  859 
  860         /* TIOCGSOFTCAR */
  861         /* TIOCSSOFTCAR */
  862 
  863         case LINUX_FIONREAD: /* LINUX_TIOCINQ */
  864                 args->cmd = FIONREAD;
  865                 error = (ioctl(td, (struct ioctl_args *)args));
  866                 break;
  867 
  868         /* LINUX_TIOCLINUX */
  869 
  870         case LINUX_TIOCCONS:
  871                 args->cmd = TIOCCONS;
  872                 error = (ioctl(td, (struct ioctl_args *)args));
  873                 break;
  874 
  875         case LINUX_TIOCGSERIAL: {
  876                 struct linux_serial_struct lss;
  877                 lss.type = LINUX_PORT_16550A;
  878                 lss.flags = 0;
  879                 lss.close_delay = 0;
  880                 error = copyout(&lss, (void *)args->arg, sizeof(lss));
  881                 break;
  882         }
  883 
  884         case LINUX_TIOCSSERIAL: {
  885                 struct linux_serial_struct lss;
  886                 error = copyin((void *)args->arg, &lss, sizeof(lss));
  887                 if (error)
  888                         break;
  889                 /* XXX - It really helps to have an implementation that
  890                  * does nothing. NOT!
  891                  */
  892                 error = 0;
  893                 break;
  894         }
  895 
  896         /* LINUX_TIOCPKT */
  897 
  898         case LINUX_FIONBIO:
  899                 args->cmd = FIONBIO;
  900                 error = (ioctl(td, (struct ioctl_args *)args));
  901                 break;
  902 
  903         case LINUX_TIOCNOTTY:
  904                 args->cmd = TIOCNOTTY;
  905                 error = (ioctl(td, (struct ioctl_args *)args));
  906                 break;
  907 
  908         case LINUX_TIOCSETD: {
  909                 int line;
  910                 switch (args->arg) {
  911                 case LINUX_N_TTY:
  912                         line = TTYDISC;
  913                         break;
  914                 case LINUX_N_SLIP:
  915                         line = SLIPDISC;
  916                         break;
  917                 case LINUX_N_PPP:
  918                         line = PPPDISC;
  919                         break;
  920                 default:
  921                         fdrop(fp, td);
  922                         return (EINVAL);
  923                 }
  924                 error = (fo_ioctl(fp, TIOCSETD, (caddr_t)&line, td->td_ucred,
  925                     td));
  926                 break;
  927         }
  928 
  929         case LINUX_TIOCGETD: {
  930                 int linux_line;
  931                 int bsd_line = TTYDISC;
  932                 error = fo_ioctl(fp, TIOCGETD, (caddr_t)&bsd_line,
  933                     td->td_ucred, td);
  934                 if (error)
  935                         return (error);
  936                 switch (bsd_line) {
  937                 case TTYDISC:
  938                         linux_line = LINUX_N_TTY;
  939                         break;
  940                 case SLIPDISC:
  941                         linux_line = LINUX_N_SLIP;
  942                         break;
  943                 case PPPDISC:
  944                         linux_line = LINUX_N_PPP;
  945                         break;
  946                 default:
  947                         fdrop(fp, td);
  948                         return (EINVAL);
  949                 }
  950                 error = (copyout(&linux_line, (void *)args->arg, sizeof(int)));
  951                 break;
  952         }
  953 
  954         /* LINUX_TCSBRKP */
  955         /* LINUX_TIOCTTYGSTRUCT */
  956 
  957         case LINUX_FIONCLEX:
  958                 args->cmd = FIONCLEX;
  959                 error = (ioctl(td, (struct ioctl_args *)args));
  960                 break;
  961 
  962         case LINUX_FIOCLEX:
  963                 args->cmd = FIOCLEX;
  964                 error = (ioctl(td, (struct ioctl_args *)args));
  965                 break;
  966 
  967         case LINUX_FIOASYNC:
  968                 args->cmd = FIOASYNC;
  969                 error = (ioctl(td, (struct ioctl_args *)args));
  970                 break;
  971 
  972         /* LINUX_TIOCSERCONFIG */
  973         /* LINUX_TIOCSERGWILD */
  974         /* LINUX_TIOCSERSWILD */
  975         /* LINUX_TIOCGLCKTRMIOS */
  976         /* LINUX_TIOCSLCKTRMIOS */
  977 
  978         case LINUX_TIOCSBRK:
  979                 args->cmd = TIOCSBRK;
  980                 error = (ioctl(td, (struct ioctl_args *)args));
  981                 break;
  982 
  983         case LINUX_TIOCCBRK:
  984                 args->cmd = TIOCCBRK;
  985                 error = (ioctl(td, (struct ioctl_args *)args));
  986                 break;
  987         case LINUX_TIOCGPTN: {
  988                 int nb;
  989                 
  990                 error = fo_ioctl(fp, TIOCGPTN, (caddr_t)&nb, td->td_ucred, td);
  991                 if (!error)
  992                         error = copyout(&nb, (void *)args->arg,
  993                             sizeof(int));
  994                 break;
  995         }
  996         default:
  997                 error = ENOIOCTL;
  998                 break;
  999         }
 1000 
 1001         fdrop(fp, td);
 1002         return (error);
 1003 }
 1004 
 1005 /*
 1006  * CDROM related ioctls
 1007  */
 1008 
 1009 struct linux_cdrom_msf
 1010 {
 1011         u_char  cdmsf_min0;
 1012         u_char  cdmsf_sec0;
 1013         u_char  cdmsf_frame0;
 1014         u_char  cdmsf_min1;
 1015         u_char  cdmsf_sec1;
 1016         u_char  cdmsf_frame1;
 1017 };
 1018 
 1019 struct linux_cdrom_tochdr
 1020 {
 1021         u_char  cdth_trk0;
 1022         u_char  cdth_trk1;
 1023 };
 1024 
 1025 union linux_cdrom_addr
 1026 {
 1027         struct {
 1028                 u_char  minute;
 1029                 u_char  second;
 1030                 u_char  frame;
 1031         } msf;
 1032         int     lba;
 1033 };
 1034 
 1035 struct linux_cdrom_tocentry
 1036 {
 1037         u_char  cdte_track;
 1038         u_char  cdte_adr:4;
 1039         u_char  cdte_ctrl:4;
 1040         u_char  cdte_format;
 1041         union linux_cdrom_addr cdte_addr;
 1042         u_char  cdte_datamode;
 1043 };
 1044 
 1045 struct linux_cdrom_subchnl
 1046 {
 1047         u_char  cdsc_format;
 1048         u_char  cdsc_audiostatus;
 1049         u_char  cdsc_adr:4;
 1050         u_char  cdsc_ctrl:4;
 1051         u_char  cdsc_trk;
 1052         u_char  cdsc_ind;
 1053         union linux_cdrom_addr cdsc_absaddr;
 1054         union linux_cdrom_addr cdsc_reladdr;
 1055 };
 1056 
 1057 struct l_cdrom_read_audio {
 1058         union linux_cdrom_addr addr;
 1059         u_char          addr_format;
 1060         l_int           nframes;
 1061         u_char          *buf;
 1062 };
 1063 
 1064 struct l_dvd_layer {
 1065         u_char          book_version:4;
 1066         u_char          book_type:4;
 1067         u_char          min_rate:4;
 1068         u_char          disc_size:4;
 1069         u_char          layer_type:4;
 1070         u_char          track_path:1;
 1071         u_char          nlayers:2;
 1072         u_char          track_density:4;
 1073         u_char          linear_density:4;
 1074         u_char          bca:1;
 1075         u_int32_t       start_sector;
 1076         u_int32_t       end_sector;
 1077         u_int32_t       end_sector_l0;
 1078 };
 1079 
 1080 struct l_dvd_physical {
 1081         u_char          type;
 1082         u_char          layer_num;
 1083         struct l_dvd_layer layer[4];
 1084 };
 1085 
 1086 struct l_dvd_copyright {
 1087         u_char          type;
 1088         u_char          layer_num;
 1089         u_char          cpst;
 1090         u_char          rmi;
 1091 };
 1092 
 1093 struct l_dvd_disckey {
 1094         u_char          type;
 1095         l_uint          agid:2;
 1096         u_char          value[2048];
 1097 };
 1098 
 1099 struct l_dvd_bca {
 1100         u_char          type;
 1101         l_int           len;
 1102         u_char          value[188];
 1103 };
 1104 
 1105 struct l_dvd_manufact {
 1106         u_char          type;
 1107         u_char          layer_num;
 1108         l_int           len;
 1109         u_char          value[2048];
 1110 };
 1111 
 1112 typedef union {
 1113         u_char                  type;
 1114         struct l_dvd_physical   physical;
 1115         struct l_dvd_copyright  copyright;
 1116         struct l_dvd_disckey    disckey;
 1117         struct l_dvd_bca        bca;
 1118         struct l_dvd_manufact   manufact;
 1119 } l_dvd_struct;
 1120 
 1121 typedef u_char l_dvd_key[5];
 1122 typedef u_char l_dvd_challenge[10];
 1123 
 1124 struct l_dvd_lu_send_agid {
 1125         u_char          type;
 1126         l_uint          agid:2;
 1127 };
 1128 
 1129 struct l_dvd_host_send_challenge {
 1130         u_char          type;
 1131         l_uint          agid:2;
 1132         l_dvd_challenge chal;
 1133 };
 1134 
 1135 struct l_dvd_send_key {
 1136         u_char          type;
 1137         l_uint          agid:2;
 1138         l_dvd_key       key;
 1139 };
 1140 
 1141 struct l_dvd_lu_send_challenge {
 1142         u_char          type;
 1143         l_uint          agid:2;
 1144         l_dvd_challenge chal;
 1145 };
 1146 
 1147 struct l_dvd_lu_send_title_key {
 1148         u_char          type;
 1149         l_uint          agid:2;
 1150         l_dvd_key       title_key;
 1151         l_int           lba;
 1152         l_uint          cpm:1;
 1153         l_uint          cp_sec:1;
 1154         l_uint          cgms:2;
 1155 };
 1156 
 1157 struct l_dvd_lu_send_asf {
 1158         u_char          type;
 1159         l_uint          agid:2;
 1160         l_uint          asf:1;
 1161 };
 1162 
 1163 struct l_dvd_host_send_rpcstate {
 1164         u_char          type;
 1165         u_char          pdrc;
 1166 };
 1167 
 1168 struct l_dvd_lu_send_rpcstate {
 1169         u_char          type:2;
 1170         u_char          vra:3;
 1171         u_char          ucca:3;
 1172         u_char          region_mask;
 1173         u_char          rpc_scheme;
 1174 };
 1175 
 1176 typedef union {
 1177         u_char                          type;
 1178         struct l_dvd_lu_send_agid       lsa;
 1179         struct l_dvd_host_send_challenge hsc;
 1180         struct l_dvd_send_key           lsk;
 1181         struct l_dvd_lu_send_challenge  lsc;
 1182         struct l_dvd_send_key           hsk;
 1183         struct l_dvd_lu_send_title_key  lstk;
 1184         struct l_dvd_lu_send_asf        lsasf;
 1185         struct l_dvd_host_send_rpcstate hrpcs;
 1186         struct l_dvd_lu_send_rpcstate   lrpcs;
 1187 } l_dvd_authinfo;
 1188 
 1189 static void
 1190 bsd_to_linux_msf_lba(u_char af, union msf_lba *bp, union linux_cdrom_addr *lp)
 1191 {
 1192         if (af == CD_LBA_FORMAT)
 1193                 lp->lba = bp->lba;
 1194         else {
 1195                 lp->msf.minute = bp->msf.minute;
 1196                 lp->msf.second = bp->msf.second;
 1197                 lp->msf.frame = bp->msf.frame;
 1198         }
 1199 }
 1200 
 1201 static void
 1202 set_linux_cdrom_addr(union linux_cdrom_addr *addr, int format, int lba)
 1203 {
 1204         if (format == LINUX_CDROM_MSF) {
 1205                 addr->msf.frame = lba % 75;
 1206                 lba /= 75;
 1207                 lba += 2;
 1208                 addr->msf.second = lba % 60;
 1209                 addr->msf.minute = lba / 60;
 1210         } else
 1211                 addr->lba = lba;
 1212 }
 1213 
 1214 static int
 1215 linux_to_bsd_dvd_struct(l_dvd_struct *lp, struct dvd_struct *bp)
 1216 {
 1217         bp->format = lp->type;
 1218         switch (bp->format) {
 1219         case DVD_STRUCT_PHYSICAL:
 1220                 if (bp->layer_num >= 4)
 1221                         return (EINVAL);
 1222                 bp->layer_num = lp->physical.layer_num;
 1223                 break;
 1224         case DVD_STRUCT_COPYRIGHT:
 1225                 bp->layer_num = lp->copyright.layer_num;
 1226                 break;
 1227         case DVD_STRUCT_DISCKEY:
 1228                 bp->agid = lp->disckey.agid;
 1229                 break;
 1230         case DVD_STRUCT_BCA:
 1231         case DVD_STRUCT_MANUFACT:
 1232                 break;
 1233         default:
 1234                 return (EINVAL);
 1235         }
 1236         return (0);
 1237 }
 1238 
 1239 static int
 1240 bsd_to_linux_dvd_struct(struct dvd_struct *bp, l_dvd_struct *lp)
 1241 {
 1242         switch (bp->format) {
 1243         case DVD_STRUCT_PHYSICAL: {
 1244                 struct dvd_layer *blp = (struct dvd_layer *)bp->data;
 1245                 struct l_dvd_layer *llp = &lp->physical.layer[bp->layer_num];
 1246                 memset(llp, 0, sizeof(*llp));
 1247                 llp->book_version = blp->book_version;
 1248                 llp->book_type = blp->book_type;
 1249                 llp->min_rate = blp->max_rate;
 1250                 llp->disc_size = blp->disc_size;
 1251                 llp->layer_type = blp->layer_type;
 1252                 llp->track_path = blp->track_path;
 1253                 llp->nlayers = blp->nlayers;
 1254                 llp->track_density = blp->track_density;
 1255                 llp->linear_density = blp->linear_density;
 1256                 llp->bca = blp->bca;
 1257                 llp->start_sector = blp->start_sector;
 1258                 llp->end_sector = blp->end_sector;
 1259                 llp->end_sector_l0 = blp->end_sector_l0;
 1260                 break;
 1261         }
 1262         case DVD_STRUCT_COPYRIGHT:
 1263                 lp->copyright.cpst = bp->cpst;
 1264                 lp->copyright.rmi = bp->rmi;
 1265                 break;
 1266         case DVD_STRUCT_DISCKEY:
 1267                 memcpy(lp->disckey.value, bp->data, sizeof(lp->disckey.value));
 1268                 break;
 1269         case DVD_STRUCT_BCA:
 1270                 lp->bca.len = bp->length;
 1271                 memcpy(lp->bca.value, bp->data, sizeof(lp->bca.value));
 1272                 break;
 1273         case DVD_STRUCT_MANUFACT:
 1274                 lp->manufact.len = bp->length;
 1275                 memcpy(lp->manufact.value, bp->data,
 1276                     sizeof(lp->manufact.value));
 1277                 /* lp->manufact.layer_num is unused in linux (redhat 7.0) */
 1278                 break;
 1279         default:
 1280                 return (EINVAL);
 1281         }
 1282         return (0);
 1283 }
 1284 
 1285 static int
 1286 linux_to_bsd_dvd_authinfo(l_dvd_authinfo *lp, int *bcode,
 1287     struct dvd_authinfo *bp)
 1288 {
 1289         switch (lp->type) {
 1290         case LINUX_DVD_LU_SEND_AGID:
 1291                 *bcode = DVDIOCREPORTKEY;
 1292                 bp->format = DVD_REPORT_AGID;
 1293                 bp->agid = lp->lsa.agid;
 1294                 break;
 1295         case LINUX_DVD_HOST_SEND_CHALLENGE:
 1296                 *bcode = DVDIOCSENDKEY;
 1297                 bp->format = DVD_SEND_CHALLENGE;
 1298                 bp->agid = lp->hsc.agid;
 1299                 memcpy(bp->keychal, lp->hsc.chal, 10);
 1300                 break;
 1301         case LINUX_DVD_LU_SEND_KEY1:
 1302                 *bcode = DVDIOCREPORTKEY;
 1303                 bp->format = DVD_REPORT_KEY1;
 1304                 bp->agid = lp->lsk.agid;
 1305                 break;
 1306         case LINUX_DVD_LU_SEND_CHALLENGE:
 1307                 *bcode = DVDIOCREPORTKEY;
 1308                 bp->format = DVD_REPORT_CHALLENGE;
 1309                 bp->agid = lp->lsc.agid;
 1310                 break;
 1311         case LINUX_DVD_HOST_SEND_KEY2:
 1312                 *bcode = DVDIOCSENDKEY;
 1313                 bp->format = DVD_SEND_KEY2;
 1314                 bp->agid = lp->hsk.agid;
 1315                 memcpy(bp->keychal, lp->hsk.key, 5);
 1316                 break;
 1317         case LINUX_DVD_LU_SEND_TITLE_KEY:
 1318                 *bcode = DVDIOCREPORTKEY;
 1319                 bp->format = DVD_REPORT_TITLE_KEY;
 1320                 bp->agid = lp->lstk.agid;
 1321                 bp->lba = lp->lstk.lba;
 1322                 break;
 1323         case LINUX_DVD_LU_SEND_ASF:
 1324                 *bcode = DVDIOCREPORTKEY;
 1325                 bp->format = DVD_REPORT_ASF;
 1326                 bp->agid = lp->lsasf.agid;
 1327                 break;
 1328         case LINUX_DVD_INVALIDATE_AGID:
 1329                 *bcode = DVDIOCREPORTKEY;
 1330                 bp->format = DVD_INVALIDATE_AGID;
 1331                 bp->agid = lp->lsa.agid;
 1332                 break;
 1333         case LINUX_DVD_LU_SEND_RPC_STATE:
 1334                 *bcode = DVDIOCREPORTKEY;
 1335                 bp->format = DVD_REPORT_RPC;
 1336                 break;
 1337         case LINUX_DVD_HOST_SEND_RPC_STATE:
 1338                 *bcode = DVDIOCSENDKEY;
 1339                 bp->format = DVD_SEND_RPC;
 1340                 bp->region = lp->hrpcs.pdrc;
 1341                 break;
 1342         default:
 1343                 return (EINVAL);
 1344         }
 1345         return (0);
 1346 }
 1347 
 1348 static int
 1349 bsd_to_linux_dvd_authinfo(struct dvd_authinfo *bp, l_dvd_authinfo *lp)
 1350 {
 1351         switch (lp->type) {
 1352         case LINUX_DVD_LU_SEND_AGID:
 1353                 lp->lsa.agid = bp->agid;
 1354                 break;
 1355         case LINUX_DVD_HOST_SEND_CHALLENGE:
 1356                 lp->type = LINUX_DVD_LU_SEND_KEY1;
 1357                 break;
 1358         case LINUX_DVD_LU_SEND_KEY1:
 1359                 memcpy(lp->lsk.key, bp->keychal, sizeof(lp->lsk.key));
 1360                 break;
 1361         case LINUX_DVD_LU_SEND_CHALLENGE:
 1362                 memcpy(lp->lsc.chal, bp->keychal, sizeof(lp->lsc.chal));
 1363                 break;
 1364         case LINUX_DVD_HOST_SEND_KEY2:
 1365                 lp->type = LINUX_DVD_AUTH_ESTABLISHED;
 1366                 break;
 1367         case LINUX_DVD_LU_SEND_TITLE_KEY:
 1368                 memcpy(lp->lstk.title_key, bp->keychal,
 1369                     sizeof(lp->lstk.title_key));
 1370                 lp->lstk.cpm = bp->cpm;
 1371                 lp->lstk.cp_sec = bp->cp_sec;
 1372                 lp->lstk.cgms = bp->cgms;
 1373                 break;
 1374         case LINUX_DVD_LU_SEND_ASF:
 1375                 lp->lsasf.asf = bp->asf;
 1376                 break;
 1377         case LINUX_DVD_INVALIDATE_AGID:
 1378                 break;
 1379         case LINUX_DVD_LU_SEND_RPC_STATE:
 1380                 lp->lrpcs.type = bp->reg_type;
 1381                 lp->lrpcs.vra = bp->vend_rsts;
 1382                 lp->lrpcs.ucca = bp->user_rsts;
 1383                 lp->lrpcs.region_mask = bp->region;
 1384                 lp->lrpcs.rpc_scheme = bp->rpc_scheme;
 1385                 break;
 1386         case LINUX_DVD_HOST_SEND_RPC_STATE:
 1387                 break;
 1388         default:
 1389                 return (EINVAL);
 1390         }
 1391         return (0);
 1392 }
 1393 
 1394 static int
 1395 linux_ioctl_cdrom(struct thread *td, struct linux_ioctl_args *args)
 1396 {
 1397         struct file *fp;
 1398         int error;
 1399 
 1400         if ((error = fget(td, args->fd, &fp)) != 0)
 1401                 return (error);
 1402         switch (args->cmd & 0xffff) {
 1403 
 1404         case LINUX_CDROMPAUSE:
 1405                 args->cmd = CDIOCPAUSE;
 1406                 error = (ioctl(td, (struct ioctl_args *)args));
 1407                 break;
 1408 
 1409         case LINUX_CDROMRESUME:
 1410                 args->cmd = CDIOCRESUME;
 1411                 error = (ioctl(td, (struct ioctl_args *)args));
 1412                 break;
 1413 
 1414         case LINUX_CDROMPLAYMSF:
 1415                 args->cmd = CDIOCPLAYMSF;
 1416                 error = (ioctl(td, (struct ioctl_args *)args));
 1417                 break;
 1418 
 1419         case LINUX_CDROMPLAYTRKIND:
 1420                 args->cmd = CDIOCPLAYTRACKS;
 1421                 error = (ioctl(td, (struct ioctl_args *)args));
 1422                 break;
 1423 
 1424         case LINUX_CDROMREADTOCHDR: {
 1425                 struct ioc_toc_header th;
 1426                 struct linux_cdrom_tochdr lth;
 1427                 error = fo_ioctl(fp, CDIOREADTOCHEADER, (caddr_t)&th,
 1428                     td->td_ucred, td);
 1429                 if (!error) {
 1430                         lth.cdth_trk0 = th.starting_track;
 1431                         lth.cdth_trk1 = th.ending_track;
 1432                         copyout(&lth, (void *)args->arg, sizeof(lth));
 1433                 }
 1434                 break;
 1435         }
 1436 
 1437         case LINUX_CDROMREADTOCENTRY: {
 1438                 struct linux_cdrom_tocentry lte;
 1439                 struct ioc_read_toc_single_entry irtse;
 1440 
 1441                 error = copyin((void *)args->arg, &lte, sizeof(lte));
 1442                 if (error)
 1443                         break;
 1444                 irtse.address_format = lte.cdte_format;
 1445                 irtse.track = lte.cdte_track;
 1446                 error = fo_ioctl(fp, CDIOREADTOCENTRY, (caddr_t)&irtse,
 1447                     td->td_ucred, td);
 1448                 if (!error) {
 1449                         lte.cdte_ctrl = irtse.entry.control;
 1450                         lte.cdte_adr = irtse.entry.addr_type;
 1451                         bsd_to_linux_msf_lba(irtse.address_format,
 1452                             &irtse.entry.addr, &lte.cdte_addr);
 1453                         error = copyout(&lte, (void *)args->arg, sizeof(lte));
 1454                 }
 1455                 break;
 1456         }
 1457 
 1458         case LINUX_CDROMSTOP:
 1459                 args->cmd = CDIOCSTOP;
 1460                 error = (ioctl(td, (struct ioctl_args *)args));
 1461                 break;
 1462 
 1463         case LINUX_CDROMSTART:
 1464                 args->cmd = CDIOCSTART;
 1465                 error = (ioctl(td, (struct ioctl_args *)args));
 1466                 break;
 1467 
 1468         case LINUX_CDROMEJECT:
 1469                 args->cmd = CDIOCEJECT;
 1470                 error = (ioctl(td, (struct ioctl_args *)args));
 1471                 break;
 1472 
 1473         /* LINUX_CDROMVOLCTRL */
 1474 
 1475         case LINUX_CDROMSUBCHNL: {
 1476                 struct linux_cdrom_subchnl sc;
 1477                 struct ioc_read_subchannel bsdsc;
 1478                 struct cd_sub_channel_info bsdinfo;
 1479 
 1480                 bsdsc.address_format = CD_LBA_FORMAT;
 1481                 bsdsc.data_format = CD_CURRENT_POSITION;
 1482                 bsdsc.track = 0;
 1483                 bsdsc.data_len = sizeof(bsdinfo);
 1484                 bsdsc.data = &bsdinfo;
 1485                 error = fo_ioctl(fp, CDIOCREADSUBCHANNEL_SYSSPACE,
 1486                     (caddr_t)&bsdsc, td->td_ucred, td);
 1487                 if (error)
 1488                         break;
 1489                 error = copyin((void *)args->arg, &sc, sizeof(sc));
 1490                 if (error)
 1491                         break;
 1492                 sc.cdsc_audiostatus = bsdinfo.header.audio_status;
 1493                 sc.cdsc_adr = bsdinfo.what.position.addr_type;
 1494                 sc.cdsc_ctrl = bsdinfo.what.position.control;
 1495                 sc.cdsc_trk = bsdinfo.what.position.track_number;
 1496                 sc.cdsc_ind = bsdinfo.what.position.index_number;
 1497                 set_linux_cdrom_addr(&sc.cdsc_absaddr, sc.cdsc_format,
 1498                     bsdinfo.what.position.absaddr.lba);
 1499                 set_linux_cdrom_addr(&sc.cdsc_reladdr, sc.cdsc_format,
 1500                     bsdinfo.what.position.reladdr.lba);
 1501                 error = copyout(&sc, (void *)args->arg, sizeof(sc));
 1502                 break;
 1503         }
 1504 
 1505         /* LINUX_CDROMREADMODE2 */
 1506         /* LINUX_CDROMREADMODE1 */
 1507         /* LINUX_CDROMREADAUDIO */
 1508         /* LINUX_CDROMEJECT_SW */
 1509         /* LINUX_CDROMMULTISESSION */
 1510         /* LINUX_CDROM_GET_UPC */
 1511 
 1512         case LINUX_CDROMRESET:
 1513                 args->cmd = CDIOCRESET;
 1514                 error = (ioctl(td, (struct ioctl_args *)args));
 1515                 break;
 1516 
 1517         /* LINUX_CDROMVOLREAD */
 1518         /* LINUX_CDROMREADRAW */
 1519         /* LINUX_CDROMREADCOOKED */
 1520         /* LINUX_CDROMSEEK */
 1521         /* LINUX_CDROMPLAYBLK */
 1522         /* LINUX_CDROMREADALL */
 1523         /* LINUX_CDROMCLOSETRAY */
 1524         /* LINUX_CDROMLOADFROMSLOT */
 1525         /* LINUX_CDROMGETSPINDOWN */
 1526         /* LINUX_CDROMSETSPINDOWN */
 1527         /* LINUX_CDROM_SET_OPTIONS */
 1528         /* LINUX_CDROM_CLEAR_OPTIONS */
 1529         /* LINUX_CDROM_SELECT_SPEED */
 1530         /* LINUX_CDROM_SELECT_DISC */
 1531         /* LINUX_CDROM_MEDIA_CHANGED */
 1532         /* LINUX_CDROM_DRIVE_STATUS */
 1533         /* LINUX_CDROM_DISC_STATUS */
 1534         /* LINUX_CDROM_CHANGER_NSLOTS */
 1535         /* LINUX_CDROM_LOCKDOOR */
 1536         /* LINUX_CDROM_DEBUG */
 1537         /* LINUX_CDROM_GET_CAPABILITY */
 1538         /* LINUX_CDROMAUDIOBUFSIZ */
 1539 
 1540         case LINUX_DVD_READ_STRUCT: {
 1541                 l_dvd_struct lds;
 1542                 struct dvd_struct bds;
 1543 
 1544                 error = copyin((void *)args->arg, &lds, sizeof(lds));
 1545                 if (error)
 1546                         break;
 1547                 error = linux_to_bsd_dvd_struct(&lds, &bds);
 1548                 if (error)
 1549                         break;
 1550                 error = fo_ioctl(fp, DVDIOCREADSTRUCTURE, (caddr_t)&bds,
 1551                     td->td_ucred, td);
 1552                 if (error)
 1553                         break;
 1554                 error = bsd_to_linux_dvd_struct(&bds, &lds);
 1555                 if (error)
 1556                         break;
 1557                 error = copyout(&lds, (void *)args->arg, sizeof(lds));
 1558                 break;
 1559         }
 1560 
 1561         /* LINUX_DVD_WRITE_STRUCT */
 1562 
 1563         case LINUX_DVD_AUTH: {
 1564                 l_dvd_authinfo lda;
 1565                 struct dvd_authinfo bda;
 1566                 int bcode;
 1567 
 1568                 error = copyin((void *)args->arg, &lda, sizeof(lda));
 1569                 if (error)
 1570                         break;
 1571                 error = linux_to_bsd_dvd_authinfo(&lda, &bcode, &bda);
 1572                 if (error)
 1573                         break;
 1574                 error = fo_ioctl(fp, bcode, (caddr_t)&bda, td->td_ucred,
 1575                     td);
 1576                 if (error) {
 1577                         if (lda.type == LINUX_DVD_HOST_SEND_KEY2) {
 1578                                 lda.type = LINUX_DVD_AUTH_FAILURE;
 1579                                 copyout(&lda, (void *)args->arg, sizeof(lda));
 1580                         }
 1581                         break;
 1582                 }
 1583                 error = bsd_to_linux_dvd_authinfo(&bda, &lda);
 1584                 if (error)
 1585                         break;
 1586                 error = copyout(&lda, (void *)args->arg, sizeof(lda));
 1587                 break;
 1588         }
 1589 
 1590         case LINUX_SCSI_GET_BUS_NUMBER:
 1591         case LINUX_SCSI_GET_IDLUN:
 1592                 error = linux_ioctl_sg(td, args);
 1593                 break;
 1594 
 1595         /* LINUX_CDROM_SEND_PACKET */
 1596         /* LINUX_CDROM_NEXT_WRITABLE */
 1597         /* LINUX_CDROM_LAST_WRITTEN */
 1598 
 1599         default:
 1600                 error = ENOIOCTL;
 1601                 break;
 1602         }
 1603 
 1604         fdrop(fp, td);
 1605         return (error);
 1606 }
 1607 
 1608 static int
 1609 linux_ioctl_vfat(struct thread *td, struct linux_ioctl_args *args)
 1610 {
 1611 
 1612         return (ENOTTY);
 1613 }
 1614 
 1615 /*
 1616  * Sound related ioctls
 1617  */
 1618 
 1619 struct linux_mixer_info {
 1620         char    id[16];
 1621         char    name[32];
 1622         int     modify_counter;
 1623         int     fillers[10];
 1624 };
 1625 
 1626 struct linux_old_mixer_info {
 1627         char    id[16];
 1628         char    name[32];
 1629 };
 1630 
 1631 static u_int32_t dirbits[4] = { IOC_VOID, IOC_IN, IOC_OUT, IOC_INOUT };
 1632 
 1633 #define SETDIR(c)       (((c) & ~IOC_DIRMASK) | dirbits[args->cmd >> 30])
 1634 
 1635 static int
 1636 linux_ioctl_sound(struct thread *td, struct linux_ioctl_args *args)
 1637 {
 1638 
 1639         switch (args->cmd & 0xffff) {
 1640 
 1641         case LINUX_SOUND_MIXER_WRITE_VOLUME:
 1642                 args->cmd = SETDIR(SOUND_MIXER_WRITE_VOLUME);
 1643                 return (ioctl(td, (struct ioctl_args *)args));
 1644 
 1645         case LINUX_SOUND_MIXER_WRITE_BASS:
 1646                 args->cmd = SETDIR(SOUND_MIXER_WRITE_BASS);
 1647                 return (ioctl(td, (struct ioctl_args *)args));
 1648 
 1649         case LINUX_SOUND_MIXER_WRITE_TREBLE:
 1650                 args->cmd = SETDIR(SOUND_MIXER_WRITE_TREBLE);
 1651                 return (ioctl(td, (struct ioctl_args *)args));
 1652 
 1653         case LINUX_SOUND_MIXER_WRITE_SYNTH:
 1654                 args->cmd = SETDIR(SOUND_MIXER_WRITE_SYNTH);
 1655                 return (ioctl(td, (struct ioctl_args *)args));
 1656 
 1657         case LINUX_SOUND_MIXER_WRITE_PCM:
 1658                 args->cmd = SETDIR(SOUND_MIXER_WRITE_PCM);
 1659                 return (ioctl(td, (struct ioctl_args *)args));
 1660 
 1661         case LINUX_SOUND_MIXER_WRITE_SPEAKER:
 1662                 args->cmd = SETDIR(SOUND_MIXER_WRITE_SPEAKER);
 1663                 return (ioctl(td, (struct ioctl_args *)args));
 1664 
 1665         case LINUX_SOUND_MIXER_WRITE_LINE:
 1666                 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE);
 1667                 return (ioctl(td, (struct ioctl_args *)args));
 1668 
 1669         case LINUX_SOUND_MIXER_WRITE_MIC:
 1670                 args->cmd = SETDIR(SOUND_MIXER_WRITE_MIC);
 1671                 return (ioctl(td, (struct ioctl_args *)args));
 1672 
 1673         case LINUX_SOUND_MIXER_WRITE_CD:
 1674                 args->cmd = SETDIR(SOUND_MIXER_WRITE_CD);
 1675                 return (ioctl(td, (struct ioctl_args *)args));
 1676 
 1677         case LINUX_SOUND_MIXER_WRITE_IMIX:
 1678                 args->cmd = SETDIR(SOUND_MIXER_WRITE_IMIX);
 1679                 return (ioctl(td, (struct ioctl_args *)args));
 1680 
 1681         case LINUX_SOUND_MIXER_WRITE_ALTPCM:
 1682                 args->cmd = SETDIR(SOUND_MIXER_WRITE_ALTPCM);
 1683                 return (ioctl(td, (struct ioctl_args *)args));
 1684 
 1685         case LINUX_SOUND_MIXER_WRITE_RECLEV:
 1686                 args->cmd = SETDIR(SOUND_MIXER_WRITE_RECLEV);
 1687                 return (ioctl(td, (struct ioctl_args *)args));
 1688 
 1689         case LINUX_SOUND_MIXER_WRITE_IGAIN:
 1690                 args->cmd = SETDIR(SOUND_MIXER_WRITE_IGAIN);
 1691                 return (ioctl(td, (struct ioctl_args *)args));
 1692 
 1693         case LINUX_SOUND_MIXER_WRITE_OGAIN:
 1694                 args->cmd = SETDIR(SOUND_MIXER_WRITE_OGAIN);
 1695                 return (ioctl(td, (struct ioctl_args *)args));
 1696 
 1697         case LINUX_SOUND_MIXER_WRITE_LINE1:
 1698                 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE1);
 1699                 return (ioctl(td, (struct ioctl_args *)args));
 1700 
 1701         case LINUX_SOUND_MIXER_WRITE_LINE2:
 1702                 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE2);
 1703                 return (ioctl(td, (struct ioctl_args *)args));
 1704 
 1705         case LINUX_SOUND_MIXER_WRITE_LINE3:
 1706                 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE3);
 1707                 return (ioctl(td, (struct ioctl_args *)args));
 1708 
 1709         case LINUX_SOUND_MIXER_INFO: {
 1710                 /* Key on encoded length */
 1711                 switch ((args->cmd >> 16) & 0x1fff) {
 1712                 case 0x005c: {  /* SOUND_MIXER_INFO */
 1713                         struct linux_mixer_info info;
 1714                         bzero(&info, sizeof(info));
 1715                         strncpy(info.id, "OSS", sizeof(info.id) - 1);
 1716                         strncpy(info.name, "FreeBSD OSS Mixer", sizeof(info.name) - 1);
 1717                         copyout(&info, (void *)args->arg, sizeof(info));
 1718                         break;
 1719                 }
 1720                 case 0x0030: {  /* SOUND_OLD_MIXER_INFO */
 1721                         struct linux_old_mixer_info info;
 1722                         bzero(&info, sizeof(info));
 1723                         strncpy(info.id, "OSS", sizeof(info.id) - 1);
 1724                         strncpy(info.name, "FreeBSD OSS Mixer", sizeof(info.name) - 1);
 1725                         copyout(&info, (void *)args->arg, sizeof(info));
 1726                         break;
 1727                 }
 1728                 default:
 1729                         return (ENOIOCTL);
 1730                 }
 1731                 break;
 1732         }
 1733 
 1734         case LINUX_OSS_GETVERSION: {
 1735                 int version = linux_get_oss_version(td);
 1736                 return (copyout(&version, (void *)args->arg, sizeof(int)));
 1737         }
 1738 
 1739         case LINUX_SOUND_MIXER_READ_STEREODEVS:
 1740                 args->cmd = SOUND_MIXER_READ_STEREODEVS;
 1741                 return (ioctl(td, (struct ioctl_args *)args));
 1742 
 1743         case LINUX_SOUND_MIXER_READ_RECMASK:
 1744                 args->cmd = SOUND_MIXER_READ_RECMASK;
 1745                 return (ioctl(td, (struct ioctl_args *)args));
 1746 
 1747         case LINUX_SOUND_MIXER_READ_DEVMASK:
 1748                 args->cmd = SOUND_MIXER_READ_DEVMASK;
 1749                 return (ioctl(td, (struct ioctl_args *)args));
 1750 
 1751         case LINUX_SOUND_MIXER_WRITE_RECSRC:
 1752                 args->cmd = SETDIR(SOUND_MIXER_WRITE_RECSRC);
 1753                 return (ioctl(td, (struct ioctl_args *)args));
 1754 
 1755         case LINUX_SNDCTL_DSP_RESET:
 1756                 args->cmd = SNDCTL_DSP_RESET;
 1757                 return (ioctl(td, (struct ioctl_args *)args));
 1758 
 1759         case LINUX_SNDCTL_DSP_SYNC:
 1760                 args->cmd = SNDCTL_DSP_SYNC;
 1761                 return (ioctl(td, (struct ioctl_args *)args));
 1762 
 1763         case LINUX_SNDCTL_DSP_SPEED:
 1764                 args->cmd = SNDCTL_DSP_SPEED;
 1765                 return (ioctl(td, (struct ioctl_args *)args));
 1766 
 1767         case LINUX_SNDCTL_DSP_STEREO:
 1768                 args->cmd = SNDCTL_DSP_STEREO;
 1769                 return (ioctl(td, (struct ioctl_args *)args));
 1770 
 1771         case LINUX_SNDCTL_DSP_GETBLKSIZE: /* LINUX_SNDCTL_DSP_SETBLKSIZE */
 1772                 args->cmd = SNDCTL_DSP_GETBLKSIZE;
 1773                 return (ioctl(td, (struct ioctl_args *)args));
 1774 
 1775         case LINUX_SNDCTL_DSP_SETFMT:
 1776                 args->cmd = SNDCTL_DSP_SETFMT;
 1777                 return (ioctl(td, (struct ioctl_args *)args));
 1778 
 1779         case LINUX_SOUND_PCM_WRITE_CHANNELS:
 1780                 args->cmd = SOUND_PCM_WRITE_CHANNELS;
 1781                 return (ioctl(td, (struct ioctl_args *)args));
 1782 
 1783         case LINUX_SOUND_PCM_WRITE_FILTER:
 1784                 args->cmd = SOUND_PCM_WRITE_FILTER;
 1785                 return (ioctl(td, (struct ioctl_args *)args));
 1786 
 1787         case LINUX_SNDCTL_DSP_POST:
 1788                 args->cmd = SNDCTL_DSP_POST;
 1789                 return (ioctl(td, (struct ioctl_args *)args));
 1790 
 1791         case LINUX_SNDCTL_DSP_SUBDIVIDE:
 1792                 args->cmd = SNDCTL_DSP_SUBDIVIDE;
 1793                 return (ioctl(td, (struct ioctl_args *)args));
 1794 
 1795         case LINUX_SNDCTL_DSP_SETFRAGMENT:
 1796                 args->cmd = SNDCTL_DSP_SETFRAGMENT;
 1797                 return (ioctl(td, (struct ioctl_args *)args));
 1798 
 1799         case LINUX_SNDCTL_DSP_GETFMTS:
 1800                 args->cmd = SNDCTL_DSP_GETFMTS;
 1801                 return (ioctl(td, (struct ioctl_args *)args));
 1802 
 1803         case LINUX_SNDCTL_DSP_GETOSPACE:
 1804                 args->cmd = SNDCTL_DSP_GETOSPACE;
 1805                 return (ioctl(td, (struct ioctl_args *)args));
 1806 
 1807         case LINUX_SNDCTL_DSP_GETISPACE:
 1808                 args->cmd = SNDCTL_DSP_GETISPACE;
 1809                 return (ioctl(td, (struct ioctl_args *)args));
 1810 
 1811         case LINUX_SNDCTL_DSP_NONBLOCK:
 1812                 args->cmd = SNDCTL_DSP_NONBLOCK;
 1813                 return (ioctl(td, (struct ioctl_args *)args));
 1814 
 1815         case LINUX_SNDCTL_DSP_GETCAPS:
 1816                 args->cmd = SNDCTL_DSP_GETCAPS;
 1817                 return (ioctl(td, (struct ioctl_args *)args));
 1818 
 1819         case LINUX_SNDCTL_DSP_SETTRIGGER: /* LINUX_SNDCTL_GETTRIGGER */
 1820                 args->cmd = SNDCTL_DSP_SETTRIGGER;
 1821                 return (ioctl(td, (struct ioctl_args *)args));
 1822 
 1823         case LINUX_SNDCTL_DSP_GETIPTR:
 1824                 args->cmd = SNDCTL_DSP_GETIPTR;
 1825                 return (ioctl(td, (struct ioctl_args *)args));
 1826 
 1827         case LINUX_SNDCTL_DSP_GETOPTR:
 1828                 args->cmd = SNDCTL_DSP_GETOPTR;
 1829                 return (ioctl(td, (struct ioctl_args *)args));
 1830 
 1831         case LINUX_SNDCTL_DSP_SETDUPLEX:
 1832                 args->cmd = SNDCTL_DSP_SETDUPLEX;
 1833                 return (ioctl(td, (struct ioctl_args *)args));
 1834 
 1835         case LINUX_SNDCTL_DSP_GETODELAY:
 1836                 args->cmd = SNDCTL_DSP_GETODELAY;
 1837                 return (ioctl(td, (struct ioctl_args *)args));
 1838 
 1839         case LINUX_SNDCTL_SEQ_RESET:
 1840                 args->cmd = SNDCTL_SEQ_RESET;
 1841                 return (ioctl(td, (struct ioctl_args *)args));
 1842 
 1843         case LINUX_SNDCTL_SEQ_SYNC:
 1844                 args->cmd = SNDCTL_SEQ_SYNC;
 1845                 return (ioctl(td, (struct ioctl_args *)args));
 1846 
 1847         case LINUX_SNDCTL_SYNTH_INFO:
 1848                 args->cmd = SNDCTL_SYNTH_INFO;
 1849                 return (ioctl(td, (struct ioctl_args *)args));
 1850 
 1851         case LINUX_SNDCTL_SEQ_CTRLRATE:
 1852                 args->cmd = SNDCTL_SEQ_CTRLRATE;
 1853                 return (ioctl(td, (struct ioctl_args *)args));
 1854 
 1855         case LINUX_SNDCTL_SEQ_GETOUTCOUNT:
 1856                 args->cmd = SNDCTL_SEQ_GETOUTCOUNT;
 1857                 return (ioctl(td, (struct ioctl_args *)args));
 1858 
 1859         case LINUX_SNDCTL_SEQ_GETINCOUNT:
 1860                 args->cmd = SNDCTL_SEQ_GETINCOUNT;
 1861                 return (ioctl(td, (struct ioctl_args *)args));
 1862 
 1863         case LINUX_SNDCTL_SEQ_PERCMODE:
 1864                 args->cmd = SNDCTL_SEQ_PERCMODE;
 1865                 return (ioctl(td, (struct ioctl_args *)args));
 1866 
 1867         case LINUX_SNDCTL_FM_LOAD_INSTR:
 1868                 args->cmd = SNDCTL_FM_LOAD_INSTR;
 1869                 return (ioctl(td, (struct ioctl_args *)args));
 1870 
 1871         case LINUX_SNDCTL_SEQ_TESTMIDI:
 1872                 args->cmd = SNDCTL_SEQ_TESTMIDI;
 1873                 return (ioctl(td, (struct ioctl_args *)args));
 1874 
 1875         case LINUX_SNDCTL_SEQ_RESETSAMPLES:
 1876                 args->cmd = SNDCTL_SEQ_RESETSAMPLES;
 1877                 return (ioctl(td, (struct ioctl_args *)args));
 1878 
 1879         case LINUX_SNDCTL_SEQ_NRSYNTHS:
 1880                 args->cmd = SNDCTL_SEQ_NRSYNTHS;
 1881                 return (ioctl(td, (struct ioctl_args *)args));
 1882 
 1883         case LINUX_SNDCTL_SEQ_NRMIDIS:
 1884                 args->cmd = SNDCTL_SEQ_NRMIDIS;
 1885                 return (ioctl(td, (struct ioctl_args *)args));
 1886 
 1887         case LINUX_SNDCTL_MIDI_INFO:
 1888                 args->cmd = SNDCTL_MIDI_INFO;
 1889                 return (ioctl(td, (struct ioctl_args *)args));
 1890 
 1891         case LINUX_SNDCTL_SEQ_TRESHOLD:
 1892                 args->cmd = SNDCTL_SEQ_TRESHOLD;
 1893                 return (ioctl(td, (struct ioctl_args *)args));
 1894 
 1895         case LINUX_SNDCTL_SYNTH_MEMAVL:
 1896                 args->cmd = SNDCTL_SYNTH_MEMAVL;
 1897                 return (ioctl(td, (struct ioctl_args *)args));
 1898 
 1899         }
 1900 
 1901         return (ENOIOCTL);
 1902 }
 1903 
 1904 /*
 1905  * Console related ioctls
 1906  */
 1907 
 1908 #define ISSIGVALID(sig)         ((sig) > 0 && (sig) < NSIG)
 1909 
 1910 static int
 1911 linux_ioctl_console(struct thread *td, struct linux_ioctl_args *args)
 1912 {
 1913         struct file *fp;
 1914         int error;
 1915 
 1916         if ((error = fget(td, args->fd, &fp)) != 0)
 1917                 return (error);
 1918         switch (args->cmd & 0xffff) {
 1919 
 1920         case LINUX_KIOCSOUND:
 1921                 args->cmd = KIOCSOUND;
 1922                 error = (ioctl(td, (struct ioctl_args *)args));
 1923                 break;
 1924 
 1925         case LINUX_KDMKTONE:
 1926                 args->cmd = KDMKTONE;
 1927                 error = (ioctl(td, (struct ioctl_args *)args));
 1928                 break;
 1929 
 1930         case LINUX_KDGETLED:
 1931                 args->cmd = KDGETLED;
 1932                 error = (ioctl(td, (struct ioctl_args *)args));
 1933                 break;
 1934 
 1935         case LINUX_KDSETLED:
 1936                 args->cmd = KDSETLED;
 1937                 error = (ioctl(td, (struct ioctl_args *)args));
 1938                 break;
 1939 
 1940         case LINUX_KDSETMODE:
 1941                 args->cmd = KDSETMODE;
 1942                 error = (ioctl(td, (struct ioctl_args *)args));
 1943                 break;
 1944 
 1945         case LINUX_KDGETMODE:
 1946                 args->cmd = KDGETMODE;
 1947                 error = (ioctl(td, (struct ioctl_args *)args));
 1948                 break;
 1949 
 1950         case LINUX_KDGKBMODE:
 1951                 args->cmd = KDGKBMODE;
 1952                 error = (ioctl(td, (struct ioctl_args *)args));
 1953                 break;
 1954 
 1955         case LINUX_KDSKBMODE: {
 1956                 int kbdmode;
 1957                 switch (args->arg) {
 1958                 case LINUX_KBD_RAW:
 1959                         kbdmode = K_RAW;
 1960                         break;
 1961                 case LINUX_KBD_XLATE:
 1962                         kbdmode = K_XLATE;
 1963                         break;
 1964                 case LINUX_KBD_MEDIUMRAW:
 1965                         kbdmode = K_RAW;
 1966                         break;
 1967                 default:
 1968                         fdrop(fp, td);
 1969                         return (EINVAL);
 1970                 }
 1971                 error = (fo_ioctl(fp, KDSKBMODE, (caddr_t)&kbdmode,
 1972                     td->td_ucred, td));
 1973                 break;
 1974         }
 1975 
 1976         case LINUX_VT_OPENQRY:
 1977                 args->cmd = VT_OPENQRY;
 1978                 error = (ioctl(td, (struct ioctl_args *)args));
 1979                 break;
 1980 
 1981         case LINUX_VT_GETMODE:
 1982                 args->cmd = VT_GETMODE;
 1983                 error = (ioctl(td, (struct ioctl_args *)args));
 1984                 break;
 1985 
 1986         case LINUX_VT_SETMODE: {
 1987                 struct vt_mode mode;
 1988                 if ((error = copyin((void *)args->arg, &mode, sizeof(mode))))
 1989                         break;
 1990                 if (!ISSIGVALID(mode.frsig) && ISSIGVALID(mode.acqsig))
 1991                         mode.frsig = mode.acqsig;
 1992                 if ((error = copyout(&mode, (void *)args->arg, sizeof(mode))))
 1993                         break;
 1994                 args->cmd = VT_SETMODE;
 1995                 error = (ioctl(td, (struct ioctl_args *)args));
 1996                 break;
 1997         }
 1998 
 1999         case LINUX_VT_GETSTATE:
 2000                 args->cmd = VT_GETACTIVE;
 2001                 error = (ioctl(td, (struct ioctl_args *)args));
 2002                 break;
 2003 
 2004         case LINUX_VT_RELDISP:
 2005                 args->cmd = VT_RELDISP;
 2006                 error = (ioctl(td, (struct ioctl_args *)args));
 2007                 break;
 2008 
 2009         case LINUX_VT_ACTIVATE:
 2010                 args->cmd = VT_ACTIVATE;
 2011                 error = (ioctl(td, (struct ioctl_args *)args));
 2012                 break;
 2013 
 2014         case LINUX_VT_WAITACTIVE:
 2015                 args->cmd = VT_WAITACTIVE;
 2016                 error = (ioctl(td, (struct ioctl_args *)args));
 2017                 break;
 2018 
 2019         default:
 2020                 error = ENOIOCTL;
 2021                 break;
 2022         }
 2023 
 2024         fdrop(fp, td);
 2025         return (error);
 2026 }
 2027 
 2028 /*
 2029  * Criteria for interface name translation
 2030  */
 2031 #define IFP_IS_ETH(ifp) (ifp->if_type == IFT_ETHER)
 2032 
 2033 /*
 2034  * Interface function used by linprocfs (at the time of writing). It's not
 2035  * used by the Linuxulator itself.
 2036  */
 2037 int
 2038 linux_ifname(struct ifnet *ifp, char *buffer, size_t buflen)
 2039 {
 2040         struct ifnet *ifscan;
 2041         int ethno;
 2042 
 2043         /* Short-circuit non ethernet interfaces */
 2044         if (!IFP_IS_ETH(ifp))
 2045                 return (strlcpy(buffer, ifp->if_xname, buflen));
 2046 
 2047         /* Determine the (relative) unit number for ethernet interfaces */
 2048         ethno = 0;
 2049         IFNET_RLOCK();
 2050         TAILQ_FOREACH(ifscan, &ifnet, if_link) {
 2051                 if (ifscan == ifp) {
 2052                         IFNET_RUNLOCK();
 2053                         return (snprintf(buffer, buflen, "eth%d", ethno));
 2054                 }
 2055                 if (IFP_IS_ETH(ifscan))
 2056                         ethno++;
 2057         }
 2058         IFNET_RUNLOCK();
 2059 
 2060         return (0);
 2061 }
 2062 
 2063 /*
 2064  * Translate a Linux interface name to a FreeBSD interface name,
 2065  * and return the associated ifnet structure
 2066  * bsdname and lxname need to be least IFNAMSIZ bytes long, but
 2067  * can point to the same buffer.
 2068  */
 2069 
 2070 static struct ifnet *
 2071 ifname_linux_to_bsd(const char *lxname, char *bsdname)
 2072 {
 2073         struct ifnet *ifp;
 2074         int len, unit;
 2075         char *ep;
 2076         int is_eth, index;
 2077 
 2078         for (len = 0; len < LINUX_IFNAMSIZ; ++len)
 2079                 if (!isalpha(lxname[len]))
 2080                         break;
 2081         if (len == 0 || len == LINUX_IFNAMSIZ)
 2082                 return (NULL);
 2083         unit = (int)strtoul(lxname + len, &ep, 10);
 2084         if (ep == NULL || ep == lxname + len || ep >= lxname + LINUX_IFNAMSIZ)
 2085                 return (NULL);
 2086         index = 0;
 2087         is_eth = (len == 3 && !strncmp(lxname, "eth", len)) ? 1 : 0;
 2088         IFNET_RLOCK();
 2089         TAILQ_FOREACH(ifp, &ifnet, if_link) {
 2090                 /*
 2091                  * Allow Linux programs to use FreeBSD names. Don't presume
 2092                  * we never have an interface named "eth", so don't make
 2093                  * the test optional based on is_eth.
 2094                  */
 2095                 if (strncmp(ifp->if_xname, lxname, LINUX_IFNAMSIZ) == 0)
 2096                         break;
 2097                 if (is_eth && IFP_IS_ETH(ifp) && unit == index++)
 2098                         break;
 2099         }
 2100         IFNET_RUNLOCK();
 2101         if (ifp != NULL)
 2102                 strlcpy(bsdname, ifp->if_xname, IFNAMSIZ);
 2103         return (ifp);
 2104 }
 2105 
 2106 /*
 2107  * Implement the SIOCGIFCONF ioctl
 2108  */
 2109 
 2110 static int
 2111 linux_ifconf(struct thread *td, struct ifconf *uifc)
 2112 {
 2113 #ifdef COMPAT_LINUX32
 2114         struct l_ifconf ifc;
 2115 #else
 2116         struct ifconf ifc;
 2117 #endif
 2118         struct l_ifreq ifr;
 2119         struct ifnet *ifp;
 2120         struct ifaddr *ifa;
 2121         struct sbuf *sb;
 2122         int error, ethno, full = 0, valid_len, max_len;
 2123 
 2124         error = copyin(uifc, &ifc, sizeof(ifc));
 2125         if (error != 0)
 2126                 return (error);
 2127 
 2128         max_len = MAXPHYS - 1;
 2129 
 2130         /* handle the 'request buffer size' case */
 2131         if (ifc.ifc_buf == PTROUT(NULL)) {
 2132                 ifc.ifc_len = 0;
 2133                 TAILQ_FOREACH(ifp, &ifnet, if_link) {
 2134                         TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
 2135                                 struct sockaddr *sa = ifa->ifa_addr;
 2136                                 if (sa->sa_family == AF_INET)
 2137                                         ifc.ifc_len += sizeof(ifr);
 2138                         }
 2139                 }
 2140                 error = copyout(&ifc, uifc, sizeof(ifc));
 2141                 return (error);
 2142         }
 2143 
 2144         if (ifc.ifc_len <= 0)
 2145                 return (EINVAL);
 2146 
 2147 again:
 2148         /* Keep track of eth interfaces */
 2149         ethno = 0;
 2150         if (ifc.ifc_len <= max_len) {
 2151                 max_len = ifc.ifc_len;
 2152                 full = 1;
 2153         }
 2154         sb = sbuf_new(NULL, NULL, max_len + 1, SBUF_FIXEDLEN);
 2155         max_len = 0;
 2156         valid_len = 0;
 2157 
 2158         /* Return all AF_INET addresses of all interfaces */
 2159         IFNET_RLOCK();          /* could sleep XXX */
 2160         TAILQ_FOREACH(ifp, &ifnet, if_link) {
 2161                 int addrs = 0;
 2162 
 2163                 bzero(&ifr, sizeof(ifr));
 2164                 if (IFP_IS_ETH(ifp))
 2165                         snprintf(ifr.ifr_name, LINUX_IFNAMSIZ, "eth%d",
 2166                             ethno++);
 2167                 else
 2168                         strlcpy(ifr.ifr_name, ifp->if_xname, LINUX_IFNAMSIZ);
 2169 
 2170                 /* Walk the address list */
 2171                 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
 2172                         struct sockaddr *sa = ifa->ifa_addr;
 2173 
 2174                         if (sa->sa_family == AF_INET) {
 2175                                 ifr.ifr_addr.sa_family = LINUX_AF_INET;
 2176                                 memcpy(ifr.ifr_addr.sa_data, sa->sa_data,
 2177                                     sizeof(ifr.ifr_addr.sa_data));
 2178                                 sbuf_bcat(sb, &ifr, sizeof(ifr));
 2179                                 max_len += sizeof(ifr);
 2180                                 addrs++;
 2181                         }
 2182 
 2183                         if (!sbuf_overflowed(sb))
 2184                                 valid_len = sbuf_len(sb);
 2185                 }
 2186                 if (addrs == 0) {
 2187                         bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
 2188                         sbuf_bcat(sb, &ifr, sizeof(ifr));
 2189                         max_len += sizeof(ifr);
 2190 
 2191                         if (!sbuf_overflowed(sb))
 2192                                 valid_len = sbuf_len(sb);
 2193                 }
 2194         }
 2195         IFNET_RUNLOCK();
 2196 
 2197         if (valid_len != max_len && !full) {
 2198                 sbuf_delete(sb);
 2199                 goto again;
 2200         }
 2201 
 2202         ifc.ifc_len = valid_len; 
 2203         sbuf_finish(sb);
 2204         memcpy(PTRIN(ifc.ifc_buf), sbuf_data(sb), ifc.ifc_len);
 2205         error = copyout(&ifc, uifc, sizeof(ifc));
 2206         sbuf_delete(sb);
 2207 
 2208         return (error);
 2209 }
 2210 
 2211 static int
 2212 linux_gifflags(struct thread *td, struct ifnet *ifp, struct l_ifreq *ifr)
 2213 {
 2214         l_short flags;
 2215 
 2216         flags = (ifp->if_flags | ifp->if_drv_flags) & 0xffff;
 2217         /* these flags have no Linux equivalent */
 2218         flags &= ~(IFF_SMART|IFF_DRV_OACTIVE|IFF_SIMPLEX|
 2219             IFF_LINK0|IFF_LINK1|IFF_LINK2);
 2220         /* Linux' multicast flag is in a different bit */
 2221         if (flags & IFF_MULTICAST) {
 2222                 flags &= ~IFF_MULTICAST;
 2223                 flags |= 0x1000;
 2224         }
 2225 
 2226         return (copyout(&flags, &ifr->ifr_flags, sizeof(flags)));
 2227 }
 2228 
 2229 #define ARPHRD_ETHER    1
 2230 #define ARPHRD_LOOPBACK 772
 2231 
 2232 static int
 2233 linux_gifhwaddr(struct ifnet *ifp, struct l_ifreq *ifr)
 2234 {
 2235         struct ifaddr *ifa;
 2236         struct sockaddr_dl *sdl;
 2237         struct l_sockaddr lsa;
 2238 
 2239         if (ifp->if_type == IFT_LOOP) {
 2240                 bzero(&lsa, sizeof(lsa));
 2241                 lsa.sa_family = ARPHRD_LOOPBACK;
 2242                 return (copyout(&lsa, &ifr->ifr_hwaddr, sizeof(lsa)));
 2243         }
 2244 
 2245         if (ifp->if_type != IFT_ETHER)
 2246                 return (ENOENT);
 2247 
 2248         TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
 2249                 sdl = (struct sockaddr_dl*)ifa->ifa_addr;
 2250                 if (sdl != NULL && (sdl->sdl_family == AF_LINK) &&
 2251                     (sdl->sdl_type == IFT_ETHER)) {
 2252                         bzero(&lsa, sizeof(lsa));
 2253                         lsa.sa_family = ARPHRD_ETHER;
 2254                         bcopy(LLADDR(sdl), lsa.sa_data, LINUX_IFHWADDRLEN);
 2255                         return (copyout(&lsa, &ifr->ifr_hwaddr, sizeof(lsa)));
 2256                 }
 2257         }
 2258 
 2259         return (ENOENT);
 2260 }
 2261 
 2262 
 2263  /*
 2264 * If we fault in bsd_to_linux_ifreq() then we will fault when we call
 2265 * the native ioctl().  Thus, we don't really need to check the return
 2266 * value of this function.
 2267 */
 2268 static int
 2269 bsd_to_linux_ifreq(struct ifreq *arg)
 2270 {
 2271         struct ifreq ifr;
 2272         size_t ifr_len = sizeof(struct ifreq);
 2273         int error;
 2274         
 2275         if ((error = copyin(arg, &ifr, ifr_len)))
 2276                 return (error);
 2277         
 2278         *(u_short *)&ifr.ifr_addr = ifr.ifr_addr.sa_family;
 2279         
 2280         error = copyout(&ifr, arg, ifr_len);
 2281 
 2282         return (error);
 2283 }
 2284 
 2285 /*
 2286  * Socket related ioctls
 2287  */
 2288 
 2289 static int
 2290 linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args)
 2291 {
 2292         char lifname[LINUX_IFNAMSIZ], ifname[IFNAMSIZ];
 2293         struct ifnet *ifp;
 2294         struct file *fp;
 2295         int error, type;
 2296 
 2297         ifp = NULL;
 2298         error = 0;
 2299 
 2300         if ((error = fget(td, args->fd, &fp)) != 0)
 2301                 return (error);
 2302         type = fp->f_type;
 2303         fdrop(fp, td);
 2304         if (type != DTYPE_SOCKET) {
 2305                 /* not a socket - probably a tap / vmnet device */
 2306                 switch (args->cmd) {
 2307                 case LINUX_SIOCGIFADDR:
 2308                 case LINUX_SIOCSIFADDR:
 2309                 case LINUX_SIOCGIFFLAGS:
 2310                         return (linux_ioctl_special(td, args));
 2311                 default:
 2312                         return (ENOIOCTL);
 2313                 }
 2314         }
 2315 
 2316         switch (args->cmd & 0xffff) {
 2317 
 2318         case LINUX_FIOGETOWN:
 2319         case LINUX_FIOSETOWN:
 2320         case LINUX_SIOCADDMULTI:
 2321         case LINUX_SIOCATMARK:
 2322         case LINUX_SIOCDELMULTI:
 2323         case LINUX_SIOCGIFCONF:
 2324         case LINUX_SIOCGPGRP:
 2325         case LINUX_SIOCSPGRP:
 2326         case LINUX_SIOCGIFCOUNT:
 2327                 /* these ioctls don't take an interface name */
 2328 #ifdef DEBUG
 2329                 printf("%s(): ioctl %d\n", __func__,
 2330                     args->cmd & 0xffff);
 2331 #endif
 2332                 break;
 2333 
 2334         case LINUX_SIOCGIFFLAGS:
 2335         case LINUX_SIOCGIFADDR:
 2336         case LINUX_SIOCSIFADDR:
 2337         case LINUX_SIOCGIFDSTADDR:
 2338         case LINUX_SIOCGIFBRDADDR:
 2339         case LINUX_SIOCGIFNETMASK:
 2340         case LINUX_SIOCSIFNETMASK:
 2341         case LINUX_SIOCGIFMTU:
 2342         case LINUX_SIOCSIFMTU:
 2343         case LINUX_SIOCSIFNAME:
 2344         case LINUX_SIOCGIFHWADDR:
 2345         case LINUX_SIOCSIFHWADDR:
 2346         case LINUX_SIOCDEVPRIVATE:
 2347         case LINUX_SIOCDEVPRIVATE+1:
 2348         case LINUX_SIOCGIFINDEX:
 2349                 /* copy in the interface name and translate it. */
 2350                 error = copyin((void *)args->arg, lifname, LINUX_IFNAMSIZ);
 2351                 if (error != 0)
 2352                         return (error);
 2353 #ifdef DEBUG
 2354                 printf("%s(): ioctl %d on %.*s\n", __func__,
 2355                     args->cmd & 0xffff, LINUX_IFNAMSIZ, lifname);
 2356 #endif
 2357                 ifp = ifname_linux_to_bsd(lifname, ifname);
 2358                 if (ifp == NULL)
 2359                         return (EINVAL);
 2360                 /*
 2361                  * We need to copy it back out in case we pass the
 2362                  * request on to our native ioctl(), which will expect
 2363                  * the ifreq to be in user space and have the correct
 2364                  * interface name.
 2365                  */
 2366                 error = copyout(ifname, (void *)args->arg, IFNAMSIZ);
 2367                 if (error != 0)
 2368                         return (error);
 2369 #ifdef DEBUG
 2370                 printf("%s(): %s translated to %s\n", __func__,
 2371                     lifname, ifname);
 2372 #endif
 2373                 break;
 2374 
 2375         default:
 2376                 return (ENOIOCTL);
 2377         }
 2378 
 2379         switch (args->cmd & 0xffff) {
 2380 
 2381         case LINUX_FIOSETOWN:
 2382                 args->cmd = FIOSETOWN;
 2383                 error = ioctl(td, (struct ioctl_args *)args);
 2384                 break;
 2385 
 2386         case LINUX_SIOCSPGRP:
 2387                 args->cmd = SIOCSPGRP;
 2388                 error = ioctl(td, (struct ioctl_args *)args);
 2389                 break;
 2390 
 2391         case LINUX_FIOGETOWN:
 2392                 args->cmd = FIOGETOWN;
 2393                 error = ioctl(td, (struct ioctl_args *)args);
 2394                 break;
 2395 
 2396         case LINUX_SIOCGPGRP:
 2397                 args->cmd = SIOCGPGRP;
 2398                 error = ioctl(td, (struct ioctl_args *)args);
 2399                 break;
 2400 
 2401         case LINUX_SIOCATMARK:
 2402                 args->cmd = SIOCATMARK;
 2403                 error = ioctl(td, (struct ioctl_args *)args);
 2404                 break;
 2405 
 2406         /* LINUX_SIOCGSTAMP */
 2407 
 2408         case LINUX_SIOCGIFCONF:
 2409                 error = linux_ifconf(td, (struct ifconf *)args->arg);
 2410                 break;
 2411 
 2412         case LINUX_SIOCGIFFLAGS:
 2413                 args->cmd = SIOCGIFFLAGS;
 2414                 error = linux_gifflags(td, ifp, (struct l_ifreq *)args->arg);
 2415                 break;
 2416 
 2417         case LINUX_SIOCGIFADDR:
 2418                 args->cmd = SIOCGIFADDR;
 2419                 error = ioctl(td, (struct ioctl_args *)args);
 2420                 bsd_to_linux_ifreq((struct ifreq *)args->arg);
 2421                 break;
 2422 
 2423         case LINUX_SIOCSIFADDR:
 2424                 /* XXX probably doesn't work, included for completeness */
 2425                 args->cmd = SIOCSIFADDR;
 2426                 error = ioctl(td, (struct ioctl_args *)args);
 2427                 break;
 2428 
 2429         case LINUX_SIOCGIFDSTADDR:
 2430                 args->cmd = SIOCGIFDSTADDR;
 2431                 error = ioctl(td, (struct ioctl_args *)args);
 2432                 bsd_to_linux_ifreq((struct ifreq *)args->arg);
 2433                 break;
 2434 
 2435         case LINUX_SIOCGIFBRDADDR:
 2436                 args->cmd = SIOCGIFBRDADDR;
 2437                 error = ioctl(td, (struct ioctl_args *)args);
 2438                 bsd_to_linux_ifreq((struct ifreq *)args->arg);
 2439                 break;
 2440 
 2441         case LINUX_SIOCGIFNETMASK:
 2442                 args->cmd = SIOCGIFNETMASK;
 2443                 error = ioctl(td, (struct ioctl_args *)args);
 2444                 bsd_to_linux_ifreq((struct ifreq *)args->arg);
 2445                 break;
 2446 
 2447         case LINUX_SIOCSIFNETMASK:
 2448                 error = ENOIOCTL;
 2449                 break;
 2450 
 2451         case LINUX_SIOCGIFMTU:
 2452                 args->cmd = SIOCGIFMTU;
 2453                 error = ioctl(td, (struct ioctl_args *)args);
 2454                 break;
 2455 
 2456         case LINUX_SIOCSIFMTU:
 2457                 args->cmd = SIOCSIFMTU;
 2458                 error = ioctl(td, (struct ioctl_args *)args);
 2459                 break;
 2460 
 2461         case LINUX_SIOCSIFNAME:
 2462                 error = ENOIOCTL;
 2463                 break;
 2464 
 2465         case LINUX_SIOCGIFHWADDR:
 2466                 error = linux_gifhwaddr(ifp, (struct l_ifreq *)args->arg);
 2467                 break;
 2468 
 2469         case LINUX_SIOCSIFHWADDR:
 2470                 error = ENOIOCTL;
 2471                 break;
 2472 
 2473         case LINUX_SIOCADDMULTI:
 2474                 args->cmd = SIOCADDMULTI;
 2475                 error = ioctl(td, (struct ioctl_args *)args);
 2476                 break;
 2477 
 2478         case LINUX_SIOCDELMULTI:
 2479                 args->cmd = SIOCDELMULTI;
 2480                 error = ioctl(td, (struct ioctl_args *)args);
 2481                 break;
 2482 
 2483         case LINUX_SIOCGIFINDEX:
 2484                 args->cmd = SIOCGIFINDEX;
 2485                 error = ioctl(td, (struct ioctl_args *)args);
 2486                 break;
 2487 
 2488         case LINUX_SIOCGIFCOUNT:
 2489                 error = 0;
 2490                 break;
 2491 
 2492         /*
 2493          * XXX This is slightly bogus, but these ioctls are currently
 2494          * XXX only used by the aironet (if_an) network driver.
 2495          */
 2496         case LINUX_SIOCDEVPRIVATE:
 2497                 args->cmd = SIOCGPRIVATE_0;
 2498                 error = ioctl(td, (struct ioctl_args *)args);
 2499                 break;
 2500 
 2501         case LINUX_SIOCDEVPRIVATE+1:
 2502                 args->cmd = SIOCGPRIVATE_1;
 2503                 error = ioctl(td, (struct ioctl_args *)args);
 2504                 break;
 2505         }
 2506 
 2507         if (ifp != NULL)
 2508                 /* restore the original interface name */
 2509                 copyout(lifname, (void *)args->arg, LINUX_IFNAMSIZ);
 2510 
 2511 #ifdef DEBUG
 2512         printf("%s(): returning %d\n", __func__, error);
 2513 #endif
 2514         return (error);
 2515 }
 2516 
 2517 /*
 2518  * Device private ioctl handler
 2519  */
 2520 static int
 2521 linux_ioctl_private(struct thread *td, struct linux_ioctl_args *args)
 2522 {
 2523         struct file *fp;
 2524         int error, type;
 2525 
 2526         if ((error = fget(td, args->fd, &fp)) != 0)
 2527                 return (error);
 2528         type = fp->f_type;
 2529         fdrop(fp, td);
 2530         if (type == DTYPE_SOCKET)
 2531                 return (linux_ioctl_socket(td, args));
 2532         return (ENOIOCTL);
 2533 }
 2534 
 2535 /*
 2536  * DRM ioctl handler (sys/dev/drm)
 2537  */
 2538 static int
 2539 linux_ioctl_drm(struct thread *td, struct linux_ioctl_args *args)
 2540 {
 2541         args->cmd = SETDIR(args->cmd);
 2542         return ioctl(td, (struct ioctl_args *)args);
 2543 }
 2544 
 2545 static int
 2546 linux_ioctl_sg(struct thread *td, struct linux_ioctl_args *args)
 2547 {
 2548         struct file *fp;
 2549         u_long cmd;
 2550         int error;
 2551 
 2552         if ((error = fget(td, args->fd, &fp)) != 0) {
 2553                 printf("sg_linux_ioctl: fget returned %d\n", error);
 2554                 return (error);
 2555         }
 2556         cmd = args->cmd;
 2557 
 2558         error = (fo_ioctl(fp, cmd, (caddr_t)args->arg, td->td_ucred, td));
 2559         fdrop(fp, td);
 2560         return (error);
 2561 }
 2562 
 2563 /*
 2564  * Special ioctl handler
 2565  */
 2566 static int
 2567 linux_ioctl_special(struct thread *td, struct linux_ioctl_args *args)
 2568 {
 2569         int error;
 2570 
 2571         switch (args->cmd) {
 2572         case LINUX_SIOCGIFADDR:
 2573                 args->cmd = SIOCGIFADDR;
 2574                 error = ioctl(td, (struct ioctl_args *)args);
 2575                 break;
 2576         case LINUX_SIOCSIFADDR:
 2577                 args->cmd = SIOCSIFADDR;
 2578                 error = ioctl(td, (struct ioctl_args *)args);
 2579                 break;
 2580         case LINUX_SIOCGIFFLAGS:
 2581                 args->cmd = SIOCGIFFLAGS;
 2582                 error = ioctl(td, (struct ioctl_args *)args);
 2583                 break;
 2584         default:
 2585                 error = ENOIOCTL;
 2586         }
 2587 
 2588         return (error);
 2589 }
 2590 
 2591 /*
 2592  * main ioctl syscall function
 2593  */
 2594 
 2595 int
 2596 linux_ioctl(struct thread *td, struct linux_ioctl_args *args)
 2597 {
 2598         struct file *fp;
 2599         struct handler_element *he;
 2600         int error, cmd;
 2601 
 2602 #ifdef DEBUG
 2603         if (ldebug(ioctl))
 2604                 printf(ARGS(ioctl, "%d, %04lx, *"), args->fd,
 2605                     (unsigned long)args->cmd);
 2606 #endif
 2607 
 2608         if ((error = fget(td, args->fd, &fp)) != 0)
 2609                 return (error);
 2610         if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
 2611                 fdrop(fp, td);
 2612                 return (EBADF);
 2613         }
 2614 
 2615         /* Iterate over the ioctl handlers */
 2616         cmd = args->cmd & 0xffff;
 2617         sx_slock(&linux_ioctl_sx);
 2618         mtx_lock(&Giant);
 2619         TAILQ_FOREACH(he, &handlers, list) {
 2620                 if (cmd >= he->low && cmd <= he->high) {
 2621                         error = (*he->func)(td, args);
 2622                         if (error != ENOIOCTL) {
 2623                                 mtx_unlock(&Giant);
 2624                                 sx_sunlock(&linux_ioctl_sx);
 2625                                 fdrop(fp, td);
 2626                                 return (error);
 2627                         }
 2628                 }
 2629         }
 2630         mtx_unlock(&Giant);
 2631         sx_sunlock(&linux_ioctl_sx);
 2632         fdrop(fp, td);
 2633 
 2634         linux_msg(td, "ioctl fd=%d, cmd=0x%x ('%c',%d) is not implemented",
 2635             args->fd, (int)(args->cmd & 0xffff),
 2636             (int)(args->cmd & 0xff00) >> 8, (int)(args->cmd & 0xff));
 2637 
 2638         return (EINVAL);
 2639 }
 2640 
 2641 int
 2642 linux_ioctl_register_handler(struct linux_ioctl_handler *h)
 2643 {
 2644         struct handler_element *he, *cur;
 2645 
 2646         if (h == NULL || h->func == NULL)
 2647                 return (EINVAL);
 2648 
 2649         /*
 2650          * Reuse the element if the handler is already on the list, otherwise
 2651          * create a new element.
 2652          */
 2653         sx_xlock(&linux_ioctl_sx);
 2654         TAILQ_FOREACH(he, &handlers, list) {
 2655                 if (he->func == h->func)
 2656                         break;
 2657         }
 2658         if (he == NULL) {
 2659                 MALLOC(he, struct handler_element *, sizeof(*he),
 2660                     M_LINUX, M_WAITOK);
 2661                 he->func = h->func;
 2662         } else
 2663                 TAILQ_REMOVE(&handlers, he, list);
 2664 
 2665         /* Initialize range information. */
 2666         he->low = h->low;
 2667         he->high = h->high;
 2668         he->span = h->high - h->low + 1;
 2669 
 2670         /* Add the element to the list, sorted on span. */
 2671         TAILQ_FOREACH(cur, &handlers, list) {
 2672                 if (cur->span > he->span) {
 2673                         TAILQ_INSERT_BEFORE(cur, he, list);
 2674                         sx_xunlock(&linux_ioctl_sx);
 2675                         return (0);
 2676                 }
 2677         }
 2678         TAILQ_INSERT_TAIL(&handlers, he, list);
 2679         sx_xunlock(&linux_ioctl_sx);
 2680 
 2681         return (0);
 2682 }
 2683 
 2684 int
 2685 linux_ioctl_unregister_handler(struct linux_ioctl_handler *h)
 2686 {
 2687         struct handler_element *he;
 2688 
 2689         if (h == NULL || h->func == NULL)
 2690                 return (EINVAL);
 2691 
 2692         sx_xlock(&linux_ioctl_sx);
 2693         TAILQ_FOREACH(he, &handlers, list) {
 2694                 if (he->func == h->func) {
 2695                         TAILQ_REMOVE(&handlers, he, list);
 2696                         sx_xunlock(&linux_ioctl_sx);
 2697                         FREE(he, M_LINUX);
 2698                         return (0);
 2699                 }
 2700         }
 2701         sx_xunlock(&linux_ioctl_sx);
 2702 
 2703         return (EINVAL);
 2704 }

Cache object: 795586ea5d58c2dd6aa2dce1ce2f59a1


[ 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.