/* rcsid[]="$Header: cpu.h,v 820.1 86/12/04 19:53:02 root Exp $" */
/* sccsid[]="%W% %Y% %Q% %G%" */

/************************************************************************
*									*
*				Copyright 1984				*
*			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 		*
*	Incorporated.							*
*									*
*	The copyright notice appearing above is included to provide	*
*	statutory protection in the event of unauthorized or 		*
*	unintentional public disclosure.				*
*									*
************************************************************************/

#ifndef	CPU_ALREADY_DEFINED
#define	CPU_ALREADY_DEFINED

/*	cpu.h	4.9	82/11/13	*/

#ifndef	LOCORE		/* So that machine/locore.s can use these #define's */

#ifdef		KERNEL
#include	"../h/types.h"
#else		KERNEL

#include	<sys/types.h>
#endif		KERNEL

/*
 * MMU parameters: pages
 */
int	pagesize;	/* Bytes per hardware page */
int	pagemask;	/* pagesize-1 */
int	pageshift;	/* LOG2(pagesize) */

/*
 * MMU parameters: segments
 */
int	segsize;	/* Bytes per hardware segment */
int	segmask;	/* segsize-1 */
int	segshift;	/* LOG2(segsize) */
int	msegsize;	/* Same as segsize */
int	nSegs;		/* Total number of segments in virtual address space */

/*
 * Memory map masks & attributes:
 */
unsigned short	page_free; /* Hardware page map value for invalid page */
unsigned short	page_reserved; /* ??? */

unsigned short	mbmem;	/* Hardware page map bits to set for Multibus memory */
unsigned short	mbio;	/* Hardware page map bits to set for Multibus I/O */

/*
 * Physical memory.
 */
int	maxmem;		/* Maximem memory in the memory pool */
int	maxpage;	/* Highest page in virtual address space */
int	p1Pages;	/* Number of pages in the P1 region */

/*
 * Virtual memory for the kernel.
 */
int	kstkbot;	/* Lower bound on kernel stack (virtual address) */
int	kvarea;		/* Lowest page in high part of kernel virtual memory */

int	k_lastpage;	/* Lowest non-kernel page */
int	systop;		/* Topmost allocatable vpno -- kernel allocs dwnwrd */

/*
 * Virtual memory for the cowboys and cowgirls.
 */
int	usrbase;	/* Lowest page of user area */
char	*usrtext;	/* Lowest address of user area */
int	usrTop;		/* First page above top of user area */
char	*usrStack;	/* First address above top of user area */

u_short	  bigmap_pages;	/* # pages denoted by   BIGMAP_PAGES	*/
u_short	smallmap_pages;	/* # pages denoted by SMALLMAP_PAGES	*/

short	normalMmuIndx;	/* Set @ startup(); never altered */
short	mmuIndxBigMap;	/* Index into mmu_sizing table for MMU_MAX_INDX */
short	largeContexts;	/* 1 ==> Running w/a Rev-B+ 68020 cpu	*/

/*
 * Flags, etc.
 */
extern	short proc0Initd;	/* 0==> proc[0] and upage NOT yet in place */

/*
 * Microprocessor chip type.
 */
#if	defined(M68000) || defined(M68010) || defined(M68020)
extern	u_long	chipType;	/* Which microprocessor we are running	*/
#endif	defined(M68000) || defined(M68010) || defined(M68020)

#ifdef	M68020
#if	0	/* Now in conf/ENG as an option */
#define	CACHE_SIZE_BYTES	0x4000		/* Size of onboard cache */
#endif	0	/* Now in conf/ENG as an option */
long	cacheSize;				/* Bucket for cache size */
#endif	M68020

#endif	LOCORE

/*
 * Microprocessor chip type designations.
 */
#define	CHIPTYPE_68000	0x00068000
#define	CHIPTYPE_68010	0x00068010
#define	CHIPTYPE_68020	0x00068020
#define	CHIPTYPE_ERROR	0xFFFFFFFF

#ifdef	M68020
#if	0	/* Now in conf/ENG as an option */
#define	CACHE_SIZE_BYTES	0x4000		/* Size of onboard cache */
#endif	0	/* Now in conf/ENG as an option */
#endif	M68020

/*
 * Well known virtual addresses
 */
#define	K_A		0x20000		/* Kernel starting address	      */

#define	SSEG1_VA	0x8000		/* Scratch segments, each 0x2000 long */
#define	SSEG2_VA	0xA000
#define	MBMEM_VA	0xC000		/* 4k multibus device memory space    */
#define	MBIO_VA		0xD000		/* 4k multibus device i/o    space    */
#define DUMMYU_PA	0xF000		/* u-page mapped here during startup  */

/*
 * MMU h/w dependent quantities & addresses
 */
#define	V_PAGESIZE	4096			/* page size */

#ifdef WHITE
#define PHYSMEMPAGES	0x400		/* number of memory pages from 0x000 */

#define V_MAXVA		0x800000 	/* 1 + biggest virtual addr, 24 bits */

#define	V_PAGEMAP	0x400000		/* address of page map */
#define V_SEGMAP	0x400000		/* address of segment map */
#else WHITE

#define PHYSMEMPAGES	0xD80		/* number of memory pages from 0x000 */

