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