/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION  1986,1987
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header:mmu.h 12.0$ */
/* $ACIS:mmu.h 12.0$ */
/* $Source: /ibm/acis/usr/sys/ca/RCS/mmu.h,v $ */

#if !defined(lint) && !defined(LOCORE) && defined(RCS_HDRS)
static char *rcsidmmu = "$Header:mmu.h 12.0$";
#endif

#define MMUBASE 0x810000
#define MMU_SEGR 0
#define MMU_IOBR 0x10
#define MMU_SER  0x11
#define MMU_SEAR 0x12
#define MMU_TRAR 0x13
#define MMU_TIDR 0x14
#define MMU_TCR  0x15
#define MMU_RAM  0x16
#define MMU_ROS  0x17
#define MMU_TLBS 0x80
#define	MMU_SEG_TLB 0x81
#define MMU_CRA  0x83

#define MMU_NSEGREGS 16
#define MMU_SEGREG0  0x810000
#define MMU_SEGREGSTEP 1

#define MMU_IOBASE   0x810010
#define MMU_EXC_ADDR 0x810012
#define MMU_REALADDR 0x810013
#define MMU_TID_ADDR 0x810014
#define MMU_INV_TLB  0x810080
#define MMU_INV_SEG  0x810081
#define MMU_INV_ADDR 0x810082
#define MMU_VTOP     0x810083


/* These TLB address should not be used.  Rather the "translate assist"
 * functions of the MMU hardware should be used instead.
 */
#define MMU_NTLBS 16
#define MMU_TLBAW1   0x810040
#define MMU_TLBBW1   0x810050
#define MMU_TLBSTEP 1
#define MMU_TLBUNUSED 0  /* valid bit is zero */

#define MMU_REFBITS  0x811000
#define MMU_MODBITS  0x811000
#define MMU_REFMOD_STEP 1

#define MMU_CONTROL	0x810015
#define MMU_VR0		0x8000  /* virtual = real for segment register zero */
#define MMU_PEI		0x4000  /* interrupt on successful parity error retry */
#define MMU_RAS		0x2000  /* enable RAS diagnostic mode */
#define MMU_IPTLOOP	0x1000  /* terminate IPT search after 128 links */
#define MMU_ECC		0x0800  /* interrupt on correctable ECC error */
#define MMU_TLB		0x0400  /* interrupt on successful TLB reload */
#define MMU_RPE		0x0200  /* ref/mod array has parity */
#define MMU_4K		0x0100  /* 4K page size (bit on), 2K page size (bit off) */
#define MMU_HATBASE	0x00FF  /* HATIPT base address */

#define MMU_EXCEPTION	0x810011
#define	MMU_EX_SEG	0x20000  /* segment protection (P,C,I bits in seg reg) */
#define	MMU_EX_ACKD	0x10000  /* PMUC ACKD */
#define	MMU_EX_NACKD	0x08000  /* PMUC NAKD */
#define	MMU_EX_ADDR	0x04000  /* invalid storage address (ROS/RAM spec reg) */
#define	MMU_EX_IO	0x02000  /* invalid i/o address (mmu's 64K block) */
#define	MMU_EX_LOAD	0x01000  /* load access (bit on), store access (bit off)*/
#define MMU_EX_ECC	0x00800  /* uncorrectable storage error */
#define MMU_EX_CORECC	0x00400  /* correctable ECC error */
#define	MMU_EX_TLBLD	0x00200  /* successful TLB reload */
#define	MMU_EX_PARITY	0x00100  /* ref/mod array parity error */
#define	MMU_EX_ROS	0x00080  /* write to ROS */
#define	MMU_EX_IPT	0x00040  /* IPT specification (128 links or end chain?) */
#define	MMU_EX_EXT	0x00020  /* external device error */
#define MMU_EX_MULTX	0x00010  /* multiple exception */
#define MMU_EX_FAULT	0x00008  /* page fault */
#define MMU_EX_TLB	0x00004  /* TLB specification (both TLB's matched) */
#define MMU_EX_KEYS	0x00002  /* storage protection (S,K bits in seg reg,
				  and key bits in tlb) */
#define	MMU_EX_LOCK	0x00001  /* data lock (S in seg reg, tid reg,
				  and tid,write,lock bits in tlb) */
