/*
 * @(#) spl.h $Date: 1999/05/10 00:36:11 $Revision: r11ros/cup_ros_ep3_pb/2 PATCH_11.00 (PHKL_18543)
 */


#ifndef	SPL_INCLUDED
#define	SPL_INCLUDED
/*
 * This files defines the processor (spl()) levels. It also assigns certain
 * eirr bits. For the series 800, the following interrupt priority levels
 * are defined:
 *
 *
 *	SPLPREEMPTOK() - allow all interrupts
 *		Enables LPMC, powerfail and all eirr bits, except
 *		HPMC_INT, which is reserved for crash dump use.
 *
 *	SPLNOPREEMPT() - disable kernel preemption
 *		Same as SPLPREEMPTOK(), except 'trap type' interrupts are
 *		disabled. 'trap type' interrupts cause the kernel to be
 *		preempted by another process when at SPLPREEMPTOK().
 *		SPLNOPREEMPT() and higher spl levels indicate the kernel
 *		cannot be preempted.
 *		Currently there are 2 'trap type' interrupts:
 *			MPSCHED -  In an MP system, one cpu tells another cpu
 *			  	   to check the runq by sending this interupt
 *				   type.
 *			KPREEMPT - When the kernel is executing and a higher
 *				   priority process should run (eg. clock tick
 *				   recomputed priorities or external interrupt
 *				   caused a wakeup()), the kernel sends itself
 *				   a KPREEMPT interrupt to cause a preemption
 *				   when the spl level is SPLPREEMPTOK().
 *
 *	SPL2() - disable software interrupts
 *		Same as SPLNOPREEMPT(), except 'software priority' interrupts
 *		are disabled. Software interrupts are often sent when
 *		the kernel is executing on the ics at a high interrupt priority
 *		and it wants to schedule some processing to be done later after
 *		all high priority interrupts (eg. device IO) are serviced.
 *		The following software interrupts are used:
 *			SOFTNET    - When a networking IO driver receives an
 *				     inbound packet, it removes the packet
 *				     and schedules other networking code to
 *				     process the packet at a lower priority.
 *				     by sending a SOFTNET interrupt.
 *		In addition to software interrupts, SPL2() also disables
 *		interrupts from low priority Type-B DMA IO modules. Currently,
 *	        there is only one low priority IO module (ieee_8024 - map).
 *
 *	SPL5() - disable IO modules
 *		 Same as SPL2(), except all IO module interrupts are disabled.
 *
 *	SPL6() - disable hard clock and kernel powerfail recovery
 *		 Same as SPL5() except hard clock interrupts are disabled.
 *
 *	SPL7() - disable the world
 *		 Same as SPL6(), except powerfail and RDB interrupts and LPMC
 *		 are disabled - PSW_I is off.
 */

/*
 * WARNING: many of these defines are used by assembly. Therefore,
 * 'C' operators ahould not be used (eg. & | >>, (), etc.)
 */


#ifndef _SYS_STDSYMS_INCLUDED
#ifdef _KERNEL_BUILD
#    include "../h/stdsyms.h"
#else  /* ! _KERNEL_BUILD */
#    include <sys/stdsyms.h>
#endif /* _KERNEL_BUILD */
#endif  /*  _SYS_STDSYMS_INCLUDED  */

#ifndef LOCORE
#ifdef _KERNEL_BUILD
#    include "../h/kern_svcs.h"
#else  /* ! _KERNEL_BUILD */
#    include <sys/kern_svcs.h>
#endif /* _KERNEL_BUILD */
#endif  /*  LOCORE  */

#ifdef _KERNEL

#  if defined(GPROF) || defined(PGPROF)
#    define GPROF_INT_BIT         0
#    define CLOCK_INT_BIT         4
#  else
#    define CLOCK_INT_BIT         0
#  endif
#  define REMOTE_PFAIL_INT_BIT    1
#  define KERN_PFR_INT_BIT        2
/*  bit 3 is required by type-a direct devices */
/*  bits 5 & 6 are used by HydraNova models 64 & 96.  These can   */
/*  be shared with RDB but not with I/O devices like lan cards.   */
#ifdef RDB
#  define SYNC_INT_BIT            5
#  define RDB_INT_BIT             6
#endif
#  define CLOCK_RESYNC_INT_BIT    7
#ifdef __LP64__
#  define PDH_INT_BIT             19UL
#endif
#  define SW_TRIGGER_6_INT_BIT    20
#  define SW_TRIGGER_5_INT_BIT    21
#  define SW_TRIGGER_4_INT_BIT    22
#  define SW_TRIGGER_3_INT_BIT    23
#  define SW_TRIGGER_2_INT_BIT    24
#  define SW_TRIGGER_1_INT_BIT    27
#  define SOFTNET_INT_BIT         25
#  define IOFORW_INT_BIT          26 
#  define MPSCHED_INT_BIT         28
#  define UNUSED_TRAP_INT_BIT29   29
#  define KPREEMPT_INT_BIT        30
#  define HPMC_INT_BIT            31
#  define LPRIV_INT_BIT           32	/* This is a fake interrupt bit used
				         * in take_a_trap() to cause a
				         * lower priv transfer trap.
				         */
