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


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

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

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

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

Cache object: 81ab0da33bedfe2cb35f434254c68edb


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