#define V_MAXVA_4MB	0x00400000 	/* 1 + biggest virtual addr, 22 bits */
#define V_MAXVA_8MB	0x00800000 	/* 1 + biggest virtual addr, 23 bits */
#define V_MAXVA_16MB	0x01000000 	/* 1 + biggest virtual addr, 24 bits */
#define V_MAXVA_32MB	0x02000000 	/* 1 + biggest virtual addr, 25 bits */
#define V_MAXVA_64MB	0x04000000 	/* 1 + biggest virtual addr, 26 bits */
#define V_MAXVA_128MB	0x08000000 	/* 1 + biggest virtual addr, 27 bits */
#define V_MAXVA_256MB	0x10000000 	/* 1 + biggest virtual addr, 28 bits */
#define V_MAXVA_512MB	0x20000000 	/* 1 + biggest virtual addr, 29 bits */
#define V_MAXVA_1024MB	0x40000000 	/* 1 + biggest virtual addr, 30 bits */
#define V_MAXVA_2048MB	0x80000000 	/* 1 + biggest virtual addr, 31 bits */
#define V_MAXVA_4096MB	(-1)		/* 0 + biggest virtual addr, 32 bits */

#define	V_PAGEMAP	0x800000		/* address of page map */
#define V_SEGMAP	0x800000		/* address of segment map */
#endif WHITE

/*
 * Miscellanea + the idiosyncratic:
 */
#define STACKPROBE	0x4AAF		/* tstl @a7(x) */
#define STACKPROBE2	0x4A2F		/* tstb @a7(x) */

#define BUFFHIGH	0x100000	/* Buffers can't be allocated > this */

/*
 * STATUS.REGISTER<7..0>:
 * Hardware addresses and typecasts.
 */
#ifdef	WHITE
#define	STATUS0_HW_ADDR	0x840007			/* Hardware address */
#else	WHITE

#define	STATUS0_HW_ADDR	0x1F001				/* Old Status Reg */
#ifdef	M68020
#define	STATUS1_HW_ADDR	0x1F000				/* New Status Reg */
#endif	M68020
#endif	WHITE

#define	STATUS0_ADDR	(*(char*) STATUS0_HW_ADDR)	/* Old register */
#define	V_STATUS	STATUS0_ADDR		

#ifdef	M68020
#define	STATUS1_ADDR	(*(u_short*) STATUS1_HW_ADDR)	/* New: h.o. of word */
#define	V_STATUS1	STATUS1_ADDR			/* New register */
#endif	M68020


/*
 * Bits in STATUS0<7..0>:	from the circuit diagrams.
 */
#define	S0_RED_LED		0x80		/* CPU Red   LED	  */ 
#define	S0_GREEN_LED		0x40		/* CPU green LED	  */ 
#define	S0_TST_STB		0x20		/* Test strobe for diags. */
#define	S0_EN_INT		0x10		/* Enable interrupts	  */
#define S0_BOOT_STATE_BAR	0x08		/* Boot state		  */

/*
 * On an M68010 and M68000,
 * STATUS0<0>==S0_EN_BKDET
 *
 * On the M68020-RevA, the bit is unused.
 * However, on the M68020-RevB,
 * the bit is STATUS0<0>==S0_USE_A25
 *
 * NOTE:  S0_USE_A27 is appropriate if and only iff LCW
 * adds cuts and jumpers to the REV_B cpu board.
 * Otherwise, S0_USE_A27 is a rumor spawned
 * by muddy thinking in the s(t)imuratol gloup.
 */
#ifdef	M68020_REV_B
#define S0_USE_A27		0x04		/* Enable use of A<27>    */
#define S0_USE_A26		0x02		/* Enable use of A<26>    */
#define S0_USE_A25		0x01		/* Enable use of A<25>    */
#else	!M68020_REV_B

#define S0_0x04_UNUSED		0x04		/* Unused bit		  */
#define S0_0x02_UNUSED		0x02		/* Unused bit		  */

#if	defined(M68010) || defined(M68000)
#define S0_EN_BKDET		0x01		/* Enable break detect	  */
#else	defined(M68010) || defined(M68000)
#define S0_0x01_UNUSED		0x01		/* Unused bit		  */
#endif	defined(M68010) || defined(M68000)
#endif	!M68020_REV_B


/*
 * How we use them in the kernel:
 */
#define	V_REDLED	S0_RED_LED		/* CPU Red   LED	  */ 
#define	V_GREENLED	S0_GREEN_LED		/* CPU Green LED	  */ 
#define	V_ENINT		S0_EN_INT		/* Enable interrupts	  */
#define V_ENBKDET	S0_EN_BKDET		/* Enable BRK-key detect  */

#define V_STATUS0_DEFAULT	(S0_BOOT_STATE_BAR)/* Default state for startup1() */

#ifdef	M68020
/*
 * Bits in STATUS1<15..8>:	from the circuit diagrams.
 */
#define	S1_INHIBIT_READ_MISS	0x8000	/* Inhibit ALL read misses (deliver bad data) */ 
#define	S1_DIS_TIMEOUT_BERR  	0x4000	/* Disable ALL timeout bus errors    */ 
#define	S1_CLR_TIMEOUT_PND	0x2000	/* Strobe to clear pending timeouts  */
#define	S1_SUICIDE_MODE		0x1000	/* Used in the boot-time diagnostics */

#ifndef	M68020_REV_B
#define S1_USE32MBY_ADRS	0x0800	/* Use 32Mbyte addressing	     */
#else	M68020_REV_B
#define S1_USE_A24		0x0800	/* Enable use of A<24> in addressing */
#endif	M68020_REV_B

#define S1_INT_CACHE_EN		0x0400	/* Enable internal, on-chip cache    */
#define S1_DIS_MB_CMDS		0x0200	/* Force mBus cmd timeout	     */
#define S1_CACHE_EN_STATUS	0x0100	/* Enable onboard cache		     */

/*
 * BUG: Default state for startup1()
 * in machine/startup.c
 */
#define V_STATUS1_DEFAULT	(0)	/* Now localized to startup1() */

#define	getStatusReg(bitMask)					\
		((chipType==CHIPTYPE_68020)			\
			? V_STATUS1				\
			: V_STATUS)

