From 3930af25b2bdaaf4da95f17175724210a51fa026 Mon Sep 17 00:00:00 2001 From: Joerg Sonnenberger Date: Sun, 15 Aug 2004 14:15:00 +0000 Subject: [PATCH] IOCTL mapping layer Part II/II Convert the Linux IOCTL emulation to use the new mapping layer. This also changes the drm(4) and aac(4) emulation of the respective APIs. Submitted-by: Simon 'corecode' Schubert --- sys/dev/drm/drm_drv.h | 45 +- sys/dev/drm/drm_os_freebsd.h | 6 +- sys/dev/raid/aac/aac.c | 33 +- sys/dev/raid/aac/aac_linux.c | 69 +- sys/emulation/linux/i386/linux.h | 14 +- sys/emulation/linux/i386/linux_sysvec.c | 9 +- sys/emulation/linux/linux_ioctl.c | 1631 ++++++++--------------- sys/emulation/linux/linux_ioctl.h | 12 +- 8 files changed, 615 insertions(+), 1204 deletions(-) diff --git a/sys/dev/drm/drm_drv.h b/sys/dev/drm/drm_drv.h index 428afc8ecb..995023116f 100644 --- a/sys/dev/drm/drm_drv.h +++ b/sys/dev/drm/drm_drv.h @@ -29,7 +29,7 @@ * Gareth Hughes * * $FreeBSD: src/sys/dev/drm/drm_drv.h,v 1.13.2.1 2003/04/26 07:05:28 anholt Exp $ - * $DragonFly: src/sys/dev/drm/Attic/drm_drv.h,v 1.8 2004/05/19 22:52:42 dillon Exp $ + * $DragonFly: src/sys/dev/drm/Attic/drm_drv.h,v 1.9 2004/08/15 14:15:00 joerg Exp $ */ /* @@ -1134,40 +1134,39 @@ int DRM(unlock)( DRM_IOCTL_ARGS ) #if DRM_LINUX +#include +#include #include +#include MODULE_DEPEND(DRIVER_NAME, linux, 1, 1, 1); #define LINUX_IOCTL_DRM_MIN 0x6400 #define LINUX_IOCTL_DRM_MAX 0x64ff -static linux_ioctl_function_t DRM(linux_ioctl); -static struct linux_ioctl_handler DRM(handler) = {DRM(linux_ioctl), - LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX}; +static ioctl_map_func DRM(ioctl_dirmap); +static struct ioctl_map_cmd DRM(ioctl_cmds)[] = { + /* XXX: we should have a BSD #define for the range */ + MAPPED_IOCTL_MAPRANGE(LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX, LINUX_IOCTL_DRM_MIN, DRM(ioctl_dirmap)), + MAPPED_IOCTL_MAPF(0, 0, NULL) +}; + +static struct ioctl_map_handler DRM(ioctl_handler) = { + &linux_ioctl_map, + __XSTRING(DRM(linux)), + DRM(ioctl_cmds) +}; SYSINIT(DRM(register), SI_SUB_KLD, SI_ORDER_MIDDLE, - linux_ioctl_register_handler, &DRM(handler)); + mapped_ioctl_register_handler, &DRM(ioctl_handler)); SYSUNINIT(DRM(unregister), SI_SUB_KLD, SI_ORDER_MIDDLE, - linux_ioctl_unregister_handler, &DRM(handler)); - -/* The bits for in/out are switched on Linux */ -#define LINUX_IOC_IN IOC_OUT -#define LINUX_IOC_OUT IOC_IN + mapped_ioctl_unregister_handler, &DRM(ioctl_handler)); static int -DRM(linux_ioctl)(DRM_STRUCTPROC *p, struct linux_ioctl_args* args) +DRM(ioctl_dirmap)(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) { - int error; - int cmd = args->cmd; - - args->cmd &= ~(LINUX_IOC_IN | LINUX_IOC_OUT); - if (cmd & LINUX_IOC_IN) - args->cmd |= IOC_IN; - if (cmd & LINUX_IOC_OUT) - args->cmd |= IOC_OUT; - - error = ioctl(p, (struct ioctl_args *)args); - - return error; + return(linux_ioctl_dirmap(fp, cmd + (ocmd - LINUX_IOCTL_DRM_MIN), + ocmd, data, td)); } + #endif /* DRM_LINUX */ diff --git a/sys/dev/drm/drm_os_freebsd.h b/sys/dev/drm/drm_os_freebsd.h index c6e252438f..db76efd7da 100644 --- a/sys/dev/drm/drm_os_freebsd.h +++ b/sys/dev/drm/drm_os_freebsd.h @@ -1,6 +1,6 @@ /* * $FreeBSD: src/sys/dev/drm/drm_os_freebsd.h,v 1.10.2.1 2003/04/26 07:05:28 anholt Exp $ - * $DragonFly: src/sys/dev/drm/Attic/drm_os_freebsd.h,v 1.10 2004/08/10 16:03:12 eirikn Exp $ + * $DragonFly: src/sys/dev/drm/Attic/drm_os_freebsd.h,v 1.11 2004/08/15 14:15:00 joerg Exp $ */ #include #include @@ -71,8 +71,8 @@ #if DRM_LINUX #include #include -#include -#include +#include +#include #endif #define DRM_TIME_SLICE (hz/20) /* Time slice for GLXContexts */ diff --git a/sys/dev/raid/aac/aac.c b/sys/dev/raid/aac/aac.c index 7107b9fa9f..9f946da271 100644 --- a/sys/dev/raid/aac/aac.c +++ b/sys/dev/raid/aac/aac.c @@ -27,7 +27,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/dev/aac/aac.c,v 1.9.2.14 2003/04/08 13:22:08 scottl Exp $ - * $DragonFly: src/sys/dev/raid/aac/aac.c,v 1.14 2004/07/26 16:03:23 joerg Exp $ + * $DragonFly: src/sys/dev/raid/aac/aac.c,v 1.15 2004/08/15 14:15:00 joerg Exp $ */ /* @@ -2359,18 +2359,15 @@ aac_close(dev_t dev, int flags, int fmt, d_thread_t *td) static int aac_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, d_thread_t *td) { - union aac_statrequest *as; - struct aac_softc *sc; + struct aac_softc *sc = dev->si_drv1; int error = 0; int i; debug_called(2); - as = (union aac_statrequest *)arg; - sc = dev->si_drv1; + if (cmd == AACIO_STATS) { + union aac_statrequest *as = (union aac_statrequest *)arg; - switch (cmd) { - case AACIO_STATS: switch (as->as_item) { case AACQ_FREE: case AACQ_BIO: @@ -2384,22 +2381,22 @@ aac_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, d_thread_t *td) error = ENOENT; break; } - break; - + return(error); + } + + arg = *(caddr_t *)arg; + + switch (cmd) { + /* AACIO_STATS already handled above */ case FSACTL_SENDFIB: - arg = *(caddr_t*)arg; - case FSACTL_LNX_SENDFIB: debug(1, "FSACTL_SENDFIB"); error = aac_ioctl_sendfib(sc, arg); break; case FSACTL_AIF_THREAD: - case FSACTL_LNX_AIF_THREAD: debug(1, "FSACTL_AIF_THREAD"); error = EINVAL; break; case FSACTL_OPEN_GET_ADAPTER_FIB: - arg = *(caddr_t*)arg; - case FSACTL_LNX_OPEN_GET_ADAPTER_FIB: debug(1, "FSACTL_OPEN_GET_ADAPTER_FIB"); /* * Pass the caller out an AdapterFibContext. @@ -2417,30 +2414,22 @@ aac_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, d_thread_t *td) error = copyout(&i, arg, sizeof(i)); break; case FSACTL_GET_NEXT_ADAPTER_FIB: - arg = *(caddr_t*)arg; - case FSACTL_LNX_GET_NEXT_ADAPTER_FIB: debug(1, "FSACTL_GET_NEXT_ADAPTER_FIB"); error = aac_getnext_aif(sc, arg); break; case FSACTL_CLOSE_GET_ADAPTER_FIB: - case FSACTL_LNX_CLOSE_GET_ADAPTER_FIB: debug(1, "FSACTL_CLOSE_GET_ADAPTER_FIB"); /* don't do anything here */ break; case FSACTL_MINIPORT_REV_CHECK: - arg = *(caddr_t*)arg; - case FSACTL_LNX_MINIPORT_REV_CHECK: debug(1, "FSACTL_MINIPORT_REV_CHECK"); error = aac_rev_check(sc, arg); break; case FSACTL_QUERY_DISK: - arg = *(caddr_t*)arg; - case FSACTL_LNX_QUERY_DISK: debug(1, "FSACTL_QUERY_DISK"); error = aac_query_disk(sc, arg); break; case FSACTL_DELETE_DISK: - case FSACTL_LNX_DELETE_DISK: /* * We don't trust the underland to tell us when to delete a * container, rather we rely on an AIF coming from the diff --git a/sys/dev/raid/aac/aac_linux.c b/sys/dev/raid/aac/aac_linux.c index 04b06ef65b..ea4a3e86b9 100644 --- a/sys/dev/raid/aac/aac_linux.c +++ b/sys/dev/raid/aac/aac_linux.c @@ -27,7 +27,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/dev/aac/aac_linux.c,v 1.1.4.1 2003/03/28 19:50:17 scottl Exp $ - * $DragonFly: src/sys/dev/raid/aac/aac_linux.c,v 1.4 2003/08/07 21:17:07 dillon Exp $ + * $DragonFly: src/sys/dev/raid/aac/aac_linux.c,v 1.5 2004/08/15 14:15:00 joerg Exp $ */ #include @@ -35,25 +35,55 @@ #include #include #include +#include +#include #include #include #include #include #include -/* There are multiple ioctl number ranges that need to be handled */ -#define AAC_LINUX_IOCTL_MIN 0x0000 -#define AAC_LINUX_IOCTL_MAX 0x21ff +#include "aacreg.h" /* needed by aac_ioctl.h */ +#include "aac_ioctl.h" -static linux_ioctl_function_t aac_linux_ioctl; -static struct linux_ioctl_handler aac_linux_handler = {aac_linux_ioctl, - AAC_LINUX_IOCTL_MIN, - AAC_LINUX_IOCTL_MAX}; +/* Define ioctl mappings */ +static struct ioctl_map_range aac_linux_ioctl_cmds[] = { + MAPPED_IOCTL_MAP(FSACTL_LNX_SENDFIB, FSACTL_SENDFIB), + MAPPED_IOCTL_MAP(FSACTL_LNX_GET_COMM_PERF_DATA, FSACTL_GET_COMM_PERF_DATA), + MAPPED_IOCTL_MAP(FSACTL_LNX_OPENCLS_COMM_PERF_DATA, FSACTL_OPENCLS_COMM_PERF_DATA), + MAPPED_IOCTL_MAP(FSACTL_LNX_OPEN_GET_ADAPTER_FIB, FSACTL_OPEN_GET_ADAPTER_FIB), + MAPPED_IOCTL_MAP(FSACTL_LNX_GET_NEXT_ADAPTER_FIB, FSACTL_GET_NEXT_ADAPTER_FIB), + MAPPED_IOCTL_MAP(FSACTL_LNX_CLOSE_GET_ADAPTER_FIB, FSACTL_CLOSE_GET_ADAPTER_FIB), + MAPPED_IOCTL_MAP(FSACTL_LNX_CLOSE_ADAPTER_CONFIG, FSACTL_CLOSE_ADAPTER_CONFIG), + MAPPED_IOCTL_MAP(FSACTL_LNX_OPEN_ADAPTER_CONFIG, FSACTL_OPEN_ADAPTER_CONFIG), + MAPPED_IOCTL_MAP(FSACTL_LNX_MINIPORT_REV_CHECK, FSACTL_MINIPORT_REV_CHECK), + MAPPED_IOCTL_MAP(FSACTL_LNX_QUERY_ADAPTER_CONFIG, FSACTL_QUERY_ADAPTER_CONFIG), + MAPPED_IOCTL_MAP(FSACTL_LNX_GET_PCI_INFO, FSACTL_GET_PCI_INFO), + MAPPED_IOCTL_MAP(FSACTL_LNX_FORCE_DELETE_DISK, FSACTL_FORCE_DELETE_DISK), + MAPPED_IOCTL_MAP(FSACTL_LNX_AIF_THREAD, FSACTL_AIF_THREAD), + MAPPED_IOCTL_MAP(FSACTL_LNX_NULL_IO_TEST, FSACTL_NULL_IO_TEST), + MAPPED_IOCTL_MAP(FSACTL_LNX_SIM_IO_TEST, FSACTL_SIM_IO_TEST), + MAPPED_IOCTL_MAP(FSACTL_LNX_DOWNLOAD, FSACTL_DOWNLOAD), + MAPPED_IOCTL_MAP(FSACTL_LNX_GET_VAR, FSACTL_GET_VAR), + MAPPED_IOCTL_MAP(FSACTL_LNX_SET_VAR, FSACTL_SET_VAR), + MAPPED_IOCTL_MAP(FSACTL_LNX_GET_FIBTIMES, FSACTL_GET_FIBTIMES), + MAPPED_IOCTL_MAP(FSACTL_LNX_ZERO_FIBTIMES, FSACTL_ZERO_FIBTIMES), + MAPPED_IOCTL_MAP(FSACTL_LNX_DELETE_DISK, FSACTL_DELETE_DISK), + MAPPED_IOCTL_MAP(FSACTL_LNX_QUERY_DISK, FSACTL_QUERY_DISK), + MAPPED_IOCTL_MAP(FSACTL_LNX_PROBE_CONTAINERS, FSACTL_PROBE_CONTAINERS), + MAPPED_IOCTL_MAPF(0 ,0, NULL) +}; + +static struct ioctl_map_handler aac_linux_ioctl_handler = { + &linux_ioctl_map, + "aac_linux", + aac_linux_ioctl_cmds +}; SYSINIT (aac_register, SI_SUB_KLD, SI_ORDER_MIDDLE, - linux_ioctl_register_handler, &aac_linux_handler); + mapped_ioctl_register_handler, &aac_linux_ioctl_handler); SYSUNINIT(aac_unregister, SI_SUB_KLD, SI_ORDER_MIDDLE, - linux_ioctl_unregister_handler, &aac_linux_handler); + mapped_ioctl_unregister_handler, &aac_linux_ioctl_handler); static int aac_linux_modevent(module_t mod, int type, void *data) @@ -64,22 +94,3 @@ aac_linux_modevent(module_t mod, int type, void *data) DEV_MODULE(aac_linux, aac_linux_modevent, NULL); MODULE_DEPEND(aac, linux, 1, 1, 1); - -static int -aac_linux_ioctl(struct thread *td, struct linux_ioctl_args *args) -{ - struct proc *p = td->td_proc; - struct file *fp; - u_long cmd; - - KKASSERT(p); - - fp = p->p_fd->fd_ofiles[args->fd]; - cmd = args->cmd; - - /* - * Pass the ioctl off to our standard handler. - */ - return(fo_ioctl(fp, cmd, (caddr_t)args->arg, td)); -} - diff --git a/sys/emulation/linux/i386/linux.h b/sys/emulation/linux/i386/linux.h index 6a89ce5015..20d4a928d7 100644 --- a/sys/emulation/linux/i386/linux.h +++ b/sys/emulation/linux/i386/linux.h @@ -26,7 +26,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/i386/linux/linux.h,v 1.41.2.4 2003/01/06 09:19:43 fjoe Exp $ - * $DragonFly: src/sys/emulation/linux/i386/linux.h,v 1.7 2004/01/08 18:39:18 asmodai Exp $ + * $DragonFly: src/sys/emulation/linux/i386/linux.h,v 1.8 2004/08/15 14:15:00 joerg Exp $ */ #ifndef _I386_LINUX_LINUX_H_ @@ -453,18 +453,8 @@ extern struct sysentvec elf_linux_sysvec; /* * Pluggable ioctl handlers */ -struct linux_ioctl_args; -struct thread; -typedef int linux_ioctl_function_t(struct thread *, struct linux_ioctl_args *); - -struct linux_ioctl_handler { - linux_ioctl_function_t *func; - int low, high; -}; - -int linux_ioctl_register_handler(struct linux_ioctl_handler *h); -int linux_ioctl_unregister_handler(struct linux_ioctl_handler *h); +extern struct ioctl_map linux_ioctl_map; /* * open/fcntl flags diff --git a/sys/emulation/linux/i386/linux_sysvec.c b/sys/emulation/linux/i386/linux_sysvec.c index 9f447aaa18..33300dfa34 100644 --- a/sys/emulation/linux/i386/linux_sysvec.c +++ b/sys/emulation/linux/i386/linux_sysvec.c @@ -26,7 +26,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/i386/linux/linux_sysvec.c,v 1.55.2.9 2002/01/12 11:03:30 bde Exp $ - * $DragonFly: src/sys/emulation/linux/i386/linux_sysvec.c,v 1.15 2003/11/15 03:52:33 daver Exp $ + * $DragonFly: src/sys/emulation/linux/i386/linux_sysvec.c,v 1.16 2004/08/15 14:15:00 joerg Exp $ */ /* XXX we use functions that might not exist. */ @@ -85,8 +85,6 @@ extern int linux_szsigcode; extern struct sysent linux_sysent[LINUX_SYS_MAXSYSCALL]; -SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler); - static int linux_fixup (register_t **stack_base, struct image_params *iparams); static int elf_linux_fixup (register_t **stack_base, @@ -822,7 +820,6 @@ linux_elf_modevent(module_t mod, int type, void *data) { Elf32_Brandinfo **brandinfo; int error; - struct linux_ioctl_handler **lihp; error = 0; @@ -833,8 +830,6 @@ linux_elf_modevent(module_t mod, int type, void *data) if (elf_insert_brand_entry(*brandinfo) < 0) error = EINVAL; if (error == 0) { - SET_FOREACH(lihp, linux_ioctl_handler_set) - linux_ioctl_register_handler(*lihp); if (bootverbose) printf("Linux ELF exec handler installed\n"); } else @@ -852,8 +847,6 @@ linux_elf_modevent(module_t mod, int type, void *data) error = EINVAL; } if (error == 0) { - SET_FOREACH(lihp, linux_ioctl_handler_set) - linux_ioctl_unregister_handler(*lihp); if (bootverbose) printf("Linux ELF exec handler removed\n"); } else diff --git a/sys/emulation/linux/linux_ioctl.c b/sys/emulation/linux/linux_ioctl.c index e73ce301df..b8f6947131 100644 --- a/sys/emulation/linux/linux_ioctl.c +++ b/sys/emulation/linux/linux_ioctl.c @@ -1,5 +1,6 @@ /* * Copyright (c) 1994-1995 Søren Schmidt + * Copyright (c) 2004 Simon 'corecode' Schubert * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,7 +27,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/compat/linux/linux_ioctl.c,v 1.55.2.11 2003/05/01 20:16:09 anholt Exp $ - * $DragonFly: src/sys/emulation/linux/linux_ioctl.c,v 1.14 2004/07/11 04:47:07 drhodus Exp $ + * $DragonFly: src/sys/emulation/linux/linux_ioctl.c,v 1.15 2004/08/15 14:15:00 joerg Exp $ */ #include @@ -40,9 +41,12 @@ #include #include #include +#include #include +#include #include #include +#include #include #include #include @@ -61,75 +65,21 @@ #include "linux_mib.h" #include "linux_util.h" -static linux_ioctl_function_t linux_ioctl_cdrom; -static linux_ioctl_function_t linux_ioctl_console; -static linux_ioctl_function_t linux_ioctl_disk; -static linux_ioctl_function_t linux_ioctl_socket; -static linux_ioctl_function_t linux_ioctl_sound; -static linux_ioctl_function_t linux_ioctl_termio; -static linux_ioctl_function_t linux_ioctl_private; -static linux_ioctl_function_t linux_ioctl_drm; -static linux_ioctl_function_t linux_ioctl_special; - -static struct linux_ioctl_handler cdrom_handler = -{ linux_ioctl_cdrom, LINUX_IOCTL_CDROM_MIN, LINUX_IOCTL_CDROM_MAX }; -static struct linux_ioctl_handler console_handler = -{ linux_ioctl_console, LINUX_IOCTL_CONSOLE_MIN, LINUX_IOCTL_CONSOLE_MAX }; -static struct linux_ioctl_handler disk_handler = -{ linux_ioctl_disk, LINUX_IOCTL_DISK_MIN, LINUX_IOCTL_DISK_MAX }; -static struct linux_ioctl_handler socket_handler = -{ linux_ioctl_socket, LINUX_IOCTL_SOCKET_MIN, LINUX_IOCTL_SOCKET_MAX }; -static struct linux_ioctl_handler sound_handler = -{ linux_ioctl_sound, LINUX_IOCTL_SOUND_MIN, LINUX_IOCTL_SOUND_MAX }; -static struct linux_ioctl_handler termio_handler = -{ linux_ioctl_termio, LINUX_IOCTL_TERMIO_MIN, LINUX_IOCTL_TERMIO_MAX }; -static struct linux_ioctl_handler private_handler = -{ linux_ioctl_private, LINUX_IOCTL_PRIVATE_MIN, LINUX_IOCTL_PRIVATE_MAX }; -static struct linux_ioctl_handler drm_handler = -{ linux_ioctl_drm, LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX }; - -DATA_SET(linux_ioctl_handler_set, cdrom_handler); -DATA_SET(linux_ioctl_handler_set, console_handler); -DATA_SET(linux_ioctl_handler_set, disk_handler); -DATA_SET(linux_ioctl_handler_set, socket_handler); -DATA_SET(linux_ioctl_handler_set, sound_handler); -DATA_SET(linux_ioctl_handler_set, termio_handler); -DATA_SET(linux_ioctl_handler_set, private_handler); -DATA_SET(linux_ioctl_handler_set, drm_handler); - -struct handler_element -{ - TAILQ_ENTRY(handler_element) list; - int (*func)(struct thread *, struct linux_ioctl_args *); - int low, high, span; -}; - -static TAILQ_HEAD(, handler_element) handlers = - TAILQ_HEAD_INITIALIZER(handlers); static int -linux_ioctl_disk(struct thread *td, struct linux_ioctl_args *args) +linux_ioctl_BLKGETSIZE(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) { - struct proc *p = td->td_proc; - struct file *fp; int error; struct disklabel dl; - KKASSERT(p); - fp = p->p_fd->fd_ofiles[args->fd]; - - switch (args->cmd & 0xffff) { - case LINUX_BLKGETSIZE: - error = fo_ioctl(fp, DIOCGDINFO, (caddr_t)&dl, p->p_thread); - if (error) - return (error); - return (copyout(&(dl.d_secperunit), (caddr_t)args->arg, - sizeof(dl.d_secperunit))); - break; - } - return (ENOIOCTL); + error = fo_ioctl(fp, DIOCGDINFO, (caddr_t)&dl, td); + if (error) + return (error); + bcopy(&(dl.d_secperunit), data, sizeof(dl.d_secperunit)); + return (0); } + /* * termio related ioctls */ @@ -554,279 +504,239 @@ linux_to_bsd_termio(struct linux_termio *lio, struct termios *bios) } static int -linux_ioctl_termio(struct thread *td, struct linux_ioctl_args *args) +linux_ioctl_TCGETS(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) { struct termios bios; struct linux_termios lios; - struct linux_termio lio; - struct file *fp; int error; - KKASSERT(td->td_proc); - fp = td->td_proc->p_fd->fd_ofiles[args->fd]; - - switch (args->cmd & 0xffff) { - case LINUX_TCGETS: - error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td); - if (error) - return (error); - bsd_to_linux_termios(&bios, &lios); - return copyout(&lios, (caddr_t)args->arg, sizeof(lios)); - - case LINUX_TCSETS: - error = copyin((caddr_t)args->arg, &lios, sizeof(lios)); - if (error) - return (error); - linux_to_bsd_termios(&lios, &bios); - return (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td)); - - case LINUX_TCSETSW: - error = copyin((caddr_t)args->arg, &lios, sizeof(lios)); - if (error) - return (error); - linux_to_bsd_termios(&lios, &bios); - return (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td)); - - case LINUX_TCSETSF: - error = copyin((caddr_t)args->arg, &lios, sizeof(lios)); - if (error) - return (error); - linux_to_bsd_termios(&lios, &bios); - return (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td)); - - case LINUX_TCGETA: - error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td); - if (error) - return (error); - bsd_to_linux_termio(&bios, &lio); - return (copyout(&lio, (caddr_t)args->arg, sizeof(lio))); - - case LINUX_TCSETA: - error = copyin((caddr_t)args->arg, &lio, sizeof(lio)); - if (error) - return (error); - linux_to_bsd_termio(&lio, &bios); - return (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td)); - - case LINUX_TCSETAW: - error = copyin((caddr_t)args->arg, &lio, sizeof(lio)); - if (error) - return (error); - linux_to_bsd_termio(&lio, &bios); - return (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td)); - - case LINUX_TCSETAF: - error = copyin((caddr_t)args->arg, &lio, sizeof(lio)); - if (error) - return (error); - linux_to_bsd_termio(&lio, &bios); - return (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td)); - - /* LINUX_TCSBRK */ - - case LINUX_TCXONC: { - switch (args->arg) { - case LINUX_TCOOFF: - args->cmd = TIOCSTOP; - break; - case LINUX_TCOON: - args->cmd = TIOCSTART; - break; - case LINUX_TCIOFF: - case LINUX_TCION: { - int c; - struct write_args wr; - error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td); - if (error) - return (error); - c = (args->arg == LINUX_TCIOFF) ? VSTOP : VSTART; - c = bios.c_cc[c]; - if (c != _POSIX_VDISABLE) { - wr.fd = args->fd; - wr.buf = &c; - wr.nbyte = sizeof(c); - return (write(&wr)); - } else - return (0); - } - default: - return (EINVAL); - } - args->arg = 0; - return (ioctl((struct ioctl_args *)args)); - } - - case LINUX_TCFLSH: { - args->cmd = TIOCFLUSH; - switch (args->arg) { - case LINUX_TCIFLUSH: - args->arg = FREAD; - break; - case LINUX_TCOFLUSH: - args->arg = FWRITE; - break; - case LINUX_TCIOFLUSH: - args->arg = FREAD | FWRITE; - break; - default: - return (EINVAL); - } - return (ioctl((struct ioctl_args *)args)); - } - - case LINUX_TIOCEXCL: - args->cmd = TIOCEXCL; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_TIOCNXCL: - args->cmd = TIOCNXCL; - return (ioctl((struct ioctl_args *)args)); - - /* LINUX_TIOCSCTTY */ + error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td); + if (error) + return (error); + bsd_to_linux_termios(&bios, &lios); + bcopy(&lios, data, sizeof(lios)); + return (0); +} - case LINUX_TIOCGPGRP: - args->cmd = TIOCGPGRP; - return (ioctl((struct ioctl_args *)args)); +static int +linux_ioctl_TCSETS(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) +{ + struct termios bios; + struct linux_termios lios; - case LINUX_TIOCSPGRP: - args->cmd = TIOCSPGRP; - return (ioctl((struct ioctl_args *)args)); + bcopy(data, &lios, sizeof(lios)); + linux_to_bsd_termios(&lios, &bios); + return (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td)); +} - /* LINUX_TIOCOUTQ */ - /* LINUX_TIOCSTI */ +static int +linux_ioctl_TCSETSW(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) +{ + struct termios bios; + struct linux_termios lios; - case LINUX_TIOCGWINSZ: - args->cmd = TIOCGWINSZ; - return (ioctl((struct ioctl_args *)args)); + bcopy(data, &lios, sizeof(lios)); + linux_to_bsd_termios(&lios, &bios); + return (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td)); +} - case LINUX_TIOCSWINSZ: - args->cmd = TIOCSWINSZ; - return (ioctl((struct ioctl_args *)args)); +static int +linux_ioctl_TCSETSF(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) +{ + struct termios bios; + struct linux_termios lios; - case LINUX_TIOCMGET: - args->cmd = TIOCMGET; - return (ioctl((struct ioctl_args *)args)); + bcopy(data, &lios, sizeof(lios)); + linux_to_bsd_termios(&lios, &bios); + return (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td)); +} - case LINUX_TIOCMBIS: - args->cmd = TIOCMBIS; - return (ioctl((struct ioctl_args *)args)); +static int +linux_ioctl_TCGETA(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) +{ + struct termios bios; + struct linux_termio lio; + int error; - case LINUX_TIOCMBIC: - args->cmd = TIOCMBIC; - return (ioctl((struct ioctl_args *)args)); + error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td); + if (error) + return (error); + bsd_to_linux_termio(&bios, &lio); + bcopy(&lio, data, sizeof(lio)); + return (0); +} - case LINUX_TIOCMSET: - args->cmd = TIOCMSET; - return (ioctl((struct ioctl_args *)args)); +static int +linux_ioctl_TCSETA(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) +{ + struct termios bios; + struct linux_termio lio; - /* TIOCGSOFTCAR */ - /* TIOCSSOFTCAR */ + bcopy(data, &lio, sizeof(lio)); + linux_to_bsd_termio(&lio, &bios); + return (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td)); +} - case LINUX_FIONREAD: /* LINUX_TIOCINQ */ - args->cmd = FIONREAD; - return (ioctl((struct ioctl_args *)args)); +static int +linux_ioctl_TCSETAW(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) +{ + struct termios bios; + struct linux_termio lio; - /* LINUX_TIOCLINUX */ + bcopy(data, &lio, sizeof(lio)); + linux_to_bsd_termio(&lio, &bios); + return (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td)); +} - case LINUX_TIOCCONS: - args->cmd = TIOCCONS; - return (ioctl((struct ioctl_args *)args)); +static int +linux_ioctl_TCSETAF(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) +{ + struct termios bios; + struct linux_termio lio; - case LINUX_TIOCGSERIAL: { - struct linux_serial_struct lss; - lss.type = LINUX_PORT_16550A; - lss.flags = 0; - lss.close_delay = 0; - return copyout(&lss, (caddr_t)args->arg, sizeof(lss)); - } + bcopy(data, &lio, sizeof(lio)); + linux_to_bsd_termio(&lio, &bios); + return (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td)); +} - case LINUX_TIOCSSERIAL: { - struct linux_serial_struct lss; - error = copyin((caddr_t)args->arg, &lss, sizeof(lss)); +static int +linux_ioctl_TCXONC(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) +{ + switch ((u_long)data) { + case LINUX_TCOOFF: + cmd = TIOCSTOP; + break; + case LINUX_TCOON: + cmd = TIOCSTART; + break; + case LINUX_TCIOFF: + case LINUX_TCION: { + struct termios bios; + int error, c; + + error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td); if (error) return (error); - /* XXX - It really helps to have an implementation that - * does nothing. NOT! - */ + c = ((u_long)data == LINUX_TCIOFF) ? VSTOP : VSTART; + c = bios.c_cc[c]; + if (c != _POSIX_VDISABLE) { + struct uio auio; + struct iovec aiov; + + aiov.iov_base = (char *)&c; + aiov.iov_len = sizeof(*bios.c_cc); + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + auio.uio_offset = -1; + auio.uio_resid = sizeof(*bios.c_cc); + auio.uio_rw = UIO_WRITE; + auio.uio_segflg = UIO_SYSSPACE; + auio.uio_td = td; + + return (fo_write(fp, &auio, fp->f_cred, 0, td)); + } + return (0); } - - /* LINUX_TIOCPKT */ - - case LINUX_FIONBIO: - args->cmd = FIONBIO; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_TIOCNOTTY: - args->cmd = TIOCNOTTY; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_TIOCSETD: { - int line; - switch (args->arg) { - case LINUX_N_TTY: - line = TTYDISC; - break; - case LINUX_N_SLIP: - line = SLIPDISC; - break; - case LINUX_N_PPP: - line = PPPDISC; - break; - default: - return (EINVAL); - } - return (fo_ioctl(fp, TIOCSETD, (caddr_t)&line, td)); + default: + return (EINVAL); } + return (fo_ioctl(fp, cmd, 0, td)); +} - case LINUX_TIOCGETD: { - int linux_line; - int bsd_line = TTYDISC; - error = fo_ioctl(fp, TIOCGETD, (caddr_t)&bsd_line, td); - if (error) - return (error); - switch (bsd_line) { - case TTYDISC: - linux_line = LINUX_N_TTY; - break; - case SLIPDISC: - linux_line = LINUX_N_SLIP; - break; - case PPPDISC: - linux_line = LINUX_N_PPP; - break; - default: - return (EINVAL); - } - return (copyout(&linux_line, (caddr_t)args->arg, sizeof(int))); +static int +linux_ioctl_TCFLSH(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) +{ + switch ((u_long)data) { + case LINUX_TCIFLUSH: + *(u_long *)data = FREAD; + break; + case LINUX_TCOFLUSH: + *(u_long *)data = FWRITE; + break; + case LINUX_TCIOFLUSH: + *(u_long *)data = FREAD | FWRITE; + break; + default: + return (EINVAL); } + return (fo_ioctl(fp, TIOCFLUSH, data, td)); +} - /* LINUX_TCSBRKP */ - /* LINUX_TIOCTTYGSTRUCT */ +static int +linux_ioctl_TIOCGSERIAL(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) +{ + struct linux_serial_struct lss; - case LINUX_FIONCLEX: - args->cmd = FIONCLEX; - return (ioctl((struct ioctl_args *)args)); + lss.type = LINUX_PORT_16550A; + lss.flags = 0; + lss.close_delay = 0; + bcopy(&lss, data, sizeof(lss)); + return (0); +} - case LINUX_FIOCLEX: - args->cmd = FIOCLEX; - return (ioctl((struct ioctl_args *)args)); +static int +linux_ioctl_TIOCSSERIAL(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) +{ +#if 0 + struct linux_serial_struct lss; - case LINUX_FIOASYNC: - args->cmd = FIOASYNC; - return (ioctl((struct ioctl_args *)args)); + bcopy(data, &lss, sizeof(lss)); + /* XXX - It really helps to have an implementation that + * does nothing. NOT! + */ +#endif + return (0); +} - /* LINUX_TIOCSERCONFIG */ - /* LINUX_TIOCSERGWILD */ - /* LINUX_TIOCSERSWILD */ - /* LINUX_TIOCGLCKTRMIOS */ - /* LINUX_TIOCSLCKTRMIOS */ +static int +linux_ioctl_TIOCSETD(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) +{ + int line; + switch ((u_long)data) { + case LINUX_N_TTY: + line = TTYDISC; + break; + case LINUX_N_SLIP: + line = SLIPDISC; + break; + case LINUX_N_PPP: + line = PPPDISC; + break; + default: + return (EINVAL); } - - return (ENOIOCTL); + return (fo_ioctl(fp, TIOCSETD, (caddr_t)&line, td)); } +static int +linux_ioctl_TIOCGETD(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) +{ + int linux_line, error; + int bsd_line = TTYDISC; + + error = fo_ioctl(fp, TIOCGETD, (caddr_t)&bsd_line, td); + if (error) + return (error); + switch (bsd_line) { + case TTYDISC: + linux_line = LINUX_N_TTY; + break; + case SLIPDISC: + linux_line = LINUX_N_SLIP; + break; + case PPPDISC: + linux_line = LINUX_N_PPP; + break; + default: + return (EINVAL); + } + bcopy(&linux_line, data, sizeof(int)); + return (0); +} + + /* * CDROM related ioctls */ @@ -905,371 +815,84 @@ set_linux_cdrom_addr(union linux_cdrom_addr *addr, int format, int lba) } static int -linux_ioctl_cdrom(struct thread *td, struct linux_ioctl_args *args) +linux_ioctl_CDROMREADTOCHDR(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) { - struct file *fp; + struct ioc_toc_header th; + struct linux_cdrom_tochdr lth; int error; - KKASSERT(td->td_proc); - fp = td->td_proc->p_fd->fd_ofiles[args->fd]; - - switch (args->cmd & 0xffff) { - case LINUX_CDROMPAUSE: - args->cmd = CDIOCPAUSE; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_CDROMRESUME: - args->cmd = CDIOCRESUME; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_CDROMPLAYMSF: - args->cmd = CDIOCPLAYMSF; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_CDROMPLAYTRKIND: - args->cmd = CDIOCPLAYTRACKS; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_CDROMREADTOCHDR: { - struct ioc_toc_header th; - struct linux_cdrom_tochdr lth; - error = fo_ioctl(fp, CDIOREADTOCHEADER, (caddr_t)&th, td); - if (!error) { - lth.cdth_trk0 = th.starting_track; - lth.cdth_trk1 = th.ending_track; - copyout(<h, (caddr_t)args->arg, sizeof(lth)); - } + error = fo_ioctl(fp, CDIOREADTOCHEADER, (caddr_t)&th, td); + if (error) return (error); - } - - case LINUX_CDROMREADTOCENTRY: { - struct linux_cdrom_tocentry lte; - struct ioc_read_toc_single_entry irtse; + lth.cdth_trk0 = th.starting_track; + lth.cdth_trk1 = th.ending_track; + bcopy(<h, data, sizeof(lth)); + return (0); +} - error = copyin((caddr_t)args->arg, <e, sizeof(lte)); - if (error) - return (error); - irtse.address_format = lte.cdte_format; - irtse.track = lte.cdte_track; - error = fo_ioctl(fp, CDIOREADTOCENTRY, (caddr_t)&irtse, td); - if (!error) { - lte.cdte_ctrl = irtse.entry.control; - lte.cdte_adr = irtse.entry.addr_type; - bsd_to_linux_msf_lba(irtse.address_format, - &irtse.entry.addr, <e.cdte_addr); - error = copyout(<e, (caddr_t)args->arg, sizeof(lte)); - } - return (error); - } +static int +linux_ioctl_CDROMREADTOCENTRY(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) +{ + struct linux_cdrom_tocentry *ltep = (struct linux_cdrom_tocentry *)data; + struct ioc_read_toc_single_entry irtse; + int error; - case LINUX_CDROMSTOP: - args->cmd = CDIOCSTOP; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_CDROMSTART: - args->cmd = CDIOCSTART; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_CDROMEJECT: - args->cmd = CDIOCEJECT; - return (ioctl((struct ioctl_args *)args)); - - /* LINUX_CDROMVOLCTRL */ - - case LINUX_CDROMSUBCHNL: { - struct linux_cdrom_subchnl sc; - struct ioc_read_subchannel bsdsc; - struct cd_sub_channel_info *bsdinfo; - caddr_t sg = stackgap_init(); - bsdinfo = (struct cd_sub_channel_info*)stackgap_alloc(&sg, - sizeof(struct cd_sub_channel_info)); - bsdsc.address_format = CD_LBA_FORMAT; - bsdsc.data_format = CD_CURRENT_POSITION; - bsdsc.track = 0; - bsdsc.data_len = sizeof(struct cd_sub_channel_info); - bsdsc.data = bsdinfo; - error = fo_ioctl(fp, CDIOCREADSUBCHANNEL, (caddr_t)&bsdsc, td); - if (error) - return (error); - error = copyin((caddr_t)args->arg, &sc, - sizeof(struct linux_cdrom_subchnl)); - if (error) - return (error); - sc.cdsc_audiostatus = bsdinfo->header.audio_status; - sc.cdsc_adr = bsdinfo->what.position.addr_type; - sc.cdsc_ctrl = bsdinfo->what.position.control; - sc.cdsc_trk = bsdinfo->what.position.track_number; - sc.cdsc_ind = bsdinfo->what.position.index_number; - set_linux_cdrom_addr(&sc.cdsc_absaddr, sc.cdsc_format, - bsdinfo->what.position.absaddr.lba); - set_linux_cdrom_addr(&sc.cdsc_reladdr, sc.cdsc_format, - bsdinfo->what.position.reladdr.lba); - error = copyout(&sc, (caddr_t)args->arg, - sizeof(struct linux_cdrom_subchnl)); + irtse.address_format = ltep->cdte_format; + irtse.track = ltep->cdte_track; + error = fo_ioctl(fp, CDIOREADTOCENTRY, (caddr_t)&irtse, td); + if (error) return (error); - } - - /* LINUX_CDROMREADMODE2 */ - /* LINUX_CDROMREADMODE1 */ - /* LINUX_CDROMREADAUDIO */ - /* LINUX_CDROMEJECT_SW */ - /* LINUX_CDROMMULTISESSION */ - /* LINUX_CDROM_GET_UPC */ - - case LINUX_CDROMRESET: - args->cmd = CDIOCRESET; - return (ioctl((struct ioctl_args *)args)); - - /* LINUX_CDROMVOLREAD */ - /* LINUX_CDROMREADRAW */ - /* LINUX_CDROMREADCOOKED */ - /* LINUX_CDROMSEEK */ - /* LINUX_CDROMPLAYBLK */ - /* LINUX_CDROMREADALL */ - /* LINUX_CDROMCLOSETRAY */ - /* LINUX_CDROMLOADFROMSLOT */ - } + ltep->cdte_ctrl = irtse.entry.control; + ltep->cdte_adr = irtse.entry.addr_type; + bsd_to_linux_msf_lba(irtse.address_format, &irtse.entry.addr, + <ep->cdte_addr); + return (0); +} - return (ENOIOCTL); +static int +linux_ioctl_CDROMSUBCHNL(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) +{ + struct linux_cdrom_subchnl *sc = (struct linux_cdrom_subchnl *)data; + struct ioc_read_subchannel bsdsc; + struct cd_sub_channel_info *bsdinfo; + int error; + caddr_t sg = stackgap_init(); + + bsdinfo = stackgap_alloc(&sg, sizeof(struct cd_sub_channel_info)); + bsdsc.address_format = CD_LBA_FORMAT; + bsdsc.data_format = CD_CURRENT_POSITION; + bsdsc.track = 0; + bsdsc.data_len = sizeof(struct cd_sub_channel_info); + bsdsc.data = bsdinfo; + error = fo_ioctl(fp, CDIOCREADSUBCHANNEL, (caddr_t)&bsdsc, td); + if (error) + return (error); + sc->cdsc_audiostatus = bsdinfo->header.audio_status; + sc->cdsc_adr = bsdinfo->what.position.addr_type; + sc->cdsc_ctrl = bsdinfo->what.position.control; + sc->cdsc_trk = bsdinfo->what.position.track_number; + sc->cdsc_ind = bsdinfo->what.position.index_number; + set_linux_cdrom_addr(&sc->cdsc_absaddr, sc->cdsc_format, bsdinfo->what.position.absaddr.lba); + set_linux_cdrom_addr(&sc->cdsc_reladdr, sc->cdsc_format, bsdinfo->what.position.reladdr.lba); + return (0); } + /* * Sound related ioctls */ -static u_int32_t dirbits[4] = { IOC_VOID, IOC_IN, IOC_OUT, IOC_INOUT }; - -#define SETDIR(c) (((c) & ~IOC_DIRMASK) | dirbits[args->cmd >> 30]) - static int -linux_ioctl_sound(struct thread *td, struct linux_ioctl_args *args) +linux_ioctl_OSS_GETVERSION(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) { + int version = linux_get_oss_version(td); - switch (args->cmd & 0xffff) { - - case LINUX_SOUND_MIXER_WRITE_VOLUME: - args->cmd = SETDIR(SOUND_MIXER_WRITE_VOLUME); - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SOUND_MIXER_WRITE_BASS: - args->cmd = SETDIR(SOUND_MIXER_WRITE_BASS); - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SOUND_MIXER_WRITE_TREBLE: - args->cmd = SETDIR(SOUND_MIXER_WRITE_TREBLE); - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SOUND_MIXER_WRITE_SYNTH: - args->cmd = SETDIR(SOUND_MIXER_WRITE_SYNTH); - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SOUND_MIXER_WRITE_PCM: - args->cmd = SETDIR(SOUND_MIXER_WRITE_PCM); - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SOUND_MIXER_WRITE_SPEAKER: - args->cmd = SETDIR(SOUND_MIXER_WRITE_SPEAKER); - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SOUND_MIXER_WRITE_LINE: - args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE); - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SOUND_MIXER_WRITE_MIC: - args->cmd = SETDIR(SOUND_MIXER_WRITE_MIC); - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SOUND_MIXER_WRITE_CD: - args->cmd = SETDIR(SOUND_MIXER_WRITE_CD); - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SOUND_MIXER_WRITE_IMIX: - args->cmd = SETDIR(SOUND_MIXER_WRITE_IMIX); - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SOUND_MIXER_WRITE_ALTPCM: - args->cmd = SETDIR(SOUND_MIXER_WRITE_ALTPCM); - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SOUND_MIXER_WRITE_RECLEV: - args->cmd = SETDIR(SOUND_MIXER_WRITE_RECLEV); - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SOUND_MIXER_WRITE_IGAIN: - args->cmd = SETDIR(SOUND_MIXER_WRITE_IGAIN); - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SOUND_MIXER_WRITE_OGAIN: - args->cmd = SETDIR(SOUND_MIXER_WRITE_OGAIN); - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SOUND_MIXER_WRITE_LINE1: - args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE1); - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SOUND_MIXER_WRITE_LINE2: - args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE2); - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SOUND_MIXER_WRITE_LINE3: - args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE3); - return (ioctl((struct ioctl_args *)args)); - - case LINUX_OSS_GETVERSION: { - int version = linux_get_oss_version(td); - return (copyout(&version, (caddr_t)args->arg, sizeof(int))); - } - - case LINUX_SOUND_MIXER_READ_DEVMASK: - args->cmd = SOUND_MIXER_READ_DEVMASK; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_DSP_RESET: - args->cmd = SNDCTL_DSP_RESET; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_DSP_SYNC: - args->cmd = SNDCTL_DSP_SYNC; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_DSP_SPEED: - args->cmd = SNDCTL_DSP_SPEED; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_DSP_STEREO: - args->cmd = SNDCTL_DSP_STEREO; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_DSP_GETBLKSIZE: /* LINUX_SNDCTL_DSP_SETBLKSIZE */ - args->cmd = SNDCTL_DSP_GETBLKSIZE; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_DSP_SETFMT: - args->cmd = SNDCTL_DSP_SETFMT; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SOUND_PCM_WRITE_CHANNELS: - args->cmd = SOUND_PCM_WRITE_CHANNELS; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SOUND_PCM_WRITE_FILTER: - args->cmd = SOUND_PCM_WRITE_FILTER; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_DSP_POST: - args->cmd = SNDCTL_DSP_POST; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_DSP_SUBDIVIDE: - args->cmd = SNDCTL_DSP_SUBDIVIDE; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_DSP_SETFRAGMENT: - args->cmd = SNDCTL_DSP_SETFRAGMENT; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_DSP_GETFMTS: - args->cmd = SNDCTL_DSP_GETFMTS; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_DSP_GETOSPACE: - args->cmd = SNDCTL_DSP_GETOSPACE; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_DSP_GETISPACE: - args->cmd = SNDCTL_DSP_GETISPACE; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_DSP_NONBLOCK: - args->cmd = SNDCTL_DSP_NONBLOCK; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_DSP_GETCAPS: - args->cmd = SNDCTL_DSP_GETCAPS; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_DSP_SETTRIGGER: /* LINUX_SNDCTL_GETTRIGGER */ - args->cmd = SNDCTL_DSP_SETTRIGGER; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_DSP_GETIPTR: - args->cmd = SNDCTL_DSP_GETIPTR; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_DSP_GETOPTR: - args->cmd = SNDCTL_DSP_GETOPTR; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_DSP_GETODELAY: - args->cmd = SNDCTL_DSP_GETODELAY; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_SEQ_RESET: - args->cmd = SNDCTL_SEQ_RESET; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_SEQ_SYNC: - args->cmd = SNDCTL_SEQ_SYNC; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_SYNTH_INFO: - args->cmd = SNDCTL_SYNTH_INFO; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_SEQ_CTRLRATE: - args->cmd = SNDCTL_SEQ_CTRLRATE; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_SEQ_GETOUTCOUNT: - args->cmd = SNDCTL_SEQ_GETOUTCOUNT; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_SEQ_GETINCOUNT: - args->cmd = SNDCTL_SEQ_GETINCOUNT; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_SEQ_PERCMODE: - args->cmd = SNDCTL_SEQ_PERCMODE; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_FM_LOAD_INSTR: - args->cmd = SNDCTL_FM_LOAD_INSTR; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_SEQ_TESTMIDI: - args->cmd = SNDCTL_SEQ_TESTMIDI; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_SEQ_RESETSAMPLES: - args->cmd = SNDCTL_SEQ_RESETSAMPLES; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_SEQ_NRSYNTHS: - args->cmd = SNDCTL_SEQ_NRSYNTHS; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_SEQ_NRMIDIS: - args->cmd = SNDCTL_SEQ_NRMIDIS; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_MIDI_INFO: - args->cmd = SNDCTL_MIDI_INFO; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_SEQ_TRESHOLD: - args->cmd = SNDCTL_SEQ_TRESHOLD; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_SNDCTL_SYNTH_MEMAVL: - args->cmd = SNDCTL_SYNTH_MEMAVL; - return (ioctl((struct ioctl_args *)args)); - - } - - return (ENOIOCTL); + bcopy(&version, data, sizeof(int)); + return (0); } + /* * Console related ioctls */ @@ -1277,104 +900,40 @@ linux_ioctl_sound(struct thread *td, struct linux_ioctl_args *args) #define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG) static int -linux_ioctl_console(struct thread *td, struct linux_ioctl_args *args) +linux_ioctl_KDSKBMODE(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) { - struct file *fp; - int error; - - KKASSERT(td->td_proc); - fp = td->td_proc->p_fd->fd_ofiles[args->fd]; - - switch (args->cmd & 0xffff) { - - case LINUX_KIOCSOUND: - args->cmd = KIOCSOUND; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_KDMKTONE: - args->cmd = KDMKTONE; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_KDGETLED: - args->cmd = KDGETLED; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_KDSETLED: - args->cmd = KDSETLED; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_KDSETMODE: - args->cmd = KDSETMODE; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_KDGETMODE: - args->cmd = KDGETMODE; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_KDGKBMODE: - args->cmd = KDGKBMODE; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_KDSKBMODE: { - int kbdmode; - switch (args->arg) { - case LINUX_KBD_RAW: - kbdmode = K_RAW; - break; - case LINUX_KBD_XLATE: - kbdmode = K_XLATE; - break; - case LINUX_KBD_MEDIUMRAW: - kbdmode = K_RAW; - break; - default: - return (EINVAL); - } - return (fo_ioctl(fp, KDSKBMODE, (caddr_t)&kbdmode, td)); - } - - case LINUX_VT_OPENQRY: - args->cmd = VT_OPENQRY; - return (ioctl((struct ioctl_args *)args)); + int kbdmode; - case LINUX_VT_GETMODE: - args->cmd = VT_GETMODE; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_VT_SETMODE: { - struct vt_mode mode; - error = copyin((caddr_t)args->arg, &mode, sizeof(mode)); - if (error) - return (error); - if (!ISSIGVALID(mode.frsig) && ISSIGVALID(mode.acqsig)) - mode.frsig = mode.acqsig; - error = copyout(&mode, (caddr_t)args->arg, sizeof(mode)); - if (error) - return (error); - args->cmd = VT_SETMODE; - return (ioctl((struct ioctl_args *)args)); + switch ((u_long)data) { + case LINUX_KBD_RAW: + kbdmode = K_RAW; + break; + case LINUX_KBD_XLATE: + kbdmode = K_XLATE; + break; + case LINUX_KBD_MEDIUMRAW: + kbdmode = K_RAW; + break; + default: + return (EINVAL); } + return (fo_ioctl(fp, KDSKBMODE, (caddr_t)&kbdmode, td)); +} - case LINUX_VT_GETSTATE: - args->cmd = VT_GETACTIVE; - return (ioctl((struct ioctl_args *)args)); - - case LINUX_VT_RELDISP: - args->cmd = VT_RELDISP; - return (ioctl((struct ioctl_args *)args)); +static int +linux_ioctl_VT_SETMODE(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) +{ + struct vt_mode *mode = (struct vt_mode *)data; - case LINUX_VT_ACTIVATE: - args->cmd = VT_ACTIVATE; - return (ioctl((struct ioctl_args *)args)); + if (!ISSIGVALID(mode->frsig) && ISSIGVALID(mode->acqsig)) + mode->frsig = mode->acqsig; + return (fo_ioctl(fp, VT_SETMODE, data, td)); +} - case LINUX_VT_WAITACTIVE: - args->cmd = VT_WAITACTIVE; - return (ioctl((struct ioctl_args *)args)); - } - - return (ENOIOCTL); -} +/* + * Socket related ioctls + */ /* * Criteria for interface name translation @@ -1448,33 +1007,24 @@ ifname_linux_to_bsd(const char *lxname, char *bsdname) return (ifp); } -/* - * Implement the SIOCGIFCONF ioctl - */ - static int -linux_ifconf(struct proc *p, struct ifconf *uifc) +linux_ioctl_SIOCGIFCONF(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) { - struct ifconf ifc; + struct ifconf *ifc = (struct ifconf *)data; struct l_ifreq ifr; struct ifnet *ifp; struct ifaddr *ifa; struct iovec iov; struct uio uio; int error, ethno; - struct thread *td = p->p_thread; - - error = copyin(uifc, &ifc, sizeof ifc); - if (error != 0) - return (error); /* much easier to use uiomove than keep track ourselves */ - iov.iov_base = ifc.ifc_buf; - iov.iov_len = ifc.ifc_len; + iov.iov_base = ifc->ifc_buf; + iov.iov_len = ifc->ifc_len; uio.uio_iov = &iov; uio.uio_iovcnt = 1; uio.uio_offset = 0; - uio.uio_resid = ifc.ifc_len; + uio.uio_resid = ifc->ifc_len; uio.uio_segflg = UIO_USERSPACE; uio.uio_rw = UIO_READ; uio.uio_td = td; @@ -1514,17 +1064,28 @@ linux_ifconf(struct proc *p, struct ifconf *uifc) } } - ifc.ifc_len -= uio.uio_resid; - error = copyout(&ifc, uifc, sizeof ifc); + ifc->ifc_len -= uio.uio_resid; - return (error); + return (0); } static int -linux_gifflags(struct proc *p, struct ifnet *ifp, struct l_ifreq *ifr) +linux_ioctl_SIOCGIFFLAGS(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) { + struct l_ifreq *ifr = (struct l_ifreq *)data; + struct ifnet *ifp; + char ifname[IFNAMSIZ]; l_short flags; + if (fp->f_type != DTYPE_SOCKET) { + /* XXX: I doubt this is correct because + * we don't translate the ifname and + * use l_ifreq instead of ifreq + */ + return (fo_ioctl(fp, SIOCGIFFLAGS, data, td)); + } + + ifp = ifname_linux_to_bsd(ifr->ifr_name, ifname); flags = ifp->if_flags; /* these flags have no Linux equivalent */ flags &= ~(IFF_SMART|IFF_OACTIVE|IFF_SIMPLEX| @@ -1535,23 +1096,28 @@ linux_gifflags(struct proc *p, struct ifnet *ifp, struct l_ifreq *ifr) flags |= 0x1000; } - return (copyout(&flags, &ifr->ifr_flags, sizeof flags)); + ifr->ifr_flags = flags; + return (0); } #define ARPHRD_ETHER 1 #define ARPHRD_LOOPBACK 772 static int -linux_gifhwaddr(struct ifnet *ifp, struct l_ifreq *ifr) +linux_ioctl_SIOGIFHWADDR(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) { + struct l_ifreq *ifr = (struct l_ifreq *)data; + struct ifnet *ifp; + char ifname[IFNAMSIZ]; struct ifaddr *ifa; struct sockaddr_dl *sdl; struct l_sockaddr lsa; + ifp = ifname_linux_to_bsd(ifr->ifr_name, ifname); if (ifp->if_type == IFT_LOOP) { - bzero(&lsa, sizeof lsa); - lsa.sa_family = ARPHRD_LOOPBACK; - return (copyout(&lsa, &ifr->ifr_hwaddr, sizeof lsa)); + bzero(&ifr->ifr_hwaddr, sizeof lsa); + ifr->ifr_hwaddr.sa_family = ARPHRD_LOOPBACK; + return (0); } if (ifp->if_type != IFT_ETHER) @@ -1561,298 +1127,235 @@ linux_gifhwaddr(struct ifnet *ifp, struct l_ifreq *ifr) sdl = (struct sockaddr_dl*)ifa->ifa_addr; if (sdl != NULL && (sdl->sdl_family == AF_LINK) && (sdl->sdl_type == IFT_ETHER)) { - bzero(&lsa, sizeof lsa); - lsa.sa_family = ARPHRD_ETHER; - bcopy(LLADDR(sdl), lsa.sa_data, LINUX_IFHWADDRLEN); - return (copyout(&lsa, &ifr->ifr_hwaddr, sizeof lsa)); + bzero(&ifr->ifr_hwaddr, sizeof lsa); + ifr->ifr_hwaddr.sa_family = ARPHRD_ETHER; + bcopy(LLADDR(sdl), ifr->ifr_hwaddr.sa_data, LINUX_IFHWADDRLEN); + return (0); } } return (ENOENT); } -/* - * Socket related ioctls - */ - static int -linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args) +linux_ioctl_map_ifname(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) { - struct proc *p = td->td_proc; - char lifname[LINUX_IFNAMSIZ], ifname[IFNAMSIZ]; struct ifnet *ifp; - struct file *fp; - int error, type; + int error; + char *oifname = (char *)data; + char lifname[LINUX_IFNAMSIZ]; - KKASSERT(p); KASSERT(LINUX_IFNAMSIZ == IFNAMSIZ, ("%s(): LINUX_IFNAMSIZ != IFNAMSIZ", __FUNCTION__)); - ifp = NULL; - error = 0; - - if (args->fd >= p->p_fd->fd_nfiles || - (fp = p->p_fd->fd_ofiles[args->fd]) == NULL) - return (EBADF); - type = fp->f_type; - - if (type != DTYPE_SOCKET) { + if (fp->f_type != DTYPE_SOCKET) { + /* + * XXX: I doubt this is correct because + * we don't map the ifname + */ /* not a socket - probably a tap / vmnet device */ - switch (args->cmd) { - case LINUX_SIOCGIFADDR: - case LINUX_SIOCSIFADDR: - case LINUX_SIOCGIFFLAGS: - return (linux_ioctl_special(td, args)); - default: + if (ocmd == LINUX_SIOCGIFADDR || ocmd == LINUX_SIOCSIFADDR) { + cmd = (ocmd == LINUX_SIOCGIFADDR) ? SIOCGIFADDR : SIOCSIFADDR; + return (fo_ioctl(fp, cmd, data, td)); + } else return (ENOIOCTL); - } } - switch (args->cmd & 0xffff) { - - case LINUX_FIOGETOWN: - case LINUX_FIOSETOWN: - case LINUX_SIOCADDMULTI: - case LINUX_SIOCATMARK: - case LINUX_SIOCDELMULTI: - case LINUX_SIOCGIFCONF: - case LINUX_SIOCGPGRP: - case LINUX_SIOCSPGRP: - /* these ioctls don't take an interface name */ -#ifdef DEBUG - printf("%s(): ioctl %d\n", __FUNCTION__, args->cmd & 0xffff); -#endif - break; - - case LINUX_SIOCGIFFLAGS: - case LINUX_SIOCGIFADDR: - case LINUX_SIOCSIFADDR: - case LINUX_SIOCGIFDSTADDR: - case LINUX_SIOCGIFBRDADDR: - case LINUX_SIOCGIFNETMASK: - case LINUX_SIOCSIFNETMASK: - case LINUX_SIOCGIFMTU: - case LINUX_SIOCSIFMTU: - case LINUX_SIOCSIFNAME: - case LINUX_SIOCGIFHWADDR: - case LINUX_SIOCSIFHWADDR: - case LINUX_SIOCDEVPRIVATE: - case LINUX_SIOCDEVPRIVATE+1: - /* copy in the interface name and translate it. */ - error = copyin((char *)args->arg, lifname, LINUX_IFNAMSIZ); - if (error != 0) - return (error); + /* Save the original ifname */ + bcopy(oifname, lifname, LINUX_IFNAMSIZ); #ifdef DEBUG - printf("%s(): ioctl %d on %.*s\n", __FUNCTION__, - args->cmd & 0xffff, LINUX_IFNAMSIZ, lifname); + printf("%s(): ioctl %d on %.*s\n", __FUNCTION__, + (int)(cmd & 0xffff), LINUX_IFNAMSIZ, lifname); #endif - ifp = ifname_linux_to_bsd(lifname, ifname); - if (ifp == NULL) - return (EINVAL); - /* - * We need to copy it back out in case we pass the - * request on to our native ioctl(), which will expect - * the ifreq to be in user space and have the correct - * interface name. - */ - error = copyout(ifname, (char *)args->arg, IFNAMSIZ); - if (error != 0) - return (error); -#ifdef DEBUG - printf("%s(): %s translated to %s\n", __FUNCTION__, - lifname, ifname); -#endif - break; - - default: - return (ENOIOCTL); + /* Replace linux ifname with bsd ifname */ + ifp = ifname_linux_to_bsd(lifname, oifname); + if (ifp == NULL) { + error = EINVAL; + goto clean_ifname; } - switch (args->cmd & 0xffff) { - - case LINUX_FIOSETOWN: - args->cmd = FIOSETOWN; - error = ioctl((struct ioctl_args *)args); - break; - - case LINUX_SIOCSPGRP: - args->cmd = SIOCSPGRP; - error = ioctl((struct ioctl_args *)args); - break; - - case LINUX_FIOGETOWN: - args->cmd = FIOGETOWN; - error = ioctl((struct ioctl_args *)args); - break; - - case LINUX_SIOCGPGRP: - args->cmd = SIOCGPGRP; - error = ioctl((struct ioctl_args *)args); - break; - - case LINUX_SIOCATMARK: - args->cmd = SIOCATMARK; - error = ioctl((struct ioctl_args *)args); - break; - - /* LINUX_SIOCGSTAMP */ - - case LINUX_SIOCGIFCONF: - error = linux_ifconf(p, (struct ifconf *)args->arg); - break; - - case LINUX_SIOCGIFFLAGS: - args->cmd = SIOCGIFFLAGS; - error = linux_gifflags(p, ifp, (struct l_ifreq *)args->arg); - break; - - case LINUX_SIOCGIFADDR: - args->cmd = OSIOCGIFADDR; - error = ioctl((struct ioctl_args *)args); - break; - - case LINUX_SIOCSIFADDR: - /* XXX probably doesn't work, included for completeness */ - args->cmd = SIOCSIFADDR; - error = ioctl((struct ioctl_args *)args); - break; - - case LINUX_SIOCGIFDSTADDR: - args->cmd = OSIOCGIFDSTADDR; - error = ioctl((struct ioctl_args *)args); - break; - - case LINUX_SIOCGIFBRDADDR: - args->cmd = OSIOCGIFBRDADDR; - error = ioctl((struct ioctl_args *)args); - break; - - case LINUX_SIOCGIFNETMASK: - args->cmd = OSIOCGIFNETMASK; - error = ioctl((struct ioctl_args *)args); - break; - - case LINUX_SIOCSIFNETMASK: - error = ENOIOCTL; - break; - - case LINUX_SIOCGIFMTU: - args->cmd = SIOCGIFMTU; - error = ioctl((struct ioctl_args *)args); - break; - - case LINUX_SIOCSIFMTU: - args->cmd = SIOCSIFMTU; - error = ioctl((struct ioctl_args *)args); - break; - - case LINUX_SIOCSIFNAME: - error = ENOIOCTL; - break; - - case LINUX_SIOCGIFHWADDR: - error = linux_gifhwaddr(ifp, (struct l_ifreq *)args->arg); - break; - - case LINUX_SIOCSIFHWADDR: - error = ENOIOCTL; - break; - - case LINUX_SIOCADDMULTI: - args->cmd = SIOCADDMULTI; - error = ioctl((struct ioctl_args *)args); - break; - - case LINUX_SIOCDELMULTI: - args->cmd = SIOCDELMULTI; - error = ioctl((struct ioctl_args *)args); - break; - - /* - * XXX This is slightly bogus, but these ioctls are currently - * XXX only used by the aironet (if_an) network driver. - */ - case LINUX_SIOCDEVPRIVATE: - args->cmd = SIOCGPRIVATE_0; - error = ioctl((struct ioctl_args *)args); - break; - - case LINUX_SIOCDEVPRIVATE+1: - args->cmd = SIOCGPRIVATE_1; - error = ioctl((struct ioctl_args *)args); - break; - } - - if (ifp != NULL) - /* restore the original interface name */ - copyout(lifname, (char *)args->arg, LINUX_IFNAMSIZ); - #ifdef DEBUG - printf("%s(): returning %d\n", __FUNCTION__, error); + printf("%s(): %s translated to %s\n", __FUNCTION__, + lifname, oifname); #endif + + error = fo_ioctl(fp, cmd, data, td); + +clean_ifname: + bcopy(lifname, oifname, LINUX_IFNAMSIZ); return (error); } -/* - * Device private ioctl handler - */ -static int -linux_ioctl_private(struct thread *td, struct linux_ioctl_args *args) -{ - struct filedesc *fdp; - struct file *fp; - int type; - - KKASSERT(td->td_proc); - fdp = td->td_proc->p_fd; - if (args->fd >= fdp->fd_nfiles || - (fp = fdp->fd_ofiles[args->fd]) == NULL) { - return (EBADF); - } else { - type = fp->f_type; - } - if (type == DTYPE_SOCKET) - return (linux_ioctl_socket(td, args)); - return (ENOIOCTL); -} /* - * DRM ioctl handler (sys/dev/drm) + * generic linux -> BSD syscall direction mapper */ -static int -linux_ioctl_drm(struct thread *td, struct linux_ioctl_args *args) +int +linux_ioctl_dirmap(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct thread *td) { - args->cmd = SETDIR(args->cmd); - return ioctl((struct ioctl_args *)args); -} + static u_int32_t dirbits[4] = { IOC_VOID, IOC_IN, IOC_OUT, IOC_INOUT }; -/* - * Special ioctl handler - */ -static int -linux_ioctl_special(struct thread *td, struct linux_ioctl_args *args) -{ - int error; + return (fo_ioctl(fp, (cmd & ~IOC_DIRMASK) | dirbits[ocmd >> 30], data, td)); +} - switch (args->cmd) { - case LINUX_SIOCGIFADDR: - args->cmd = SIOCGIFADDR; - error = ioctl((struct ioctl_args *)args); - break; - case LINUX_SIOCSIFADDR: - args->cmd = SIOCSIFADDR; - error = ioctl((struct ioctl_args *)args); - break; - case LINUX_SIOCGIFFLAGS: - args->cmd = SIOCGIFFLAGS; - error = ioctl((struct ioctl_args *)args); - break; - default: - error = ENOIOCTL; - } - return (error); -} +static struct ioctl_map_range linux_ioctl_map_entries[] = { + /* disk ioctl */ + MAPPED_IOCTL_IOR(LINUX_BLKGETSIZE, linux_ioctl_BLKGETSIZE, uint32_t), + /* termio ioctl */ + MAPPED_IOCTL_IOR(LINUX_TCGETS, linux_ioctl_TCGETS, struct linux_termios), + MAPPED_IOCTL_IOW(LINUX_TCSETS, linux_ioctl_TCSETS, struct linux_termios), + MAPPED_IOCTL_IOW(LINUX_TCSETSW, linux_ioctl_TCSETSW, struct linux_termios), + MAPPED_IOCTL_IOW(LINUX_TCSETSF, linux_ioctl_TCSETSF, struct linux_termios), + MAPPED_IOCTL_IOR(LINUX_TCGETA, linux_ioctl_TCGETA, struct linux_termio), + MAPPED_IOCTL_IOW(LINUX_TCSETA, linux_ioctl_TCSETA, struct linux_termio), + MAPPED_IOCTL_IOW(LINUX_TCSETAW, linux_ioctl_TCSETAW, struct linux_termio), + MAPPED_IOCTL_IOW(LINUX_TCSETAF, linux_ioctl_TCSETAF, struct linux_termio), + MAPPED_IOCTL_IO(LINUX_TCXONC, linux_ioctl_TCXONC), + MAPPED_IOCTL_IO(LINUX_TCFLSH, linux_ioctl_TCFLSH), + MAPPED_IOCTL_MAP(LINUX_TIOCEXCL, TIOCEXCL), + MAPPED_IOCTL_MAP(LINUX_TIOCNXCL, TIOCNXCL), + MAPPED_IOCTL_MAP(LINUX_TIOCGPGRP, TIOCGPGRP), + MAPPED_IOCTL_MAP(LINUX_TIOCSPGRP, TIOCSPGRP), + MAPPED_IOCTL_MAP(LINUX_TIOCGWINSZ, TIOCGWINSZ), + MAPPED_IOCTL_MAP(LINUX_TIOCSWINSZ, TIOCSWINSZ), + MAPPED_IOCTL_MAP(LINUX_TIOCMGET, TIOCMGET), + MAPPED_IOCTL_MAP(LINUX_TIOCMBIS, TIOCMBIS), + MAPPED_IOCTL_MAP(LINUX_TIOCMBIC, TIOCMBIC), + MAPPED_IOCTL_MAP(LINUX_TIOCMSET, TIOCMSET), + MAPPED_IOCTL_MAP(LINUX_FIONREAD, FIONREAD), + MAPPED_IOCTL_MAP(LINUX_TIOCCONS, TIOCCONS), + MAPPED_IOCTL_IOR(LINUX_TIOCGSERIAL, linux_ioctl_TIOCGSERIAL, struct linux_serial_struct), + MAPPED_IOCTL_IOW(LINUX_TIOCSSERIAL, linux_ioctl_TIOCSSERIAL, struct linux_serial_struct), + MAPPED_IOCTL_MAP(LINUX_FIONBIO, FIONBIO), + MAPPED_IOCTL_MAP(LINUX_TIOCNOTTY, TIOCNOTTY), + MAPPED_IOCTL_IO(LINUX_TIOCSETD, linux_ioctl_TIOCSETD), + MAPPED_IOCTL_IOR(LINUX_TIOCGETD, linux_ioctl_TIOCGETD, int), + MAPPED_IOCTL_MAP(LINUX_FIONCLEX, FIONCLEX), + MAPPED_IOCTL_MAP(LINUX_FIOCLEX, FIOCLEX), + MAPPED_IOCTL_MAP(LINUX_FIOASYNC, FIOASYNC), + /* cdrom ioctl */ + MAPPED_IOCTL_MAP(LINUX_CDROMPAUSE, CDIOCPAUSE), + MAPPED_IOCTL_MAP(LINUX_CDROMRESUME, CDIOCRESUME), + MAPPED_IOCTL_MAP(LINUX_CDROMPLAYMSF, CDIOCPLAYMSF), + MAPPED_IOCTL_MAP(LINUX_CDROMPLAYTRKIND, CDIOCPLAYTRACKS), + MAPPED_IOCTL_IOR(LINUX_CDROMREADTOCHDR, linux_ioctl_CDROMREADTOCHDR, struct linux_cdrom_tochdr), + MAPPED_IOCTL_IOWR(LINUX_CDROMREADTOCENTRY, linux_ioctl_CDROMREADTOCENTRY, struct linux_cdrom_tocentry), + MAPPED_IOCTL_MAP(LINUX_CDROMSTOP, CDIOCSTOP), + MAPPED_IOCTL_MAP(LINUX_CDROMSTART, CDIOCSTART), + MAPPED_IOCTL_MAP(LINUX_CDROMEJECT, CDIOCEJECT), + MAPPED_IOCTL_IOWR(LINUX_CDROMSUBCHNL, linux_ioctl_CDROMSUBCHNL, struct linux_cdrom_subchnl), + MAPPED_IOCTL_MAP(LINUX_CDROMRESET, CDIOCRESET), + /* sound ioctl */ + MAPPED_IOCTL_MAPF(LINUX_SOUND_MIXER_WRITE_VOLUME, SOUND_MIXER_WRITE_VOLUME, linux_ioctl_dirmap), + MAPPED_IOCTL_MAPF(LINUX_SOUND_MIXER_WRITE_BASS, SOUND_MIXER_WRITE_BASS, linux_ioctl_dirmap), + MAPPED_IOCTL_MAPF(LINUX_SOUND_MIXER_WRITE_TREBLE, SOUND_MIXER_WRITE_TREBLE, linux_ioctl_dirmap), + MAPPED_IOCTL_MAPF(LINUX_SOUND_MIXER_WRITE_SYNTH, SOUND_MIXER_WRITE_SYNTH, linux_ioctl_dirmap), + MAPPED_IOCTL_MAPF(LINUX_SOUND_MIXER_WRITE_PCM, SOUND_MIXER_WRITE_PCM, linux_ioctl_dirmap), + MAPPED_IOCTL_MAPF(LINUX_SOUND_MIXER_WRITE_SPEAKER, SOUND_MIXER_WRITE_SPEAKER, linux_ioctl_dirmap), + MAPPED_IOCTL_MAPF(LINUX_SOUND_MIXER_WRITE_LINE, SOUND_MIXER_WRITE_LINE, linux_ioctl_dirmap), + MAPPED_IOCTL_MAPF(LINUX_SOUND_MIXER_WRITE_MIC, SOUND_MIXER_WRITE_MIC, linux_ioctl_dirmap), + MAPPED_IOCTL_MAPF(LINUX_SOUND_MIXER_WRITE_CD, SOUND_MIXER_WRITE_CD, linux_ioctl_dirmap), + MAPPED_IOCTL_MAPF(LINUX_SOUND_MIXER_WRITE_IMIX, SOUND_MIXER_WRITE_IMIX, linux_ioctl_dirmap), + MAPPED_IOCTL_MAPF(LINUX_SOUND_MIXER_WRITE_ALTPCM, SOUND_MIXER_WRITE_ALTPCM, linux_ioctl_dirmap), + MAPPED_IOCTL_MAPF(LINUX_SOUND_MIXER_WRITE_RECLEV, SOUND_MIXER_WRITE_RECLEV, linux_ioctl_dirmap), + MAPPED_IOCTL_MAPF(LINUX_SOUND_MIXER_WRITE_IGAIN, SOUND_MIXER_WRITE_IGAIN, linux_ioctl_dirmap), + MAPPED_IOCTL_MAPF(LINUX_SOUND_MIXER_WRITE_OGAIN, SOUND_MIXER_WRITE_OGAIN, linux_ioctl_dirmap), + MAPPED_IOCTL_MAPF(LINUX_SOUND_MIXER_WRITE_LINE1, SOUND_MIXER_WRITE_LINE1, linux_ioctl_dirmap), + MAPPED_IOCTL_MAPF(LINUX_SOUND_MIXER_WRITE_LINE2, SOUND_MIXER_WRITE_LINE2, linux_ioctl_dirmap), + MAPPED_IOCTL_MAPF(LINUX_SOUND_MIXER_WRITE_LINE3, SOUND_MIXER_WRITE_LINE3, linux_ioctl_dirmap), + MAPPED_IOCTL_IOR(LINUX_OSS_GETVERSION, linux_ioctl_OSS_GETVERSION, int), + MAPPED_IOCTL_MAP(LINUX_SOUND_MIXER_READ_DEVMASK, SOUND_MIXER_READ_DEVMASK), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_DSP_RESET, SNDCTL_DSP_RESET), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_DSP_SYNC, SNDCTL_DSP_SYNC), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_DSP_SPEED, SNDCTL_DSP_SPEED), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_DSP_STEREO, SNDCTL_DSP_STEREO), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_DSP_GETBLKSIZE, SNDCTL_DSP_GETBLKSIZE), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_DSP_SETFMT, SNDCTL_DSP_SETFMT), + MAPPED_IOCTL_MAP(LINUX_SOUND_PCM_WRITE_CHANNELS, SOUND_PCM_WRITE_CHANNELS), + MAPPED_IOCTL_MAP(LINUX_SOUND_PCM_WRITE_FILTER, SOUND_PCM_WRITE_FILTER), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_DSP_POST, SNDCTL_DSP_POST), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_DSP_SUBDIVIDE, SNDCTL_DSP_SUBDIVIDE), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_DSP_SETFRAGMENT, SNDCTL_DSP_SETFRAGMENT), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_DSP_GETFMTS, SNDCTL_DSP_GETFMTS), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_DSP_GETOSPACE, SNDCTL_DSP_GETOSPACE), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_DSP_GETISPACE, SNDCTL_DSP_GETISPACE), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_DSP_NONBLOCK, SNDCTL_DSP_NONBLOCK), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_DSP_GETCAPS, SNDCTL_DSP_GETCAPS), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_DSP_SETTRIGGER, SNDCTL_DSP_SETTRIGGER), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_DSP_GETIPTR, SNDCTL_DSP_GETIPTR), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_DSP_GETOPTR, SNDCTL_DSP_GETOPTR), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_DSP_GETODELAY, SNDCTL_DSP_GETODELAY), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_SEQ_RESET, SNDCTL_SEQ_RESET), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_SEQ_SYNC, SNDCTL_SEQ_SYNC), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_SYNTH_INFO, SNDCTL_SYNTH_INFO), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_SEQ_CTRLRATE, SNDCTL_SEQ_CTRLRATE), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_SEQ_GETOUTCOUNT, SNDCTL_SEQ_GETOUTCOUNT), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_SEQ_GETINCOUNT, SNDCTL_SEQ_GETINCOUNT), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_SEQ_PERCMODE, SNDCTL_SEQ_PERCMODE), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_FM_LOAD_INSTR, SNDCTL_FM_LOAD_INSTR), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_SEQ_TESTMIDI, SNDCTL_SEQ_TESTMIDI), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_SEQ_RESETSAMPLES, SNDCTL_SEQ_RESETSAMPLES), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_SEQ_NRSYNTHS, SNDCTL_SEQ_NRSYNTHS), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_SEQ_NRMIDIS, SNDCTL_SEQ_NRMIDIS), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_MIDI_INFO, SNDCTL_MIDI_INFO), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_SEQ_TRESHOLD, SNDCTL_SEQ_TRESHOLD), + MAPPED_IOCTL_MAP(LINUX_SNDCTL_SYNTH_MEMAVL, SNDCTL_SYNTH_MEMAVL), + /* console ioctl */ + MAPPED_IOCTL_MAP(LINUX_KIOCSOUND, KIOCSOUND), + MAPPED_IOCTL_MAP(LINUX_KDMKTONE, KDMKTONE), + MAPPED_IOCTL_MAP(LINUX_KDGETLED, KDGETLED), + MAPPED_IOCTL_MAP(LINUX_KDSETLED, KDSETLED), + MAPPED_IOCTL_MAP(LINUX_KDSETMODE, KDSETMODE), + MAPPED_IOCTL_MAP(LINUX_KDGETMODE, KDGETMODE), + MAPPED_IOCTL_MAP(LINUX_KDGKBMODE, KDGKBMODE), + MAPPED_IOCTL_IOW(LINUX_KDSKBMODE, linux_ioctl_KDSKBMODE, int), + MAPPED_IOCTL_MAP(LINUX_VT_OPENQRY, VT_OPENQRY), + MAPPED_IOCTL_MAP(LINUX_VT_GETMODE, VT_GETMODE), + MAPPED_IOCTL_IOW(LINUX_VT_SETMODE, linux_ioctl_VT_SETMODE, struct vt_mode), + MAPPED_IOCTL_MAP(LINUX_VT_GETSTATE, VT_GETACTIVE), + MAPPED_IOCTL_MAP(LINUX_VT_RELDISP, VT_RELDISP), + MAPPED_IOCTL_MAP(LINUX_VT_ACTIVATE, VT_ACTIVATE), + MAPPED_IOCTL_MAP(LINUX_VT_WAITACTIVE, VT_WAITACTIVE), + /* socket ioctl */ + MAPPED_IOCTL_MAP(LINUX_FIOSETOWN, FIOSETOWN), + MAPPED_IOCTL_MAP(LINUX_SIOCSPGRP, SIOCSPGRP), + MAPPED_IOCTL_MAP(LINUX_FIOGETOWN, FIOGETOWN), + MAPPED_IOCTL_MAP(LINUX_SIOCGPGRP, SIOCGPGRP), + MAPPED_IOCTL_MAP(LINUX_SIOCATMARK, SIOCATMARK), + MAPPED_IOCTL_IOWR(LINUX_SIOCGIFCONF, linux_ioctl_SIOCGIFCONF, struct ifconf), + MAPPED_IOCTL_IOWR(LINUX_SIOCGIFFLAGS, linux_ioctl_SIOCGIFFLAGS, struct l_ifreq), + MAPPED_IOCTL_MAPF(LINUX_SIOCGIFADDR, OSIOCGIFADDR, linux_ioctl_map_ifname), + MAPPED_IOCTL_MAPF(LINUX_SIOCSIFADDR, SIOCSIFADDR, linux_ioctl_map_ifname), + MAPPED_IOCTL_MAPF(LINUX_SIOCGIFDSTADDR, OSIOCGIFDSTADDR, linux_ioctl_map_ifname), + MAPPED_IOCTL_MAPF(LINUX_SIOCGIFBRDADDR, OSIOCGIFBRDADDR, linux_ioctl_map_ifname), + MAPPED_IOCTL_MAPF(LINUX_SIOCGIFNETMASK, OSIOCGIFNETMASK, linux_ioctl_map_ifname), + /*MAPPED_IOCTL_IOx(LINUX_SIOCSIFNETMASK, x, x),*/ + MAPPED_IOCTL_MAPF(LINUX_SIOCGIFMTU, SIOCGIFMTU, linux_ioctl_map_ifname), + MAPPED_IOCTL_MAPF(LINUX_SIOCSIFMTU, SIOCSIFMTU, linux_ioctl_map_ifname), + MAPPED_IOCTL_IOWR(LINUX_SIOCGIFHWADDR, linux_ioctl_SIOGIFHWADDR, struct l_ifreq), + MAPPED_IOCTL_MAP(LINUX_SIOCADDMULTI, SIOCADDMULTI), + MAPPED_IOCTL_MAP(LINUX_SIOCDELMULTI, SIOCDELMULTI), + /* + * XXX This is slightly bogus, but these ioctls are currently + * XXX only used by the aironet (if_an) network driver. + */ + MAPPED_IOCTL_MAPF(LINUX_SIOCDEVPRIVATE, SIOCGPRIVATE_0, linux_ioctl_map_ifname), + MAPPED_IOCTL_MAPF(LINUX_SIOCDEVPRIVATE+1, SIOCGPRIVATE_1, linux_ioctl_map_ifname), + MAPPED_IOCTL_MAPF(0, 0, NULL) + }; + +struct ioctl_map linux_ioctl_map = { + 0xffff, /* mask */ + "linux", /* subsys */ + LIST_HEAD_INITIALIZER(mapping) + }; + +static struct ioctl_map_handler linux_ioctl_base_handler = { + &linux_ioctl_map, + "base", + linux_ioctl_map_entries + }; /* * main ioctl syscall function @@ -1861,99 +1364,15 @@ linux_ioctl_special(struct thread *td, struct linux_ioctl_args *args) int linux_ioctl(struct linux_ioctl_args *args) { - struct thread *td = curthread; - struct proc *p = td->td_proc; - struct filedesc *fdp; - struct file *fp; - struct handler_element *he; - int error, cmd; - - KKASSERT(p); - #ifdef DEBUG if (ldebug(ioctl)) printf(ARGS(ioctl, "%d, %04x, *"), args->fd, args->cmd); #endif - fdp = p->p_fd; - if ((unsigned)args->fd >= fdp->fd_nfiles) - return (EBADF); - fp = fdp->fd_ofiles[args->fd]; - if (fp == NULL || (fp->f_flag & (FREAD|FWRITE)) == 0) - return (EBADF); - - /* Iterate over the ioctl handlers */ - cmd = args->cmd & 0xffff; - TAILQ_FOREACH(he, &handlers, list) { - if (cmd >= he->low && cmd <= he->high) { - error = (*he->func)(td, args); - if (error != ENOIOCTL) - return (error); - } - } - - printf("linux: 'ioctl' fd=%d, cmd=0x%x ('%c',%d) not implemented\n", - args->fd, (int)(args->cmd & 0xffff), - (int)(args->cmd & 0xff00) >> 8, (int)(args->cmd & 0xff)); - - return (EINVAL); + return (mapped_ioctl(args->fd, args->cmd, (caddr_t)args->arg, &linux_ioctl_map)); } -int -linux_ioctl_register_handler(struct linux_ioctl_handler *h) -{ - struct handler_element *he, *cur; - - if (h == NULL || h->func == NULL) - return (EINVAL); - - /* - * Reuse the element if the handler is already on the list, otherwise - * create a new element. - */ - TAILQ_FOREACH(he, &handlers, list) { - if (he->func == h->func) - break; - } - if (he == NULL) { - MALLOC(he, struct handler_element *, sizeof(*he), - M_LINUX, M_WAITOK); - he->func = h->func; - } else - TAILQ_REMOVE(&handlers, he, list); - - /* Initialize range information. */ - he->low = h->low; - he->high = h->high; - he->span = h->high - h->low + 1; - - /* Add the element to the list, sorted on span. */ - TAILQ_FOREACH(cur, &handlers, list) { - if (cur->span > he->span) { - TAILQ_INSERT_BEFORE(cur, he, list); - return (0); - } - } - TAILQ_INSERT_TAIL(&handlers, he, list); - - return (0); -} - -int -linux_ioctl_unregister_handler(struct linux_ioctl_handler *h) -{ - struct handler_element *he; - - if (h == NULL || h->func == NULL) - return (EINVAL); - - TAILQ_FOREACH(he, &handlers, list) { - if (he->func == h->func) { - TAILQ_REMOVE(&handlers, he, list); - FREE(he, M_LINUX); - return (0); - } - } - - return (EINVAL); -} +SYSINIT (linux_ioctl_register, SI_SUB_KLD, SI_ORDER_MIDDLE, + mapped_ioctl_register_handler, &linux_ioctl_base_handler); +SYSUNINIT(linux_ioctl_register, SI_SUB_KLD, SI_ORDER_MIDDLE, + mapped_ioctl_unregister_handler, &linux_ioctl_base_handler); diff --git a/sys/emulation/linux/linux_ioctl.h b/sys/emulation/linux/linux_ioctl.h index fabeae41c0..abe2fb20d4 100644 --- a/sys/emulation/linux/linux_ioctl.h +++ b/sys/emulation/linux/linux_ioctl.h @@ -26,12 +26,21 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/compat/linux/linux_ioctl.h,v 1.4.2.4 2003/05/01 20:16:09 anholt Exp $ - * $DragonFly: src/sys/emulation/linux/linux_ioctl.h,v 1.3 2003/06/25 03:55:44 dillon Exp $ + * $DragonFly: src/sys/emulation/linux/linux_ioctl.h,v 1.4 2004/08/15 14:15:00 joerg Exp $ */ #ifndef _LINUX_IOCTL_H_ #define _LINUX_IOCTL_H_ +/* + * direction flags + */ +#define LINUX_IOC_VOID 0x00000000 +#define LINUX_IOC_IN 0x40000000 +#define LINUX_IOC_OUT 0x80000000 +#define LINUX_IOC_INOUT (LINUX_IOC_IN | LINUX_IOC_OUT) +#define LINUX_IOC_DIRMASK 0xc0000000 + /* * disk */ @@ -634,5 +643,6 @@ */ struct ifnet; int linux_ifname(struct ifnet *, char *, size_t); +int linux_ioctl_dirmap(struct file *, u_long, u_long, caddr_t, struct thread *); #endif /* !_LINUX_IOCTL_H_ */ -- 2.41.0