# ifdef __LP64__

/* 64XXX:
 * The following is a workaround to the problem where the assembler does not
 * handle literals in the constand (L suffix). It may be taken out and the
 * L suffix will be explicity added to the constants. 
 *
 * REVISIT: Will be removed once the assembler is fixed.
 *
 */
#   ifndef LOCORE
#     ifdef __STDC__
#       define LONG(x)      x ## L
#     else
#       define LONG(x)      x/**/L
#     endif
#   else
#     define LONG(x)        x
#   endif

/*
 * These two constants are to be used by the LP64 assembly routines
 * to load the lower word of the SPL and interrupt mask.
 */
#   define SPL_LO          0x00000000
#   define INT_ENABLE_LO   0xffffffff

#   define MSB	           LONG(0x8000000000000000)  /* Most Significant Bit */

#   if defined(GPROF) || defined(PGPROF)
#     define GPROF_INT_ENABLE        LONG(0x8000000000000000)
#     define GPROF_INT_ENABLE_HI     0x80000000
#     define GPROF_INT_ENABLE_NIBBLE_0 0x8
#     define GPROF_INT_ENABLE_LO     SPL_LO

#     define CLOCK_INT_ENABLE        LONG(0x0800000000000000)
#     define CLOCK_INT_ENABLE_HI     0x08000000
#     define CLOCK_INT_ENABLE_LO     SPL_LO
#   else  /* ! GPROF || PGPROF */
#     define CLOCK_INT_ENABLE        LONG(0x8000000000000000)
#     define CLOCK_INT_ENABLE_HI     0x80000000
#     define CLOCK_INT_ENABLE_LO     SPL_LO
#   endif /* ! GPROF || PGPROF */

#  define REMOTE_PFAIL_INT_ENABLE LONG(0x4000000000000000)
#  define REMOTE_PFAIL_INT_ENABLE_HI 0x40000000
#  define REMOTE_PFAIL_INT_NIBBLE_0  0x4
#  define REMOTE_PFAIL_INT_ENABLE_LO SPL_LO

#  define KERN_PFR_INT_ENABLE	  LONG(0x2000000000000000)
#  define KERN_PFR_INT_ENABLE_HI  0x20000000
#  define KERN_PFR_INT_ENABLE_LO  SPL_LO

/* The CLOCK_RESYNC bit is used by the monarch processor in an MP system
 * to bring a non-monarch processor into the synchronization code.
 * The interval timer synchronization code coordinates the monarch and
 * non-monarch and allows the non-monarch to compute a couple of local
 * variables that may be used by it at any time to compute an estimate
 * of the monarch's itimer value.  The CLOCK_INT_BIT used to be used for
 * this purpose, but was abandoned, since a non-monarch could receive
 * that interrupt either from the monarch or from its own interval timer.
 */

#define CLOCK_RESYNC_INT_ENABLE    LONG(0x0100000000000000)
#define CLOCK_RESYNC_INT_ENABLE_HI 0x01000000
#define CLOCK_RESYNC_INT_ENABLE_LO SPL_LO

#define SW_TRIGGER_6_INT_ENABLE    LONG(0x0000080000000000)
#define SW_TRIGGER_6_INT_ENABLE_HI 0x00000800
#define SW_TRIGGER_6_INT_ENABLE_LO SPL_LO

#define SW_TRIGGER_5_INT_ENABLE    LONG(0x0000040000000000)
#define SW_TRIGGER_5_INT_ENABLE_HI 0x00000400
#define SW_TRIGGER_5_INT_ENABLE_LO SPL_LO

#define SW_TRIGGER_4_INT_ENABLE    LONG(0x0000020000000000)
#define SW_TRIGGER_4_INT_ENABLE_HI 0x00000200
#define SW_TRIGGER_4_INT_ENABLE_LO SPL_LO

#define SW_TRIGGER_3_INT_ENABLE    LONG(0x0000010000000000)
#define SW_TRIGGER_3_INT_ENABLE_HI 0x00000100
#define SW_TRIGGER_3_INT_ENABLE_LO SPL_LO