#define	setStatusReg(bitMask)					\
		if (chipType==CHIPTYPE_68020)			\
			V_STATUS1 = (u_short)(bitMask);		\
		else	V_STATUS  = (u_char )(bitMask);

#define	andStatusReg(bitMask)					\
		if (chipType==CHIPTYPE_68020)			\
			V_STATUS1 &= (u_short)(bitMask);	\
		else	V_STATUS  &= (u_char )(bitMask);

#define	orStatusReg(bitMask)					\
		if (chipType==CHIPTYPE_68020)			\
			V_STATUS1 |= (u_short)(bitMask);	\
		else	V_STATUS  |= (u_char )(bitMask);

#define	xorStatusReg(bitMask)					\
		if (chipType==CHIPTYPE_68020)			\
			V_STATUS1 ^= (u_short)(bitMask);	\
		else	V_STATUS  ^= (u_char )(bitMask);


/*
 * "There but for where I'm coming from,
 * go I..."	Anon.
 *
 * CONTEXT.REGISTER<7..0>:
 * =======================
 */
#ifdef WHITE
#define	CONTEXT_HW_ADDR	0x840003		/* Addr of Context Register */
#define V_MAP_CONTROL	0xF0			/* map control bits */
#define V_ACCUSER	0x10			/* access user map */
#else WHITE
#define	CONTEXT_HW_ADDR	0x1E001			/* Addr of Context Register */
#define V_MAP_CONTROL	0xE0			/* map control bits */
#endif WHITE


#define	V_CONTEXT     (*(unsigned char*) CONTEXT_HW_ADDR) /* Reg on PC board  */

/*
 * Addressing and register usage conventions
 * for the manipulation of the cpu's context register.
 */
#define	A_V_CONTEXT register u_char *  rCtxt_ = (u_char *)CONTEXT_HW_ADDR
#define	R_V_CONTEXT (* rCtxt_)				  /* Usage as LHS     */


/*
 * Access to memory map control, per se.
 * These bit are in CONTEXT.REGISTER<7..4>:
 *
 *	CTXT<3..0>:
 *	===========
 */
#define	V_ACCPM		0x80			/* access page map */
#define V_ACCSM		0xA0			/* access segment map */
#define V_ACCLOW	0x40			/* access low half of map */
#define V_ACCHIGH	0x00			/* access high half of map */

/*
 * Large virtual address space support.
 */
#define	SETS_4MB_MAXVA		0
#define	SETS_8MB_MAXVA		0
#define	SETS_16MB_MAXVA		0
#define	SETS_32MB_MAXVA		S1_USE_A24
#define	SETS_64MB_MAXVA		S1_USE_A24|S0_USE_A25
#define	SETS_128MB_MAXVA	S1_USE_A24|S0_USE_A25|S0_USE_A26
#define	SETS_256MB_MAXVA	S1_USE_A24|S0_USE_A25|S0_USE_A26|S0_USE_A27

#define	S_LARGE_VADDR_MASK	(SETS_128MB_MAXVA)
#define	MAXVA_BITS(x)		((x) & (S_LARGE_VADDR_MASK))

#define	IS_4MB_MAXVA(x)		(MAXVA_BITS(x)==(SETS_4MB_MAXVA))
#define	IS_8MB_MAXVA(x)		(MAXVA_BITS(x)==(SETS_8MB_MAXVA))
#define	IS_16MB_MAXVA(x)	(MAXVA_BITS(x)==(SETS_16MB_MAXVA))
#define	IS_32MB_MAXVA(x)	(MAXVA_BITS(x)==(SETS_32MB_MAXVA))
#define	IS_64MB_MAXVA(x)	(MAXVA_BITS(x)==(SETS_64MB_MAXVA))
#define	IS_128MB_MAXVA(x)	(MAXVA_BITS(x)==(SETS_128MB_MAXVA))
#define	IS_256MB_MAXVA(x)	(MAXVA_BITS(x)==(SETS_256MB_MAXVA))


/*
 * We get both the CTXT<3..0> and the STATUS
 * register's "context"-bits when dealing
 * with LARGE contexts.
 * (We only need the STATUS reg bits for debugging.)
 */
#define	getContextReg(p,ctxtBucket)					\
	{								\
		if (largeContexts) {					\
			(p)->p_mmuStatRegBits				\
			   = mmu_sizing[(p)->p_mmuIndx].mmu_statRegMask	\
			   & getStatusReg();				\
		}							\
		(ctxtBucket) = V_CONTEXT;				\
	}

/*
 * NOTES: 
 * ======
 * 1) Setting the CONTEXT register
 * involves a firedoor kept in a proc entry.
 *
 * 2) BUG: It is NOT clear from which proc
 * we are obtaining the STATUS reg mask!
 * Alternately, is u.u_procp ALWAYS the correct proc?
 *
 * 2) Also the STATUS register's "context"-bits
 * must be retained when switching to/from LARGE contexts.
 *
 * 3) Accessing/altering the same context does not
 * require quite so much procedural care.
 *
 * 4) We only logical 'or' "context" bits into the STATUS reg.
 */
#ifndef	LOCORE
u_long	setCtxtReg0;	/* Tracing/Debug */
u_long	setCtxtReg1;
u_long	setCtxtReg2;
u_long	setCtxtReg3;
#endif	LOCORE