/* #define MMU_EX_OHOH   0x3E3E5  /* all unexpected exceptions */
#ifdef ATR
#define MMU_EX_OHOH   (MMU_EX_ACKD+MMU_EX_NACKD+MMU_EX_ADDR+MMU_EX_IO+MMU_EX_ECC+MMU_EX_PARITY+MMU_EX_ROS+MMU_EX_IPT+MMU_EX_EXT+MMU_EX_TLB) /* all unexpected exceptions */
#else !ATR
#define MMU_EX_OHOH   (MMU_EX_ACKD+MMU_EX_NACKD+MMU_EX_ADDR+MMU_EX_IO+MMU_EX_ECC+MMU_EX_PARITY+MMU_EX_ROS+MMU_EX_IPT+MMU_EX_EXT+MMU_EX_TLB+MMU_EX_LOCK) /* all unexpected exceptions */
#endif !ATR
#define MMU_EX_OHOH_UPPER (MMU_EX_OHOH>>16)
#define MMU_EX_OHOH_LOWER (MMU_EX_OHOH&0xffff)


#define MMU_UNDEF_PTR 0x97FF	/* undefined pointer value for debugging */
#define MMU_END_PTR 0x97fe	/* initial value set by lohatipt */

#ifdef IBMRTPC
#define get_mod_bit(rpage) (ior(MMUBASE+0x1000+(rpage))&1)
#define set_mod_bit(rpage,v) (iow(MMUBASE+0x1000+(rpage),\
(ior(MMUBASE+0x1000+(rpage))&2)|(v)))

#define get_ref_bit(rpage) ((ior(MMUBASE+0x1000+(rpage))>>1)&1)
#define set_ref_bit(rpage,v) (iow(MMUBASE+0x1000+(rpage),\
(ior(MMUBASE+0x1000+(rpage))&1)|((v)<<1)))

#define set_refmod_bits(rpage,ref,mod) iow(MMUBASE+0x1000+(rpage),\
((ref)<<1)|(mod))
#endif IBMRTPC

#ifdef ATR
#define IOBUGMASK 0x003000
 
#define get_mod_bit(rpage) (ior((MMUBASE+0x1000+(rpage))^IOBUGMASK)&1)
 
#define set_mod_bit(rpage,v) (iow((MMUBASE+0x1000+(rpage))^IOBUGMASK,\
(ior((MMUBASE+0x1000+(rpage))^IOBUGMASK)&2)|(v)))
 
#define get_ref_bit(rpage) ((ior((MMUBASE+0x1000+(rpage))^IOBUGMASK)>>1)&1)
 
 
#define set_ref_bit(rpage,v) (iow((MMUBASE+0x1000+(rpage))^IOBUGMASK,\
(ior((MMUBASE+0x1000+(rpage))^IOBUGMASK)&1)|((v)<<1)))
 
#define set_refmod_bits(rpage,ref,mod) iow((MMUBASE+0x1000+(rpage))^IOBUGMASK,\
((ref)<<1)|(mod))
#endif ATR

#define get_hatptr(ipte) ((ipte)->hat_ptr)
#define set_hatptr(ipte,v) ((ipte)->hat_ptr = (v))
#define get_iptptr(ipte) ((ipte)->ipt_ptr)
#define set_iptptr(ipte,v) ((ipte)->ipt_ptr = (v))

#define MMU_SID_SYSTEM 0x200
#define MMU_SID_UNUSED 0x201
#ifdef ATR
#define MMU_SID_IO     0x202
/* defines for ATR */
#define MMU_IO_SEG		0xd
/*
 * These defines control access to the I/O segment by using the
 * transaction ID. TID = 0 access, TID = anything else is no access.
 */
#define MMU_IO_ENABLE 	0
#define MMU_IO_DISABLE 	1
#endif

/* bit definitions for segment registers */
#define MMU_SEG_PRESENT 0x10000
#define MMU_SEG_P	0x10000		/* 1=segment present */
#define MMU_SEG_C	0x08000		/* 1=no cpu access */
#define MMU_SEG_I	0x04000		/* 1=no I/O access */
#define MMU_SEG_SID	0x03ffc		/* mask for Segment ID */
#define MMU_SEG_S	0x00002		/* 1=special, 0=normal */
#define MMU_SEG_K	0x00001		/* Protect key bit, 1=public rules */
#define MMU_SID_SHIFT	2		/* shift to get SID */


#define make407sid(p) (p->p_ndx)
#define make410sid(xp) (0x1FF-(xp-text))
#define makeUsid(p) (~p->p_ndx&0x3FF)
#define makeP0sid(p) (~p->p_sid1&0x3FF)

