//-----------------------------------------------------------------------------
// Copyright © 2001 - Philip Howard - All rights reserved, released under GPL
//
// 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, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//-----------------------------------------------------------------------------
// package	cdinit
// version	0.8.0
// header	cdinit.h
//
// purpose	Do common declarations and definitions.
//-----------------------------------------------------------------------------
// author	Philip Howard
// email	phil@ipal.org
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Set up CDROM machine architecture directory name string.
//-----------------------------------------------------------------------------
#ifdef CDINIT_TRACE

#define trace1(a)	{trace[0]=a;}
#define trace2(a,b)	{trace[0]=a;trace[1]=b;}
#define trace3(a,b,c)	{trace[0]=a;trace[1]=b;trace[2]=c;}
#define trace4(a,b,c,d)	{trace[0]=a;trace[1]=b;trace[2]=c;trace[3]=d;}

#else

#define trace1(a)
#define trace2(a,b)
#define trace3(a,b,c)
#define trace4(a,b,c,d)

#endif


//-----------------------------------------------------------------------------
// Define misc stuff.
//-----------------------------------------------------------------------------
signed long	errno		;

//-----------------------------------------------------------------------------
// Include only certain headers due to redefine conflicts.
//-----------------------------------------------------------------------------
#include <linux/types.h>
#include <asm/errno.h>
#include <asm/fcntl.h>
#include <asm/stat.h>
#include <asm/unistd.h>
#include <linux/fs.h>
#include <linux/reboot.h>
#include <linux/time.h>
#include <asm/signal.h>
#include <stdarg.h>
#include <sys/sysmacros.h>

//-----------------------------------------------------------------------------
// Define this in case we are compiled on an older system.
//-----------------------------------------------------------------------------
#ifndef MS_BIND
#define MS_BIND		0x1000
#endif

//-----------------------------------------------------------------------------
// Define some system calls.
//-----------------------------------------------------------------------------
static inline _syscall1(int,chdir,
			const char*,path);

static inline _syscall1(int,close,
			int,fd);

static inline _syscall1(int,dup,
			int,oldfd);

static inline _syscall2(int,dup2,
			int,oldfd,
			int,newfd);

static inline _syscall3(int,execve,
			const char*,filename,
			char*const*,argv,
			char*const*,envp);

static inline _syscall1(int,exit,
			int,status);

static inline _syscall3(int,fcntl,
			int,fd,
			int,cmd,
			long,arg);

//--------------------------------------------------------------------
// The fork(2) syscall has a weird interface into the kernel on Sparc.
// So code this specifically with a simple assembly inline.
//--------------------------------------------------------------------
#ifdef CDINIT_ARCH_SPARC32

static inline
int
fork ()
{
    register long pid __asm__ ("o0");
    register long child __asm__ ("o1");
    register long sys __asm__ ("g1") = __NR_fork;
    __asm__ __volatile__( "t\t0x10" : : "r" (sys) );
    if ( pid <= 0 ) return -1;
    return ( child - 1 ) & pid;
}

#else

static inline _syscall0(int,fork);

#endif

static inline _syscall2(int,fstat,
			int,filedes,
			struct stat*,buf);

static inline _syscall0(pid_t,getpid);

static inline _syscall2(int,gettimeofday,
			struct timeval*,tv,
			struct timezone*,tz);

static inline _syscall3(int,ioctl,
			int,d,
			int,request,
			char*,argp);

static inline _syscall2(int,mkdir,
			const char*,pathname,
			mode_t,mode);

static inline _syscall3(int,mknod,
			const char*,pathname,
			mode_t,mode,
			dev_t,dev);

static inline _syscall5(int,mount,
			const char*,specialfile,
			const char*,dir,
			const char*,filesystemtype,
			unsigned long,rwflag,
			const void*,data);

static inline _syscall2(int,nanosleep,
			const struct timespec*,req,
			struct timespec*,rem);

static inline _syscall3(int,open,
			const char*,pathname,
			int,flags,
			mode_t,mode);

static inline _syscall2(int,pivot_root,
			const char*,new_root,
			const char*,put_old);

static inline _syscall3(int,read,
			int,fd,
			const char*,buf,
			unsigned long,count);

static inline _syscall1(int,rmdir,
			const char*,pathname);

static inline _syscall2(int,stat,
			const char*,file_name,
			struct stat*,buf);

static inline _syscall2(int,symlink,
			const char*,oldname,
			const char*,newname);

//--------------------------------------------------------------------
// The pipe(2) syscall has a weird interface into the kernel on Sparc.
// So code this specifically with a simple assembly inline.
//--------------------------------------------------------------------
#ifdef CDINIT_ARCH_SPARC32

static inline
int
pipe (
    int *	fds
    )
{
    register long fd0 __asm__ ("o0");
    register long fd1 __asm__ ("o1");
    register long sys __asm__ ("g1") = __NR_pipe;
    __asm__ __volatile__( "t\t0x10" : : "r" (sys) );
    if ( fd0 < 0 ) return -1;
    fds[0] = fd0;
    fds[1] = fd1;
    return 0;
}

#else

static inline _syscall1(int,pipe,
			int*,filedes);
#endif

static inline _syscall4(int,reboot,
			int,magic,
			int,magic2,
			int,flag,
			void*,arg);

//-------------------------------------------
// Use int intead of void* for return type to
// avoid an error in Linux _syscallX macros.
//-------------------------------------------
#ifdef USE_INT_FOR_SYSCALL_SIGNAL
static inline _syscall2(int,signal,
			int,signum,
			void*,handler);
#else
static inline _syscall2(void*,signal,
			int,signum,
			void*,handler);
#endif

static inline _syscall1(int,umount,
			const char*,specialfile);

static inline _syscall1(int,unlink,
			const char*,pathname);

static inline _syscall3(pid_t,waitpid,
			pid_t,pid,
			int*,status,
			int,options);

static inline _syscall3(int,write,
			int,fd,
			const char*,buf,
			unsigned long,count);

//-----------------------------------------------------------------------------
// End of cdinit.h
//-----------------------------------------------------------------------------

