freebsd-dev/sys/alpha/osf1/osf1_ioctl.c
Andrew Gallatin 32a8490d32 Finally add the Alpha OSF/1 compat code. I will add it to the
sys/modules Makefile after completing a buildworld.

History:

The bulk of this code was obtained from NetBSD approximately one year
ago (I have taken care to preserve the original NetBSD copyrights and
I thank the authors for their work.) At that time, the OSF/1 code was
what was left over from their initial bootstrapping off of OSF/1 and
did not provide support for executing shared binaries.

I have independently added support for shared libraries, and support
for some of the more obscure system calls.  This code has been
available for testing and comment since January of 1999 and running on
production machines here at Duke since April.

Known working applications include:

- Netscape (all versions I've tried)
- Mathematica 3.0.2
- Splus 3.4
- ArcInfo 7.1
- Matlab (version unknown)
- SimOS
- Atom instrumented binaries (built on a real OSF/1 system)

Applications which are known not to work:

- All applications linking to libmach
- Adobe Acrobat  (uses libmach)

This has been tested with applications running against shared
libraries from OSF/1 (aka Tru64) 4.0D and 4.0F.

Reviewed by: marcel, obrien
BDE-lint by: obrien
Agreed in principal to by: msmith
1999-12-14 22:35:36 +00:00

332 lines
8.0 KiB
C

/* $NetBSD: osf1_ioctl.c,v 1.5 1996/10/13 00:46:53 christos Exp $ */
/*
* Copyright (c) 1994, 1995 Carnegie-Mellon University.
* All rights reserved.
*
* Author: Chris G. Demetriou
*
* Permission to use, copy, modify and distribute this software and
* its documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
* FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* Additional Copyright (c) 1999 by Andrew Gallatin
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/fcntl.h>
#include <sys/filio.h>
#include <sys/ioctl_compat.h>
#include <sys/termios.h>
#include <sys/filedesc.h>
#include <sys/file.h>
#include <sys/proc.h>
#include <sys/mount.h>
#include <sys/sysproto.h>
#include <alpha/osf1/osf1_signal.h>
#include <alpha/osf1/osf1_proto.h>
#include <alpha/osf1/osf1.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <sys/sockio.h>
#include "opt_compat.h"
/*#define IOCTL_DEBUG*/
int osf1_ioctl_i __P((struct proc *p, struct ioctl_args *nuap,
int cmd, int dir, int len));
int osf1_ioctl_t __P((struct proc *p, struct ioctl_args *nuap,
int cmd, int dir, int len));
int osf1_ioctl_f __P((struct proc *p, struct ioctl_args *nuap,
int cmd, int dir, int len));
int
osf1_ioctl(p, uap)
struct proc *p;
struct osf1_ioctl_args *uap;
{
char *dirstr;
unsigned int cmd, dir, group, len, op;
struct ioctl_args /* {
syscallarg(int) fd;
syscallarg(u_long) com;
syscallarg(caddr_t) data;
} */ a;
op = uap->com;
dir = op & OSF1_IOC_DIRMASK;
group = OSF1_IOCGROUP(op);
cmd = OSF1_IOCCMD(op);
len = OSF1_IOCPARM_LEN(op);
switch (dir) {
case OSF1_IOC_VOID:
dir = IOC_VOID;
dirstr = "none";
break;
case OSF1_IOC_OUT:
dir = IOC_OUT;
dirstr = "out";
break;
case OSF1_IOC_IN:
dir = IOC_IN;
dirstr = "in";
break;
case OSF1_IOC_INOUT:
dir = IOC_INOUT;
dirstr = "in-out";
break;
default:
return (EINVAL);
break;
}
#ifdef IOCTL_DEBUG
uprintf(
"OSF/1 IOCTL: group = %c, cmd = %d, len = %d, dir = %s\n",
group, cmd, len, dirstr);
#endif
a.fd = uap->fd;
a.com = (unsigned long)uap->com;
bzero(&a.com, sizeof(long));
a.com = _IOC(dir, group, cmd, len);
a.data = uap->data;
switch (group) {
case 'i':
return osf1_ioctl_i(p, &a, cmd, dir, len);
case 't':
return osf1_ioctl_t(p, &a, cmd, dir, len);
case 'f':
return osf1_ioctl_f(p, &a, cmd, dir, len);
default:
printf(
"unimplented OSF/1 IOCTL: group = %c, cmd = %d, len = %d, dir = %s\n",
group, cmd, len, dirstr);
return (ENOTTY);
}
}
/*
* Structure used to query de and qe for physical addresses.
*/
struct osf1_ifdevea {
char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */
u_char default_pa[6]; /* default hardware address */
u_char current_pa[6]; /* current physical address */
};
int
osf1_ioctl_i(p, uap, cmd, dir, len)
struct proc *p;
struct ioctl_args /* {
syscallarg(int) fd;
syscallarg(u_long) com;
syscallarg(caddr_t) data;
} */ *uap;
int cmd;
int dir;
int len;
{
switch (cmd) {
case 20: /* OSF/1 OSIOCGIFCONF */
case 36: /* OSF/1 SIOCGIFCONF */
case 12: /* OSF/1 SIOCSIFADDR */
case 14: /* OSF/1 SIOCSIFDSTADDR */
case 16: /* OSF/1 SIOCSIFFLAGS (XXX) */
case 17: /* OSF/1 SIOCGIFFLAGS (XXX) */
case 19: /* OSF/1 SIOCSIFBRDADDR */
case 22: /* OSF/1 SIOCSIFNETMASK */
case 23: /* OSF/1 SIOCGIFMETRIC */
case 24: /* OSF/1 SIOCSIFMETRIC */
case 25: /* OSF/1 SIOCDIFADDR */
case 33: /* OSF/1 SIOCGIFADDR */
case 34: /* OSF/1 SIOCGIFDSTADDR */
case 35: /* OSF/1 SIOCGIFBRDADDR */
case 37: /* OSF/1 SIOCGIFNETMASK */
/* same as in FreeBSD */
return ioctl(p, uap);
break;
case 62: /* OSF/1 SIOCRPHYSADDR */
{
int ifn, retval;
struct ifnet *ifp;
struct ifaddr *ifa;
struct sockaddr_dl *sdl;
struct osf1_ifdevea *ifd = (struct osf1_ifdevea *)uap->data;
/*
* Note that we don't actually respect the name in the ifreq
* structure, as DU interface names are all different.
*/
for (ifn = 0; ifn < if_index; ifn++) {
ifp = ifnet_addrs[ifn]->ifa_ifp; /* pointer to interface */
/* Only look at ether interfaces, exclude alteon nics
* because osf/1 doesn't know about most of them.
*/
if (ifp->if_type == IFT_ETHER
&& strcmp(ifp->if_name, "ti")) { /* looks good */
/* walk the address list */
for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa;
ifa = TAILQ_NEXT(ifa, ifa_link)) {
if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) /* we have an address structure */
&& (sdl->sdl_family == AF_LINK) /* it's a link address */
&& (sdl->sdl_type == IFT_ETHER)) { /* for an ethernet link */
retval = copyout(LLADDR(sdl),
(caddr_t)&ifd->current_pa,
6);
if (!retval) {
return(copyout(
LLADDR(sdl),
(caddr_t)&ifd->default_pa,
6));
}
}
}
}
}
return(ENOENT); /* ??? */
}
default:
printf("osf1_ioctl_i: cmd = %d\n", cmd);
return (ENOTTY);
}
}
#ifndef _SGTTYB_
#define _SGTTYB_
struct sgttyb {
char sg_ispeed; /* input speed */
char sg_ospeed; /* output speed */
char sg_erase; /* erase character */
char sg_kill; /* kill character */
short sg_flags; /* mode flags */
};
#endif
int
osf1_ioctl_t(p, uap, cmd, dir, len)
struct proc *p;
struct ioctl_args /* {
syscallarg(int) fd;
syscallarg(u_long) com;
syscallarg(caddr_t) data;
} */ *uap;
int cmd;
int dir;
int len;
{
int retval;
switch (cmd) {
#ifdef COMPAT_43
case 0: /* OSF/1 COMPAT_43 TIOCGETD */
case 1: /* OSF/1 COMPAT_43 TIOCSETD */
case 8: /* OSF/1 COMPAT_43 TIOCGETP */
case 9: /* OSF/1 COMPAT_43 TIOCSETP */
case 10: /* OSF/1 COMPAT_43 TIOCSETN */
case 17: /* OSF/1 TIOCSETC (XXX) */
case 18: /* OSF/1 TIOCGETC (XXX) */
case 116: /* OSF/1 TIOCSLTC */
case 117: /* OSF/1 TIOCGLTC */
case 124: /* OSF/1 TIOCLGET */
case 125: /* OSF/1 TIOCLSET */
case 126: /* OSF/1 TIOCLBIC */
case 127: /* OSF/1 TIOCLBIS */
#endif
case 19: /* OSF/1 TIOCGETA (XXX) */
case 20: /* OSF/1 TIOCSETA (XXX) */
case 21: /* OSF/1 TIOCSETAW (XXX) */
case 22: /* OSF/1 TIOCSETAF (XXX) */
case 26: /* OSF/1 TIOCGETD (XXX) */
case 27: /* OSF/1 TIOCSETD (XXX) */
case 97: /* OSF/1 TIOCSCTTY */
case 103: /* OSF/1 TIOCSWINSZ */
case 104: /* OSF/1 TIOCGWINSZ */
case 110: /* OSF/1 TIOCSTART */
case 111: /* OSF/1 TIOCSTOP */
case 118: /* OSF/1 TIOCGPGRP */
case 119: /* OSF/1 TIOCGPGRP */
/* same as in NetBSD */
break;
default:
printf("osf1_ioctl_t: cmd = %d\n", cmd);
return (ENOTTY);
}
retval = ioctl(p, uap);
#if 0
if (retval)
printf("osf1_ioctl_t: cmd = %d, com = 0x%lx, retval = %d\n",
cmd, uap->com,retval);
#endif
return retval;
}
int
osf1_ioctl_f(p, uap, cmd, dir, len)
struct proc *p;
struct ioctl_args /* {
syscallarg(int) fd;
syscallarg(int) com;
syscallarg(caddr_t) data;
} */ *uap;
int cmd;
int dir;
int len;
{
switch (cmd) {
case 1: /* OSF/1 FIOCLEX (XXX) */
case 2: /* OSF/1 FIONCLEX (XXX) */
case 127: /* OSF/1 FIONREAD (XXX) */
case 126: /* OSF/1 FIONREAD (XXX) */
case 125: /* OSF/1 FIOASYNC (XXX) */
case 124: /* OSF/1 FIOSETOWN (XXX) */
case 123: /* OSF/1 FIOGETOWN (XXX) */
/* same as in FreeBSD */
break;
default:
printf("osf1_ioctl_f: cmd = %d\n", cmd);
return (ENOTTY);
}
return ioctl(p, uap);
}