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


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

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

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: aab3a997bbe22ceff7ca572d89141b07


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