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


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

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

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

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

Cache object: 5eb9d958fa03111eaeb854374bb36f72


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