; ParityErrors.asm -- Handles parity error interrupts
; Copyright Xerox Corporation 1979
; last modified December 7, 1978  11:28 PM by Taft

.ent ParityInterrupt
.bext lvParitySweepCount
.bext lvParityPhantomEnable

	.srel

ParityInterrupt:	.ParityInterrupt
lvParitySweepCount:	.SweepCount
lvParityPhantomEnable:	.PhantomEnable

; Mechanism:
;	Interrupt causes execution of code at parity.
;	Save state, turn off display.
;	Wait for disk and display activity to finish.
;	Enable interrupts
;	Iterate through core until another error happens.
;	Call swat by executing  #77401.  if addr = 0 then
;	 we couldn't find the parity error.
;
; Following order is known by Swat:
;	.PC = return link
;	.PC+1 = address of error
;	.PC+2 = saved interrupt PC
;	.PC+3 = unspecified
;	.PC+4 = unspecified
;	.PC+5 = display pointer
;	.PC+6 = unspecified
;	.PC+7-14 = saved R registers
; Interrupts are disabled when Swat is called

	.nrel

.PhantomEnable:	177777	; true if call swat for Phantoms
.SweepCount:	176777	; highest address to sweep, work down to zero

.ParityInterrupt:
	sta 0 peAC0	; save registers
	sta 1 peAC1	; *** except AC2, not used in this routine ***
	sta 3 peAC3	; *** careful not to clobber carry until ***** below

; Save R register dump area so we will not be fooled by new
; parity errors detected during sweep or Swat swap-out.
	jsr .+1
RRegRel: lda 1 rRegOffset
	add 3 1		; points to last destination word
	lda 3 cm6	; 6 words to xfer
	lda 0 c613	; starting at 614
	blt

	lda 3 c613	; for displacement addressing in i/o page
	lda 0 Display 3	; save display list head
	sta 0 peDisplay
	lda 0 IntPC 3	; save interrupt pc
	sta 0 pePC
	lda 0 Active 3	; save active interrupt channels
	movl 0 0	; save carry (bit 0 of Active unused) *****
	sta 0 peActive
	mkzero 0 0
	sta 0 Active 3	; disable all interrupt channels
	eir		; but leave interrupts enabled

	lda 0 .SweepCount
	snz 0 0		; shall we sweep core?
	 jmp Dismiss	; no
	sta 0 peAddr	; initialize loop control

DskWait:lda 0 KBLK 3	; wait for disk to quit
	sz 0 0
	 jmp DskWait

	sta 0 Display 3	; turn off display
	lda 0 dspDelay	; wait for display to quit
DspWait:inc 0 0 szr
	 jmp DspWait

; Sweep loop
	lda 0 WW 3
	movzr 0 0
	movzl 0 0
	sta 0 WW 3	; clear any pending parity interrupt
Sweep:	lda 0 @peAddr	; load each word in core until we get an error
	dsz peAddr	; or reach zero.  CPT says to perform 1 extra
	 jmp Sweep1
	jmp Sweep2
Sweep1:	lda 0 WW 3
	movr 0 0 snc	; did a parity interrupt try to happen?
	 jmp Sweep	; no
	isz peAddr	; reincrement the address
Sweep2: lda 1 .PhantomEnable
	lda 0 peAddr
	snz 1 1		; Skip if phantoms are enabled
	sz 0 0		; Do not call Swat unless real error

;------ S W A T   P A R I T Y   C O M M U N I C A T I O N   T A B L E --------
; *** Assume nobody looks at the entries marked ***,
; *** but the position in the table of things following them is important.
ToSwat:		77401		; call swat. 77401 => parity error trap
		jmp Dismiss
peAddr:		0		; parity error address or zero
pePC:		0		; saved interrupt pc
peAC0:		0		; *** saved ac0
peAC1:		0		; *** saved ac1
peDisplay:	0		; ptr to display word
peActive: 	0		; *** saved active interrupts word
peRRegs:	.blk 6		; R-registers saved by parity error task
;-----------------------------------------------------------------------------

rRegOffset:	peRRegs+5-RRegRel
cm6:		-6
c613:		613
peAC3:		0
dspDelay:	-4500.		; wait at least 1/60 second.

; i/o page displacements relative to 613
Display =	420-613		; display control block list
WW =		452-613		; wakeup waiting
Active = 	453-613		; active interrupts
IntPC = 	500-613		; interrupt pc
KBLK =	 	521-613		; disk control block list


Dismiss:dir
	lda 0 peDisplay
	sta 0 Display 3	; restore display
	lda 0 WW 3
	movzr 0 0
	movzl 0 0
	sta 0 WW 3	; flush any pending parity interrupts
	lda 0 peActive
	movzr 0 0	; restore carry
	sta 0 Active 3	; restore active interrupts
	lda 0 peAC0	; restore registers
	lda 1 peAC1
	lda 3 peAC3
	bri		; Dismiss interrupt

	.end