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