xref: /freebsd/sys/compat/linux/linux_ioctl.c (revision 31eec6fe1aea614e89060af0554abe1a98d8d8ed)
1898b0535SWarner Losh /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
37f2d13d6SPedro F. Giffuni  *
49a14aa01SUlrich Spörlein  * Copyright (c) 1994-1995 Søren Schmidt
5c21dee17SSøren Schmidt  * All rights reserved.
6c21dee17SSøren Schmidt  *
7c21dee17SSøren Schmidt  * Redistribution and use in source and binary forms, with or without
8c21dee17SSøren Schmidt  * modification, are permitted provided that the following conditions
9c21dee17SSøren Schmidt  * are met:
10c21dee17SSøren Schmidt  * 1. Redistributions of source code must retain the above copyright
110ba1b365SEd Maste  *    notice, this list of conditions and the following disclaimer.
12c21dee17SSøren Schmidt  * 2. Redistributions in binary form must reproduce the above copyright
13c21dee17SSøren Schmidt  *    notice, this list of conditions and the following disclaimer in the
14c21dee17SSøren Schmidt  *    documentation and/or other materials provided with the distribution.
15c21dee17SSøren Schmidt  *
160ba1b365SEd Maste  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
170ba1b365SEd Maste  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
180ba1b365SEd Maste  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
190ba1b365SEd Maste  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
200ba1b365SEd Maste  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
210ba1b365SEd Maste  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
220ba1b365SEd Maste  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
230ba1b365SEd Maste  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
240ba1b365SEd Maste  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
250ba1b365SEd Maste  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
260ba1b365SEd Maste  * SUCH DAMAGE.
27c21dee17SSøren Schmidt  */
28c21dee17SSøren Schmidt 
29c21dee17SSøren Schmidt #include <sys/param.h>
304a144410SRobert Watson #include <sys/capsicum.h>
319debe213SLuoqi Chen #include <sys/cdio.h>
3200d25f51SPoul-Henning Kamp #include <sys/consio.h>
33d8e53d94SDmitry Chagin #include <sys/disk.h>
34d8e53d94SDmitry Chagin #include <sys/dvdio.h>
353ac4d1efSBruce Evans #include <sys/fcntl.h>
3671455815SBruce Evans #include <sys/filio.h>
37ebd8672cSBjoern A. Zeeb #include <sys/jail.h>
3800d25f51SPoul-Henning Kamp #include <sys/kbio.h>
3946888dedSMark Johnston #include <sys/kcov.h>
40ad6d226dSJohn Baldwin #include <sys/kernel.h>
4143bef515SMarcel Moolenaar #include <sys/linker_set.h>
42ad6d226dSJohn Baldwin #include <sys/lock.h>
4343bef515SMarcel Moolenaar #include <sys/malloc.h>
44d8e53d94SDmitry Chagin #include <sys/mman.h>
458cdcad81SDag-Erling Smørgrav #include <sys/proc.h>
468739cd44SCraig Rodrigues #include <sys/sbuf.h>
478cdcad81SDag-Erling Smørgrav #include <sys/sockio.h>
488cdcad81SDag-Erling Smørgrav #include <sys/soundcard.h>
49f9b0675bSDmitry Chagin #include <sys/syscallsubr.h>
5060c6d236SAlexander Leidinger #include <sys/sysctl.h>
51d8e53d94SDmitry Chagin #include <sys/sysproto.h>
52d8e53d94SDmitry Chagin #include <sys/sx.h>
538cdcad81SDag-Erling Smørgrav #include <sys/tty.h>
54603724d3SBjoern A. Zeeb 
55d66a5066SPeter Wemm #include <net/if.h>
5676039bc8SGleb Smirnoff #include <net/if_var.h>
573713cbffSMike Smith #include <net/if_dl.h>
583713cbffSMike Smith #include <net/if_types.h>
591f3dad5aSBruce Evans 
606e1d05bbSDmitry Chagin #include <dev/evdev/input.h>
61eedfc35cSWojciech A. Koszek #include <dev/usb/usb_ioctl.h>
62eedfc35cSWojciech A. Koszek 
631997c537SDavid E. O'Brien #ifdef COMPAT_LINUX32
644af27623STim J. Robbins #include <machine/../linux32/linux.h>
654af27623STim J. Robbins #include <machine/../linux32/linux32_proto.h>
661997c537SDavid E. O'Brien #else
671997c537SDavid E. O'Brien #include <machine/../linux/linux.h>
681997c537SDavid E. O'Brien #include <machine/../linux/linux_proto.h>
694af27623STim J. Robbins #endif
705231fb20SDavid E. O'Brien 
71d151344dSDmitry Chagin #include <compat/linux/linux_common.h>
72607d46efSMarcel Moolenaar #include <compat/linux/linux_ioctl.h>
73607d46efSMarcel Moolenaar #include <compat/linux/linux_mib.h>
7413f20d7eSDmitry Chagin #include <compat/linux/linux_socket.h>
75c8a79231SDmitry Chagin #include <compat/linux/linux_time.h>
76607d46efSMarcel Moolenaar #include <compat/linux/linux_util.h>
77c21dee17SSøren Schmidt 
78b85e1f7dSAlexander Leidinger #include <contrib/v4l/videodev.h>
797b6bedd3SAlexander Leidinger #include <compat/linux/linux_videodev_compat.h>
807b6bedd3SAlexander Leidinger 
81b85e1f7dSAlexander Leidinger #include <contrib/v4l/videodev2.h>
8215bf9014SAlexander Leidinger #include <compat/linux/linux_videodev2_compat.h>
8315bf9014SAlexander Leidinger 
84fcaf473cSAlexander Motin #include <cam/scsi/scsi_sg.h>
85fcaf473cSAlexander Motin 
86ad9cc86bSChuck Tuffli #include <dev/nvme/nvme_linux.h>
87ad9cc86bSChuck Tuffli 
8853efdb55SConrad Meyer #define	DEFINE_LINUX_IOCTL_SET(shortname, SHORTNAME)		\
8953efdb55SConrad Meyer static linux_ioctl_function_t linux_ioctl_ ## shortname;	\
9053efdb55SConrad Meyer static struct linux_ioctl_handler shortname ## _handler = {	\
9153efdb55SConrad Meyer 	.func = linux_ioctl_ ## shortname,			\
9253efdb55SConrad Meyer 	.low = LINUX_IOCTL_ ## SHORTNAME ## _MIN,		\
9353efdb55SConrad Meyer 	.high = LINUX_IOCTL_ ## SHORTNAME ## _MAX,		\
9453efdb55SConrad Meyer };								\
9553efdb55SConrad Meyer DATA_SET(linux_ioctl_handler_set, shortname ## _handler)
9643bef515SMarcel Moolenaar 
9753efdb55SConrad Meyer DEFINE_LINUX_IOCTL_SET(cdrom, CDROM);
9853efdb55SConrad Meyer DEFINE_LINUX_IOCTL_SET(vfat, VFAT);
9953efdb55SConrad Meyer DEFINE_LINUX_IOCTL_SET(console, CONSOLE);
10053efdb55SConrad Meyer DEFINE_LINUX_IOCTL_SET(hdio, HDIO);
10153efdb55SConrad Meyer DEFINE_LINUX_IOCTL_SET(disk, DISK);
10253efdb55SConrad Meyer DEFINE_LINUX_IOCTL_SET(socket, SOCKET);
10353efdb55SConrad Meyer DEFINE_LINUX_IOCTL_SET(sound, SOUND);
10453efdb55SConrad Meyer DEFINE_LINUX_IOCTL_SET(termio, TERMIO);
10553efdb55SConrad Meyer DEFINE_LINUX_IOCTL_SET(private, PRIVATE);
10653efdb55SConrad Meyer DEFINE_LINUX_IOCTL_SET(drm, DRM);
10753efdb55SConrad Meyer DEFINE_LINUX_IOCTL_SET(sg, SG);
10853efdb55SConrad Meyer DEFINE_LINUX_IOCTL_SET(v4l, VIDEO);
10953efdb55SConrad Meyer DEFINE_LINUX_IOCTL_SET(v4l2, VIDEO2);
11053efdb55SConrad Meyer DEFINE_LINUX_IOCTL_SET(fbsd_usb, FBSD_LUSB);
11153efdb55SConrad Meyer DEFINE_LINUX_IOCTL_SET(evdev, EVDEV);
11253efdb55SConrad Meyer DEFINE_LINUX_IOCTL_SET(kcov, KCOV);
113ad9cc86bSChuck Tuffli #ifndef COMPAT_LINUX32
114ad9cc86bSChuck Tuffli DEFINE_LINUX_IOCTL_SET(nvme, NVME);
115ad9cc86bSChuck Tuffli #endif
11643bef515SMarcel Moolenaar 
11753efdb55SConrad Meyer #undef DEFINE_LINUX_IOCTL_SET
11853efdb55SConrad Meyer 
11953efdb55SConrad Meyer static int linux_ioctl_special(struct thread *, struct linux_ioctl_args *);
12043bef515SMarcel Moolenaar 
121d6d9ddd4SMateusz Guzik /*
122d6d9ddd4SMateusz Guzik  * Keep sorted by low.
123d6d9ddd4SMateusz Guzik  */
124d6d9ddd4SMateusz Guzik static struct linux_ioctl_handler linux_ioctls[] = {
125d6d9ddd4SMateusz Guzik 	{ .func = linux_ioctl_termio, .low = LINUX_IOCTL_TERMIO_MIN,
126d6d9ddd4SMateusz Guzik 	    .high = LINUX_IOCTL_TERMIO_MAX },
127d6d9ddd4SMateusz Guzik };
128d6d9ddd4SMateusz Guzik 
1298fc08087STijl Coosemans #ifdef __i386__
1308fc08087STijl Coosemans static TAILQ_HEAD(, linux_ioctl_handler_element) linux_ioctl_handlers =
1318fc08087STijl Coosemans     TAILQ_HEAD_INITIALIZER(linux_ioctl_handlers);
132ad6d226dSJohn Baldwin static struct sx linux_ioctl_sx;
133eae594f7SEd Maste SX_SYSINIT(linux_ioctl, &linux_ioctl_sx, "Linux ioctl handlers");
1348fc08087STijl Coosemans #else
1358fc08087STijl Coosemans extern TAILQ_HEAD(, linux_ioctl_handler_element) linux_ioctl_handlers;
1368fc08087STijl Coosemans extern struct sx linux_ioctl_sx;
1378fc08087STijl Coosemans #endif
1388fc08087STijl Coosemans #ifdef COMPAT_LINUX32
1398fc08087STijl Coosemans static TAILQ_HEAD(, linux_ioctl_handler_element) linux32_ioctl_handlers =
1408fc08087STijl Coosemans     TAILQ_HEAD_INITIALIZER(linux32_ioctl_handlers);
1418fc08087STijl Coosemans #endif
14243bef515SMarcel Moolenaar 
14371e9d5f9SPoul-Henning Kamp /*
14471e9d5f9SPoul-Henning Kamp  * hdio related ioctls for VMWare support
14571e9d5f9SPoul-Henning Kamp  */
14671e9d5f9SPoul-Henning Kamp 
14771e9d5f9SPoul-Henning Kamp struct linux_hd_geometry {
148cc5aa0a4SJohn Baldwin 	uint8_t		heads;
149cc5aa0a4SJohn Baldwin 	uint8_t		sectors;
150cc5aa0a4SJohn Baldwin 	uint16_t	cylinders;
151cc5aa0a4SJohn Baldwin 	uint32_t	start;
15271e9d5f9SPoul-Henning Kamp };
15371e9d5f9SPoul-Henning Kamp 
15471e9d5f9SPoul-Henning Kamp struct linux_hd_big_geometry {
155cc5aa0a4SJohn Baldwin 	uint8_t		heads;
156cc5aa0a4SJohn Baldwin 	uint8_t		sectors;
157cc5aa0a4SJohn Baldwin 	uint32_t	cylinders;
158cc5aa0a4SJohn Baldwin 	uint32_t	start;
15971e9d5f9SPoul-Henning Kamp };
16071e9d5f9SPoul-Henning Kamp 
16171e9d5f9SPoul-Henning Kamp static int
linux_ioctl_hdio(struct thread * td,struct linux_ioctl_args * args)16271e9d5f9SPoul-Henning Kamp linux_ioctl_hdio(struct thread *td, struct linux_ioctl_args *args)
16371e9d5f9SPoul-Henning Kamp {
16471e9d5f9SPoul-Henning Kamp 	struct file *fp;
16571e9d5f9SPoul-Henning Kamp 	int error;
16671e9d5f9SPoul-Henning Kamp 	u_int sectorsize, fwcylinders, fwheads, fwsectors;
16771e9d5f9SPoul-Henning Kamp 	off_t mediasize, bytespercyl;
16871e9d5f9SPoul-Henning Kamp 
169cbd92ce6SMatt Macy 	error = fget(td, args->fd, &cap_ioctl_rights, &fp);
1707008be5bSPawel Jakub Dawidek 	if (error != 0)
17171e9d5f9SPoul-Henning Kamp 		return (error);
17271e9d5f9SPoul-Henning Kamp 	switch (args->cmd & 0xffff) {
17371e9d5f9SPoul-Henning Kamp 	case LINUX_HDIO_GET_GEO:
17471e9d5f9SPoul-Henning Kamp 	case LINUX_HDIO_GET_GEO_BIG:
17571e9d5f9SPoul-Henning Kamp 		error = fo_ioctl(fp, DIOCGMEDIASIZE,
17671e9d5f9SPoul-Henning Kamp 			(caddr_t)&mediasize, td->td_ucred, td);
17771e9d5f9SPoul-Henning Kamp 		if (!error)
17871e9d5f9SPoul-Henning Kamp 			error = fo_ioctl(fp, DIOCGSECTORSIZE,
17971e9d5f9SPoul-Henning Kamp 				(caddr_t)&sectorsize, td->td_ucred, td);
18071e9d5f9SPoul-Henning Kamp 		if (!error)
18171e9d5f9SPoul-Henning Kamp 			error = fo_ioctl(fp, DIOCGFWHEADS,
18271e9d5f9SPoul-Henning Kamp 				(caddr_t)&fwheads, td->td_ucred, td);
18371e9d5f9SPoul-Henning Kamp 		if (!error)
18471e9d5f9SPoul-Henning Kamp 			error = fo_ioctl(fp, DIOCGFWSECTORS,
18571e9d5f9SPoul-Henning Kamp 				(caddr_t)&fwsectors, td->td_ucred, td);
18671e9d5f9SPoul-Henning Kamp 		/*
18771e9d5f9SPoul-Henning Kamp 		 * XXX: DIOCGFIRSTOFFSET is not yet implemented, so
18871e9d5f9SPoul-Henning Kamp 		 * so pretend that GEOM always says 0. This is NOT VALID
18971e9d5f9SPoul-Henning Kamp 		 * for slices or partitions, only the per-disk raw devices.
19071e9d5f9SPoul-Henning Kamp 		 */
19171e9d5f9SPoul-Henning Kamp 
19271e9d5f9SPoul-Henning Kamp 		fdrop(fp, td);
19371e9d5f9SPoul-Henning Kamp 		if (error)
19471e9d5f9SPoul-Henning Kamp 			return (error);
19571e9d5f9SPoul-Henning Kamp 		/*
19671e9d5f9SPoul-Henning Kamp 		 * 1. Calculate the number of bytes in a cylinder,
19771e9d5f9SPoul-Henning Kamp 		 *    given the firmware's notion of heads and sectors
19871e9d5f9SPoul-Henning Kamp 		 *    per cylinder.
19971e9d5f9SPoul-Henning Kamp 		 * 2. Calculate the number of cylinders, given the total
20071e9d5f9SPoul-Henning Kamp 		 *    size of the media.
20171e9d5f9SPoul-Henning Kamp 		 * All internal calculations should have 64-bit precision.
20271e9d5f9SPoul-Henning Kamp 		 */
20371e9d5f9SPoul-Henning Kamp 		bytespercyl = (off_t) sectorsize * fwheads * fwsectors;
20471e9d5f9SPoul-Henning Kamp 		fwcylinders = mediasize / bytespercyl;
205c5156c77SDmitry Chagin 
20671e9d5f9SPoul-Henning Kamp 		if ((args->cmd & 0xffff) == LINUX_HDIO_GET_GEO) {
20771e9d5f9SPoul-Henning Kamp 			struct linux_hd_geometry hdg;
20871e9d5f9SPoul-Henning Kamp 
20971e9d5f9SPoul-Henning Kamp 			hdg.cylinders = fwcylinders;
21071e9d5f9SPoul-Henning Kamp 			hdg.heads = fwheads;
21171e9d5f9SPoul-Henning Kamp 			hdg.sectors = fwsectors;
21271e9d5f9SPoul-Henning Kamp 			hdg.start = 0;
21371e9d5f9SPoul-Henning Kamp 			error = copyout(&hdg, (void *)args->arg, sizeof(hdg));
21471e9d5f9SPoul-Henning Kamp 		} else if ((args->cmd & 0xffff) == LINUX_HDIO_GET_GEO_BIG) {
21571e9d5f9SPoul-Henning Kamp 			struct linux_hd_big_geometry hdbg;
21671e9d5f9SPoul-Henning Kamp 
217d851b216SEd Maste 			memset(&hdbg, 0, sizeof(hdbg));
21871e9d5f9SPoul-Henning Kamp 			hdbg.cylinders = fwcylinders;
21971e9d5f9SPoul-Henning Kamp 			hdbg.heads = fwheads;
22071e9d5f9SPoul-Henning Kamp 			hdbg.sectors = fwsectors;
22171e9d5f9SPoul-Henning Kamp 			hdbg.start = 0;
22271e9d5f9SPoul-Henning Kamp 			error = copyout(&hdbg, (void *)args->arg, sizeof(hdbg));
22371e9d5f9SPoul-Henning Kamp 		}
22471e9d5f9SPoul-Henning Kamp 		return (error);
22571e9d5f9SPoul-Henning Kamp 		break;
22671e9d5f9SPoul-Henning Kamp 	default:
22771e9d5f9SPoul-Henning Kamp 		/* XXX */
22871e9d5f9SPoul-Henning Kamp 		linux_msg(td,
22963ed2e36SConrad Meyer 			"%s fd=%d, cmd=0x%x ('%c',%d) is not implemented",
23063ed2e36SConrad Meyer 			__func__, args->fd, args->cmd,
23171e9d5f9SPoul-Henning Kamp 			(int)(args->cmd & 0xff00) >> 8,
23271e9d5f9SPoul-Henning Kamp 			(int)(args->cmd & 0xff));
23371e9d5f9SPoul-Henning Kamp 		break;
23471e9d5f9SPoul-Henning Kamp 	}
23571e9d5f9SPoul-Henning Kamp 	fdrop(fp, td);
23671e9d5f9SPoul-Henning Kamp 	return (ENOIOCTL);
23771e9d5f9SPoul-Henning Kamp }
23871e9d5f9SPoul-Henning Kamp 
2399deb82d4SNick Sayer static int
linux_ioctl_disk(struct thread * td,struct linux_ioctl_args * args)240b40ce416SJulian Elischer linux_ioctl_disk(struct thread *td, struct linux_ioctl_args *args)
2419deb82d4SNick Sayer {
242426da3bcSAlfred Perlstein 	struct file *fp;
2439deb82d4SNick Sayer 	int error;
244aa754121SEdward Tomasz Napierala 	u_int sectorsize, psectorsize;
245b9594cd9SEdward Tomasz Napierala 	uint64_t blksize64;
246aa754121SEdward Tomasz Napierala 	off_t mediasize, stripesize;
2479deb82d4SNick Sayer 
248cbd92ce6SMatt Macy 	error = fget(td, args->fd, &cap_ioctl_rights, &fp);
2497008be5bSPawel Jakub Dawidek 	if (error != 0)
250a4db4953SAlfred Perlstein 		return (error);
2519deb82d4SNick Sayer 	switch (args->cmd & 0xffff) {
2529deb82d4SNick Sayer 	case LINUX_BLKGETSIZE:
25310c665efSPoul-Henning Kamp 		error = fo_ioctl(fp, DIOCGSECTORSIZE,
25410c665efSPoul-Henning Kamp 		    (caddr_t)&sectorsize, td->td_ucred, td);
25510c665efSPoul-Henning Kamp 		if (!error)
25610c665efSPoul-Henning Kamp 			error = fo_ioctl(fp, DIOCGMEDIASIZE,
25710c665efSPoul-Henning Kamp 			    (caddr_t)&mediasize, td->td_ucred, td);
258426da3bcSAlfred Perlstein 		fdrop(fp, td);
2599deb82d4SNick Sayer 		if (error)
2609deb82d4SNick Sayer 			return (error);
26110c665efSPoul-Henning Kamp 		sectorsize = mediasize / sectorsize;
26210c665efSPoul-Henning Kamp 		/*
26310c665efSPoul-Henning Kamp 		 * XXX: How do we know we return the right size of integer ?
26410c665efSPoul-Henning Kamp 		 */
26510c665efSPoul-Henning Kamp 		return (copyout(&sectorsize, (void *)args->arg,
26610c665efSPoul-Henning Kamp 		    sizeof(sectorsize)));
26771e9d5f9SPoul-Henning Kamp 		break;
268b9594cd9SEdward Tomasz Napierala 	case LINUX_BLKGETSIZE64:
269b9594cd9SEdward Tomasz Napierala 		error = fo_ioctl(fp, DIOCGMEDIASIZE,
270b9594cd9SEdward Tomasz Napierala 		    (caddr_t)&mediasize, td->td_ucred, td);
271b9594cd9SEdward Tomasz Napierala 		fdrop(fp, td);
272b9594cd9SEdward Tomasz Napierala 		if (error)
273b9594cd9SEdward Tomasz Napierala 			return (error);
27421cc0918SElliott Mitchell 		blksize64 = mediasize;
275b9594cd9SEdward Tomasz Napierala 		return (copyout(&blksize64, (void *)args->arg,
276b9594cd9SEdward Tomasz Napierala 		    sizeof(blksize64)));
277ede2869cSDmitry Chagin 	case LINUX_BLKSSZGET:
278ede2869cSDmitry Chagin 		error = fo_ioctl(fp, DIOCGSECTORSIZE,
279ede2869cSDmitry Chagin 		    (caddr_t)&sectorsize, td->td_ucred, td);
280ede2869cSDmitry Chagin 		fdrop(fp, td);
281ede2869cSDmitry Chagin 		if (error)
282ede2869cSDmitry Chagin 			return (error);
283ede2869cSDmitry Chagin 		return (copyout(&sectorsize, (void *)args->arg,
284ede2869cSDmitry Chagin 		    sizeof(sectorsize)));
285ede2869cSDmitry Chagin 		break;
286aa754121SEdward Tomasz Napierala 	case LINUX_BLKPBSZGET:
287aa754121SEdward Tomasz Napierala 		error = fo_ioctl(fp, DIOCGSTRIPESIZE,
288aa754121SEdward Tomasz Napierala 		    (caddr_t)&stripesize, td->td_ucred, td);
289aa754121SEdward Tomasz Napierala 		if (error != 0) {
290aa754121SEdward Tomasz Napierala 			fdrop(fp, td);
291aa754121SEdward Tomasz Napierala 			return (error);
292aa754121SEdward Tomasz Napierala 		}
293aa754121SEdward Tomasz Napierala 		if (stripesize > 0 && stripesize <= 4096) {
294aa754121SEdward Tomasz Napierala 			psectorsize = stripesize;
295aa754121SEdward Tomasz Napierala 		} else  {
296aa754121SEdward Tomasz Napierala 			error = fo_ioctl(fp, DIOCGSECTORSIZE,
297aa754121SEdward Tomasz Napierala 			    (caddr_t)&sectorsize, td->td_ucred, td);
298aa754121SEdward Tomasz Napierala 			if (error != 0) {
299aa754121SEdward Tomasz Napierala 				fdrop(fp, td);
300aa754121SEdward Tomasz Napierala 				return (error);
301aa754121SEdward Tomasz Napierala 			}
302aa754121SEdward Tomasz Napierala 			psectorsize = sectorsize;
303aa754121SEdward Tomasz Napierala 		}
304aa754121SEdward Tomasz Napierala 		fdrop(fp, td);
305aa754121SEdward Tomasz Napierala 		return (copyout(&psectorsize, (void *)args->arg,
306aa754121SEdward Tomasz Napierala 		    sizeof(psectorsize)));
3079deb82d4SNick Sayer 	}
308426da3bcSAlfred Perlstein 	fdrop(fp, td);
3099deb82d4SNick Sayer 	return (ENOIOCTL);
3109deb82d4SNick Sayer }
3119deb82d4SNick Sayer 
31243bef515SMarcel Moolenaar /*
31343bef515SMarcel Moolenaar  * termio related ioctls
31443bef515SMarcel Moolenaar  */
3152394cd9aSJordan K. Hubbard 
3164f735d8eSPeter Wemm struct linux_termio {
3174f735d8eSPeter Wemm 	unsigned short c_iflag;
3184f735d8eSPeter Wemm 	unsigned short c_oflag;
3194f735d8eSPeter Wemm 	unsigned short c_cflag;
3204f735d8eSPeter Wemm 	unsigned short c_lflag;
3214f735d8eSPeter Wemm 	unsigned char c_line;
3224f735d8eSPeter Wemm 	unsigned char c_cc[LINUX_NCC];
3234f735d8eSPeter Wemm };
3244f735d8eSPeter Wemm 
325c21dee17SSøren Schmidt struct linux_termios {
326432d528cSMarcel Moolenaar 	unsigned int c_iflag;
327432d528cSMarcel Moolenaar 	unsigned int c_oflag;
328432d528cSMarcel Moolenaar 	unsigned int c_cflag;
329432d528cSMarcel Moolenaar 	unsigned int c_lflag;
330c21dee17SSøren Schmidt 	unsigned char c_line;
331c21dee17SSøren Schmidt 	unsigned char c_cc[LINUX_NCCS];
332c21dee17SSøren Schmidt };
333c21dee17SSøren Schmidt 
334c21dee17SSøren Schmidt struct linux_winsize {
335c21dee17SSøren Schmidt 	unsigned short ws_row, ws_col;
336c21dee17SSøren Schmidt 	unsigned short ws_xpixel, ws_ypixel;
337c21dee17SSøren Schmidt };
338c21dee17SSøren Schmidt 
339bc093719SEd Schouten struct speedtab {
340bc093719SEd Schouten 	int sp_speed;			/* Speed. */
341bc093719SEd Schouten 	int sp_code;			/* Code. */
342bc093719SEd Schouten };
343bc093719SEd Schouten 
344c21dee17SSøren Schmidt static struct speedtab sptab[] = {
345432d528cSMarcel Moolenaar 	{ B0, LINUX_B0 }, { B50, LINUX_B50 },
346432d528cSMarcel Moolenaar 	{ B75, LINUX_B75 }, { B110, LINUX_B110 },
347432d528cSMarcel Moolenaar 	{ B134, LINUX_B134 }, { B150, LINUX_B150 },
348432d528cSMarcel Moolenaar 	{ B200, LINUX_B200 }, { B300, LINUX_B300 },
349432d528cSMarcel Moolenaar 	{ B600, LINUX_B600 }, { B1200, LINUX_B1200 },
350432d528cSMarcel Moolenaar 	{ B1800, LINUX_B1800 }, { B2400, LINUX_B2400 },
351432d528cSMarcel Moolenaar 	{ B4800, LINUX_B4800 }, { B9600, LINUX_B9600 },
352432d528cSMarcel Moolenaar 	{ B19200, LINUX_B19200 }, { B38400, LINUX_B38400 },
353432d528cSMarcel Moolenaar 	{ B57600, LINUX_B57600 }, { B115200, LINUX_B115200 },
354432d528cSMarcel Moolenaar 	{-1, -1 }
355c21dee17SSøren Schmidt };
356c21dee17SSøren Schmidt 
3579c5ee423SPeter Wemm struct linux_serial_struct {
3589c5ee423SPeter Wemm 	int	type;
3599c5ee423SPeter Wemm 	int	line;
3609c5ee423SPeter Wemm 	int	port;
3619c5ee423SPeter Wemm 	int	irq;
3629c5ee423SPeter Wemm 	int	flags;
3639c5ee423SPeter Wemm 	int	xmit_fifo_size;
3649c5ee423SPeter Wemm 	int	custom_divisor;
3659c5ee423SPeter Wemm 	int	baud_base;
3669c5ee423SPeter Wemm 	unsigned short close_delay;
3679c5ee423SPeter Wemm 	char	reserved_char[2];
3689c5ee423SPeter Wemm 	int	hub6;
3699c5ee423SPeter Wemm 	unsigned short closing_wait;
3709c5ee423SPeter Wemm 	unsigned short closing_wait2;
3719c5ee423SPeter Wemm 	int	reserved[4];
3729c5ee423SPeter Wemm };
3739c5ee423SPeter Wemm 
374c21dee17SSøren Schmidt static int
linux_to_bsd_speed(int code,struct speedtab * table)375c21dee17SSøren Schmidt linux_to_bsd_speed(int code, struct speedtab *table)
376c21dee17SSøren Schmidt {
377c21dee17SSøren Schmidt 	for ( ; table->sp_code != -1; table++)
378c21dee17SSøren Schmidt 		if (table->sp_code == code)
379c21dee17SSøren Schmidt 			return (table->sp_speed);
380340f4a8dSEd Maste 	return (-1);
381c21dee17SSøren Schmidt }
382c21dee17SSøren Schmidt 
383c21dee17SSøren Schmidt static int
bsd_to_linux_speed(int speed,struct speedtab * table)384c21dee17SSøren Schmidt bsd_to_linux_speed(int speed, struct speedtab *table)
385c21dee17SSøren Schmidt {
386c21dee17SSøren Schmidt 	for ( ; table->sp_speed != -1; table++)
387c21dee17SSøren Schmidt 		if (table->sp_speed == speed)
388c21dee17SSøren Schmidt 			return (table->sp_code);
389340f4a8dSEd Maste 	return (-1);
390c21dee17SSøren Schmidt }
391c21dee17SSøren Schmidt 
392c21dee17SSøren Schmidt static void
bsd_to_linux_termios(struct termios * bios,struct linux_termios * lios)39343bef515SMarcel Moolenaar bsd_to_linux_termios(struct termios *bios, struct linux_termios *lios)
394c21dee17SSøren Schmidt {
395c23670e2SGary Palmer 	int i;
396c21dee17SSøren Schmidt 
39743bef515SMarcel Moolenaar 	lios->c_iflag = 0;
39843bef515SMarcel Moolenaar 	if (bios->c_iflag & IGNBRK)
39943bef515SMarcel Moolenaar 		lios->c_iflag |= LINUX_IGNBRK;
40043bef515SMarcel Moolenaar 	if (bios->c_iflag & BRKINT)
40143bef515SMarcel Moolenaar 		lios->c_iflag |= LINUX_BRKINT;
40243bef515SMarcel Moolenaar 	if (bios->c_iflag & IGNPAR)
40343bef515SMarcel Moolenaar 		lios->c_iflag |= LINUX_IGNPAR;
40443bef515SMarcel Moolenaar 	if (bios->c_iflag & PARMRK)
40543bef515SMarcel Moolenaar 		lios->c_iflag |= LINUX_PARMRK;
40643bef515SMarcel Moolenaar 	if (bios->c_iflag & INPCK)
40743bef515SMarcel Moolenaar 		lios->c_iflag |= LINUX_INPCK;
40843bef515SMarcel Moolenaar 	if (bios->c_iflag & ISTRIP)
40943bef515SMarcel Moolenaar 		lios->c_iflag |= LINUX_ISTRIP;
41043bef515SMarcel Moolenaar 	if (bios->c_iflag & INLCR)
41143bef515SMarcel Moolenaar 		lios->c_iflag |= LINUX_INLCR;
41243bef515SMarcel Moolenaar 	if (bios->c_iflag & IGNCR)
41343bef515SMarcel Moolenaar 		lios->c_iflag |= LINUX_IGNCR;
41443bef515SMarcel Moolenaar 	if (bios->c_iflag & ICRNL)
41543bef515SMarcel Moolenaar 		lios->c_iflag |= LINUX_ICRNL;
41643bef515SMarcel Moolenaar 	if (bios->c_iflag & IXON)
41743bef515SMarcel Moolenaar 		lios->c_iflag |= LINUX_IXON;
41843bef515SMarcel Moolenaar 	if (bios->c_iflag & IXANY)
41943bef515SMarcel Moolenaar 		lios->c_iflag |= LINUX_IXANY;
42043bef515SMarcel Moolenaar 	if (bios->c_iflag & IXOFF)
42143bef515SMarcel Moolenaar 		lios->c_iflag |= LINUX_IXOFF;
42243bef515SMarcel Moolenaar 	if (bios->c_iflag & IMAXBEL)
42343bef515SMarcel Moolenaar 		lios->c_iflag |= LINUX_IMAXBEL;
424*31eec6feSEdward Tomasz Napierala 	if (bios->c_iflag & IUTF8)
425*31eec6feSEdward Tomasz Napierala 		lios->c_iflag |= LINUX_IUTF8;
426c21dee17SSøren Schmidt 
42743bef515SMarcel Moolenaar 	lios->c_oflag = 0;
42843bef515SMarcel Moolenaar 	if (bios->c_oflag & OPOST)
42943bef515SMarcel Moolenaar 		lios->c_oflag |= LINUX_OPOST;
43043bef515SMarcel Moolenaar 	if (bios->c_oflag & ONLCR)
43143bef515SMarcel Moolenaar 		lios->c_oflag |= LINUX_ONLCR;
432bc093719SEd Schouten 	if (bios->c_oflag & TAB3)
43343bef515SMarcel Moolenaar 		lios->c_oflag |= LINUX_XTABS;
434c21dee17SSøren Schmidt 
43543bef515SMarcel Moolenaar 	lios->c_cflag = bsd_to_linux_speed(bios->c_ispeed, sptab);
43643bef515SMarcel Moolenaar 	lios->c_cflag |= (bios->c_cflag & CSIZE) >> 4;
43743bef515SMarcel Moolenaar 	if (bios->c_cflag & CSTOPB)
43843bef515SMarcel Moolenaar 		lios->c_cflag |= LINUX_CSTOPB;
43943bef515SMarcel Moolenaar 	if (bios->c_cflag & CREAD)
44043bef515SMarcel Moolenaar 		lios->c_cflag |= LINUX_CREAD;
44143bef515SMarcel Moolenaar 	if (bios->c_cflag & PARENB)
44243bef515SMarcel Moolenaar 		lios->c_cflag |= LINUX_PARENB;
44343bef515SMarcel Moolenaar 	if (bios->c_cflag & PARODD)
44443bef515SMarcel Moolenaar 		lios->c_cflag |= LINUX_PARODD;
44543bef515SMarcel Moolenaar 	if (bios->c_cflag & HUPCL)
44643bef515SMarcel Moolenaar 		lios->c_cflag |= LINUX_HUPCL;
44743bef515SMarcel Moolenaar 	if (bios->c_cflag & CLOCAL)
44843bef515SMarcel Moolenaar 		lios->c_cflag |= LINUX_CLOCAL;
44943bef515SMarcel Moolenaar 	if (bios->c_cflag & CRTSCTS)
45043bef515SMarcel Moolenaar 		lios->c_cflag |= LINUX_CRTSCTS;
45143bef515SMarcel Moolenaar 
45243bef515SMarcel Moolenaar 	lios->c_lflag = 0;
45343bef515SMarcel Moolenaar 	if (bios->c_lflag & ISIG)
45443bef515SMarcel Moolenaar 		lios->c_lflag |= LINUX_ISIG;
45543bef515SMarcel Moolenaar 	if (bios->c_lflag & ICANON)
45643bef515SMarcel Moolenaar 		lios->c_lflag |= LINUX_ICANON;
45743bef515SMarcel Moolenaar 	if (bios->c_lflag & ECHO)
45843bef515SMarcel Moolenaar 		lios->c_lflag |= LINUX_ECHO;
45943bef515SMarcel Moolenaar 	if (bios->c_lflag & ECHOE)
46043bef515SMarcel Moolenaar 		lios->c_lflag |= LINUX_ECHOE;
46143bef515SMarcel Moolenaar 	if (bios->c_lflag & ECHOK)
46243bef515SMarcel Moolenaar 		lios->c_lflag |= LINUX_ECHOK;
46343bef515SMarcel Moolenaar 	if (bios->c_lflag & ECHONL)
46443bef515SMarcel Moolenaar 		lios->c_lflag |= LINUX_ECHONL;
46543bef515SMarcel Moolenaar 	if (bios->c_lflag & NOFLSH)
46643bef515SMarcel Moolenaar 		lios->c_lflag |= LINUX_NOFLSH;
46743bef515SMarcel Moolenaar 	if (bios->c_lflag & TOSTOP)
46843bef515SMarcel Moolenaar 		lios->c_lflag |= LINUX_TOSTOP;
46943bef515SMarcel Moolenaar 	if (bios->c_lflag & ECHOCTL)
47043bef515SMarcel Moolenaar 		lios->c_lflag |= LINUX_ECHOCTL;
47143bef515SMarcel Moolenaar 	if (bios->c_lflag & ECHOPRT)
47243bef515SMarcel Moolenaar 		lios->c_lflag |= LINUX_ECHOPRT;
47343bef515SMarcel Moolenaar 	if (bios->c_lflag & ECHOKE)
47443bef515SMarcel Moolenaar 		lios->c_lflag |= LINUX_ECHOKE;
47543bef515SMarcel Moolenaar 	if (bios->c_lflag & FLUSHO)
47643bef515SMarcel Moolenaar 		lios->c_lflag |= LINUX_FLUSHO;
47743bef515SMarcel Moolenaar 	if (bios->c_lflag & PENDIN)
47843bef515SMarcel Moolenaar 		lios->c_lflag |= LINUX_PENDIN;
47943bef515SMarcel Moolenaar 	if (bios->c_lflag & IEXTEN)
48043bef515SMarcel Moolenaar 		lios->c_lflag |= LINUX_IEXTEN;
481c21dee17SSøren Schmidt 
482c21dee17SSøren Schmidt 	for (i=0; i<LINUX_NCCS; i++)
48343bef515SMarcel Moolenaar 		lios->c_cc[i] = LINUX_POSIX_VDISABLE;
48443bef515SMarcel Moolenaar 	lios->c_cc[LINUX_VINTR] = bios->c_cc[VINTR];
48543bef515SMarcel Moolenaar 	lios->c_cc[LINUX_VQUIT] = bios->c_cc[VQUIT];
48643bef515SMarcel Moolenaar 	lios->c_cc[LINUX_VERASE] = bios->c_cc[VERASE];
48743bef515SMarcel Moolenaar 	lios->c_cc[LINUX_VKILL] = bios->c_cc[VKILL];
48843bef515SMarcel Moolenaar 	lios->c_cc[LINUX_VEOF] = bios->c_cc[VEOF];
48943bef515SMarcel Moolenaar 	lios->c_cc[LINUX_VEOL] = bios->c_cc[VEOL];
49043bef515SMarcel Moolenaar 	lios->c_cc[LINUX_VMIN] = bios->c_cc[VMIN];
49143bef515SMarcel Moolenaar 	lios->c_cc[LINUX_VTIME] = bios->c_cc[VTIME];
49243bef515SMarcel Moolenaar 	lios->c_cc[LINUX_VEOL2] = bios->c_cc[VEOL2];
49343bef515SMarcel Moolenaar 	lios->c_cc[LINUX_VSUSP] = bios->c_cc[VSUSP];
49443bef515SMarcel Moolenaar 	lios->c_cc[LINUX_VSTART] = bios->c_cc[VSTART];
49543bef515SMarcel Moolenaar 	lios->c_cc[LINUX_VSTOP] = bios->c_cc[VSTOP];
49643bef515SMarcel Moolenaar 	lios->c_cc[LINUX_VREPRINT] = bios->c_cc[VREPRINT];
49743bef515SMarcel Moolenaar 	lios->c_cc[LINUX_VDISCARD] = bios->c_cc[VDISCARD];
49843bef515SMarcel Moolenaar 	lios->c_cc[LINUX_VWERASE] = bios->c_cc[VWERASE];
49943bef515SMarcel Moolenaar 	lios->c_cc[LINUX_VLNEXT] = bios->c_cc[VLNEXT];
5002cf9eb6cSEdward Tomasz Napierala 	if (linux_preserve_vstatus)
5012cf9eb6cSEdward Tomasz Napierala 		lios->c_cc[LINUX_VSTATUS] = bios->c_cc[VSTATUS];
502c21dee17SSøren Schmidt 
5034f735d8eSPeter Wemm 	for (i=0; i<LINUX_NCCS; i++) {
50419acf030SMarcel Moolenaar 		if (i != LINUX_VMIN && i != LINUX_VTIME &&
50519acf030SMarcel Moolenaar 		    lios->c_cc[i] == _POSIX_VDISABLE)
50643bef515SMarcel Moolenaar 			lios->c_cc[i] = LINUX_POSIX_VDISABLE;
5074f735d8eSPeter Wemm 	}
50843bef515SMarcel Moolenaar 	lios->c_line = 0;
509c21dee17SSøren Schmidt }
510c21dee17SSøren Schmidt 
511c21dee17SSøren Schmidt static void
linux_to_bsd_termios(struct linux_termios * lios,struct termios * bios)51243bef515SMarcel Moolenaar linux_to_bsd_termios(struct linux_termios *lios, struct termios *bios)
513c21dee17SSøren Schmidt {
514c23670e2SGary Palmer 	int i;
51543bef515SMarcel Moolenaar 
51643bef515SMarcel Moolenaar 	bios->c_iflag = 0;
51743bef515SMarcel Moolenaar 	if (lios->c_iflag & LINUX_IGNBRK)
51843bef515SMarcel Moolenaar 		bios->c_iflag |= IGNBRK;
51943bef515SMarcel Moolenaar 	if (lios->c_iflag & LINUX_BRKINT)
52043bef515SMarcel Moolenaar 		bios->c_iflag |= BRKINT;
52143bef515SMarcel Moolenaar 	if (lios->c_iflag & LINUX_IGNPAR)
52243bef515SMarcel Moolenaar 		bios->c_iflag |= IGNPAR;
52343bef515SMarcel Moolenaar 	if (lios->c_iflag & LINUX_PARMRK)
52443bef515SMarcel Moolenaar 		bios->c_iflag |= PARMRK;
52543bef515SMarcel Moolenaar 	if (lios->c_iflag & LINUX_INPCK)
52643bef515SMarcel Moolenaar 		bios->c_iflag |= INPCK;
52743bef515SMarcel Moolenaar 	if (lios->c_iflag & LINUX_ISTRIP)
52843bef515SMarcel Moolenaar 		bios->c_iflag |= ISTRIP;
52943bef515SMarcel Moolenaar 	if (lios->c_iflag & LINUX_INLCR)
53043bef515SMarcel Moolenaar 		bios->c_iflag |= INLCR;
53143bef515SMarcel Moolenaar 	if (lios->c_iflag & LINUX_IGNCR)
53243bef515SMarcel Moolenaar 		bios->c_iflag |= IGNCR;
53343bef515SMarcel Moolenaar 	if (lios->c_iflag & LINUX_ICRNL)
53443bef515SMarcel Moolenaar 		bios->c_iflag |= ICRNL;
53543bef515SMarcel Moolenaar 	if (lios->c_iflag & LINUX_IXON)
53643bef515SMarcel Moolenaar 		bios->c_iflag |= IXON;
53743bef515SMarcel Moolenaar 	if (lios->c_iflag & LINUX_IXANY)
53843bef515SMarcel Moolenaar 		bios->c_iflag |= IXANY;
53943bef515SMarcel Moolenaar 	if (lios->c_iflag & LINUX_IXOFF)
54043bef515SMarcel Moolenaar 		bios->c_iflag |= IXOFF;
54143bef515SMarcel Moolenaar 	if (lios->c_iflag & LINUX_IMAXBEL)
54243bef515SMarcel Moolenaar 		bios->c_iflag |= IMAXBEL;
543*31eec6feSEdward Tomasz Napierala 	if (lios->c_iflag & LINUX_IUTF8)
544*31eec6feSEdward Tomasz Napierala 		bios->c_iflag |= IUTF8;
545c21dee17SSøren Schmidt 
54643bef515SMarcel Moolenaar 	bios->c_oflag = 0;
54743bef515SMarcel Moolenaar 	if (lios->c_oflag & LINUX_OPOST)
54843bef515SMarcel Moolenaar 		bios->c_oflag |= OPOST;
54943bef515SMarcel Moolenaar 	if (lios->c_oflag & LINUX_ONLCR)
55043bef515SMarcel Moolenaar 		bios->c_oflag |= ONLCR;
55143bef515SMarcel Moolenaar 	if (lios->c_oflag & LINUX_XTABS)
552bc093719SEd Schouten 		bios->c_oflag |= TAB3;
553c21dee17SSøren Schmidt 
55443bef515SMarcel Moolenaar 	bios->c_cflag = (lios->c_cflag & LINUX_CSIZE) << 4;
55543bef515SMarcel Moolenaar 	if (lios->c_cflag & LINUX_CSTOPB)
55643bef515SMarcel Moolenaar 		bios->c_cflag |= CSTOPB;
55743bef515SMarcel Moolenaar 	if (lios->c_cflag & LINUX_CREAD)
55843bef515SMarcel Moolenaar 		bios->c_cflag |= CREAD;
55943bef515SMarcel Moolenaar 	if (lios->c_cflag & LINUX_PARENB)
56043bef515SMarcel Moolenaar 		bios->c_cflag |= PARENB;
56143bef515SMarcel Moolenaar 	if (lios->c_cflag & LINUX_PARODD)
56243bef515SMarcel Moolenaar 		bios->c_cflag |= PARODD;
56343bef515SMarcel Moolenaar 	if (lios->c_cflag & LINUX_HUPCL)
56443bef515SMarcel Moolenaar 		bios->c_cflag |= HUPCL;
56543bef515SMarcel Moolenaar 	if (lios->c_cflag & LINUX_CLOCAL)
56643bef515SMarcel Moolenaar 		bios->c_cflag |= CLOCAL;
56743bef515SMarcel Moolenaar 	if (lios->c_cflag & LINUX_CRTSCTS)
56843bef515SMarcel Moolenaar 		bios->c_cflag |= CRTSCTS;
56943bef515SMarcel Moolenaar 
57043bef515SMarcel Moolenaar 	bios->c_lflag = 0;
57143bef515SMarcel Moolenaar 	if (lios->c_lflag & LINUX_ISIG)
57243bef515SMarcel Moolenaar 		bios->c_lflag |= ISIG;
57343bef515SMarcel Moolenaar 	if (lios->c_lflag & LINUX_ICANON)
57443bef515SMarcel Moolenaar 		bios->c_lflag |= ICANON;
57543bef515SMarcel Moolenaar 	if (lios->c_lflag & LINUX_ECHO)
57643bef515SMarcel Moolenaar 		bios->c_lflag |= ECHO;
57743bef515SMarcel Moolenaar 	if (lios->c_lflag & LINUX_ECHOE)
57843bef515SMarcel Moolenaar 		bios->c_lflag |= ECHOE;
57943bef515SMarcel Moolenaar 	if (lios->c_lflag & LINUX_ECHOK)
58043bef515SMarcel Moolenaar 		bios->c_lflag |= ECHOK;
58143bef515SMarcel Moolenaar 	if (lios->c_lflag & LINUX_ECHONL)
58243bef515SMarcel Moolenaar 		bios->c_lflag |= ECHONL;
58343bef515SMarcel Moolenaar 	if (lios->c_lflag & LINUX_NOFLSH)
58443bef515SMarcel Moolenaar 		bios->c_lflag |= NOFLSH;
58543bef515SMarcel Moolenaar 	if (lios->c_lflag & LINUX_TOSTOP)
58643bef515SMarcel Moolenaar 		bios->c_lflag |= TOSTOP;
58743bef515SMarcel Moolenaar 	if (lios->c_lflag & LINUX_ECHOCTL)
58843bef515SMarcel Moolenaar 		bios->c_lflag |= ECHOCTL;
58943bef515SMarcel Moolenaar 	if (lios->c_lflag & LINUX_ECHOPRT)
59043bef515SMarcel Moolenaar 		bios->c_lflag |= ECHOPRT;
59143bef515SMarcel Moolenaar 	if (lios->c_lflag & LINUX_ECHOKE)
59243bef515SMarcel Moolenaar 		bios->c_lflag |= ECHOKE;
59343bef515SMarcel Moolenaar 	if (lios->c_lflag & LINUX_FLUSHO)
59443bef515SMarcel Moolenaar 		bios->c_lflag |= FLUSHO;
59543bef515SMarcel Moolenaar 	if (lios->c_lflag & LINUX_PENDIN)
59643bef515SMarcel Moolenaar 		bios->c_lflag |= PENDIN;
59743bef515SMarcel Moolenaar 	if (lios->c_lflag & LINUX_IEXTEN)
59843bef515SMarcel Moolenaar 		bios->c_lflag |= IEXTEN;
599c21dee17SSøren Schmidt 
600c21dee17SSøren Schmidt 	for (i=0; i<NCCS; i++)
60143bef515SMarcel Moolenaar 		bios->c_cc[i] = _POSIX_VDISABLE;
60243bef515SMarcel Moolenaar 	bios->c_cc[VINTR] = lios->c_cc[LINUX_VINTR];
60343bef515SMarcel Moolenaar 	bios->c_cc[VQUIT] = lios->c_cc[LINUX_VQUIT];
60443bef515SMarcel Moolenaar 	bios->c_cc[VERASE] = lios->c_cc[LINUX_VERASE];
60543bef515SMarcel Moolenaar 	bios->c_cc[VKILL] = lios->c_cc[LINUX_VKILL];
60643bef515SMarcel Moolenaar 	bios->c_cc[VEOF] = lios->c_cc[LINUX_VEOF];
60743bef515SMarcel Moolenaar 	bios->c_cc[VEOL] = lios->c_cc[LINUX_VEOL];
60843bef515SMarcel Moolenaar 	bios->c_cc[VMIN] = lios->c_cc[LINUX_VMIN];
60943bef515SMarcel Moolenaar 	bios->c_cc[VTIME] = lios->c_cc[LINUX_VTIME];
61043bef515SMarcel Moolenaar 	bios->c_cc[VEOL2] = lios->c_cc[LINUX_VEOL2];
61143bef515SMarcel Moolenaar 	bios->c_cc[VSUSP] = lios->c_cc[LINUX_VSUSP];
61243bef515SMarcel Moolenaar 	bios->c_cc[VSTART] = lios->c_cc[LINUX_VSTART];
61343bef515SMarcel Moolenaar 	bios->c_cc[VSTOP] = lios->c_cc[LINUX_VSTOP];
61443bef515SMarcel Moolenaar 	bios->c_cc[VREPRINT] = lios->c_cc[LINUX_VREPRINT];
61543bef515SMarcel Moolenaar 	bios->c_cc[VDISCARD] = lios->c_cc[LINUX_VDISCARD];
61643bef515SMarcel Moolenaar 	bios->c_cc[VWERASE] = lios->c_cc[LINUX_VWERASE];
61743bef515SMarcel Moolenaar 	bios->c_cc[VLNEXT] = lios->c_cc[LINUX_VLNEXT];
6182cf9eb6cSEdward Tomasz Napierala 	if (linux_preserve_vstatus)
6192cf9eb6cSEdward Tomasz Napierala 		bios->c_cc[VSTATUS] = lios->c_cc[LINUX_VSTATUS];
620c21dee17SSøren Schmidt 
6214f735d8eSPeter Wemm 	for (i=0; i<NCCS; i++) {
62219acf030SMarcel Moolenaar 		if (i != VMIN && i != VTIME &&
62319acf030SMarcel Moolenaar 		    bios->c_cc[i] == LINUX_POSIX_VDISABLE)
62443bef515SMarcel Moolenaar 			bios->c_cc[i] = _POSIX_VDISABLE;
6254f735d8eSPeter Wemm 	}
6264f735d8eSPeter Wemm 
62743bef515SMarcel Moolenaar 	bios->c_ispeed = bios->c_ospeed =
62843bef515SMarcel Moolenaar 	    linux_to_bsd_speed(lios->c_cflag & LINUX_CBAUD, sptab);
629c21dee17SSøren Schmidt }
630c21dee17SSøren Schmidt 
6314f735d8eSPeter Wemm static void
bsd_to_linux_termio(struct termios * bios,struct linux_termio * lio)63243bef515SMarcel Moolenaar bsd_to_linux_termio(struct termios *bios, struct linux_termio *lio)
6334f735d8eSPeter Wemm {
63443bef515SMarcel Moolenaar 	struct linux_termios lios;
6354f735d8eSPeter Wemm 
6369866e7bbSEd Maste 	memset(lio, 0, sizeof(*lio));
63743bef515SMarcel Moolenaar 	bsd_to_linux_termios(bios, &lios);
63843bef515SMarcel Moolenaar 	lio->c_iflag = lios.c_iflag;
63943bef515SMarcel Moolenaar 	lio->c_oflag = lios.c_oflag;
64043bef515SMarcel Moolenaar 	lio->c_cflag = lios.c_cflag;
64143bef515SMarcel Moolenaar 	lio->c_lflag = lios.c_lflag;
64243bef515SMarcel Moolenaar 	lio->c_line  = lios.c_line;
64343bef515SMarcel Moolenaar 	memcpy(lio->c_cc, lios.c_cc, LINUX_NCC);
6444f735d8eSPeter Wemm }
6454f735d8eSPeter Wemm 
6464f735d8eSPeter Wemm static void
linux_to_bsd_termio(struct linux_termio * lio,struct termios * bios)64743bef515SMarcel Moolenaar linux_to_bsd_termio(struct linux_termio *lio, struct termios *bios)
6484f735d8eSPeter Wemm {
64943bef515SMarcel Moolenaar 	struct linux_termios lios;
6504f735d8eSPeter Wemm 	int i;
6514f735d8eSPeter Wemm 
65243bef515SMarcel Moolenaar 	lios.c_iflag = lio->c_iflag;
65343bef515SMarcel Moolenaar 	lios.c_oflag = lio->c_oflag;
65443bef515SMarcel Moolenaar 	lios.c_cflag = lio->c_cflag;
65543bef515SMarcel Moolenaar 	lios.c_lflag = lio->c_lflag;
656432d528cSMarcel Moolenaar 	for (i=LINUX_NCC; i<LINUX_NCCS; i++)
65743bef515SMarcel Moolenaar 		lios.c_cc[i] = LINUX_POSIX_VDISABLE;
65843bef515SMarcel Moolenaar 	memcpy(lios.c_cc, lio->c_cc, LINUX_NCC);
65943bef515SMarcel Moolenaar 	linux_to_bsd_termios(&lios, bios);
6604f735d8eSPeter Wemm }
6614f735d8eSPeter Wemm 
66243bef515SMarcel Moolenaar static int
linux_ioctl_termio(struct thread * td,struct linux_ioctl_args * args)663b40ce416SJulian Elischer linux_ioctl_termio(struct thread *td, struct linux_ioctl_args *args)
66443bef515SMarcel Moolenaar {
66543bef515SMarcel Moolenaar 	struct termios bios;
66643bef515SMarcel Moolenaar 	struct linux_termios lios;
66743bef515SMarcel Moolenaar 	struct linux_termio lio;
668426da3bcSAlfred Perlstein 	struct file *fp;
66943bef515SMarcel Moolenaar 	int error;
67043bef515SMarcel Moolenaar 
671cbd92ce6SMatt Macy 	error = fget(td, args->fd, &cap_ioctl_rights, &fp);
6727008be5bSPawel Jakub Dawidek 	if (error != 0)
673a4db4953SAlfred Perlstein 		return (error);
674a4db4953SAlfred Perlstein 
67543bef515SMarcel Moolenaar 	switch (args->cmd & 0xffff) {
67643bef515SMarcel Moolenaar 	case LINUX_TCGETS:
677d49fa1caSRobert Watson 		error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td->td_ucred,
678d49fa1caSRobert Watson 		    td);
67943bef515SMarcel Moolenaar 		if (error)
680426da3bcSAlfred Perlstein 			break;
68143bef515SMarcel Moolenaar 		bsd_to_linux_termios(&bios, &lios);
6824b7ef73dSDag-Erling Smørgrav 		error = copyout(&lios, (void *)args->arg, sizeof(lios));
683426da3bcSAlfred Perlstein 		break;
68443bef515SMarcel Moolenaar 
68543bef515SMarcel Moolenaar 	case LINUX_TCSETS:
6864b7ef73dSDag-Erling Smørgrav 		error = copyin((void *)args->arg, &lios, sizeof(lios));
68743bef515SMarcel Moolenaar 		if (error)
688426da3bcSAlfred Perlstein 			break;
68943bef515SMarcel Moolenaar 		linux_to_bsd_termios(&lios, &bios);
690d49fa1caSRobert Watson 		error = (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td->td_ucred,
691d49fa1caSRobert Watson 		    td));
692426da3bcSAlfred Perlstein 		break;
69343bef515SMarcel Moolenaar 
69443bef515SMarcel Moolenaar 	case LINUX_TCSETSW:
6954b7ef73dSDag-Erling Smørgrav 		error = copyin((void *)args->arg, &lios, sizeof(lios));
69643bef515SMarcel Moolenaar 		if (error)
697426da3bcSAlfred Perlstein 			break;
69843bef515SMarcel Moolenaar 		linux_to_bsd_termios(&lios, &bios);
699d49fa1caSRobert Watson 		error = (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td->td_ucred,
700d49fa1caSRobert Watson 		    td));
701426da3bcSAlfred Perlstein 		break;
70243bef515SMarcel Moolenaar 
70343bef515SMarcel Moolenaar 	case LINUX_TCSETSF:
7044b7ef73dSDag-Erling Smørgrav 		error = copyin((void *)args->arg, &lios, sizeof(lios));
70543bef515SMarcel Moolenaar 		if (error)
706426da3bcSAlfred Perlstein 			break;
70743bef515SMarcel Moolenaar 		linux_to_bsd_termios(&lios, &bios);
708d49fa1caSRobert Watson 		error = (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td->td_ucred,
709d49fa1caSRobert Watson 		    td));
710426da3bcSAlfred Perlstein 		break;
71143bef515SMarcel Moolenaar 
71243bef515SMarcel Moolenaar 	case LINUX_TCGETA:
713d49fa1caSRobert Watson 		error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td->td_ucred,
714d49fa1caSRobert Watson 		    td);
71543bef515SMarcel Moolenaar 		if (error)
716426da3bcSAlfred Perlstein 			break;
71743bef515SMarcel Moolenaar 		bsd_to_linux_termio(&bios, &lio);
7184b7ef73dSDag-Erling Smørgrav 		error = (copyout(&lio, (void *)args->arg, sizeof(lio)));
719426da3bcSAlfred Perlstein 		break;
72043bef515SMarcel Moolenaar 
72143bef515SMarcel Moolenaar 	case LINUX_TCSETA:
7224b7ef73dSDag-Erling Smørgrav 		error = copyin((void *)args->arg, &lio, sizeof(lio));
72343bef515SMarcel Moolenaar 		if (error)
724426da3bcSAlfred Perlstein 			break;
72543bef515SMarcel Moolenaar 		linux_to_bsd_termio(&lio, &bios);
726d49fa1caSRobert Watson 		error = (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td->td_ucred,
727d49fa1caSRobert Watson 		    td));
728426da3bcSAlfred Perlstein 		break;
72943bef515SMarcel Moolenaar 
73043bef515SMarcel Moolenaar 	case LINUX_TCSETAW:
7314b7ef73dSDag-Erling Smørgrav 		error = copyin((void *)args->arg, &lio, sizeof(lio));
73243bef515SMarcel Moolenaar 		if (error)
733426da3bcSAlfred Perlstein 			break;
73443bef515SMarcel Moolenaar 		linux_to_bsd_termio(&lio, &bios);
735d49fa1caSRobert Watson 		error = (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td->td_ucred,
736d49fa1caSRobert Watson 		    td));
737426da3bcSAlfred Perlstein 		break;
73843bef515SMarcel Moolenaar 
73943bef515SMarcel Moolenaar 	case LINUX_TCSETAF:
7404b7ef73dSDag-Erling Smørgrav 		error = copyin((void *)args->arg, &lio, sizeof(lio));
74143bef515SMarcel Moolenaar 		if (error)
742426da3bcSAlfred Perlstein 			break;
74343bef515SMarcel Moolenaar 		linux_to_bsd_termio(&lio, &bios);
744d49fa1caSRobert Watson 		error = (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td->td_ucred,
745d49fa1caSRobert Watson 		    td));
746426da3bcSAlfred Perlstein 		break;
74743bef515SMarcel Moolenaar 
7487e7859e7SEdward Tomasz Napierala 	case LINUX_TCSBRK:
7497e7859e7SEdward Tomasz Napierala 		if (args->arg != 0) {
7507e7859e7SEdward Tomasz Napierala 			error = (fo_ioctl(fp, TIOCDRAIN, (caddr_t)&bios, td->td_ucred,
7517e7859e7SEdward Tomasz Napierala 			    td));
7527e7859e7SEdward Tomasz Napierala 		} else {
7537e7859e7SEdward Tomasz Napierala 			linux_msg(td, "ioctl TCSBRK arg 0 not implemented");
7547e7859e7SEdward Tomasz Napierala 			error = ENOIOCTL;
7557e7859e7SEdward Tomasz Napierala 		}
7567e7859e7SEdward Tomasz Napierala 		break;
75743bef515SMarcel Moolenaar 
75843bef515SMarcel Moolenaar 	case LINUX_TCXONC: {
75943bef515SMarcel Moolenaar 		switch (args->arg) {
76043bef515SMarcel Moolenaar 		case LINUX_TCOOFF:
76143bef515SMarcel Moolenaar 			args->cmd = TIOCSTOP;
76243bef515SMarcel Moolenaar 			break;
76343bef515SMarcel Moolenaar 		case LINUX_TCOON:
76443bef515SMarcel Moolenaar 			args->cmd = TIOCSTART;
76543bef515SMarcel Moolenaar 			break;
76643bef515SMarcel Moolenaar 		case LINUX_TCIOFF:
76743bef515SMarcel Moolenaar 		case LINUX_TCION: {
76843bef515SMarcel Moolenaar 			int c;
76943bef515SMarcel Moolenaar 			struct write_args wr;
770d49fa1caSRobert Watson 			error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios,
771d49fa1caSRobert Watson 			    td->td_ucred, td);
77243bef515SMarcel Moolenaar 			if (error)
773426da3bcSAlfred Perlstein 				break;
774426da3bcSAlfred Perlstein 			fdrop(fp, td);
77543bef515SMarcel Moolenaar 			c = (args->arg == LINUX_TCIOFF) ? VSTOP : VSTART;
77643bef515SMarcel Moolenaar 			c = bios.c_cc[c];
77743bef515SMarcel Moolenaar 			if (c != _POSIX_VDISABLE) {
77843bef515SMarcel Moolenaar 				wr.fd = args->fd;
77943bef515SMarcel Moolenaar 				wr.buf = &c;
78043bef515SMarcel Moolenaar 				wr.nbyte = sizeof(c);
7818451d0ddSKip Macy 				return (sys_write(td, &wr));
78243bef515SMarcel Moolenaar 			} else
78343bef515SMarcel Moolenaar 				return (0);
78443bef515SMarcel Moolenaar 		}
78543bef515SMarcel Moolenaar 		default:
786426da3bcSAlfred Perlstein 			fdrop(fp, td);
78743bef515SMarcel Moolenaar 			return (EINVAL);
78843bef515SMarcel Moolenaar 		}
78943bef515SMarcel Moolenaar 		args->arg = 0;
7908451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
791426da3bcSAlfred Perlstein 		break;
79243bef515SMarcel Moolenaar 	}
79343bef515SMarcel Moolenaar 
79443bef515SMarcel Moolenaar 	case LINUX_TCFLSH: {
7951278dd68SXin LI 		int val;
79643bef515SMarcel Moolenaar 		switch (args->arg) {
79743bef515SMarcel Moolenaar 		case LINUX_TCIFLUSH:
7981278dd68SXin LI 			val = FREAD;
79943bef515SMarcel Moolenaar 			break;
80043bef515SMarcel Moolenaar 		case LINUX_TCOFLUSH:
8011278dd68SXin LI 			val = FWRITE;
80243bef515SMarcel Moolenaar 			break;
80343bef515SMarcel Moolenaar 		case LINUX_TCIOFLUSH:
8041278dd68SXin LI 			val = FREAD | FWRITE;
80543bef515SMarcel Moolenaar 			break;
80643bef515SMarcel Moolenaar 		default:
807426da3bcSAlfred Perlstein 			fdrop(fp, td);
80843bef515SMarcel Moolenaar 			return (EINVAL);
80943bef515SMarcel Moolenaar 		}
8101278dd68SXin LI 		error = (fo_ioctl(fp,TIOCFLUSH,(caddr_t)&val,td->td_ucred,td));
811426da3bcSAlfred Perlstein 		break;
81243bef515SMarcel Moolenaar 	}
81343bef515SMarcel Moolenaar 
81443bef515SMarcel Moolenaar 	case LINUX_TIOCEXCL:
81543bef515SMarcel Moolenaar 		args->cmd = TIOCEXCL;
8168451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
817426da3bcSAlfred Perlstein 		break;
81843bef515SMarcel Moolenaar 
81943bef515SMarcel Moolenaar 	case LINUX_TIOCNXCL:
82043bef515SMarcel Moolenaar 		args->cmd = TIOCNXCL;
8218451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
822426da3bcSAlfred Perlstein 		break;
82343bef515SMarcel Moolenaar 
8244048f0fdSMarcel Moolenaar 	case LINUX_TIOCSCTTY:
8254048f0fdSMarcel Moolenaar 		args->cmd = TIOCSCTTY;
8268451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
8274048f0fdSMarcel Moolenaar 		break;
82843bef515SMarcel Moolenaar 
82943bef515SMarcel Moolenaar 	case LINUX_TIOCGPGRP:
83043bef515SMarcel Moolenaar 		args->cmd = TIOCGPGRP;
8318451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
832426da3bcSAlfred Perlstein 		break;
83343bef515SMarcel Moolenaar 
83443bef515SMarcel Moolenaar 	case LINUX_TIOCSPGRP:
83543bef515SMarcel Moolenaar 		args->cmd = TIOCSPGRP;
8368451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
837426da3bcSAlfred Perlstein 		break;
83843bef515SMarcel Moolenaar 
83943bef515SMarcel Moolenaar 	/* LINUX_TIOCOUTQ */
84043bef515SMarcel Moolenaar 	/* LINUX_TIOCSTI */
84143bef515SMarcel Moolenaar 
84243bef515SMarcel Moolenaar 	case LINUX_TIOCGWINSZ:
84343bef515SMarcel Moolenaar 		args->cmd = TIOCGWINSZ;
8448451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
845426da3bcSAlfred Perlstein 		break;
84643bef515SMarcel Moolenaar 
84743bef515SMarcel Moolenaar 	case LINUX_TIOCSWINSZ:
84843bef515SMarcel Moolenaar 		args->cmd = TIOCSWINSZ;
8498451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
850426da3bcSAlfred Perlstein 		break;
85143bef515SMarcel Moolenaar 
85243bef515SMarcel Moolenaar 	case LINUX_TIOCMGET:
85343bef515SMarcel Moolenaar 		args->cmd = TIOCMGET;
8548451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
855426da3bcSAlfred Perlstein 		break;
85643bef515SMarcel Moolenaar 
85743bef515SMarcel Moolenaar 	case LINUX_TIOCMBIS:
85843bef515SMarcel Moolenaar 		args->cmd = TIOCMBIS;
8598451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
860426da3bcSAlfred Perlstein 		break;
86143bef515SMarcel Moolenaar 
86243bef515SMarcel Moolenaar 	case LINUX_TIOCMBIC:
86343bef515SMarcel Moolenaar 		args->cmd = TIOCMBIC;
8648451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
865426da3bcSAlfred Perlstein 		break;
86643bef515SMarcel Moolenaar 
86743bef515SMarcel Moolenaar 	case LINUX_TIOCMSET:
86843bef515SMarcel Moolenaar 		args->cmd = TIOCMSET;
8698451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
870426da3bcSAlfred Perlstein 		break;
87143bef515SMarcel Moolenaar 
87243bef515SMarcel Moolenaar 	/* TIOCGSOFTCAR */
87343bef515SMarcel Moolenaar 	/* TIOCSSOFTCAR */
87443bef515SMarcel Moolenaar 
87543bef515SMarcel Moolenaar 	case LINUX_FIONREAD: /* LINUX_TIOCINQ */
87643bef515SMarcel Moolenaar 		args->cmd = FIONREAD;
8778451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
878426da3bcSAlfred Perlstein 		break;
87943bef515SMarcel Moolenaar 
88043bef515SMarcel Moolenaar 	/* LINUX_TIOCLINUX */
88143bef515SMarcel Moolenaar 
88243bef515SMarcel Moolenaar 	case LINUX_TIOCCONS:
88343bef515SMarcel Moolenaar 		args->cmd = TIOCCONS;
8848451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
885426da3bcSAlfred Perlstein 		break;
88643bef515SMarcel Moolenaar 
88743bef515SMarcel Moolenaar 	case LINUX_TIOCGSERIAL: {
88843bef515SMarcel Moolenaar 		struct linux_serial_struct lss;
88934e05ebeSGleb Smirnoff 
89034e05ebeSGleb Smirnoff 		bzero(&lss, sizeof(lss));
89143bef515SMarcel Moolenaar 		lss.type = LINUX_PORT_16550A;
89243bef515SMarcel Moolenaar 		lss.flags = 0;
89343bef515SMarcel Moolenaar 		lss.close_delay = 0;
8944b7ef73dSDag-Erling Smørgrav 		error = copyout(&lss, (void *)args->arg, sizeof(lss));
895426da3bcSAlfred Perlstein 		break;
89643bef515SMarcel Moolenaar 	}
89743bef515SMarcel Moolenaar 
89843bef515SMarcel Moolenaar 	case LINUX_TIOCSSERIAL: {
89943bef515SMarcel Moolenaar 		struct linux_serial_struct lss;
9004b7ef73dSDag-Erling Smørgrav 		error = copyin((void *)args->arg, &lss, sizeof(lss));
90143bef515SMarcel Moolenaar 		if (error)
902426da3bcSAlfred Perlstein 			break;
90343bef515SMarcel Moolenaar 		/* XXX - It really helps to have an implementation that
90443bef515SMarcel Moolenaar 		 * does nothing. NOT!
90543bef515SMarcel Moolenaar 		 */
906426da3bcSAlfred Perlstein 		error = 0;
907426da3bcSAlfred Perlstein 		break;
90843bef515SMarcel Moolenaar 	}
90943bef515SMarcel Moolenaar 
910b377be43SEd Schouten 	case LINUX_TIOCPKT:
911b377be43SEd Schouten 		args->cmd = TIOCPKT;
9128451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
913b377be43SEd Schouten 		break;
91443bef515SMarcel Moolenaar 
91543bef515SMarcel Moolenaar 	case LINUX_FIONBIO:
91643bef515SMarcel Moolenaar 		args->cmd = FIONBIO;
9178451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
918426da3bcSAlfred Perlstein 		break;
91943bef515SMarcel Moolenaar 
92043bef515SMarcel Moolenaar 	case LINUX_TIOCNOTTY:
92143bef515SMarcel Moolenaar 		args->cmd = TIOCNOTTY;
9228451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
923426da3bcSAlfred Perlstein 		break;
92443bef515SMarcel Moolenaar 
92543bef515SMarcel Moolenaar 	case LINUX_TIOCSETD: {
92643bef515SMarcel Moolenaar 		int line;
92743bef515SMarcel Moolenaar 		switch (args->arg) {
92843bef515SMarcel Moolenaar 		case LINUX_N_TTY:
92943bef515SMarcel Moolenaar 			line = TTYDISC;
93043bef515SMarcel Moolenaar 			break;
93143bef515SMarcel Moolenaar 		case LINUX_N_SLIP:
93243bef515SMarcel Moolenaar 			line = SLIPDISC;
93343bef515SMarcel Moolenaar 			break;
93443bef515SMarcel Moolenaar 		case LINUX_N_PPP:
93543bef515SMarcel Moolenaar 			line = PPPDISC;
93643bef515SMarcel Moolenaar 			break;
93743bef515SMarcel Moolenaar 		default:
938426da3bcSAlfred Perlstein 			fdrop(fp, td);
93943bef515SMarcel Moolenaar 			return (EINVAL);
94043bef515SMarcel Moolenaar 		}
941d49fa1caSRobert Watson 		error = (fo_ioctl(fp, TIOCSETD, (caddr_t)&line, td->td_ucred,
942d49fa1caSRobert Watson 		    td));
943426da3bcSAlfred Perlstein 		break;
94443bef515SMarcel Moolenaar 	}
94543bef515SMarcel Moolenaar 
94643bef515SMarcel Moolenaar 	case LINUX_TIOCGETD: {
94743bef515SMarcel Moolenaar 		int linux_line;
94843bef515SMarcel Moolenaar 		int bsd_line = TTYDISC;
949d49fa1caSRobert Watson 		error = fo_ioctl(fp, TIOCGETD, (caddr_t)&bsd_line,
950d49fa1caSRobert Watson 		    td->td_ucred, td);
95143bef515SMarcel Moolenaar 		if (error)
952ab610366SDmitry Chagin 			break;
95343bef515SMarcel Moolenaar 		switch (bsd_line) {
95443bef515SMarcel Moolenaar 		case TTYDISC:
95543bef515SMarcel Moolenaar 			linux_line = LINUX_N_TTY;
95643bef515SMarcel Moolenaar 			break;
95743bef515SMarcel Moolenaar 		case SLIPDISC:
95843bef515SMarcel Moolenaar 			linux_line = LINUX_N_SLIP;
95943bef515SMarcel Moolenaar 			break;
96043bef515SMarcel Moolenaar 		case PPPDISC:
96143bef515SMarcel Moolenaar 			linux_line = LINUX_N_PPP;
96243bef515SMarcel Moolenaar 			break;
96343bef515SMarcel Moolenaar 		default:
964426da3bcSAlfred Perlstein 			fdrop(fp, td);
96543bef515SMarcel Moolenaar 			return (EINVAL);
96643bef515SMarcel Moolenaar 		}
9674b7ef73dSDag-Erling Smørgrav 		error = (copyout(&linux_line, (void *)args->arg, sizeof(int)));
968426da3bcSAlfred Perlstein 		break;
96943bef515SMarcel Moolenaar 	}
97043bef515SMarcel Moolenaar 
97143bef515SMarcel Moolenaar 	/* LINUX_TCSBRKP */
97243bef515SMarcel Moolenaar 	/* LINUX_TIOCTTYGSTRUCT */
97343bef515SMarcel Moolenaar 
97443bef515SMarcel Moolenaar 	case LINUX_FIONCLEX:
97543bef515SMarcel Moolenaar 		args->cmd = FIONCLEX;
9768451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
977426da3bcSAlfred Perlstein 		break;
97843bef515SMarcel Moolenaar 
97943bef515SMarcel Moolenaar 	case LINUX_FIOCLEX:
98043bef515SMarcel Moolenaar 		args->cmd = FIOCLEX;
9818451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
982426da3bcSAlfred Perlstein 		break;
98343bef515SMarcel Moolenaar 
98443bef515SMarcel Moolenaar 	case LINUX_FIOASYNC:
98543bef515SMarcel Moolenaar 		args->cmd = FIOASYNC;
9868451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
987426da3bcSAlfred Perlstein 		break;
98843bef515SMarcel Moolenaar 
98943bef515SMarcel Moolenaar 	/* LINUX_TIOCSERCONFIG */
99043bef515SMarcel Moolenaar 	/* LINUX_TIOCSERGWILD */
99143bef515SMarcel Moolenaar 	/* LINUX_TIOCSERSWILD */
99243bef515SMarcel Moolenaar 	/* LINUX_TIOCGLCKTRMIOS */
99343bef515SMarcel Moolenaar 	/* LINUX_TIOCSLCKTRMIOS */
99443bef515SMarcel Moolenaar 
995a1166f24SBruce M Simpson 	case LINUX_TIOCSBRK:
996a1166f24SBruce M Simpson 		args->cmd = TIOCSBRK;
9978451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
998a1166f24SBruce M Simpson 		break;
999a1166f24SBruce M Simpson 
1000a1166f24SBruce M Simpson 	case LINUX_TIOCCBRK:
1001a1166f24SBruce M Simpson 		args->cmd = TIOCCBRK;
10028451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1003a1166f24SBruce M Simpson 		break;
1004e83d253bSOlivier Houchard 	case LINUX_TIOCGPTN: {
1005e83d253bSOlivier Houchard 		int nb;
1006a1166f24SBruce M Simpson 
1007e83d253bSOlivier Houchard 		error = fo_ioctl(fp, TIOCGPTN, (caddr_t)&nb, td->td_ucred, td);
1008e83d253bSOlivier Houchard 		if (!error)
1009e83d253bSOlivier Houchard 			error = copyout(&nb, (void *)args->arg,
1010e83d253bSOlivier Houchard 			    sizeof(int));
1011e83d253bSOlivier Houchard 		break;
1012e83d253bSOlivier Houchard 	}
10131866c766SEdward Tomasz Napierala 	case LINUX_TIOCGPTPEER:
10141866c766SEdward Tomasz Napierala 		linux_msg(td, "unsupported ioctl TIOCGPTPEER");
10151866c766SEdward Tomasz Napierala 		error = ENOIOCTL;
10161866c766SEdward Tomasz Napierala 		break;
1017b377be43SEd Schouten 	case LINUX_TIOCSPTLCK:
10180f62290eSDmitry Chagin 		/*
10190f62290eSDmitry Chagin 		 * Our unlockpt() does nothing. Check that fd refers
10200f62290eSDmitry Chagin 		 * to a pseudo-terminal master device.
10210f62290eSDmitry Chagin 		 */
10220f62290eSDmitry Chagin 		args->cmd = TIOCPTMASTER;
10230f62290eSDmitry Chagin 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1024b377be43SEd Schouten 		break;
1025426da3bcSAlfred Perlstein 	default:
1026426da3bcSAlfred Perlstein 		error = ENOIOCTL;
1027426da3bcSAlfred Perlstein 		break;
102843bef515SMarcel Moolenaar 	}
102943bef515SMarcel Moolenaar 
1030426da3bcSAlfred Perlstein 	fdrop(fp, td);
1031426da3bcSAlfred Perlstein 	return (error);
103243bef515SMarcel Moolenaar }
103343bef515SMarcel Moolenaar 
103443bef515SMarcel Moolenaar /*
103543bef515SMarcel Moolenaar  * CDROM related ioctls
103643bef515SMarcel Moolenaar  */
103743bef515SMarcel Moolenaar 
10389debe213SLuoqi Chen struct linux_cdrom_msf
10399debe213SLuoqi Chen {
10409debe213SLuoqi Chen 	u_char	cdmsf_min0;
10419debe213SLuoqi Chen 	u_char	cdmsf_sec0;
10429debe213SLuoqi Chen 	u_char	cdmsf_frame0;
10439debe213SLuoqi Chen 	u_char	cdmsf_min1;
10449debe213SLuoqi Chen 	u_char	cdmsf_sec1;
10459debe213SLuoqi Chen 	u_char	cdmsf_frame1;
10469debe213SLuoqi Chen };
10479debe213SLuoqi Chen 
10489debe213SLuoqi Chen struct linux_cdrom_tochdr
10499debe213SLuoqi Chen {
10509debe213SLuoqi Chen 	u_char	cdth_trk0;
10519debe213SLuoqi Chen 	u_char	cdth_trk1;
10529debe213SLuoqi Chen };
10539debe213SLuoqi Chen 
10549debe213SLuoqi Chen union linux_cdrom_addr
10559debe213SLuoqi Chen {
10569debe213SLuoqi Chen 	struct {
10579debe213SLuoqi Chen 		u_char	minute;
10589debe213SLuoqi Chen 		u_char	second;
10599debe213SLuoqi Chen 		u_char	frame;
10609debe213SLuoqi Chen 	} msf;
10619debe213SLuoqi Chen 	int	lba;
10629debe213SLuoqi Chen };
10639debe213SLuoqi Chen 
10649debe213SLuoqi Chen struct linux_cdrom_tocentry
10659debe213SLuoqi Chen {
10669debe213SLuoqi Chen 	u_char	cdte_track;
10679debe213SLuoqi Chen 	u_char	cdte_adr:4;
10689debe213SLuoqi Chen 	u_char	cdte_ctrl:4;
10699debe213SLuoqi Chen 	u_char	cdte_format;
10709debe213SLuoqi Chen 	union linux_cdrom_addr cdte_addr;
10719debe213SLuoqi Chen 	u_char	cdte_datamode;
10729debe213SLuoqi Chen };
10739debe213SLuoqi Chen 
10747636612dSMarcel Moolenaar struct linux_cdrom_subchnl
10757636612dSMarcel Moolenaar {
10767636612dSMarcel Moolenaar 	u_char	cdsc_format;
10777636612dSMarcel Moolenaar 	u_char	cdsc_audiostatus;
10787636612dSMarcel Moolenaar 	u_char	cdsc_adr:4;
10797636612dSMarcel Moolenaar 	u_char	cdsc_ctrl:4;
10807636612dSMarcel Moolenaar 	u_char	cdsc_trk;
10817636612dSMarcel Moolenaar 	u_char	cdsc_ind;
10827636612dSMarcel Moolenaar 	union linux_cdrom_addr cdsc_absaddr;
10837636612dSMarcel Moolenaar 	union linux_cdrom_addr cdsc_reladdr;
10847636612dSMarcel Moolenaar };
10857636612dSMarcel Moolenaar 
108660d04085SMarcel Moolenaar struct l_cdrom_read_audio {
108760d04085SMarcel Moolenaar 	union linux_cdrom_addr addr;
108860d04085SMarcel Moolenaar 	u_char		addr_format;
108960d04085SMarcel Moolenaar 	l_int		nframes;
109060d04085SMarcel Moolenaar 	u_char		*buf;
109160d04085SMarcel Moolenaar };
109260d04085SMarcel Moolenaar 
10939d2ff928SMarcel Moolenaar struct l_dvd_layer {
10949d2ff928SMarcel Moolenaar 	u_char		book_version:4;
10959d2ff928SMarcel Moolenaar 	u_char		book_type:4;
10969d2ff928SMarcel Moolenaar 	u_char		min_rate:4;
10979d2ff928SMarcel Moolenaar 	u_char		disc_size:4;
10989d2ff928SMarcel Moolenaar 	u_char		layer_type:4;
10999d2ff928SMarcel Moolenaar 	u_char		track_path:1;
11009d2ff928SMarcel Moolenaar 	u_char		nlayers:2;
11019d2ff928SMarcel Moolenaar 	u_char		track_density:4;
11029d2ff928SMarcel Moolenaar 	u_char		linear_density:4;
11039d2ff928SMarcel Moolenaar 	u_char		bca:1;
1104cc5aa0a4SJohn Baldwin 	uint32_t	start_sector;
1105cc5aa0a4SJohn Baldwin 	uint32_t	end_sector;
1106cc5aa0a4SJohn Baldwin 	uint32_t	end_sector_l0;
11079d2ff928SMarcel Moolenaar };
11089d2ff928SMarcel Moolenaar 
11099d2ff928SMarcel Moolenaar struct l_dvd_physical {
11109d2ff928SMarcel Moolenaar 	u_char		type;
11119d2ff928SMarcel Moolenaar 	u_char		layer_num;
11129d2ff928SMarcel Moolenaar 	struct l_dvd_layer layer[4];
11139d2ff928SMarcel Moolenaar };
11149d2ff928SMarcel Moolenaar 
11159d2ff928SMarcel Moolenaar struct l_dvd_copyright {
11169d2ff928SMarcel Moolenaar 	u_char		type;
11179d2ff928SMarcel Moolenaar 	u_char		layer_num;
11189d2ff928SMarcel Moolenaar 	u_char		cpst;
11199d2ff928SMarcel Moolenaar 	u_char		rmi;
11209d2ff928SMarcel Moolenaar };
11219d2ff928SMarcel Moolenaar 
11229d2ff928SMarcel Moolenaar struct l_dvd_disckey {
11239d2ff928SMarcel Moolenaar 	u_char		type;
11249d2ff928SMarcel Moolenaar 	l_uint		agid:2;
11259d2ff928SMarcel Moolenaar 	u_char		value[2048];
11269d2ff928SMarcel Moolenaar };
11279d2ff928SMarcel Moolenaar 
11289d2ff928SMarcel Moolenaar struct l_dvd_bca {
11299d2ff928SMarcel Moolenaar 	u_char		type;
11309d2ff928SMarcel Moolenaar 	l_int		len;
11319d2ff928SMarcel Moolenaar 	u_char		value[188];
11329d2ff928SMarcel Moolenaar };
11339d2ff928SMarcel Moolenaar 
11349d2ff928SMarcel Moolenaar struct l_dvd_manufact {
11359d2ff928SMarcel Moolenaar 	u_char		type;
11369d2ff928SMarcel Moolenaar 	u_char		layer_num;
11379d2ff928SMarcel Moolenaar 	l_int		len;
11389d2ff928SMarcel Moolenaar 	u_char		value[2048];
11399d2ff928SMarcel Moolenaar };
11409d2ff928SMarcel Moolenaar 
11419d2ff928SMarcel Moolenaar typedef union {
11429d2ff928SMarcel Moolenaar 	u_char			type;
11439d2ff928SMarcel Moolenaar 	struct l_dvd_physical	physical;
11449d2ff928SMarcel Moolenaar 	struct l_dvd_copyright	copyright;
11459d2ff928SMarcel Moolenaar 	struct l_dvd_disckey	disckey;
11469d2ff928SMarcel Moolenaar 	struct l_dvd_bca	bca;
11479d2ff928SMarcel Moolenaar 	struct l_dvd_manufact	manufact;
11489d2ff928SMarcel Moolenaar } l_dvd_struct;
11499d2ff928SMarcel Moolenaar 
11509d2ff928SMarcel Moolenaar typedef u_char l_dvd_key[5];
11519d2ff928SMarcel Moolenaar typedef u_char l_dvd_challenge[10];
11529d2ff928SMarcel Moolenaar 
11539d2ff928SMarcel Moolenaar struct l_dvd_lu_send_agid {
11549d2ff928SMarcel Moolenaar 	u_char		type;
11559d2ff928SMarcel Moolenaar 	l_uint		agid:2;
11569d2ff928SMarcel Moolenaar };
11579d2ff928SMarcel Moolenaar 
11589d2ff928SMarcel Moolenaar struct l_dvd_host_send_challenge {
11599d2ff928SMarcel Moolenaar 	u_char		type;
11609d2ff928SMarcel Moolenaar 	l_uint		agid:2;
11619d2ff928SMarcel Moolenaar 	l_dvd_challenge	chal;
11629d2ff928SMarcel Moolenaar };
11639d2ff928SMarcel Moolenaar 
11649d2ff928SMarcel Moolenaar struct l_dvd_send_key {
11659d2ff928SMarcel Moolenaar 	u_char		type;
11669d2ff928SMarcel Moolenaar 	l_uint		agid:2;
11679d2ff928SMarcel Moolenaar 	l_dvd_key	key;
11689d2ff928SMarcel Moolenaar };
11699d2ff928SMarcel Moolenaar 
11709d2ff928SMarcel Moolenaar struct l_dvd_lu_send_challenge {
11719d2ff928SMarcel Moolenaar 	u_char		type;
11729d2ff928SMarcel Moolenaar 	l_uint		agid:2;
11739d2ff928SMarcel Moolenaar 	l_dvd_challenge	chal;
11749d2ff928SMarcel Moolenaar };
11759d2ff928SMarcel Moolenaar 
11769d2ff928SMarcel Moolenaar struct l_dvd_lu_send_title_key {
11779d2ff928SMarcel Moolenaar 	u_char		type;
11789d2ff928SMarcel Moolenaar 	l_uint		agid:2;
11799d2ff928SMarcel Moolenaar 	l_dvd_key	title_key;
11809d2ff928SMarcel Moolenaar 	l_int		lba;
11819d2ff928SMarcel Moolenaar 	l_uint		cpm:1;
11829d2ff928SMarcel Moolenaar 	l_uint		cp_sec:1;
11839d2ff928SMarcel Moolenaar 	l_uint		cgms:2;
11849d2ff928SMarcel Moolenaar };
11859d2ff928SMarcel Moolenaar 
11869d2ff928SMarcel Moolenaar struct l_dvd_lu_send_asf {
11879d2ff928SMarcel Moolenaar 	u_char		type;
11889d2ff928SMarcel Moolenaar 	l_uint		agid:2;
11899d2ff928SMarcel Moolenaar 	l_uint		asf:1;
11909d2ff928SMarcel Moolenaar };
11919d2ff928SMarcel Moolenaar 
11929d2ff928SMarcel Moolenaar struct l_dvd_host_send_rpcstate {
11939d2ff928SMarcel Moolenaar 	u_char		type;
11949d2ff928SMarcel Moolenaar 	u_char		pdrc;
11959d2ff928SMarcel Moolenaar };
11969d2ff928SMarcel Moolenaar 
11979d2ff928SMarcel Moolenaar struct l_dvd_lu_send_rpcstate {
11989d2ff928SMarcel Moolenaar 	u_char		type:2;
11999d2ff928SMarcel Moolenaar 	u_char		vra:3;
12009d2ff928SMarcel Moolenaar 	u_char		ucca:3;
12019d2ff928SMarcel Moolenaar 	u_char		region_mask;
12029d2ff928SMarcel Moolenaar 	u_char		rpc_scheme;
12039d2ff928SMarcel Moolenaar };
12049d2ff928SMarcel Moolenaar 
12059d2ff928SMarcel Moolenaar typedef union {
12069d2ff928SMarcel Moolenaar 	u_char				type;
12079d2ff928SMarcel Moolenaar 	struct l_dvd_lu_send_agid	lsa;
12089d2ff928SMarcel Moolenaar 	struct l_dvd_host_send_challenge hsc;
12099d2ff928SMarcel Moolenaar 	struct l_dvd_send_key		lsk;
12109d2ff928SMarcel Moolenaar 	struct l_dvd_lu_send_challenge	lsc;
12119d2ff928SMarcel Moolenaar 	struct l_dvd_send_key		hsk;
12129d2ff928SMarcel Moolenaar 	struct l_dvd_lu_send_title_key	lstk;
12139d2ff928SMarcel Moolenaar 	struct l_dvd_lu_send_asf	lsasf;
12149d2ff928SMarcel Moolenaar 	struct l_dvd_host_send_rpcstate	hrpcs;
12159d2ff928SMarcel Moolenaar 	struct l_dvd_lu_send_rpcstate	lrpcs;
12169d2ff928SMarcel Moolenaar } l_dvd_authinfo;
12179d2ff928SMarcel Moolenaar 
12189debe213SLuoqi Chen static void
bsd_to_linux_msf_lba(u_char af,union msf_lba * bp,union linux_cdrom_addr * lp)121943bef515SMarcel Moolenaar bsd_to_linux_msf_lba(u_char af, union msf_lba *bp, union linux_cdrom_addr *lp)
12209debe213SLuoqi Chen {
122143bef515SMarcel Moolenaar 	if (af == CD_LBA_FORMAT)
12229debe213SLuoqi Chen 		lp->lba = bp->lba;
12239debe213SLuoqi Chen 	else {
12249debe213SLuoqi Chen 		lp->msf.minute = bp->msf.minute;
12259debe213SLuoqi Chen 		lp->msf.second = bp->msf.second;
12269debe213SLuoqi Chen 		lp->msf.frame = bp->msf.frame;
12279debe213SLuoqi Chen 	}
12289debe213SLuoqi Chen }
12299debe213SLuoqi Chen 
12307636612dSMarcel Moolenaar static void
set_linux_cdrom_addr(union linux_cdrom_addr * addr,int format,int lba)12317636612dSMarcel Moolenaar set_linux_cdrom_addr(union linux_cdrom_addr *addr, int format, int lba)
12327636612dSMarcel Moolenaar {
12337636612dSMarcel Moolenaar 	if (format == LINUX_CDROM_MSF) {
12347636612dSMarcel Moolenaar 		addr->msf.frame = lba % 75;
12357636612dSMarcel Moolenaar 		lba /= 75;
12367636612dSMarcel Moolenaar 		lba += 2;
12377636612dSMarcel Moolenaar 		addr->msf.second = lba % 60;
12387636612dSMarcel Moolenaar 		addr->msf.minute = lba / 60;
123943bef515SMarcel Moolenaar 	} else
12407636612dSMarcel Moolenaar 		addr->lba = lba;
12417636612dSMarcel Moolenaar }
12427636612dSMarcel Moolenaar 
124343bef515SMarcel Moolenaar static int
linux_to_bsd_dvd_struct(l_dvd_struct * lp,struct dvd_struct * bp)12449d2ff928SMarcel Moolenaar linux_to_bsd_dvd_struct(l_dvd_struct *lp, struct dvd_struct *bp)
12459d2ff928SMarcel Moolenaar {
12469d2ff928SMarcel Moolenaar 	bp->format = lp->type;
12479d2ff928SMarcel Moolenaar 	switch (bp->format) {
12489d2ff928SMarcel Moolenaar 	case DVD_STRUCT_PHYSICAL:
12499d2ff928SMarcel Moolenaar 		if (bp->layer_num >= 4)
12509d2ff928SMarcel Moolenaar 			return (EINVAL);
12519d2ff928SMarcel Moolenaar 		bp->layer_num = lp->physical.layer_num;
12529d2ff928SMarcel Moolenaar 		break;
12539d2ff928SMarcel Moolenaar 	case DVD_STRUCT_COPYRIGHT:
12549d2ff928SMarcel Moolenaar 		bp->layer_num = lp->copyright.layer_num;
12559d2ff928SMarcel Moolenaar 		break;
12569d2ff928SMarcel Moolenaar 	case DVD_STRUCT_DISCKEY:
12579d2ff928SMarcel Moolenaar 		bp->agid = lp->disckey.agid;
12589d2ff928SMarcel Moolenaar 		break;
12599d2ff928SMarcel Moolenaar 	case DVD_STRUCT_BCA:
12609d2ff928SMarcel Moolenaar 	case DVD_STRUCT_MANUFACT:
12619d2ff928SMarcel Moolenaar 		break;
12629d2ff928SMarcel Moolenaar 	default:
12639d2ff928SMarcel Moolenaar 		return (EINVAL);
12649d2ff928SMarcel Moolenaar 	}
12659d2ff928SMarcel Moolenaar 	return (0);
12669d2ff928SMarcel Moolenaar }
12679d2ff928SMarcel Moolenaar 
12689d2ff928SMarcel Moolenaar static int
bsd_to_linux_dvd_struct(struct dvd_struct * bp,l_dvd_struct * lp)12699d2ff928SMarcel Moolenaar bsd_to_linux_dvd_struct(struct dvd_struct *bp, l_dvd_struct *lp)
12709d2ff928SMarcel Moolenaar {
12719d2ff928SMarcel Moolenaar 	switch (bp->format) {
12729d2ff928SMarcel Moolenaar 	case DVD_STRUCT_PHYSICAL: {
12739d2ff928SMarcel Moolenaar 		struct dvd_layer *blp = (struct dvd_layer *)bp->data;
12749d2ff928SMarcel Moolenaar 		struct l_dvd_layer *llp = &lp->physical.layer[bp->layer_num];
12759d2ff928SMarcel Moolenaar 		memset(llp, 0, sizeof(*llp));
12769d2ff928SMarcel Moolenaar 		llp->book_version = blp->book_version;
12779d2ff928SMarcel Moolenaar 		llp->book_type = blp->book_type;
12789d2ff928SMarcel Moolenaar 		llp->min_rate = blp->max_rate;
12799d2ff928SMarcel Moolenaar 		llp->disc_size = blp->disc_size;
12809d2ff928SMarcel Moolenaar 		llp->layer_type = blp->layer_type;
12819d2ff928SMarcel Moolenaar 		llp->track_path = blp->track_path;
12829d2ff928SMarcel Moolenaar 		llp->nlayers = blp->nlayers;
12839d2ff928SMarcel Moolenaar 		llp->track_density = blp->track_density;
12849d2ff928SMarcel Moolenaar 		llp->linear_density = blp->linear_density;
12859d2ff928SMarcel Moolenaar 		llp->bca = blp->bca;
12869d2ff928SMarcel Moolenaar 		llp->start_sector = blp->start_sector;
12879d2ff928SMarcel Moolenaar 		llp->end_sector = blp->end_sector;
12889d2ff928SMarcel Moolenaar 		llp->end_sector_l0 = blp->end_sector_l0;
12899d2ff928SMarcel Moolenaar 		break;
12909d2ff928SMarcel Moolenaar 	}
12919d2ff928SMarcel Moolenaar 	case DVD_STRUCT_COPYRIGHT:
12929d2ff928SMarcel Moolenaar 		lp->copyright.cpst = bp->cpst;
12939d2ff928SMarcel Moolenaar 		lp->copyright.rmi = bp->rmi;
12949d2ff928SMarcel Moolenaar 		break;
12959d2ff928SMarcel Moolenaar 	case DVD_STRUCT_DISCKEY:
12969d2ff928SMarcel Moolenaar 		memcpy(lp->disckey.value, bp->data, sizeof(lp->disckey.value));
12979d2ff928SMarcel Moolenaar 		break;
12989d2ff928SMarcel Moolenaar 	case DVD_STRUCT_BCA:
12999d2ff928SMarcel Moolenaar 		lp->bca.len = bp->length;
13009d2ff928SMarcel Moolenaar 		memcpy(lp->bca.value, bp->data, sizeof(lp->bca.value));
13019d2ff928SMarcel Moolenaar 		break;
13029d2ff928SMarcel Moolenaar 	case DVD_STRUCT_MANUFACT:
13039d2ff928SMarcel Moolenaar 		lp->manufact.len = bp->length;
13049d2ff928SMarcel Moolenaar 		memcpy(lp->manufact.value, bp->data,
13059d2ff928SMarcel Moolenaar 		    sizeof(lp->manufact.value));
1306eae594f7SEd Maste 		/* lp->manufact.layer_num is unused in Linux (redhat 7.0). */
13079d2ff928SMarcel Moolenaar 		break;
13089d2ff928SMarcel Moolenaar 	default:
13099d2ff928SMarcel Moolenaar 		return (EINVAL);
13109d2ff928SMarcel Moolenaar 	}
13119d2ff928SMarcel Moolenaar 	return (0);
13129d2ff928SMarcel Moolenaar }
13139d2ff928SMarcel Moolenaar 
13149d2ff928SMarcel Moolenaar static int
linux_to_bsd_dvd_authinfo(l_dvd_authinfo * lp,int * bcode,struct dvd_authinfo * bp)13159d2ff928SMarcel Moolenaar linux_to_bsd_dvd_authinfo(l_dvd_authinfo *lp, int *bcode,
13169d2ff928SMarcel Moolenaar     struct dvd_authinfo *bp)
13179d2ff928SMarcel Moolenaar {
13189d2ff928SMarcel Moolenaar 	switch (lp->type) {
13199d2ff928SMarcel Moolenaar 	case LINUX_DVD_LU_SEND_AGID:
13209d2ff928SMarcel Moolenaar 		*bcode = DVDIOCREPORTKEY;
13219d2ff928SMarcel Moolenaar 		bp->format = DVD_REPORT_AGID;
13229d2ff928SMarcel Moolenaar 		bp->agid = lp->lsa.agid;
13239d2ff928SMarcel Moolenaar 		break;
13249d2ff928SMarcel Moolenaar 	case LINUX_DVD_HOST_SEND_CHALLENGE:
13259d2ff928SMarcel Moolenaar 		*bcode = DVDIOCSENDKEY;
13269d2ff928SMarcel Moolenaar 		bp->format = DVD_SEND_CHALLENGE;
13279d2ff928SMarcel Moolenaar 		bp->agid = lp->hsc.agid;
13289d2ff928SMarcel Moolenaar 		memcpy(bp->keychal, lp->hsc.chal, 10);
13299d2ff928SMarcel Moolenaar 		break;
13309d2ff928SMarcel Moolenaar 	case LINUX_DVD_LU_SEND_KEY1:
13319d2ff928SMarcel Moolenaar 		*bcode = DVDIOCREPORTKEY;
13329d2ff928SMarcel Moolenaar 		bp->format = DVD_REPORT_KEY1;
13339d2ff928SMarcel Moolenaar 		bp->agid = lp->lsk.agid;
13349d2ff928SMarcel Moolenaar 		break;
13359d2ff928SMarcel Moolenaar 	case LINUX_DVD_LU_SEND_CHALLENGE:
13369d2ff928SMarcel Moolenaar 		*bcode = DVDIOCREPORTKEY;
13379d2ff928SMarcel Moolenaar 		bp->format = DVD_REPORT_CHALLENGE;
13389d2ff928SMarcel Moolenaar 		bp->agid = lp->lsc.agid;
13399d2ff928SMarcel Moolenaar 		break;
13409d2ff928SMarcel Moolenaar 	case LINUX_DVD_HOST_SEND_KEY2:
13419d2ff928SMarcel Moolenaar 		*bcode = DVDIOCSENDKEY;
13429d2ff928SMarcel Moolenaar 		bp->format = DVD_SEND_KEY2;
13439d2ff928SMarcel Moolenaar 		bp->agid = lp->hsk.agid;
13449d2ff928SMarcel Moolenaar 		memcpy(bp->keychal, lp->hsk.key, 5);
13459d2ff928SMarcel Moolenaar 		break;
13469d2ff928SMarcel Moolenaar 	case LINUX_DVD_LU_SEND_TITLE_KEY:
13479d2ff928SMarcel Moolenaar 		*bcode = DVDIOCREPORTKEY;
13489d2ff928SMarcel Moolenaar 		bp->format = DVD_REPORT_TITLE_KEY;
13499d2ff928SMarcel Moolenaar 		bp->agid = lp->lstk.agid;
13509d2ff928SMarcel Moolenaar 		bp->lba = lp->lstk.lba;
13519d2ff928SMarcel Moolenaar 		break;
13529d2ff928SMarcel Moolenaar 	case LINUX_DVD_LU_SEND_ASF:
13539d2ff928SMarcel Moolenaar 		*bcode = DVDIOCREPORTKEY;
13549d2ff928SMarcel Moolenaar 		bp->format = DVD_REPORT_ASF;
13559d2ff928SMarcel Moolenaar 		bp->agid = lp->lsasf.agid;
13569d2ff928SMarcel Moolenaar 		break;
13579d2ff928SMarcel Moolenaar 	case LINUX_DVD_INVALIDATE_AGID:
13589d2ff928SMarcel Moolenaar 		*bcode = DVDIOCREPORTKEY;
13599d2ff928SMarcel Moolenaar 		bp->format = DVD_INVALIDATE_AGID;
13609d2ff928SMarcel Moolenaar 		bp->agid = lp->lsa.agid;
13619d2ff928SMarcel Moolenaar 		break;
13629d2ff928SMarcel Moolenaar 	case LINUX_DVD_LU_SEND_RPC_STATE:
13639d2ff928SMarcel Moolenaar 		*bcode = DVDIOCREPORTKEY;
13649d2ff928SMarcel Moolenaar 		bp->format = DVD_REPORT_RPC;
13659d2ff928SMarcel Moolenaar 		break;
13669d2ff928SMarcel Moolenaar 	case LINUX_DVD_HOST_SEND_RPC_STATE:
13679d2ff928SMarcel Moolenaar 		*bcode = DVDIOCSENDKEY;
13689d2ff928SMarcel Moolenaar 		bp->format = DVD_SEND_RPC;
13699d2ff928SMarcel Moolenaar 		bp->region = lp->hrpcs.pdrc;
13709d2ff928SMarcel Moolenaar 		break;
13719d2ff928SMarcel Moolenaar 	default:
13729d2ff928SMarcel Moolenaar 		return (EINVAL);
13739d2ff928SMarcel Moolenaar 	}
13749d2ff928SMarcel Moolenaar 	return (0);
13759d2ff928SMarcel Moolenaar }
13769d2ff928SMarcel Moolenaar 
13779d2ff928SMarcel Moolenaar static int
bsd_to_linux_dvd_authinfo(struct dvd_authinfo * bp,l_dvd_authinfo * lp)13789d2ff928SMarcel Moolenaar bsd_to_linux_dvd_authinfo(struct dvd_authinfo *bp, l_dvd_authinfo *lp)
13799d2ff928SMarcel Moolenaar {
13809d2ff928SMarcel Moolenaar 	switch (lp->type) {
13819d2ff928SMarcel Moolenaar 	case LINUX_DVD_LU_SEND_AGID:
13829d2ff928SMarcel Moolenaar 		lp->lsa.agid = bp->agid;
13839d2ff928SMarcel Moolenaar 		break;
13849d2ff928SMarcel Moolenaar 	case LINUX_DVD_HOST_SEND_CHALLENGE:
13859d2ff928SMarcel Moolenaar 		lp->type = LINUX_DVD_LU_SEND_KEY1;
13869d2ff928SMarcel Moolenaar 		break;
13879d2ff928SMarcel Moolenaar 	case LINUX_DVD_LU_SEND_KEY1:
13889d2ff928SMarcel Moolenaar 		memcpy(lp->lsk.key, bp->keychal, sizeof(lp->lsk.key));
13899d2ff928SMarcel Moolenaar 		break;
13909d2ff928SMarcel Moolenaar 	case LINUX_DVD_LU_SEND_CHALLENGE:
13919d2ff928SMarcel Moolenaar 		memcpy(lp->lsc.chal, bp->keychal, sizeof(lp->lsc.chal));
13929d2ff928SMarcel Moolenaar 		break;
13939d2ff928SMarcel Moolenaar 	case LINUX_DVD_HOST_SEND_KEY2:
13949d2ff928SMarcel Moolenaar 		lp->type = LINUX_DVD_AUTH_ESTABLISHED;
13959d2ff928SMarcel Moolenaar 		break;
13969d2ff928SMarcel Moolenaar 	case LINUX_DVD_LU_SEND_TITLE_KEY:
13979d2ff928SMarcel Moolenaar 		memcpy(lp->lstk.title_key, bp->keychal,
13989d2ff928SMarcel Moolenaar 		    sizeof(lp->lstk.title_key));
13999d2ff928SMarcel Moolenaar 		lp->lstk.cpm = bp->cpm;
14009d2ff928SMarcel Moolenaar 		lp->lstk.cp_sec = bp->cp_sec;
14019d2ff928SMarcel Moolenaar 		lp->lstk.cgms = bp->cgms;
14029d2ff928SMarcel Moolenaar 		break;
14039d2ff928SMarcel Moolenaar 	case LINUX_DVD_LU_SEND_ASF:
14049d2ff928SMarcel Moolenaar 		lp->lsasf.asf = bp->asf;
14059d2ff928SMarcel Moolenaar 		break;
14069d2ff928SMarcel Moolenaar 	case LINUX_DVD_INVALIDATE_AGID:
14079d2ff928SMarcel Moolenaar 		break;
14089d2ff928SMarcel Moolenaar 	case LINUX_DVD_LU_SEND_RPC_STATE:
14099d2ff928SMarcel Moolenaar 		lp->lrpcs.type = bp->reg_type;
14109d2ff928SMarcel Moolenaar 		lp->lrpcs.vra = bp->vend_rsts;
14119d2ff928SMarcel Moolenaar 		lp->lrpcs.ucca = bp->user_rsts;
14129d2ff928SMarcel Moolenaar 		lp->lrpcs.region_mask = bp->region;
14139d2ff928SMarcel Moolenaar 		lp->lrpcs.rpc_scheme = bp->rpc_scheme;
14149d2ff928SMarcel Moolenaar 		break;
14159d2ff928SMarcel Moolenaar 	case LINUX_DVD_HOST_SEND_RPC_STATE:
14169d2ff928SMarcel Moolenaar 		break;
14179d2ff928SMarcel Moolenaar 	default:
14189d2ff928SMarcel Moolenaar 		return (EINVAL);
14199d2ff928SMarcel Moolenaar 	}
14209d2ff928SMarcel Moolenaar 	return (0);
14219d2ff928SMarcel Moolenaar }
14229d2ff928SMarcel Moolenaar 
14239d2ff928SMarcel Moolenaar static int
linux_ioctl_cdrom(struct thread * td,struct linux_ioctl_args * args)1424b40ce416SJulian Elischer linux_ioctl_cdrom(struct thread *td, struct linux_ioctl_args *args)
1425c21dee17SSøren Schmidt {
1426426da3bcSAlfred Perlstein 	struct file *fp;
1427c21dee17SSøren Schmidt 	int error;
1428c21dee17SSøren Schmidt 
1429cbd92ce6SMatt Macy 	error = fget(td, args->fd, &cap_ioctl_rights, &fp);
14307008be5bSPawel Jakub Dawidek 	if (error != 0)
1431a4db4953SAlfred Perlstein 		return (error);
143296e0f535SSøren Schmidt 	switch (args->cmd & 0xffff) {
14339debe213SLuoqi Chen 	case LINUX_CDROMPAUSE:
14349debe213SLuoqi Chen 		args->cmd = CDIOCPAUSE;
14358451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1436426da3bcSAlfred Perlstein 		break;
14379debe213SLuoqi Chen 
14389debe213SLuoqi Chen 	case LINUX_CDROMRESUME:
14399debe213SLuoqi Chen 		args->cmd = CDIOCRESUME;
14408451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1441426da3bcSAlfred Perlstein 		break;
14429debe213SLuoqi Chen 
14439debe213SLuoqi Chen 	case LINUX_CDROMPLAYMSF:
14449debe213SLuoqi Chen 		args->cmd = CDIOCPLAYMSF;
14458451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1446426da3bcSAlfred Perlstein 		break;
14479debe213SLuoqi Chen 
14489debe213SLuoqi Chen 	case LINUX_CDROMPLAYTRKIND:
14499debe213SLuoqi Chen 		args->cmd = CDIOCPLAYTRACKS;
14508451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1451426da3bcSAlfred Perlstein 		break;
14529debe213SLuoqi Chen 
14539debe213SLuoqi Chen 	case LINUX_CDROMREADTOCHDR: {
14549debe213SLuoqi Chen 		struct ioc_toc_header th;
14559debe213SLuoqi Chen 		struct linux_cdrom_tochdr lth;
1456d49fa1caSRobert Watson 		error = fo_ioctl(fp, CDIOREADTOCHEADER, (caddr_t)&th,
1457d49fa1caSRobert Watson 		    td->td_ucred, td);
14589debe213SLuoqi Chen 		if (!error) {
14599debe213SLuoqi Chen 			lth.cdth_trk0 = th.starting_track;
14609debe213SLuoqi Chen 			lth.cdth_trk1 = th.ending_track;
1461b9924c20SMark Johnston 			error = copyout(&lth, (void *)args->arg, sizeof(lth));
14629debe213SLuoqi Chen 		}
1463426da3bcSAlfred Perlstein 		break;
14649debe213SLuoqi Chen 	}
14659debe213SLuoqi Chen 
14669debe213SLuoqi Chen 	case LINUX_CDROMREADTOCENTRY: {
146736db02ffSBruce M Simpson 		struct linux_cdrom_tocentry lte;
14689debe213SLuoqi Chen 		struct ioc_read_toc_single_entry irtse;
146936db02ffSBruce M Simpson 
147036db02ffSBruce M Simpson 		error = copyin((void *)args->arg, &lte, sizeof(lte));
147136db02ffSBruce M Simpson 		if (error)
147236db02ffSBruce M Simpson 			break;
147336db02ffSBruce M Simpson 		irtse.address_format = lte.cdte_format;
147436db02ffSBruce M Simpson 		irtse.track = lte.cdte_track;
1475d49fa1caSRobert Watson 		error = fo_ioctl(fp, CDIOREADTOCENTRY, (caddr_t)&irtse,
1476d49fa1caSRobert Watson 		    td->td_ucred, td);
14779debe213SLuoqi Chen 		if (!error) {
14789debe213SLuoqi Chen 			lte.cdte_ctrl = irtse.entry.control;
14799debe213SLuoqi Chen 			lte.cdte_adr = irtse.entry.addr_type;
14809debe213SLuoqi Chen 			bsd_to_linux_msf_lba(irtse.address_format,
14819debe213SLuoqi Chen 			    &irtse.entry.addr, &lte.cdte_addr);
148236db02ffSBruce M Simpson 			error = copyout(&lte, (void *)args->arg, sizeof(lte));
14839debe213SLuoqi Chen 		}
1484426da3bcSAlfred Perlstein 		break;
14859debe213SLuoqi Chen 	}
14869debe213SLuoqi Chen 
148743bef515SMarcel Moolenaar 	case LINUX_CDROMSTOP:
148843bef515SMarcel Moolenaar 		args->cmd = CDIOCSTOP;
14898451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1490426da3bcSAlfred Perlstein 		break;
149143bef515SMarcel Moolenaar 
149243bef515SMarcel Moolenaar 	case LINUX_CDROMSTART:
149343bef515SMarcel Moolenaar 		args->cmd = CDIOCSTART;
14948451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1495426da3bcSAlfred Perlstein 		break;
149643bef515SMarcel Moolenaar 
149743bef515SMarcel Moolenaar 	case LINUX_CDROMEJECT:
149843bef515SMarcel Moolenaar 		args->cmd = CDIOCEJECT;
14998451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1500426da3bcSAlfred Perlstein 		break;
150143bef515SMarcel Moolenaar 
150243bef515SMarcel Moolenaar 	/* LINUX_CDROMVOLCTRL */
150343bef515SMarcel Moolenaar 
15047636612dSMarcel Moolenaar 	case LINUX_CDROMSUBCHNL: {
15057636612dSMarcel Moolenaar 		struct linux_cdrom_subchnl sc;
15067636612dSMarcel Moolenaar 		struct ioc_read_subchannel bsdsc;
150743792195SMaxim Sobolev 		struct cd_sub_channel_info bsdinfo;
150843792195SMaxim Sobolev 
1509fc795c25SMark Johnston 		error = copyin((void *)args->arg, &sc, sizeof(sc));
1510fc795c25SMark Johnston 		if (error)
1511fc795c25SMark Johnston 			break;
1512fc795c25SMark Johnston 
1513fc795c25SMark Johnston 		/*
1514fc795c25SMark Johnston 		 * Invoke the native ioctl and bounce the returned data through
1515fc795c25SMark Johnston 		 * the userspace buffer.  This works because the Linux structure
1516fc795c25SMark Johnston 		 * is the same size as our structures for the subchannel header
1517fc795c25SMark Johnston 		 * and position data.
1518fc795c25SMark Johnston 		 */
15197636612dSMarcel Moolenaar 		bsdsc.address_format = CD_LBA_FORMAT;
15207636612dSMarcel Moolenaar 		bsdsc.data_format = CD_CURRENT_POSITION;
1521651e9214SNick Sayer 		bsdsc.track = 0;
1522fc795c25SMark Johnston 		bsdsc.data_len = sizeof(sc);
1523fc795c25SMark Johnston 		bsdsc.data = (void *)args->arg;
1524fc795c25SMark Johnston 		error = fo_ioctl(fp, CDIOCREADSUBCHANNEL, (caddr_t)&bsdsc,
1525fc795c25SMark Johnston 		    td->td_ucred, td);
15267636612dSMarcel Moolenaar 		if (error)
1527426da3bcSAlfred Perlstein 			break;
1528fc795c25SMark Johnston 		error = copyin((void *)args->arg, &bsdinfo, sizeof(bsdinfo));
15297636612dSMarcel Moolenaar 		if (error)
1530426da3bcSAlfred Perlstein 			break;
153143792195SMaxim Sobolev 		sc.cdsc_audiostatus = bsdinfo.header.audio_status;
153243792195SMaxim Sobolev 		sc.cdsc_adr = bsdinfo.what.position.addr_type;
153343792195SMaxim Sobolev 		sc.cdsc_ctrl = bsdinfo.what.position.control;
153443792195SMaxim Sobolev 		sc.cdsc_trk = bsdinfo.what.position.track_number;
153543792195SMaxim Sobolev 		sc.cdsc_ind = bsdinfo.what.position.index_number;
15367636612dSMarcel Moolenaar 		set_linux_cdrom_addr(&sc.cdsc_absaddr, sc.cdsc_format,
153743792195SMaxim Sobolev 		    bsdinfo.what.position.absaddr.lba);
15387636612dSMarcel Moolenaar 		set_linux_cdrom_addr(&sc.cdsc_reladdr, sc.cdsc_format,
153943792195SMaxim Sobolev 		    bsdinfo.what.position.reladdr.lba);
15404b7ef73dSDag-Erling Smørgrav 		error = copyout(&sc, (void *)args->arg, sizeof(sc));
1541426da3bcSAlfred Perlstein 		break;
15427636612dSMarcel Moolenaar 	}
15437636612dSMarcel Moolenaar 
154443bef515SMarcel Moolenaar 	/* LINUX_CDROMREADMODE2 */
154543bef515SMarcel Moolenaar 	/* LINUX_CDROMREADMODE1 */
1546a55140ceSSøren Schmidt 	/* LINUX_CDROMREADAUDIO */
154743bef515SMarcel Moolenaar 	/* LINUX_CDROMEJECT_SW */
154843bef515SMarcel Moolenaar 	/* LINUX_CDROMMULTISESSION */
154943bef515SMarcel Moolenaar 	/* LINUX_CDROM_GET_UPC */
155043bef515SMarcel Moolenaar 
155143bef515SMarcel Moolenaar 	case LINUX_CDROMRESET:
155243bef515SMarcel Moolenaar 		args->cmd = CDIOCRESET;
15538451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1554426da3bcSAlfred Perlstein 		break;
155543bef515SMarcel Moolenaar 
155643bef515SMarcel Moolenaar 	/* LINUX_CDROMVOLREAD */
155743bef515SMarcel Moolenaar 	/* LINUX_CDROMREADRAW */
155843bef515SMarcel Moolenaar 	/* LINUX_CDROMREADCOOKED */
155943bef515SMarcel Moolenaar 	/* LINUX_CDROMSEEK */
156043bef515SMarcel Moolenaar 	/* LINUX_CDROMPLAYBLK */
156143bef515SMarcel Moolenaar 	/* LINUX_CDROMREADALL */
156243bef515SMarcel Moolenaar 	/* LINUX_CDROMCLOSETRAY */
156343bef515SMarcel Moolenaar 	/* LINUX_CDROMLOADFROMSLOT */
15649d2ff928SMarcel Moolenaar 	/* LINUX_CDROMGETSPINDOWN */
15659d2ff928SMarcel Moolenaar 	/* LINUX_CDROMSETSPINDOWN */
15669d2ff928SMarcel Moolenaar 	/* LINUX_CDROM_SET_OPTIONS */
15679d2ff928SMarcel Moolenaar 	/* LINUX_CDROM_CLEAR_OPTIONS */
15689d2ff928SMarcel Moolenaar 	/* LINUX_CDROM_SELECT_SPEED */
15699d2ff928SMarcel Moolenaar 	/* LINUX_CDROM_SELECT_DISC */
15709d2ff928SMarcel Moolenaar 	/* LINUX_CDROM_MEDIA_CHANGED */
15719d2ff928SMarcel Moolenaar 	/* LINUX_CDROM_DRIVE_STATUS */
15729d2ff928SMarcel Moolenaar 	/* LINUX_CDROM_DISC_STATUS */
15739d2ff928SMarcel Moolenaar 	/* LINUX_CDROM_CHANGER_NSLOTS */
15749d2ff928SMarcel Moolenaar 	/* LINUX_CDROM_LOCKDOOR */
15759d2ff928SMarcel Moolenaar 	/* LINUX_CDROM_DEBUG */
15769d2ff928SMarcel Moolenaar 	/* LINUX_CDROM_GET_CAPABILITY */
15779d2ff928SMarcel Moolenaar 	/* LINUX_CDROMAUDIOBUFSIZ */
15789d2ff928SMarcel Moolenaar 
15799d2ff928SMarcel Moolenaar 	case LINUX_DVD_READ_STRUCT: {
158093f0eafdSAndriy Gapon 		l_dvd_struct *lds;
158193f0eafdSAndriy Gapon 		struct dvd_struct *bds;
15829d2ff928SMarcel Moolenaar 
158393f0eafdSAndriy Gapon 		lds = malloc(sizeof(*lds), M_LINUX, M_WAITOK);
158493f0eafdSAndriy Gapon 		bds = malloc(sizeof(*bds), M_LINUX, M_WAITOK);
158593f0eafdSAndriy Gapon 		error = copyin((void *)args->arg, lds, sizeof(*lds));
15869d2ff928SMarcel Moolenaar 		if (error)
158793f0eafdSAndriy Gapon 			goto out;
158893f0eafdSAndriy Gapon 		error = linux_to_bsd_dvd_struct(lds, bds);
15899d2ff928SMarcel Moolenaar 		if (error)
159093f0eafdSAndriy Gapon 			goto out;
159193f0eafdSAndriy Gapon 		error = fo_ioctl(fp, DVDIOCREADSTRUCTURE, (caddr_t)bds,
1592d49fa1caSRobert Watson 		    td->td_ucred, td);
15939d2ff928SMarcel Moolenaar 		if (error)
159493f0eafdSAndriy Gapon 			goto out;
159593f0eafdSAndriy Gapon 		error = bsd_to_linux_dvd_struct(bds, lds);
15969d2ff928SMarcel Moolenaar 		if (error)
159793f0eafdSAndriy Gapon 			goto out;
159893f0eafdSAndriy Gapon 		error = copyout(lds, (void *)args->arg, sizeof(*lds));
159993f0eafdSAndriy Gapon 	out:
160093f0eafdSAndriy Gapon 		free(bds, M_LINUX);
160193f0eafdSAndriy Gapon 		free(lds, M_LINUX);
1602426da3bcSAlfred Perlstein 		break;
16039d2ff928SMarcel Moolenaar 	}
16049d2ff928SMarcel Moolenaar 
16059d2ff928SMarcel Moolenaar 	/* LINUX_DVD_WRITE_STRUCT */
16069d2ff928SMarcel Moolenaar 
16079d2ff928SMarcel Moolenaar 	case LINUX_DVD_AUTH: {
16089d2ff928SMarcel Moolenaar 		l_dvd_authinfo lda;
16099d2ff928SMarcel Moolenaar 		struct dvd_authinfo bda;
16109d2ff928SMarcel Moolenaar 		int bcode;
16119d2ff928SMarcel Moolenaar 
16124b7ef73dSDag-Erling Smørgrav 		error = copyin((void *)args->arg, &lda, sizeof(lda));
16139d2ff928SMarcel Moolenaar 		if (error)
1614426da3bcSAlfred Perlstein 			break;
16159d2ff928SMarcel Moolenaar 		error = linux_to_bsd_dvd_authinfo(&lda, &bcode, &bda);
16169d2ff928SMarcel Moolenaar 		if (error)
1617426da3bcSAlfred Perlstein 			break;
1618d49fa1caSRobert Watson 		error = fo_ioctl(fp, bcode, (caddr_t)&bda, td->td_ucred,
1619d49fa1caSRobert Watson 		    td);
16209d2ff928SMarcel Moolenaar 		if (error) {
16219d2ff928SMarcel Moolenaar 			if (lda.type == LINUX_DVD_HOST_SEND_KEY2) {
16229d2ff928SMarcel Moolenaar 				lda.type = LINUX_DVD_AUTH_FAILURE;
1623b9924c20SMark Johnston 				(void)copyout(&lda, (void *)args->arg,
1624b9924c20SMark Johnston 				    sizeof(lda));
16259d2ff928SMarcel Moolenaar 			}
1626426da3bcSAlfred Perlstein 			break;
16279d2ff928SMarcel Moolenaar 		}
16289d2ff928SMarcel Moolenaar 		error = bsd_to_linux_dvd_authinfo(&bda, &lda);
16299d2ff928SMarcel Moolenaar 		if (error)
1630426da3bcSAlfred Perlstein 			break;
16314b7ef73dSDag-Erling Smørgrav 		error = copyout(&lda, (void *)args->arg, sizeof(lda));
1632426da3bcSAlfred Perlstein 		break;
16339d2ff928SMarcel Moolenaar 	}
16349d2ff928SMarcel Moolenaar 
16351eba4c79SScott Long 	case LINUX_SCSI_GET_BUS_NUMBER:
1636fcaf473cSAlexander Motin 	{
1637fcaf473cSAlexander Motin 		struct sg_scsi_id id;
1638fcaf473cSAlexander Motin 
1639fcaf473cSAlexander Motin 		error = fo_ioctl(fp, SG_GET_SCSI_ID, (caddr_t)&id,
1640fcaf473cSAlexander Motin 		    td->td_ucred, td);
1641fcaf473cSAlexander Motin 		if (error)
16421eba4c79SScott Long 			break;
1643fcaf473cSAlexander Motin 		error = copyout(&id.channel, (void *)args->arg, sizeof(int));
1644fcaf473cSAlexander Motin 		break;
1645fcaf473cSAlexander Motin 	}
1646fcaf473cSAlexander Motin 
1647fcaf473cSAlexander Motin 	case LINUX_SCSI_GET_IDLUN:
1648fcaf473cSAlexander Motin 	{
1649fcaf473cSAlexander Motin 		struct sg_scsi_id id;
1650fcaf473cSAlexander Motin 		struct scsi_idlun idl;
1651fcaf473cSAlexander Motin 
1652fcaf473cSAlexander Motin 		error = fo_ioctl(fp, SG_GET_SCSI_ID, (caddr_t)&id,
1653fcaf473cSAlexander Motin 		    td->td_ucred, td);
1654fcaf473cSAlexander Motin 		if (error)
1655fcaf473cSAlexander Motin 			break;
1656fcaf473cSAlexander Motin 		idl.dev_id = (id.scsi_id & 0xff) + ((id.lun & 0xff) << 8) +
1657fcaf473cSAlexander Motin 		    ((id.channel & 0xff) << 16) + ((id.host_no & 0xff) << 24);
1658fcaf473cSAlexander Motin 		idl.host_unique_id = id.host_no;
1659fcaf473cSAlexander Motin 		error = copyout(&idl, (void *)args->arg, sizeof(idl));
1660fcaf473cSAlexander Motin 		break;
1661fcaf473cSAlexander Motin 	}
16621eba4c79SScott Long 
16639d2ff928SMarcel Moolenaar 	/* LINUX_CDROM_SEND_PACKET */
16649d2ff928SMarcel Moolenaar 	/* LINUX_CDROM_NEXT_WRITABLE */
16659d2ff928SMarcel Moolenaar 	/* LINUX_CDROM_LAST_WRITTEN */
166643bef515SMarcel Moolenaar 
1667426da3bcSAlfred Perlstein 	default:
1668426da3bcSAlfred Perlstein 		error = ENOIOCTL;
1669426da3bcSAlfred Perlstein 		break;
167043bef515SMarcel Moolenaar 	}
167143bef515SMarcel Moolenaar 
1672426da3bcSAlfred Perlstein 	fdrop(fp, td);
1673426da3bcSAlfred Perlstein 	return (error);
167443bef515SMarcel Moolenaar }
167543bef515SMarcel Moolenaar 
16763ad9c842SMaxim Sobolev static int
linux_ioctl_vfat(struct thread * td,struct linux_ioctl_args * args)16773ad9c842SMaxim Sobolev linux_ioctl_vfat(struct thread *td, struct linux_ioctl_args *args)
16783ad9c842SMaxim Sobolev {
16793ad9c842SMaxim Sobolev 
16803ad9c842SMaxim Sobolev 	return (ENOTTY);
16813ad9c842SMaxim Sobolev }
16823ad9c842SMaxim Sobolev 
168343bef515SMarcel Moolenaar /*
168443bef515SMarcel Moolenaar  * Sound related ioctls
168543bef515SMarcel Moolenaar  */
168643bef515SMarcel Moolenaar 
1687f9763094SMatthew N. Dodd struct linux_old_mixer_info {
1688f9763094SMatthew N. Dodd 	char	id[16];
1689f9763094SMatthew N. Dodd 	char	name[32];
1690f9763094SMatthew N. Dodd };
1691f9763094SMatthew N. Dodd 
1692cc5aa0a4SJohn Baldwin static uint32_t dirbits[4] = { IOC_VOID, IOC_IN, IOC_OUT, IOC_INOUT };
169343bef515SMarcel Moolenaar 
169443bef515SMarcel Moolenaar #define	SETDIR(c)	(((c) & ~IOC_DIRMASK) | dirbits[args->cmd >> 30])
169543bef515SMarcel Moolenaar 
169643bef515SMarcel Moolenaar static int
linux_ioctl_sound(struct thread * td,struct linux_ioctl_args * args)1697b40ce416SJulian Elischer linux_ioctl_sound(struct thread *td, struct linux_ioctl_args *args)
169843bef515SMarcel Moolenaar {
169943bef515SMarcel Moolenaar 
170043bef515SMarcel Moolenaar 	switch (args->cmd & 0xffff) {
170143bef515SMarcel Moolenaar 	case LINUX_SOUND_MIXER_WRITE_VOLUME:
170243bef515SMarcel Moolenaar 		args->cmd = SETDIR(SOUND_MIXER_WRITE_VOLUME);
17038451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
170443bef515SMarcel Moolenaar 
170543bef515SMarcel Moolenaar 	case LINUX_SOUND_MIXER_WRITE_BASS:
170643bef515SMarcel Moolenaar 		args->cmd = SETDIR(SOUND_MIXER_WRITE_BASS);
17078451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
170843bef515SMarcel Moolenaar 
170943bef515SMarcel Moolenaar 	case LINUX_SOUND_MIXER_WRITE_TREBLE:
171043bef515SMarcel Moolenaar 		args->cmd = SETDIR(SOUND_MIXER_WRITE_TREBLE);
17118451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
171243bef515SMarcel Moolenaar 
171343bef515SMarcel Moolenaar 	case LINUX_SOUND_MIXER_WRITE_SYNTH:
171443bef515SMarcel Moolenaar 		args->cmd = SETDIR(SOUND_MIXER_WRITE_SYNTH);
17158451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
171643bef515SMarcel Moolenaar 
171743bef515SMarcel Moolenaar 	case LINUX_SOUND_MIXER_WRITE_PCM:
171843bef515SMarcel Moolenaar 		args->cmd = SETDIR(SOUND_MIXER_WRITE_PCM);
17198451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
172043bef515SMarcel Moolenaar 
172143bef515SMarcel Moolenaar 	case LINUX_SOUND_MIXER_WRITE_SPEAKER:
172243bef515SMarcel Moolenaar 		args->cmd = SETDIR(SOUND_MIXER_WRITE_SPEAKER);
17238451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
172443bef515SMarcel Moolenaar 
172543bef515SMarcel Moolenaar 	case LINUX_SOUND_MIXER_WRITE_LINE:
172643bef515SMarcel Moolenaar 		args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE);
17278451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
172843bef515SMarcel Moolenaar 
172943bef515SMarcel Moolenaar 	case LINUX_SOUND_MIXER_WRITE_MIC:
173043bef515SMarcel Moolenaar 		args->cmd = SETDIR(SOUND_MIXER_WRITE_MIC);
17318451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
173243bef515SMarcel Moolenaar 
173343bef515SMarcel Moolenaar 	case LINUX_SOUND_MIXER_WRITE_CD:
173443bef515SMarcel Moolenaar 		args->cmd = SETDIR(SOUND_MIXER_WRITE_CD);
17358451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
173643bef515SMarcel Moolenaar 
173743bef515SMarcel Moolenaar 	case LINUX_SOUND_MIXER_WRITE_IMIX:
173843bef515SMarcel Moolenaar 		args->cmd = SETDIR(SOUND_MIXER_WRITE_IMIX);
17398451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
174043bef515SMarcel Moolenaar 
174143bef515SMarcel Moolenaar 	case LINUX_SOUND_MIXER_WRITE_ALTPCM:
174243bef515SMarcel Moolenaar 		args->cmd = SETDIR(SOUND_MIXER_WRITE_ALTPCM);
17438451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
174443bef515SMarcel Moolenaar 
174543bef515SMarcel Moolenaar 	case LINUX_SOUND_MIXER_WRITE_RECLEV:
174643bef515SMarcel Moolenaar 		args->cmd = SETDIR(SOUND_MIXER_WRITE_RECLEV);
17478451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
174843bef515SMarcel Moolenaar 
174943bef515SMarcel Moolenaar 	case LINUX_SOUND_MIXER_WRITE_IGAIN:
175043bef515SMarcel Moolenaar 		args->cmd = SETDIR(SOUND_MIXER_WRITE_IGAIN);
17518451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
175243bef515SMarcel Moolenaar 
175343bef515SMarcel Moolenaar 	case LINUX_SOUND_MIXER_WRITE_OGAIN:
175443bef515SMarcel Moolenaar 		args->cmd = SETDIR(SOUND_MIXER_WRITE_OGAIN);
17558451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
175643bef515SMarcel Moolenaar 
175743bef515SMarcel Moolenaar 	case LINUX_SOUND_MIXER_WRITE_LINE1:
175843bef515SMarcel Moolenaar 		args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE1);
17598451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
176043bef515SMarcel Moolenaar 
176143bef515SMarcel Moolenaar 	case LINUX_SOUND_MIXER_WRITE_LINE2:
176243bef515SMarcel Moolenaar 		args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE2);
17638451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
176443bef515SMarcel Moolenaar 
176543bef515SMarcel Moolenaar 	case LINUX_SOUND_MIXER_WRITE_LINE3:
176643bef515SMarcel Moolenaar 		args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE3);
17678451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
176843bef515SMarcel Moolenaar 
176979e3da06SEdward Tomasz Napierala 	case LINUX_SOUND_MIXER_WRITE_MONITOR:
177079e3da06SEdward Tomasz Napierala 		args->cmd = SETDIR(SOUND_MIXER_WRITE_MONITOR);
177179e3da06SEdward Tomasz Napierala 		return (sys_ioctl(td, (struct ioctl_args *)args));
177279e3da06SEdward Tomasz Napierala 
1773f9763094SMatthew N. Dodd 	case LINUX_SOUND_MIXER_INFO: {
1774f9763094SMatthew N. Dodd 		/* Key on encoded length */
1775f9763094SMatthew N. Dodd 		switch ((args->cmd >> 16) & 0x1fff) {
1776f9763094SMatthew N. Dodd 		case 0x005c: {	/* SOUND_MIXER_INFO */
17776a9bcacfSAlexander Motin 			args->cmd = SOUND_MIXER_INFO;
17786a9bcacfSAlexander Motin 			return (sys_ioctl(td, (struct ioctl_args *)args));
1779f9763094SMatthew N. Dodd 		}
1780f9763094SMatthew N. Dodd 		case 0x0030: {	/* SOUND_OLD_MIXER_INFO */
1781f9763094SMatthew N. Dodd 			struct linux_old_mixer_info info;
1782f9763094SMatthew N. Dodd 			bzero(&info, sizeof(info));
1783f9763094SMatthew N. Dodd 			strncpy(info.id, "OSS", sizeof(info.id) - 1);
1784b9924c20SMark Johnston 			strncpy(info.name, "FreeBSD OSS Mixer",
1785b9924c20SMark Johnston 			    sizeof(info.name) - 1);
1786b9924c20SMark Johnston 			return (copyout(&info, (void *)args->arg,
1787b9924c20SMark Johnston 			    sizeof(info)));
1788f9763094SMatthew N. Dodd 		}
1789f9763094SMatthew N. Dodd 		default:
1790f9763094SMatthew N. Dodd 			return (ENOIOCTL);
1791f9763094SMatthew N. Dodd 		}
1792f9763094SMatthew N. Dodd 		break;
1793f9763094SMatthew N. Dodd 	}
1794bf4f8992SBruce M Simpson 
179586f95e6bSMarcel Moolenaar 	case LINUX_OSS_GETVERSION: {
1796b62f75cfSJohn Baldwin 		int version = linux_get_oss_version(td);
17974b7ef73dSDag-Erling Smørgrav 		return (copyout(&version, (void *)args->arg, sizeof(int)));
179886f95e6bSMarcel Moolenaar 	}
179986f95e6bSMarcel Moolenaar 
18003ad9c842SMaxim Sobolev 	case LINUX_SOUND_MIXER_READ_STEREODEVS:
18013ad9c842SMaxim Sobolev 		args->cmd = SOUND_MIXER_READ_STEREODEVS;
18028451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
18033ad9c842SMaxim Sobolev 
1804506e9a3aSSean Farley 	case LINUX_SOUND_MIXER_READ_CAPS:
1805506e9a3aSSean Farley 		args->cmd = SOUND_MIXER_READ_CAPS;
18068451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
1807506e9a3aSSean Farley 
1808cc5f91eeSBruce M Simpson 	case LINUX_SOUND_MIXER_READ_RECMASK:
1809cc5f91eeSBruce M Simpson 		args->cmd = SOUND_MIXER_READ_RECMASK;
18108451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
1811cc5f91eeSBruce M Simpson 
181243bef515SMarcel Moolenaar 	case LINUX_SOUND_MIXER_READ_DEVMASK:
181343bef515SMarcel Moolenaar 		args->cmd = SOUND_MIXER_READ_DEVMASK;
18148451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
181543bef515SMarcel Moolenaar 
181633b3cce0SMarcel Moolenaar 	case LINUX_SOUND_MIXER_WRITE_RECSRC:
181733b3cce0SMarcel Moolenaar 		args->cmd = SETDIR(SOUND_MIXER_WRITE_RECSRC);
18188451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
181933b3cce0SMarcel Moolenaar 
182043bef515SMarcel Moolenaar 	case LINUX_SNDCTL_DSP_RESET:
182143bef515SMarcel Moolenaar 		args->cmd = SNDCTL_DSP_RESET;
18228451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
182343bef515SMarcel Moolenaar 
182443bef515SMarcel Moolenaar 	case LINUX_SNDCTL_DSP_SYNC:
182543bef515SMarcel Moolenaar 		args->cmd = SNDCTL_DSP_SYNC;
18268451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
182743bef515SMarcel Moolenaar 
182843bef515SMarcel Moolenaar 	case LINUX_SNDCTL_DSP_SPEED:
182943bef515SMarcel Moolenaar 		args->cmd = SNDCTL_DSP_SPEED;
18308451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
183143bef515SMarcel Moolenaar 
183243bef515SMarcel Moolenaar 	case LINUX_SNDCTL_DSP_STEREO:
183343bef515SMarcel Moolenaar 		args->cmd = SNDCTL_DSP_STEREO;
18348451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
183543bef515SMarcel Moolenaar 
183643bef515SMarcel Moolenaar 	case LINUX_SNDCTL_DSP_GETBLKSIZE: /* LINUX_SNDCTL_DSP_SETBLKSIZE */
183743bef515SMarcel Moolenaar 		args->cmd = SNDCTL_DSP_GETBLKSIZE;
18388451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
183943bef515SMarcel Moolenaar 
184043bef515SMarcel Moolenaar 	case LINUX_SNDCTL_DSP_SETFMT:
184143bef515SMarcel Moolenaar 		args->cmd = SNDCTL_DSP_SETFMT;
18428451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
184343bef515SMarcel Moolenaar 
184443bef515SMarcel Moolenaar 	case LINUX_SOUND_PCM_WRITE_CHANNELS:
184543bef515SMarcel Moolenaar 		args->cmd = SOUND_PCM_WRITE_CHANNELS;
18468451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
184743bef515SMarcel Moolenaar 
184843bef515SMarcel Moolenaar 	case LINUX_SOUND_PCM_WRITE_FILTER:
184943bef515SMarcel Moolenaar 		args->cmd = SOUND_PCM_WRITE_FILTER;
18508451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
185143bef515SMarcel Moolenaar 
185243bef515SMarcel Moolenaar 	case LINUX_SNDCTL_DSP_POST:
185343bef515SMarcel Moolenaar 		args->cmd = SNDCTL_DSP_POST;
18548451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
185543bef515SMarcel Moolenaar 
185643bef515SMarcel Moolenaar 	case LINUX_SNDCTL_DSP_SUBDIVIDE:
185743bef515SMarcel Moolenaar 		args->cmd = SNDCTL_DSP_SUBDIVIDE;
18588451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
185943bef515SMarcel Moolenaar 
186043bef515SMarcel Moolenaar 	case LINUX_SNDCTL_DSP_SETFRAGMENT:
186143bef515SMarcel Moolenaar 		args->cmd = SNDCTL_DSP_SETFRAGMENT;
18628451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
186343bef515SMarcel Moolenaar 
186443bef515SMarcel Moolenaar 	case LINUX_SNDCTL_DSP_GETFMTS:
186543bef515SMarcel Moolenaar 		args->cmd = SNDCTL_DSP_GETFMTS;
18668451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
186743bef515SMarcel Moolenaar 
186843bef515SMarcel Moolenaar 	case LINUX_SNDCTL_DSP_GETOSPACE:
186943bef515SMarcel Moolenaar 		args->cmd = SNDCTL_DSP_GETOSPACE;
18708451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
187143bef515SMarcel Moolenaar 
187243bef515SMarcel Moolenaar 	case LINUX_SNDCTL_DSP_GETISPACE:
187343bef515SMarcel Moolenaar 		args->cmd = SNDCTL_DSP_GETISPACE;
18748451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
187543bef515SMarcel Moolenaar 
187643bef515SMarcel Moolenaar 	case LINUX_SNDCTL_DSP_NONBLOCK:
187743bef515SMarcel Moolenaar 		args->cmd = SNDCTL_DSP_NONBLOCK;
18788451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
187943bef515SMarcel Moolenaar 
188043bef515SMarcel Moolenaar 	case LINUX_SNDCTL_DSP_GETCAPS:
188143bef515SMarcel Moolenaar 		args->cmd = SNDCTL_DSP_GETCAPS;
18828451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
188343bef515SMarcel Moolenaar 
188443bef515SMarcel Moolenaar 	case LINUX_SNDCTL_DSP_SETTRIGGER: /* LINUX_SNDCTL_GETTRIGGER */
188543bef515SMarcel Moolenaar 		args->cmd = SNDCTL_DSP_SETTRIGGER;
18868451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
188743bef515SMarcel Moolenaar 
188843bef515SMarcel Moolenaar 	case LINUX_SNDCTL_DSP_GETIPTR:
188943bef515SMarcel Moolenaar 		args->cmd = SNDCTL_DSP_GETIPTR;
18908451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
189143bef515SMarcel Moolenaar 
189243bef515SMarcel Moolenaar 	case LINUX_SNDCTL_DSP_GETOPTR:
189343bef515SMarcel Moolenaar 		args->cmd = SNDCTL_DSP_GETOPTR;
18948451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
189543bef515SMarcel Moolenaar 
1896a92c890fSAlexander Leidinger 	case LINUX_SNDCTL_DSP_SETDUPLEX:
1897a92c890fSAlexander Leidinger 		args->cmd = SNDCTL_DSP_SETDUPLEX;
18988451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
1899a92c890fSAlexander Leidinger 
190043bef515SMarcel Moolenaar 	case LINUX_SNDCTL_DSP_GETODELAY:
190143bef515SMarcel Moolenaar 		args->cmd = SNDCTL_DSP_GETODELAY;
19028451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
190343bef515SMarcel Moolenaar 
190443bef515SMarcel Moolenaar 	case LINUX_SNDCTL_SEQ_RESET:
190543bef515SMarcel Moolenaar 		args->cmd = SNDCTL_SEQ_RESET;
19068451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
190743bef515SMarcel Moolenaar 
190843bef515SMarcel Moolenaar 	case LINUX_SNDCTL_SEQ_SYNC:
190943bef515SMarcel Moolenaar 		args->cmd = SNDCTL_SEQ_SYNC;
19108451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
191143bef515SMarcel Moolenaar 
191243bef515SMarcel Moolenaar 	case LINUX_SNDCTL_SYNTH_INFO:
191343bef515SMarcel Moolenaar 		args->cmd = SNDCTL_SYNTH_INFO;
19148451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
191543bef515SMarcel Moolenaar 
191643bef515SMarcel Moolenaar 	case LINUX_SNDCTL_SEQ_CTRLRATE:
191743bef515SMarcel Moolenaar 		args->cmd = SNDCTL_SEQ_CTRLRATE;
19188451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
191943bef515SMarcel Moolenaar 
192043bef515SMarcel Moolenaar 	case LINUX_SNDCTL_SEQ_GETOUTCOUNT:
192143bef515SMarcel Moolenaar 		args->cmd = SNDCTL_SEQ_GETOUTCOUNT;
19228451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
192343bef515SMarcel Moolenaar 
192443bef515SMarcel Moolenaar 	case LINUX_SNDCTL_SEQ_GETINCOUNT:
192543bef515SMarcel Moolenaar 		args->cmd = SNDCTL_SEQ_GETINCOUNT;
19268451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
192743bef515SMarcel Moolenaar 
192843bef515SMarcel Moolenaar 	case LINUX_SNDCTL_SEQ_PERCMODE:
192943bef515SMarcel Moolenaar 		args->cmd = SNDCTL_SEQ_PERCMODE;
19308451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
193143bef515SMarcel Moolenaar 
193243bef515SMarcel Moolenaar 	case LINUX_SNDCTL_FM_LOAD_INSTR:
193343bef515SMarcel Moolenaar 		args->cmd = SNDCTL_FM_LOAD_INSTR;
19348451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
193543bef515SMarcel Moolenaar 
193643bef515SMarcel Moolenaar 	case LINUX_SNDCTL_SEQ_TESTMIDI:
193743bef515SMarcel Moolenaar 		args->cmd = SNDCTL_SEQ_TESTMIDI;
19388451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
193943bef515SMarcel Moolenaar 
194043bef515SMarcel Moolenaar 	case LINUX_SNDCTL_SEQ_RESETSAMPLES:
194143bef515SMarcel Moolenaar 		args->cmd = SNDCTL_SEQ_RESETSAMPLES;
19428451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
194343bef515SMarcel Moolenaar 
194443bef515SMarcel Moolenaar 	case LINUX_SNDCTL_SEQ_NRSYNTHS:
194543bef515SMarcel Moolenaar 		args->cmd = SNDCTL_SEQ_NRSYNTHS;
19468451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
194743bef515SMarcel Moolenaar 
194843bef515SMarcel Moolenaar 	case LINUX_SNDCTL_SEQ_NRMIDIS:
194943bef515SMarcel Moolenaar 		args->cmd = SNDCTL_SEQ_NRMIDIS;
19508451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
195143bef515SMarcel Moolenaar 
195243bef515SMarcel Moolenaar 	case LINUX_SNDCTL_MIDI_INFO:
195343bef515SMarcel Moolenaar 		args->cmd = SNDCTL_MIDI_INFO;
19548451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
195543bef515SMarcel Moolenaar 
195643bef515SMarcel Moolenaar 	case LINUX_SNDCTL_SEQ_TRESHOLD:
195743bef515SMarcel Moolenaar 		args->cmd = SNDCTL_SEQ_TRESHOLD;
19588451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
195943bef515SMarcel Moolenaar 
196043bef515SMarcel Moolenaar 	case LINUX_SNDCTL_SYNTH_MEMAVL:
196143bef515SMarcel Moolenaar 		args->cmd = SNDCTL_SYNTH_MEMAVL;
19628451d0ddSKip Macy 		return (sys_ioctl(td, (struct ioctl_args *)args));
1963c21dee17SSøren Schmidt 	}
19642394cd9aSJordan K. Hubbard 
196543bef515SMarcel Moolenaar 	return (ENOIOCTL);
196643bef515SMarcel Moolenaar }
196743bef515SMarcel Moolenaar 
196843bef515SMarcel Moolenaar /*
196943bef515SMarcel Moolenaar  * Console related ioctls
197043bef515SMarcel Moolenaar  */
197143bef515SMarcel Moolenaar 
197243bef515SMarcel Moolenaar static int
linux_ioctl_console(struct thread * td,struct linux_ioctl_args * args)1973b40ce416SJulian Elischer linux_ioctl_console(struct thread *td, struct linux_ioctl_args *args)
197443bef515SMarcel Moolenaar {
1975426da3bcSAlfred Perlstein 	struct file *fp;
1976426da3bcSAlfred Perlstein 	int error;
197743bef515SMarcel Moolenaar 
1978cbd92ce6SMatt Macy 	error = fget(td, args->fd, &cap_ioctl_rights, &fp);
19797008be5bSPawel Jakub Dawidek 	if (error != 0)
1980a4db4953SAlfred Perlstein 		return (error);
198143bef515SMarcel Moolenaar 	switch (args->cmd & 0xffff) {
198243bef515SMarcel Moolenaar 	case LINUX_KIOCSOUND:
198343bef515SMarcel Moolenaar 		args->cmd = KIOCSOUND;
19848451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1985426da3bcSAlfred Perlstein 		break;
198643bef515SMarcel Moolenaar 
198743bef515SMarcel Moolenaar 	case LINUX_KDMKTONE:
198843bef515SMarcel Moolenaar 		args->cmd = KDMKTONE;
19898451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1990426da3bcSAlfred Perlstein 		break;
199143bef515SMarcel Moolenaar 
199243bef515SMarcel Moolenaar 	case LINUX_KDGETLED:
199343bef515SMarcel Moolenaar 		args->cmd = KDGETLED;
19948451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1995426da3bcSAlfred Perlstein 		break;
199643bef515SMarcel Moolenaar 
199743bef515SMarcel Moolenaar 	case LINUX_KDSETLED:
199843bef515SMarcel Moolenaar 		args->cmd = KDSETLED;
19998451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
2000426da3bcSAlfred Perlstein 		break;
200143bef515SMarcel Moolenaar 
200243bef515SMarcel Moolenaar 	case LINUX_KDSETMODE:
200343bef515SMarcel Moolenaar 		args->cmd = KDSETMODE;
20048451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
2005426da3bcSAlfred Perlstein 		break;
200643bef515SMarcel Moolenaar 
200743bef515SMarcel Moolenaar 	case LINUX_KDGETMODE:
200843bef515SMarcel Moolenaar 		args->cmd = KDGETMODE;
20098451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
2010426da3bcSAlfred Perlstein 		break;
201143bef515SMarcel Moolenaar 
201243bef515SMarcel Moolenaar 	case LINUX_KDGKBMODE:
201343bef515SMarcel Moolenaar 		args->cmd = KDGKBMODE;
20148451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
2015426da3bcSAlfred Perlstein 		break;
201643bef515SMarcel Moolenaar 
201743bef515SMarcel Moolenaar 	case LINUX_KDSKBMODE: {
201843bef515SMarcel Moolenaar 		int kbdmode;
201943bef515SMarcel Moolenaar 		switch (args->arg) {
202043bef515SMarcel Moolenaar 		case LINUX_KBD_RAW:
202143bef515SMarcel Moolenaar 			kbdmode = K_RAW;
202243bef515SMarcel Moolenaar 			break;
202343bef515SMarcel Moolenaar 		case LINUX_KBD_XLATE:
202443bef515SMarcel Moolenaar 			kbdmode = K_XLATE;
202543bef515SMarcel Moolenaar 			break;
202643bef515SMarcel Moolenaar 		case LINUX_KBD_MEDIUMRAW:
202743bef515SMarcel Moolenaar 			kbdmode = K_RAW;
202843bef515SMarcel Moolenaar 			break;
202943bef515SMarcel Moolenaar 		default:
2030426da3bcSAlfred Perlstein 			fdrop(fp, td);
203143bef515SMarcel Moolenaar 			return (EINVAL);
203243bef515SMarcel Moolenaar 		}
2033d49fa1caSRobert Watson 		error = (fo_ioctl(fp, KDSKBMODE, (caddr_t)&kbdmode,
2034d49fa1caSRobert Watson 		    td->td_ucred, td));
2035426da3bcSAlfred Perlstein 		break;
203643bef515SMarcel Moolenaar 	}
203743bef515SMarcel Moolenaar 
203843bef515SMarcel Moolenaar 	case LINUX_VT_OPENQRY:
203943bef515SMarcel Moolenaar 		args->cmd = VT_OPENQRY;
20408451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
2041426da3bcSAlfred Perlstein 		break;
204243bef515SMarcel Moolenaar 
204343bef515SMarcel Moolenaar 	case LINUX_VT_GETMODE:
204443bef515SMarcel Moolenaar 		args->cmd = VT_GETMODE;
20458451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
2046426da3bcSAlfred Perlstein 		break;
204743bef515SMarcel Moolenaar 
204843bef515SMarcel Moolenaar 	case LINUX_VT_SETMODE: {
204936db02ffSBruce M Simpson 		struct vt_mode mode;
205036db02ffSBruce M Simpson 		if ((error = copyin((void *)args->arg, &mode, sizeof(mode))))
205136db02ffSBruce M Simpson 			break;
2052b7c4ebdbSDmitry Chagin 		if (LINUX_SIG_VALID(mode.relsig))
2053b7c4ebdbSDmitry Chagin 			mode.relsig = linux_to_bsd_signal(mode.relsig);
2054b7c4ebdbSDmitry Chagin 		else
2055b7c4ebdbSDmitry Chagin 			mode.relsig = 0;
2056b7c4ebdbSDmitry Chagin 		if (LINUX_SIG_VALID(mode.acqsig))
2057b7c4ebdbSDmitry Chagin 			mode.acqsig = linux_to_bsd_signal(mode.acqsig);
2058b7c4ebdbSDmitry Chagin 		else
2059b7c4ebdbSDmitry Chagin 			mode.acqsig = 0;
2060b7c4ebdbSDmitry Chagin 		/* XXX. Linux ignores frsig and set it to 0. */
2061b7c4ebdbSDmitry Chagin 		mode.frsig = 0;
206236db02ffSBruce M Simpson 		if ((error = copyout(&mode, (void *)args->arg, sizeof(mode))))
206336db02ffSBruce M Simpson 			break;
206443bef515SMarcel Moolenaar 		args->cmd = VT_SETMODE;
20658451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
2066426da3bcSAlfred Perlstein 		break;
206743bef515SMarcel Moolenaar 	}
206843bef515SMarcel Moolenaar 
206943bef515SMarcel Moolenaar 	case LINUX_VT_GETSTATE:
207043bef515SMarcel Moolenaar 		args->cmd = VT_GETACTIVE;
20718451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
2072426da3bcSAlfred Perlstein 		break;
207343bef515SMarcel Moolenaar 
207443bef515SMarcel Moolenaar 	case LINUX_VT_RELDISP:
207543bef515SMarcel Moolenaar 		args->cmd = VT_RELDISP;
20768451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
2077426da3bcSAlfred Perlstein 		break;
207843bef515SMarcel Moolenaar 
207943bef515SMarcel Moolenaar 	case LINUX_VT_ACTIVATE:
208043bef515SMarcel Moolenaar 		args->cmd = VT_ACTIVATE;
20818451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
2082426da3bcSAlfred Perlstein 		break;
208343bef515SMarcel Moolenaar 
208443bef515SMarcel Moolenaar 	case LINUX_VT_WAITACTIVE:
208543bef515SMarcel Moolenaar 		args->cmd = VT_WAITACTIVE;
20868451d0ddSKip Macy 		error = (sys_ioctl(td, (struct ioctl_args *)args));
2087426da3bcSAlfred Perlstein 		break;
208843bef515SMarcel Moolenaar 
2089426da3bcSAlfred Perlstein 	default:
2090426da3bcSAlfred Perlstein 		error = ENOIOCTL;
2091426da3bcSAlfred Perlstein 		break;
209243bef515SMarcel Moolenaar 	}
209343bef515SMarcel Moolenaar 
2094426da3bcSAlfred Perlstein 	fdrop(fp, td);
2095426da3bcSAlfred Perlstein 	return (error);
209643bef515SMarcel Moolenaar }
209743bef515SMarcel Moolenaar 
2098b0cb4883SIan Dowse /*
2099113bb55fSTai-hwa Liang  * Implement the SIOCGIFNAME ioctl
2100113bb55fSTai-hwa Liang  */
2101113bb55fSTai-hwa Liang 
2102113bb55fSTai-hwa Liang static int
linux_ioctl_ifname(struct thread * td,struct l_ifreq * uifr)2103113bb55fSTai-hwa Liang linux_ioctl_ifname(struct thread *td, struct l_ifreq *uifr)
2104113bb55fSTai-hwa Liang {
2105113bb55fSTai-hwa Liang 	struct l_ifreq ifr;
21063ab3c9c2SDmitry Chagin 	int error, ret;
2107113bb55fSTai-hwa Liang 
2108e9e637bfSJustin Hibbits 	error = copyin(uifr, &ifr, sizeof(ifr));
2109113bb55fSTai-hwa Liang 	if (error != 0)
2110113bb55fSTai-hwa Liang 		return (error);
2111a927409cSDmitry Chagin 	ret = ifname_bsd_to_linux_idx(ifr.ifr_index, ifr.ifr_name,
2112e9e637bfSJustin Hibbits 	    LINUX_IFNAMSIZ);
21133ab3c9c2SDmitry Chagin 	if (ret > 0)
21143ab3c9c2SDmitry Chagin 		return (copyout(&ifr, uifr, sizeof(ifr)));
21153ab3c9c2SDmitry Chagin 	else
21163ab3c9c2SDmitry Chagin 		return (ENODEV);
2117113bb55fSTai-hwa Liang }
2118113bb55fSTai-hwa Liang 
2119113bb55fSTai-hwa Liang /*
21208cdcad81SDag-Erling Smørgrav  * Implement the SIOCGIFCONF ioctl
21218cdcad81SDag-Erling Smørgrav  */
21226c5786fdSDmitry Chagin static u_int
linux_ifconf_ifaddr_cb(void * arg,struct ifaddr * ifa,u_int count)21236c5786fdSDmitry Chagin linux_ifconf_ifaddr_cb(void *arg, struct ifaddr *ifa, u_int count)
21246c5786fdSDmitry Chagin {
21256c5786fdSDmitry Chagin #ifdef COMPAT_LINUX32
21266c5786fdSDmitry Chagin 	struct l_ifconf *ifc;
21276c5786fdSDmitry Chagin #else
21286c5786fdSDmitry Chagin 	struct ifconf *ifc;
21296c5786fdSDmitry Chagin #endif
21306c5786fdSDmitry Chagin 
21316c5786fdSDmitry Chagin 	ifc = arg;
21326c5786fdSDmitry Chagin 	ifc->ifc_len += sizeof(struct l_ifreq);
21336c5786fdSDmitry Chagin 	return (1);
21346c5786fdSDmitry Chagin }
21356c5786fdSDmitry Chagin 
21366c5786fdSDmitry Chagin static int
linux_ifconf_ifnet_cb(if_t ifp,void * arg)21376c5786fdSDmitry Chagin linux_ifconf_ifnet_cb(if_t ifp, void *arg)
21386c5786fdSDmitry Chagin {
21396c5786fdSDmitry Chagin 
21406c5786fdSDmitry Chagin 	if_foreach_addr_type(ifp, AF_INET, linux_ifconf_ifaddr_cb, arg);
21416c5786fdSDmitry Chagin 	return (0);
21426c5786fdSDmitry Chagin }
21436c5786fdSDmitry Chagin 
21446c5786fdSDmitry Chagin struct linux_ifconfig_ifaddr_cb2_s {
21456c5786fdSDmitry Chagin 	struct l_ifreq ifr;
21466c5786fdSDmitry Chagin 	struct sbuf *sb;
21476c5786fdSDmitry Chagin 	size_t max_len;
21486c5786fdSDmitry Chagin 	size_t valid_len;
21496c5786fdSDmitry Chagin };
21506c5786fdSDmitry Chagin 
21516c5786fdSDmitry Chagin static u_int
linux_ifconf_ifaddr_cb2(void * arg,struct ifaddr * ifa,u_int len)21526c5786fdSDmitry Chagin linux_ifconf_ifaddr_cb2(void *arg, struct ifaddr *ifa, u_int len)
21536c5786fdSDmitry Chagin {
21546c5786fdSDmitry Chagin 	struct linux_ifconfig_ifaddr_cb2_s *cbs = arg;
21556c5786fdSDmitry Chagin 	struct sockaddr *sa = ifa->ifa_addr;
21566c5786fdSDmitry Chagin 
21576c5786fdSDmitry Chagin 	cbs->ifr.ifr_addr.sa_family = LINUX_AF_INET;
21586c5786fdSDmitry Chagin 	memcpy(cbs->ifr.ifr_addr.sa_data, sa->sa_data,
21596c5786fdSDmitry Chagin 	    sizeof(cbs->ifr.ifr_addr.sa_data));
21606c5786fdSDmitry Chagin 	sbuf_bcat(cbs->sb, &cbs->ifr, sizeof(cbs->ifr));
21616c5786fdSDmitry Chagin 	cbs->max_len += sizeof(cbs->ifr);
21626c5786fdSDmitry Chagin 
21636c5786fdSDmitry Chagin 	if (sbuf_error(cbs->sb) == 0)
21646c5786fdSDmitry Chagin 		cbs->valid_len = sbuf_len(cbs->sb);
21656c5786fdSDmitry Chagin 	return (1);
21666c5786fdSDmitry Chagin }
21676c5786fdSDmitry Chagin 
21686c5786fdSDmitry Chagin static int
linux_ifconf_ifnet_cb2(if_t ifp,void * arg)21696c5786fdSDmitry Chagin linux_ifconf_ifnet_cb2(if_t ifp, void *arg)
21706c5786fdSDmitry Chagin {
21716c5786fdSDmitry Chagin 	struct linux_ifconfig_ifaddr_cb2_s *cbs = arg;
21726c5786fdSDmitry Chagin 
21736c5786fdSDmitry Chagin 	bzero(&cbs->ifr, sizeof(cbs->ifr));
21746c5786fdSDmitry Chagin 	ifname_bsd_to_linux_ifp(ifp, cbs->ifr.ifr_name,
21756c5786fdSDmitry Chagin 	    sizeof(cbs->ifr.ifr_name));
21766c5786fdSDmitry Chagin 
21776c5786fdSDmitry Chagin 	/* Walk the address list */
21786c5786fdSDmitry Chagin 	if_foreach_addr_type(ifp, AF_INET, linux_ifconf_ifaddr_cb2, cbs);
21796c5786fdSDmitry Chagin 	return (0);
21806c5786fdSDmitry Chagin }
21818cdcad81SDag-Erling Smørgrav 
21828cdcad81SDag-Erling Smørgrav static int
linux_ifconf(struct thread * td,struct ifconf * uifc)21838cdcad81SDag-Erling Smørgrav linux_ifconf(struct thread *td, struct ifconf *uifc)
21848cdcad81SDag-Erling Smørgrav {
21856c5786fdSDmitry Chagin 	struct linux_ifconfig_ifaddr_cb2_s cbs;
21863ab3c9c2SDmitry Chagin 	struct epoch_tracker et;
21871997c537SDavid E. O'Brien #ifdef COMPAT_LINUX32
21884af27623STim J. Robbins 	struct l_ifconf ifc;
21894af27623STim J. Robbins #else
21908cdcad81SDag-Erling Smørgrav 	struct ifconf ifc;
21914af27623STim J. Robbins #endif
21928739cd44SCraig Rodrigues 	struct sbuf *sb;
21936c5786fdSDmitry Chagin 	int error, full;
21948cdcad81SDag-Erling Smørgrav 
21954b7ef73dSDag-Erling Smørgrav 	error = copyin(uifc, &ifc, sizeof(ifc));
21968cdcad81SDag-Erling Smørgrav 	if (error != 0)
21978cdcad81SDag-Erling Smørgrav 		return (error);
21988739cd44SCraig Rodrigues 
21993f77a2b4SBruce M Simpson 	/* handle the 'request buffer size' case */
220096a8c6aaSDmitry Chagin 	if (PTRIN(ifc.ifc_buf) == NULL) {
22013f77a2b4SBruce M Simpson 		ifc.ifc_len = 0;
22023ab3c9c2SDmitry Chagin 		NET_EPOCH_ENTER(et);
22036c5786fdSDmitry Chagin 		if_foreach(linux_ifconf_ifnet_cb, &ifc);
22043ab3c9c2SDmitry Chagin 		NET_EPOCH_EXIT(et);
2205f9b0675bSDmitry Chagin 		return (copyout(&ifc, uifc, sizeof(ifc)));
22063f77a2b4SBruce M Simpson 	}
2207f9b0675bSDmitry Chagin 	if (ifc.ifc_len <= 0)
22088739cd44SCraig Rodrigues 		return (EINVAL);
22098cdcad81SDag-Erling Smørgrav 
2210d447088dSDmitry Chagin 	full = 0;
2211d447088dSDmitry Chagin 	cbs.max_len = maxphys - 1;
2212d447088dSDmitry Chagin 
22138739cd44SCraig Rodrigues again:
22146c5786fdSDmitry Chagin 	if (ifc.ifc_len <= cbs.max_len) {
22156c5786fdSDmitry Chagin 		cbs.max_len = ifc.ifc_len;
22168739cd44SCraig Rodrigues 		full = 1;
22178739cd44SCraig Rodrigues 	}
22186c5786fdSDmitry Chagin 	cbs.sb = sb = sbuf_new(NULL, NULL, cbs.max_len + 1, SBUF_FIXEDLEN);
22196c5786fdSDmitry Chagin 	cbs.max_len = 0;
22206c5786fdSDmitry Chagin 	cbs.valid_len = 0;
2221217bab1eSMarcel Moolenaar 
222275387a27SMarcel Moolenaar 	/* Return all AF_INET addresses of all interfaces */
22233ab3c9c2SDmitry Chagin 	NET_EPOCH_ENTER(et);
22246c5786fdSDmitry Chagin 	if_foreach(linux_ifconf_ifnet_cb2, &cbs);
22253ab3c9c2SDmitry Chagin 	NET_EPOCH_EXIT(et);
22268cdcad81SDag-Erling Smørgrav 
22276c5786fdSDmitry Chagin 	if (cbs.valid_len != cbs.max_len && !full) {
22288739cd44SCraig Rodrigues 		sbuf_delete(sb);
22298739cd44SCraig Rodrigues 		goto again;
22308739cd44SCraig Rodrigues 	}
22318739cd44SCraig Rodrigues 
22326c5786fdSDmitry Chagin 	ifc.ifc_len = cbs.valid_len;
22338739cd44SCraig Rodrigues 	sbuf_finish(sb);
223443f13beaSColin Percival 	error = copyout(sbuf_data(sb), PTRIN(ifc.ifc_buf), ifc.ifc_len);
223543f13beaSColin Percival 	if (error == 0)
22364b7ef73dSDag-Erling Smørgrav 		error = copyout(&ifc, uifc, sizeof(ifc));
22378739cd44SCraig Rodrigues 	sbuf_delete(sb);
22388cdcad81SDag-Erling Smørgrav 
22398cdcad81SDag-Erling Smørgrav 	return (error);
22408cdcad81SDag-Erling Smørgrav }
22418cdcad81SDag-Erling Smørgrav 
22428cdcad81SDag-Erling Smørgrav static int
linux_ioctl_socket_ifreq(struct thread * td,int fd,u_int cmd,struct l_ifreq * uifr)2243f9b0675bSDmitry Chagin linux_ioctl_socket_ifreq(struct thread *td, int fd, u_int cmd,
2244f9b0675bSDmitry Chagin     struct l_ifreq *uifr)
22458cdcad81SDag-Erling Smørgrav {
2246f9b0675bSDmitry Chagin 	struct l_ifreq lifr;
2247f9b0675bSDmitry Chagin 	struct ifreq bifr;
2248f9b0675bSDmitry Chagin 	size_t ifrusiz;
2249f9b0675bSDmitry Chagin 	int error, temp_flags;
22508cdcad81SDag-Erling Smørgrav 
2251f9b0675bSDmitry Chagin 	switch (cmd) {
2252f9b0675bSDmitry Chagin 	case LINUX_SIOCGIFINDEX:
2253f9b0675bSDmitry Chagin 		cmd = SIOCGIFINDEX;
2254f9b0675bSDmitry Chagin 		break;
2255f9b0675bSDmitry Chagin 	case LINUX_SIOCGIFFLAGS:
2256f9b0675bSDmitry Chagin 		cmd = SIOCGIFFLAGS;
2257f9b0675bSDmitry Chagin 		break;
2258f9b0675bSDmitry Chagin 	case LINUX_SIOCGIFADDR:
2259f9b0675bSDmitry Chagin 		cmd = SIOCGIFADDR;
2260f9b0675bSDmitry Chagin 		break;
2261f9b0675bSDmitry Chagin 	case LINUX_SIOCSIFADDR:
2262f9b0675bSDmitry Chagin 		cmd = SIOCSIFADDR;
2263f9b0675bSDmitry Chagin 		break;
2264f9b0675bSDmitry Chagin 	case LINUX_SIOCGIFDSTADDR:
2265f9b0675bSDmitry Chagin 		cmd = SIOCGIFDSTADDR;
2266f9b0675bSDmitry Chagin 		break;
2267f9b0675bSDmitry Chagin 	case LINUX_SIOCGIFBRDADDR:
2268f9b0675bSDmitry Chagin 		cmd = SIOCGIFBRDADDR;
2269f9b0675bSDmitry Chagin 		break;
2270f9b0675bSDmitry Chagin 	case LINUX_SIOCGIFNETMASK:
2271f9b0675bSDmitry Chagin 		cmd = SIOCGIFNETMASK;
2272f9b0675bSDmitry Chagin 		break;
2273f9b0675bSDmitry Chagin 	case LINUX_SIOCSIFNETMASK:
2274f9b0675bSDmitry Chagin 		cmd = SIOCSIFNETMASK;
2275f9b0675bSDmitry Chagin 		break;
2276f9b0675bSDmitry Chagin 	case LINUX_SIOCGIFMTU:
2277f9b0675bSDmitry Chagin 		cmd = SIOCGIFMTU;
2278f9b0675bSDmitry Chagin 		break;
2279f9b0675bSDmitry Chagin 	case LINUX_SIOCSIFMTU:
2280f9b0675bSDmitry Chagin 		cmd = SIOCSIFMTU;
2281f9b0675bSDmitry Chagin 		break;
2282f9b0675bSDmitry Chagin 	case LINUX_SIOCGIFHWADDR:
2283f9b0675bSDmitry Chagin 		cmd = SIOCGHWADDR;
2284f9b0675bSDmitry Chagin 		break;
22851f2b31f7SAlvin Chen 	case LINUX_SIOCGIFMETRIC:
22861f2b31f7SAlvin Chen 		cmd = SIOCGIFMETRIC;
22871f2b31f7SAlvin Chen 		break;
22881f2b31f7SAlvin Chen 	case LINUX_SIOCSIFMETRIC:
22891f2b31f7SAlvin Chen 		cmd = SIOCSIFMETRIC;
22901f2b31f7SAlvin Chen 		break;
2291f9b0675bSDmitry Chagin 	/*
2292f9b0675bSDmitry Chagin 	 * XXX This is slightly bogus, but these ioctls are currently
2293f9b0675bSDmitry Chagin 	 * XXX only used by the aironet (if_an) network driver.
2294f9b0675bSDmitry Chagin 	 */
2295f9b0675bSDmitry Chagin 	case LINUX_SIOCDEVPRIVATE:
2296f9b0675bSDmitry Chagin 		cmd = SIOCGPRIVATE_0;
2297f9b0675bSDmitry Chagin 		break;
2298f9b0675bSDmitry Chagin 	case LINUX_SIOCDEVPRIVATE+1:
2299f9b0675bSDmitry Chagin 		cmd = SIOCGPRIVATE_1;
2300f9b0675bSDmitry Chagin 		break;
2301f9b0675bSDmitry Chagin 	default:
23025ad5cf50SAlvin Chen 		LINUX_RATELIMIT_MSG_OPT2(
23035ad5cf50SAlvin Chen 		    "ioctl_socket_ifreq fd=%d, cmd=0x%x is not implemented",
23045ad5cf50SAlvin Chen 		    fd, cmd);
2305f9b0675bSDmitry Chagin 		return (ENOIOCTL);
23068cdcad81SDag-Erling Smørgrav 	}
23078cdcad81SDag-Erling Smørgrav 
2308f9b0675bSDmitry Chagin 	error = copyin(uifr, &lifr, sizeof(lifr));
2309f9b0675bSDmitry Chagin 	if (error != 0)
2310f9b0675bSDmitry Chagin 		return (error);
2311f9b0675bSDmitry Chagin 	bzero(&bifr, sizeof(bifr));
23128cdcad81SDag-Erling Smørgrav 
23135c8919adSAlexander Leidinger 	/*
2314f9b0675bSDmitry Chagin 	 * The size of Linux enum ifr_ifru is bigger than
2315f9b0675bSDmitry Chagin 	 * the FreeBSD size due to the struct ifmap.
23165c8919adSAlexander Leidinger 	 */
2317f9b0675bSDmitry Chagin 	ifrusiz = (sizeof(lifr) > sizeof(bifr) ? sizeof(bifr) :
2318f9b0675bSDmitry Chagin 	    sizeof(lifr)) - offsetof(struct l_ifreq, ifr_ifru);
2319f9b0675bSDmitry Chagin 	bcopy(&lifr.ifr_ifru, &bifr.ifr_ifru, ifrusiz);
23205c8919adSAlexander Leidinger 
2321f9b0675bSDmitry Chagin 	error = ifname_linux_to_bsd(td, lifr.ifr_name, bifr.ifr_name);
2322f9b0675bSDmitry Chagin 	if (error != 0)
23235c8919adSAlexander Leidinger 		return (error);
23245c8919adSAlexander Leidinger 
2325f9b0675bSDmitry Chagin 	/* Translate in values. */
2326f9b0675bSDmitry Chagin 	switch (cmd) {
2327f9b0675bSDmitry Chagin 	case SIOCGIFINDEX:
2328f9b0675bSDmitry Chagin 		bifr.ifr_index = lifr.ifr_index;
2329f9b0675bSDmitry Chagin 		break;
2330f9b0675bSDmitry Chagin 	case SIOCSIFADDR:
2331f9b0675bSDmitry Chagin 	case SIOCSIFNETMASK:
2332f9b0675bSDmitry Chagin 		bifr.ifr_addr.sa_len = sizeof(struct sockaddr);
2333f9b0675bSDmitry Chagin 		bifr.ifr_addr.sa_family =
2334f9b0675bSDmitry Chagin 		    linux_to_bsd_domain(lifr.ifr_addr.sa_family);
2335f9b0675bSDmitry Chagin 		break;
2336f9b0675bSDmitry Chagin 	default:
2337f9b0675bSDmitry Chagin 		break;
2338f9b0675bSDmitry Chagin 	}
23395c8919adSAlexander Leidinger 
2340f9b0675bSDmitry Chagin 	error = kern_ioctl(td, fd, cmd, (caddr_t)&bifr);
2341f9b0675bSDmitry Chagin 	if (error != 0)
23425c8919adSAlexander Leidinger 		return (error);
2343f9b0675bSDmitry Chagin 	bzero(&lifr.ifr_ifru, sizeof(lifr.ifr_ifru));
2344f9b0675bSDmitry Chagin 
2345f9b0675bSDmitry Chagin 	/* Translate out values. */
2346f9b0675bSDmitry Chagin  	switch (cmd) {
2347f9b0675bSDmitry Chagin 	case SIOCGIFINDEX:
2348f9b0675bSDmitry Chagin 		lifr.ifr_index = bifr.ifr_index;
2349f9b0675bSDmitry Chagin 		break;
2350f9b0675bSDmitry Chagin 	case SIOCGIFFLAGS:
2351f9b0675bSDmitry Chagin 		temp_flags = bifr.ifr_flags | (bifr.ifr_flagshigh << 16);
2352f9b0675bSDmitry Chagin 		lifr.ifr_flags = bsd_to_linux_ifflags(temp_flags);
2353f9b0675bSDmitry Chagin 		break;
2354f9b0675bSDmitry Chagin 	case SIOCGIFADDR:
2355f9b0675bSDmitry Chagin 	case SIOCSIFADDR:
2356f9b0675bSDmitry Chagin 	case SIOCGIFDSTADDR:
2357f9b0675bSDmitry Chagin 	case SIOCGIFBRDADDR:
2358f9b0675bSDmitry Chagin 	case SIOCGIFNETMASK:
2359f9b0675bSDmitry Chagin 		bcopy(&bifr.ifr_addr, &lifr.ifr_addr, sizeof(bifr.ifr_addr));
2360f9b0675bSDmitry Chagin 		lifr.ifr_addr.sa_family =
2361f9b0675bSDmitry Chagin 		    bsd_to_linux_domain(bifr.ifr_addr.sa_family);
2362f9b0675bSDmitry Chagin 		break;
2363f9b0675bSDmitry Chagin 	case SIOCGHWADDR:
2364f9b0675bSDmitry Chagin 		bcopy(&bifr.ifr_addr, &lifr.ifr_hwaddr, sizeof(bifr.ifr_addr));
2365f9b0675bSDmitry Chagin 		lifr.ifr_hwaddr.sa_family = LINUX_ARPHRD_ETHER;
2366f9b0675bSDmitry Chagin 		break;
2367f9b0675bSDmitry Chagin 	default:
2368f9b0675bSDmitry Chagin 		bcopy(&bifr.ifr_ifru, &lifr.ifr_ifru, ifrusiz);
2369f9b0675bSDmitry Chagin 		break;
2370f9b0675bSDmitry Chagin 	}
2371f9b0675bSDmitry Chagin 
2372f9b0675bSDmitry Chagin 	return (copyout(&lifr, uifr, sizeof(lifr)));
23735c8919adSAlexander Leidinger }
23745c8919adSAlexander Leidinger 
237543bef515SMarcel Moolenaar /*
237643bef515SMarcel Moolenaar  * Socket related ioctls
237743bef515SMarcel Moolenaar  */
237843bef515SMarcel Moolenaar 
237943bef515SMarcel Moolenaar static int
linux_ioctl_socket(struct thread * td,struct linux_ioctl_args * args)2380b40ce416SJulian Elischer linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args)
238143bef515SMarcel Moolenaar {
2382b0cb4883SIan Dowse 	struct file *fp;
2383b0cb4883SIan Dowse 	int error, type;
23848cdcad81SDag-Erling Smørgrav 
2385cbd92ce6SMatt Macy 	error = fget(td, args->fd, &cap_ioctl_rights, &fp);
23867008be5bSPawel Jakub Dawidek 	if (error != 0)
2387b0cb4883SIan Dowse 		return (error);
2388b0cb4883SIan Dowse 	type = fp->f_type;
2389b0cb4883SIan Dowse 	fdrop(fp, td);
2390f9b0675bSDmitry Chagin 
2391f9b0675bSDmitry Chagin 	CURVNET_SET(TD_TO_VNET(td));
2392f9b0675bSDmitry Chagin 
2393b0cb4883SIan Dowse 	if (type != DTYPE_SOCKET) {
2394b0cb4883SIan Dowse 		/* not a socket - probably a tap / vmnet device */
2395b0cb4883SIan Dowse 		switch (args->cmd) {
2396b0cb4883SIan Dowse 		case LINUX_SIOCGIFADDR:
2397b0cb4883SIan Dowse 		case LINUX_SIOCSIFADDR:
2398b0cb4883SIan Dowse 		case LINUX_SIOCGIFFLAGS:
2399f9b0675bSDmitry Chagin 			error = linux_ioctl_special(td, args);
24008cdcad81SDag-Erling Smørgrav 			break;
24018cdcad81SDag-Erling Smørgrav 		default:
2402f9b0675bSDmitry Chagin 			error = ENOIOCTL;
2403f9b0675bSDmitry Chagin 			break;
2404f9b0675bSDmitry Chagin 		}
2405f9b0675bSDmitry Chagin 		CURVNET_RESTORE();
2406f9b0675bSDmitry Chagin 		return (error);
24078cdcad81SDag-Erling Smørgrav 	}
240843bef515SMarcel Moolenaar 
2409f9b0675bSDmitry Chagin 	switch (args->cmd) {
241043bef515SMarcel Moolenaar 	case LINUX_FIOSETOWN:
241143bef515SMarcel Moolenaar 		args->cmd = FIOSETOWN;
24128451d0ddSKip Macy 		error = sys_ioctl(td, (struct ioctl_args *)args);
24138cdcad81SDag-Erling Smørgrav 		break;
241443bef515SMarcel Moolenaar 
241543bef515SMarcel Moolenaar 	case LINUX_SIOCSPGRP:
241643bef515SMarcel Moolenaar 		args->cmd = SIOCSPGRP;
24178451d0ddSKip Macy 		error = sys_ioctl(td, (struct ioctl_args *)args);
24188cdcad81SDag-Erling Smørgrav 		break;
241943bef515SMarcel Moolenaar 
242043bef515SMarcel Moolenaar 	case LINUX_FIOGETOWN:
242143bef515SMarcel Moolenaar 		args->cmd = FIOGETOWN;
24228451d0ddSKip Macy 		error = sys_ioctl(td, (struct ioctl_args *)args);
24238cdcad81SDag-Erling Smørgrav 		break;
242443bef515SMarcel Moolenaar 
242543bef515SMarcel Moolenaar 	case LINUX_SIOCGPGRP:
242643bef515SMarcel Moolenaar 		args->cmd = SIOCGPGRP;
24278451d0ddSKip Macy 		error = sys_ioctl(td, (struct ioctl_args *)args);
24288cdcad81SDag-Erling Smørgrav 		break;
242943bef515SMarcel Moolenaar 
243043bef515SMarcel Moolenaar 	case LINUX_SIOCATMARK:
243143bef515SMarcel Moolenaar 		args->cmd = SIOCATMARK;
24328451d0ddSKip Macy 		error = sys_ioctl(td, (struct ioctl_args *)args);
24338cdcad81SDag-Erling Smørgrav 		break;
243443bef515SMarcel Moolenaar 
243543bef515SMarcel Moolenaar 	/* LINUX_SIOCGSTAMP */
243643bef515SMarcel Moolenaar 
2437113bb55fSTai-hwa Liang 	case LINUX_SIOCGIFNAME:
2438113bb55fSTai-hwa Liang 		error = linux_ioctl_ifname(td, (struct l_ifreq *)args->arg);
2439113bb55fSTai-hwa Liang 		break;
2440113bb55fSTai-hwa Liang 
244143bef515SMarcel Moolenaar 	case LINUX_SIOCGIFCONF:
24428cdcad81SDag-Erling Smørgrav 		error = linux_ifconf(td, (struct ifconf *)args->arg);
24438cdcad81SDag-Erling Smørgrav 		break;
244443bef515SMarcel Moolenaar 
244543bef515SMarcel Moolenaar 	case LINUX_SIOCADDMULTI:
244643bef515SMarcel Moolenaar 		args->cmd = SIOCADDMULTI;
24478451d0ddSKip Macy 		error = sys_ioctl(td, (struct ioctl_args *)args);
24488cdcad81SDag-Erling Smørgrav 		break;
244943bef515SMarcel Moolenaar 
245043bef515SMarcel Moolenaar 	case LINUX_SIOCDELMULTI:
245143bef515SMarcel Moolenaar 		args->cmd = SIOCDELMULTI;
24528451d0ddSKip Macy 		error = sys_ioctl(td, (struct ioctl_args *)args);
24538cdcad81SDag-Erling Smørgrav 		break;
2454b51cc76cSDag-Erling Smørgrav 
2455d60f0a3dSKonstantin Belousov 	case LINUX_SIOCGIFCOUNT:
2456d60f0a3dSKonstantin Belousov 		error = 0;
2457d60f0a3dSKonstantin Belousov 		break;
2458d60f0a3dSKonstantin Belousov 
2459f9b0675bSDmitry Chagin 	default:
2460f9b0675bSDmitry Chagin 		error = linux_ioctl_socket_ifreq(td, args->fd, args->cmd,
2461f9b0675bSDmitry Chagin 		    PTRIN(args->arg));
246282835638SDag-Erling Smørgrav 		break;
246343bef515SMarcel Moolenaar 	}
246443bef515SMarcel Moolenaar 
2465f9b0675bSDmitry Chagin 	CURVNET_RESTORE();
24668cdcad81SDag-Erling Smørgrav 	return (error);
246743bef515SMarcel Moolenaar }
246843bef515SMarcel Moolenaar 
246943bef515SMarcel Moolenaar /*
2470b51cc76cSDag-Erling Smørgrav  * Device private ioctl handler
2471b51cc76cSDag-Erling Smørgrav  */
2472b51cc76cSDag-Erling Smørgrav static int
linux_ioctl_private(struct thread * td,struct linux_ioctl_args * args)2473b51cc76cSDag-Erling Smørgrav linux_ioctl_private(struct thread *td, struct linux_ioctl_args *args)
2474b51cc76cSDag-Erling Smørgrav {
2475b51cc76cSDag-Erling Smørgrav 	struct file *fp;
2476b0cb4883SIan Dowse 	int error, type;
2477b51cc76cSDag-Erling Smørgrav 
2478cbd92ce6SMatt Macy 	error = fget(td, args->fd, &cap_ioctl_rights, &fp);
24797008be5bSPawel Jakub Dawidek 	if (error != 0)
2480b0cb4883SIan Dowse 		return (error);
2481b0cb4883SIan Dowse 	type = fp->f_type;
2482b0cb4883SIan Dowse 	fdrop(fp, td);
2483b51cc76cSDag-Erling Smørgrav 	if (type == DTYPE_SOCKET)
2484b51cc76cSDag-Erling Smørgrav 		return (linux_ioctl_socket(td, args));
2485b0cb4883SIan Dowse 	return (ENOIOCTL);
2486b0cb4883SIan Dowse }
2487b0cb4883SIan Dowse 
2488b0cb4883SIan Dowse /*
2489caa18809SEric Anholt  * DRM ioctl handler (sys/dev/drm)
2490caa18809SEric Anholt  */
2491caa18809SEric Anholt static int
linux_ioctl_drm(struct thread * td,struct linux_ioctl_args * args)2492caa18809SEric Anholt linux_ioctl_drm(struct thread *td, struct linux_ioctl_args *args)
2493caa18809SEric Anholt {
2494caa18809SEric Anholt 	args->cmd = SETDIR(args->cmd);
2495340f4a8dSEd Maste 	return (sys_ioctl(td, (struct ioctl_args *)args));
2496caa18809SEric Anholt }
2497caa18809SEric Anholt 
2498fcaf473cSAlexander Motin #ifdef COMPAT_LINUX32
24991eba4c79SScott Long static int
linux_ioctl_sg_io(struct thread * td,struct linux_ioctl_args * args)2500fcaf473cSAlexander Motin linux_ioctl_sg_io(struct thread *td, struct linux_ioctl_args *args)
25011eba4c79SScott Long {
2502fcaf473cSAlexander Motin 	struct sg_io_hdr io;
2503fcaf473cSAlexander Motin 	struct sg_io_hdr32 io32;
25041eba4c79SScott Long 	struct file *fp;
25051eba4c79SScott Long 	int error;
25061eba4c79SScott Long 
2507cbd92ce6SMatt Macy 	error = fget(td, args->fd, &cap_ioctl_rights, &fp);
25087008be5bSPawel Jakub Dawidek 	if (error != 0) {
25091eba4c79SScott Long 		printf("sg_linux_ioctl: fget returned %d\n", error);
25101eba4c79SScott Long 		return (error);
25111eba4c79SScott Long 	}
25121eba4c79SScott Long 
2513fcaf473cSAlexander Motin 	if ((error = copyin((void *)args->arg, &io32, sizeof(io32))) != 0)
2514fcaf473cSAlexander Motin 		goto out;
2515fcaf473cSAlexander Motin 
2516fcaf473cSAlexander Motin 	CP(io32, io, interface_id);
2517fcaf473cSAlexander Motin 	CP(io32, io, dxfer_direction);
2518fcaf473cSAlexander Motin 	CP(io32, io, cmd_len);
2519fcaf473cSAlexander Motin 	CP(io32, io, mx_sb_len);
2520fcaf473cSAlexander Motin 	CP(io32, io, iovec_count);
2521fcaf473cSAlexander Motin 	CP(io32, io, dxfer_len);
2522fcaf473cSAlexander Motin 	PTRIN_CP(io32, io, dxferp);
2523fcaf473cSAlexander Motin 	PTRIN_CP(io32, io, cmdp);
2524fcaf473cSAlexander Motin 	PTRIN_CP(io32, io, sbp);
2525fcaf473cSAlexander Motin 	CP(io32, io, timeout);
2526fcaf473cSAlexander Motin 	CP(io32, io, flags);
2527fcaf473cSAlexander Motin 	CP(io32, io, pack_id);
2528fcaf473cSAlexander Motin 	PTRIN_CP(io32, io, usr_ptr);
2529fcaf473cSAlexander Motin 	CP(io32, io, status);
2530fcaf473cSAlexander Motin 	CP(io32, io, masked_status);
2531fcaf473cSAlexander Motin 	CP(io32, io, msg_status);
2532fcaf473cSAlexander Motin 	CP(io32, io, sb_len_wr);
2533fcaf473cSAlexander Motin 	CP(io32, io, host_status);
2534fcaf473cSAlexander Motin 	CP(io32, io, driver_status);
2535fcaf473cSAlexander Motin 	CP(io32, io, resid);
2536fcaf473cSAlexander Motin 	CP(io32, io, duration);
2537fcaf473cSAlexander Motin 	CP(io32, io, info);
2538fcaf473cSAlexander Motin 
2539fcaf473cSAlexander Motin 	if ((error = fo_ioctl(fp, SG_IO, (caddr_t)&io, td->td_ucred, td)) != 0)
2540fcaf473cSAlexander Motin 		goto out;
2541fcaf473cSAlexander Motin 
2542fcaf473cSAlexander Motin 	CP(io, io32, interface_id);
2543fcaf473cSAlexander Motin 	CP(io, io32, dxfer_direction);
2544fcaf473cSAlexander Motin 	CP(io, io32, cmd_len);
2545fcaf473cSAlexander Motin 	CP(io, io32, mx_sb_len);
2546fcaf473cSAlexander Motin 	CP(io, io32, iovec_count);
2547fcaf473cSAlexander Motin 	CP(io, io32, dxfer_len);
2548fcaf473cSAlexander Motin 	PTROUT_CP(io, io32, dxferp);
2549fcaf473cSAlexander Motin 	PTROUT_CP(io, io32, cmdp);
2550fcaf473cSAlexander Motin 	PTROUT_CP(io, io32, sbp);
2551fcaf473cSAlexander Motin 	CP(io, io32, timeout);
2552fcaf473cSAlexander Motin 	CP(io, io32, flags);
2553fcaf473cSAlexander Motin 	CP(io, io32, pack_id);
2554fcaf473cSAlexander Motin 	PTROUT_CP(io, io32, usr_ptr);
2555fcaf473cSAlexander Motin 	CP(io, io32, status);
2556fcaf473cSAlexander Motin 	CP(io, io32, masked_status);
2557fcaf473cSAlexander Motin 	CP(io, io32, msg_status);
2558fcaf473cSAlexander Motin 	CP(io, io32, sb_len_wr);
2559fcaf473cSAlexander Motin 	CP(io, io32, host_status);
2560fcaf473cSAlexander Motin 	CP(io, io32, driver_status);
2561fcaf473cSAlexander Motin 	CP(io, io32, resid);
2562fcaf473cSAlexander Motin 	CP(io, io32, duration);
2563fcaf473cSAlexander Motin 	CP(io, io32, info);
2564fcaf473cSAlexander Motin 
2565fcaf473cSAlexander Motin 	error = copyout(&io32, (void *)args->arg, sizeof(io32));
2566fcaf473cSAlexander Motin 
2567fcaf473cSAlexander Motin out:
25681eba4c79SScott Long 	fdrop(fp, td);
25691eba4c79SScott Long 	return (error);
25701eba4c79SScott Long }
2571fcaf473cSAlexander Motin #endif
2572fcaf473cSAlexander Motin 
2573fcaf473cSAlexander Motin static int
linux_ioctl_sg(struct thread * td,struct linux_ioctl_args * args)2574fcaf473cSAlexander Motin linux_ioctl_sg(struct thread *td, struct linux_ioctl_args *args)
2575fcaf473cSAlexander Motin {
2576fcaf473cSAlexander Motin 
2577fcaf473cSAlexander Motin 	switch (args->cmd) {
2578fcaf473cSAlexander Motin 	case LINUX_SG_GET_VERSION_NUM:
2579fcaf473cSAlexander Motin 		args->cmd = SG_GET_VERSION_NUM;
2580fcaf473cSAlexander Motin 		break;
2581fcaf473cSAlexander Motin 	case LINUX_SG_SET_TIMEOUT:
2582fcaf473cSAlexander Motin 		args->cmd = SG_SET_TIMEOUT;
2583fcaf473cSAlexander Motin 		break;
2584fcaf473cSAlexander Motin 	case LINUX_SG_GET_TIMEOUT:
2585fcaf473cSAlexander Motin 		args->cmd = SG_GET_TIMEOUT;
2586fcaf473cSAlexander Motin 		break;
2587fcaf473cSAlexander Motin 	case LINUX_SG_IO:
2588fcaf473cSAlexander Motin 		args->cmd = SG_IO;
2589fcaf473cSAlexander Motin #ifdef COMPAT_LINUX32
2590fcaf473cSAlexander Motin 		return (linux_ioctl_sg_io(td, args));
2591fcaf473cSAlexander Motin #endif
2592fcaf473cSAlexander Motin 		break;
2593fcaf473cSAlexander Motin 	case LINUX_SG_GET_RESERVED_SIZE:
2594fcaf473cSAlexander Motin 		args->cmd = SG_GET_RESERVED_SIZE;
2595fcaf473cSAlexander Motin 		break;
2596fcaf473cSAlexander Motin 	case LINUX_SG_GET_SCSI_ID:
2597fcaf473cSAlexander Motin 		args->cmd = SG_GET_SCSI_ID;
2598fcaf473cSAlexander Motin 		break;
259994fe9f95SAlexander Motin 	case LINUX_SG_GET_SG_TABLESIZE:
260094fe9f95SAlexander Motin 		args->cmd = SG_GET_SG_TABLESIZE;
260194fe9f95SAlexander Motin 		break;
2602fcaf473cSAlexander Motin 	default:
2603fcaf473cSAlexander Motin 		return (ENODEV);
2604fcaf473cSAlexander Motin 	}
2605fcaf473cSAlexander Motin 	return (sys_ioctl(td, (struct ioctl_args *)args));
2606fcaf473cSAlexander Motin }
26071eba4c79SScott Long 
2608caa18809SEric Anholt /*
26097b6bedd3SAlexander Leidinger  * Video4Linux (V4L) ioctl handler
26107b6bedd3SAlexander Leidinger  */
26117b6bedd3SAlexander Leidinger static int
linux_to_bsd_v4l_tuner(struct l_video_tuner * lvt,struct video_tuner * vt)26127b6bedd3SAlexander Leidinger linux_to_bsd_v4l_tuner(struct l_video_tuner *lvt, struct video_tuner *vt)
26137b6bedd3SAlexander Leidinger {
26147b6bedd3SAlexander Leidinger 	vt->tuner = lvt->tuner;
26157b6bedd3SAlexander Leidinger 	strlcpy(vt->name, lvt->name, LINUX_VIDEO_TUNER_NAME_SIZE);
26167b6bedd3SAlexander Leidinger 	vt->rangelow = lvt->rangelow;	/* possible long size conversion */
26177b6bedd3SAlexander Leidinger 	vt->rangehigh = lvt->rangehigh;	/* possible long size conversion */
26187b6bedd3SAlexander Leidinger 	vt->flags = lvt->flags;
26197b6bedd3SAlexander Leidinger 	vt->mode = lvt->mode;
26207b6bedd3SAlexander Leidinger 	vt->signal = lvt->signal;
26217b6bedd3SAlexander Leidinger 	return (0);
26227b6bedd3SAlexander Leidinger }
26237b6bedd3SAlexander Leidinger 
26247b6bedd3SAlexander Leidinger static int
bsd_to_linux_v4l_tuner(struct video_tuner * vt,struct l_video_tuner * lvt)26257b6bedd3SAlexander Leidinger bsd_to_linux_v4l_tuner(struct video_tuner *vt, struct l_video_tuner *lvt)
26267b6bedd3SAlexander Leidinger {
26277b6bedd3SAlexander Leidinger 	lvt->tuner = vt->tuner;
26287b6bedd3SAlexander Leidinger 	strlcpy(lvt->name, vt->name, LINUX_VIDEO_TUNER_NAME_SIZE);
26297b6bedd3SAlexander Leidinger 	lvt->rangelow = vt->rangelow;	/* possible long size conversion */
26307b6bedd3SAlexander Leidinger 	lvt->rangehigh = vt->rangehigh;	/* possible long size conversion */
26317b6bedd3SAlexander Leidinger 	lvt->flags = vt->flags;
26327b6bedd3SAlexander Leidinger 	lvt->mode = vt->mode;
26337b6bedd3SAlexander Leidinger 	lvt->signal = vt->signal;
26347b6bedd3SAlexander Leidinger 	return (0);
26357b6bedd3SAlexander Leidinger }
26367b6bedd3SAlexander Leidinger 
2637eddc4003SAlexander Leidinger #ifdef COMPAT_LINUX_V4L_CLIPLIST
26387b6bedd3SAlexander Leidinger static int
linux_to_bsd_v4l_clip(struct l_video_clip * lvc,struct video_clip * vc)26397b6bedd3SAlexander Leidinger linux_to_bsd_v4l_clip(struct l_video_clip *lvc, struct video_clip *vc)
26407b6bedd3SAlexander Leidinger {
26417b6bedd3SAlexander Leidinger 	vc->x = lvc->x;
26427b6bedd3SAlexander Leidinger 	vc->y = lvc->y;
26437b6bedd3SAlexander Leidinger 	vc->width = lvc->width;
26447b6bedd3SAlexander Leidinger 	vc->height = lvc->height;
26457b6bedd3SAlexander Leidinger 	vc->next = PTRIN(lvc->next);	/* possible pointer size conversion */
26467b6bedd3SAlexander Leidinger 	return (0);
26477b6bedd3SAlexander Leidinger }
2648eddc4003SAlexander Leidinger #endif
26497b6bedd3SAlexander Leidinger 
26507b6bedd3SAlexander Leidinger static int
linux_to_bsd_v4l_window(struct l_video_window * lvw,struct video_window * vw)26517b6bedd3SAlexander Leidinger linux_to_bsd_v4l_window(struct l_video_window *lvw, struct video_window *vw)
26527b6bedd3SAlexander Leidinger {
26537b6bedd3SAlexander Leidinger 	vw->x = lvw->x;
26547b6bedd3SAlexander Leidinger 	vw->y = lvw->y;
26557b6bedd3SAlexander Leidinger 	vw->width = lvw->width;
26567b6bedd3SAlexander Leidinger 	vw->height = lvw->height;
26577b6bedd3SAlexander Leidinger 	vw->chromakey = lvw->chromakey;
26587b6bedd3SAlexander Leidinger 	vw->flags = lvw->flags;
26597b6bedd3SAlexander Leidinger 	vw->clips = PTRIN(lvw->clips);	/* possible pointer size conversion */
26607b6bedd3SAlexander Leidinger 	vw->clipcount = lvw->clipcount;
26617b6bedd3SAlexander Leidinger 	return (0);
26627b6bedd3SAlexander Leidinger }
26637b6bedd3SAlexander Leidinger 
26647b6bedd3SAlexander Leidinger static int
bsd_to_linux_v4l_window(struct video_window * vw,struct l_video_window * lvw)26657b6bedd3SAlexander Leidinger bsd_to_linux_v4l_window(struct video_window *vw, struct l_video_window *lvw)
26667b6bedd3SAlexander Leidinger {
26674308a374SEd Maste 	memset(lvw, 0, sizeof(*lvw));
26684308a374SEd Maste 
26697b6bedd3SAlexander Leidinger 	lvw->x = vw->x;
26707b6bedd3SAlexander Leidinger 	lvw->y = vw->y;
26717b6bedd3SAlexander Leidinger 	lvw->width = vw->width;
26727b6bedd3SAlexander Leidinger 	lvw->height = vw->height;
26737b6bedd3SAlexander Leidinger 	lvw->chromakey = vw->chromakey;
26747b6bedd3SAlexander Leidinger 	lvw->flags = vw->flags;
26757b6bedd3SAlexander Leidinger 	lvw->clips = PTROUT(vw->clips);	/* possible pointer size conversion */
26767b6bedd3SAlexander Leidinger 	lvw->clipcount = vw->clipcount;
26777b6bedd3SAlexander Leidinger 	return (0);
26787b6bedd3SAlexander Leidinger }
26797b6bedd3SAlexander Leidinger 
26807b6bedd3SAlexander Leidinger static int
linux_to_bsd_v4l_buffer(struct l_video_buffer * lvb,struct video_buffer * vb)26817b6bedd3SAlexander Leidinger linux_to_bsd_v4l_buffer(struct l_video_buffer *lvb, struct video_buffer *vb)
26827b6bedd3SAlexander Leidinger {
26837b6bedd3SAlexander Leidinger 	vb->base = PTRIN(lvb->base);	/* possible pointer size conversion */
26847b6bedd3SAlexander Leidinger 	vb->height = lvb->height;
26857b6bedd3SAlexander Leidinger 	vb->width = lvb->width;
26867b6bedd3SAlexander Leidinger 	vb->depth = lvb->depth;
26877b6bedd3SAlexander Leidinger 	vb->bytesperline = lvb->bytesperline;
26887b6bedd3SAlexander Leidinger 	return (0);
26897b6bedd3SAlexander Leidinger }
26907b6bedd3SAlexander Leidinger 
26917b6bedd3SAlexander Leidinger static int
bsd_to_linux_v4l_buffer(struct video_buffer * vb,struct l_video_buffer * lvb)26927b6bedd3SAlexander Leidinger bsd_to_linux_v4l_buffer(struct video_buffer *vb, struct l_video_buffer *lvb)
26937b6bedd3SAlexander Leidinger {
26947b6bedd3SAlexander Leidinger 	lvb->base = PTROUT(vb->base);	/* possible pointer size conversion */
26957b6bedd3SAlexander Leidinger 	lvb->height = vb->height;
26967b6bedd3SAlexander Leidinger 	lvb->width = vb->width;
26977b6bedd3SAlexander Leidinger 	lvb->depth = vb->depth;
26987b6bedd3SAlexander Leidinger 	lvb->bytesperline = vb->bytesperline;
26997b6bedd3SAlexander Leidinger 	return (0);
27007b6bedd3SAlexander Leidinger }
27017b6bedd3SAlexander Leidinger 
27027b6bedd3SAlexander Leidinger static int
linux_to_bsd_v4l_code(struct l_video_code * lvc,struct video_code * vc)27037b6bedd3SAlexander Leidinger linux_to_bsd_v4l_code(struct l_video_code *lvc, struct video_code *vc)
27047b6bedd3SAlexander Leidinger {
27057b6bedd3SAlexander Leidinger 	strlcpy(vc->loadwhat, lvc->loadwhat, LINUX_VIDEO_CODE_LOADWHAT_SIZE);
27067b6bedd3SAlexander Leidinger 	vc->datasize = lvc->datasize;
27077b6bedd3SAlexander Leidinger 	vc->data = PTRIN(lvc->data);	/* possible pointer size conversion */
27087b6bedd3SAlexander Leidinger 	return (0);
27097b6bedd3SAlexander Leidinger }
27107b6bedd3SAlexander Leidinger 
2711eddc4003SAlexander Leidinger #ifdef COMPAT_LINUX_V4L_CLIPLIST
27127b6bedd3SAlexander Leidinger static int
linux_v4l_clip_copy(void * lvc,struct video_clip ** ppvc)27130f6800b9SAlexander Leidinger linux_v4l_clip_copy(void *lvc, struct video_clip **ppvc)
27147b6bedd3SAlexander Leidinger {
27150f6800b9SAlexander Leidinger 	int error;
27167b6bedd3SAlexander Leidinger 	struct video_clip vclip;
27177b6bedd3SAlexander Leidinger 	struct l_video_clip l_vclip;
27187b6bedd3SAlexander Leidinger 
27190f6800b9SAlexander Leidinger 	error = copyin(lvc, &l_vclip, sizeof(l_vclip));
27207b6bedd3SAlexander Leidinger 	if (error) return (error);
27217b6bedd3SAlexander Leidinger 	linux_to_bsd_v4l_clip(&l_vclip, &vclip);
27227b6bedd3SAlexander Leidinger 	/* XXX: If there can be no concurrency: s/M_NOWAIT/M_WAITOK/ */
27237b6bedd3SAlexander Leidinger 	if ((*ppvc = malloc(sizeof(**ppvc), M_LINUX, M_NOWAIT)) == NULL)
2724eae594f7SEd Maste 		return (ENOMEM);    /* XXX: Linux has no ENOMEM here. */
272590782c0aSAlexander Leidinger 	memcpy(*ppvc, &vclip, sizeof(vclip));
27260f6800b9SAlexander Leidinger 	(*ppvc)->next = NULL;
27277b6bedd3SAlexander Leidinger 	return (0);
27287b6bedd3SAlexander Leidinger }
27297b6bedd3SAlexander Leidinger 
27307b6bedd3SAlexander Leidinger static int
linux_v4l_cliplist_free(struct video_window * vw)27317b6bedd3SAlexander Leidinger linux_v4l_cliplist_free(struct video_window *vw)
27327b6bedd3SAlexander Leidinger {
27337b6bedd3SAlexander Leidinger 	struct video_clip **ppvc;
27347b6bedd3SAlexander Leidinger 	struct video_clip **ppvc_next;
27357b6bedd3SAlexander Leidinger 
27367b6bedd3SAlexander Leidinger 	for (ppvc = &(vw->clips); *ppvc != NULL; ppvc = ppvc_next) {
27377b6bedd3SAlexander Leidinger 		ppvc_next = &((*ppvc)->next);
27387b6bedd3SAlexander Leidinger 		free(*ppvc, M_LINUX);
27397b6bedd3SAlexander Leidinger 	}
274090782c0aSAlexander Leidinger 	vw->clips = NULL;
274190782c0aSAlexander Leidinger 
27427b6bedd3SAlexander Leidinger 	return (0);
27437b6bedd3SAlexander Leidinger }
27440f6800b9SAlexander Leidinger 
27450f6800b9SAlexander Leidinger static int
linux_v4l_cliplist_copy(struct l_video_window * lvw,struct video_window * vw)27460f6800b9SAlexander Leidinger linux_v4l_cliplist_copy(struct l_video_window *lvw, struct video_window *vw)
27470f6800b9SAlexander Leidinger {
27480f6800b9SAlexander Leidinger 	int error;
27490f6800b9SAlexander Leidinger 	int clipcount;
27500f6800b9SAlexander Leidinger 	void *plvc;
27510f6800b9SAlexander Leidinger 	struct video_clip **ppvc;
27520f6800b9SAlexander Leidinger 
27530f6800b9SAlexander Leidinger 	/*
27540f6800b9SAlexander Leidinger 	 * XXX: The cliplist is used to pass in a list of clipping
27550f6800b9SAlexander Leidinger 	 *	rectangles or, if clipcount == VIDEO_CLIP_BITMAP, a
27560f6800b9SAlexander Leidinger 	 *	clipping bitmap.  Some Linux apps, however, appear to
27570f6800b9SAlexander Leidinger 	 *	leave cliplist and clips uninitialized.  In any case,
27580f6800b9SAlexander Leidinger 	 *	the cliplist is not used by pwc(4), at the time of
27590f6800b9SAlexander Leidinger 	 *	writing, FreeBSD's only V4L driver.  When a driver
27600f6800b9SAlexander Leidinger 	 *	that uses the cliplist is developed, this code may
27610f6800b9SAlexander Leidinger 	 *	need re-examiniation.
27620f6800b9SAlexander Leidinger 	 */
27630f6800b9SAlexander Leidinger 	error = 0;
27640f6800b9SAlexander Leidinger 	clipcount = vw->clipcount;
27650f6800b9SAlexander Leidinger 	if (clipcount == VIDEO_CLIP_BITMAP) {
27660f6800b9SAlexander Leidinger 		/*
27670f6800b9SAlexander Leidinger 		 * In this case, the pointer (clips) is overloaded
27680f6800b9SAlexander Leidinger 		 * to be a "void *" to a bitmap, therefore there
27690f6800b9SAlexander Leidinger 		 * is no struct video_clip to copy now.
27700f6800b9SAlexander Leidinger 		 */
27710f6800b9SAlexander Leidinger 	} else if (clipcount > 0 && clipcount <= 16384) {
27720f6800b9SAlexander Leidinger 		/*
27730f6800b9SAlexander Leidinger 		 * Clips points to list of clip rectangles, so
27740f6800b9SAlexander Leidinger 		 * copy the list.
27750f6800b9SAlexander Leidinger 		 *
27760f6800b9SAlexander Leidinger 		 * XXX: Upper limit of 16384 was used here to try to
27770f6800b9SAlexander Leidinger 		 *	avoid cases when clipcount and clips pointer
27780f6800b9SAlexander Leidinger 		 *	are uninitialized and therefore have high random
27790f6800b9SAlexander Leidinger 		 *	values, as is the case in the Linux Skype
27800f6800b9SAlexander Leidinger 		 *	application.  The value 16384 was chosen as that
27810f6800b9SAlexander Leidinger 		 *	is what is used in the Linux stradis(4) MPEG
27820f6800b9SAlexander Leidinger 		 *	decoder driver, the only place we found an
27830f6800b9SAlexander Leidinger 		 *	example of cliplist use.
27840f6800b9SAlexander Leidinger 		 */
27850f6800b9SAlexander Leidinger 		plvc = PTRIN(lvw->clips);
2786eddc4003SAlexander Leidinger 		vw->clips = NULL;
27870f6800b9SAlexander Leidinger 		ppvc = &(vw->clips);
27880f6800b9SAlexander Leidinger 		while (clipcount-- > 0) {
2789500ed14dSPedro F. Giffuni 			if (plvc == NULL) {
27900f6800b9SAlexander Leidinger 				error = EFAULT;
2791eddc4003SAlexander Leidinger 				break;
2792eddc4003SAlexander Leidinger 			} else {
27930f6800b9SAlexander Leidinger 				error = linux_v4l_clip_copy(plvc, ppvc);
27940f6800b9SAlexander Leidinger 				if (error) {
27950f6800b9SAlexander Leidinger 					linux_v4l_cliplist_free(vw);
27960f6800b9SAlexander Leidinger 					break;
27970f6800b9SAlexander Leidinger 				}
2798eddc4003SAlexander Leidinger 			}
27990f6800b9SAlexander Leidinger 			ppvc = &((*ppvc)->next);
28000f6800b9SAlexander Leidinger 			plvc = PTRIN(((struct l_video_clip *) plvc)->next);
28010f6800b9SAlexander Leidinger 		}
28020f6800b9SAlexander Leidinger 	} else {
28030f6800b9SAlexander Leidinger 		/*
28040f6800b9SAlexander Leidinger 		 * clipcount == 0 or negative (but not VIDEO_CLIP_BITMAP)
28050f6800b9SAlexander Leidinger 		 * Force cliplist to null.
28060f6800b9SAlexander Leidinger 		 */
28070f6800b9SAlexander Leidinger 		vw->clipcount = 0;
28080f6800b9SAlexander Leidinger 		vw->clips = NULL;
28090f6800b9SAlexander Leidinger 	}
28100f6800b9SAlexander Leidinger 	return (error);
28110f6800b9SAlexander Leidinger }
2812eddc4003SAlexander Leidinger #endif
28137b6bedd3SAlexander Leidinger 
28147b6bedd3SAlexander Leidinger static int
linux_ioctl_v4l(struct thread * td,struct linux_ioctl_args * args)28157b6bedd3SAlexander Leidinger linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args)
28167b6bedd3SAlexander Leidinger {
28177b6bedd3SAlexander Leidinger 	struct file *fp;
28187b6bedd3SAlexander Leidinger 	int error;
28197b6bedd3SAlexander Leidinger 	struct video_tuner vtun;
28207b6bedd3SAlexander Leidinger 	struct video_window vwin;
28217b6bedd3SAlexander Leidinger 	struct video_buffer vbuf;
28227b6bedd3SAlexander Leidinger 	struct video_code vcode;
28237b6bedd3SAlexander Leidinger 	struct l_video_tuner l_vtun;
28247b6bedd3SAlexander Leidinger 	struct l_video_window l_vwin;
28257b6bedd3SAlexander Leidinger 	struct l_video_buffer l_vbuf;
28267b6bedd3SAlexander Leidinger 	struct l_video_code l_vcode;
28277b6bedd3SAlexander Leidinger 
28287b6bedd3SAlexander Leidinger 	switch (args->cmd & 0xffff) {
28297b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCGCAP:		args->cmd = VIDIOCGCAP; break;
28307b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCGCHAN:		args->cmd = VIDIOCGCHAN; break;
28317b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCSCHAN:		args->cmd = VIDIOCSCHAN; break;
28327b6bedd3SAlexander Leidinger 
28337b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCGTUNER:
28347008be5bSPawel Jakub Dawidek 		error = fget(td, args->fd,
2835cbd92ce6SMatt Macy 		    &cap_ioctl_rights, &fp);
28367008be5bSPawel Jakub Dawidek 		if (error != 0)
28377b6bedd3SAlexander Leidinger 			return (error);
2838eddc4003SAlexander Leidinger 		error = copyin((void *) args->arg, &l_vtun, sizeof(l_vtun));
2839eddc4003SAlexander Leidinger 		if (error) {
2840eddc4003SAlexander Leidinger 			fdrop(fp, td);
2841eddc4003SAlexander Leidinger 			return (error);
2842eddc4003SAlexander Leidinger 		}
2843eddc4003SAlexander Leidinger 		linux_to_bsd_v4l_tuner(&l_vtun, &vtun);
28447b6bedd3SAlexander Leidinger 		error = fo_ioctl(fp, VIDIOCGTUNER, &vtun, td->td_ucred, td);
28457b6bedd3SAlexander Leidinger 		if (!error) {
28467b6bedd3SAlexander Leidinger 			bsd_to_linux_v4l_tuner(&vtun, &l_vtun);
28477b6bedd3SAlexander Leidinger 			error = copyout(&l_vtun, (void *) args->arg,
28487b6bedd3SAlexander Leidinger 			    sizeof(l_vtun));
28497b6bedd3SAlexander Leidinger 		}
28507b6bedd3SAlexander Leidinger 		fdrop(fp, td);
28517b6bedd3SAlexander Leidinger 		return (error);
28527b6bedd3SAlexander Leidinger 
28537b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCSTUNER:
28547008be5bSPawel Jakub Dawidek 		error = fget(td, args->fd,
2855cbd92ce6SMatt Macy 		    &cap_ioctl_rights, &fp);
28567008be5bSPawel Jakub Dawidek 		if (error != 0)
28577b6bedd3SAlexander Leidinger 			return (error);
28587b6bedd3SAlexander Leidinger 		error = copyin((void *) args->arg, &l_vtun, sizeof(l_vtun));
28597b6bedd3SAlexander Leidinger 		if (error) {
28607b6bedd3SAlexander Leidinger 			fdrop(fp, td);
28617b6bedd3SAlexander Leidinger 			return (error);
28627b6bedd3SAlexander Leidinger 		}
28637b6bedd3SAlexander Leidinger 		linux_to_bsd_v4l_tuner(&l_vtun, &vtun);
2864eddc4003SAlexander Leidinger 		error = fo_ioctl(fp, VIDIOCSTUNER, &vtun, td->td_ucred, td);
28657b6bedd3SAlexander Leidinger 		fdrop(fp, td);
28667b6bedd3SAlexander Leidinger 		return (error);
28677b6bedd3SAlexander Leidinger 
28687b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCGPICT:		args->cmd = VIDIOCGPICT; break;
28697b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCSPICT:		args->cmd = VIDIOCSPICT; break;
28707b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCCAPTURE:	args->cmd = VIDIOCCAPTURE; break;
28717b6bedd3SAlexander Leidinger 
28727b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCGWIN:
28737008be5bSPawel Jakub Dawidek 		error = fget(td, args->fd,
2874cbd92ce6SMatt Macy 		    &cap_ioctl_rights, &fp);
28757008be5bSPawel Jakub Dawidek 		if (error != 0)
28767b6bedd3SAlexander Leidinger 			return (error);
28777b6bedd3SAlexander Leidinger 		error = fo_ioctl(fp, VIDIOCGWIN, &vwin, td->td_ucred, td);
28787b6bedd3SAlexander Leidinger 		if (!error) {
28797b6bedd3SAlexander Leidinger 			bsd_to_linux_v4l_window(&vwin, &l_vwin);
28807b6bedd3SAlexander Leidinger 			error = copyout(&l_vwin, (void *) args->arg,
28817b6bedd3SAlexander Leidinger 			    sizeof(l_vwin));
28827b6bedd3SAlexander Leidinger 		}
28837b6bedd3SAlexander Leidinger 		fdrop(fp, td);
28847b6bedd3SAlexander Leidinger 		return (error);
28857b6bedd3SAlexander Leidinger 
28867b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCSWIN:
28877008be5bSPawel Jakub Dawidek 		error = fget(td, args->fd,
2888cbd92ce6SMatt Macy 		    &cap_ioctl_rights, &fp);
28897008be5bSPawel Jakub Dawidek 		if (error != 0)
28907b6bedd3SAlexander Leidinger 			return (error);
28917b6bedd3SAlexander Leidinger 		error = copyin((void *) args->arg, &l_vwin, sizeof(l_vwin));
28927b6bedd3SAlexander Leidinger 		if (error) {
28937b6bedd3SAlexander Leidinger 			fdrop(fp, td);
28947b6bedd3SAlexander Leidinger 			return (error);
28957b6bedd3SAlexander Leidinger 		}
28967b6bedd3SAlexander Leidinger 		linux_to_bsd_v4l_window(&l_vwin, &vwin);
2897eddc4003SAlexander Leidinger #ifdef COMPAT_LINUX_V4L_CLIPLIST
28987b6bedd3SAlexander Leidinger 		error = linux_v4l_cliplist_copy(&l_vwin, &vwin);
28990f6800b9SAlexander Leidinger 		if (error) {
29000f6800b9SAlexander Leidinger 			fdrop(fp, td);
29010f6800b9SAlexander Leidinger 			return (error);
29020f6800b9SAlexander Leidinger 		}
2903eddc4003SAlexander Leidinger #endif
29047b6bedd3SAlexander Leidinger 		error = fo_ioctl(fp, VIDIOCSWIN, &vwin, td->td_ucred, td);
29057b6bedd3SAlexander Leidinger 		fdrop(fp, td);
2906eddc4003SAlexander Leidinger #ifdef COMPAT_LINUX_V4L_CLIPLIST
29077b6bedd3SAlexander Leidinger 		linux_v4l_cliplist_free(&vwin);
2908eddc4003SAlexander Leidinger #endif
29097b6bedd3SAlexander Leidinger 		return (error);
29107b6bedd3SAlexander Leidinger 
29117b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCGFBUF:
29127008be5bSPawel Jakub Dawidek 		error = fget(td, args->fd,
2913cbd92ce6SMatt Macy 		    &cap_ioctl_rights, &fp);
29147008be5bSPawel Jakub Dawidek 		if (error != 0)
29157b6bedd3SAlexander Leidinger 			return (error);
29167b6bedd3SAlexander Leidinger 		error = fo_ioctl(fp, VIDIOCGFBUF, &vbuf, td->td_ucred, td);
29177b6bedd3SAlexander Leidinger 		if (!error) {
29187b6bedd3SAlexander Leidinger 			bsd_to_linux_v4l_buffer(&vbuf, &l_vbuf);
29197b6bedd3SAlexander Leidinger 			error = copyout(&l_vbuf, (void *) args->arg,
29207b6bedd3SAlexander Leidinger 			    sizeof(l_vbuf));
29217b6bedd3SAlexander Leidinger 		}
29227b6bedd3SAlexander Leidinger 		fdrop(fp, td);
29237b6bedd3SAlexander Leidinger 		return (error);
29247b6bedd3SAlexander Leidinger 
29257b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCSFBUF:
29267008be5bSPawel Jakub Dawidek 		error = fget(td, args->fd,
2927cbd92ce6SMatt Macy 		    &cap_ioctl_rights, &fp);
29287008be5bSPawel Jakub Dawidek 		if (error != 0)
29297b6bedd3SAlexander Leidinger 			return (error);
29307b6bedd3SAlexander Leidinger 		error = copyin((void *) args->arg, &l_vbuf, sizeof(l_vbuf));
29317b6bedd3SAlexander Leidinger 		if (error) {
29327b6bedd3SAlexander Leidinger 			fdrop(fp, td);
29337b6bedd3SAlexander Leidinger 			return (error);
29347b6bedd3SAlexander Leidinger 		}
29357b6bedd3SAlexander Leidinger 		linux_to_bsd_v4l_buffer(&l_vbuf, &vbuf);
29367b6bedd3SAlexander Leidinger 		error = fo_ioctl(fp, VIDIOCSFBUF, &vbuf, td->td_ucred, td);
29377b6bedd3SAlexander Leidinger 		fdrop(fp, td);
29387b6bedd3SAlexander Leidinger 		return (error);
29397b6bedd3SAlexander Leidinger 
29407b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCKEY:		args->cmd = VIDIOCKEY; break;
29417b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCGFREQ:		args->cmd = VIDIOCGFREQ; break;
29427b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCSFREQ:		args->cmd = VIDIOCSFREQ; break;
29437b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCGAUDIO:	args->cmd = VIDIOCGAUDIO; break;
29447b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCSAUDIO:	args->cmd = VIDIOCSAUDIO; break;
29457b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCSYNC:		args->cmd = VIDIOCSYNC; break;
29467b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCMCAPTURE:	args->cmd = VIDIOCMCAPTURE; break;
29477b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCGMBUF:		args->cmd = VIDIOCGMBUF; break;
29487b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCGUNIT:		args->cmd = VIDIOCGUNIT; break;
29497b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCGCAPTURE:	args->cmd = VIDIOCGCAPTURE; break;
29507b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCSCAPTURE:	args->cmd = VIDIOCSCAPTURE; break;
29517b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCSPLAYMODE:	args->cmd = VIDIOCSPLAYMODE; break;
29527b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCSWRITEMODE:	args->cmd = VIDIOCSWRITEMODE; break;
29537b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCGPLAYINFO:	args->cmd = VIDIOCGPLAYINFO; break;
29547b6bedd3SAlexander Leidinger 
29557b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCSMICROCODE:
29567008be5bSPawel Jakub Dawidek 		error = fget(td, args->fd,
2957cbd92ce6SMatt Macy 		    &cap_ioctl_rights, &fp);
29587008be5bSPawel Jakub Dawidek 		if (error != 0)
29597b6bedd3SAlexander Leidinger 			return (error);
29607b6bedd3SAlexander Leidinger 		error = copyin((void *) args->arg, &l_vcode, sizeof(l_vcode));
29617b6bedd3SAlexander Leidinger 		if (error) {
29627b6bedd3SAlexander Leidinger 			fdrop(fp, td);
29637b6bedd3SAlexander Leidinger 			return (error);
29647b6bedd3SAlexander Leidinger 		}
29657b6bedd3SAlexander Leidinger 		linux_to_bsd_v4l_code(&l_vcode, &vcode);
2966eddc4003SAlexander Leidinger 		error = fo_ioctl(fp, VIDIOCSMICROCODE, &vcode, td->td_ucred, td);
29677b6bedd3SAlexander Leidinger 		fdrop(fp, td);
29687b6bedd3SAlexander Leidinger 		return (error);
29697b6bedd3SAlexander Leidinger 
29707b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCGVBIFMT:	args->cmd = VIDIOCGVBIFMT; break;
29717b6bedd3SAlexander Leidinger 	case LINUX_VIDIOCSVBIFMT:	args->cmd = VIDIOCSVBIFMT; break;
29727b6bedd3SAlexander Leidinger 	default:			return (ENOIOCTL);
29737b6bedd3SAlexander Leidinger 	}
29747b6bedd3SAlexander Leidinger 
29758451d0ddSKip Macy 	error = sys_ioctl(td, (struct ioctl_args *)args);
29767b6bedd3SAlexander Leidinger 	return (error);
29777b6bedd3SAlexander Leidinger }
29787b6bedd3SAlexander Leidinger 
29797b6bedd3SAlexander Leidinger /*
2980b0cb4883SIan Dowse  * Special ioctl handler
2981b0cb4883SIan Dowse  */
2982b0cb4883SIan Dowse static int
linux_ioctl_special(struct thread * td,struct linux_ioctl_args * args)2983b0cb4883SIan Dowse linux_ioctl_special(struct thread *td, struct linux_ioctl_args *args)
2984b0cb4883SIan Dowse {
2985b0cb4883SIan Dowse 	int error;
2986b0cb4883SIan Dowse 
2987b0cb4883SIan Dowse 	switch (args->cmd) {
2988b0cb4883SIan Dowse 	case LINUX_SIOCGIFADDR:
2989b0cb4883SIan Dowse 		args->cmd = SIOCGIFADDR;
29908451d0ddSKip Macy 		error = sys_ioctl(td, (struct ioctl_args *)args);
2991b0cb4883SIan Dowse 		break;
2992b0cb4883SIan Dowse 	case LINUX_SIOCSIFADDR:
2993b0cb4883SIan Dowse 		args->cmd = SIOCSIFADDR;
29948451d0ddSKip Macy 		error = sys_ioctl(td, (struct ioctl_args *)args);
2995b0cb4883SIan Dowse 		break;
2996b0cb4883SIan Dowse 	case LINUX_SIOCGIFFLAGS:
2997b0cb4883SIan Dowse 		args->cmd = SIOCGIFFLAGS;
29988451d0ddSKip Macy 		error = sys_ioctl(td, (struct ioctl_args *)args);
2999b0cb4883SIan Dowse 		break;
3000b0cb4883SIan Dowse 	default:
3001b0cb4883SIan Dowse 		error = ENOIOCTL;
3002b0cb4883SIan Dowse 	}
3003b0cb4883SIan Dowse 
3004b0cb4883SIan Dowse 	return (error);
3005b51cc76cSDag-Erling Smørgrav }
3006b51cc76cSDag-Erling Smørgrav 
300715bf9014SAlexander Leidinger static int
linux_to_bsd_v4l2_standard(struct l_v4l2_standard * lvstd,struct v4l2_standard * vstd)300815bf9014SAlexander Leidinger linux_to_bsd_v4l2_standard(struct l_v4l2_standard *lvstd, struct v4l2_standard *vstd)
300915bf9014SAlexander Leidinger {
301015bf9014SAlexander Leidinger 	vstd->index = lvstd->index;
301115bf9014SAlexander Leidinger 	vstd->id = lvstd->id;
3012c6943f3aSConrad Meyer 	CTASSERT(sizeof(vstd->name) == sizeof(lvstd->name));
3013c6943f3aSConrad Meyer 	memcpy(vstd->name, lvstd->name, sizeof(vstd->name));
3014c6943f3aSConrad Meyer 	vstd->frameperiod = lvstd->frameperiod;
3015c6943f3aSConrad Meyer 	vstd->framelines = lvstd->framelines;
3016c6943f3aSConrad Meyer 	CTASSERT(sizeof(vstd->reserved) == sizeof(lvstd->reserved));
3017c6943f3aSConrad Meyer 	memcpy(vstd->reserved, lvstd->reserved, sizeof(vstd->reserved));
301815bf9014SAlexander Leidinger 	return (0);
301915bf9014SAlexander Leidinger }
302015bf9014SAlexander Leidinger 
302115bf9014SAlexander Leidinger static int
bsd_to_linux_v4l2_standard(struct v4l2_standard * vstd,struct l_v4l2_standard * lvstd)302215bf9014SAlexander Leidinger bsd_to_linux_v4l2_standard(struct v4l2_standard *vstd, struct l_v4l2_standard *lvstd)
302315bf9014SAlexander Leidinger {
302415bf9014SAlexander Leidinger 	lvstd->index = vstd->index;
302515bf9014SAlexander Leidinger 	lvstd->id = vstd->id;
3026c6943f3aSConrad Meyer 	CTASSERT(sizeof(vstd->name) == sizeof(lvstd->name));
3027c6943f3aSConrad Meyer 	memcpy(lvstd->name, vstd->name, sizeof(lvstd->name));
3028c6943f3aSConrad Meyer 	lvstd->frameperiod = vstd->frameperiod;
3029c6943f3aSConrad Meyer 	lvstd->framelines = vstd->framelines;
3030c6943f3aSConrad Meyer 	CTASSERT(sizeof(vstd->reserved) == sizeof(lvstd->reserved));
3031c6943f3aSConrad Meyer 	memcpy(lvstd->reserved, vstd->reserved, sizeof(lvstd->reserved));
303215bf9014SAlexander Leidinger 	return (0);
303315bf9014SAlexander Leidinger }
303415bf9014SAlexander Leidinger 
303515bf9014SAlexander Leidinger static int
linux_to_bsd_v4l2_buffer(struct l_v4l2_buffer * lvb,struct v4l2_buffer * vb)303615bf9014SAlexander Leidinger linux_to_bsd_v4l2_buffer(struct l_v4l2_buffer *lvb, struct v4l2_buffer *vb)
303715bf9014SAlexander Leidinger {
303815bf9014SAlexander Leidinger 	vb->index = lvb->index;
303915bf9014SAlexander Leidinger 	vb->type = lvb->type;
304015bf9014SAlexander Leidinger 	vb->bytesused = lvb->bytesused;
304115bf9014SAlexander Leidinger 	vb->flags = lvb->flags;
304215bf9014SAlexander Leidinger 	vb->field = lvb->field;
304315bf9014SAlexander Leidinger 	vb->timestamp.tv_sec = lvb->timestamp.tv_sec;
304415bf9014SAlexander Leidinger 	vb->timestamp.tv_usec = lvb->timestamp.tv_usec;
304515bf9014SAlexander Leidinger 	memcpy(&vb->timecode, &lvb->timecode, sizeof (lvb->timecode));
304615bf9014SAlexander Leidinger 	vb->sequence = lvb->sequence;
304715bf9014SAlexander Leidinger 	vb->memory = lvb->memory;
304815bf9014SAlexander Leidinger 	if (lvb->memory == V4L2_MEMORY_USERPTR)
304915bf9014SAlexander Leidinger 		/* possible pointer size conversion */
305015bf9014SAlexander Leidinger 		vb->m.userptr = (unsigned long)PTRIN(lvb->m.userptr);
305115bf9014SAlexander Leidinger 	else
305215bf9014SAlexander Leidinger 		vb->m.offset = lvb->m.offset;
305315bf9014SAlexander Leidinger 	vb->length = lvb->length;
305415bf9014SAlexander Leidinger 	vb->input = lvb->input;
305515bf9014SAlexander Leidinger 	vb->reserved = lvb->reserved;
305615bf9014SAlexander Leidinger 	return (0);
305715bf9014SAlexander Leidinger }
305815bf9014SAlexander Leidinger 
305915bf9014SAlexander Leidinger static int
bsd_to_linux_v4l2_buffer(struct v4l2_buffer * vb,struct l_v4l2_buffer * lvb)306015bf9014SAlexander Leidinger bsd_to_linux_v4l2_buffer(struct v4l2_buffer *vb, struct l_v4l2_buffer *lvb)
306115bf9014SAlexander Leidinger {
306215bf9014SAlexander Leidinger 	lvb->index = vb->index;
306315bf9014SAlexander Leidinger 	lvb->type = vb->type;
306415bf9014SAlexander Leidinger 	lvb->bytesused = vb->bytesused;
306515bf9014SAlexander Leidinger 	lvb->flags = vb->flags;
306615bf9014SAlexander Leidinger 	lvb->field = vb->field;
306715bf9014SAlexander Leidinger 	lvb->timestamp.tv_sec = vb->timestamp.tv_sec;
306815bf9014SAlexander Leidinger 	lvb->timestamp.tv_usec = vb->timestamp.tv_usec;
306915bf9014SAlexander Leidinger 	memcpy(&lvb->timecode, &vb->timecode, sizeof (vb->timecode));
307015bf9014SAlexander Leidinger 	lvb->sequence = vb->sequence;
307115bf9014SAlexander Leidinger 	lvb->memory = vb->memory;
307215bf9014SAlexander Leidinger 	if (vb->memory == V4L2_MEMORY_USERPTR)
307315bf9014SAlexander Leidinger 		/* possible pointer size conversion */
307415bf9014SAlexander Leidinger 		lvb->m.userptr = PTROUT(vb->m.userptr);
307515bf9014SAlexander Leidinger 	else
307615bf9014SAlexander Leidinger 		lvb->m.offset = vb->m.offset;
307715bf9014SAlexander Leidinger 	lvb->length = vb->length;
307815bf9014SAlexander Leidinger 	lvb->input = vb->input;
307915bf9014SAlexander Leidinger 	lvb->reserved = vb->reserved;
308015bf9014SAlexander Leidinger 	return (0);
308115bf9014SAlexander Leidinger }
308215bf9014SAlexander Leidinger 
308315bf9014SAlexander Leidinger static int
linux_to_bsd_v4l2_format(struct l_v4l2_format * lvf,struct v4l2_format * vf)308415bf9014SAlexander Leidinger linux_to_bsd_v4l2_format(struct l_v4l2_format *lvf, struct v4l2_format *vf)
308515bf9014SAlexander Leidinger {
308615bf9014SAlexander Leidinger 	vf->type = lvf->type;
308715bf9014SAlexander Leidinger 	if (lvf->type == V4L2_BUF_TYPE_VIDEO_OVERLAY
308815bf9014SAlexander Leidinger #ifdef V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
308915bf9014SAlexander Leidinger 	    || lvf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
309015bf9014SAlexander Leidinger #endif
309115bf9014SAlexander Leidinger 	    )
309215bf9014SAlexander Leidinger 		/*
309315bf9014SAlexander Leidinger 		 * XXX TODO - needs 32 -> 64 bit conversion:
309415bf9014SAlexander Leidinger 		 * (unused by webcams?)
309515bf9014SAlexander Leidinger 		 */
3096340f4a8dSEd Maste 		return (EINVAL);
309715bf9014SAlexander Leidinger 	memcpy(&vf->fmt, &lvf->fmt, sizeof(vf->fmt));
3098340f4a8dSEd Maste 	return (0);
309915bf9014SAlexander Leidinger }
310015bf9014SAlexander Leidinger 
310115bf9014SAlexander Leidinger static int
bsd_to_linux_v4l2_format(struct v4l2_format * vf,struct l_v4l2_format * lvf)310215bf9014SAlexander Leidinger bsd_to_linux_v4l2_format(struct v4l2_format *vf, struct l_v4l2_format *lvf)
310315bf9014SAlexander Leidinger {
310415bf9014SAlexander Leidinger 	lvf->type = vf->type;
310515bf9014SAlexander Leidinger 	if (vf->type == V4L2_BUF_TYPE_VIDEO_OVERLAY
310615bf9014SAlexander Leidinger #ifdef V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
310715bf9014SAlexander Leidinger 	    || vf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
310815bf9014SAlexander Leidinger #endif
310915bf9014SAlexander Leidinger 	    )
311015bf9014SAlexander Leidinger 		/*
311115bf9014SAlexander Leidinger 		 * XXX TODO - needs 32 -> 64 bit conversion:
311215bf9014SAlexander Leidinger 		 * (unused by webcams?)
311315bf9014SAlexander Leidinger 		 */
3114340f4a8dSEd Maste 		return (EINVAL);
311515bf9014SAlexander Leidinger 	memcpy(&lvf->fmt, &vf->fmt, sizeof(vf->fmt));
3116340f4a8dSEd Maste 	return (0);
311715bf9014SAlexander Leidinger }
311815bf9014SAlexander Leidinger static int
linux_ioctl_v4l2(struct thread * td,struct linux_ioctl_args * args)311915bf9014SAlexander Leidinger linux_ioctl_v4l2(struct thread *td, struct linux_ioctl_args *args)
312015bf9014SAlexander Leidinger {
312115bf9014SAlexander Leidinger 	struct file *fp;
312215bf9014SAlexander Leidinger 	int error;
312315bf9014SAlexander Leidinger 	struct v4l2_format vformat;
312415bf9014SAlexander Leidinger 	struct l_v4l2_format l_vformat;
312515bf9014SAlexander Leidinger 	struct v4l2_standard vstd;
312615bf9014SAlexander Leidinger 	struct l_v4l2_standard l_vstd;
312715bf9014SAlexander Leidinger 	struct l_v4l2_buffer l_vbuf;
312815bf9014SAlexander Leidinger 	struct v4l2_buffer vbuf;
312915bf9014SAlexander Leidinger 	struct v4l2_input vinp;
313015bf9014SAlexander Leidinger 
313115bf9014SAlexander Leidinger 	switch (args->cmd & 0xffff) {
313215bf9014SAlexander Leidinger 	case LINUX_VIDIOC_RESERVED:
313315bf9014SAlexander Leidinger 	case LINUX_VIDIOC_LOG_STATUS:
313415bf9014SAlexander Leidinger 		if ((args->cmd & IOC_DIRMASK) != LINUX_IOC_VOID)
3135340f4a8dSEd Maste 			return (ENOIOCTL);
313615bf9014SAlexander Leidinger 		args->cmd = (args->cmd & 0xffff) | IOC_VOID;
313715bf9014SAlexander Leidinger 		break;
313815bf9014SAlexander Leidinger 
313915bf9014SAlexander Leidinger 	case LINUX_VIDIOC_OVERLAY:
314015bf9014SAlexander Leidinger 	case LINUX_VIDIOC_STREAMON:
314115bf9014SAlexander Leidinger 	case LINUX_VIDIOC_STREAMOFF:
314215bf9014SAlexander Leidinger 	case LINUX_VIDIOC_S_STD:
314315bf9014SAlexander Leidinger 	case LINUX_VIDIOC_S_TUNER:
314415bf9014SAlexander Leidinger 	case LINUX_VIDIOC_S_AUDIO:
314515bf9014SAlexander Leidinger 	case LINUX_VIDIOC_S_AUDOUT:
314615bf9014SAlexander Leidinger 	case LINUX_VIDIOC_S_MODULATOR:
314715bf9014SAlexander Leidinger 	case LINUX_VIDIOC_S_FREQUENCY:
314815bf9014SAlexander Leidinger 	case LINUX_VIDIOC_S_CROP:
314915bf9014SAlexander Leidinger 	case LINUX_VIDIOC_S_JPEGCOMP:
315015bf9014SAlexander Leidinger 	case LINUX_VIDIOC_S_PRIORITY:
315115bf9014SAlexander Leidinger 	case LINUX_VIDIOC_DBG_S_REGISTER:
315215bf9014SAlexander Leidinger 	case LINUX_VIDIOC_S_HW_FREQ_SEEK:
315315bf9014SAlexander Leidinger 	case LINUX_VIDIOC_SUBSCRIBE_EVENT:
315415bf9014SAlexander Leidinger 	case LINUX_VIDIOC_UNSUBSCRIBE_EVENT:
315515bf9014SAlexander Leidinger 		args->cmd = (args->cmd & ~IOC_DIRMASK) | IOC_IN;
315615bf9014SAlexander Leidinger 		break;
315715bf9014SAlexander Leidinger 
315815bf9014SAlexander Leidinger 	case LINUX_VIDIOC_QUERYCAP:
315915bf9014SAlexander Leidinger 	case LINUX_VIDIOC_G_STD:
316015bf9014SAlexander Leidinger 	case LINUX_VIDIOC_G_AUDIO:
316115bf9014SAlexander Leidinger 	case LINUX_VIDIOC_G_INPUT:
316215bf9014SAlexander Leidinger 	case LINUX_VIDIOC_G_OUTPUT:
316315bf9014SAlexander Leidinger 	case LINUX_VIDIOC_G_AUDOUT:
316415bf9014SAlexander Leidinger 	case LINUX_VIDIOC_G_JPEGCOMP:
316515bf9014SAlexander Leidinger 	case LINUX_VIDIOC_QUERYSTD:
316615bf9014SAlexander Leidinger 	case LINUX_VIDIOC_G_PRIORITY:
316715bf9014SAlexander Leidinger 	case LINUX_VIDIOC_QUERY_DV_PRESET:
316815bf9014SAlexander Leidinger 		args->cmd = (args->cmd & ~IOC_DIRMASK) | IOC_OUT;
316915bf9014SAlexander Leidinger 		break;
317015bf9014SAlexander Leidinger 
317115bf9014SAlexander Leidinger 	case LINUX_VIDIOC_ENUM_FMT:
317215bf9014SAlexander Leidinger 	case LINUX_VIDIOC_REQBUFS:
317315bf9014SAlexander Leidinger 	case LINUX_VIDIOC_G_PARM:
317415bf9014SAlexander Leidinger 	case LINUX_VIDIOC_S_PARM:
317515bf9014SAlexander Leidinger 	case LINUX_VIDIOC_G_CTRL:
317615bf9014SAlexander Leidinger 	case LINUX_VIDIOC_S_CTRL:
317715bf9014SAlexander Leidinger 	case LINUX_VIDIOC_G_TUNER:
317815bf9014SAlexander Leidinger 	case LINUX_VIDIOC_QUERYCTRL:
317915bf9014SAlexander Leidinger 	case LINUX_VIDIOC_QUERYMENU:
318015bf9014SAlexander Leidinger 	case LINUX_VIDIOC_S_INPUT:
318115bf9014SAlexander Leidinger 	case LINUX_VIDIOC_S_OUTPUT:
318215bf9014SAlexander Leidinger 	case LINUX_VIDIOC_ENUMOUTPUT:
318315bf9014SAlexander Leidinger 	case LINUX_VIDIOC_G_MODULATOR:
318415bf9014SAlexander Leidinger 	case LINUX_VIDIOC_G_FREQUENCY:
318515bf9014SAlexander Leidinger 	case LINUX_VIDIOC_CROPCAP:
318615bf9014SAlexander Leidinger 	case LINUX_VIDIOC_G_CROP:
318715bf9014SAlexander Leidinger 	case LINUX_VIDIOC_ENUMAUDIO:
318815bf9014SAlexander Leidinger 	case LINUX_VIDIOC_ENUMAUDOUT:
318915bf9014SAlexander Leidinger 	case LINUX_VIDIOC_G_SLICED_VBI_CAP:
319015bf9014SAlexander Leidinger #ifdef VIDIOC_ENUM_FRAMESIZES
319115bf9014SAlexander Leidinger 	case LINUX_VIDIOC_ENUM_FRAMESIZES:
319215bf9014SAlexander Leidinger 	case LINUX_VIDIOC_ENUM_FRAMEINTERVALS:
319315bf9014SAlexander Leidinger 	case LINUX_VIDIOC_ENCODER_CMD:
319415bf9014SAlexander Leidinger 	case LINUX_VIDIOC_TRY_ENCODER_CMD:
319515bf9014SAlexander Leidinger #endif
319615bf9014SAlexander Leidinger 	case LINUX_VIDIOC_DBG_G_REGISTER:
319715bf9014SAlexander Leidinger 	case LINUX_VIDIOC_DBG_G_CHIP_IDENT:
319815bf9014SAlexander Leidinger 	case LINUX_VIDIOC_ENUM_DV_PRESETS:
319915bf9014SAlexander Leidinger 	case LINUX_VIDIOC_S_DV_PRESET:
320015bf9014SAlexander Leidinger 	case LINUX_VIDIOC_G_DV_PRESET:
320115bf9014SAlexander Leidinger 	case LINUX_VIDIOC_S_DV_TIMINGS:
320215bf9014SAlexander Leidinger 	case LINUX_VIDIOC_G_DV_TIMINGS:
320315bf9014SAlexander Leidinger 		args->cmd = (args->cmd & ~IOC_DIRMASK) | IOC_INOUT;
320415bf9014SAlexander Leidinger 		break;
320515bf9014SAlexander Leidinger 
320615bf9014SAlexander Leidinger 	case LINUX_VIDIOC_G_FMT:
320715bf9014SAlexander Leidinger 	case LINUX_VIDIOC_S_FMT:
320815bf9014SAlexander Leidinger 	case LINUX_VIDIOC_TRY_FMT:
320915bf9014SAlexander Leidinger 		error = copyin((void *)args->arg, &l_vformat, sizeof(l_vformat));
321015bf9014SAlexander Leidinger 		if (error)
321115bf9014SAlexander Leidinger 			return (error);
32127008be5bSPawel Jakub Dawidek 		error = fget(td, args->fd,
3213cbd92ce6SMatt Macy 		    &cap_ioctl_rights, &fp);
32147008be5bSPawel Jakub Dawidek 		if (error)
321515bf9014SAlexander Leidinger 			return (error);
321615bf9014SAlexander Leidinger 		if (linux_to_bsd_v4l2_format(&l_vformat, &vformat) != 0)
321715bf9014SAlexander Leidinger 			error = EINVAL;
321815bf9014SAlexander Leidinger 		else if ((args->cmd & 0xffff) == LINUX_VIDIOC_G_FMT)
321915bf9014SAlexander Leidinger 			error = fo_ioctl(fp, VIDIOC_G_FMT, &vformat,
322015bf9014SAlexander Leidinger 			    td->td_ucred, td);
322115bf9014SAlexander Leidinger 		else if ((args->cmd & 0xffff) == LINUX_VIDIOC_S_FMT)
322215bf9014SAlexander Leidinger 			error = fo_ioctl(fp, VIDIOC_S_FMT, &vformat,
322315bf9014SAlexander Leidinger 			    td->td_ucred, td);
322415bf9014SAlexander Leidinger 		else
322515bf9014SAlexander Leidinger 			error = fo_ioctl(fp, VIDIOC_TRY_FMT, &vformat,
322615bf9014SAlexander Leidinger 			    td->td_ucred, td);
322715bf9014SAlexander Leidinger 		bsd_to_linux_v4l2_format(&vformat, &l_vformat);
3228b9924c20SMark Johnston 		if (error == 0)
3229b9924c20SMark Johnston 			error = copyout(&l_vformat, (void *)args->arg,
3230b9924c20SMark Johnston 			    sizeof(l_vformat));
323115bf9014SAlexander Leidinger 		fdrop(fp, td);
323215bf9014SAlexander Leidinger 		return (error);
323315bf9014SAlexander Leidinger 
323415bf9014SAlexander Leidinger 	case LINUX_VIDIOC_ENUMSTD:
323515bf9014SAlexander Leidinger 		error = copyin((void *)args->arg, &l_vstd, sizeof(l_vstd));
323615bf9014SAlexander Leidinger 		if (error)
323715bf9014SAlexander Leidinger 			return (error);
323815bf9014SAlexander Leidinger 		linux_to_bsd_v4l2_standard(&l_vstd, &vstd);
32397008be5bSPawel Jakub Dawidek 		error = fget(td, args->fd,
3240cbd92ce6SMatt Macy 		    &cap_ioctl_rights, &fp);
32417008be5bSPawel Jakub Dawidek 		if (error)
324215bf9014SAlexander Leidinger 			return (error);
324315bf9014SAlexander Leidinger 		error = fo_ioctl(fp, VIDIOC_ENUMSTD, (caddr_t)&vstd,
324415bf9014SAlexander Leidinger 		    td->td_ucred, td);
324515bf9014SAlexander Leidinger 		if (error) {
324615bf9014SAlexander Leidinger 			fdrop(fp, td);
324715bf9014SAlexander Leidinger 			return (error);
324815bf9014SAlexander Leidinger 		}
324915bf9014SAlexander Leidinger 		bsd_to_linux_v4l2_standard(&vstd, &l_vstd);
325015bf9014SAlexander Leidinger 		error = copyout(&l_vstd, (void *)args->arg, sizeof(l_vstd));
325115bf9014SAlexander Leidinger 		fdrop(fp, td);
325215bf9014SAlexander Leidinger 		return (error);
325315bf9014SAlexander Leidinger 
325415bf9014SAlexander Leidinger 	case LINUX_VIDIOC_ENUMINPUT:
325515bf9014SAlexander Leidinger 		/*
325615bf9014SAlexander Leidinger 		 * The Linux struct l_v4l2_input differs only in size,
325715bf9014SAlexander Leidinger 		 * it has no padding at the end.
325815bf9014SAlexander Leidinger 		 */
325915bf9014SAlexander Leidinger 		error = copyin((void *)args->arg, &vinp,
326015bf9014SAlexander Leidinger 				sizeof(struct l_v4l2_input));
326115bf9014SAlexander Leidinger 		if (error != 0)
326215bf9014SAlexander Leidinger 			return (error);
32637008be5bSPawel Jakub Dawidek 		error = fget(td, args->fd,
3264cbd92ce6SMatt Macy 		    &cap_ioctl_rights, &fp);
32657008be5bSPawel Jakub Dawidek 		if (error != 0)
326615bf9014SAlexander Leidinger 			return (error);
326715bf9014SAlexander Leidinger 		error = fo_ioctl(fp, VIDIOC_ENUMINPUT, (caddr_t)&vinp,
326815bf9014SAlexander Leidinger 		    td->td_ucred, td);
326915bf9014SAlexander Leidinger 		if (error) {
327015bf9014SAlexander Leidinger 			fdrop(fp, td);
327115bf9014SAlexander Leidinger 			return (error);
327215bf9014SAlexander Leidinger 		}
327315bf9014SAlexander Leidinger 		error = copyout(&vinp, (void *)args->arg,
327415bf9014SAlexander Leidinger 				sizeof(struct l_v4l2_input));
327515bf9014SAlexander Leidinger 		fdrop(fp, td);
327615bf9014SAlexander Leidinger 		return (error);
327715bf9014SAlexander Leidinger 
327815bf9014SAlexander Leidinger 	case LINUX_VIDIOC_QUERYBUF:
327915bf9014SAlexander Leidinger 	case LINUX_VIDIOC_QBUF:
328015bf9014SAlexander Leidinger 	case LINUX_VIDIOC_DQBUF:
328115bf9014SAlexander Leidinger 		error = copyin((void *)args->arg, &l_vbuf, sizeof(l_vbuf));
328215bf9014SAlexander Leidinger 		if (error)
328315bf9014SAlexander Leidinger 			return (error);
32847008be5bSPawel Jakub Dawidek 		error = fget(td, args->fd,
3285cbd92ce6SMatt Macy 		    &cap_ioctl_rights, &fp);
32867008be5bSPawel Jakub Dawidek 		if (error)
328715bf9014SAlexander Leidinger 			return (error);
328815bf9014SAlexander Leidinger 		linux_to_bsd_v4l2_buffer(&l_vbuf, &vbuf);
328915bf9014SAlexander Leidinger 		if ((args->cmd & 0xffff) == LINUX_VIDIOC_QUERYBUF)
329015bf9014SAlexander Leidinger 			error = fo_ioctl(fp, VIDIOC_QUERYBUF, &vbuf,
329115bf9014SAlexander Leidinger 			    td->td_ucred, td);
329215bf9014SAlexander Leidinger 		else if ((args->cmd & 0xffff) == LINUX_VIDIOC_QBUF)
329315bf9014SAlexander Leidinger 			error = fo_ioctl(fp, VIDIOC_QBUF, &vbuf,
329415bf9014SAlexander Leidinger 			    td->td_ucred, td);
329515bf9014SAlexander Leidinger 		else
329615bf9014SAlexander Leidinger 			error = fo_ioctl(fp, VIDIOC_DQBUF, &vbuf,
329715bf9014SAlexander Leidinger 			    td->td_ucred, td);
329815bf9014SAlexander Leidinger 		bsd_to_linux_v4l2_buffer(&vbuf, &l_vbuf);
3299b9924c20SMark Johnston 		if (error == 0)
3300b9924c20SMark Johnston 			error = copyout(&l_vbuf, (void *)args->arg,
3301b9924c20SMark Johnston 			    sizeof(l_vbuf));
330215bf9014SAlexander Leidinger 		fdrop(fp, td);
330315bf9014SAlexander Leidinger 		return (error);
330415bf9014SAlexander Leidinger 
330515bf9014SAlexander Leidinger 	/*
330615bf9014SAlexander Leidinger 	 * XXX TODO - these need 32 -> 64 bit conversion:
330715bf9014SAlexander Leidinger 	 * (are any of them needed for webcams?)
330815bf9014SAlexander Leidinger 	 */
330915bf9014SAlexander Leidinger 	case LINUX_VIDIOC_G_FBUF:
331015bf9014SAlexander Leidinger 	case LINUX_VIDIOC_S_FBUF:
331115bf9014SAlexander Leidinger 
331215bf9014SAlexander Leidinger 	case LINUX_VIDIOC_G_EXT_CTRLS:
331315bf9014SAlexander Leidinger 	case LINUX_VIDIOC_S_EXT_CTRLS:
331415bf9014SAlexander Leidinger 	case LINUX_VIDIOC_TRY_EXT_CTRLS:
331515bf9014SAlexander Leidinger 
331615bf9014SAlexander Leidinger 	case LINUX_VIDIOC_DQEVENT:
331715bf9014SAlexander Leidinger 
331815bf9014SAlexander Leidinger 	default:			return (ENOIOCTL);
331915bf9014SAlexander Leidinger 	}
332015bf9014SAlexander Leidinger 
33218451d0ddSKip Macy 	error = sys_ioctl(td, (struct ioctl_args *)args);
332215bf9014SAlexander Leidinger 	return (error);
332315bf9014SAlexander Leidinger }
332415bf9014SAlexander Leidinger 
3325b51cc76cSDag-Erling Smørgrav /*
3326eedfc35cSWojciech A. Koszek  * Support for emulators/linux-libusb. This port uses FBSD_LUSB* macros
3327eedfc35cSWojciech A. Koszek  * instead of USB* ones. This lets us to provide correct values for cmd.
3328eedfc35cSWojciech A. Koszek  * 0xffffffe0 -- 0xffffffff range seemed to be the least collision-prone.
3329edfe497eSWojciech A. Koszek  */
3330edfe497eSWojciech A. Koszek static int
linux_ioctl_fbsd_usb(struct thread * td,struct linux_ioctl_args * args)3331edfe497eSWojciech A. Koszek linux_ioctl_fbsd_usb(struct thread *td, struct linux_ioctl_args *args)
3332edfe497eSWojciech A. Koszek {
3333eedfc35cSWojciech A. Koszek 	int error;
3334edfe497eSWojciech A. Koszek 
3335eedfc35cSWojciech A. Koszek 	error = 0;
3336eedfc35cSWojciech A. Koszek 	switch (args->cmd) {
3337eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_DEVICEENUMERATE:
3338eedfc35cSWojciech A. Koszek 		args->cmd = USB_DEVICEENUMERATE;
3339eedfc35cSWojciech A. Koszek 		break;
3340eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_DEV_QUIRK_ADD:
3341eedfc35cSWojciech A. Koszek 		args->cmd = USB_DEV_QUIRK_ADD;
3342eedfc35cSWojciech A. Koszek 		break;
3343eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_DEV_QUIRK_GET:
3344eedfc35cSWojciech A. Koszek 		args->cmd = USB_DEV_QUIRK_GET;
3345eedfc35cSWojciech A. Koszek 		break;
3346eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_DEV_QUIRK_REMOVE:
3347eedfc35cSWojciech A. Koszek 		args->cmd = USB_DEV_QUIRK_REMOVE;
3348eedfc35cSWojciech A. Koszek 		break;
3349eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_DO_REQUEST:
3350eedfc35cSWojciech A. Koszek 		args->cmd = USB_DO_REQUEST;
3351eedfc35cSWojciech A. Koszek 		break;
3352eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_FS_CLEAR_STALL_SYNC:
3353eedfc35cSWojciech A. Koszek 		args->cmd = USB_FS_CLEAR_STALL_SYNC;
3354eedfc35cSWojciech A. Koszek 		break;
3355eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_FS_CLOSE:
3356eedfc35cSWojciech A. Koszek 		args->cmd = USB_FS_CLOSE;
3357eedfc35cSWojciech A. Koszek 		break;
3358eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_FS_COMPLETE:
3359eedfc35cSWojciech A. Koszek 		args->cmd = USB_FS_COMPLETE;
3360eedfc35cSWojciech A. Koszek 		break;
3361eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_FS_INIT:
3362eedfc35cSWojciech A. Koszek 		args->cmd = USB_FS_INIT;
3363eedfc35cSWojciech A. Koszek 		break;
3364eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_FS_OPEN:
3365eedfc35cSWojciech A. Koszek 		args->cmd = USB_FS_OPEN;
3366eedfc35cSWojciech A. Koszek 		break;
3367eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_FS_START:
3368eedfc35cSWojciech A. Koszek 		args->cmd = USB_FS_START;
3369eedfc35cSWojciech A. Koszek 		break;
3370eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_FS_STOP:
3371eedfc35cSWojciech A. Koszek 		args->cmd = USB_FS_STOP;
3372eedfc35cSWojciech A. Koszek 		break;
3373eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_FS_UNINIT:
3374eedfc35cSWojciech A. Koszek 		args->cmd = USB_FS_UNINIT;
3375eedfc35cSWojciech A. Koszek 		break;
3376eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_GET_CONFIG:
3377eedfc35cSWojciech A. Koszek 		args->cmd = USB_GET_CONFIG;
3378eedfc35cSWojciech A. Koszek 		break;
3379eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_GET_DEVICEINFO:
3380eedfc35cSWojciech A. Koszek 		args->cmd = USB_GET_DEVICEINFO;
3381eedfc35cSWojciech A. Koszek 		break;
3382eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_GET_DEVICE_DESC:
3383eedfc35cSWojciech A. Koszek 		args->cmd = USB_GET_DEVICE_DESC;
3384eedfc35cSWojciech A. Koszek 		break;
3385eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_GET_FULL_DESC:
3386eedfc35cSWojciech A. Koszek 		args->cmd = USB_GET_FULL_DESC;
3387eedfc35cSWojciech A. Koszek 		break;
3388eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_GET_IFACE_DRIVER:
3389eedfc35cSWojciech A. Koszek 		args->cmd = USB_GET_IFACE_DRIVER;
3390eedfc35cSWojciech A. Koszek 		break;
3391eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_GET_PLUGTIME:
3392eedfc35cSWojciech A. Koszek 		args->cmd = USB_GET_PLUGTIME;
3393eedfc35cSWojciech A. Koszek 		break;
3394eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_GET_POWER_MODE:
3395eedfc35cSWojciech A. Koszek 		args->cmd = USB_GET_POWER_MODE;
3396eedfc35cSWojciech A. Koszek 		break;
3397eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_GET_REPORT_DESC:
3398eedfc35cSWojciech A. Koszek 		args->cmd = USB_GET_REPORT_DESC;
3399eedfc35cSWojciech A. Koszek 		break;
3400eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_GET_REPORT_ID:
3401eedfc35cSWojciech A. Koszek 		args->cmd = USB_GET_REPORT_ID;
3402eedfc35cSWojciech A. Koszek 		break;
3403eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_GET_TEMPLATE:
3404eedfc35cSWojciech A. Koszek 		args->cmd = USB_GET_TEMPLATE;
3405eedfc35cSWojciech A. Koszek 		break;
3406eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_IFACE_DRIVER_ACTIVE:
3407eedfc35cSWojciech A. Koszek 		args->cmd = USB_IFACE_DRIVER_ACTIVE;
3408eedfc35cSWojciech A. Koszek 		break;
3409eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_IFACE_DRIVER_DETACH:
3410eedfc35cSWojciech A. Koszek 		args->cmd = USB_IFACE_DRIVER_DETACH;
3411eedfc35cSWojciech A. Koszek 		break;
3412eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_QUIRK_NAME_GET:
3413eedfc35cSWojciech A. Koszek 		args->cmd = USB_QUIRK_NAME_GET;
3414eedfc35cSWojciech A. Koszek 		break;
3415eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_READ_DIR:
3416eedfc35cSWojciech A. Koszek 		args->cmd = USB_READ_DIR;
3417eedfc35cSWojciech A. Koszek 		break;
3418eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_SET_ALTINTERFACE:
3419eedfc35cSWojciech A. Koszek 		args->cmd = USB_SET_ALTINTERFACE;
3420eedfc35cSWojciech A. Koszek 		break;
3421eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_SET_CONFIG:
3422eedfc35cSWojciech A. Koszek 		args->cmd = USB_SET_CONFIG;
3423eedfc35cSWojciech A. Koszek 		break;
3424eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_SET_IMMED:
3425eedfc35cSWojciech A. Koszek 		args->cmd = USB_SET_IMMED;
3426eedfc35cSWojciech A. Koszek 		break;
3427eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_SET_POWER_MODE:
3428eedfc35cSWojciech A. Koszek 		args->cmd = USB_SET_POWER_MODE;
3429eedfc35cSWojciech A. Koszek 		break;
3430eedfc35cSWojciech A. Koszek 	case FBSD_LUSB_SET_TEMPLATE:
3431eedfc35cSWojciech A. Koszek 		args->cmd = USB_SET_TEMPLATE;
3432eedfc35cSWojciech A. Koszek 		break;
3433a40a377cSHans Petter Selasky 	case FBSD_LUSB_FS_OPEN_STREAM:
3434a40a377cSHans Petter Selasky 		args->cmd = USB_FS_OPEN_STREAM;
3435a40a377cSHans Petter Selasky 		break;
3436a40a377cSHans Petter Selasky 	case FBSD_LUSB_GET_DEV_PORT_PATH:
3437a40a377cSHans Petter Selasky 		args->cmd = USB_GET_DEV_PORT_PATH;
3438a40a377cSHans Petter Selasky 		break;
3439a40a377cSHans Petter Selasky 	case FBSD_LUSB_GET_POWER_USAGE:
3440a40a377cSHans Petter Selasky 		args->cmd = USB_GET_POWER_USAGE;
3441a40a377cSHans Petter Selasky 		break;
3442d845d3dcSHans Petter Selasky 	case FBSD_LUSB_DEVICESTATS:
3443d845d3dcSHans Petter Selasky 		args->cmd = USB_DEVICESTATS;
3444d845d3dcSHans Petter Selasky 		break;
3445eedfc35cSWojciech A. Koszek 	default:
3446eedfc35cSWojciech A. Koszek 		error = ENOIOCTL;
3447eedfc35cSWojciech A. Koszek 	}
3448eedfc35cSWojciech A. Koszek 	if (error != ENOIOCTL)
34498451d0ddSKip Macy 		error = sys_ioctl(td, (struct ioctl_args *)args);
3450eedfc35cSWojciech A. Koszek 	return (error);
3451edfe497eSWojciech A. Koszek }
3452edfe497eSWojciech A. Koszek 
3453edfe497eSWojciech A. Koszek /*
34546e1d05bbSDmitry Chagin  * Some evdev ioctls must be translated.
34556e1d05bbSDmitry Chagin  *  - EVIOCGMTSLOTS is a IOC_READ ioctl on Linux although it has input data
34566e1d05bbSDmitry Chagin  *    (must be IOC_INOUT on FreeBSD).
34576e1d05bbSDmitry Chagin  *  - On Linux, EVIOCGRAB, EVIOCREVOKE and EVIOCRMFF are defined as _IOW with
34586e1d05bbSDmitry Chagin  *    an int argument. You don't pass an int pointer to the ioctl(), however,
34596e1d05bbSDmitry Chagin  *    but just the int directly. On FreeBSD, they are defined as _IOWINT for
34606e1d05bbSDmitry Chagin  *    this to work.
34616e1d05bbSDmitry Chagin  */
34626e1d05bbSDmitry Chagin static int
linux_ioctl_evdev(struct thread * td,struct linux_ioctl_args * args)34636e1d05bbSDmitry Chagin linux_ioctl_evdev(struct thread *td, struct linux_ioctl_args *args)
34646e1d05bbSDmitry Chagin {
34656e1d05bbSDmitry Chagin 	struct file *fp;
34666e1d05bbSDmitry Chagin 	clockid_t clock;
34676e1d05bbSDmitry Chagin 	int error;
34686e1d05bbSDmitry Chagin 
34696e1d05bbSDmitry Chagin 	args->cmd = SETDIR(args->cmd);
34706e1d05bbSDmitry Chagin 
34716e1d05bbSDmitry Chagin 	switch (args->cmd) {
34726e1d05bbSDmitry Chagin 	case (EVIOCGRAB & ~IOC_DIRMASK) | IOC_IN:
34736e1d05bbSDmitry Chagin 		args->cmd = EVIOCGRAB;
34746e1d05bbSDmitry Chagin 		break;
34756e1d05bbSDmitry Chagin 	case (EVIOCREVOKE & ~IOC_DIRMASK) | IOC_IN:
34766e1d05bbSDmitry Chagin 		args->cmd = EVIOCREVOKE;
34776e1d05bbSDmitry Chagin 		break;
34786e1d05bbSDmitry Chagin 	case (EVIOCRMFF & ~IOC_DIRMASK) | IOC_IN:
34796e1d05bbSDmitry Chagin 		args->cmd = EVIOCRMFF;
34806e1d05bbSDmitry Chagin 		break;
34816e1d05bbSDmitry Chagin 	case EVIOCSCLOCKID: {
34826e1d05bbSDmitry Chagin 		error = copyin(PTRIN(args->arg), &clock, sizeof(clock));
34836e1d05bbSDmitry Chagin 		if (error != 0)
34846e1d05bbSDmitry Chagin 			return (error);
34856e1d05bbSDmitry Chagin 		if (clock & ~(LINUX_IOCTL_EVDEV_CLK))
34866e1d05bbSDmitry Chagin 			return (EINVAL);
34876e1d05bbSDmitry Chagin 		error = linux_to_native_clockid(&clock, clock);
34886e1d05bbSDmitry Chagin 		if (error != 0)
34896e1d05bbSDmitry Chagin 			return (error);
34906e1d05bbSDmitry Chagin 
34916e1d05bbSDmitry Chagin 		error = fget(td, args->fd,
3492cbd92ce6SMatt Macy 		    &cap_ioctl_rights, &fp);
34936e1d05bbSDmitry Chagin 		if (error != 0)
34946e1d05bbSDmitry Chagin 			return (error);
34956e1d05bbSDmitry Chagin 
34966e1d05bbSDmitry Chagin 		error = fo_ioctl(fp, EVIOCSCLOCKID, &clock, td->td_ucred, td);
34976e1d05bbSDmitry Chagin 		fdrop(fp, td);
34986e1d05bbSDmitry Chagin 		return (error);
34996e1d05bbSDmitry Chagin 	}
35006e1d05bbSDmitry Chagin 	default:
35016e1d05bbSDmitry Chagin 		break;
35026e1d05bbSDmitry Chagin 	}
35036e1d05bbSDmitry Chagin 
35046e1d05bbSDmitry Chagin 	if (IOCBASECMD(args->cmd) ==
35056e1d05bbSDmitry Chagin 	    ((EVIOCGMTSLOTS(0) & ~IOC_DIRMASK) | IOC_OUT))
35066e1d05bbSDmitry Chagin 		args->cmd = (args->cmd & ~IOC_DIRMASK) | IOC_INOUT;
35076e1d05bbSDmitry Chagin 
35086e1d05bbSDmitry Chagin 	return (sys_ioctl(td, (struct ioctl_args *)args));
35096e1d05bbSDmitry Chagin }
35106e1d05bbSDmitry Chagin 
351146888dedSMark Johnston static int
linux_ioctl_kcov(struct thread * td,struct linux_ioctl_args * args)351246888dedSMark Johnston linux_ioctl_kcov(struct thread *td, struct linux_ioctl_args *args)
351346888dedSMark Johnston {
351446888dedSMark Johnston 	int error;
351546888dedSMark Johnston 
351646888dedSMark Johnston 	error = 0;
351746888dedSMark Johnston 	switch (args->cmd & 0xffff) {
351846888dedSMark Johnston 	case LINUX_KCOV_INIT_TRACE:
351946888dedSMark Johnston 		args->cmd = KIOSETBUFSIZE;
352046888dedSMark Johnston 		break;
352146888dedSMark Johnston 	case LINUX_KCOV_ENABLE:
352246888dedSMark Johnston 		args->cmd = KIOENABLE;
352346888dedSMark Johnston 		if (args->arg == 0)
352446888dedSMark Johnston 			args->arg = KCOV_MODE_TRACE_PC;
352546888dedSMark Johnston 		else if (args->arg == 1)
352646888dedSMark Johnston 			args->arg = KCOV_MODE_TRACE_CMP;
352746888dedSMark Johnston 		else
352846888dedSMark Johnston 			error = EINVAL;
352946888dedSMark Johnston 		break;
353046888dedSMark Johnston 	case LINUX_KCOV_DISABLE:
353146888dedSMark Johnston 		args->cmd = KIODISABLE;
353246888dedSMark Johnston 		break;
353346888dedSMark Johnston 	default:
353446888dedSMark Johnston 		error = ENOTTY;
353546888dedSMark Johnston 		break;
353646888dedSMark Johnston 	}
353746888dedSMark Johnston 
353846888dedSMark Johnston 	if (error == 0)
353946888dedSMark Johnston 		error = sys_ioctl(td, (struct ioctl_args *)args);
354046888dedSMark Johnston 	return (error);
354146888dedSMark Johnston }
354246888dedSMark Johnston 
3543ad9cc86bSChuck Tuffli #ifndef COMPAT_LINUX32
3544ad9cc86bSChuck Tuffli static int
linux_ioctl_nvme(struct thread * td,struct linux_ioctl_args * args)3545ad9cc86bSChuck Tuffli linux_ioctl_nvme(struct thread *td, struct linux_ioctl_args *args)
3546ad9cc86bSChuck Tuffli {
3547ad9cc86bSChuck Tuffli 
3548ad9cc86bSChuck Tuffli 	/*
3549ad9cc86bSChuck Tuffli 	 * The NVMe drivers for namespace and controller implement these
3550ad9cc86bSChuck Tuffli 	 * commands using their native format. All the others are not
3551ad9cc86bSChuck Tuffli 	 * implemented yet.
3552ad9cc86bSChuck Tuffli 	 */
3553ad9cc86bSChuck Tuffli 	switch (args->cmd & 0xffff) {
3554ad9cc86bSChuck Tuffli 	case LINUX_NVME_IOCTL_ID:
3555ad9cc86bSChuck Tuffli 		args->cmd = NVME_IOCTL_ID;
3556ad9cc86bSChuck Tuffli 		break;
3557ad9cc86bSChuck Tuffli 	case LINUX_NVME_IOCTL_RESET:
3558ad9cc86bSChuck Tuffli 		args->cmd = NVME_IOCTL_RESET;
3559ad9cc86bSChuck Tuffli 		break;
3560ad9cc86bSChuck Tuffli 	case LINUX_NVME_IOCTL_ADMIN_CMD:
3561ad9cc86bSChuck Tuffli 		args->cmd = NVME_IOCTL_ADMIN_CMD;
3562ad9cc86bSChuck Tuffli 		break;
3563ad9cc86bSChuck Tuffli 	case LINUX_NVME_IOCTL_IO_CMD:
3564ad9cc86bSChuck Tuffli 		args->cmd = NVME_IOCTL_IO_CMD;
3565ad9cc86bSChuck Tuffli 		break;
3566ad9cc86bSChuck Tuffli 	default:
3567ad9cc86bSChuck Tuffli 		return (ENODEV);
3568ad9cc86bSChuck Tuffli 	}
3569ad9cc86bSChuck Tuffli 	return (sys_ioctl(td, (struct ioctl_args *)args));
3570ad9cc86bSChuck Tuffli }
3571ad9cc86bSChuck Tuffli #endif
3572ad9cc86bSChuck Tuffli 
35736e1d05bbSDmitry Chagin /*
357443bef515SMarcel Moolenaar  * main ioctl syscall function
357543bef515SMarcel Moolenaar  */
357643bef515SMarcel Moolenaar 
3577d6d9ddd4SMateusz Guzik static int
linux_ioctl_fallback(struct thread * td,struct linux_ioctl_args * args)3578d6d9ddd4SMateusz Guzik linux_ioctl_fallback(struct thread *td, struct linux_ioctl_args *args)
357943bef515SMarcel Moolenaar {
358043bef515SMarcel Moolenaar 	struct file *fp;
35818fc08087STijl Coosemans 	struct linux_ioctl_handler_element *he;
358243bef515SMarcel Moolenaar 	int error, cmd;
358343bef515SMarcel Moolenaar 
3584cbd92ce6SMatt Macy 	error = fget(td, args->fd, &cap_ioctl_rights, &fp);
35857008be5bSPawel Jakub Dawidek 	if (error != 0)
3586a4db4953SAlfred Perlstein 		return (error);
3587426da3bcSAlfred Perlstein 	if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
3588426da3bcSAlfred Perlstein 		fdrop(fp, td);
358943bef515SMarcel Moolenaar 		return (EBADF);
3590426da3bcSAlfred Perlstein 	}
359143bef515SMarcel Moolenaar 
359243bef515SMarcel Moolenaar 	/* Iterate over the ioctl handlers */
359343bef515SMarcel Moolenaar 	cmd = args->cmd & 0xffff;
3594ad6d226dSJohn Baldwin 	sx_slock(&linux_ioctl_sx);
3595ad6d226dSJohn Baldwin 	mtx_lock(&Giant);
35968fc08087STijl Coosemans #ifdef COMPAT_LINUX32
35978fc08087STijl Coosemans 	TAILQ_FOREACH(he, &linux32_ioctl_handlers, list) {
35988fc08087STijl Coosemans 		if (cmd >= he->low && cmd <= he->high) {
35998fc08087STijl Coosemans 			error = (*he->func)(td, args);
36008fc08087STijl Coosemans 			if (error != ENOIOCTL) {
36018fc08087STijl Coosemans 				mtx_unlock(&Giant);
36028fc08087STijl Coosemans 				sx_sunlock(&linux_ioctl_sx);
36038fc08087STijl Coosemans 				fdrop(fp, td);
36048fc08087STijl Coosemans 				return (error);
36058fc08087STijl Coosemans 			}
36068fc08087STijl Coosemans 		}
36078fc08087STijl Coosemans 	}
36088fc08087STijl Coosemans #endif
36098fc08087STijl Coosemans 	TAILQ_FOREACH(he, &linux_ioctl_handlers, list) {
361043bef515SMarcel Moolenaar 		if (cmd >= he->low && cmd <= he->high) {
3611b40ce416SJulian Elischer 			error = (*he->func)(td, args);
36122335a944SAlfred Perlstein 			if (error != ENOIOCTL) {
3613ad6d226dSJohn Baldwin 				mtx_unlock(&Giant);
3614ad6d226dSJohn Baldwin 				sx_sunlock(&linux_ioctl_sx);
3615426da3bcSAlfred Perlstein 				fdrop(fp, td);
361643bef515SMarcel Moolenaar 				return (error);
361743bef515SMarcel Moolenaar 			}
361843bef515SMarcel Moolenaar 		}
36192335a944SAlfred Perlstein 	}
3620ad6d226dSJohn Baldwin 	mtx_unlock(&Giant);
3621ad6d226dSJohn Baldwin 	sx_sunlock(&linux_ioctl_sx);
3622426da3bcSAlfred Perlstein 	fdrop(fp, td);
362343bef515SMarcel Moolenaar 
36245989b75bSDmitry Chagin 	switch (args->cmd & 0xffff) {
36255989b75bSDmitry Chagin 	case LINUX_BTRFS_IOC_CLONE:
362677311940SConrad Meyer 	case LINUX_F2FS_IOC_GET_FEATURES:
36270fabd7b5SEdward Tomasz Napierala 	case LINUX_FS_IOC_FIEMAP:
36285989b75bSDmitry Chagin 		return (ENOTSUP);
36295989b75bSDmitry Chagin 
36305989b75bSDmitry Chagin 	default:
363163ed2e36SConrad Meyer 		linux_msg(td, "%s fd=%d, cmd=0x%x ('%c',%d) is not implemented",
363263ed2e36SConrad Meyer 		    __func__, args->fd, args->cmd,
363343bef515SMarcel Moolenaar 		    (int)(args->cmd & 0xff00) >> 8, (int)(args->cmd & 0xff));
36345989b75bSDmitry Chagin 		break;
36355989b75bSDmitry Chagin 	}
363643bef515SMarcel Moolenaar 
363743bef515SMarcel Moolenaar 	return (EINVAL);
363843bef515SMarcel Moolenaar }
363943bef515SMarcel Moolenaar 
364043bef515SMarcel Moolenaar int
linux_ioctl(struct thread * td,struct linux_ioctl_args * args)3641d6d9ddd4SMateusz Guzik linux_ioctl(struct thread *td, struct linux_ioctl_args *args)
3642d6d9ddd4SMateusz Guzik {
3643d6d9ddd4SMateusz Guzik 	struct linux_ioctl_handler *handler;
3644d6d9ddd4SMateusz Guzik 	int error, cmd, i;
3645d6d9ddd4SMateusz Guzik 
3646d6d9ddd4SMateusz Guzik 	cmd = args->cmd & 0xffff;
3647d6d9ddd4SMateusz Guzik 
3648d6d9ddd4SMateusz Guzik 	/*
3649d6d9ddd4SMateusz Guzik 	 * array of ioctls known at compilation time. Elides a lot of work on
3650d6d9ddd4SMateusz Guzik 	 * each call compared to the list variant. Everything frequently used
3651d6d9ddd4SMateusz Guzik 	 * should be moved here.
3652d6d9ddd4SMateusz Guzik 	 *
3653d6d9ddd4SMateusz Guzik 	 * Arguably the magic creating the list should create an array instead.
3654d6d9ddd4SMateusz Guzik 	 *
3655d6d9ddd4SMateusz Guzik 	 * For now just a linear scan.
3656d6d9ddd4SMateusz Guzik 	 */
3657d6d9ddd4SMateusz Guzik 	for (i = 0; i < nitems(linux_ioctls); i++) {
3658d6d9ddd4SMateusz Guzik 		handler = &linux_ioctls[i];
3659d6d9ddd4SMateusz Guzik 		if (cmd >= handler->low && cmd <= handler->high) {
3660d6d9ddd4SMateusz Guzik 			error = (*handler->func)(td, args);
3661d6d9ddd4SMateusz Guzik 			if (error != ENOIOCTL) {
3662d6d9ddd4SMateusz Guzik 				return (error);
3663d6d9ddd4SMateusz Guzik 			}
3664d6d9ddd4SMateusz Guzik 		}
3665d6d9ddd4SMateusz Guzik 	}
3666d6d9ddd4SMateusz Guzik 	return (linux_ioctl_fallback(td, args));
3667d6d9ddd4SMateusz Guzik }
3668d6d9ddd4SMateusz Guzik 
3669d6d9ddd4SMateusz Guzik int
linux_ioctl_register_handler(struct linux_ioctl_handler * h)367043bef515SMarcel Moolenaar linux_ioctl_register_handler(struct linux_ioctl_handler *h)
367143bef515SMarcel Moolenaar {
36728fc08087STijl Coosemans 	struct linux_ioctl_handler_element *he, *cur;
367343bef515SMarcel Moolenaar 
367443bef515SMarcel Moolenaar 	if (h == NULL || h->func == NULL)
367543bef515SMarcel Moolenaar 		return (EINVAL);
367643bef515SMarcel Moolenaar 
367743bef515SMarcel Moolenaar 	/*
367843bef515SMarcel Moolenaar 	 * Reuse the element if the handler is already on the list, otherwise
367943bef515SMarcel Moolenaar 	 * create a new element.
368043bef515SMarcel Moolenaar 	 */
3681ad6d226dSJohn Baldwin 	sx_xlock(&linux_ioctl_sx);
36828fc08087STijl Coosemans 	TAILQ_FOREACH(he, &linux_ioctl_handlers, list) {
368343bef515SMarcel Moolenaar 		if (he->func == h->func)
368443bef515SMarcel Moolenaar 			break;
368543bef515SMarcel Moolenaar 	}
368643bef515SMarcel Moolenaar 	if (he == NULL) {
36871ede983cSDag-Erling Smørgrav 		he = malloc(sizeof(*he),
3688a163d034SWarner Losh 		    M_LINUX, M_WAITOK);
368943bef515SMarcel Moolenaar 		he->func = h->func;
369043bef515SMarcel Moolenaar 	} else
36918fc08087STijl Coosemans 		TAILQ_REMOVE(&linux_ioctl_handlers, he, list);
369243bef515SMarcel Moolenaar 
369343bef515SMarcel Moolenaar 	/* Initialize range information. */
369443bef515SMarcel Moolenaar 	he->low = h->low;
369543bef515SMarcel Moolenaar 	he->high = h->high;
369643bef515SMarcel Moolenaar 	he->span = h->high - h->low + 1;
369743bef515SMarcel Moolenaar 
369843bef515SMarcel Moolenaar 	/* Add the element to the list, sorted on span. */
36998fc08087STijl Coosemans 	TAILQ_FOREACH(cur, &linux_ioctl_handlers, list) {
370043bef515SMarcel Moolenaar 		if (cur->span > he->span) {
370143bef515SMarcel Moolenaar 			TAILQ_INSERT_BEFORE(cur, he, list);
3702ad6d226dSJohn Baldwin 			sx_xunlock(&linux_ioctl_sx);
370343bef515SMarcel Moolenaar 			return (0);
370443bef515SMarcel Moolenaar 		}
370543bef515SMarcel Moolenaar 	}
37068fc08087STijl Coosemans 	TAILQ_INSERT_TAIL(&linux_ioctl_handlers, he, list);
3707ad6d226dSJohn Baldwin 	sx_xunlock(&linux_ioctl_sx);
370843bef515SMarcel Moolenaar 
370943bef515SMarcel Moolenaar 	return (0);
371043bef515SMarcel Moolenaar }
371143bef515SMarcel Moolenaar 
371243bef515SMarcel Moolenaar int
linux_ioctl_unregister_handler(struct linux_ioctl_handler * h)371343bef515SMarcel Moolenaar linux_ioctl_unregister_handler(struct linux_ioctl_handler *h)
371443bef515SMarcel Moolenaar {
37158fc08087STijl Coosemans 	struct linux_ioctl_handler_element *he;
371643bef515SMarcel Moolenaar 
371743bef515SMarcel Moolenaar 	if (h == NULL || h->func == NULL)
371843bef515SMarcel Moolenaar 		return (EINVAL);
371943bef515SMarcel Moolenaar 
3720ad6d226dSJohn Baldwin 	sx_xlock(&linux_ioctl_sx);
37218fc08087STijl Coosemans 	TAILQ_FOREACH(he, &linux_ioctl_handlers, list) {
372243bef515SMarcel Moolenaar 		if (he->func == h->func) {
37238fc08087STijl Coosemans 			TAILQ_REMOVE(&linux_ioctl_handlers, he, list);
3724ad6d226dSJohn Baldwin 			sx_xunlock(&linux_ioctl_sx);
37251ede983cSDag-Erling Smørgrav 			free(he, M_LINUX);
372643bef515SMarcel Moolenaar 			return (0);
372743bef515SMarcel Moolenaar 		}
372843bef515SMarcel Moolenaar 	}
3729ad6d226dSJohn Baldwin 	sx_xunlock(&linux_ioctl_sx);
373043bef515SMarcel Moolenaar 
373143bef515SMarcel Moolenaar 	return (EINVAL);
373243bef515SMarcel Moolenaar }
37338fc08087STijl Coosemans 
37348fc08087STijl Coosemans #ifdef COMPAT_LINUX32
37358fc08087STijl Coosemans int
linux32_ioctl_register_handler(struct linux_ioctl_handler * h)37368fc08087STijl Coosemans linux32_ioctl_register_handler(struct linux_ioctl_handler *h)
37378fc08087STijl Coosemans {
37388fc08087STijl Coosemans 	struct linux_ioctl_handler_element *he, *cur;
37398fc08087STijl Coosemans 
37408fc08087STijl Coosemans 	if (h == NULL || h->func == NULL)
37418fc08087STijl Coosemans 		return (EINVAL);
37428fc08087STijl Coosemans 
37438fc08087STijl Coosemans 	/*
37448fc08087STijl Coosemans 	 * Reuse the element if the handler is already on the list, otherwise
37458fc08087STijl Coosemans 	 * create a new element.
37468fc08087STijl Coosemans 	 */
37478fc08087STijl Coosemans 	sx_xlock(&linux_ioctl_sx);
37488fc08087STijl Coosemans 	TAILQ_FOREACH(he, &linux32_ioctl_handlers, list) {
37498fc08087STijl Coosemans 		if (he->func == h->func)
37508fc08087STijl Coosemans 			break;
37518fc08087STijl Coosemans 	}
37528fc08087STijl Coosemans 	if (he == NULL) {
37538fc08087STijl Coosemans 		he = malloc(sizeof(*he), M_LINUX, M_WAITOK);
37548fc08087STijl Coosemans 		he->func = h->func;
37558fc08087STijl Coosemans 	} else
37568fc08087STijl Coosemans 		TAILQ_REMOVE(&linux32_ioctl_handlers, he, list);
37578fc08087STijl Coosemans 
37588fc08087STijl Coosemans 	/* Initialize range information. */
37598fc08087STijl Coosemans 	he->low = h->low;
37608fc08087STijl Coosemans 	he->high = h->high;
37618fc08087STijl Coosemans 	he->span = h->high - h->low + 1;
37628fc08087STijl Coosemans 
37638fc08087STijl Coosemans 	/* Add the element to the list, sorted on span. */
37648fc08087STijl Coosemans 	TAILQ_FOREACH(cur, &linux32_ioctl_handlers, list) {
37658fc08087STijl Coosemans 		if (cur->span > he->span) {
37668fc08087STijl Coosemans 			TAILQ_INSERT_BEFORE(cur, he, list);
37678fc08087STijl Coosemans 			sx_xunlock(&linux_ioctl_sx);
37688fc08087STijl Coosemans 			return (0);
37698fc08087STijl Coosemans 		}
37708fc08087STijl Coosemans 	}
37718fc08087STijl Coosemans 	TAILQ_INSERT_TAIL(&linux32_ioctl_handlers, he, list);
37728fc08087STijl Coosemans 	sx_xunlock(&linux_ioctl_sx);
37738fc08087STijl Coosemans 
37748fc08087STijl Coosemans 	return (0);
37758fc08087STijl Coosemans }
37768fc08087STijl Coosemans 
37778fc08087STijl Coosemans int
linux32_ioctl_unregister_handler(struct linux_ioctl_handler * h)37788fc08087STijl Coosemans linux32_ioctl_unregister_handler(struct linux_ioctl_handler *h)
37798fc08087STijl Coosemans {
37808fc08087STijl Coosemans 	struct linux_ioctl_handler_element *he;
37818fc08087STijl Coosemans 
37828fc08087STijl Coosemans 	if (h == NULL || h->func == NULL)
37838fc08087STijl Coosemans 		return (EINVAL);
37848fc08087STijl Coosemans 
37858fc08087STijl Coosemans 	sx_xlock(&linux_ioctl_sx);
37868fc08087STijl Coosemans 	TAILQ_FOREACH(he, &linux32_ioctl_handlers, list) {
37878fc08087STijl Coosemans 		if (he->func == h->func) {
37888fc08087STijl Coosemans 			TAILQ_REMOVE(&linux32_ioctl_handlers, he, list);
37898fc08087STijl Coosemans 			sx_xunlock(&linux_ioctl_sx);
37908fc08087STijl Coosemans 			free(he, M_LINUX);
37918fc08087STijl Coosemans 			return (0);
37928fc08087STijl Coosemans 		}
37938fc08087STijl Coosemans 	}
37948fc08087STijl Coosemans 	sx_xunlock(&linux_ioctl_sx);
37958fc08087STijl Coosemans 
37968fc08087STijl Coosemans 	return (EINVAL);
37978fc08087STijl Coosemans }
37988fc08087STijl Coosemans #endif
3799