 /*
 |  Stuff
*/

#include <stdarg.h>

#include <sys/hardware.h>
#include <sys/useful.h>
#include <sys/types.h>
#include <sys/unix.h>
#include <sys/devtty.h>

extern oneterm vterms[NOTERMS];


/* This is here because fs_init() is.  Prettiness only */
#define MAIN
#include <sys/extern.h>
#undef MAIN

char setupflag = 0;

static int cursig;
static int (*curvec)();

void timersetup()
{
	setupflag = 1;

	/* disable interrupts (just in case) */
	*CIAA_ICR = 0x3;

	/* stop both timers if not already */
	*CIAA_CRA &= ~1;
	*CIAA_CRB &= ~1;

	/* This effectively flushes the timer */
	*CIAA_TBLO = 1;
	*CIAA_TBHI = 0;
	*CIAA_CRB  = 0x19;	/* start/oneshot/10cyc */
	while( 1 )
		if( ciaa_bits(2) )
			break;
}


int delay( mic )
uint16	mic;
{
	if( !setupflag )
		timersetup();

	if( mic <= 1 )
		return;

	*CIAA_TBLO = mic&0xff;
	*CIAA_TBHI = (mic>>8)&0xff;
	*CIAA_CRB  = 0x19;	/* start/oneshot/10cyc */
	while( 1 )
		if( ciaa_bits(2) )
			break;
}


/* Keeping counts would increate the general robustness, but atm it seems
   that enables are disables do not come in exact pairs - mcy */
/* Count of di()s verus ei()s */
/*static int int_cnt = 0;*/

 /*
 |  Turn interrupts off
*/
int di()
{
	*INTENA = 0x4000;	/* Disable master ints */
	/*int_cnt++;*/
}


 /*
 |  Turn interrupts on
*/
int ei()
{
	/*if( --int_cnt <= 0 )*/
		*INTENA = 0xc000;	/* Enable master ints */
}



 /*
 |  Misc functions, some from extras.c
*/

int bzero( ptr, len )
char *ptr;
int len;
{
	while(len--)
		*ptr++=0;
}

int bcopy( src, dst, len )
char *src, *dst;
int len;
{
	while(len--)
		*dst++=*src++;
}

int atoi( str )
char	*str;
{
	int	sgn = 1;
	int	res = 0;
	char	c;

	while( *str )
	{
		c=*str++;
		if( c == '-' )
		{
			sgn = -sgn;
			continue;
		}
		if( c>47 && c<58 )
			res = (res*10)+(c-48);
		else
			break;
	}
	return( res*sgn );
}

int strcmp( s1, s2 )
char	*s1,
	*s2;
{
	while( *s1 == *s2 )
		if( (*s1++==0) || (*s2++==0) )
			return 0;
	return 1;
}

int strlen( s1 )
char	*s1;
{
	int	len = 0;
	while( *s1++ )
		len++;
	return( len );
}

int strcpy( s1, s2 )
char	*s1,
	*s2;
{
	while( *s2 )
		*s1++=*s2++;
	*s1=0;
}

int strcat( s1, s2 )
char	*s1,
	*s2;
{
	while( *s1 )
		s1++;
	strcpy( s1, s2 );
}

int valadr()
{
	return 1;
}

int rdtime()
{
	return 0;
}

 /*
 |  This is where we come first off
*/
fs_init()
{
	termInit( &(vterms[0]), 0 );
	termInit( &(vterms[1]), 1 );
	termInit( &(vterms[2]), 2 );
	termInit( &(vterms[3]), 3 );
	kprintf("MAPUX kernel v0.5 - feeping creaturitis\n");
	kprintf("        (c) 1995 Martin Young\n\n");

	/* Initialise the memory management code */
	memmanInit();

	/* Must put init functions in the switch table sometime */
	fdd_init(0);
	di();
	inint = 0;
	udata.u_euid = 0;
	udata.u_insys = 1;
	ei();

	init2();
}


int sscanf( line, fmt )
char	*line;
char	*fmt;
{
	va_list	arg;
	char	str[32];
	char	*spos;
	char	c;

	va_start( arg, fmt );

	while( c = *fmt++ )
	{
		if( c != '%' )
		{
			if( c != *line++ )
				return;
			continue;
		}
		switch( c = *fmt++ )
		{
			case 's':
				spos = str;
				while( c=*spos=*line, c && c!=32 && c!=9 && c!=10 )
					{ spos++; line++; }
				*spos = 0;
				strcpy( va_arg(arg,char*), str );
				break;
			case 'i':
				*(va_arg(arg,int*)) = atoi( line );
				while( cins( "-0123456789", *line ) )
					line++;
				break;
		}
	}
}

