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