mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-19 10:53:58 +00:00
69b770e238
This is the main files for the iBCS2 emulator. It can be use compiled into the kernel by using: options IBCS2 options COMPAT_IBCS2 or as a lkm module using: options COMPAT_IBCS2 and then loading it via the ibcs2 script in /usr/bin REMEMBER: this code is still experimental ! NO WARRENTY ! Submitted by: sef@kithrup.com, mostyn@mrl.com, sos@kmd-ac.dk
368 lines
9.5 KiB
C
368 lines
9.5 KiB
C
/*-
|
|
* Copyright (c) 1994 Sean Eric Fagan
|
|
* Copyright (c) 1994 Søren Schmidt
|
|
* All rights reserved.
|
|
*
|
|
* 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
|
|
* in this position and unchanged.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. The name of the author may not be used to endorse or promote products
|
|
* derived from this software withough 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.
|
|
*
|
|
* $Id: ibcs2_xenix.c,v 1.10 1994/10/12 19:38:38 sos Exp $
|
|
*/
|
|
|
|
#include <i386/ibcs2/ibcs2.h>
|
|
#include <sys/param.h>
|
|
#include <sys/proc.h>
|
|
#include <sys/exec.h>
|
|
#include <sys/sysent.h>
|
|
#include <sys/errno.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/signal.h>
|
|
#include <sys/syslimits.h>
|
|
#include <sys/unistd.h>
|
|
#include <sys/timeb.h>
|
|
#include <vm/vm.h>
|
|
#include <machine/cpu.h>
|
|
#include <machine/psl.h>
|
|
#include <machine/reg.h>
|
|
|
|
struct ibcs2_sco_chsize_args {
|
|
int fd;
|
|
ibcs2_off_t size;
|
|
};
|
|
|
|
static int
|
|
sco_chsize(struct proc *p, struct ibcs2_sco_chsize_args *args, int *retval)
|
|
{
|
|
struct ftruncate_args {
|
|
int fd;
|
|
int pad;
|
|
off_t length;
|
|
} tmp;
|
|
|
|
if (ibcs2_trace & IBCS2_TRACE_XENIX)
|
|
printf("IBCS2: 'cxenix chsize'\n");
|
|
tmp.fd = args->fd;
|
|
tmp.pad = 0;
|
|
tmp.length = args->size;
|
|
return ftruncate(p, &tmp, retval);
|
|
}
|
|
|
|
struct ibcs2_sco_ftime_args {
|
|
struct timeb *tp;
|
|
};
|
|
|
|
static int
|
|
sco_ftime(struct proc *p, struct ibcs2_sco_ftime_args *args, int *retval)
|
|
{
|
|
struct timeval atv;
|
|
extern struct timezone tz;
|
|
struct timeb tb;
|
|
|
|
if (ibcs2_trace & IBCS2_TRACE_XENIX)
|
|
printf("IBCS2: 'cxenix ftime'\n");
|
|
microtime(&atv);
|
|
tb.time = atv.tv_sec;
|
|
tb.millitm = atv.tv_usec / 1000;
|
|
tb.timezone = tz.tz_minuteswest;
|
|
tb.dstflag = tz.tz_dsttime != DST_NONE;
|
|
|
|
return copyout((caddr_t)&tb, (caddr_t)args->tp, sizeof(struct timeb));
|
|
}
|
|
|
|
struct ibcs2_sco_nap_args {
|
|
long time;
|
|
};
|
|
|
|
static int
|
|
sco_nap(struct proc *p, struct ibcs2_sco_nap_args *args, int *retval)
|
|
{
|
|
long period;
|
|
extern int hz;
|
|
|
|
if (ibcs2_trace & IBCS2_TRACE_XENIX)
|
|
printf("IBCS2: 'cxenix nap %d ms'\n", args->time);
|
|
period = (long)args->time / (1000/hz);
|
|
if (period)
|
|
while (tsleep(&period, PUSER, "nap", period)
|
|
!= EWOULDBLOCK) ;
|
|
return 0;
|
|
}
|
|
|
|
struct ibcs2_sco_rdchk_args {
|
|
int fd;
|
|
};
|
|
|
|
static int
|
|
sco_rdchk(struct proc *p, struct ibcs2_sco_rdchk_args *args, int *retval)
|
|
{
|
|
struct ioctl_arg {
|
|
int fd;
|
|
int cmd;
|
|
caddr_t arg;
|
|
} tmp;
|
|
int error;
|
|
|
|
if (ibcs2_trace & IBCS2_TRACE_XENIX)
|
|
printf("IBCS2: 'cxenix rdchk'\n");
|
|
tmp.fd = args->fd;
|
|
tmp.cmd = FIONREAD;
|
|
tmp.arg = (caddr_t)UA_ALLOC();
|
|
error = ioctl(p, &tmp, retval);
|
|
if (!error)
|
|
*retval = *retval <= 0 ? 0 : 1;
|
|
return error;
|
|
}
|
|
|
|
struct ibcs2_sco_utsname_args {
|
|
long addr;
|
|
};
|
|
|
|
static int
|
|
sco_utsname(struct proc *p, struct ibcs2_sco_utsname_args *args, int *retval)
|
|
{
|
|
struct ibcs2_sco_utsname {
|
|
char sysname[9];
|
|
char nodename[9];
|
|
char release[16];
|
|
char kernelid[20];
|
|
char machine[9];
|
|
char bustype[9];
|
|
char sysserial[10];
|
|
unsigned short sysorigin;
|
|
unsigned short sysoem;
|
|
char numusers[9];
|
|
unsigned short numcpu;
|
|
} ibcs2_sco_uname;
|
|
extern char ostype[], hostname[], osrelease[], version[], machine[];
|
|
|
|
if (ibcs2_trace & IBCS2_TRACE_XENIX)
|
|
printf("IBCS2: 'cxenix sco_utsname'\n");
|
|
bzero(&ibcs2_sco_uname, sizeof(struct ibcs2_sco_utsname));
|
|
strncpy(ibcs2_sco_uname.sysname, ostype, 8);
|
|
strncpy(ibcs2_sco_uname.nodename, hostname, 8);
|
|
strncpy(ibcs2_sco_uname.release, osrelease, 15);
|
|
strncpy(ibcs2_sco_uname.kernelid, version, 19);
|
|
strncpy(ibcs2_sco_uname.machine, machine, 8);
|
|
bcopy("ISA/EISA", ibcs2_sco_uname.bustype, 8);
|
|
bcopy("no charge", ibcs2_sco_uname.sysserial, 9);
|
|
bcopy("unlim", ibcs2_sco_uname.numusers, 8);
|
|
ibcs2_sco_uname.sysorigin = 0xFFFF;
|
|
ibcs2_sco_uname.sysoem = 0xFFFF;
|
|
ibcs2_sco_uname.numcpu = 1;
|
|
return copyout((caddr_t)&ibcs2_sco_uname, (caddr_t)args->addr,
|
|
sizeof(struct ibcs2_sco_utsname));
|
|
}
|
|
|
|
int
|
|
ibcs2_cxenix(struct proc *p, void *args, int *retval)
|
|
{
|
|
struct trapframe *tf = (struct trapframe *)p->p_md.md_regs;
|
|
|
|
switch ((tf->tf_eax & 0xff00) >> 8) {
|
|
|
|
case 0x07: /* rdchk */
|
|
return sco_rdchk(p, args, retval);
|
|
|
|
case 0x0a: /* chsize */
|
|
return sco_chsize(p, args, retval);
|
|
|
|
case 0x0b: /* ftime */
|
|
return sco_ftime(p, args, retval);
|
|
|
|
case 0x0c: /* nap */
|
|
return sco_nap(p, args, retval);
|
|
|
|
case 0x15: /* scoinfo (not documented) */
|
|
*retval = 0;
|
|
return 0;
|
|
|
|
case 0x24: /* select */
|
|
if (ibcs2_trace & IBCS2_TRACE_XENIX)
|
|
printf("IBCS2: 'cxenix select'\n");
|
|
return select(p, args, retval);
|
|
|
|
case 0x25: /* eaccess */
|
|
if (ibcs2_trace & IBCS2_TRACE_XENIX)
|
|
printf("IBCS2: 'cxenix eaccess'\n");
|
|
return ibcs2_access(p, args, retval);
|
|
|
|
case 0x27: /* sigaction */
|
|
if (ibcs2_trace & IBCS2_TRACE_XENIX)
|
|
printf("IBCS2: 'cxenix sigaction'\n");
|
|
return ibcs2_sigaction (p, args, retval);
|
|
|
|
case 0x28: /* sigprocmask */
|
|
if (ibcs2_trace & IBCS2_TRACE_XENIX)
|
|
printf("IBCS2: 'cxenix sigprocmask'\n");
|
|
return ibcs2_sigprocmask (p, args, retval);
|
|
|
|
case 0x29: /* sigpending */
|
|
if (ibcs2_trace & IBCS2_TRACE_XENIX)
|
|
printf("IBCS2: 'cxenix sigpending'\n");
|
|
return ibcs2_sigpending (p, args, retval);
|
|
|
|
case 0x2a: /* sigsuspend */
|
|
if (ibcs2_trace & IBCS2_TRACE_XENIX)
|
|
printf("IBCS2: 'cxenix sigsuspend'\n");
|
|
return ibcs2_sigsuspend (p, args, retval);
|
|
|
|
case 0x2b: /* getgroups */
|
|
if (ibcs2_trace & IBCS2_TRACE_XENIX)
|
|
printf("IBCS2: 'cxenix getgroups'\n");
|
|
return ibcs2_getgroups(p, args, retval);
|
|
|
|
case 0x2c: /* setgroups */
|
|
if (ibcs2_trace & IBCS2_TRACE_XENIX)
|
|
printf("IBCS2: 'cxenix setgroups'\n");
|
|
return ibcs2_setgroups(p, args, retval);
|
|
|
|
case 0x2d: { /* sysconf */
|
|
struct ibcs2_sysconf_args {
|
|
int num;
|
|
} *sysconf_args = args;
|
|
|
|
if (ibcs2_trace & IBCS2_TRACE_XENIX)
|
|
printf("IBCS2: 'cxenix sysconf'");
|
|
switch (sysconf_args->num) {
|
|
case 0: /* _SC_ARG_MAX */
|
|
*retval = (ARG_MAX);
|
|
break;
|
|
case 1: /* _SC_CHILD_MAX */
|
|
*retval = (CHILD_MAX);
|
|
break;
|
|
case 2: /* _SC_CLK_TCK */
|
|
*retval = (CLK_TCK);
|
|
break;
|
|
case 3: /* _SC_NGROUPS_MAX */
|
|
*retval = (NGROUPS_MAX);
|
|
break;
|
|
case 4: /* _SC_OPEN_MAX */
|
|
*retval = (OPEN_MAX);
|
|
break;
|
|
case 5: /* _SC_JOB_CONTROL */
|
|
#ifdef _POSIX_JOB_CONTORL
|
|
*retval = _POSIX_JOB_CONTORL;
|
|
#else
|
|
*retval = (0);
|
|
#endif
|
|
break;
|
|
case 6: /* _SC_SAVED_IDS */
|
|
#ifdef _POSIX_SAVED_IDS
|
|
*retval = (_POSIX_SAVED_IDS);
|
|
#else
|
|
*retval = (0);
|
|
#endif
|
|
break;
|
|
case 7: /* _SC_VERSION */
|
|
*retval = (_POSIX_VERSION);
|
|
break;
|
|
default:
|
|
*retval = -1;
|
|
return EINVAL;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
case 0x2e: /* pathconf */
|
|
case 0x2f: /* fpathconf */
|
|
if (ibcs2_trace & IBCS2_TRACE_XENIX)
|
|
printf("IBCS2: 'cxenix (f)pathconf'\n");
|
|
return ibcs2_pathconf(p, args, retval);
|
|
|
|
case 0x30: /* rename */
|
|
if (ibcs2_trace & IBCS2_TRACE_XENIX)
|
|
printf("IBCS2: 'cxenix rename'\n");
|
|
return ibcs2_rename(p, args, retval);
|
|
|
|
case 0x32: /* sco_utsname */
|
|
return sco_utsname(p, args, retval);
|
|
|
|
case 0x37: /* getitimer */
|
|
if (ibcs2_trace & IBCS2_TRACE_XENIX)
|
|
printf("IBCS2: 'cxenix getitimer'\n");
|
|
return getitimer(p, args, retval);
|
|
|
|
case 0x38: /* setitimer */
|
|
if (ibcs2_trace & IBCS2_TRACE_XENIX)
|
|
printf("IBCS2: 'cxenix setitimer'\n");
|
|
return setitimer(p, args, retval);
|
|
|
|
|
|
/* Not implemented yet SORRY */
|
|
case 0x01: /* xlocking */
|
|
printf("IBCS2: 'cxenix xlocking'");
|
|
break;
|
|
case 0x02: /* creatsem */
|
|
printf("IBCS2: 'cxenix creatsem'");
|
|
break;
|
|
case 0x03: /* opensem */
|
|
printf("IBCS2: 'cxenix opensem'");
|
|
break;
|
|
case 0x04: /* sigsem */
|
|
printf("IBCS2: 'cxenix sigsem'");
|
|
break;
|
|
case 0x05: /* waitsem */
|
|
printf("IBCS2: 'cxenix waitsem'");
|
|
break;
|
|
case 0x06: /* nbwaitsem */
|
|
printf("IBCS2: 'cxenix nbwaitsem'");
|
|
break;
|
|
case 0x0d: /* sdget */
|
|
printf("IBCS2: 'cxenix sdget'");
|
|
break;
|
|
case 0x0e: /* sdfree */
|
|
printf("IBCS2: 'cxenix sdfree'");
|
|
break;
|
|
case 0x0f: /* sdenter */
|
|
printf("IBCS2: 'cxenix sdenter'");
|
|
break;
|
|
case 0x10: /* sdleave */
|
|
printf("IBCS2: 'cxenix sdleave'");
|
|
break;
|
|
case 0x11: /* sdgetv */
|
|
printf("IBCS2: 'cxenix sdgetv'");
|
|
break;
|
|
case 0x12: /* sdwaitv */
|
|
printf("IBCS2: 'cxenix sdwaitv'");
|
|
break;
|
|
case 0x20: /* proctl */
|
|
printf("IBCS2: 'cxenix proctl'");
|
|
break;
|
|
case 0x21: /* execseg */
|
|
printf("IBCS2: 'cxenix execseg'");
|
|
break;
|
|
case 0x22: /* unexecseg */
|
|
printf("IBCS2: 'cxenix unexecseg'");
|
|
break;
|
|
case 0x26: /* paccess */
|
|
printf("IBCS2: 'cxenix paccess'");
|
|
break;
|
|
default:
|
|
printf("IBCS2: 'cxenix' function %d(0x%x)",
|
|
tf->tf_eax>>8, tf->tf_eax>>8);
|
|
break;
|
|
}
|
|
printf(" not implemented yet\n");
|
|
return EINVAL;
|
|
}
|