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