#define	setContextReg(p,ctxtBucket)					\
	{								\
	   asm(" movl #0$,setCtxtReg0");	/* Tracing/Debug */ \
	   asm("0$:");				/* Tracing/Debug */ \
	   V_CONTEXT = (ctxtBucket);  /* Identical w/stmts we replace */\
	   if (largeContexts) {	      /* Twiddle the STATUS reg */	\
	        \
		asm(" movl #1$,setCtxtReg1");	/* Tracing/Debug */ \
		asm("1$:");			/* Tracing/Debug */ \
		andStatusReg(~S_LARGE_VADDR_MASK); /* Clear prior */	\
		\
		asm(" movl #2$,setCtxtReg2");	/* Tracing/Debug */ \
		asm("2$:");			/* Tracing/Debug */ \
		orStatusReg(mmu_sizing[(p)->p_mmuIndx].mmu_statRegBits);\
		asm(" movl #3$,setCtxtReg3");	/* Tracing/Debug */ \
		asm("3$:");			/* Tracing/Debug */ \
	   }								\
	}

/*
 * Virtual Memory/Swapping definitions that are also dependent on the
 * size of virtaul memory space.
 * In order to support larger virtual memory space either DMMAX must be 
 * increased or we must increase the arrays in the 'dmap' struct.  Since
 * that particular struct is used 4 times in the user struct, increasing
 * the array sizes would have a four-fold impact.  Increasing DMMAX will
 * not affect much since the minimum amount that can be allocated, DMMIN,
 * is not being altered.
 *
 *	ELP - 4/21/86
 *
 * Note: DMMAX must be a factor of 2^n in size or you will get a panic rmalloc
 */

#define	DMMIN	32
#ifdef WHITE
#define	DMMAX		512	/* max block size alloc on drum = .25M byte */
#define	DMTEXT		256	/* size of blocks of pure text = .125M byte */
#else WHITE
#define	DMMAX_256MB	16384	/* max block size alloc on drum = 8.0M byte */
#define	DMTEXT_256MB	16384	/* size of blocks of pure text = 8.0M byte */
#define	DMMAX_128MB	8192	/* max block size alloc on drum = 4.0M byte */
#define	DMTEXT_128MB	8192	/* size of blocks of pure text = 4.0M byte */
#define	DMMAX_64MB	4096	/* max block size alloc on drum = 2.0M byte */
#define	DMTEXT_64MB	4096	/* size of blocks of pure text = 2.0M byte */
#define	DMMAX_32MB	2048	/* max block size alloc on drum = 1.0M byte */
#define	DMTEXT_32MB	2048	/* size of blocks of pure text = 1.0M byte */
#define	DMMAX_16MB	1024	/* max block size alloc on drum = 0.5M byte */
#define	DMTEXT_16MB	1024	/* size of blocks of pure text = 0.5M byte */
#endif WHITE
/*
	As you will see from examining the diagram below,
	various context slots will be consumed
	by map references for the virtual address space #N.

	Of particular interest in checking your understanding,
	is the 64Mb case...

	Examples
	========
	  16Mb x 16:#N	CTXT<1..0> == N; A<26..25> = ignored;	ctxtId = [N]
	  16Mb x 16:#1	CTXT<1..0> == 1; A<26..25> = ignored;	ctxtId = [1]
	  16Mb x 16:#2	CTXT<1..0> == 2; A<26..25> = ignored;	ctxtId = [2]
	  ...



	  32Mb x 16:	same as 16Mb



------->  64Mb x  8:#N	CTXT<3,1,0> == N; A<26..25> = [0..1];	ctxtId = [N,N+4]
		     =		       =				  = =
	  64Mb x  8:#0	CTXT<3,1,0> == 0; A<26..25> = [0..1];	ctxtId = [0,  4]
	  64Mb x  8:#1	CTXT<3,1,0> == 1; A<26..25> = [0..1];	ctxtId = [1,  5]
	  64Mb x  8:#2	CTXT<3,1,0> == 2; A<26..25> = [0..1];	ctxtId = [2,  6]
	  64Mb x  8:#3	CTXT<3,1,0> == 3; A<26..25> = [0..1];	ctxtId = [3,  7]

	  64Mb x  8:#4	CTXT<3,1,0> == 8; A<26..25> = [0..1];	ctxtId = [8, 12]
	  64Mb x  8:#5	CTXT<3,1,0> == 9; A<26..25> = [0..1];	ctxtId = [9, 13]
	  64Mb x  8:#6	CTXT<3,1,0> ==10; A<26..25> = [0..1];	ctxtId = [10,14]
	  64Mb x  8:#7	CTXT<3,1,0> ==11; A<26..25> = [0..1];	ctxtId = [11,15]



	 128Mb x  4:#N	CTXT<1..0> == N; A<26..25> = [0..3];	ctxtId = [N,N+4,N+8,N+12]
	 128Mb x  4:#0	CTXT<1..0> == 0; A<26..25> = [0..3];	ctxtId = [0,4,8,12]
	 128Mb x  4:#1	CTXT<1..0> == 1; A<26..25> = [0..3];	ctxtId = [1,5,9,13]
	 128Mb x  4:#2	CTXT<1..0> == 2; A<26..25> = [0..3];	ctxtId = [2,6,10,14]
	 128Mb x  4:#3	CTXT<1..0> == 3; A<26..25> = [0..3];	ctxtId = [3,7,11,15]


	 128Mb Details:
	 ==============

			    CTXT<3..0>
			    ==========

		....... -----------------
		:	|	15	|	<--- CTXT<1..0> = 3
		:	-----------------
		:	|	14	|	<--- CTXT<1..0> = 2
A<26..25> = 3  <	-----------------
		:	|	13	|	<--- CTXT<1..0> = 1
		:	-----------------
		:	|	12	|	<--- CTXT<1..0> = 0
		....... -----------------


		....... -----------------
		:	|	11	|		   <--- CTXT<1..0> = 3
		:	-----------------
		:	|	10	|		<--- CTXT<1..0> = 2
A<26..25> = 2  <	-----------------
		:	|	 9	|	   <--- CTXT<1..0> = 1
		:	-----------------
		:	|	 8	|	<--- CTXT<1..0> = 0
		....... -----------------


		....... -----------------
		:	|	 7	|		   <--- CTXT<1..0> = 3
		:	-----------------
		:	|	 6	|		<--- CTXT<1..0> = 2
A<26..25> = 1  <	-----------------
		:	|	 5	|	   <--- CTXT<1..0> = 1
		:	-----------------
		:	|	 4	|	<--- CTXT<1..0> = 0
		....... -----------------


		....... -----------------
		:	|	 3	|		   <--- CTXT<1..0> = 3
		:	-----------------
		:	|	 2	|		<--- CTXT<1..0> = 2
A<26..25> = 0  <	-----------------
		:	|	 1	|	   <--- CTXT<1..0> = 1
		:	-----------------
		:	|	 0	|	<--- CTXT<1..0> = 0
		....... -----------------

*/
			/********************************/
			/*				*/
			/*	MMU SIZING TABLE	*/
			/*				*/
			/********************************/