#define SW_TRIGGER_2_INT_ENABLE    LONG(0x0000008000000000)
#define SW_TRIGGER_2_INT_ENABLE_HI 0x00000080
#define SW_TRIGGER_2_INT_ENABLE_LO SPL_LO

#define SW_TRIGGER_1_INT_ENABLE    LONG(0x0000001000000000)
#define SW_TRIGGER_1_INT_ENABLE_HI 0x00000010
#define SW_TRIGGER_1_INT_ENABLE_LO SPL_LO

#define SOFTNET_INT_ENABLE         LONG(0x0000004000000000)
#define SOFTNET_INT_ENABLE_HI      0x00000040
#define SOFTNET_INT_ENABLE_LO      SPL_LO

#define IOFORW_INT_ENABLE          LONG(0x0000002000000000)
#define IOFORW_INT_ENABLE_HI       0x00000020
#define IOFORW_INT_ENABLE_LO       SPL_LO

/*
 *	First trap type interrupt bit.
 */

#define MPSCHED_INT_ENABLE          LONG(0x0000000800000000)
#define MPSCHED_INT_ENABLE_HI       0x00000008
#define MPSCHED_INT_ENABLE_LO       SPL_LO

#define UNUSED_TRAP_INT_ENABLE29    LONG(0x0000000400000000)
#define UNUSED_TRAP_INT_ENABLE29_HI 0x00000004
#define UNUSED_TRAP_INT_ENABLE29_LO SPL_LO

#define KPREEMPT_INT_ENABLE         LONG(0x0000000200000000)
#define KPREEMPT_INT_ENABLE_HI      0x00000002
#define KPREEMPT_INT_ENABLE_LO      SPL_LO

/*
 * HPMC_INT_BIT should never be enabled, except by crash dump assembly.
 */
#define HPMC_INT_ENABLE            LONG(0x0000000100000000)
#define HPMC_INT_ENABLE_HI         0x00000001
#define HPMC_INT_ENABLE_LO         SPL_LO

#if defined(GPROF) || defined(PGPROF)
#define _GPROF_SPL6     GPROF_INT_ENABLE
#define _GPROF_SPL6_HI  GPROF_INT_ENABLE_HI
#define _GPROF_SPL6_NIBBLE_0  GPROF_INT_ENABLE_NIBBLE_0
#define _GPROF_SPL6_LO  GPROF_INT_ENABLE_LO

#define _GPROF_SPL5     GPROF_INT_ENABLE | CLOCK_INT_ENABLE
#define _GPROF_SPL5_HI  GPROF_INT_ENABLE_HI | CLOCK_INT_ENABLE_HI
#define _GPROF_SPL5_LO  GPROF_INT_ENABLE_LO | CLOCK_INT_ENABLE_LO
#else
#define _GPROF_SPL6     LONG(0)
#define _GPROF_SPL6_HI  0
#define _GPROF_SPL6_NIBBLE_0  0
#define _GPROF_SPL6_LO  0

#define _GPROF_SPL5     LONG(0)
#define _GPROF_SPL5_HI  0
#define _GPROF_SPL5_LO  0
#endif

#ifdef RDB
#define _RDB_SPL6       LONG(0x0600000000000000)
#define _RDB_SPL6_HI    0x06000000
#define RDB_INT_NIBBLE_1 0x6
#define _RDB_SPL6_NIBBLE_1 0x6
#define _RDB_SPL6_LO    SPL_LO
#else
#define _RDB_SPL6       LONG(0)
#define _RDB_SPL6_HI    0
#define RDB_INT_NIBBLE_1 0
#define _RDB_SPL6_NIBBLE_1 0
#define _RDB_SPL6_LO    0
#endif
#define _RDB_SPL5         _RDB_SPL6
#define _RDB_SPL5_HI      _RDB_SPL6_HI
#define _RDB_SPL5_LO      _RDB_SPL6_LO

#define	RDB_INT_ENABLE    _RDB_SPL6
#define	RDB_INT_ENABLE_HI _RDB_SPL6_HI
#define	RDB_INT_ENABLE_LO _RDB_SPL6_LO

/*
 * The value for SPL7 is arbitrary, since psw-I is off; it is less than
 * five bits so that comib can be used to test it.
 */

#define SPL7            LONG(0x0000000700000000)
#define SPL7_HI         0x00000007
#define SPL7_LO         SPL_LO

