freebsd-dev/sys/i386/ibcs2/ibcs2_ioctl.c
Ed Schouten bc093719ca Integrate the new MPSAFE TTY layer to the FreeBSD operating system.
The last half year I've been working on a replacement TTY layer for the
FreeBSD kernel. The new TTY layer was designed to improve the following:

- Improved driver model:

  The old TTY layer has a driver model that is not abstract enough to
  make it friendly to use. A good example is the output path, where the
  device drivers directly access the output buffers. This means that an
  in-kernel PPP implementation must always convert network buffers into
  TTY buffers.

  If a PPP implementation would be built on top of the new TTY layer
  (still needs a hooks layer, though), it would allow the PPP
  implementation to directly hand the data to the TTY driver.

- Improved hotplugging:

  With the old TTY layer, it isn't entirely safe to destroy TTY's from
  the system. This implementation has a two-step destructing design,
  where the driver first abandons the TTY. After all threads have left
  the TTY, the TTY layer calls a routine in the driver, which can be
  used to free resources (unit numbers, etc).

  The pts(4) driver also implements this feature, which means
  posix_openpt() will now return PTY's that are created on the fly.

- Improved performance:

  One of the major improvements is the per-TTY mutex, which is expected
  to improve scalability when compared to the old Giant locking.
  Another change is the unbuffered copying to userspace, which is both
  used on TTY device nodes and PTY masters.

Upgrading should be quite straightforward. Unlike previous versions,
existing kernel configuration files do not need to be changed, except
when they reference device drivers that are listed in UPDATING.

Obtained from:		//depot/projects/mpsafetty/...
Approved by:		philip (ex-mentor)
Discussed:		on the lists, at BSDCan, at the DevSummit
Sponsored by:		Snow B.V., the Netherlands
dcons(4) fixed by:	kan
2008-08-20 08:31:58 +00:00

716 lines
18 KiB
C