#define	MAXCONTEXTS	16		/* Max # of context (smallest vaddr) */

#ifndef	LOCORE		/* Keep machine/locore.s from using these definitions */

struct	mmu_sizing_t {
	caddr_t	mmu_ctxtMaxVaddr;		/* 1+biggest virt. address    */
	char  *	mmu_name;			/* Name for ctxtMaxVaddr      */

	/*
	 * Start of program's text
	 */
	int	mmu_usrbase;			/* Page #		      */
	char  *	mmu_usrtext;			/* Virtual address 	      */

	/*
	 * Top of the program's stack
	 */
	int	mmu_usrtop;			/* Page #		      */
	char  *	mmu_usrstack;			/* Virtual address 	      */

	/*
	 * Bits OR'd/AND'd to gate A<26..24>
	 * into the CTXT<3..2> register 
	 */
	u_short		mmu_statRegBits;	/* Status Reg bits: A<26..24> */
#define	mmu_statRegMask	mmu_statRegBits

	/*
	 * MMU characteristics
	 */
	short	mmu_idsInACtxt;			/* # ctxt ids in a context    */
	short	mmu_ctxtCntsBy;			/* Inc for next in series     */
	short	mmu_nContexts;			/* # elements in alignedIds   */
						/* ... 0 ==> no elements      */
	char	mmu_alignedIds[MAXCONTEXTS];	/* Aligned MMU context #s     */

	int		mmu_nsegs;		/* # segments to be supported */

	/*
	 * Pagnos and ptrs to kernel areas fixed in real memory,
	 * but which may have different virtual addresses,
	 * since they reside near the "top" of an address space.
	 */
	int		mmu_kvarea;	/* Lowest page in high virt kernel */
	int		mmu_p1pages;	/* # pages in P1 region		   */
	struct	pte  *	mmu_usrpt;	/* Ptr to usr page tables	   */
	struct	mbuf *	mmu_mbutl;	/* Virtual address of net free mem */
	u_long		mmu_maxVaddrMask;/* Mask for high bits above ??    */
	u_long		mmu_SEGNO_MASK;	/* Mask for seg # from page #	   */
	int		mmu_maxVSmaps;	/* # virt smaps a process can have */
	int		mmu_dmmax;	/* Swap space chunk size	   */
	int		mmu_dmtext;	/* Swap space chunk size	   */
	int		mmu_pad[10];
};

#ifdef	KERNEL	/* Otherwise this gets defined in 'ps' */
struct	mmu_sizing_t	mmu_sizing[]
#endif	KERNEL

#define	MMU_name(p)		mmu_sizing[(p)->p_mmuIndx].mmu_name
#define	MMU_nContexts(p)	mmu_sizing[(p)->p_mmuIndx].mmu_nContexts
#define	MMU_ctxtCntsBy(p)	mmu_sizing[(p)->p_mmuIndx].mmu_ctxtCntsBy
#define	MMU_alignedIds(p)	mmu_sizing[(p)->p_mmuIndx].mmu_alignedIds
#define	MMU_idsInACtxt(p)	mmu_sizing[(p)->p_mmuIndx].mmu_idsInACtxt
#define	MMU_SEGNO_MASK(p)	mmu_sizing[(p)->p_mmuIndx].mmu_SEGNO_MASK
#define	MMU_maxVSmaps(p)	mmu_sizing[(p)->p_mmuIndx].mmu_maxVSmaps

/*
 * Initialization for the above mmu_sizing table:
 */
