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

	.data
#if !defined(NO_RCS_HDRS)
rcsidlointr:	.asciz	"$Header:lointr.s 12.0$"
#endif
	.text

	.align 2	# *tjm
	.globl int0
	.globl int1
	.globl int2
	.globl int3
	.globl int4
	.globl int5
	.globl int6

 #****************************************************************
 #* 	Level 0 Interrupt Handler				 *
 #****************************************************************
 #
 # Level 0 interrupts result from:
 # 1. IRQ_0 	level 0 request bit (used for single instruction stepping)
 # 2. soft-reset	keyboard "panic" request 
 #

eye_catcher(int0):
	.text
	.using	real0,r0

	st	r1,low_save1
	stm	r10,low_save10
	mfs	scr_irb,r15		# get copy of irb
	mttbil	r15,IRB_IRQ_0		# get int level 0 bit
	jntb	int0_ext		# no irb bit, must be external i/o interrupt

	l	r15,LV0+old_ics_cs	# get old icscs
	mttbiu	r15,PROBSTATE-16	# problem state?
	jtb	int0_step		# yes, user instruction step

	# single step interrupt in kernel mode, jump to debugger
	# do not clear IRB in case of debugger multiple step

int0_lm:
	bx	int0_jump_to_dan	# transfer to aligned word
	lm	r10,low_save10		# get the registers back
	.align	2
int0_jump_to_dan: b real0		# go there (branch patched during start)

         # single step interrupt in user mode, handle via fault
int0_step:
	clrsb	scr_irb,IRB_IRQ_0	# reset interrupt request bit

	 cau   r10,(STEP)>>16(r0) # mcs_pcs value for inst step "check"
	 oil   r10,r10,(STEP)&0xffff
	 lis   r11,0             # no additional information required
	 l     r12,int0_ps+old_iar     # get interrupt time iar
	 l     r13,int0_ps+old_ics_cs  # get interrupt time ics and cs
	 bali  sp,flipmode       # switch to kernel mode
	 cau   sp,(KERNSTACK)>>16(r0) # switch to kernel stack
	 oil   sp,sp,(KERNSTACK)&0xffff
	 lps   0,fault_ps        # goto fault: translation on, interrupts off
 #
 # other level 0 interrupt
 # if debugger is present pass it control, otherwise go to interrupt common
 # routine
 #
int0_ext:
#ifdef RDB
	j	int0_lm		# to the debugger
#else
	lm	r10,low_save10		# get the registers back
	st	r6,iosave6		# save r6
	l	r6,iosavep		# get interrupt stack pointer
	cal	r6,-IOSAVEL(r6)		# adjust for frame size
#ifndef FAST_INTERRUPTS
	ti	4,r6,iosavea-real0	# test to see if overflowed
#endif
	st	r6,iosavep		# save new value
	stm	r0,XIHR0(r6)		# save all registers on interrupt stack

#ifdef ATR 
	l	r10,_current_128_w
	st	r10,XIH_PCIF128(r6)

	l	r10,_current_512_w
	st	r10,XIH_PCIF512(r6)
#endif ATR
	# Get the old IAR and ICS/CS
	l	r10,LV0
	l	r11,LV0+old_ics_cs

	bx	int_comm
	  cal	r7,slih_0-real0(r0)
#endif RDB

 #****************************************************************
 #* 	Level 1 Interrupt Handler Should be Hard IO Timer	 *
 #****************************************************************

eye_catcher(int1):
	.using	real0,r0
	clrsb	scr_irb,IRB_IRQ_1	# reset interrupt request bit
	clrsb	scr_ts,26-16		# Reset Timer interrupt status bit
	st	r6,iosave6		# save r6
	l	r6,iosavep		# get interrrupt stack pointer
	cal	r6,-IOSAVEL(r6)		# adjust for frame size
#if !defined(FAST_INTERRUPTS)
	ti	4,r6,iosavea-real0	# test to see if overflowed
#endif
	st	r6,iosavep		# save new value
	stm	r0,XIHR0(r6)		# save all registers on interrupt stack
#ifdef ATR 
	l	r10,_current_128_w
	st	r10,XIH_PCIF128(r6)

	l	r10,_current_512_w
	st	r10,XIH_PCIF512(r6)
