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