/* $NetBSD: ibcs2_ioctl.c,v 1.6 1995/03/14 15:12:28 scottb Exp $ */
/*-
* Copyright (c) 1994, 1995 Scott Bartram
* All rights reserved.
*
* based on compat/sunos/sun_ioctl.c
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/consio.h>
#include <sys/fcntl.h>
#include <sys/file.h>
#include <sys/filedesc.h>
#include <sys/filio.h>
#include <sys/ioctl_compat.h>
#include <sys/kbio.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/sysproto.h>
#include <sys/tty.h>
#include <i386/ibcs2/ibcs2_signal.h>
#include <i386/ibcs2/ibcs2_socksys.h>
#include <i386/ibcs2/ibcs2_stropts.h>
#include <i386/ibcs2/ibcs2_proto.h>
#include <i386/ibcs2/ibcs2_termios.h>
#include <i386/ibcs2/ibcs2_util.h>
#include <i386/ibcs2/ibcs2_ioctl.h>
static void stios2btios(struct ibcs2_termios *, struct termios *);
static void btios2stios(struct termios *, struct ibcs2_termios *);
static void stios2stio(struct ibcs2_termios *, struct ibcs2_termio *);
static void stio2stios(struct ibcs2_termio *, struct ibcs2_termios *);
#ifndef BURN_BRIDGES
int
ibcs2_gtty(struct thread *td, struct ibcs2_gtty_args *args)
{
struct ioctl_args ioctl_arg;
ioctl_arg.fd = args->fd;
ioctl_arg.com = TIOCGETC;
ioctl_arg.data = (caddr_t)args->buf;
return ioctl(td, &ioctl_arg);
}
int
ibcs2_stty(struct thread *td, struct ibcs2_stty_args *args)
{
struct ioctl_args ioctl_arg;
ioctl_arg.fd = args->fd;
ioctl_arg.com = TIOCSETC;
ioctl_arg.data = (caddr_t)args->buf;
return ioctl(td, &ioctl_arg);
}
#endif /* BURN BRIDGES */
/*
* iBCS2 ioctl calls.
*/
struct speedtab {
int sp_speed; /* Speed. */
int sp_code; /* Code. */
};
static struct speedtab sptab[] = {
{ 0, 0 },
{ 50, 1 },
{ 75, 2 },
{ 110, 3 },
{ 134, 4 },
{ 135, 4 },
{ 150, 5 },
{ 200, 6 },
{ 300, 7 },
{ 600, 8 },
{ 1200, 9 },
{ 1800, 10 },
{ 2400, 11 },
{ 4800, 12 },
{ 9600, 13 },
{ 19200, 14 },
{ 38400, 15 },
{ -1, -1 }
};
static u_long s2btab[] = {
0,
50,
75,
110,
134,
150,
200,
300,
600,
1200,
1800,
2400,
4800,
9600,
19200,
38400,
};
static int
ttspeedtab(int speed, struct speedtab *table)
{
for ( ; table->sp_speed != -1; table++)
if (table->sp_speed == speed)
return (table->sp_code);
return (-1);
}
static void
stios2btios(st, bt)
struct ibcs2_termios *st;
struct termios *bt;
{
register u_long l, r;
l = st->c_iflag; r = 0;
if (l & IBCS2_IGNBRK) r |= IGNBRK;
if (l & IBCS2_BRKINT) r |= BRKINT;
if (l & IBCS2_IGNPAR) r |= IGNPAR;
if (l & IBCS2_PARMRK) r |= PARMRK;
if (l & IBCS2_INPCK) r |= INPCK;
if (l & IBCS2_ISTRIP) r |= ISTRIP;
if (l & IBCS2_INLCR) r |= INLCR;
if (l & IBCS2_IGNCR) r |= IGNCR;
if (l & IBCS2_ICRNL) r |= ICRNL;
if (l & IBCS2_IXON) r |= IXON;
if (l & IBCS2_IXANY) r |= IXANY;
if (l & IBCS2_IXOFF) r |= IXOFF;
if (l & IBCS2_IMAXBEL) r |= IMAXBEL;
bt->c_iflag = r;
l = st->c_oflag; r = 0;
if (l & IBCS2_OPOST) r |= OPOST;
if (l & IBCS2_ONLCR) r |= ONLCR;
if (l & IBCS2_TAB3) r |= TAB3;
bt->c_oflag = r;
l = st->c_cflag; r = 0;
switch (l & IBCS2_CSIZE) {
case IBCS2_CS5: r |= CS5; break;
case IBCS2_CS6: r |= CS6; break;
case IBCS2_CS7: r |= CS7; break;
case IBCS2_CS8: r |= CS8; break;
}
if (l & IBCS2_CSTOPB) r |= CSTOPB;
if (l & IBCS2_CREAD) r |= CREAD;
if (l & IBCS2_PARENB) r |= PARENB;
if (l & IBCS2_PARODD) r |= PARODD;
if (l & IBCS2_HUPCL) r |= HUPCL;
if (l & IBCS2_CLOCAL) r |= CLOCAL;
bt->c_cflag = r;
bt->c_ispeed = bt->c_ospeed = s2btab[l & 0x0000000f];
l = st->c_lflag; r = 0;
if (l & IBCS2_ISIG) r |= ISIG;
if (l & IBCS2_ICANON) r |= ICANON;
if (l & IBCS2_ECHO) r |= ECHO;
if (l & IBCS2_ECHOE) r |= ECHOE;
if (l & IBCS2_ECHOK) r |= ECHOK;
if (l & IBCS2_ECHONL) r |= ECHONL;
if (l & IBCS2_NOFLSH) r |= NOFLSH;
if (l & IBCS2_TOSTOP) r |= TOSTOP;
bt->c_lflag = r;
bt->c_cc[VINTR] =
st->c_cc[IBCS2_VINTR] ? st->c_cc[IBCS2_VINTR] : _POSIX_VDISABLE;
bt->c_cc[VQUIT] =
st->c_cc[IBCS2_VQUIT] ? st->c_cc[IBCS2_VQUIT] : _POSIX_VDISABLE;
bt->c_cc[VERASE] =
st->c_cc[IBCS2_VERASE] ? st->c_cc[IBCS2_VERASE] : _POSIX_VDISABLE;
bt->c_cc[VKILL] =
st->c_cc[IBCS2_VKILL] ? st->c_cc[IBCS2_VKILL] : _POSIX_VDISABLE;
if (bt->c_lflag & ICANON) {
bt->c_cc[VEOF] =
st->c_cc[IBCS2_VEOF] ? st->c_cc[IBCS2_VEOF] : _POSIX_VDISABLE;
bt->c_cc[VEOL] =
st->c_cc[IBCS2_VEOL] ? st->c_cc[IBCS2_VEOL] : _POSIX_VDISABLE;
} else {
bt->c_cc[VMIN] = st->c_cc[IBCS2_VMIN];
bt->c_cc[VTIME] = st->c_cc[IBCS2_VTIME];
}
bt->c_cc[VEOL2] =
st->c_cc[IBCS2_VEOL2] ? st->c_cc[IBCS2_VEOL2] : _POSIX_VDISABLE;
#if 0
bt->c_cc[VSWTCH] =
st->c_cc[IBCS2_VSWTCH] ? st->c_cc[IBCS2_VSWTCH] : _POSIX_VDISABLE;
#endif
bt->c_cc[VSTART] =
st->c_cc[IBCS2_VSTART] ? st->c_cc[IBCS2_VSTART] : _POSIX_VDISABLE;
bt->c_cc[VSTOP] =
st->c_cc[IBCS2_VSTOP] ? st->c_cc[IBCS2_VSTOP] : _POSIX_VDISABLE;
bt->c_cc[VSUSP] =
st->c_cc[IBCS2_VSUSP] ? st->c_cc[IBCS2_VSUSP] : _POSIX_VDISABLE;
bt->c_cc[VDSUSP] = _POSIX_VDISABLE;
bt->c_cc[VREPRINT] = _POSIX_VDISABLE;
bt->c_cc[VDISCARD] = _POSIX_VDISABLE;
bt->c_cc[VWERASE] = _POSIX_VDISABLE;
bt->c_cc[VLNEXT] = _POSIX_VDISABLE;
bt->c_cc[VSTATUS] = _POSIX_VDISABLE;
}
static void
btios2stios(bt, st)
struct termios *bt;
struct ibcs2_termios *st;
{
register u_long l, r;
l = bt->c_iflag; r = 0;
if (l & IGNBRK) r |= IBCS2_IGNBRK;
if (l & BRKINT) r |= IBCS2_BRKINT;
if (l & IGNPAR) r |= IBCS2_IGNPAR;
if (l & PARMRK) r |= IBCS2_PARMRK;
if (l & INPCK) r |= IBCS2_INPCK;
if (l & ISTRIP) r |= IBCS2_ISTRIP;
if (l & INLCR) r |= IBCS2_INLCR;
if (l & IGNCR) r |= IBCS2_IGNCR;
if (l & ICRNL) r |= IBCS2_ICRNL;
if (l & IXON) r |= IBCS2_IXON;
if (l & IXANY) r |= IBCS2_IXANY;
if (l & IXOFF) r |= IBCS2_IXOFF;
if (l & IMAXBEL) r |= IBCS2_IMAXBEL;
st->c_iflag = r;
l = bt->c_oflag; r = 0;
if (l & OPOST) r |= IBCS2_OPOST;
if (l & ONLCR) r |= IBCS2_ONLCR;
if (l & TAB3) r |= IBCS2_TAB3;
st->c_oflag = r;
l = bt->c_cflag; r = 0;
switch (l & CSIZE) {
case CS5: r |= IBCS2_CS5; break;
case CS6: r |= IBCS2_CS6; break;
case CS7: r |= IBCS2_CS7; break;
case CS8: r |= IBCS2_CS8; break;
}
if (l & CSTOPB) r |= IBCS2_CSTOPB;
if (l & CREAD) r |= IBCS2_CREAD;
if (l & PARENB) r |= IBCS2_PARENB;
if (l & PARODD) r |= IBCS2_PARODD;
if (l & HUPCL) r |= IBCS2_HUPCL;
if (l & CLOCAL) r |= IBCS2_CLOCAL;
st->c_cflag = r;
l = bt->c_lflag; r = 0;
if (l & ISIG) r |= IBCS2_ISIG;
if (l & ICANON) r |= IBCS2_ICANON;
if (l & ECHO) r |= IBCS2_ECHO;
if (l & ECHOE) r |= IBCS2_ECHOE;
if (l & ECHOK) r |= IBCS2_ECHOK;
if (l & ECHONL) r |= IBCS2_ECHONL;
if (l & NOFLSH) r |= IBCS2_NOFLSH;
if (l & TOSTOP) r |= IBCS2_TOSTOP;
st->c_lflag = r;
l = ttspeedtab(bt->c_ospeed, sptab);
if ((int)l >= 0)
st->c_cflag |= l;
st->c_cc[IBCS2_VINTR] =
bt->c_cc[VINTR] != _POSIX_VDISABLE ? bt->c_cc[VINTR] : 0;
st->c_cc[IBCS2_VQUIT] =
bt->c_cc[VQUIT] != _POSIX_VDISABLE ? bt->c_cc[VQUIT] : 0;
st->c_cc[IBCS2_VERASE] =
bt->c_cc[VERASE] != _POSIX_VDISABLE ? bt->c_cc[VERASE] : 0;
st->c_cc[IBCS2_VKILL] =
bt->c_cc[VKILL] != _POSIX_VDISABLE ? bt->c_cc[VKILL] : 0;
if (bt->c_lflag & ICANON) {
st->c_cc[IBCS2_VEOF] =
bt->c_cc[VEOF] != _POSIX_VDISABLE ? bt->c_cc[VEOF] : 0;
st->c_cc[IBCS2_VEOL] =
bt->c_cc[VEOL] != _POSIX_VDISABLE ? bt->c_cc[VEOL] : 0;
} else {
st->c_cc[IBCS2_VMIN] = bt->c_cc[VMIN];
st->c_cc[IBCS2_VTIME] = bt->c_cc[VTIME];
}
st->c_cc[IBCS2_VEOL2] =
bt->c_cc[VEOL2] != _POSIX_VDISABLE ? bt->c_cc[VEOL2] : 0;
st->c_cc[IBCS2_VSWTCH] =
0;
st->c_cc[IBCS2_VSUSP] =
bt->c_cc[VSUSP] != _POSIX_VDISABLE ? bt->c_cc[VSUSP] : 0;
st->c_cc[IBCS2_VSTART] =
bt->c_cc[VSTART] != _POSIX_VDISABLE ? bt->c_cc[VSTART] : 0;
st->c_cc[IBCS2_VSTOP] =
bt->c_cc[VSTOP] != _POSIX_VDISABLE ? bt->c_cc[VSTOP] : 0;
st->c_line = 0;
}
static void
stios2stio(ts, t)
struct ibcs2_termios *ts;
struct ibcs2_termio *t;
{
t->c_iflag = ts->c_iflag;
t->c_oflag = ts->c_oflag;
t->c_cflag = ts->c_cflag;
t->c_lflag = ts->c_lflag;
t->c_line = ts->c_line;
bcopy(ts->c_cc, t->c_cc, IBCS2_NCC);
}
static void
stio2stios(t, ts)
struct ibcs2_termio *t;
struct ibcs2_termios *ts;
{
ts->c_iflag = t->c_iflag;
ts->c_oflag = t->c_oflag;
ts->c_cflag = t->c_cflag;
ts->c_lflag = t->c_lflag;
ts->c_line = t->c_line;
bcopy(t->c_cc, ts->c_cc, IBCS2_NCC);
}
int
ibcs2_ioctl(td, uap)
struct thread *td;
struct ibcs2_ioctl_args *uap;
{
struct proc *p = td->td_proc;
struct file *fp;
int error;
if ((error = fget(td, uap->fd, &fp)) != 0) {
DPRINTF(("ibcs2_ioctl(%d): bad fd %d ", p->p_pid,
uap->fd));
return EBADF;
}
if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
fdrop(fp, td);
DPRINTF(("ibcs2_ioctl(%d): bad fp flag ", p->p_pid));
return EBADF;
}
switch (uap->cmd) {
case IBCS2_TCGETA:
case IBCS2_XCGETA:
case IBCS2_OXCGETA:
{
struct termios bts;
struct ibcs2_termios sts;
struct ibcs2_termio st;
if ((error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bts,
td->td_ucred, td)) != 0)
break;
btios2stios (&bts, &sts);
if (uap->cmd == IBCS2_TCGETA) {
stios2stio (&sts, &st);
error = copyout((caddr_t)&st, uap->data,
sizeof (st));
#ifdef DEBUG_IBCS2
if (error)
DPRINTF(("ibcs2_ioctl(%d): copyout failed ",
p->p_pid));
#endif
break;
} else {
error = copyout((caddr_t)&sts, uap->data,
sizeof (sts));
break;
}
/*NOTREACHED*/
}
case IBCS2_TCSETA:
case IBCS2_TCSETAW:
case IBCS2_TCSETAF:
{
struct termios bts;
struct ibcs2_termios sts;
struct ibcs2_termio st;
if ((error = copyin(uap->data, (caddr_t)&st,
sizeof(st))) != 0) {
DPRINTF(("ibcs2_ioctl(%d): TCSET copyin failed ",
p->p_pid));
break;
}
/* get full BSD termios so we don't lose information */
if ((error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bts,
td->td_ucred, td)) != 0) {
DPRINTF(("ibcs2_ioctl(%d): TCSET ctl failed fd %d ",
p->p_pid, uap->fd));
break;
}
/*
* convert to iBCS2 termios, copy in information from
* termio, and convert back, then set new values.
*/
btios2stios(&bts, &sts);
stio2stios(&st, &sts);
stios2btios(&sts, &bts);
error = fo_ioctl(fp, uap->cmd - IBCS2_TCSETA + TIOCSETA,
(caddr_t)&bts, td->td_ucred, td);
break;
}
case IBCS2_XCSETA:
case IBCS2_XCSETAW:
case IBCS2_XCSETAF:
{
struct termios bts;
struct ibcs2_termios sts;
if ((error = copyin(uap->data, (caddr_t)&sts,
sizeof (sts))) != 0)
break;
stios2btios (&sts, &bts);
error = fo_ioctl(fp, uap->cmd - IBCS2_XCSETA + TIOCSETA,
(caddr_t)&bts, td->td_ucred, td);
break;
}
case IBCS2_OXCSETA:
case IBCS2_OXCSETAW:
case IBCS2_OXCSETAF:
{
struct termios bts;
struct ibcs2_termios sts;
if ((error = copyin(uap->data, (caddr_t)&sts,
sizeof (sts))) != 0)
break;
stios2btios (&sts, &bts);
error = fo_ioctl(fp, uap->cmd - IBCS2_OXCSETA + TIOCSETA,
(caddr_t)&bts, td->td_ucred, td);
break;
}
case IBCS2_TCSBRK:
DPRINTF(("ibcs2_ioctl(%d): TCSBRK ", p->p_pid));
error = ENOSYS;
break;
case IBCS2_TCXONC:
{
switch ((int)uap->data) {
case 0:
case 1:
DPRINTF(("ibcs2_ioctl(%d): TCXONC ", p->p_pid));
error = ENOSYS;
break;
case 2:
error = fo_ioctl(fp, TIOCSTOP, (caddr_t)0,
td->td_ucred, td);
break;
case 3:
error = fo_ioctl(fp, TIOCSTART, (caddr_t)1,
td->td_ucred, td);
break;
default:
error = EINVAL;
break;
}
break;
}
case IBCS2_TCFLSH:
{
int arg;
switch ((int)uap->data) {
case 0:
arg = FREAD;
break;
case 1:
arg = FWRITE;
break;
case 2:
arg = FREAD | FWRITE;
break;
default:
fdrop(fp, td);
return EINVAL;
}
error = fo_ioctl(fp, TIOCFLUSH, (caddr_t)&arg, td->td_ucred,
td);
break;
}
case IBCS2_TIOCGWINSZ:
uap->cmd = TIOCGWINSZ;
error = ioctl(td, (struct ioctl_args *)uap);
break;
case IBCS2_TIOCSWINSZ:
uap->cmd = TIOCSWINSZ;
error = ioctl(td, (struct ioctl_args *)uap);
break;
case IBCS2_TIOCGPGRP:
{
pid_t pg_id;
PROC_LOCK(p);
pg_id = p->p_pgrp->pg_id;
PROC_UNLOCK(p);
error = copyout((caddr_t)&pg_id, uap->data,
sizeof(pg_id));
break;
}
case IBCS2_TIOCSPGRP: /* XXX - is uap->data a pointer to pgid? */
{
struct setpgid_args sa;
sa.pid = 0;
sa.pgid = (int)uap->data;
error = setpgid(td, &sa);
break;
}
case IBCS2_TCGETSC: /* SCO console - get scancode flags */
error = EINTR; /* ENOSYS; */
break;
case IBCS2_TCSETSC: /* SCO console - set scancode flags */
error = 0; /* ENOSYS; */
break;
case IBCS2_JWINSIZE: /* Unix to Jerq I/O control */
{
struct ibcs2_jwinsize {
char bytex, bytey;
short bitx, bity;
} ibcs2_jwinsize;
PROC_LOCK(p);
SESS_LOCK(p->p_session);
ibcs2_jwinsize.bytex = 80;
/* p->p_session->s_ttyp->t_winsize.ws_col; XXX */
ibcs2_jwinsize.bytey = 25;
/* p->p_session->s_ttyp->t_winsize.ws_row; XXX */
ibcs2_jwinsize.bitx =
p->p_session->s_ttyp->t_winsize.ws_xpixel;
ibcs2_jwinsize.bity =
p->p_session->s_ttyp->t_winsize.ws_ypixel;
SESS_UNLOCK(p->p_session);
PROC_UNLOCK(p);
error = copyout((caddr_t)&ibcs2_jwinsize, uap->data,
sizeof(ibcs2_jwinsize));
break;
}
/* keyboard and display ioctl's -- type 'K' */
case IBCS2_KDGKBMODE: /* get keyboard translation mode */
uap->cmd = KDGKBMODE;
/* printf("ioctl KDGKBMODE = %x\n", uap->cmd);*/
error = ioctl(td, (struct ioctl_args *)uap);
break;
case IBCS2_KDSKBMODE: /* set keyboard translation mode */
uap->cmd = KDSKBMODE;
error = ioctl(td, (struct ioctl_args *)uap);
break;
case IBCS2_KDMKTONE: /* sound tone */
uap->cmd = KDMKTONE;
error = ioctl(td, (struct ioctl_args *)uap);
break;
case IBCS2_KDGETMODE: /* get text/graphics mode */
uap->cmd = KDGETMODE;
error = ioctl(td, (struct ioctl_args *)uap);
break;
case IBCS2_KDSETMODE: /* set text/graphics mode */
uap->cmd = KDSETMODE;
error = ioctl(td, (struct ioctl_args *)uap);
break;
case IBCS2_KDSBORDER: /* set ega color border */
uap->cmd = KDSBORDER;
error = ioctl(td, (struct ioctl_args *)uap);
break;
case IBCS2_KDGKBSTATE:
uap->cmd = KDGKBSTATE;
error = ioctl(td, (struct ioctl_args *)uap);
break;
case IBCS2_KDSETRAD:
uap->cmd = KDSETRAD;
error = ioctl(td, (struct ioctl_args *)uap);
break;
case IBCS2_KDENABIO: /* enable direct I/O to ports */
uap->cmd = KDENABIO;
error = ioctl(td, (struct ioctl_args *)uap);
break;
case IBCS2_KDDISABIO: /* disable direct I/O to ports */
uap->cmd = KDDISABIO;
error = ioctl(td, (struct ioctl_args *)uap);
break;
case IBCS2_KIOCSOUND: /* start sound generation */
uap->cmd = KIOCSOUND;
error = ioctl(td, (struct ioctl_args *)uap);
break;
case IBCS2_KDGKBTYPE: /* get keyboard type */
uap->cmd = KDGKBTYPE;
error = ioctl(td, (struct ioctl_args *)uap);
break;
case IBCS2_KDGETLED: /* get keyboard LED status */
uap->cmd = KDGETLED;
error = ioctl(td, (struct ioctl_args *)uap);
break;
case IBCS2_KDSETLED: /* set keyboard LED status */
uap->cmd = KDSETLED;
error = ioctl(td, (struct ioctl_args *)uap);
break;
/* Xenix keyboard and display ioctl's from sys/kd.h -- type 'k' */
case IBCS2_GETFKEY: /* Get function key */
uap->cmd = GETFKEY;
error = ioctl(td, (struct ioctl_args *)uap);
break;
case IBCS2_SETFKEY: /* Set function key */
uap->cmd = SETFKEY;
error = ioctl(td, (struct ioctl_args *)uap);
break;
case IBCS2_GIO_SCRNMAP: /* Get screen output map table */
uap->cmd = GIO_SCRNMAP;
error = ioctl(td, (struct ioctl_args *)uap);
break;
case IBCS2_PIO_SCRNMAP: /* Set screen output map table */
uap->cmd = PIO_SCRNMAP;
error = ioctl(td, (struct ioctl_args *)uap);
break;
case IBCS2_GIO_KEYMAP: /* Get keyboard map table */
uap->cmd = GIO_KEYMAP;
error = ioctl(td, (struct ioctl_args *)uap);
break;
case IBCS2_PIO_KEYMAP: /* Set keyboard map table */
uap->cmd = PIO_KEYMAP;
error = ioctl(td, (struct ioctl_args *)uap);
break;
/* socksys */
case IBCS2_SIOCSOCKSYS:
error = ibcs2_socksys(td, (struct ibcs2_socksys_args *)uap);
break;
case IBCS2_FIONREAD:
case IBCS2_I_NREAD: /* STREAMS */
uap->cmd = FIONREAD;
error = ioctl(td, (struct ioctl_args *)uap);
break;
default:
DPRINTF(("ibcs2_ioctl(%d): unknown cmd 0x%lx ",
td->proc->p_pid, uap->cmd));
error = ENOSYS;
break;
}
fdrop(fp, td);
return error;
}