#endif ATR

	l	r10,_intrcnt		# count clock interrupts
	inc	r10,1
	st	r10,_intrcnt
	# Get the old IAR and ICS/CS
	l	r10,LV1
	cal	r7,slih_1-real0(r0)
	bx	int_comm
	  l	r11,LV1+old_ics_cs

 #****************************************************************
 #* 	Level 2 Interrupt Handler				 *
 #****************************************************************
 # Level 2 interrupts generated by:
 #
 # 1. IOCC
 # 2. MMU program check
 #

eye_catcher(int2):
	.using	real0,r0
	clrsb	scr_irb,IRB_IRQ_2	# reset interrupt request bit
	st	r6,iosave6		# save r6
	l	r6,iosavep		# get insterrrupt stack pointer
	cal	r6,-IOSAVEL(r6)		# adjust for frame size
#if !defined(FAST_INTERRUPTS)
	ti	4,r6,iosavea-real0	# test to see if overflowed
#endif
	st	r6,iosavep		# save new value
	stm	r0,XIHR0(r6)		# save all registers on interrupt stack

#ifdef ATR 
	l	r10,_current_128_w
	st	r10,XIH_PCIF128(r6)

	l	r10,_current_512_w
	st	r10,XIH_PCIF512(r6)
#endif ATR

	# Get the old IAR and ICS/CS
	l	r10,LV2
	l	r11,LV2+old_ics_cs

	# Check if in Supervisor state and set Kernel stack

	bx	int_comm
	  cal	r7,slih_2-real0(r0)

 #****************************************************************
 #* 	Level 3 Interrupt Handler				 *
 #****************************************************************
 #
 # Level 3 interrupts generated by I/O Bus levels and Planar:
 #
 # 8259 level	I/O Level	I/O adapter
 #	0	0 (Planar)	8237 Terminal count
 #	1	10 		I/O BUS IRQ 10
 #	2	9		I/O BUS IRQ 9
 #	3	3		I/O BUS IRQ 3
 #	4	4		I/O BUS IRQ 4
 #	5	1 (planar)	Keyboard controller
 #	6	2 (planar)	8530 serial port
 #	7	7		I/O BUS IRQ 7
 #

eye_catcher(int3):

	.using	real0,r0
	st	r6,iosave6
	l	r6,iosavep
	cal	r6,-IOSAVEL(r6)
#if !defined(FAST_INTERRUPTS)
	ti	4,r6,iosavea-real0
#endif
	st	r6,iosavep
	stm	r0,XIHR0(r6)

#ifdef ATR 
	l	r10,_current_128_w
	st	r10,XIH_PCIF128(r6)

	l	r10,_current_512_w
	st	r10,XIH_PCIF512(r6)
#endif ATR
	# Get the old IAR and ICS/CS
	l	r10,LV3
	cal	r7,slih_3-real0(r0)
	bx	int_comm
	l	r11,LV3+old_ics_cs

 #****************************************************************
 #* 	Level 4 Interrupt Handler				 *
 #****************************************************************
 #
 # Level 4 interrupts generated by:
 #
 # I/O interrupts thru second 8259A interrupt controller
 #

eye_catcher(int4):

	.using	real0,r0
	st	r6,iosave6
	l	r6,iosavep
	cal	r6,-IOSAVEL(r6)
#if !defined(FAST_INTERRUPTS)
	ti	4,r6,iosavea-real0
#endif
	st	r6,iosavep
	stm	r0,XIHR0(r6)

#ifdef ATR 
	l	r10,_current_128_w
	st	r10,XIH_PCIF128(r6)

	l	r10,_current_512_w
	st	r10,XIH_PCIF512(r6)
#endif ATR
	# Get the old IAR and ICS/CS
	l	r10,LV4
	cal	r7,slih_4-real0(r0)
	bx	int_comm
	l	r11,LV4+old_ics_cs

 #****************************************************************
 #* 	Level 5 Interrupt Handler				 *
 #****************************************************************

eye_catcher(int5):

	.using	real0,r0
	st	r6,iosave6
	l	r6,iosavep
	cal	r6,-IOSAVEL(r6)
#if !defined(FAST_INTERRUPTS)
	ti	4,r6,iosavea-real0
#endif
	st	r6,iosavep
	stm	r0,XIHR0(r6)

#ifdef ATR 
	l	r10,_current_128_w
	st	r10,XIH_PCIF128(r6)

	l	r10,_current_512_w
	st	r10,XIH_PCIF512(r6)