#define SPL6            (LONG(0x4000000000000000) | _GPROF_SPL6 | _RDB_SPL6)
#define SPL6_HI         (0x40000000 | _GPROF_SPL6_HI | _RDB_SPL6_HI)
#define SPL6_NIBBLE_0  (REMOTE_PFAIL_INT_NIBBLE_0 | _GPROF_SPL6_NIBBLE_0)
#define SPL6_NIBBLE_1   _RDB_SPL6_NIBBLE_1
#define SPL6_LO         SPL_LO

#define SPL5            (LONG(0xe100080000000000) | _GPROF_SPL5 | _RDB_SPL5)
#define SPL5_HI         (0xe1000800 | _GPROF_SPL5_HI | _RDB_SPL5_HI)
#define SPL5_LO         SPL_LO

#define SPL4            LONG(0xfffffc00ffffffff)
#define SPL4_HI         0xfffffc00
#define SPL4_LO         INT_ENABLE_LO

#define SPL3            LONG(0xfffffe00ffffffff)
#define SPL3_HI         0xfffffe00
#define SPL3_LO         INT_ENABLE_LO

#define SPL2            LONG(0xffffff00ffffffff)
#define SPL2_HI         0xffffff00 
#define SPL2_LO         INT_ENABLE_LO

#define SPL1            LONG(0xffffffc0ffffffff)
#define SPL1_HI         0xffffffc0 
#define SPL1_LO         INT_ENABLE_LO

#define SPL0            SPLNOPREEMPT
#define SPL0_HI         SPLNOPREEMPT_HI
#define SPL0_LO         INT_ENABLE_LO

#define SPLNOPREEMPT    LONG(0xfffffff0ffffffff)
#define SPLNOPREEMPT_HI 0xfffffff0
#define SPLNOPREEMPT_LO INT_ENABLE_LO

#define SPLPREEMPTOK    LONG(0xffffffffffffffff)
#define SPLPREEMPTOK_HI 0xffffffff
#define SPLPREEMPTOK_LO INT_ENABLE_LO

/*
 * Note that in addition to RDB/RPF being turned off, the gprof interrupt is
 * also disabled.  The assumption is that if the user of these definitions
 * don't want RDB/RPF then gprof is probably not important to them either.
 * This is leftover from pre-I/O Convergence days.
 */
#define SPL6NORDB       LONG(0x4000000000000000)
#define SPL6NORDB_HI    0x40000000
#define SPL6NORDB_LO    SPL_LO

#define SPL6NORPF       _RDB_SPL6
#define SPL6NORPF_HI    _RDB_SPL6_HI
#define SPL6NORPF_LO    SPL_LO

#define SPLIMP		SPL5
#define SPLIMP_HI	SPL5_HI
#define SPLIMP_LO	SPL5_LO

#define SPLNET		SPL2
#define SPLNET_HI	SPL2_HI
#define SPLNET_LO	SPL2_LO

# else /* __LP64__ */

#define MSB	        0x80000000

#if     defined(GPROF) || defined(PGPROF)
#define GPROF_INT_ENABLE                0x80000000
#define CLOCK_INT_ENABLE                0x08000000
#else  /* ! GPROF || PGPROF */
#define CLOCK_INT_ENABLE                0x80000000
#endif /* ! GPROF || PGPROF */

#define REMOTE_PFAIL_INT_ENABLE		0x40000000
#define KERN_PFR_INT_ENABLE		0x20000000

/* The CLOCK_RESYNC bit is used by the monarch processor in an MP system
 * to bring a non-monarch processor into the synchronization code.
 * The interval timer synchronization code coordinates the monarch and
 * non-monarch and allows the non-monarch to compute a couple of local
 * variables that may be used by it at any time to compute an estimate
 * of the monarch's itimer value.  The CLOCK_INT_BIT used to be used for
 * this purpose, but was abandoned, since a non-monarch could receive
 * that interrupt either from the monarch or from its own interval timer.
 */
#define CLOCK_RESYNC_INT_ENABLE		0x01000000
#define SW_TRIGGER_6_INT_ENABLE         0x00000800
#define SW_TRIGGER_5_INT_ENABLE         0x00000400
#define SW_TRIGGER_4_INT_ENABLE         0x00000200
#define SW_TRIGGER_3_INT_ENABLE         0x00000100
#define SW_TRIGGER_2_INT_ENABLE         0x00000080
#define SW_TRIGGER_1_INT_ENABLE         0x00000010
#define SOFTNET_INT_ENABLE              0x00000040
#define IOFORW_INT_ENABLE               0x00000020

/*
 *	First trap type interrupt bit.
 */
#define MPSCHED_INT_ENABLE              0x00000008
#define UNUSED_TRAP_INT_ENABLE29        0x00000004
#define KPREEMPT_INT_ENABLE             0x00000002
/*
 * HPMC_INT_BIT should never be enabled, except by crash dump assembly.
 */