#ifdef	STARTUP_DOT_C				/* Defined only in startup.c  */
= {
#endif	STARTUP_DOT_C

#define	MMU_4MB	0

#ifdef	STARTUP_DOT_C
   {(caddr_t)V_MAXVA_4MB,	"4MB",
	0,0,0,0,	(SETS_4MB_MAXVA),
	1,1,16,	{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},
	0,0,0,0,0,
	V_MAXVA_4MB,
	0x03F0,			
	0,
	DMMAX_16MB,
	DMTEXT_16MB
   },
#endif	STARTUP_DOT_C				/* Defined only in startup.c  */

#define   V_MINVA	V_MINVA_4MB 	/* 1 + smallest virtual addr	*/
#define	MMU_MIN_INDX	    MMU_4MB	/* Index to historical V_MINVA	*/


#define	MMU_8MB	1

#ifdef	STARTUP_DOT_C				/* Defined only in startup.c  */
   {(caddr_t)V_MAXVA_8MB,	"8MB",
	0,0,0,0,	(SETS_8MB_MAXVA),
	1,1,16,	{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},
	0,0,0,0,0,
	V_MAXVA_4MB,
	0x07F0,			
	0,
	DMMAX_16MB,
	DMTEXT_16MB
   },
#endif	STARTUP_DOT_C				/* Defined only in startup.c  */



#define	MMU_16MB 2		/* A "wand of tradition" */

#ifdef	STARTUP_DOT_C				/* Defined only in startup.c  */
   {(caddr_t)V_MAXVA_16MB,	"16MB",
	0,0,0,0,	(SETS_16MB_MAXVA),
	1,1,16,	{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},
	0,0,0,0,0,
	V_MAXVA_8MB|V_MAXVA_4MB,
	0x0FF0,			
	0,
	DMMAX_16MB,
	DMTEXT_16MB
   },
#endif	STARTUP_DOT_C				/* Defined only in startup.c  */



#define	MMU_32MB 3

#ifdef	STARTUP_DOT_C				/* Defined only in startup.c  */
   {(caddr_t)V_MAXVA_32MB,	"32MB",
	0,0,0,0,	(SETS_32MB_MAXVA),
	1,1,16,	{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},
	0,0,0,0,0,
	V_MAXVA_16MB|V_MAXVA_8MB|V_MAXVA_4MB,
	0x1FF0,			
	0,
	DMMAX_32MB,
	DMTEXT_32MB
   },
#endif	STARTUP_DOT_C				/* Defined only in startup.c  */



#define	MMU_64MB 4

#ifdef	STARTUP_DOT_C				/* Defined only in startup.c  */
   {(caddr_t)V_MAXVA_64MB,	"64MB",
	0,0,0,0,	(SETS_64MB_MAXVA),
	2,4,8,	{0,1,2,3,	8,9,10,11},
	0,0,0,0,0,
	V_MAXVA_32MB|V_MAXVA_16MB|V_MAXVA_8MB|V_MAXVA_4MB,
	0x3FF0,			
	0,
	DMMAX_64MB,
	DMTEXT_64MB
   },
#endif	STARTUP_DOT_C				/* Defined only in startup.c  */



#define	MMU_128MB 5

#ifdef	STARTUP_DOT_C				/* Defined only in startup.c  */
   {(caddr_t)V_MAXVA_128MB,	"128MB",
	0,0,0,0,	(SETS_128MB_MAXVA),
	4,4,4,	{0,1,2,3},
	0,0,0,0,0,
	V_MAXVA_64MB|V_MAXVA_32MB|V_MAXVA_16MB|V_MAXVA_8MB|V_MAXVA_4MB,
	0x7FF0,			
	0,
	DMMAX_128MB,
	DMTEXT_128MB
   },
#endif	STARTUP_DOT_C				/* Defined only in startup.c  */

	/*
	 * 128Mb is as far as LCW's h/w goes,
	 * without relayout of the 68020 boardset
	 * to pick up <A29>.
	 */
#define   V_MAXVA	V_MAXVA_128MB 	/* 1 + biggest RevB virt. addr	*/
#define	MMU_MAX_INDX	    MMU_128MB	/* Index to V_MAXVA		*/

	/*
	 * 256Mb could be experimentally set up
	 * in the lab by making a small number
	 * of mods to the current RevB 68020 boardset.
	 * The following entries are here for completeness.
	 */
#define	MMU_256MB 6

#ifdef	STARTUP_DOT_C				/* Defined only in startup.c  */
   {(caddr_t)V_MAXVA_256MB,	"256MB",
	0,0,0,0,	(0),
	1,8,2,	{0,1},
	0,0,0,0,0,
	V_MAXVA_128MB|
	V_MAXVA_64MB|V_MAXVA_32MB|V_MAXVA_16MB|V_MAXVA_8MB|V_MAXVA_4MB,
	0xFFF0,			
	0,
	DMMAX_256MB,
	DMTEXT_256MB
   },

	/*
	 * Valid's MMU will require redesign
	 * to use 512Mb and beyond.
	 *
	 * Why didn't LCW assign A<28,27,26,25> to CTXT<3,2,1,0> ?
	 * He could have deferred hooking up A<28,27> pending
	 * a relayout of the 68020 boardset
	 * and given us a growth path...
	 * Again, the o/s group was never consulted...
	 */
#define	MMU_512MB 7
   {(caddr_t)V_MAXVA_512MB,	"512MB",
	0,0,0,0,	(0),
	1,16,1,	{0},
	0,0,0,0,0,
	V_MAXVA_256MB|V_MAXVA_128MB|
	V_MAXVA_64MB|V_MAXVA_32MB|V_MAXVA_16MB|V_MAXVA_8MB|V_MAXVA_4MB,
	0x1FFF0,			
	0,
	DMMAX_128MB,
	DMTEXT_128MB
   },

/*
 * These would require a wider, CTXT<6,5,4, 3,2,1,0> register
 * and a substantially (8x) larger, expensive mmu RAM.
 * We would probably be better off
 * with a translation look aside buffer (TLB).
 * That way, we could use separate page tables for p0 and p1,
 * as well as have the h/w update the page-has-been-referenced bit,
 * rather than have the s/w emulate such an endeavor with a "clock-hand".
 */
#define	MMU_1024MB 8
   {(caddr_t)V_MAXVA_1024MB,	"1GB",
	0,0,0,0,	(0),
	-1,32,0,	{0},
	0,0,0,0,0,
	V_MAXVA_512MB|V_MAXVA_256MB|V_MAXVA_128MB|
	V_MAXVA_64MB|V_MAXVA_32MB|V_MAXVA_16MB|V_MAXVA_8MB|V_MAXVA_4MB,
	0x3FFF0,			
	0,
	DMMAX_128MB,
	DMTEXT_128MB
   },

#define	MMU_2048MB 9
   {(caddr_t)V_MAXVA_2048MB,	"2GB",
	0,0,0,0,	(0),
	-1,64,0,	{0},
	0,0,0,0,0,
	V_MAXVA_1024MB|V_MAXVA_512MB|V_MAXVA_256MB|V_MAXVA_128MB|
	V_MAXVA_64MB|V_MAXVA_32MB|V_MAXVA_16MB|V_MAXVA_8MB|V_MAXVA_4MB,
	0x7FFF0,			
	0,
	DMMAX_128MB,
	DMTEXT_128MB
   },

#define	MMU_4096MB 10
   {(caddr_t)V_MAXVA_4096MB,	"4GB",
	0,0,0,0,	(0),
	-1,128,0,	{0},
	0,0,0,0,0,
	V_MAXVA_2048MB|V_MAXVA_1024MB|V_MAXVA_256MB|V_MAXVA_128MB|
	V_MAXVA_64MB|V_MAXVA_32MB|V_MAXVA_16MB|V_MAXVA_8MB|V_MAXVA_4MB,
	0xFFFF0,			
	0,
	DMMAX_128MB,
	DMTEXT_128MB
   },

};
#else	STARTUP_DOT_C
 ;
