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