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