#endif	STARTUP_DOT_C
#endif	LOCORE
#endif	M68020

/*
 * SWITCH.REGISTER<7..0>:
 * ======================
 */
#ifndef WHITE
#define SWITCHES_HW_ADDR	0x1F801			/* Hardware address */
#define V_SWITCHES	(*(char*) SWITCHES_HW_ADDR)	/* Switch Register */
#define V_SWITCH_BIGMAP		0x08		/* switch for big map */
#define V_SWITCH_LARGEVM	0x10		/* switch for large VM */
#endif


#ifdef	WHITE
/*
 * "The fault of our ways."	Anon.
 *
 * ERROR.REGISTER<7..0>:
 * =====================
 */
#define	EREG_HW_ADDR	0x840005		/* Hardware address */
#define	V_EREG		(*(char*) EREG_HW_ADDR)	/* Error Register */

#define V_SUMERR	0x80			/* summary error */
#define V_PARERR	0x40			/* parity error */
#define V_DMAERR	0x20			/* error during DMA */
#define V_DMADELAY	0x10			/* error during DMA */

#define V_SMERR		0x02			/* segment map error */
#define V_PMERR		0x01			/* page map error */

#define	V_CLR_ERRS	V_EREG		/* Write to clear Rupts and Errs */

#else	WHITE

#if	defined(M68000) || defined(M68010)
/*
 * ERROR.REGISTER<7..4>:	LOW;
 * ERROR.REGISTER<3..0>:	(From the circuit diagrams.)
 *
 *   ERROR.REGISTER<3>:	TIMEOUT<0>:		No response;
 *   ERROR.REGISTER<2>:	ADR.BNDS.ERR<0>:	Addr out of bounds;
 *   ERROR.REGISTER<1>:	SMAP.ERR<0>:		Segment-map error;
 *   ERROR.REGISTER<0>:	PMAP.ERR<0>:		Page-map error.
 */
#define	EREG_HW_ADDR	0x1E801			/* Hardware address */
#define	V_EREG		(*(char*) EREG_HW_ADDR)	/* 8-bit Error Register  */
#define	V_CLR_ERRS	V_EREG		/* Write to clear rupts and errs */

#define V_TIMEOUT	0x08		/* Location did not respond	 */
#define V_BOUNDS	0x04		/* Address out of bounds	 */
#define V_SMERR		0x02		/* segment map error		 */
#define V_PMERR		0x01		/* page map error		 */

#endif	defined(M68000) || defined(M68010)



#ifdef	M68020
/*
 * Note that the error register
 * for the M68020 is INCOMPATIBLE
 * with both the M68000 & M68010.
 *
 * ERROR.REGISTER<31..8>:	MB_BERR_PHYSADDR<32..0>;
 * ======================
 *
 * ERROR.REGISTER<7..0>:	(From the circuit diagrams.)
 * =====================
 *
 *   ERROR.REGISTER<7>:	MBSEQ.BHEN<0>:		Mbus busHigh Enable;
 *   ERROR.REGISTER<6>:	MBSEQ.MB.W<0>:		Mbus write;
 *   ERROR.REGISTER<5>:	MBCMDR.MEM.EN<0>:	Mbus ECM enable;
 *   ERROR.REGISTER<4>:	UNUSED<0>:		Unused;
 *
 *   ERROR.REGISTER<3>:	SUM.BERR*<0>:		'or' next 3 bits + TIMEOUT.BERR
 *   ERROR.REGISTER<2>:	BAD.LADR.ERR<0>:	Bad logical address;
 *   ERROR.REGISTER<1>:	SMAP.ERR<0>:		Segment-map error;
 *   ERROR.REGISTER<0>:	PMAP.ERR<0>:		Page-map error.
 */
#define	EREG32_HW_ADDR	0x1E800			    /* Hardware address      */
#define	V_EREG32	(*(u_long*) EREG32_HW_ADDR) /* 32-bit Error Register */
#define	V_CLR_ERRS32	V_EREG32	/* Write to clear rupts and errs     */

#define V_EREG32_PHYSADDR_SHIFT	8	/* # bits to shift physaddr	*/

#define V_MBSEQ_MB_W	0x40		/* Mbus Write			*/
#define V_MBCMDR_MEM_EN	0x20		/* Mbus Memory enable		*/
#define V_TIMEOUT_INT	0x10		/* Location did not respond	*/

#define V_SUM_BERR_BAR	0x08		/* Summation of several ERRs	*/
#define V_BAD_LADR_ERR	0x04		/* BAD.LADR.ERR			*/
#define V_SMAP_BERR	0x02		/* Segment map error		*/
#define V_PMAP_BERR	0x01		/* Page map error		*/