#endif ATR
	# Get the old IAR and ICS/CS
	l	r10,LV5
	l	r11,LV5+old_ics_cs


	bx	int_comm
		cal	r7,slih_5-real0(r0)

 #****************************************************************
 #* 	Level 6 Interrupt Handler Soft Timer			 *
 #****************************************************************

eye_catcher(int6):
	.using	real0,r0
	st	r6,iosave6
	l	r6,iosavep
	cal	r6,-IOSAVEL(r6)
#if !defined(FAST_INTERRUPTS)
	ti	4,r6,iosavea-real0
#endif
	st	r6,iosavep
	stm	r0,XIHR0(r6)

#ifdef ATR 
	l	r10,_current_128_w
	st	r10,XIH_PCIF128(r6)

	l	r10,_current_512_w
	st	r10,XIH_PCIF512(r6)
#endif ATR
	l	r10,_intrcnt+4		# count soft interrupts
	inc	r10,1
	st	r10,_intrcnt+4

	# Get the old IAR and ICS/CS
	l	r10,LV6
	l	r11,LV6+old_ics_cs

	mfs	scr_irb,r15	  # get copy of irb
	mttbil	r15,IRB_IRQ_6	  # get int level 6 bit
	jntb	int6_ext	  # no irb bit, must be external i/o interrupt

 # interrupt was requested via the IRB

	clrsb	scr_irb,IRB_IRQ_6 # clear interrupt request bit
	bx	int_comm
	  cal	r7,slih_6soft-real0(r0)

int6_ext:
	bx	int_comm
	  cal	r7,slih_6-real0(r0)

 #****************************************************************
 #* 	Machine Check Interrupt Handler				 *
 #****************************************************************

	.align	2
mck_vec1:
	.long	mck1 -real0		# New IAR
	.short	NOTRANS_ICS+INTMASK_ICS+INT_PRI0,0	# New ICS
eye_catcher(mck0):
#ifdef ROMPC
	cas	r0,r0,r0		# nop
	st	r15,low_save15		# these instructions prevent "death-by-88"
 #	bala	0f - real0		# on both SGP and ROMPC
	.long	BALA + 0f - real0	# can't use bala - sigh
0:	l	r15,low_save15
#else
	b	0f	# this instruction is necessary for certain page-faults
			# that will result in a "death-by-88" without it.
0:
#endif

        st    r1,low_save1      # copy interrupt time r1 into low_save var
        stm   r10,low_save10    # copy interrupt time rx into low_save var

        mfs   scr_mcspcs,r10    # r10 = program check status
	oi	r10,r10,MCS_CHECK # fake the machine check status
	lps	1,mck_vec1	# get off machine check level ASAP
mck1:

 #
 #  machine check
 #  if LORDB and debugger present and in kernel mode pass to the debugger
 #  otherwise pass to 'trap'.
 #
mck_notstg:
#ifdef LORDB
	l	r11,mck_ps+old_ics_cs # get the ics into r11
	mttbiu	r11,PROBSTATE-16	#copy problem state bit from old ics
	jntb	mck_debug	#transfer control to debugger if not user mode
#endif
 #
 #  real macine checks - call fault to handle
 #
mck_real:
	lis r11,0             # no additional information required
	l     r12,mck_ps+old_iar     # get interrupt time iar
	l     r13,mck_ps+old_ics_cs  # get interrupt time ics and cs
	b	mck_fault	# handle as a fault

	.align	2
 #
 # pass control to debugger if it is present
 #
mck_debug:
         lm    r10,low_save10    # restore regs
mck_jump_to_dan: b real0         # jump to original owner of program check


 #****************************************************************
 #* 	Common Interrupt Handler				*
 #*	On entry:						*
 #*		r6 = INT STACK					*
 #*		r7 = slih table entry pointer (real)		*
 #*		r10 = iar at interrupt time			*
 #*		r11 = icscs at interrupt time			*
 #*	The registers are saved at 0(r6)...60(r6)		*
 #*		except for r6 which is in iosave6		*
 #*	During:							*
 #*		r1 = KERN STACK (sp)				*
 #*		r9 = Save MQ at interrupt time			*
 #*								*
 #****************************************************************

booboo:  get	r2,$LED_INT_SP	# value for 'booboo' in lights
	bali	r5,display
	tgte	r5,r5		# cause a program check
	j	booboo		# and loop (sigh)

	.globl	int_comm
