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