/*
 * (Virtual) "TIMEOUT.BERR" is inferred to be
 * asserted if all other consitituents
 * of SUM.BERR* are NOT asserted.
 */
#define	V_TIMEOUT_BERR(x)	(   !	((x) &	( V_BAD_LADR_ERR\
						 |V_SMAP_BERR	\
						 |V_PMAP_BERR	\
						)		\
					)			\
				)
#endif	M68020

#define	V_PROM		0x10000		/* Starting address of cpu's EPROM */

/*
 * Processor dependent manipulation
 * of the ERROR.REGISTER on the Valid CPU board(s).
 *
 * Note that ONLY the l.o. 4 bits of the error register
 * are FUNCTIONALLY identical for ALL flavors
 * of the CPU boards.
 */
#define	testErrorReg(bitMask) ((chipType==CHIPTYPE_68020) \
				? (error32 & (bitMask))	  \
				: (error   & (bitMask)))

#define	setErrorReg(bitMask)				\
		if (chipType==CHIPTYPE_68020)		\
			V_CLR_ERRS32 = (u_long)(bitMask);	\
		else	V_CLR_ERRS   =	   (bitMask);

#endif	WHITE

/*
 * Onboard segment table entry:
 */
#define V_SUNUSED	0xF000			/* seg map: unused bits	     */
#define V_SUSER		0x0800			/* seg map => User access    */
#define V_SWRITE	0x0400			/* seg map => Write access   */
#define V_SREAD		0x0200			/* seg map => Read access    */
#define V_SEXEC		0x0100			/* seg map => Execute access */
#define V_SEG_INVALID	0x0000			/* No access at all	     */

#define V_SKERNEL	(V_SEXEC|V_SWRITE|V_SREAD)/* kernel mode access */

/*
 * Onboard page table hardware.
 */
#ifdef	WHITE
#define V_USED		0x2000			/* Page has been accessed*/
#define V_DIRTY		0x1000			/* Page has been written*/
#define V_MISSING	0x0800			/* Page not present	*/
#define V_PAGE_INVALID	0x0800			/* Page map => invalid */
#define V_PAGE_RO	0x0400			/* Page is read only */

#define V_PAGEMASK	0x03FF			/* Physical page number */
#ifdef	M68020
#define	V_MBIO		0			/* Null definitions for WHITE */
#define	V_NONCACHED	0
#endif	M68020
#else	WHITE

/*
 * PAGE.TABLE.ENTRY<15..12>:	(from the circuit drawings:)
 *
 * ...also known as PAGE.CONTROL<3..0>
 *
 * Masks for page control bits in page table entry h/w
 * in Valid's s32 onboard mmu.
 */
#define	PMAP_USED	0x8000		/* PAGE.CONTROL<3>: maintained by H/W */
#define	PMAP_DIRTY	0x4000		/* PAGE.CONTROL<2>: maintained by H/W */
#define	PMAP_LCL	0x2000		/* PAGE.CONTROL<1> */
#define	PMAP_IO		0x1000		/* PAGE.CONTROL<0> */

/*
 *	PAGE.CONTROL<3..2>:
 */
#define V_USED		PMAP_USED	/* 1 ==> Page has been accessed    */
#define V_DIRTY		PMAP_DIRTY	/* 1 ==> Page has been written to  */

/*
 *	PAGE.CONTROL<1..0>:
 */
#define V_PAGE_INVALID	(PMAP_LCL|PMAP_IO)	/* Page not valid	      */
#define V_MISSING	V_PAGE_INVALID		/* Page not represented in map*/

#define V_MBIO		PMAP_IO		/* 1 ==> Page maps to Multibus I/O  */
#define	V_MBMEM		0x0		/* 0 ==> Page maps to Multibus MEM  */


#ifdef	M68020
/*
 * There are TWO bitstring values that result 
 * in the board's NON-caching of data values:
 *
 *	PAGE.CONTROL<1..0> == 01B ==> present + mbio -- functional side effect.
 *
 * ...and the (unused in the kernel) explicit cache-bypassing
 * of Valid's M68020 onboard cache:
 *
 *	PAGE.CONTROL<1..0> == 10B ==> (EXPLICIT) non-caching.
 */

#define V_NONCACHED	(PMAP_LCL|V_MBMEM)	/* Page not cached	*/
#endif	M68020

#define V_PAGEMASK	0x0FFF			/* Physical page number */
#endif	WHITE



/*
 * Given a Valid virtual page number,
 * use these masks to extract:
 */
#ifndef	M68020_REV_B
#define V_VSEGNO	0x0FF0			/* the segment number */
#else	M68020_REV_B
#define V_VSEGNO	0x7FF0			/* Segment #: 3+24bit address */
#endif	M68020_REV_B
#define V_VPAGENO	0x000F			/* the page number */

#define	V_SEGMASK	(V_VSEGNO<<PGSHIFT)	/* Seg-addr from addr */
#define	V_VSEGNO_MASK	(V_VSEGNO>>PTOSSHIFT)	/* Seg-# from page #  */

#ifdef	M68020

/*
 * We flush the write-queue by reading two known
 * locations that are 'cacheSize' bytes apart,
 * thus forcing a cache-miss, which in turn dallies
 * until the write-queue is (or becomes) empty.
 */
#define	flushWriteQueue() {if (chipType==CHIPTYPE_68020) {		  \
				register i = *(u_long *) K_A;		  \
					 i = *(u_long *)(K_A + cacheSize);\
			   }						  \
			  }
#endif	M68020

#endif	CPU_ALREADY_DEFINED