#define get_segreg(reg) ((ior(MMUBASE+(reg))>>2)&0xFFF)
#define set_segreg(reg,sid) (iow(MMUBASE+(reg),((sid)<<2)|MMU_SEG_PRESENT))


/***** Universal Truths *****/

#define MMU_VPAGE_BITS 17
#define MMU_VPAGE_MASK ((1<<MMU_VPAGE_BITS)-1)
#define MMU_SID_MASK (0xFFF<<MMU_VPAGE_BITS)

#define MMU_ADDRTAG_MASK 0x1FFFFFFF
#define MMU_SEGSHIFT 24

/* storage protection variables */

#define MMU_KEY_SHIFT 30
#define MMU_KEY_BITS 0xC0000000
#define MMU_KEY_KW   0  /* kernel write, user none */
#define MMU_KEY_URKW 1  /* kernel write, user read */
#define MMU_KEY_UW   2  /* kernel write, user write */
#define MMU_KEY_URKR 3  /* kernel read, user read */
/*      MMU_KEY_KR      /* kernel read, user none */
/*      MMU_KEY_NOACC   /* kernel none, user none */

#define MMU_KEYBIT(k) (1<<((unsigned)(k)>>30))  /* k = hatipt.key_addrtag */
#define MMU_KEY_OK(k) (1<<(k))  /* k = MMU_KEY_KW,URKW,UW,URKR */

#define UWRITE_OK (1<<MMU_KEY_UW)
#define UREAD_OK ((1<<MMU_KEY_UW)|(1<<MMU_KEY_URKW)|(1<<MMU_KEY_URKR))
#define KWRITE_OK (1<<MMU_KEY_KW)
#define KREAD_OK ((1<<MMU_KEY_KW)|(1<<MMU_KEY_UW)|\
(1<<MMU_KEY_URKW)|(1<<MMU_KEY_URKR))

#ifndef LOCORE

struct hatipt_entry  /* more or less */
  {
    long key_addrtag;
    unsigned short hat_ptr,ipt_ptr;
    unsigned char w,tid;
    unsigned short lockbits;
    long reserved;
  };

struct ipt_entry  /* all fields broken out */
  {
    unsigned ipt_key   :2;
    unsigned ipt_r     :1;
    unsigned ipt_sid   :12;
    unsigned ipt_vpage :17;
    unsigned ipt_hat_e :1;
    unsigned           :2;
    unsigned ipt_hatptr:13;
    unsigned ipt_ipt_l :1;
    unsigned           :2;
    unsigned ipt_iptptr:13;
    unsigned           :7;
    unsigned ipt_w     :1;
    unsigned ipt_tid   :8;
    unsigned ipt_locks :16;
    unsigned           :32;
  };

#define MMU_ENDCHAIN(ptr) ((ptr)&0x8000)

#ifdef KERNEL
extern struct hatipt_entry *MMU_HATIPT;
extern int MMU_HASHMASK;
#endif KERNEL

#define MMU_HASH(seg,vpage) ((seg ^ vpage) & MMU_HASHMASK)

#endif
#define VR0_BIT         (1<<(31-16))
#define GET_MMU_TCR     (ior(MMUBASE+MMU_TCR))
#define SET_MMU_TCR(v)  (iow(MMUBASE+MMU_TCR, v))
#define SET_VR0         (SET_MMU_TCR (GET_MMU_TCR | VR0_BIT))
#define CLR_VR0         (SET_MMU_TCR (GET_MMU_TCR & ~VR0_BIT))
#define GET_VR0(x)	(SET_MMU_TCR ((x = GET_MMU_TCR) | VR0_BIT))
#define SET_VR(x)	(SET_MMU_TCR (x))

#define MMU_ROS_SPEC	0x807	/* value for ROS register mapping in ROS */

#define GETSEG(addr) ((unsigned)(addr) >> 28)	/* get segment number */
#define GETSUBSEG(addr) (((unsigned) (addr) >> 24) & 0xf)

#ifdef DUALCALL
/*
 * NOTE: we protect beyond our current page to handle cases where the stack
 * has been unwound before an exception is detected. The hc compiler will
 * insure that a processor sync is done on all stack frames > 1 page.
 */
#define GROWSP(stack) (grow((unsigned) ((stack)+(u.u_calltype ? FRM_PROTECT - NBPG  : 0))))
#else
#define GROWSP(stack) (grow((unsigned) ((stack)+ FRM_PROTECT - NBPG)))
#endif DUALCALL
