
static char rcsid[] = "$Header: header.c,v 10.1 86/07/21 14:56:20 bog Exp $";

/************************************************************************\
**									**
**				Copyright 1986				**
**			VALID LOGIC SYSTEMS INCORPORATED		**
**									**
**	This listing contains confidential proprietary information	**
**	which is not to be disclosed to unauthorized persons without	**
**	written consent of an officer of Valid Logic Systems 		**
**	Incoroporated.							**
**									**
**	The copyright notice appearing above is included to provide	**
**	statutory protection in the event of unauthorized or 		**
**	unintentional public disclosure.				**
**									**
\************************************************************************/

/*
 * Machine-dependent type stuff.  (As opposed to everything else in this
 * library)
 *
 * Stolen from Valid boot code 0786 by Bill O. Gallmeister.
 */

#include "../h/param.h"
#include "../s32/cpu.h"
#include "../s32/clock.h"
#include "sas32.h"

extern sysdebug;	/* System level debugging statements {en,dis}abled */
int pagesize, pagemask, pageshift, *nofault;
long	PC;
short	statusReg;
extern int ignerr;
extern short berrfound;

/*
 * Startup
 *
 * Initializes interrupt vectors.  Figure out whether we're running on an
 * MC68010 or a 68020.  Deal with the clock, the contexts and all that other
 * whizzy stuff.
 *
 * Returns: garbage.  _stop()s directly if it screws up.
 */
startup() {
	register long func, i, *p = 0;
	extern buserr(), addrerr(), defaulterr();


	for (i=0; i < 0x100; i++)
	 {
		if (i == 2)
			func = (long)buserr;
		else if (i == 3)
			func = (long)addrerr;
		else if (i == 47) /* debugger's trap */
			continue;
		else 
			func = (long)defaulterr;
		p[i] = func;
	 }

	/* setup fundamental constants */

	pagesize = V_PAGESIZE;
	pagemask = pagesize - 1;
	for (pageshift=0; (1<<pageshift) != pagesize; pageshift++);

		/* turn off the clock for now  */
	CLKADDR->c_mode = C_SEL0 | C_WORD;  /* cntr 0 for sys clock */
	/*V_STATUS |= V_ENINT;   /* enable future interrupts */

	if (getChipType() == -1)
		_stop("Bad Chip Type");

}

printfRTE()
{
    printf("Returning from buserr exception ...\n");
}

printfCPU2()
{
    printf("68020 \n");
}

/*
 * Trap
 *
 * Handles all traps received by the running system.
 * The way it handles them is to yell, then die.
 */
trap(number,startregs) 
short number;
u_long startregs;	/* Only care about the address */
{
	register u_long i, *r = &startregs;
	if (nofault)
		longjmp (nofault, -1);

	printf("trap %x at pc %x, sr %x\n", number, PC, statusReg); /* Yell */
	/*
	 * Dump registers.
	 */
	for (i=0;i<8;i++)
		printf("d%d= 0x%x, ",i,*r++);
	printf("\n");
	for (i=0;i<8;i++)
		printf("a%d= 0x%x, ",i,*r++);
	printf("\n");
#ifdef	USE_ERM
	trap15();
#endif	USE_ERM
	_stop ("unexpected trap"); /* Die */
}

/*
 * Bob_trap
 *
 * This routine will ignore bus errors if you set the global IGNERR.
 * It's a stupid routine to use, and we don't.  But it's possibly handy, so it's
 * still here.
 */
bob_trap(number) 
short number;
{
	if (sysdebug)
		printf("<trap>");

	if (number == 2)	/* XXX 10/15/85 */
	    if (ignerr) {
		    printf("We are IGNORING bus errors OK!\n");
		    return;
	    }

	printf("trap %x at pc %x, sr %x\n", number, PC, statusReg);
	_stop ("unexpected trap");
}

/*
 * Clear bytes within kernel (standalone)
 */
/*ARGSUSED*/
bclear(to, count)
	caddr_t to;
	unsigned count;
{

	while (count --) *to++ = 0;
}

/*
 * Copy bytes within kernel (standalone)
 */
/*ARGSUSED*/
bcopy(from, to, count)
	register caddr_t from, to;
	register unsigned count;
{
	register long	*lto = (long *) to,
			*lfrom = (long *) from;

	if (((int)from | (int)to | (int)count)&0xF)
		while (count --) *to++ = *from++;
	else
		while (count -= 16) {
			*lto++ = *lfrom++;
			*lto++ = *lfrom++;
			*lto++ = *lfrom++;
			*lto++ = *lfrom++;
		}

}

/*
 * Overlapping bcopy -- copies bytes in reverse order in
 * case source and dest are overlapping.
 */
ovbcopy(from, to, count)
	caddr_t from, to;
	unsigned count;
{
	if ((long)from + count > (long)to)
	{
		/*
		 * Source and dest. overlap.
		 */
		from += count;
		to += count;
		while (count --) *--to = *--from;
	}
	else
		bcopy(from, to, count);
}


/*
 * Setpagemap
 *
 * Hammer a page entry into the hardware.  Used to make sundry addresses
 * accessible.  Used largely through the makeioaddr()/makememaddr() paradigm
 * (see below).
 *
 * Returns: nothing.
 */
