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