Patchwork [18/23] bsd-user: add shim for the ioctl system call

login
register
mail settings
Submitter Stacey Son
Date June 24, 2013, 2:03 a.m.
Message ID <1372039435-41921-19-git-send-email-sson@FreeBSD.org>
Download mbox | patch
Permalink /patch/253926/
State New
Headers show

Comments

Stacey Son - June 24, 2013, 2:03 a.m.
This change adds support for the ioctl(2) system call emulation.  In addtion,
it adds definitions and support for the FreeBSD tty(4) and file io ioctl's.

Signed-off-by: Stacey Son <sson@FreeBSD.org>
---
 Makefile.target                 |    2 +-
 bsd-user/Makefile.objs          |    2 +-
 bsd-user/freebsd/ioctl-cmds.h   |   47 ++++
 bsd-user/freebsd/ioctl-filio.h  |   45 ++++
 bsd-user/freebsd/ioctl-ioccom.h |   54 +++++
 bsd-user/freebsd/ioctl-ttycom.h |  257 ++++++++++++++++++++++
 bsd-user/freebsd/ioctl-types.h  |    7 +
 bsd-user/ioctl.c                |  447 +++++++++++++++++++++++++++++++++++++++
 bsd-user/netbsd/ioctl-cmds.h    |   48 +++++
 bsd-user/netbsd/ioctl-filio.h   |   29 +++
 bsd-user/netbsd/ioctl-ioccom.h  |   38 ++++
 bsd-user/netbsd/ioctl-ttycom.h  |  240 +++++++++++++++++++++
 bsd-user/netbsd/ioctl-types.h   |    7 +
 bsd-user/openbsd/ioctl-cmds.h   |   48 +++++
 bsd-user/openbsd/ioctl-filio.h  |   29 +++
 bsd-user/openbsd/ioctl-ioccom.h |   38 ++++
 bsd-user/openbsd/ioctl-ttycom.h |  240 +++++++++++++++++++++
 bsd-user/openbsd/ioctl-types.h  |    7 +
 bsd-user/qemu.h                 |    5 +
 bsd-user/syscall.c              |    9 +
 20 files changed, 1597 insertions(+), 2 deletions(-)
 create mode 100644 bsd-user/freebsd/ioctl-cmds.h
 create mode 100644 bsd-user/freebsd/ioctl-filio.h
 create mode 100644 bsd-user/freebsd/ioctl-ioccom.h
 create mode 100644 bsd-user/freebsd/ioctl-ttycom.h
 create mode 100644 bsd-user/freebsd/ioctl-types.h
 create mode 100644 bsd-user/ioctl.c
 create mode 100644 bsd-user/netbsd/ioctl-cmds.h
 create mode 100644 bsd-user/netbsd/ioctl-filio.h
 create mode 100644 bsd-user/netbsd/ioctl-ioccom.h
 create mode 100644 bsd-user/netbsd/ioctl-ttycom.h
 create mode 100644 bsd-user/netbsd/ioctl-types.h
 create mode 100644 bsd-user/openbsd/ioctl-cmds.h
 create mode 100644 bsd-user/openbsd/ioctl-filio.h
 create mode 100644 bsd-user/openbsd/ioctl-ioccom.h
 create mode 100644 bsd-user/openbsd/ioctl-ttycom.h
 create mode 100644 bsd-user/openbsd/ioctl-types.h

Patch

diff --git a/Makefile.target b/Makefile.target
index ec00c80..e67e2bd 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -107,7 +107,7 @@  QEMU_CFLAGS+=-I$(SRC_PATH)/bsd-user -I$(SRC_PATH)/bsd-user/$(TARGET_ARCH) \
 			 -I$(SRC_PATH)/bsd-user/$(TARGET_OS)
 
 obj-y += bsd-user/
-obj-y += gdbstub.o user-exec.o
+obj-y += gdbstub.o thunk.o user-exec.o
 
 endif #CONFIG_BSD_USER
 
diff --git a/bsd-user/Makefile.objs b/bsd-user/Makefile.objs
index 2608337..fbb3e56 100644
--- a/bsd-user/Makefile.objs
+++ b/bsd-user/Makefile.objs
@@ -1,4 +1,4 @@ 
-obj-y = main.o bsdload.o elfload.o mmap.o signal.o strace.o syscall.o \
+obj-y = main.o bsdload.o elfload.o ioctl.o mmap.o signal.o strace.o syscall.o \
 	        uaccess.o bsd-mem.o bsd-proc.o $(TARGET_OS)/os-time.o \
 			$(TARGET_OS)/os-proc.o bsd-socket.o $(TARGET_OS)/os-socket.o \
 			$(TARGET_OS)/os-stat.o $(TARGET_OS)/os-thread.o