setpagemap(page, entry)
   	register u_long page;
   	register u_short entry;
{
	register u_char	oldctxt;
	register u_short *ptr;

	oldctxt = V_CONTEXT;
	V_CONTEXT = V_ACCPM | V_ACCLOW;
	if (V_HALFMAP < page) {
		V_CONTEXT &= ~V_ACCLOW;
		ptr = (u_short *) page;
	}
	else
		ptr = (u_short *) (page | V_PAGEMAP);
	*ptr = entry;
	if (page != V_SCRATCHPAGE)
		printf ("setpagemap(%x, %x, %x, %x)\n", page, entry, ptr, *ptr);
	V_CONTEXT = oldctxt;
}

/*
 * Vtop
 *
 * Virtual to physical address translation
 */
vtop (virt)
caddr_t virt;
{
	int entry, physical;

	if ((u_long)virt < (u_long)V_PAGEMAP)
		V_CONTEXT |= V_ACCPM | V_ACCLOW;
	else
		V_CONTEXT |= V_ACCPM | V_ACCHIGH;
	entry = *(int*) (V_PAGEMAP + ((long) virt & ~V_PAGEMASK))
		& 0xFFFF;
	physical = (entry << PGSHIFT) | ((long) virt & V_PAGEMASK);
	V_CONTEXT &= ~(V_ACCPM | V_ACCLOW | V_ACCHIGH);
	return (physical);
}

/*
 * makeioaddr -- Make an address with which to reference an I/O
 *               page using scratchpage
 */
u_long
makeioaddr(address)
	register u_long	address;
{
	register u_long entry;

	entry = (((address & V_PGNUMMASK) >> V_PGSHIFT) | V_MBIO);
	setpagemap(V_SCRATCHPAGE, entry);
	return((address & V_PAGEMASK) + V_SCRATCHPAGE);
}

/*
** initmap -- init segment and page maps
**
** Returns: nothing.
*/
initmap()
{
	initsmap();
	initpmap();
}

/*
** initsmap -- initialize the segment map as identity.  All contexts
*	       map the same.  Make all segments user inaccessible.
*	       Determine from switches whether big or small map
*
* Returns: nothing.
*/
initsmap()
{
    register u_char oldctxt	= V_CONTEXT;
    register char	ctxtindex;
    register int	 addr;
    register u_short segnum;
    register u_short *ptr;

    for (ctxtindex = V_CTXTLIM - 1; ctxtindex >= 0; ctxtindex--) 
    {
#ifdef MAPDEBUG
	prf("\nContext: %2x", ctxtindex);
#endif MAPDEBUG
	V_CONTEXT = ctxtindex | V_ACCSM;
	addr	= V_MAXVA - SEGSIZE;   /* -SEGSIZE added mjg */
	segnum	= V_MAXSEGNUM;

#ifdef SMALLMAP 
	if (!(V_SWITCHES & SW_BIGMAP)) 
	{
		addr >>= 2;
		segnum >>= 2;
	}
	addr	-= SEGSIZE;
#endif SMALLMAP 
#ifdef NOTYET
	segnum 	= (((segnum - 1) | V_ACCESSMASK) & ~V_SUSER);
#else NOTYET
	segnum 	= ((segnum - 1) | V_ACCESSMASK);
#endif NOTYET

	for (; addr >= 0; segnum--, addr -= SEGSIZE) 
	{
	    V_CONTEXT |= V_ACCLOW;

/*
** This fixes the problem of not initializing
** address 0x800000
*/
	    if (addr >= V_HALFMAP) 
	    {
/*
** V_CONTEXT |= V_ACCHIGH
*/
		ptr = (u_short *) addr;
		V_CONTEXT &= ~V_ACCLOW;
	    } 
	    else
		ptr = (u_short *) (addr | V_SEGMAP);

	    *ptr = segnum;
	}
    }

    V_CONTEXT = oldctxt;
}

/*
 * initpmap -- Initialize the page map as identity.  All contexts map the
 *	       same.  Look at switches to determine if big map or small map
 *
 * Returns: nothing.
 */
initpmap()
{
    register u_char oldctxt	= V_CONTEXT;
    register int		addr;
    register u_short 	pgnum;
    register u_short	*ptr;

    V_CONTEXT = V_ACCPM;
    addr	= V_MAXVA;
    pgnum	= V_MAXPGNUM;

#ifdef BONEYARD
    if (!(V_SWITCHES & SW_BIGMAP)) 
    {
	    addr >>= 2;
	    pgnum >>= 2;
    }
#endif BONEYARD
    addr	-= V_PAGESIZE;
    pgnum--;

    for (; addr >= 0; addr -= V_PAGESIZE, pgnum--) 
    {
	ptr	= (u_short *) addr;
	V_CONTEXT |= V_ACCLOW;
/*
** This fixes the problem of not initializing
** address 0x800000
*/
	if (addr >= V_HALFMAP) 
	{
/*
** V_CONTEXT |= V_ACCHIGH
*/
	    ptr = (u_short *) addr;
	    V_CONTEXT &= ~V_ACCLOW;
	} 
	else
	    ptr = (u_short *) (addr | V_PAGEMAP);
	*ptr = pgnum;
    }

    V_CONTEXT = oldctxt;
}
