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


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

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

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

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

Cache object: bcd1bad057dd1e5a54cbe6e98f4767c6


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