/* Character in a string? */
int cins( s, c )
char	*s;
char	c;
{
	while( *s )
		if( *s++ == c )
			return( 1 );
	return( 0 );
}


 /*
 |  This adds two tick counts together.
 |  The t_time field holds up to one minutes of ticks,
 |  while the t_date field counts minutes
*/
int addtick( t1, t2 )
time__t	*t1, *t2;
{
	t1->t_time += t2->t_time;
	t1->t_date += t2->t_date;
	if( t1->t_time >= 60*TICKSPERSEC )
	{
		t1->t_time -= 60*TICKSPERSEC;
		++t1->t_date;
	}
}

int incrtick( t )
time__t	*t;
{
	if( ++t->t_time == 60*TICKSPERSEC )
	{
		t->t_time = 0;
		++t->t_date;
	}
}


 /*
 |  Update global time of day
*/
rdtod()
{
	/* Until I get this tod sorted: */
	tod.t_time = 0;
	tod.t_date = 0;
}


 /*
 |  UZI has this is machdep.c, but it doesn't look very
 |  machine dependent to me
*/
calltrap( context, type )
void	*context;
int	type;
{
	/* Deal with a pending caught signal, if any.
	   udata.u_insys should be false, and interrupts enabled.
	   remember, the user may never return from the trap routine */

	if( udata.u_cursig )
	{
		cursig = udata.u_cursig;
		curvec = udata.u_sigvec[cursig];
		udata.u_cursig = 0;
		udata.u_sigvec[cursig] = SIG_DFL;   /* Reset to default */
		leave_trap( context, type, curvec, cursig );
	}
}

int ciaa_bits( bit )
char	bit;
{
	static char pre = 0;
	char	new;
	int	retval;

	di();
	new = *CIAA_ICR;
	pre |= new;
	if( pre & bit )
	{
		pre &= ~bit;
		retval = 1;
	}
	else
		retval = 0;
	ei();

	return( retval );
}

 /*
 |  This allows up to 32 events to be scheduled, up to 10 minutes
 |  into the future.
 |  A function called by timeout may not set a timeout
*/

typedef struct tofunc
{
	int	(*func)();
	int	when;
	char	*arg;
} tofunc;
tofunc flist[32];

int	count = 0;
int	next = 0;

timeout( proc, arg, ticks )
int	(*proc)();
int	ticks;
void	*arg;
{
	int	i, gap=-1;
	int	nwhen;

	di();

	for(i=0;i<32;i++)
	{
		if( (flist[i].func==proc) && (flist[i].arg==arg) )
		{
			gap = i;
			break;
		}
		if( flist[i].func == 0 )
			gap=i;
	}

	/* No indicatation of error is given */
	if( gap == -1 )
	{
		ei();
		return;
	}
		
	flist[gap].func = proc;
	flist[gap].arg = arg;
	if( (flist[gap].when=count+ticks)>=(hz*600) )
		flist[gap].when -= (hz*600);
	nwhen = flist[gap].when;
	if( (nwhen>count ? nwhen-count : (nwhen-count)+(hz*600)) < 
	    (next>count ? next-count : (next-count)+(hz*600)) )
	    	next = nwhen;
	ei();
}

untimeout( proc, arg )
int	(*proc)();
void	*arg;
{
	int	i;
	di();
	for(i=0;i<32;i++)
		if( (flist[i].func==proc) && (flist[i].arg==arg) )
			flist[i].func = (void*)0;
	ei();
	/* next does not need correcting - a false alarm merely creates a 
	   little extra work for toutcheck() */
}


toutcheck()
{
	int	nnext = 0,
		soonest = (hz*600)+1,
		until,
		nwhen,
		i;

	/* Bump the counter up */
	if( (++count) == (hz*600) )
		count = 0;

	/* Only search the list if something is due */
	if( count==next )
	{
		for( i=0; i<32; i++ )
		{
			/* Trigger this event */
			if( (flist[i].func!=0) && (flist[i].when==count) )
			{
				int	(*dud)() = flist[i].func;
				flist[i].func = (void*)0;
				(*dud)(flist[i].arg);
			}
			else /* Check for the next next while we're here */
			{
				if( flist[i].func != 0 )
				{
					nwhen = flist[i].when;
					until = nwhen>count ? nwhen-count : (nwhen-count)+(hz*600);
					if( until < soonest )
					{
						soonest = until;
						nnext = nwhen;
					}
				}
			}
		}
		next = nnext;
	}
}