diff --git a/bsd-user/freebsd/ioctl-cmds.h b/bsd-user/freebsd/ioctl-cmds.h
new file mode 100644
index 0000000..85d3c41
--- /dev/null
+++ b/bsd-user/freebsd/ioctl-cmds.h
@@ -0,0 +1,47 @@ 
+
+/* sys/ttycom.h tty(4) */
+IOCTL(TIOCSETD, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(TIOCGETD, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(TIOCSBRK, IOC_, TYPE_NULL)
+IOCTL(TIOCCBRK, IOC_, TYPE_NULL)
+IOCTL(TIOCSDTR, IOC_, TYPE_NULL)
+IOCTL(TIOCCDTR, IOC_, TYPE_NULL)
+IOCTL(TIOCGPGRP, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(TIOCSPGRP, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(TIOCGETA, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
+IOCTL(TIOCSETA, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
+IOCTL(TIOCSETAW, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
+IOCTL(TIOCSETAF, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
+IOCTL(TIOCOUTQ, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(TIOCSTI, IOC_W, MK_PTR(TYPE_CHAR))
+IOCTL(TIOCNOTTY, IOC_, TYPE_NULL)
+IOCTL(TIOCSTOP, IOC_, TYPE_NULL)
+IOCTL(TIOCSTART, IOC_, TYPE_NULL)
+IOCTL(TIOCSCTTY, IOC_, TYPE_NULL)
+IOCTL(TIOCDRAIN, IOC_, TYPE_NULL)
+IOCTL(TIOCEXCL, IOC_, TYPE_NULL)
+IOCTL(TIOCNXCL, IOC_, TYPE_NULL)
+IOCTL(TIOCFLUSH, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(TIOCGWINSZ, IOC_R, MK_PTR(MK_STRUCT(STRUCT_winsize)))
+IOCTL(TIOCSWINSZ, IOC_W, MK_PTR(MK_STRUCT(STRUCT_winsize)))
+IOCTL(TIOCCONS, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(TIOCMSET, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(TIOCMGET, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(TIOCMBIS, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(TIOCMBIC, IOC_W, MK_PTR(TYPE_INT))
+
+/* sys/filio.h */
+IOCTL(FIOCLEX, IOC_, TYPE_NULL)
+IOCTL(FIONCLEX, IOC_, TYPE_NULL)
+IOCTL(FIONREAD, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(FIONBIO, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(FIOASYNC, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(FIOSETOWN, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(FIOGETOWN, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(FIODTYPE, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(FIOGETLBA, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(FIODGNAME, IOC_R, MK_PTR(STRUCT_fiodgname_arg))
+IOCTL(FIONWRITE, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(FIONSPACE, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(FIOSEEKDATA, IOC_RW, MK_PTR(TYPE_ULONG))
+IOCTL(FIOSEEKHOLE, IOC_RW, MK_PTR(TYPE_ULONG))
diff --git a/bsd-user/freebsd/ioctl-filio.h b/bsd-user/freebsd/ioctl-filio.h
new file mode 100644
index 0000000..7e1aae9
--- /dev/null
+++ b/bsd-user/freebsd/ioctl-filio.h
@@ -0,0 +1,45 @@ 
+/*
+ *  FreeBSD filio definitions for ioctl(2) emulation
+ *
+ *  Copyright (c) 2013 Stacey D. Son
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _IOCTL_FILIO_H_
+#define _IOCTL_FILIO_H_
+
+/* see sys/filio.h */
+#define TARGET_FIOCLEX      TARGET_IO('f', 1)
+#define TARGET_FIONCLEX     TARGET_IO('f', 2)
+#define TARGET_FIONREAD     TARGET_IOR('f', 127, int)
+#define TARGET_FIONBIO      TARGET_IOW('f', 126, int)
+#define TARGET_FIOASYNC     TARGET_IOW('f', 125, int)
+#define TARGET_FIOSETOWN    TARGET_IOW('f', 124, int)
+#define TARGET_FIOGETOWN    TARGET_IOR('f', 123, int)
+#define TARGET_FIODTYPE     TARGET_IOR('f', 122, int)
+#define TARGET_FIOGETLBA    TARGET_IOR('f', 121, int)
+
+struct target_fiodgname_arg {
+    int32_t     len;
+    abi_ulong   buf;
+};
+
+#define TARGET_FIODGNAME    TARGET_IOW('f', 120,    \
+                struct target_fiodgname_arg)
+#define TARGET_FIONWRITE    TARGET_IOR('f', 119, int)
+#define TARGET_FIONSPACE    TARGET_IOR('f', 118, int)
+#define TARGET_FIOSEEKDATA  TARGET_IOWR('f', 97, off_t)
+#define TARGET_FIOSEEKHOLE  TARGET_IOWR('f', 98, off_t)
+
+#endif /* !_IOCTL_FILIO_H_ */
diff --git a/bsd-user/freebsd/ioctl-ioccom.h b/bsd-user/freebsd/ioctl-ioccom.h
new file mode 100644
index 0000000..fb9456f
--- /dev/null
+++ b/bsd-user/freebsd/ioctl-ioccom.h
@@ -0,0 +1,54 @@ 
+/*
+ *  FreeBSD ioccom definitions for ioctl(2) emulation
+ *
+ *  Copyright (c) 2013 Stacey D. Son
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _IOCTL_IOCCOM_H_
+#define _IOCTL_IOCCOM_H_
+/*
+ * Ioctl's have the command encoded in the lower word, and the size of
+ * any in or out parameters in the upper word.  The high 3 bits of the
+ * upper word are used to encode the in/out status of the parameter.
+ */
+/* number of bits for ioctl size */
+#define TARGET_IOCPARM_SHIFT    13
+
+/* parameter length mask */
+#define TARGET_IOCPARM_MASK ((1 << TARGET_IOCPARM_SHIFT) - 1)
+
+#define TARGET_IOCPARM_LEN(x)   (((x) >> 16) & TARGET_IOCPARM_MASK)
+#define TARGET_IOCBASECMD(x)    ((x) & ~(TARGET_IOCPARM_MASK << 16))
+#define TARGET_IOCGROUP(x)  (((x) >> 8) & 0xff)
+
+#define TARGET_IOCPARM_MAX  (1 << TARGET_IOCPARM_SHIFT) /* max size of ioctl */
+#define TARGET_IOC_VOID     0x20000000  /* no parameters */
+#define TARGET_IOC_OUT      0x40000000  /* copy out parameters */
+#define TARGET_IOC_IN       0x80000000  /* copy in parameters */
+#define TARGET_IOC_INOUT    (TARGET_IOC_IN|TARGET_IOC_OUT)
+#define TARGET_IOC_DIRMASK  (TARGET_IOC_VOID|TARGET_IOC_OUT|TARGET_IOC_IN)
+
+#define TARGET_IOC(inout, group, num, len) ((abi_ulong) \
+    ((inout) | (((len) & TARGET_IOCPARM_MASK) << 16) | ((group) << 8) \
+     | (num)))
+#define TARGET_IO(g, n)       TARGET_IOC(IOC_VOID,    (g), (n), 0)
+#define TARGET_IOWINT(g, n)   TARGET_IOC(IOC_VOID,    (g), (n), sizeof(int))
+#define TARGET_IOR(g, n, t)   TARGET_IOC(IOC_OUT, (g), (n), sizeof(t))
+#define TARGET_IOW(g, n, t)   TARGET_IOC(IOC_IN,  (g), (n), sizeof(t))
+/* this should be _IORW, but stdio got there first */
+#define TARGET_IOWR(g, n, t)  TARGET_IOC(IOC_INOUT,   (g), (n), sizeof(t))
+
+#endif /* !_IOCTL_IOCCOM_H_ */
diff --git a/bsd-user/freebsd/ioctl-ttycom.h b/bsd-user/freebsd/ioctl-ttycom.h
new file mode 100644
index 0000000..49affc2
--- /dev/null
+++ b/bsd-user/freebsd/ioctl-ttycom.h
@@ -0,0 +1,257 @@ 
+/*
+ *  FreeBSD ttycom definitions for ioctl(2) emulation
+ *
+ *  Copyright (c) 2013 Stacey D. Son
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _IOCTL_TTYCOM_H_
+#define _IOCTL_TTYCOM_H_
+
+#include "ioctl-ioccom.h"
+
+/* From sys/ttycom.h and sys/_termios.h */
+
+#define TARGET_VEOF     0   /* ICANON */
+#define TARGET_VEOL     1   /* ICANON */
+#define TARGET_VEOL2    2   /* ICANON together with IEXTEN */
+#define TARGET_VERASE   3   /* ICANON */
+#define TARGET_VWERASE  4   /* ICANON together with IEXTEN */
+#define TARGET_VKILL    5   /* ICANON */
+#define TARGET_VREPRINT 6   /* ICANON together with IEXTEN */
+#define TARGET_VERASE2  7   /* ICANON */
+#define TARGET_VINTR    8   /* ISIG */
+#define TARGET_VQUIT    9   /* ISIG */
+#define TARGET_VSUSP    10  /* ISIG */
+#define TARGET_VDSUSP   11  /* ISIG together with IEXTEN */
+#define TARGET_VSTART   12  /* IXON, IXOFF */
+#define TARGET_VSTOP    13  /* IXON, IXOFF */
+#define TARGET_VLNEXT   14  /* IEXTEN */
+#define TARGET_VDISCARD 15  /* IEXTEN */
+#define TARGET_VMIN     16  /* !ICANON */
+#define TARGET_VTIME    17  /* !ICANON */
+#define TARGET_VSTATUS  18  /* ICANON together with IEXTEN */
+/*                      19         spare 2 */
+#define TARGET_NCCS     20
+
+/*
+ * Input flags - software input processing
+ */
+#define TARGET_IGNBRK   0x00000001  /* ignore BREAK condition */
+#define TARGET_BRKINT   0x00000002  /* map BREAK to SIGINTR */
+#define TARGET_IGNPAR   0x00000004  /* ignore (discard) parity errors */
+#define TARGET_PARMRK   0x00000008  /* mark parity and framing errors */
+#define TARGET_INPCK    0x00000010  /* enable checking of parity errors */
+#define TARGET_ISTRIP   0x00000020  /* strip 8th bit off chars */
+#define TARGET_INLCR    0x00000040  /* map NL into CR */
+#define TARGET_IGNCR    0x00000080  /* ignore CR */
+#define TARGET_ICRNL    0x00000100  /* map CR to NL (ala CRMOD) */
+#define TARGET_IXON     0x00000200  /* enable output flow control */
+#define TARGET_IXOFF    0x00000400  /* enable input flow control */
+#define TARGET_IXANY    0x00000800  /* any char will restart after stop */
+#define TARGET_IMAXBEL  0x00002000  /* ring bell on input queue full */
+
+/*
+ * Output flags - software output processing
+ */
+#define TARGET_OPOST    0x00000001  /* enable following output processing */
+#define TARGET_ONLCR    0x00000002  /* map NL to CR-NL (ala CRMOD) */
+#define TARGET_TABDLY   0x00000004  /* tab delay mask */
+#define TARGET_TAB0     0x00000000  /* no tab delay and expansion */
+#define TARGET_TAB3     0x00000004  /* expand tabs to spaces */
+#define TARGET_ONOEOT   0x00000008  /* discard EOT's (^D) on output) */
+#define TARGET_OCRNL    0x00000010  /* map CR to NL on output */
+#define TARGET_ONOCR    0x00000020  /* no CR output at column 0 */
+#define TARGET_ONLRET   0x00000040  /* NL performs CR function */
+
+/*
+ * Control flags - hardware control of terminal
+ */
+#define TARGET_CIGNORE      0x00000001  /* ignore control flags */
+#define TARGET_CSIZE        0x00000300  /* character size mask */
+#define     TARGET_CS5      0x00000000  /* 5 bits (pseudo) */
+#define     TARGET_CS6      0x00000100  /* 6 bits */
+#define     TARGET_CS7      0x00000200  /* 7 bits */
+#define     TARGET_CS8      0x00000300  /* 8 bits */
+#define TARGET_CSTOPB       0x00000400  /* send 2 stop bits */
+#define TARGET_CREAD        0x00000800  /* enable receiver */
+#define TARGET_PARENB       0x00001000  /* parity enable */
+#define TARGET_PARODD       0x00002000  /* odd parity, else even */
+#define TARGET_HUPCL        0x00004000  /* hang up on last close */
+#define TARGET_CLOCAL       0x00008000  /* ignore modem status lines */
+#define TARGET_CCTS_OFLOW   0x00010000  /* CTS flow control of output */
+#define TARGET_CRTSCTS      (TARGET_CCTS_OFLOW | TARGET_CRTS_IFLOW)
+#define TARGET_CRTS_IFLOW   0x00020000  /* RTS flow control of input */
+#define TARGET_CDTR_IFLOW   0x00040000  /* DTR flow control of input */
+#define TARGET_CDSR_OFLOW   0x00080000  /* DSR flow control of output */
+#define TARGET_CCAR_OFLOW   0x00100000  /* DCD flow control of output */
+
+/*
+ * "Local" flags - dumping ground for other state
+ */
+#define TARGET_ECHOKE   0x00000001  /* visual erase for line kill */
+#define TARGET_ECHOE    0x00000002  /* visually erase chars */
+#define TARGET_ECHOK    0x00000004  /* echo NL after line kill */
+#define TARGET_ECHO 0x00000008  /* enable echoing */
+#define TARGET_ECHONL   0x00000010  /* echo NL even if ECHO is off */
+#define TARGET_ECHOPRT  0x00000020  /* visual erase mode for hardcopy */
+#define TARGET_ECHOCTL  0x00000040  /* echo control chars as ^(Char) */
+#define TARGET_ISIG 0x00000080  /* enable signals INTR, QUIT, [D]SUSP */
+#define TARGET_ICANON   0x00000100  /* canonicalize input lines */
+#define TARGET_ALTWERASE 0x00000200 /* use alternate WERASE algorithm */
+#define TARGET_IEXTEN   0x00000400  /* enable DISCARD and LNEXT */
+#define TARGET_EXTPROC  0x00000800  /* external processing */
+#define TARGET_TOSTOP   0x00400000  /* stop background jobs from output */
+#define TARGET_FLUSHO   0x00800000  /* output being flushed (state) */
+#define TARGET_NOKERNINFO 0x02000000    /* no kernel output from VSTATUS */
+#define TARGET_PENDIN   0x20000000  /* XXX retype pending input (state) */
+#define TARGET_NOFLSH   0x80000000  /* don't flush after interrupt */
+
+struct target_termios {
+    uint32_t c_iflag;   /* input flags */
+    uint32_t c_oflag;   /* output flags */
+    uint32_t c_cflag;   /* control flags */
+    uint32_t c_lflag;   /* local flags */
+    uint8_t  c_cc[TARGET_NCCS]; /* control chars */
+    uint32_t c_ispeed;  /* input speed */
+    uint32_t c_ospeed;  /* output speed */
+};
+
+
+struct target_winsize {
+    uint16_t ws_row;    /* rows, in characters */
+    uint16_t ws_col;    /* columns, in characters */
+    uint16_t ws_xpixel; /* horizontal size, pixels */
+    uint16_t ws_ypixel; /* vertical size, pixels */
+};
+
+                        /* 0-2 compat */
+                        /* 3-7 unused */
+                        /* 8-10 compat */
+                        /* 11-12 unused */
+#define TARGET_TIOCEXCL  TARGET_IO('t', 13) /* set exclusive use of tty */
+#define TARGET_TIOCNXCL  TARGET_IO('t', 14) /* reset exclusive use of tty */
+#define TARGET_TIOCGPTN  TARGET_IOR('t', 15, int) /* Get pts number. */
+#define TARGET_TIOCFLUSH TARGET_IOW('t', 16, int) /* flush buffers */
+                    /* 17-18 compat */
+/* get termios struct */
+#define TARGET_TIOCGETA TARGET_IOR('t', 19, struct target_termios)
+/* set termios struct */
+#define TARGET_TIOCSETA TARGET_IOW('t', 20, struct target_termios)
+/* drain output, set */
+#define TARGET_TIOCSETAW    TARGET_IOW('t', 21, struct target_termios)
+/* drn out, fls in, set */
+#define TARGET_TIOCSETAF    TARGET_IOW('t', 22, struct target_termios)
+                        /* 23-25 unused */
+#define TARGET_TIOCGETD TARGET_IOR('t', 26, int) /* get line discipline */
+#define TARGET_TIOCSETD TARGET_IOW('t', 27, int) /* set line discipline */
+#define TARGET_TIOCPTMASTER  TARGET_IO('t', 28) /* pts master validation */
+                    /* 29-85 unused */
+/* get ttywait timeout */
+#define TARGET_TIOCGDRAINWAIT   TARGET_IOR('t', 86, int)
+/* set ttywait timeout */
+#define TARGET_TIOCSDRAINWAIT   TARGET_IOW('t', 87, int)
+                    /* 88 unused */
+                    /* 89-91 conflicts: tun and tap */
+/* enable/get timestamp of last input event */
+#define TARGET_TIOCTIMESTAMP    TARGET_IOR('t', 89, struct target_timeval)
+/* modem: get wait on close */
+#define TARGET_TIOCMGDTRWAIT    TARGET_IOR('t', 90, int)
+/* modem: set wait on close */
+#define TARGET_TIOCMSDTRWAIT    TARGET_IOW('t', 91, int)
+                    /* 92-93 tun and tap */
+                    /* 94-97 conflicts: tun and tap */
+/* wait till output drained */
+#define TARGET_TIOCDRAIN     TARGET_IO('t', 94)
+ /* pty: generate signal */
+#define TARGET_TIOCSIG      TARGET_IOWINT('t', 95)
+/* pty: external processing */
+#define TARGET_TIOCEXT      TARGET_IOW('t', 96, int)
+/* become controlling tty */
+#define TARGET_TIOCSCTTY     TARGET_IO('t', 97)
+/* become virtual console */
+#define TARGET_TIOCCONS TARGET_IOW('t', 98, int)
+/* get session id */
+#define TARGET_TIOCGSID TARGET_IOR('t', 99, int)
+                        /* 100 unused */
+/* simulate ^T status message */
+#define TARGET_TIOCSTAT  TARGET_IO('t', 101)
+ /* pty: set/clr usr cntl mode */
+#define TARGET_TIOCUCNTL    TARGET_IOW('t', 102, int)
+/* usr cntl op "n" */
+#define TARGET_TIOCCMD(n)   TARGET_IO('u', n)
+/* set window size */
+#define TARGET_TIOCSWINSZ   TARGET_IOW('t', 103, struct target_winsize)
+/* get window size */
+#define TARGET_TIOCGWINSZ   TARGET_IOR('t', 104, struct target_winsize)
+                        /* 105 unused */
+/* get all modem bits */
+#define TARGET_TIOCMGET TARGET_IOR('t', 106, int)
+#define     TARGET_TIOCM_LE 0001        /* line enable */
+#define     TARGET_TIOCM_DTR    0002    /* data terminal ready */
+#define     TARGET_TIOCM_RTS    0004    /* request to send */
+#define     TARGET_TIOCM_ST 0010        /* secondary transmit */
+#define     TARGET_TIOCM_SR 0020        /* secondary receive */
+#define     TARGET_TIOCM_CTS    0040    /* clear to send */
+#define     TARGET_TIOCM_DCD    0100    /* data carrier detect */
+#define     TARGET_TIOCM_RI     0200    /* ring indicate */
+#define     TARGET_TIOCM_DSR    0400    /* data set ready */
+#define     TARGET_TIOCM_CD TARGET_TIOCM_DCD
+#define     TARGET_TIOCM_CAR    TARGET_TIOCM_DCD
+#define     TARGET_TIOCM_RNG    TARGET_TIOCM_RI
+#define TARGET_TIOCMBIC TARGET_IOW('t', 107, int) /* bic modem bits */
+#define TARGET_TIOCMBIS TARGET_IOW('t', 108, int) /* bis modem bits */
+#define TARGET_TIOCMSET TARGET_IOW('t', 109, int) /* set all modem bits */
+/* start output, like ^Q */
+#define TARGET_TIOCSTART     TARGET_IO('t', 110)
+/* stop output, like ^S */
+#define TARGET_TIOCSTOP  TARGET_IO('t', 111)
+/* pty: set/clear packet mode */
+#define TARGET_TIOCPKT      TARGET_IOW('t', 112, int)
+#define     TARGET_TIOCPKT_DATA     0x00    /* data packet */
+#define     TARGET_TIOCPKT_FLUSHREAD    0x01    /* flush packet */
+#define     TARGET_TIOCPKT_FLUSHWRITE   0x02    /* flush packet */
+#define     TARGET_TIOCPKT_STOP     0x04    /* stop output */
+#define     TARGET_TIOCPKT_START        0x08    /* start output */
+#define     TARGET_TIOCPKT_NOSTOP       0x10    /* no more ^S, ^Q */
+#define     TARGET_TIOCPKT_DOSTOP       0x20    /* now do ^S ^Q */
+#define     TARGET_TIOCPKT_IOCTL        0x40    /* state change of pty
+                               driver */
+#define TARGET_TIOCNOTTY     TARGET_IO('t', 113)    /* void tty
+                               association */
+#define TARGET_TIOCSTI      TARGET_IOW('t', 114, char)  /* simulate
+                            terminal input */
+#define TARGET_TIOCOUTQ TARGET_IOR('t', 115, int)   /* output queue size */
+                        /* 116-117 compat */
+#define TARGET_TIOCSPGRP    TARGET_IOW('t', 118, int) /* set pgrp of tty */
+#define TARGET_TIOCGPGRP    TARGET_IOR('t', 119, int) /* get pgrp of tty */
+#define TARGET_TIOCCDTR  TARGET_IO('t', 120)        /* clear data terminal
+                               ready */
+#define TARGET_TIOCSDTR  TARGET_IO('t', 121)        /* set data terminal
+                               ready */
+#define TARGET_TIOCCBRK  TARGET_IO('t', 122)        /* clear break bit */
+#define TARGET_TIOCSBRK  TARGET_IO('t', 123)        /* set break bit */
+                        /* 124-127 compat */
+
+#define TARGET_TTYDISC      0       /* termios tty line
+                           discipline */
+#define TARGET_SLIPDISC     4       /* serial IP discipline */
+#define TARGET_PPPDISC      5       /* PPP discipline */
+#define TARGET_NETGRAPHDISC 6       /* Netgraph tty node
+                           discipline */
+#define TARGET_H4DISC       7       /* Netgraph Bluetooth H4
+                           discipline */
+
+#endif /*! _IOCTL_TTYCOM_H_ */
diff --git a/bsd-user/freebsd/ioctl-types.h b/bsd-user/freebsd/ioctl-types.h
new file mode 100644
index 0000000..60b9288
--- /dev/null
+++ b/bsd-user/freebsd/ioctl-types.h
@@ -0,0 +1,7 @@ 
+
+STRUCT_SPECIAL(termios)
+
+STRUCT(winsize, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT)
+
+STRUCT(fiodgname_arg, TYPE_INT, TYPE_PTRVOID)
+
diff --git a/bsd-user/ioctl.c b/bsd-user/ioctl.c
new file mode 100644
index 0000000..5168098
--- /dev/null
+++ b/bsd-user/ioctl.c
@@ -0,0 +1,447 @@ 
+/*
+ *  BSD ioctl(2) emulation
+ *
+ *  Copyright (c) 2013 Stacey D. Son
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
+#include <sys/_termios.h>
+#else
+#include <sys/termios.h>
+#endif
+#include <sys/ttycom.h>
+#include <sys/filio.h>
+
+#include "qemu.h"
+#include "qemu-common.h"
+
+#include "ioctl-filio.h"
+#include "ioctl-ttycom.h"
+
+static const bitmask_transtbl iflag_tbl[] = {
+    { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
+    { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
+    { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
+    { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
+    { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
+    { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
+    { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
+    { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
+    { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
+    { TARGET_IXON, TARGET_IXON, IXON, IXON },
+    { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
+#ifdef IXANY
+    { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
+#endif
+#ifdef IMAXBEL
+    { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
+#endif
+    { 0, 0, 0, 0 }
+};
+
+static const bitmask_transtbl oflag_tbl[] = {
+    { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
+#ifdef ONLCR
+    { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
+#endif
+#ifdef TABDLY
+    { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
+    { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
+#endif
+#ifdef ONOEOT
+    { TARGET_ONOEOT, TARGET_ONOEOT, ONOEOT, ONOEOT },
+#endif
+#ifdef OCRNL
+    { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
+#endif
+#ifdef ONOCR
+    { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
+#endif
+#ifdef ONLRET
+    { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
+#endif
+    { 0, 0, 0, 0 }
+};
+
+static const bitmask_transtbl cflag_tbl[] = {
+#ifdef CIGNORE
+    { TARGET_CIGNORE, TARGET_CIGNORE, CIGNORE, CIGNORE },
+#endif
+    { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
+    { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
+    { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
+    { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
+    { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
+    { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
+    { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
+    { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
+    { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
+    { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
+#ifdef CCTS_OFLOW
+    { TARGET_CCTS_OFLOW, TARGET_CCTS_OFLOW, CCTS_OFLOW, CCTS_OFLOW },
+#endif
+#ifdef CRTSCTS
+    { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
+#endif
+#ifdef CRTS_IFLOW
+    { TARGET_CRTS_IFLOW, TARGET_CRTS_IFLOW, CRTS_IFLOW, CRTS_IFLOW },
+#endif
+#ifdef CDTS_IFLOW
+    { TARGET_CDTR_IFLOW, TARGET_CDTR_IFLOW, CDTR_IFLOW, CDTR_IFLOW },
+#endif
+#ifdef CDSR_OFLOW
+    { TARGET_CDSR_OFLOW, TARGET_CDSR_OFLOW, CDSR_OFLOW, CDSR_OFLOW },
+#endif
+#ifdef CCAR_OFLOW
+    { TARGET_CCAR_OFLOW, TARGET_CCAR_OFLOW, CCAR_OFLOW, CCAR_OFLOW },
+#endif
+    { 0, 0, 0, 0 }
+};
+
+static const bitmask_transtbl lflag_tbl[] = {
+#ifdef ECHOKE
+    { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
+#endif
+    { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
+    { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
+    { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
+    { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
+#ifdef ECHOPRT
+    { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
+#endif
+#ifdef ECHOCTL
+    { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
+#endif
+    { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
+    { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
+#ifdef ALTWERASE
+    { TARGET_ALTWERASE, TARGET_ALTWERASE, ALTWERASE, ALTWERASE },
+#endif
+    { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
+    { TARGET_EXTPROC, TARGET_EXTPROC, EXTPROC, EXTPROC },
+    { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
+#ifdef FLUSHO
+    { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
+#endif
+#ifdef NOKERNINFO
+    { TARGET_NOKERNINFO, TARGET_NOKERNINFO, NOKERNINFO, NOKERNINFO },
+#endif
+#ifdef PENDIN
+    { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
+#endif
+    { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
+    { 0, 0, 0, 0 }
+};
+
+static void target_to_host_termios(void *dst, const void *src)
+{
+    struct termios *host = dst;
+    const struct target_termios *target = src;
+
+    host->c_iflag = target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
+    host->c_oflag = target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
+    host->c_cflag = target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
+    host->c_lflag = target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
+
+    memset(host->c_cc, 0, sizeof(host->c_cc));
+    host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
+    host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
+#ifdef VEOL2
+    host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
+#endif
+    host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
+#ifdef VWERASE
+    host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
+#endif
+    host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
+#ifdef VREPRINT
+    host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
+#endif
+#ifdef VERASE2
+    host->c_cc[VERASE2] = target->c_cc[TARGET_VERASE2];
+#endif
+    host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
+    host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
+    host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
+#ifdef VDSUSP
+    host->c_cc[VDSUSP] = target->c_cc[TARGET_VDSUSP];
+#endif
+    host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
+    host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
+#ifdef VLNEXT
+    host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
+#endif
+#ifdef VDISCARD
+    host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
+#endif
+    host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
+    host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
+#ifdef VSTATUS
+    host->c_cc[VSTATUS] = target->c_cc[TARGET_VSTATUS];
+#endif
+
+    host->c_ispeed = tswap32(target->c_ispeed);
+    host->c_ospeed = tswap32(target->c_ospeed);
+}
+
+static void host_to_target_termios(void *dst, const void *src)
+{
+    struct target_termios *target = dst;
+    const struct termios *host = src;
+
+    target->c_iflag = tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
+    target->c_oflag = tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
+    target->c_cflag = tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
+    target->c_lflag = tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
+
+    memset(target->c_cc, 0, sizeof(target->c_cc));
+    target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
+    target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
+#ifdef VEOL2
+    target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
+#endif
+    target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
+#ifdef VWERASE
+    target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
+#endif
+    target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
+#ifdef VREPRINT
+    target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
+#endif
+#ifdef VERASE2
+    target->c_cc[TARGET_VERASE2] = host->c_cc[VERASE2];
+#endif
+    target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
+    target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
+    target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
+#ifdef VDSUSP
+    target->c_cc[TARGET_VDSUSP] = host->c_cc[VDSUSP];
+#endif
+    target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
+    target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
+#ifdef VLNEXT
+    target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
+#endif
+#ifdef VDISCARD
+    target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
+#endif
+    target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
+    target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
+#ifdef VSTATUS
+    target->c_cc[TARGET_VSTATUS] = host->c_cc[VSTATUS];
+#endif
+
+    target->c_ispeed = tswap32(host->c_ispeed);
+    target->c_ospeed = tswap32(host->c_ospeed);
+}
+
+static const StructEntry struct_termios_def = {
+    .convert = { host_to_target_termios, target_to_host_termios },
+    .size = { sizeof(struct target_termios), sizeof(struct termios) },
+    .align = { __alignof__(struct target_termios),
+        __alignof__(struct termios) },
+};
+
+
+/* ioctl structure type definitions */
+#define STRUCT(name, ...) STRUCT_ ## name,
+#define STRUCT_SPECIAL(name) STRUCT_ ## name,
+enum {
+#include "ioctl-types.h"
+};
+#undef STRUCT
+#undef STRUCT_SPECIAL
+
+#define STRUCT(name, ...) \
+    static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
+#define STRUCT_SPECIAL(name)
+#include "ioctl-types.h"
+#undef STRUCT
+#undef STRUCT_SPECIAL
+
+
+struct IOCTLEntry;
+
+typedef abi_long do_ioctl_fn(const struct IOCTLEntry *ie, uint8_t *buf_temp,
+                int fd, abi_long cmd, abi_long arg);
+
+struct IOCTLEntry {
+    unsigned int target_cmd;
+    unsigned int host_cmd;
+    const char *name;
+    int access;
+    do_ioctl_fn *do_ioctl;
+    const argtype arg_type[5];
+};
+typedef struct IOCTLEntry IOCTLEntry;
+
+#define MAX_STRUCT_SIZE 4096
+
+static IOCTLEntry ioctl_entries[] = {
+#define IOC_    0x0000
+#define IOC_R   0x0001
+#define IOC_W   0x0002
+#define IOC_RW  (IOC_R | IOC_W)
+#define IOCTL(cmd, access, ...) \
+    { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
+#define IOCTL_SPECIAL(cmd, access, dofn, ...) \
+    { TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } },
+#include "ioctl-cmds.h"
+    { 0, 0 },
+};
+
+abi_long do_bsd_ioctl(int fd, abi_long cmd, abi_long arg)
+{
+    const IOCTLEntry *ie;
+    const argtype *arg_type;
+    abi_long ret;
+    uint8_t buf_temp[MAX_STRUCT_SIZE];
+    int target_size;
+    void *argptr;
+
+    ie = ioctl_entries;
+    for (;;) {
+        if (ie->target_cmd == 0) {
+            gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
+            return -TARGET_ENOSYS;
+        }
+        if (ie->target_cmd == cmd) {
+            break;
+        }
+        ie++;
+    }
+    arg_type = ie->arg_type;
+#if defined(DEBUG)
+    gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
+#endif
+    if (ie->do_ioctl) {
+        return ie->do_ioctl(ie, buf_temp, fd, cmd, arg);
+    }
+
+    switch (arg_type[0]) {
+    case TYPE_NULL:
+        /* no argument */
+        ret = get_errno(ioctl(fd, ie->host_cmd));
+        break;
+
+    case TYPE_PTRVOID:
+    case TYPE_INT:
+        /* int argument */
+        ret = get_errno(ioctl(fd, ie->host_cmd, arg));
+        break;
+
+    case TYPE_PTR:
+        arg_type++;
+        target_size = thunk_type_size(arg_type, 0);
+        switch (ie->access) {
+        case IOC_R:
+            ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
+            if (!is_error(ret)) {
+                argptr = lock_user(VERIFY_WRITE, arg,
+                    target_size, 0);
+                if (!argptr) {
+                    return -TARGET_EFAULT;
+                }
+                thunk_convert(argptr, buf_temp, arg_type,
+                    THUNK_TARGET);
+                unlock_user(argptr, arg, target_size);
+            }
+            break;
+
+        case IOC_W:
+            argptr = lock_user(VERIFY_READ, arg, target_size, 1);
+            if (!argptr) {
+                return -TARGET_EFAULT;
+            }
+            thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
+            unlock_user(argptr, arg, 0);
+            ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
+            break;
+
+        case IOC_RW:
+            /* fallthrough */
+        default:
+            argptr = lock_user(VERIFY_READ, arg, target_size, 1);
+            if (!argptr) {
+                return -TARGET_EFAULT;
+            }
+            thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
+            unlock_user(argptr, arg, 0);
+            ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
+            if (!is_error(ret)) {
+                argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
+                if (!argptr) {
+                    return -TARGET_EFAULT;
+                }
+                thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
+                unlock_user(argptr, arg, target_size);
+            }
+            break;
+        }
+        break;
+
+    default:
+        gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
+            (long)cmd, arg_type[0]);
+        ret = -TARGET_ENOSYS;
+        break;
+    }
+    return ret;
+}
+
+void ioctl_init(void)
+{
+    IOCTLEntry *ie;
+    const argtype *arg_type;
+    int size;
+
+#define STRUCT(name, ...) \
+ thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
+#define STRUCT_SPECIAL(name) \
+ thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
+#include "ioctl-types.h"
+#undef STRUCT
+#undef STRUCT_SPECIAL
+
+    /*
+     * Patch the ioctl size if necessary using the fact that no
+     * ioctl has all the bits at '1' in the size field
+     * (IOCPARM_MAX - 1).
+     */
+    ie = ioctl_entries;
+    while (ie->target_cmd != 0) {
+        if (((ie->target_cmd >> TARGET_IOCPARM_SHIFT) &
+                    TARGET_IOCPARM_MASK) == TARGET_IOCPARM_MASK) {
+            arg_type = ie->arg_type;
+            if (arg_type[0] != TYPE_PTR) {
+                fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
+                        ie->target_cmd);
+                exit(1);
+            }
+            arg_type++;
+            size = thunk_type_size(arg_type, 0);
+            ie->target_cmd = (ie->target_cmd &
+                    ~(TARGET_IOCPARM_MASK << TARGET_IOCPARM_SHIFT)) |
+                (size << TARGET_IOCPARM_SHIFT);
+        }
+        ie++;
+    }
+
+}
+
diff --git a/bsd-user/netbsd/ioctl-cmds.h b/bsd-user/netbsd/ioctl-cmds.h
new file mode 100644
index 0000000..12af33c
--- /dev/null
+++ b/bsd-user/netbsd/ioctl-cmds.h
@@ -0,0 +1,48 @@ 
+/* XXX should be fixed for NetBSD ioctl cmds */
+
+/* sys/ttycom.h tty(4) */
+IOCTL(TIOCSETD, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(TIOCGETD, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(TIOCSBRK, IOC_, TYPE_NULL)
+IOCTL(TIOCCBRK, IOC_, TYPE_NULL)
+IOCTL(TIOCSDTR, IOC_, TYPE_NULL)
+IOCTL(TIOCCDTR, IOC_, TYPE_NULL)
+IOCTL(TIOCGPGRP, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(TIOCSPGRP, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(TIOCGETA, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
+IOCTL(TIOCSETA, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
+IOCTL(TIOCSETAW, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
+IOCTL(TIOCSETAF, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
+IOCTL(TIOCOUTQ, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(TIOCSTI, IOC_W, MK_PTR(TYPE_CHAR))
+IOCTL(TIOCNOTTY, IOC_, TYPE_NULL)
+IOCTL(TIOCSTOP, IOC_, TYPE_NULL)
+IOCTL(TIOCSTART, IOC_, TYPE_NULL)
+IOCTL(TIOCSCTTY, IOC_, TYPE_NULL)
+IOCTL(TIOCDRAIN, IOC_, TYPE_NULL)
+IOCTL(TIOCEXCL, IOC_, TYPE_NULL)
+IOCTL(TIOCNXCL, IOC_, TYPE_NULL)
+IOCTL(TIOCFLUSH, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(TIOCGWINSZ, IOC_R, MK_PTR(MK_STRUCT(STRUCT_winsize)))
+IOCTL(TIOCSWINSZ, IOC_W, MK_PTR(MK_STRUCT(STRUCT_winsize)))
+IOCTL(TIOCCONS, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(TIOCMSET, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(TIOCMGET, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(TIOCMBIS, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(TIOCMBIC, IOC_W, MK_PTR(TYPE_INT))
+
+/* sys/filio.h */
+IOCTL(FIOCLEX, IOC_, TYPE_NULL)
+IOCTL(FIONCLEX, IOC_, TYPE_NULL)
+IOCTL(FIONREAD, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(FIONBIO, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(FIOASYNC, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(FIOSETOWN, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(FIOGETOWN, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(FIODTYPE, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(FIOGETLBA, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(FIODGNAME, IOC_R, MK_PTR(STRUCT_fiodgname_arg))
+IOCTL(FIONWRITE, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(FIONSPACE, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(FIOSEEKDATA, IOC_RW, MK_PTR(TYPE_ULONG))
+IOCTL(FIOSEEKHOLE, IOC_RW, MK_PTR(TYPE_ULONG))
diff --git a/bsd-user/netbsd/ioctl-filio.h b/bsd-user/netbsd/ioctl-filio.h
new file mode 100644
index 0000000..24b63ae
--- /dev/null
+++ b/bsd-user/netbsd/ioctl-filio.h
@@ -0,0 +1,29 @@ 
+#ifndef _IOCTL_FILIO_H_
+#define _IOCTL_FILIO_H_
+
+/* XXX needs to be fixed for NetBSD dependencies */
+
+/* see sys/filio.h */
+#define TARGET_FIOCLEX      TARGET_IO('f', 1)
+#define TARGET_FIONCLEX     TARGET_IO('f', 2)
+#define TARGET_FIONREAD     TARGET_IOR('f', 127, int)
+#define TARGET_FIONBIO      TARGET_IOW('f', 126, int)
+#define TARGET_FIOASYNC     TARGET_IOW('f', 125, int)
+#define TARGET_FIOSETOWN    TARGET_IOW('f', 124, int)
+#define TARGET_FIOGETOWN    TARGET_IOR('f', 123, int)
+#define TARGET_FIODTYPE     TARGET_IOR('f', 122, int)
+#define TARGET_FIOGETLBA    TARGET_IOR('f', 121, int)
+
+struct target_fiodgname_arg {
+    int32_t     len;
+    abi_ulong   buf;
+};
+
+#define TARGET_FIODGNAME    TARGET_IOW('f', 120,    \
+                struct target_fiodgname_arg)
+#define TARGET_FIONWRITE    TARGET_IOR('f', 119, int)
+#define TARGET_FIONSPACE    TARGET_IOR('f', 118, int)
+#define TARGET_FIOSEEKDATA  TARGET_IOWR('f', 97, off_t)
+#define TARGET_FIOSEEKHOLE  TARGET_IOWR('f', 98, off_t)
+
+#endif /* !_IOCTL_FILIO_H_ */
diff --git a/bsd-user/netbsd/ioctl-ioccom.h b/bsd-user/netbsd/ioctl-ioccom.h
new file mode 100644
index 0000000..e193a16
--- /dev/null
+++ b/bsd-user/netbsd/ioctl-ioccom.h
@@ -0,0 +1,38 @@ 
+#ifndef _IOCTL_IOCCOM_H_
+#define _IOCTL_IOCCOM_H_
+
+/* XXX needs to be fixed for NetBSD dependencies */
+
+/*
+ * Ioctl's have the command encoded in the lower word, and the size of
+ * any in or out parameters in the upper word.  The high 3 bits of the
+ * upper word are used to encode the in/out status of the parameter.
+ */
+/* number of bits for ioctl size */
+#define TARGET_IOCPARM_SHIFT    13
+
+/* parameter length mask */
+#define TARGET_IOCPARM_MASK ((1 << TARGET_IOCPARM_SHIFT) - 1)
+
+#define TARGET_IOCPARM_LEN(x)   (((x) >> 16) & TARGET_IOCPARM_MASK)
+#define TARGET_IOCBASECMD(x)    ((x) & ~(TARGET_IOCPARM_MASK << 16))
+#define TARGET_IOCGROUP(x)  (((x) >> 8) & 0xff)
+
+#define TARGET_IOCPARM_MAX  (1 << TARGET_IOCPARM_SHIFT) /* max size of ioctl */
+#define TARGET_IOC_VOID     0x20000000  /* no parameters */
+#define TARGET_IOC_OUT      0x40000000  /* copy out parameters */
+#define TARGET_IOC_IN       0x80000000  /* copy in parameters */
+#define TARGET_IOC_INOUT    (TARGET_IOC_IN|TARGET_IOC_OUT)
+#define TARGET_IOC_DIRMASK  (TARGET_IOC_VOID|TARGET_IOC_OUT|TARGET_IOC_IN)
+
+#define TARGET_IOC(inout, group, num, len) ((abi_ulong) \
+    ((inout) | (((len) & TARGET_IOCPARM_MASK) << 16) | ((group) << 8) \
+     | (num)))
+#define TARGET_IO(g, n)      TARGET_IOC(IOC_VOID,    (g), (n), 0)
+#define TARGET_IOWINT(g, n)  TARGET_IOC(IOC_VOID,    (g), (n), sizeof(int))
+#define TARGET_IOR(g, n, t)   TARGET_IOC(IOC_OUT, (g), (n), sizeof(t))
+#define TARGET_IOW(g, n, t)   TARGET_IOC(IOC_IN,  (g), (n), sizeof(t))
+/* this should be _IORW, but stdio got there first */
+#define TARGET_IOWR(g, n, t)  TARGET_IOC(IOC_INOUT,   (g), (n), sizeof(t))
+
+#endif /* !_IOCTL_IOCCOM_H_ */
diff --git a/bsd-user/netbsd/ioctl-ttycom.h b/bsd-user/netbsd/ioctl-ttycom.h
new file mode 100644
index 0000000..5a7bc22
--- /dev/null
+++ b/bsd-user/netbsd/ioctl-ttycom.h
@@ -0,0 +1,240 @@ 
+#ifndef _IOCTL_TTYCOM_H_
+#define _IOCTL_TTYCOM_H_
+
+/* XXX Needs to be fixed for NetBSD dependencies */
+
+#include "ioctl-ioccom.h"
+
+/* From sys/ttycom.h and sys/_termios.h */
+
+#define TARGET_VEOF     0   /* ICANON */
+#define TARGET_VEOL     1   /* ICANON */
+#define TARGET_VEOL2    2   /* ICANON together with IEXTEN */
+#define TARGET_VERASE   3   /* ICANON */
+#define TARGET_VWERASE  4   /* ICANON together with IEXTEN */
+#define TARGET_VKILL    5   /* ICANON */
+#define TARGET_VREPRINT 6   /* ICANON together with IEXTEN */
+#define TARGET_VERASE2  7   /* ICANON */
+#define TARGET_VINTR    8   /* ISIG */
+#define TARGET_VQUIT    9   /* ISIG */
+#define TARGET_VSUSP    10  /* ISIG */
+#define TARGET_VDSUSP   11  /* ISIG together with IEXTEN */
+#define TARGET_VSTART   12  /* IXON, IXOFF */
+#define TARGET_VSTOP    13  /* IXON, IXOFF */
+#define TARGET_VLNEXT   14  /* IEXTEN */
+#define TARGET_VDISCARD 15  /* IEXTEN */
+#define TARGET_VMIN     16  /* !ICANON */
+#define TARGET_VTIME    17  /* !ICANON */
+#define TARGET_VSTATUS  18  /* ICANON together with IEXTEN */
+/*                      19         spare 2 */
+#define TARGET_NCCS     20
+
+/*
+ * Input flags - software input processing
+ */
+#define TARGET_IGNBRK   0x00000001  /* ignore BREAK condition */
+#define TARGET_BRKINT   0x00000002  /* map BREAK to SIGINTR */
+#define TARGET_IGNPAR   0x00000004  /* ignore (discard) parity errors */
+#define TARGET_PARMRK   0x00000008  /* mark parity and framing errors */
+#define TARGET_INPCK    0x00000010  /* enable checking of parity errors */
+#define TARGET_ISTRIP   0x00000020  /* strip 8th bit off chars */
+#define TARGET_INLCR    0x00000040  /* map NL into CR */
+#define TARGET_IGNCR    0x00000080  /* ignore CR */
+#define TARGET_ICRNL    0x00000100  /* map CR to NL (ala CRMOD) */
+#define TARGET_IXON     0x00000200  /* enable output flow control */
+#define TARGET_IXOFF    0x00000400  /* enable input flow control */
+#define TARGET_IXANY    0x00000800  /* any char will restart after stop */
+#define TARGET_IMAXBEL  0x00002000  /* ring bell on input queue full */
+
+/*
+ * Output flags - software output processing
+ */
+#define TARGET_OPOST    0x00000001  /* enable following output processing */
+#define TARGET_ONLCR    0x00000002  /* map NL to CR-NL (ala CRMOD) */
+#define TARGET_TABDLY   0x00000004  /* tab delay mask */
+#define TARGET_TAB0     0x00000000  /* no tab delay and expansion */
+#define TARGET_TAB3     0x00000004  /* expand tabs to spaces */
+#define TARGET_ONOEOT   0x00000008  /* discard EOT's (^D) on output) */
+#define TARGET_OCRNL    0x00000010  /* map CR to NL on output */
+#define TARGET_ONOCR    0x00000020  /* no CR output at column 0 */
+#define TARGET_ONLRET   0x00000040  /* NL performs CR function */
+
+/*
+ * Control flags - hardware control of terminal
+ */
+#define TARGET_CIGNORE      0x00000001  /* ignore control flags */
+#define TARGET_CSIZE        0x00000300  /* character size mask */
+#define     TARGET_CS5      0x00000000  /* 5 bits (pseudo) */
+#define     TARGET_CS6      0x00000100  /* 6 bits */
+#define     TARGET_CS7      0x00000200  /* 7 bits */
+#define     TARGET_CS8      0x00000300  /* 8 bits */
+#define TARGET_CSTOPB       0x00000400  /* send 2 stop bits */
+#define TARGET_CREAD        0x00000800  /* enable receiver */
+#define TARGET_PARENB       0x00001000  /* parity enable */
+#define TARGET_PARODD       0x00002000  /* odd parity, else even */
+#define TARGET_HUPCL        0x00004000  /* hang up on last close */
+#define TARGET_CLOCAL       0x00008000  /* ignore modem status lines */
+#define TARGET_CCTS_OFLOW   0x00010000  /* CTS flow control of output */
+#define TARGET_CRTSCTS      (TARGET_CCTS_OFLOW | TARGET_CRTS_IFLOW)
+#define TARGET_CRTS_IFLOW   0x00020000  /* RTS flow control of input */
+#define TARGET_CDTR_IFLOW   0x00040000  /* DTR flow control of input */
+#define TARGET_CDSR_OFLOW   0x00080000  /* DSR flow control of output */
+#define TARGET_CCAR_OFLOW   0x00100000  /* DCD flow control of output */
+
+/*
+ * "Local" flags - dumping ground for other state
+ */
+#define TARGET_ECHOKE   0x00000001  /* visual erase for line kill */
+#define TARGET_ECHOE    0x00000002  /* visually erase chars */
+#define TARGET_ECHOK    0x00000004  /* echo NL after line kill */
+#define TARGET_ECHO 0x00000008  /* enable echoing */
+#define TARGET_ECHONL   0x00000010  /* echo NL even if ECHO is off */
+#define TARGET_ECHOPRT  0x00000020  /* visual erase mode for hardcopy */
+#define TARGET_ECHOCTL  0x00000040  /* echo control chars as ^(Char) */
+#define TARGET_ISIG 0x00000080  /* enable signals INTR, QUIT, [D]SUSP */
+#define TARGET_ICANON   0x00000100  /* canonicalize input lines */
+#define TARGET_ALTWERASE 0x00000200 /* use alternate WERASE algorithm */
+#define TARGET_IEXTEN   0x00000400  /* enable DISCARD and LNEXT */
+#define TARGET_EXTPROC  0x00000800  /* external processing */
+#define TARGET_TOSTOP   0x00400000  /* stop background jobs from output */
+#define TARGET_FLUSHO   0x00800000  /* output being flushed (state) */
+#define TARGET_NOKERNINFO 0x02000000    /* no kernel output from VSTATUS */
+#define TARGET_PENDIN   0x20000000  /* XXX retype pending input (state) */
+#define TARGET_NOFLSH   0x80000000  /* don't flush after interrupt */
+
+struct target_termios {
+    uint32_t c_iflag;   /* input flags */
+    uint32_t c_oflag;   /* output flags */
+    uint32_t c_cflag;   /* control flags */
+    uint32_t c_lflag;   /* local flags */
+    uint8_t  c_cc[TARGET_NCCS]; /* control chars */
+    uint32_t c_ispeed;  /* input speed */
+    uint32_t c_ospeed;  /* output speed */
+};
+
+
+struct target_winsize {
+    uint16_t ws_row;    /* rows, in characters */
+    uint16_t ws_col;    /* columns, in characters */
+    uint16_t ws_xpixel; /* horizontal size, pixels */
+    uint16_t ws_ypixel; /* vertical size, pixels */
+};
+
+                        /* 0-2 compat */
+                        /* 3-7 unused */
+                        /* 8-10 compat */
+                        /* 11-12 unused */
+#define TARGET_TIOCEXCL  TARGET_IO('t', 13) /* set exclusive use of tty */
+#define TARGET_TIOCNXCL  TARGET_IO('t', 14) /* reset exclusive use of tty */
+#define TARGET_TIOCGPTN  TARGET_IOR('t', 15, int) /* Get pts number. */
+#define TARGET_TIOCFLUSH TARGET_IOW('t', 16, int) /* flush buffers */
+                    /* 17-18 compat */
+/* get termios struct */
+#define TARGET_TIOCGETA TARGET_IOR('t', 19, struct target_termios)
+/* set termios struct */
+#define TARGET_TIOCSETA TARGET_IOW('t', 20, struct target_termios)
+/* drain output, set */
+#define TARGET_TIOCSETAW    TARGET_IOW('t', 21, struct target_termios)
+/* drn out, fls in, set */
+#define TARGET_TIOCSETAF    TARGET_IOW('t', 22, struct target_termios)
+                        /* 23-25 unused */
+#define TARGET_TIOCGETD TARGET_IOR('t', 26, int) /* get line discipline */
+#define TARGET_TIOCSETD TARGET_IOW('t', 27, int) /* set line discipline */
+#define TARGET_TIOCPTMASTER  TARGET_IO('t', 28) /* pts master validation */
+                    /* 29-85 unused */
+/* get ttywait timeout */
+#define TARGET_TIOCGDRAINWAIT   TARGET_IOR('t', 86, int)
+/* set ttywait timeout */
+#define TARGET_TIOCSDRAINWAIT   TARGET_IOW('t', 87, int)
+                    /* 88 unused */
+                    /* 89-91 conflicts: tun and tap */
+/* enable/get timestamp of last input event */
+#define TARGET_TIOCTIMESTAMP    TARGET_IOR('t', 89, struct target_timeval)
+/* modem: get wait on close */
+#define TARGET_TIOCMGDTRWAIT    TARGET_IOR('t', 90, int)
+/* modem: set wait on close */
+#define TARGET_TIOCMSDTRWAIT    TARGET_IOW('t', 91, int)
+                    /* 92-93 tun and tap */
+                    /* 94-97 conflicts: tun and tap */
+/* wait till output drained */
+#define TARGET_TIOCDRAIN     TARGET_IO('t', 94)
+ /* pty: generate signal */
+#define TARGET_TIOCSIG      TARGET_IOWINT('t', 95)
+/* pty: external processing */
+#define TARGET_TIOCEXT      TARGET_IOW('t', 96, int)
+/* become controlling tty */
+#define TARGET_TIOCSCTTY     TARGET_IO('t', 97)
+/* become virtual console */
+#define TARGET_TIOCCONS TARGET_IOW('t', 98, int)
+/* get session id */
+#define TARGET_TIOCGSID TARGET_IOR('t', 99, int)
+                        /* 100 unused */
+/* simulate ^T status message */
+#define TARGET_TIOCSTAT  TARGET_IO('t', 101)
+ /* pty: set/clr usr cntl mode */
+#define TARGET_TIOCUCNTL    TARGET_IOW('t', 102, int)
+/* usr cntl op "n" */
+#define TARGET_TIOCCMD(n)   TARGET_IO('u', n)
+/* set window size */
+#define TARGET_TIOCSWINSZ   TARGET_IOW('t', 103, struct target_winsize)
+/* get window size */
+#define TARGET_TIOCGWINSZ   TARGET_IOR('t', 104, struct target_winsize)
+                        /* 105 unused */
+/* get all modem bits */
+#define TARGET_TIOCMGET TARGET_IOR('t', 106, int)
+#define     TARGET_TIOCM_LE 0001        /* line enable */
+#define     TARGET_TIOCM_DTR    0002    /* data terminal ready */
+#define     TARGET_TIOCM_RTS    0004    /* request to send */
+#define     TARGET_TIOCM_ST 0010        /* secondary transmit */
+#define     TARGET_TIOCM_SR 0020        /* secondary receive */
+#define     TARGET_TIOCM_CTS    0040    /* clear to send */
+#define     TARGET_TIOCM_DCD    0100    /* data carrier detect */
+#define     TARGET_TIOCM_RI     0200    /* ring indicate */
+#define     TARGET_TIOCM_DSR    0400    /* data set ready */
+#define     TARGET_TIOCM_CD TARGET_TIOCM_DCD
+#define     TARGET_TIOCM_CAR    TARGET_TIOCM_DCD
+#define     TARGET_TIOCM_RNG    TARGET_TIOCM_RI
+#define TARGET_TIOCMBIC TARGET_IOW('t', 107, int) /* bic modem bits */
+#define TARGET_TIOCMBIS TARGET_IOW('t', 108, int) /* bis modem bits */
+#define TARGET_TIOCMSET TARGET_IOW('t', 109, int) /* set all modem bits */
+/* start output, like ^Q */
+#define TARGET_TIOCSTART     TARGET_IO('t', 110)
+/* stop output, like ^S */
+#define TARGET_TIOCSTOP  TARGET_IO('t', 111)
+/* pty: set/clear packet mode */
+#define TARGET_TIOCPKT      TARGET_IOW('t', 112, int)
+#define     TARGET_TIOCPKT_DATA     0x00    /* data packet */
+#define     TARGET_TIOCPKT_FLUSHREAD    0x01    /* flush packet */
+#define     TARGET_TIOCPKT_FLUSHWRITE   0x02    /* flush packet */
+#define     TARGET_TIOCPKT_STOP     0x04    /* stop output */
+#define     TARGET_TIOCPKT_START        0x08    /* start output */
+#define     TARGET_TIOCPKT_NOSTOP       0x10    /* no more ^S, ^Q */
+#define     TARGET_TIOCPKT_DOSTOP       0x20    /* now do ^S ^Q */
+#define     TARGET_TIOCPKT_IOCTL        0x40    /* state change of pty
+                               driver */
+#define TARGET_TIOCNOTTY     TARGET_IO('t', 113)    /* void tty
+                               association */
+#define TARGET_TIOCSTI      TARGET_IOW('t', 114, char)  /* simulate
+                            terminal input */
+#define TARGET_TIOCOUTQ TARGET_IOR('t', 115, int)   /* output queue size */
+                        /* 116-117 compat */
+#define TARGET_TIOCSPGRP    TARGET_IOW('t', 118, int) /* set pgrp of tty */
+#define TARGET_TIOCGPGRP    TARGET_IOR('t', 119, int) /* get pgrp of tty */
+#define TARGET_TIOCCDTR  TARGET_IO('t', 120)        /* clear data terminal
+                               ready */
+#define TARGET_TIOCSDTR  TARGET_IO('t', 121)        /* set data terminal
+                               ready */
+#define TARGET_TIOCCBRK  TARGET_IO('t', 122)        /* clear break bit */
+#define TARGET_TIOCSBRK  TARGET_IO('t', 123)        /* set break bit */
+                        /* 124-127 compat */
+
+#define TARGET_TTYDISC      0       /* termios tty line
+                           discipline */
+#define TARGET_SLIPDISC     4       /* serial IP discipline */
+#define TARGET_PPPDISC      5       /* PPP discipline */
+#define TARGET_NETGRAPHDISC 6       /* Netgraph tty node
+                           discipline */
+#define TARGET_H4DISC       7       /* Netgraph Bluetooth H4
+                           discipline */
+
+#endif /*! _IOCTL_TTYCOM_H_ */
diff --git a/bsd-user/netbsd/ioctl-types.h b/bsd-user/netbsd/ioctl-types.h
new file mode 100644
index 0000000..e761c20
--- /dev/null
+++ b/bsd-user/netbsd/ioctl-types.h
@@ -0,0 +1,7 @@ 
+/* XXX should be fixed for NetBSD types and structs */
+STRUCT_SPECIAL(termios)
+
+STRUCT(winsize, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT)
+
+STRUCT(fiodgname_arg, TYPE_INT, TYPE_PTRVOID)
+
diff --git a/bsd-user/openbsd/ioctl-cmds.h b/bsd-user/openbsd/ioctl-cmds.h
new file mode 100644
index 0000000..a15f056
--- /dev/null
+++ b/bsd-user/openbsd/ioctl-cmds.h
@@ -0,0 +1,48 @@ 
+/* XXX should be fixed for OpenBSD ioctl cmds */
+
+/* sys/ttycom.h tty(4) */
+IOCTL(TIOCSETD, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(TIOCGETD, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(TIOCSBRK, IOC_, TYPE_NULL)
+IOCTL(TIOCCBRK, IOC_, TYPE_NULL)
+IOCTL(TIOCSDTR, IOC_, TYPE_NULL)
+IOCTL(TIOCCDTR, IOC_, TYPE_NULL)
+IOCTL(TIOCGPGRP, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(TIOCSPGRP, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(TIOCGETA, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
+IOCTL(TIOCSETA, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
+IOCTL(TIOCSETAW, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
+IOCTL(TIOCSETAF, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
+IOCTL(TIOCOUTQ, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(TIOCSTI, IOC_W, MK_PTR(TYPE_CHAR))
+IOCTL(TIOCNOTTY, IOC_, TYPE_NULL)
+IOCTL(TIOCSTOP, IOC_, TYPE_NULL)
+IOCTL(TIOCSTART, IOC_, TYPE_NULL)
+IOCTL(TIOCSCTTY, IOC_, TYPE_NULL)
+IOCTL(TIOCDRAIN, IOC_, TYPE_NULL)
+IOCTL(TIOCEXCL, IOC_, TYPE_NULL)
+IOCTL(TIOCNXCL, IOC_, TYPE_NULL)
+IOCTL(TIOCFLUSH, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(TIOCGWINSZ, IOC_R, MK_PTR(MK_STRUCT(STRUCT_winsize)))
+IOCTL(TIOCSWINSZ, IOC_W, MK_PTR(MK_STRUCT(STRUCT_winsize)))
+IOCTL(TIOCCONS, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(TIOCMSET, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(TIOCMGET, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(TIOCMBIS, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(TIOCMBIC, IOC_W, MK_PTR(TYPE_INT))
+
+/* sys/filio.h */
+IOCTL(FIOCLEX, IOC_, TYPE_NULL)
+IOCTL(FIONCLEX, IOC_, TYPE_NULL)
+IOCTL(FIONREAD, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(FIONBIO, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(FIOASYNC, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(FIOSETOWN, IOC_W, MK_PTR(TYPE_INT))
+IOCTL(FIOGETOWN, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(FIODTYPE, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(FIOGETLBA, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(FIODGNAME, IOC_R, MK_PTR(STRUCT_fiodgname_arg))
+IOCTL(FIONWRITE, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(FIONSPACE, IOC_R, MK_PTR(TYPE_INT))
+IOCTL(FIOSEEKDATA, IOC_RW, MK_PTR(TYPE_ULONG))
+IOCTL(FIOSEEKHOLE, IOC_RW, MK_PTR(TYPE_ULONG))
diff --git a/bsd-user/openbsd/ioctl-filio.h b/bsd-user/openbsd/ioctl-filio.h
new file mode 100644
index 0000000..e3f7474
--- /dev/null
+++ b/bsd-user/openbsd/ioctl-filio.h
@@ -0,0 +1,29 @@ 
+#ifndef _IOCTL_FILIO_H_
+#define _IOCTL_FILIO_H_
+
+/* XXX needs to be fixed for OpenBSD dependencies */
+
+/* see sys/filio.h */
+#define TARGET_FIOCLEX      TARGET_IO('f', 1)
+#define TARGET_FIONCLEX     TARGET_IO('f', 2)
+#define TARGET_FIONREAD     TARGET_IOR('f', 127, int)
+#define TARGET_FIONBIO      TARGET_IOW('f', 126, int)
+#define TARGET_FIOASYNC     TARGET_IOW('f', 125, int)
+#define TARGET_FIOSETOWN    TARGET_IOW('f', 124, int)
+#define TARGET_FIOGETOWN    TARGET_IOR('f', 123, int)
+#define TARGET_FIODTYPE     TARGET_IOR('f', 122, int)
+#define TARGET_FIOGETLBA    TARGET_IOR('f', 121, int)
+
+struct target_fiodgname_arg {
+    int32_t     len;
+    abi_ulong   buf;
+};
+
+#define TARGET_FIODGNAME    TARGET_IOW('f', 120,    \
+                struct target_fiodgname_arg)
+#define TARGET_FIONWRITE    TARGET_IOR('f', 119, int)
+#define TARGET_FIONSPACE    TARGET_IOR('f', 118, int)
+#define TARGET_FIOSEEKDATA  TARGET_IOWR('f', 97, off_t)
+#define TARGET_FIOSEEKHOLE  TARGET_IOWR('f', 98, off_t)
+
+#endif /* !_IOCTL_FILIO_H_ */
diff --git a/bsd-user/openbsd/ioctl-ioccom.h b/bsd-user/openbsd/ioctl-ioccom.h
new file mode 100644
index 0000000..fa1c6b4
--- /dev/null
+++ b/bsd-user/openbsd/ioctl-ioccom.h
@@ -0,0 +1,38 @@ 
+#ifndef _IOCTL_IOCCOM_H_
+#define _IOCTL_IOCCOM_H_
+
+/* XXX needs to be fixed for OpenBSD dependencies */
+
+/*
+ * Ioctl's have the command encoded in the lower word, and the size of
+ * any in or out parameters in the upper word.  The high 3 bits of the
+ * upper word are used to encode the in/out status of the parameter.
+ */
+/* number of bits for ioctl size */
+#define TARGET_IOCPARM_SHIFT    13
+
+/* parameter length mask */
+#define TARGET_IOCPARM_MASK ((1 << TARGET_IOCPARM_SHIFT) - 1)
+
+#define TARGET_IOCPARM_LEN(x)   (((x) >> 16) & TARGET_IOCPARM_MASK)
+#define TARGET_IOCBASECMD(x)    ((x) & ~(TARGET_IOCPARM_MASK << 16))
+#define TARGET_IOCGROUP(x)  (((x) >> 8) & 0xff)
+
+#define TARGET_IOCPARM_MAX  (1 << TARGET_IOCPARM_SHIFT) /* max size of ioctl */
+#define TARGET_IOC_VOID     0x20000000  /* no parameters */
+#define TARGET_IOC_OUT      0x40000000  /* copy out parameters */
+#define TARGET_IOC_IN       0x80000000  /* copy in parameters */
+#define TARGET_IOC_INOUT    (TARGET_IOC_IN|TARGET_IOC_OUT)
+#define TARGET_IOC_DIRMASK  (TARGET_IOC_VOID|TARGET_IOC_OUT|TARGET_IOC_IN)
+
+#define TARGET_IOC(inout, group, num, len) ((abi_ulong) \
+    ((inout) | (((len) & TARGET_IOCPARM_MASK) << 16) | ((group) << 8) \
+     | (num)))
+#define TARGET_IO(g, n)       TARGET_IOC(IOC_VOID,    (g), (n), 0)
+#define TARGET_IOWINT(g, n)   TARGET_IOC(IOC_VOID,    (g), (n), sizeof(int))
+#define TARGET_IOR(g, n, t)   TARGET_IOC(IOC_OUT, (g), (n), sizeof(t))
+#define TARGET_IOW(g, n, t)   TARGET_IOC(IOC_IN,  (g), (n), sizeof(t))
+/* this should be _IORW, but stdio got there first */
+#define TARGET_IOWR(g, n, t)  TARGET_IOC(IOC_INOUT,   (g), (n), sizeof(t))
+
+#endif /* !_IOCTL_IOCCOM_H_ */
diff --git a/bsd-user/openbsd/ioctl-ttycom.h b/bsd-user/openbsd/ioctl-ttycom.h
new file mode 100644
index 0000000..4c25d49
--- /dev/null
+++ b/bsd-user/openbsd/ioctl-ttycom.h
@@ -0,0 +1,240 @@ 
+#ifndef _IOCTL_TTYCOM_H_
+#define _IOCTL_TTYCOM_H_
+
+/* XXX Needs to be fixed for OpenBSD dependencies */
+
+#include "ioctl-ioccom.h"
+
+/* From sys/ttycom.h and sys/_termios.h */
+
+#define TARGET_VEOF     0   /* ICANON */
+#define TARGET_VEOL     1   /* ICANON */
+#define TARGET_VEOL2    2   /* ICANON together with IEXTEN */
+#define TARGET_VERASE   3   /* ICANON */
+#define TARGET_VWERASE  4   /* ICANON together with IEXTEN */
+#define TARGET_VKILL    5   /* ICANON */
+#define TARGET_VREPRINT 6   /* ICANON together with IEXTEN */
+#define TARGET_VERASE2  7   /* ICANON */
+#define TARGET_VINTR    8   /* ISIG */
+#define TARGET_VQUIT    9   /* ISIG */
+#define TARGET_VSUSP    10  /* ISIG */
+#define TARGET_VDSUSP   11  /* ISIG together with IEXTEN */
+#define TARGET_VSTART   12  /* IXON, IXOFF */
+#define TARGET_VSTOP    13  /* IXON, IXOFF */
+#define TARGET_VLNEXT   14  /* IEXTEN */
+#define TARGET_VDISCARD 15  /* IEXTEN */
+#define TARGET_VMIN     16  /* !ICANON */
+#define TARGET_VTIME    17  /* !ICANON */
+#define TARGET_VSTATUS  18  /* ICANON together with IEXTEN */
+/*                      19         spare 2 */
+#define TARGET_NCCS     20
+
+/*
+ * Input flags - software input processing
+ */
+#define TARGET_IGNBRK   0x00000001  /* ignore BREAK condition */
+#define TARGET_BRKINT   0x00000002  /* map BREAK to SIGINTR */
+#define TARGET_IGNPAR   0x00000004  /* ignore (discard) parity errors */
+#define TARGET_PARMRK   0x00000008  /* mark parity and framing errors */
+#define TARGET_INPCK    0x00000010  /* enable checking of parity errors */
+#define TARGET_ISTRIP   0x00000020  /* strip 8th bit off chars */
+#define TARGET_INLCR    0x00000040  /* map NL into CR */
+#define TARGET_IGNCR    0x00000080  /* ignore CR */
+#define TARGET_ICRNL    0x00000100  /* map CR to NL (ala CRMOD) */
+#define TARGET_IXON     0x00000200  /* enable output flow control */
+#define TARGET_IXOFF    0x00000400  /* enable input flow control */
+#define TARGET_IXANY    0x00000800  /* any char will restart after stop */
+#define TARGET_IMAXBEL  0x00002000  /* ring bell on input queue full */
+
+/*
+ * Output flags - software output processing
+ */
+#define TARGET_OPOST    0x00000001  /* enable following output processing */
+#define TARGET_ONLCR    0x00000002  /* map NL to CR-NL (ala CRMOD) */
+#define TARGET_TABDLY   0x00000004  /* tab delay mask */
+#define TARGET_TAB0     0x00000000  /* no tab delay and expansion */
+#define TARGET_TAB3     0x00000004  /* expand tabs to spaces */
+#define TARGET_ONOEOT   0x00000008  /* discard EOT's (^D) on output) */
+#define TARGET_OCRNL    0x00000010  /* map CR to NL on output */
+#define TARGET_ONOCR    0x00000020  /* no CR output at column 0 */
+#define TARGET_ONLRET   0x00000040  /* NL performs CR function */
+
+/*
+ * Control flags - hardware control of terminal
+ */
+#define TARGET_CIGNORE      0x00000001  /* ignore control flags */
+#define TARGET_CSIZE        0x00000300  /* character size mask */
+#define     TARGET_CS5      0x00000000  /* 5 bits (pseudo) */
+#define     TARGET_CS6      0x00000100  /* 6 bits */
+#define     TARGET_CS7      0x00000200  /* 7 bits */
+#define     TARGET_CS8      0x00000300  /* 8 bits */
+#define TARGET_CSTOPB       0x00000400  /* send 2 stop bits */
+#define TARGET_CREAD        0x00000800  /* enable receiver */
+#define TARGET_PARENB       0x00001000  /* parity enable */
+#define TARGET_PARODD       0x00002000  /* odd parity, else even */
+#define TARGET_HUPCL        0x00004000  /* hang up on last close */
+#define TARGET_CLOCAL       0x00008000  /* ignore modem status lines */
+#define TARGET_CCTS_OFLOW   0x00010000  /* CTS flow control of output */
+#define TARGET_CRTSCTS      (TARGET_CCTS_OFLOW | TARGET_CRTS_IFLOW)
+#define TARGET_CRTS_IFLOW   0x00020000  /* RTS flow control of input */
+#define TARGET_CDTR_IFLOW   0x00040000  /* DTR flow control of input */
+#define TARGET_CDSR_OFLOW   0x00080000  /* DSR flow control of output */
+#define TARGET_CCAR_OFLOW   0x00100000  /* DCD flow control of output */
+
+/*
+ * "Local" flags - dumping ground for other state
+ */
+#define TARGET_ECHOKE   0x00000001  /* visual erase for line kill */
+#define TARGET_ECHOE    0x00000002  /* visually erase chars */
+#define TARGET_ECHOK    0x00000004  /* echo NL after line kill */
+#define TARGET_ECHO 0x00000008  /* enable echoing */
+#define TARGET_ECHONL   0x00000010  /* echo NL even if ECHO is off */
+#define TARGET_ECHOPRT  0x00000020  /* visual erase mode for hardcopy */
+#define TARGET_ECHOCTL  0x00000040  /* echo control chars as ^(Char) */
+#define TARGET_ISIG 0x00000080  /* enable signals INTR, QUIT, [D]SUSP */
+#define TARGET_ICANON   0x00000100  /* canonicalize input lines */
+#define TARGET_ALTWERASE 0x00000200 /* use alternate WERASE algorithm */
+#define TARGET_IEXTEN   0x00000400  /* enable DISCARD and LNEXT */
+#define TARGET_EXTPROC  0x00000800  /* external processing */
+#define TARGET_TOSTOP   0x00400000  /* stop background jobs from output */
+#define TARGET_FLUSHO   0x00800000  /* output being flushed (state) */
+#define TARGET_NOKERNINFO 0x02000000    /* no kernel output from VSTATUS */
+#define TARGET_PENDIN   0x20000000  /* XXX retype pending input (state) */
+#define TARGET_NOFLSH   0x80000000  /* don't flush after interrupt */
+
+struct target_termios {
+    uint32_t c_iflag;   /* input flags */
+    uint32_t c_oflag;   /* output flags */
+    uint32_t c_cflag;   /* control flags */
+    uint32_t c_lflag;   /* local flags */
+    uint8_t  c_cc[TARGET_NCCS]; /* control chars */
+    uint32_t c_ispeed;  /* input speed */
+    uint32_t c_ospeed;  /* output speed */
+};
+
+
+struct target_winsize {
+    uint16_t ws_row;    /* rows, in characters */
+    uint16_t ws_col;    /* columns, in characters */
+    uint16_t ws_xpixel; /* horizontal size, pixels */
+    uint16_t ws_ypixel; /* vertical size, pixels */
+};
+
+                        /* 0-2 compat */
+                        /* 3-7 unused */
+                        /* 8-10 compat */
+                        /* 11-12 unused */
+#define TARGET_TIOCEXCL  TARGET_IO('t', 13) /* set exclusive use of tty */
+#define TARGET_TIOCNXCL  TARGET_IO('t', 14) /* reset exclusive use of tty */
+#define TARGET_TIOCGPTN  TARGET_IOR('t', 15, int) /* Get pts number. */
+#define TARGET_TIOCFLUSH TARGET_IOW('t', 16, int) /* flush buffers */
+                    /* 17-18 compat */
+/* get termios struct */
+#define TARGET_TIOCGETA TARGET_IOR('t', 19, struct target_termios)
+/* set termios struct */
+#define TARGET_TIOCSETA TARGET_IOW('t', 20, struct target_termios)
+/* drain output, set */
+#define TARGET_TIOCSETAW    TARGET_IOW('t', 21, struct target_termios)
+/* drn out, fls in, set */
+#define TARGET_TIOCSETAF    TARGET_IOW('t', 22, struct target_termios)
+                        /* 23-25 unused */
+#define TARGET_TIOCGETD TARGET_IOR('t', 26, int) /* get line discipline */
+#define TARGET_TIOCSETD TARGET_IOW('t', 27, int) /* set line discipline */
+#define TARGET_TIOCPTMASTER  TARGET_IO('t', 28) /* pts master validation */
+                    /* 29-85 unused */
+/* get ttywait timeout */
+#define TARGET_TIOCGDRAINWAIT   TARGET_IOR('t', 86, int)
+/* set ttywait timeout */
+#define TARGET_TIOCSDRAINWAIT   TARGET_IOW('t', 87, int)
+                    /* 88 unused */
+                    /* 89-91 conflicts: tun and tap */
+/* enable/get timestamp of last input event */
+#define TARGET_TIOCTIMESTAMP    TARGET_IOR('t', 89, struct target_timeval)
+/* modem: get wait on close */
+#define TARGET_TIOCMGDTRWAIT    TARGET_IOR('t', 90, int)
+/* modem: set wait on close */
+#define TARGET_TIOCMSDTRWAIT    TARGET_IOW('t', 91, int)
+                    /* 92-93 tun and tap */
+                    /* 94-97 conflicts: tun and tap */
+/* wait till output drained */
+#define TARGET_TIOCDRAIN     TARGET_IO('t', 94)
+ /* pty: generate signal */
+#define TARGET_TIOCSIG      TARGET_IOWINT('t', 95)
+/* pty: external processing */
+#define TARGET_TIOCEXT      TARGET_IOW('t', 96, int)
+/* become controlling tty */
+#define TARGET_TIOCSCTTY     TARGET_IO('t', 97)
+/* become virtual console */
+#define TARGET_TIOCCONS TARGET_IOW('t', 98, int)
+/* get session id */
+#define TARGET_TIOCGSID TARGET_IOR('t', 99, int)
+                        /* 100 unused */
+/* simulate ^T status message */
+#define TARGET_TIOCSTAT  TARGET_IO('t', 101)
+ /* pty: set/clr usr cntl mode */
+#define TARGET_TIOCUCNTL    TARGET_IOW('t', 102, int)
+/* usr cntl op "n" */
+#define TARGET_TIOCCMD(n)   TARGET_IO('u', n)
+/* set window size */
+#define TARGET_TIOCSWINSZ   TARGET_IOW('t', 103, struct target_winsize)
+/* get window size */
+#define TARGET_TIOCGWINSZ   TARGET_IOR('t', 104, struct target_winsize)
+                        /* 105 unused */
+/* get all modem bits */
+#define TARGET_TIOCMGET TARGET_IOR('t', 106, int)
+#define     TARGET_TIOCM_LE 0001        /* line enable */
+#define     TARGET_TIOCM_DTR    0002    /* data terminal ready */
+#define     TARGET_TIOCM_RTS    0004    /* request to send */
+#define     TARGET_TIOCM_ST 0010        /* secondary transmit */
+#define     TARGET_TIOCM_SR 0020        /* secondary receive */
+#define     TARGET_TIOCM_CTS    0040    /* clear to send */
+#define     TARGET_TIOCM_DCD    0100    /* data carrier detect */
+#define     TARGET_TIOCM_RI     0200    /* ring indicate */
+#define     TARGET_TIOCM_DSR    0400    /* data set ready */
+#define     TARGET_TIOCM_CD TARGET_TIOCM_DCD
+#define     TARGET_TIOCM_CAR    TARGET_TIOCM_DCD
+#define     TARGET_TIOCM_RNG    TARGET_TIOCM_RI
+#define TARGET_TIOCMBIC TARGET_IOW('t', 107, int) /* bic modem bits */
+#define TARGET_TIOCMBIS TARGET_IOW('t', 108, int) /* bis modem bits */
+#define TARGET_TIOCMSET TARGET_IOW('t', 109, int) /* set all modem bits */
+/* start output, like ^Q */
+#define TARGET_TIOCSTART     TARGET_IO('t', 110)
+/* stop output, like ^S */
+#define TARGET_TIOCSTOP  TARGET_IO('t', 111)
+/* pty: set/clear packet mode */
+#define TARGET_TIOCPKT      TARGET_IOW('t', 112, int)
+#define     TARGET_TIOCPKT_DATA     0x00    /* data packet */
+#define     TARGET_TIOCPKT_FLUSHREAD    0x01    /* flush packet */
+#define     TARGET_TIOCPKT_FLUSHWRITE   0x02    /* flush packet */
+#define     TARGET_TIOCPKT_STOP     0x04    /* stop output */
+#define     TARGET_TIOCPKT_START        0x08    /* start output */
+#define     TARGET_TIOCPKT_NOSTOP       0x10    /* no more ^S, ^Q */
+#define     TARGET_TIOCPKT_DOSTOP       0x20    /* now do ^S ^Q */
+#define     TARGET_TIOCPKT_IOCTL        0x40    /* state change of pty
+                               driver */
+#define TARGET_TIOCNOTTY     TARGET_IO('t', 113)    /* void tty
+                               association */
+#define TARGET_TIOCSTI      TARGET_IOW('t', 114, char)  /* simulate
+                            terminal input */
+#define TARGET_TIOCOUTQ TARGET_IOR('t', 115, int)   /* output queue size */
+                        /* 116-117 compat */
+#define TARGET_TIOCSPGRP    TARGET_IOW('t', 118, int) /* set pgrp of tty */
+#define TARGET_TIOCGPGRP    TARGET_IOR('t', 119, int) /* get pgrp of tty */
+#define TARGET_TIOCCDTR  TARGET_IO('t', 120)        /* clear data terminal
+                               ready */
+#define TARGET_TIOCSDTR  TARGET_IO('t', 121)        /* set data terminal
+                               ready */
+#define TARGET_TIOCCBRK  TARGET_IO('t', 122)        /* clear break bit */
+#define TARGET_TIOCSBRK  TARGET_IO('t', 123)        /* set break bit */
+                        /* 124-127 compat */
+
+#define TARGET_TTYDISC      0       /* termios tty line
+                           discipline */
+#define TARGET_SLIPDISC     4       /* serial IP discipline */
+#define TARGET_PPPDISC      5       /* PPP discipline */
+#define TARGET_NETGRAPHDISC 6       /* Netgraph tty node
+                           discipline */
+#define TARGET_H4DISC       7       /* Netgraph Bluetooth H4
+                           discipline */
+
+#endif /*! _IOCTL_TTYCOM_H_ */
diff --git a/bsd-user/openbsd/ioctl-types.h b/bsd-user/openbsd/ioctl-types.h
new file mode 100644
index 0000000..6f8b97b
--- /dev/null
+++ b/bsd-user/openbsd/ioctl-types.h
@@ -0,0 +1,7 @@ 
+/* XXX should be fixed for OpenBSD types and structs */
+STRUCT_SPECIAL(termios)
+
+STRUCT(winsize, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT)
+
+STRUCT(fiodgname_arg, TYPE_INT, TYPE_PTRVOID)
+
diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
index f063974..ec194d2 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -36,6 +36,7 @@  enum BSDType {
 };
 extern enum BSDType bsd_type;
 
+#include "exec/user/thunk.h"
 #include "syscall_defs.h"
 #include "syscall.h"
 #include "target_os_vmparam.h"
@@ -235,6 +236,10 @@  extern unsigned long target_maxssiz;
 extern unsigned long target_sgrowsiz;
 extern char qemu_proc_pathname[];
 
+/* ioctl.c */
+abi_long do_bsd_ioctl(int fd, abi_long cmd, abi_long arg);
+void ioctl_init(void);
+
 /* syscall.c */
 abi_long get_errno(abi_long ret);
 int is_error(abi_long ret);
diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
index 86aa471..3407894 100644
--- a/bsd-user/syscall.c
+++ b/bsd-user/syscall.c
@@ -1341,6 +1341,13 @@  abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
         ret = do_freebsd__umtx_op(arg1, arg2, arg3, arg4, arg5);
         break;
 
+        /*
+         * ioctl(2)
+         */
+    case TARGET_FREEBSD_NR_ioctl: /* ioctl(2) */
+        ret = do_bsd_ioctl(arg1, arg2, arg3);
+        break;
+
 
     case TARGET_FREEBSD_NR_break:
         ret = do_obreak(arg1);
@@ -1472,4 +1479,6 @@  abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1,
 
 void syscall_init(void)
 {
+
+    ioctl_init();
 }