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