eye_catcher(int_comm):

	.using	real0,r0
	mttbiu	r11,PROBSTATE-16	# get probstate bit
 	bntbx	goto_int_comm_1		# not probstate, sp was sys sp, ie. ok
 	 ai	sp,sp,FRM_PROTECT 
	 FLIPMODE(sp,r15)		# flip MMU to kernel mode
	get     sp,$KERNSTACK		# switch to kernel stack

goto_int_comm_1:

 # FAST_INTERRUPTS are faster because they don't do error checking
 # on the stack. It is not clear that it is a good idea to use it.
#if !defined(FAST_INTERRUPTS)
	cau   r12,(UAREA+KERNFRAME)>>16(r0) # address of 1st byte of kernel stack
	oil   r12,r12,(UAREA+KERNFRAME)&0xffff
	cl    sp,r12            # if kernel stack invalid
	jl    booboo            # then jump
	cau   r12,(KERNSTACK)>>16(r0)	 # address of last byte of kernel stack
	oil   r12,r12,(KERNSTACK)&0xffff
	cl    sp,r12            # if kernel stack invalid
	jh    booboo            # then jump
#endif FAST_INTERRUPTS

	l	r0,iosave6		# Get The real value of R6 at IRPT
	sts	r0,XIHR6(r6)		# Save it on INT Stack
	mfs	scr_mq,r9		# r9 = get mq at IRPT

	#
	# Get ready to call SLIH
	#
	# Save the ICS and set the SLIH's priority
	lh	r5,IOSLICS(r7)		# Set ICS for SLIH Execution
	sth	r5,go_callslih+4	# Set the SLIH ICS
	lps	0,go_callslih

 #
 # interrupts can (and will) happen between here and 'afterslih'
 # note that translation is now ON.
 #
callslih:


#ifdef RDB
 #
 # following is to fake up a C entry sequence for the debugger
 # traceback routine
 #
	cas	r15,r10,r0		# fake "return" value
	j	0f
	ai	sp,sp,FRM_PROTECT	# for RDB's benifit
0:
	.globl	_callslih
_callslih:
	stm	r15,-4(sp)		# save return address
	ai	sp,sp,-4		# room for 1 register
#endif
	oiu	r7,r7,SYS_ORG/UPPER	# Prepare to enter translate mode
 # Set up stack for SLIH arguments

	ls	r5,DEVSLIH(r7)		# Entry Point to SLIH code
	l	r2,DEVDEP(r7)		# Pass Device Dependant information

	cas	r3,r11,r0		# Pass the SLIH the icscs (arg2)
	cas	r4,r10,r0		#  and the IAR at interrupt (arg3)
#ifdef IODEBUG
	get	r15,$_iotrap
	mr	r0,r15
	l	r15,0(r15)
	balr	r15,r15
#else !IODEBUG
	l	r15,0(r5)
	balrx	r15,r15
	 mr	r0,r5
#endif !IODEBUG
	# Restore state for return from Interrupt Processing
1:	.using	1b
	mfs	scr_iar,r15
	.text
1:	.using 1b,r15
	lps	0,go_afterslih
 # we are now back at FLIH priority with translate off.
afterslih:

	.using	real0,r0
	mts	scr_mq,r9		# Restore MQ
	st	r10,low_ps+old_iar	# Store old program status for
	st	r11,low_ps+old_ics_cs	#   end Interrupt processing

#ifndef FAST_INTERRUPTS
	ti	1,r6,iounmask-1-real0	# Check for IO Stack underflow
#endif

	# Restore Registers and resume interrupted proram

#ifdef ATR 
	get	r1,pcif_base		# get REAL Address PCIF I/O byte

	l	r10,XIH_PCIF128(r6)	# Restore the 128K window pointer
	st	r10,_current_128_w
	st	r10,P_WIND128(r1)

	l	r10,XIH_PCIF512(r6)	# Restore the 512K window pointer
	st	r10,_current_512_w
	st	r10,P_WIND512(r1)
#endif ATR

	cal	r6,IOSAVEL(r6)		# Pop Register save area stack
	# This is safe before restoring regs. because All Int's are masked
	st	r6,iosavep		# Save new stack pointer

	lm	r0,XIHR0-IOSAVEL(r6)	# restore all registers
	st	r15,low_save15		# stash away for go
	st	r1,low_save1		# stash away for go

	# Resume interrupted program
	lps	0,go_ps			# jump to "go" with interrupts off
1:	.using	1b			# no longer have addressability
