/*
 *  linux/ibcs/sysi86.c
 *
 *  Copyright (C) 1994  Mike Jagdis (jaggy@purplet.demon.co.uk)
 *
 * $Id: sysi86.c,v 1.3 1994/04/12 10:38:40 mike Exp $
 * $Source: /var/CVS/ibcs/sysi86.c,v $
 */


#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/segment.h>
#include <linux/ptrace.h>
#include <linux/config.h>
#include <linux/fcntl.h>

#include <asm/segment.h>
#include <asm/system.h>
#include <linux/fs.h>
#include <linux/sys.h>

#include <ibcs/ibcs.h>

#ifdef IBCS_TRACE
#include <ibcs/trace.h>
#endif


/* The sysi86() call is used for machine specific functions. As far as
 * SCO goes these are used for things like VP/IX, Merge and the Xenix
 * emulator. These are just the handful that might perhaps be expected
 * to either do something useful or give useful clues about the system.
 */
#define SI86FPHW	40
#  define FP_NO		0	/* No fp at all */
#  define FP_SW		1	/* using emulator */
#  define FP_HW		2	/* using hardware */
#  define FP_287	2	/* using a 287 */
#  define FP_387	3	/* using a 387 */
#define STIME		54
#define SETNAME		56
#define SI86MEM		65


int ibcs_sysi86(struct pt_regs * regs) {
	int	cmd;

	cmd = get_fs_long(((unsigned long *) regs->esp) + 1);

	switch (cmd) {
		case SI86FPHW: {
			int	*np;

			/* If we remove the 'static' from the definition
			 * of fpu_error in linux/init/main.c we can tell
			 * whether we are using hardware or software at
			 * least. For now let's lie... (actually SCO
			 * Unix 3.4 gives me -1...)
			 */
			np = (int *)get_fs_long(((unsigned long *) regs->esp) + 2);
			put_fs_long(FP_387, np);
			return 0;
		}

		case STIME: {
			/* Set the system time. The argument is a long,
			 * sys_stime() expects a pointer to a long...
			 */
			return SYS(stime)(((unsigned long *) regs->esp) + 2);
		}

		case SETNAME: {
			/* The name is required to be string of no more
			 * than 7 characters. We don't get passed the
			 * length so we are depending upon the current
			 * implementation of sys_sethostname() here.
			 */
			char	*cp;

			cp = (char *)get_fs_long(((unsigned long *) regs->esp) + 2);
			return SYS(sethostname)(cp, 7);
		}

		case SI86MEM: {
			/* Returns the size of physical memory.
			 */
			struct sysinfo i;

			si_meminfo(&i);
			return i.totalram;
		}
	}

#ifdef IBCS_TRACE
	if ((ibcs_trace & TRACE_API) || ibcs_func_p->trace) {
		printk(KERN_DEBUG "iBCS2: unsupported sysi86 call %d\n", cmd);
	}
#endif

	return -EINVAL;
}