#define HPMC_INT_ENABLE                 0x00000001

#if defined(GPROF) || defined(PGPROF)
#define _GPROF_SPL6     GPROF_INT_ENABLE
#define _GPROF_SPL5     GPROF_INT_ENABLE | CLOCK_INT_ENABLE
#else
#define _GPROF_SPL6     0
#define _GPROF_SPL5     0
#endif
#ifdef RDB
#define _RDB_SPL6       0x06000000
#else
#define _RDB_SPL6       0
#endif
#define _RDB_SPL5       _RDB_SPL6
#define	RDB_INT_ENABLE  _RDB_SPL6

/*
 * The value for SPL7 is arbitrary, since psw-I is off; it is less than
 * five bits so that comib can be used to test it.
 */
#define SPL7            0x00000007
#define SPL6           (0x40000000 | _GPROF_SPL6 | _RDB_SPL6)
#define SPL5           (0xe1000800 | _GPROF_SPL5 | _RDB_SPL5)
#define SPL4            0xfffffc00
#define SPL3            0xfffffe00
#define SPL2            0xffffff00
#define SPL1            0xffffffc0
#define SPL0            SPLNOPREEMPT

#define SPLNOPREEMPT    0xfffffff0
#define SPLPREEMPTOK	0xffffffff

/*
 * Note that in addition to RDB/RPF being turned off, the gprof interrupt is
 * also disabled.  The assumption is that if the user of these definitions
 * don't want RDB/RPF then gprof is probably not important to them either.
 * This is leftover from pre-I/O Convergence days.
 */
#define SPL6NORDB       0x40000000
#define SPL6NORPF       _RDB_SPL6

#define SPLIMP		SPL5
#define SPLNET		SPL2

# endif /* __LP64__ */

/*
 * Below are the Tahoe equivalents to the SPL# constants.  These
 * constants should be used in PIK code since they will be defined
 * for both Tahoe and PA builds.
 */
#define SPLLWI   SPL7
#define SPLDBG   _RDB_SPL6
#define SPLSYS   SPL6
#define SPLIO    SPL5
#define SPLSOFT  SPL2
#define SPLSCHED SPLNOPREEMPT
#define SPLUSER  SPLPREEMPTOK

#define MPLOCAL_MASK	(MPSCHED_INT_ENABLE	| KPREEMPT_INT_ENABLE	| \
			 SOFTNET_INT_ENABLE     | \
			 KERN_PFR_INT_ENABLE	| RDB_INT_ENABLE	| \
			 CLOCK_INT_ENABLE	| REMOTE_PFAIL_INT_ENABLE)

#if defined(GPROF) || defined(PGPROF)

#define 	SPINLOCK_EIEM    SPL6
#ifdef __LP64__
# define 	SPINLOCK_EIEM_HI SPL6_HI
# define        SPINLOCK_EIEM_NIBBLE_0 SPL6_NIBBLE_0
# define        SPINLOCK_EIEM_NIBBLE_1 SPL6_NIBBLE_1
# define 	SPINLOCK_EIEM_LO SPL6_LO
#endif

#else  /* ! (GPROF || PGPROF) */

#define        SPINLOCK_EIEM   (REMOTE_PFAIL_INT_ENABLE | RDB_INT_ENABLE)
#ifdef __LP64__
# define       SPINLOCK_EIEM_HI (REMOTE_PFAIL_INT_ENABLE_HI | RDB_INT_ENABLE_HI)
# define       SPINLOCK_EIEM_NIBBLE_0 REMOTE_PFAIL_INT_HI_NIBBLE
# define       SPINLOCK_EIEM_NIBBLE_1 SPL6_NIBBLE_1
# define       SPINLOCK_EIEM_LO SPL6_LO
#endif

#endif /* ! (GPROF || PGPROF) */

#ifdef __LP64__
# define  LOAD_SPINLOCK_EIEM(reg) depdi,z eval(SPINLOCK_EIEM_NIBBLE_0),3,4,reg !\
				  depdi   eval(SPINLOCK_EIEM_NIBBLE_1),7,4,reg
#else
# define  LOAD_SPINLOCK_EIEM(reg) LDI(SPINLOCK_EIEM, reg)
#endif

/*
 * BASEPRI is true when the spl level of eiem passed to us equals that
 *         used in the idle loop in swtch().
 */
#define	BASEPRI(eiem)	(eiem == (ulong_t) SPLNOPREEMPT)

#endif /* _KERNEL */
#endif /* SPL_INCLUDED */
