Google
 

Trailing-Edge - PDP-10 Archives - BB-JR93N-BB_1990 - 10,7/mon/errcon.mac
There are 13 other files named errcon.mac in the archive. Click here to see a list.
TITLE ERRCON - MONITOR DETECTED ERROR HANDLING ROUTINES - V1270
SUBTTL T. HASTINGS/TH/CHW/TW/RCC/DAL	17-APR-90
	SEARCH	F,S,DEVPRM
	$RELOC
	$HIGH


;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
;  OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION
; 1973,1974,1975,1976,1977,1978,1979,1980,1982,1984,1986,1988,1990.
;ALL RIGHTS RESERVED.

.CPYRT<1973,1990>


XP VERRCN,1270	;THIS MACRO PUTS VERSION NO. IN STORAGE MAP AND GLOB

ENTRY	ERRCON		;ALWAYS LOAD ERRCON(IF LIB SEARCH)

ERRCON::
SUBTTL	CLOCK LEVEL APR ERROR HANDLING

;HERE ON PI 7 CLOCK INTERRUPT TO PROCESS APR ERRORS FOR INDIVIDUAL JOBS
;.CPAEF HOLDS COMMUNICATION FLAGS SET BY APR PI INTERRUPT LEVEL
;CALL:	MOVE	S,.CPAEF
;	JUMPN	S,APRILM	;COME HERE IF ANYTHING HAPPENED
;	RETURN TO RESCHEDULE NEW USER

APRILM::MOVEM	S,.CPSAC##	;HERE ON ANY APR ERROR OR MEM PARITY
	SKIPN	J,.CPJOB##	;CURRENT JOB ON THIS CPU
	SETOM	.CPNJE##	;MAKE SURE NULL JOBS AC'S ARE RESTORED
	JUMPGE	S,APRIL1	;REQUEST TO SCAN MEMORY FOR PARITY OR NXM?
	TLNN	S,(CP.PSX!CP.CSX) ;YES IS THIS JUST A PRINT JOB MESSAGES REQUEST?
	JRST	APRIL2		;YES--GO LOOP THRU JOBS AND PRINT MESSAGES TO TTY'S
	PUSHJ	P,PARSWP	;NO--SWEEP CORE (AND FLAG JOBS ON KI10)
APRIL2:	MOVE	J,HIGHJB##	;HIGHEST JOB NUMBER
	TRNE	S,UE.NXM	;NXM INSTEAD OF PARITY ERROR?
	JRST	NXMLOP		;YES--REPORT NXM TO ALL JOBS AFFECTED
				;NO--REPORT PARITY TO ALL JOBS AFFECTED
				; FALL INTO PARLOP
;;LOOP TO SCAN ALL JOBS, ZAP BAD ONES AND PRINT PARITY ERROR MESSAGE
PARLOP:	MOVEI	T1,JS.MPE	;MEM PARITY FOR JOB
	TDNN	T1,JBTSTS##(J)	;JOB HAVE MEM PAR IN LOW/HIGH SEG OR UPMP?
	JRST	PARLO1		;NO--KEEP LOOKING
	ANDCAM	T1,JBTSTS##(J)	;YES, CLEAR IN JOB STATUS WORD
	SKIPN	JBTADR##(J)	;IS LOW SEG STILL IN CORE? (NO IF SWAPOUT ERROR)
	JRST	PARLO1		;NO--KEEP LOOKING
	PUSHJ	P,ZAPHIM	;RETURN ALL HIS RESOURCES
	PUSHJ	P,PARSTP	;STOP JOB AND PRINT MESSAGE
PARLO1:	SOJG	J,PARLOP	;LOOP OVER ALL JOBS
IFN FTMP,<
	PUSHJ	P,GETMM##	;GET THE MM
	  JRST	.-1		;MUST WAIT
>
	PUSHJ	P,CPINXF	;FIX CORE TABLES, IF NEEDED
	  SKIPA			;CORMAX WAS DECREASED
	JRST	PARXIT		;ALL JOBS NOT ZAPPED CAN CONTINUE TO RUN
IFN FTMP,<
	PUSHJ	P,GIVMM##	;RETURN THE MM
>
;HERE IF CORMAX WAS DECREASED SO ALL JOBS MUST BE SCANNED AND ANY
; WHICH ARE TOO BIG TO BE SWAPPED IN MUST BE ZAPPED ALSO
	SETZ	J,		;FIRST CALL ARG. TO JBSTBG
PARLP2:	MOVE	T1,CORMAX##	;GET CURRENT VALUE OF CORMAX
	PUSHJ	P,JBSTBG	;SEE IF THIS JOB IS NOW TOO BIG TO RUN
	  JRST	PARXI1		;ALL JOBS HAVE BEEN LOOKED AT
	PUSHJ	P,PARSTP	;STOP THE JOB AND TELL THE USER
	JRST	PARLP2		;KEEP GOING

;EXIT FROM PARITY SWEEP AND PRINT ROUTINE
PARXIT:
IFN FTMP,<
	PUSHJ	P,GIVMM##	;RETURN THE MM
>
PARXI1:	HRROI	S,UE.PEF	;CLEAR PARITY ERROR FLAG
	ANDCAB	S,.CPAEF##	;OTHER APR ERRORS?
	JUMPN	S,APRILM	;YES, GO PROCESS THEM
	POPJ	P,		;RETURN
NXMLOP:	MOVEI	T1,JS.NXM	;JOB OVERLAPS NXM BIT
	TDNN	T1,JBTSTS##(J)	;DOES THIS JOB OVERLAP NXM?
	JRST	NXMLP1		;NO, KEEP LOOKING
	ANDCAM	T1,JBTSTS##(J)	;CLEAR THE BIT
	CAME	J,MOFLPG##	;IS THIS THE JOB THAT TYPED SET MEM ON?

	SKIPN	JBTADR##(J)	;DOES THIS JOB HAVE CORE IN CORE?
	JRST	NXMLP1		;IF NO TO EITHER, DO NOTHING
	PUSHJ	P,ZAPUSR	;ZAP THE PROGRAM
IFN FTLOCK,<
	PUSHJ	P,UNLOCK##	;UNLOCK IT IF LOCKED
	  JFCL			;OH WELL
>
	PUSHJ	P,NXMSTP	;STOP THE JOB AND TELL THE USER WHAT HAPPENED
NXMLP1:	SOJG	J,NXMLOP	;LOOP OVER ALL JOBS ON THE SYSTEM
	MOVE	J,.CPJOB##	;JOB CURRENTLY RUNNING ON THIS CPU
	CAMN	J,MOFLPG##	;JOB SETTING MEMORY ON-LINE?
	JRST	NXMXI1		;YES, IT CAUSED NXM, SET MEM ON WILL CALL CPINXF
IFN FTMP,<
	PUSHJ	P,GETMM##	;GET THE MM
	  JRST	.-1		;MUST WAIT
>
	PUSHJ	P,CPINXF	;FIX CORE ALLOCATION TABLES, ETC.
	  SKIPA			;CORMAX WAS DECREASED
	JRST	NXMXIT		;ALL JOBS NOT ZAPPED CAN CONTINUE TO RUN
IFN FTMP,<
	PUSHJ	P,GIVMM##
>
;HERE IF CORMAX WAS DECREASED SO ALL JOBS MUST BE SCANNED AND ANY
; WHICH ARE TOO BIG TOO BE SWAPPED IN MUST BE ZAPPED
	MOVEI	J,0		;STARTING WITH JOB 0,
NXMLP2:	MOVE	T1,CORMAX##	; AND THE CURRENT VALUE OF CORMAX
	PUSHJ	P,JBSTBG	;SEE IF THIS JOB IS NOW TO BIG TO BE RUN
	  JRST	NXMXI1		;ALL JOBS HAVE BEEN LOOKED AT
	PUSHJ	P,NXMSTP	;STOP THE JOB AND TELL THE USER
	JRST	NXMLP2		;SEE IF ANYMORE JOBS ARE TOO BIG
NXMXIT:
IFN FTMP,<
	PUSHJ	P,GIVMM##
>
NXMXI1:	HRROI	S,UE.NXM	;CLEAR SOFTWARE NXM FLAG
	ANDCAB	S,.CPAEF##	; ..
	JUMPN	S,APRILM	;GO PROCESS OTHER ERRORS IF THEY EXIST
	POPJ	P,		;OTHERWISE, RETURN
;SUBROUTINE TO PRINT MEM PAR ERROR FOR JOB N AND STOP JOB
;CALL:	MOVE	J,JOB NO
;	PUSHJ	P,PARSTP
;	ALWAYS RETURN
PARSTP:	PUSHJ	P,SVEUB##	;MAKE JOB ADDRESSABLE
	PUSHJ	P,ZAPPGM##	;"CORE 0"
	JSP	T1,ERRPNT	;PRINT STANDARD ERROR IN JOB MESSAGE
	ASCIZ	/Memory parity error/
	JRST	NXMST1		;PRINT MESSAGE AND STOP HIM

;SUBROUTINE TO PRINT NXM ERROR FOR JOB N AND STOP JOB
NXMSTP:	PUSHJ	P,SVEUB##	;MAKE JOB ADDRESSABLE
	PUSHJ	P,ZAPPGM##	;"CORE 0"
	JSP	T1,ERRPNT	;PRINT ERROR MESSAGE FOR THE USER
	ASCIZ /Non-existent memory error/
	AOS	.CPNJA##	;COUNT NUMBER OF JOBS ZAPPED BECAUSE OF NXM
NXMST1:	DMOVE	T1,.CPMDP##	;PC WHERE THE ERROR OCCURRED
	PJRST	DPCPNT		;PRINT INFO FOR USER AND STOP HIM
;SUBROUTINE CALLED TO HALT CPU ON SERIOUS ERROR IN MEMORY
PARHLT::CONO	PI,PI.OFF	;NO INTERRUPTS DURING TYPEOUT
	PUSHJ	P,PARHL1	;TYPE OUT APPROPRIATE MESSAGE ON CTY
	DIENLK			;GIVE DIE LOCK BACK
	STOPCD	.,HALT,FEM	;++FATAL ERROR IN MONITOR
PARHL1:	MOVEI	T1,CTYWAT##	;NON-PI CTY TYPEOUT ROUTINE ADDRESS
	MOVEM	T1,.CPTOA##	;MAKE IT THE ONE TO USE HERE
IFN FTKL10,<
	PUSHJ	P,SVPPC##	;MAKE SURE WE'RE IN SECONDARY PROTOCOL ON KL10
>
	SKIPN	.CPREP##	;A PARITY ERROR? (NOT NXM)
	JRST	NXMCTY		;NO, NXM REPORT NXM INSTEAD
	PUSHJ	P,INLMES##	;PRINT MESSAGE TO INFORM OPER OF HALT
	ASCIZ	/
?Non-recoverable memory parity error in monitor.

[CPU Halt]

/
	POPJ	P,		;RETURN AND HALT
NXMCTY:	PUSHJ	P,INLMES##	;INFORM OPR OF HALT
	ASCIZ	/
?Non-existent memory detected in monitor.

[CPU Halt]

/
	POPJ	P,		;RETURN AND HALT
;ROUTINE TO SCAN MEMORY FOR PARITY OR NXM ERRORS (APR PI OR PI 7)
;CALLED AT APR PI IF MAY BE A SERIOUS ERROR IN MONITOR AND PIS IN PROGRESS
;CALL:
;	MOVE	J,CURRENT JOB NO. ON THIS CPU
;	MOVE	S,.CPAEF SWEEP REQUEST BITS
;	PUSHJ	P,PARSWP
;	ALWAYS RETURNS - LH .CPMPC SET NEG. IF SERIOUS MONITOR PARITY
;	S PRESERVED

PARSWP::HRRZ	U,.CPCTN##	;GET CPU'S CTY LINE NUMBER
	MOVE	U,LINTAB##(U)	;NOW GET HIS LDB
	TRNN	S,UE.PEF	;PARITY ERROR?
	JRST	NXMSWP		;NO, SWEEP FOR NXM
	PUSHJ	P,ANNSWP##	;YES, TELL OPR THAT A SWEEP IS IN PROGRESS
	SETOM	.CPREP##	;TELL REPORTERS WHICH ERROR TYPE TO REPORT
	SETOM	.CPPAA##	;YES, SET PARITY AND OF BAD ADDRESSES TO -1
	SETOM	.CPPAC##	;SET PARITY AND OF BAD CONTENTS TO -1
	SETZM	.CPPOA##	;SET PARITY OR OF BAD ADDRESSES TO 0
	SETZM	.CPPOC##	;SET PARITY OR OF BAD CONTENTS TO 0
	AOS	.CPPSC##	;INCREMENT PARITY SWEEP COUNT
	SETZM	.CPPTS##	;SET NO OF PARITIES THIS SWEEP TO 0
IFN FTKL10,<
	PUSHJ	P,SVPPC##	;DON'T LET FE TIME US OUT WHILE SWEEPING
>
	PUSHJ	P,APRMPS##	;CALL MEMORY SWEEP ROUTINE
	SETZM	.CPLPP##	;CLEAR LAST PARITY ERROR PC
	SKIPE	.CPPTS##	;WERE SOME BAD WORDS FOUND ON SWEEP?
	SKIPA	T1,[EDELIM]	;YES--JUST GET END DELIMITER TEXT
	MOVEI	T1,[ASCIZ /No parity errors were found.
***************
/]				;NO--TELL THEM THAT
	PUSHJ	P,CONMES##	;PRINT IT
	PUSHJ	P,PARELG	;DO PARITY TRAP ERROR LOGGING
	SKIPE	.CPPTS##	;IF SOME REAL ERRORS WERE FOUND
	POPJ	P,		; THEN JUST RETURN NOW
	TLNN	S,(CP.PSX)	;DID PROCESSOR DETECT PARITY?
	AOSA	.CPPCS##	;NO, COUNT CHANNEL SPURIOUS COUNT
	AOS	.CPSPE##	;YES, COUNT PROCESSOR SPURIOUS COUNT
	POPJ	P,		;RETURN
PARELG:	HLRE	T1,PSETBL+.EXFLG ;GET TRANSFER TABLE LENGTH
	MOVMS	T1		;MAKE POSITIVE
	ADDI	T1,.CPPRL##+M.CBAT## ;PLUS LENGTHS OF PARITY & BAT SUBTABLES
	PUSHJ	P,ALCSEB	;ALLOCATE CORE FOR SYSTEM ERROR BLOCK
	  POPJ	P,		;NONE AVAILABLE
	XMOVEI	T2,PSETBL	;POINT TO TRANSFER TABLE
	PUSHJ	P,XFRSEB	;FILL IN THE STATIC PORTION
	  JFCL			;??
	MOVSI	T2,.CPLPA##	;POINT TO START OF PARITY TABLE
	HRRI	T2,15(T1)	;AND TO STORAGE
	MOVEI	T3,15+.CPPRL##(T1) ;COMPUTE END OF BLT
	BLT	T2,-1(T3)	;COPY PARITY TABLE
	HRLI	T2,.CPBAT##	;POINT TO START OF BAD ADDRESS TABLE
	BLT	T2,M.CBAT##-1(T3) ;COPY IT
	PJRST	QUESEB		;QUEUE ERROR BLOCK AND RETURN


;TRANSFER TABLE FOR PARITY REPORTING
PSETBL:	SEBTBL	(.ERSPR,PSEEND,<EX.SYE>)
	MOVE	.CPPHY##	;(R00) PHYSICAL CPU NAME
	MOVE	.CPTPE##	;(R01) TOTAL ERRORS ON SWEEP OF CORE
	MOVE	.CPSPE##	;(R02) TOTAL ERRORS NOT REPRODUCABLE
	MOVE	.CPMPW##	;(R03) CONTENS OF FIRST BAD WORD
	MOVE	.CPMPA##	;(R04) FIRST BAD ADDRESS
	MOVE	[-.CPPRL##,,15]	;(R05) OFFSET TO PARITY DATA
	MOVE	[-M.CBAT##,,15+.CPPRL##] ;(R06) OFFSET TO BAD ADDRESS TABLE
PSEEND:!
;ROUTINE TO PRINT WHO REQUESTED SCAN, WHERE, AND AT WHAT TIME
PRCHCP::TLNN	S,(CP.PSX)	;REQUESTED BY CPU?
	JRST	PRCHC1		;NO--BY CHANNEL
	MOVEI	T1,[ASCIZ /CPU/]
	PUSHJ	P,CONMES##	;APPEND "CPU"
	MOVEI	T1,5		;START WITH CPU 5
	MOVE	T2,S		;COPY OF S
PRCHC0:	LSH	T2,-1		;NEXT CPU
	TLNN	T2,(CP.PS5_-1)	;IS IT THIS CPU?
	SOJGE	T1,PRCHC0	;NO--TRY NEXT
	PUSHJ	P,RADX10##	;YES--APPEND CPU NUMBER
	JRST	PRCHC3		;CONTINUE
PRCHC1:	MOVEI	T1,[ASCIZ /channel /]
	PUSHJ	P,CONMES##	;APPEND "CHANNEL"
	MOVEI	T1,7		;START WITH CHANNEL 7
	MOVE	T2,S		;COPY OF S
PRCHC2:	LSH	T2,-1		;NEXT CHANNEL
	TLNN	T2,(CP.CS7_-1)	;IS IT THIS CHANNEL?
	SOJGE	T1,PRCHC2	;NO--TRY NEXT
	PUSHJ	P,RADX10##	;YES--APPEND CHANNEL NUMBER
PRCHC3:	MOVEI	T1,[ASCIZ / on /]
	PUSHJ	P,CONMES##	;APPEND "ON"
	MOVE	T2,.CPLOG##	;SCANNING CPU'S (THIS) NAME
	PUSHJ	P,PRNAME##	;APPEND IT
	MOVEI	T1,[ASCIZ / on /]
	PUSHJ	P,CONMES##	;APPEND "ON"
	PUSHJ	P,DATIME##	;AND THE DATE AND TIME
	PUSHJ	P,PCRLF##	;FINISH WITH A CRLF
	POPJ	P,		;RETURN
;SUBROUTINE TO SWEEP CORE LOOKING FOR NON-EXISTENT MEMORY

NXMSWP:	PUSHJ	P,ANNSWP##	;ANNOUNCE SWEEP
	SETZM	.CPLNA##	;ZERO HIGHEST NXM SEEN
	SETZM	.CPREP##	;SET NXM FLAG
	SETOM	.CPNAA##	;CLEAR AND OF NON-EXISTENT ADDRESSES
	SETZM	.CPNOA##	; AND OR OF NON-EXISTENT ADDRESSES
	SETZM	.CPNJA##	;NO JOBS AFFECTED YET
	AOS	.CPNSC##	;INCREMENT THE NUMBER OF NXM SWEEPS DONE
	SETZM	.CPNTS##	;CLEAR THE COUNT OF NXMS SEEN THIS SWEEP
IFN FTKL10,<
	PUSHJ	P,SVPPC##	;DON'T LET FE TIME US OUT
>
	PUSHJ	P,APRMPS##	;SWEEP MEMORY
	SETZM	.CPLPP##	;CLEAR LAST ERROR PC
	SKIPE	T1,.CPNTS##	;ANY NON-EXISTANT MEMORY SEEN?
	JRST	[SOSE T1	;ANY SEEN?
		 PUSHJ P,PRTEMS	;YES, REPORT THEM
		 MOVEI T1,EDELIM;GET ENDING MESSAGE
		 JRST .+2]	;PRINT THAT
	MOVEI	T1,[ASCIZ /No non-existent memory was found.
***************
/]				;NO--TELL THEM THAT
	PUSHJ	P,CONMES##	;PRINT IT
	PUSHJ	P,NXMELG	;DO NXM TRAP ERROR LOGGING
	SKIPE	.CPNTS##	;IF SOME REAL ERRORS WERE FOUND
	POPJ	P,		; THEN JUST RETURN NOW
	TLNE	S,(CP.PSX)	;DID THE PROCESSOR SEE THE NXM?
	AOSA	.CPSNE##	;YES, COUNT PROCESSOR SPURIOUS COUNT
	AOS	.CPNCS##	;NO, COUNT SPURIOUS CHANNEL NXMS
	POPJ	P,		;RETURN

PRTEMS:	MOVEI	T1,[ASCIZ / to /]
	PUSHJ	P,CONMES##	;PRINT END OF RANGE TEXT
	MOVE	T1,.CPLNA##	;LAST NXM ADDRESS IN RANGE
	PUSHJ	P,PRTDI8##	;PRINT HIGHEST NXM ADDRESS SEEN
	MOVEI	T1,[ASCIZ / (phys.)
/]
	PJRST	CONMES##	;PRINT THAT

;DELIMITER TEXT FOR CTY SYSTEM ERROR MESSAGES
SDELIM::ASCIZ	/
***************
/
EDELIM::ASCIZ	/***************
/
NXMELG:	HLRE	T1,NXETBL+.EXFLG ;GET TRANSFER TABLE LENGTH
	MOVMS	T1		;MAKE POSITIVE
	ADDI	T1,<2*NXMTBL##>+M.CBAT## ;PLUS 2 COPIES OF NXMTAB AND BAT
	PUSHJ	P,ALCSEB	;ALLOCATE CORE FOR SYSTEM ERROR BLOCK
	  POPJ	P,		;NONE AVAILABLE
	XMOVEI	T2,NXETBL	;POINT TO TRANSFER TABLE
	PUSHJ	P,XFRSEB	;FILL IN THE STATIC PORTION
	  JFCL			;??
	MOVSI	T2,OLDNXM##	;ADDR OF OLD NXMTAB
	HRRI	T2,.EBHDR+21(T1) ;WHERE TO PUT OLD NXMTAB
	MOVEI	T3,.EBHDR+21+NXMTBL##(T1) ;COMPUTE END OF BLT
	BLT	T2,-1(T3)	;COPY OLD NXMTAB
	HRLI	T2,NXMTAB##	;POINT TO CURRENT NXMTAB
	ADDI	T3,NXMTBL##	;COMPUTE END OF BLT
	BLT	T2,-1(T3)	;COPY CURRENT NXMTAB
	HRLI	T2,.CPBAT##	;POINT TO START OF BAD ADDRESS TABLE
	BLT	T2,M.CBAT##-1(T1) ;COPY IT
	PJRST	QUESEB		;QUEUE ERROR BLOCK AND RETURN


;TRANSFER TABLE FOR NXM REPORTING
NXETBL:	SEBTBL	(.ERSNX,NXEEND,<EX.SYE>)
	MOVE	.CPPHY##	;(R00) PHYSICAL CPU NAME
	MOVE	.CPTNE##	;(R01) COUNT OF ERROR ON SWEEP OF CORE
	MOVE	.CPSNE##	;(R02) NOT REPRODUCIBLE ERROR COUNT
	MOVE	.CPMNA##	;(R03) FIRST BAD ADDR FROM SWEEP
	MOVE	.CPLNA##	;(R04) LAST NXM ADDRESS
	MOVE	.CPMNR##	;(R05) LAST NXM RELATIVE ADDRESS
	MOVE	.CPNTS##	;(R06) NUMBER OF NXMS FOUND THIS SWEEP
	MOVE	.CPNSC##	;(R07) NUMBER OF NXM SWEEPS DONE
	MOVE	.CPUEN##	;(R10) NUMBER OF USER ENABLED NXMS
	MOVE	.CPNAA##	;(R11) LOGICAL AND OF BAD ADDRESSES
	MOVE	.CPNOA##	;(R12) INCLOSIVE OR OF BAD ADDRESSES
	MOVE	.CPNCS##	;(R13) NUMBER OF SPURIOUS CHANNEL NXMS
	MOVE	[707070,,1]	;(R14) SYSERR CODE,,PAGING MACHINE
	MOVE	[-NXMTBL##,,26]	;(R15) OFFSET TO OLD NXMTAB
	MOVE	[-NXMTBL##,,26+NXMTBL##] ;(R16) OFFSET TO NEW NXMTAB
	MOVE	[-M.CBAT##,,26+<2*NXMTBL##>] ;(R17) OFFSET TO BAD ADDRESS TABLE
NXEEND:!
;SUBROUTINE TO RECORD MEM PARITY DATA FOR EACH BAD WORD
;CALL:	MOVE	T1,REL ADDR WITHIN HIGH OR LOW SEG,
;			-1 IF NEITHER IN MONITOR NOR HIGH NOR LOW SEG
;	MOVE	P1,ABS ADR OF BAD WORD (22 BITS)
;	MOVE	S,.CPAEF FLAG BITS
;	MOVE	P2,CONTENTS OF BAD WORD
;	PUSHJ	P,PARRBD	;RECORD BAD DATA
;	ALWAYS RETURN EVEN IF SERIOUS ERROR
;CALLED FROM CPU DPENDENT MEMORY SWEEP LOOP

PARRBD::TRNN	S,UE.PEF	;A PARITY ERROR?
	JRST	NXMRBD		;NO, RECORD NXM
	AOS	.CPTPE##	;INCREMENTATION NO OF MEM PARITY ERRORS FOR SYSTEM
	AOS	T2,.CPPTS##	;INCREMENT NO OF PARITY ERRORS THIS SWEEP
	SOJG	T2,PARSEC	;IS THIS THE FIRST ERROR THIS SWEEP?
	MOVEM	P1,.CPMPA##	;YES, SAVE BAD ADDRESS
	MOVEM	P2,.CPMPW##	;BAD CONTENTS
	MOVEI	T1,[ASCIZ /Parity errors detected:
/]
	PUSHJ	P,CONMES##	;ANNOUNCE ERRORS SEEN
PARSEC:	MOVEI	T1,[ASCIZ /  at /]
	PUSHJ	P,CONMES##	;PRINT "AT"
	MOVE	T1,P1		;BAD ADDRESS
	PUSHJ	P,PRTDI8##	;PRINT IT
	MOVEI	T1,[ASCIZ / (phys.), Contents = /]
	PUSHJ	P,CONMES##	;PRINT MORE MESSAGE
	MOVE	T1,P2		;GET BAD CONTENTS
	PUSHJ	P,HWDPNT##	;PRINT IT
IFN FTKL10,<
	MOVEI	T1,[ASCIZ /, ERA = /]
	PUSHJ	P,CONMES##	;CONTINUE MESSAGE
	MOVE	T1,.CPSTE##	;GET ERA FROM LAST SCAN TRAP
	PUSHJ	P,HWDPNT##	;PRINT IT
>
	PUSHJ	P,CRLF##	;END WITH CRLF
	ANDM	P1,.CPPAA##	;ACCUM AND OF BAD ADDRESSES THIS SWEEP
	ANDM	P2,.CPPAC##	;ACCUM AND OF BAD CONTENTS THIS SWEEP
	IORM	P1,.CPPOA##	;ACCUM OR OF BAD ADDRESSES THIS SWEEP
	IORM	P2,.CPPOC##	;ACCUM OR OF BAD CONTENTS THIS SWEEP
	MOVE	T2,.CPPTS##	;PARITY ERRORS FOUND ON CURRENT SCAN
	CAIG	T2,M.CBAT##	;IS THERE ROOM FOR THIS BAD ADR IN TABLE?
	MOVEM	P1,.CPBAT##-1(T2) ;YES, STORE IN I-TH POSITION IN CDB
	MOVEM	P1,.CPLPA##	;ALWAYS STORE LAST PARITY ADDRESS
	POPJ	P,		;RETURN
;HERE TO RECORD NON-EXISTANT MEMORY FOUND ON THE SWEEP

NXMRBD:	PUSH	P,T1		;SAVE T1
	AOS	.CPTNE##	;COUNT TOTAL NUMBER OF NXMS SEEN
	AOS	T2,.CPNTS##	;COUNT UP THE NUMBER SEEN THIS SWEEP
	SOJG	T2,NXMSEC	;JUMP IF NOT THE FIRST NXM THIS SWEEP
	MOVEM	P1,.CPMNA##	;FIRST THIS SWEEP, RECORD BAD ADDRESS
	MOVEI	T1,[ASCIZ /Non-existent memory detected:
/]
	PUSHJ	P,CONMES##	;ANNOUNCE ERRORS
NXMSEC:	SKIPN	T2,.CPLNA##	;SEEN A NXM?
	JRST	NXMSE1		;NO
	AOS	T2		;CONTIGUOUS WITH PREVIOUS NON-EXISTANT WORD?
	CAMN	P1,T2		; ...
	JRST	NXMSE2		;NO, JUST RECORD
	PUSHJ	P,PRTEMS	;YES, REPORT THE NXM RANGE
NXMSE1:	MOVEI	T1,[ASCIZ /  at /]
	PUSHJ	P,CONMES##	;PRINT "AT"
	MOVE	T1,P1		;GET BAD ADDRESS
	PUSHJ	P,PRTDI8##	;PRINT IT
	MOVEI	T1,[ASCIZ / (phys.)/]
	PUSHJ	P,CONMES##	;AND THIS
NXMSE2:	ANDM	P1,.CPNAA##	;AND OF BAD ADDRESSES
	IORM	P1,.CPNOA##	;OR OF BAD ADDRESSES
	MOVE	T2,.CPNTS##	;NUMBER OF NXM'S SEEN ON CURRENT SCAN
	CAIG	T2,M.CBAT##	;HAVE THE MAXIMUM NUMBER OF BAD ADDRESSES BEEN STORED?
	MOVEM	P1,.CPBAT##-1(T2) ;NO, STORE THIS ONE
 	MOVEM	P1,.CPLNA##	;ALWAYS STORE THE LAST BAD ADDRESS
	MOVE	T1,P1		;BAD ADDRESS TO T1
	LSH	T1,W2PLSH	;CONVERT TO BAD PAGE
	IDIVI	T1,^D36		;36 BITS/WORD
	MOVE	T2,BITTBL##(T2)	;BIT POSITION WITHIN THE WORD
	IORM	T2,NXMTAB##(T1)	;MARK THIS PAGE AS NON-EXISTANT
	POP	P,T1		;RESTORE T1
	JUMPE	T1,CPOPJ##	;RETURN IF BAD ADDRESS NOT IN THE MONITOR OR A JOB
	JUMPN	J,NXMJHS	;JUMP IF BAD ADDRESS IN SOME SEGMENT
	HRROS	.CPMPC##	;BAD ADDRESS IS IN THE MONITOR,
				; FLAG THIS AS A SERIOUS ERROR
	POPJ	P,		;AND CONTINUE THE SWEEP
NXMJHS:	JUMPL	J,NXMJH2	;FLAG JOB IF IN UPMP
	CAILE	J,JOBMAX##	;BAD ADDRESS IN A HIGH SEGMENT?
	PJRST	HGHPAR##	;YES, FLAG HIGH SEGMENT AS IN NXM
NXMJH2:	MOVEI	T1,JS.NXM	;BAD ADDRESS IN A LOW SEGMENT, FLAG
	IORM	T1,JBTSTS##(J)	; THE JOB TO BE STOPPED
	POPJ	P,		;AND RETURN TO CONTINUE THE SWEEP
;SUBROUTINE TO FLAG JOB FOR MESSAGE - IF APR DETECTED (RATHER THAN CHANNEL)
;CALL:	MOVE	J,JOB NUMBER
;	MOVE	S.CPAEF	;CPU OR CHAN DETECTED PARITY
;	PUSHJ	P,PARJOB
;	ALWAYS RETURN
;CALLED ON CPU0 AND CPU1

PARJOB:	TLNN	S,(CP.PSX)	;PARITY FOUND BY ANY PROCESSOR?
	POPJ	P,		;NO, RETURN
				;YES, FALL INTO PARJB1
;SUBROUTINE TO FLAG JOB FOR MEM PAR MESSAGE - ALWAYS
;CALL:	MOVE	J,JOB NUMBER
;	PUSHJ	P,PARJB1
;	ALWAYS RETURN

PARJB1::MOVSI	T1,JACCT	;CLEAR JACCT SO THAT DAMAGED PROGRAM
	ANDCAM	T1,JBTSTS##(J)	; WILL NOT HAVE PRIVILEGES
	MOVEI	T1,JS.MPE	;MEMORY PARITY ERROR IN JOB FLAG
	IORM	T1,JBTSTS##(J)	;SET JOB STATUS WORD
	POPJ	P,		;RETURN

;SUBROUTINE TO RETURN ALL JOBS WHICH ARE OR WOULD BE TOO BIG TO RUN
; IF MEMORY HAS DROPPED OFF LINE OR WERE TO BE SET OFF LINE
;CALLING SEQUENCE:
;	MOVE	T1,NEW VALUE OF CORMAX
;	MOVEI	J,0	;FIRST CALL
;	PUSHJ	P,JBSTBG
;RETURN CPOPJ IF NO JOB OR NONE OF THE REMAINING JOBS ARE TOO BIG, CPOPJ1
; IF A JOB IS TOO BIG, J = JOB NUMBER OF THE JOB WHICH IS TOO BIG

JBSTBG::PUSH	P,T1		;SAVE THE NEW VALUE OF CORMAX
JBSTB1:	ADDI	J,1		;LOOK AT THE NEXT JOB
	CAMLE	J,HIGHJB##	;LOOKED AT ALL JOBS?
	JRST	TPOPJ##		;YES, GIVE ALL DONE RETURN
	PUSHJ	P,SEGSIZ##	;SIZE OF THIS JOBS LOW SEGMENT
	PUSH	P,T2		;SAVE IT
	HRRZ	T1,JBTSGN##(J)	;POINT TO SEGMENT CHAIN
	JUMPE	T1,JBTSB4	;NO SEGS
	PUSH	P,J		;SAVE THE JOB NUMBER
JBTSB2:	SKIPLE	J,.HBSGN(T1)	;SEGMENT WORD FOR THIS SEGMENT
	  PUSHJ	P,SEGSIZ##	;REAL, GET THE SIZE OF THE HIGH SEGMENT
	ADDM	T2,-1(P)	;ADD IT IN
	HRRZ	T1,.HBLNK(T1)	;POINT TO NEXT SEGMENT
	JUMPN	T1,JBTSB2	;LOOP ON
	POP	P,J		;RESTORE THE JOB NUMBER
JBTSB4:	POP	P,T1		;RESTORE SUMMED SIZE
	LSH	T1,P2WLSH	;SIZE OF THE JOB IN WORDS
	CAMLE	T1,(P)		;IS THE JOB TOO BIG TO CONTINUE TO RUN?
	JRST	TPOPJ1##	;YES, SKIP RETURN TO CALLER
	JRST	JBSTB1		;NO, LOOK AT THE NEXT JOB
;HERE IF NO MEM PARITY - MUST BE APR ERROR
APRIL1:	SETZM	.CPAEF##	;CLEAR APR ERROR FLAG (IN CASE OTHER APR ERRORS
				; OCCUR BEFORE EXIT THIS CODE)
	DMOVE	T1,.CPAPC##	;ERROR PC STORED BY APR PI LEVEL
				; (REAL PC MAY HAVE BEEN ZEROED TO DISMISS INT)

	DMOVEM	T1,.CPPC##	;STORE IN CURRENT USER PROTECTED PC
				; (SO DUMP WILL KNOW REAL PC)
	DMOVEM	T1,.JDAT+JOBPD1##  ;STORE FOR POSSIBLE .JBINT

	TRNE	S,AP.PPV	;PROPRIETARY VIOLATION?
	JRST	APRPPV		;YES
	TRNN	S,AP.ILM	;ILLEGAL MEMORY?
	JRST	APRNXM		;NO
	SIGNAL	C$IMR		;SIGNAL ILL MEM REF CONDITION
	  SKIPA			;USER DOESN'T WANT TRAP
	POPJ	P,		;WANTS INTERCEPT GO TO USER

	MOVE	T1,.CPAPC##+1	;PC STORED BY APR INTERRUPT
	XOR	T1,.USPFW	;PAGE FAULT WORD
	TDNE	T1,[MXSECN*<HLGPNO+1>+<HLGPNO_P2WLSH>+PG.BDY]
	JRST	APRILR		;YES, GO PRINT ILL MEM REF
	JSP	T1,ERRPTU	;NO, PRINT PC EXCEEDS MEM BOUND
	ASCIZ	/PC out of bounds/
	JRST	APRSCD		;PRINT LOC, THEN STOP JOB

APRILR:	JSP	T1,ERRPTU
	ASCIZ	/Illegal memory reference/
	JRST	APRSCD		;PRINT LOC, THEN STOP JOB
APRNXM:	TRNN	S,AP.NXM	;NON-EX MEM?
	JRST	APRPDL		;NO
	SIGNAL	C$NXM		;SIGNAL JOB
	  SKIPA			;NOT INTERRESTED
	POPJ	P,		;TRAP TO USER
	SKIPE	J,.CPJOB##	;JOB RUNNING WHEN NXM HAPPENED
	PUSHJ	P,GIVRES	;RETURN RESOURCES, ETC.
	JSP	T1,ERRPTU	;YES
NXMMES::ASCIZ	/Non-existent memory/
	JRST	APRSCD		;PRINT LOC, THEN STOP JOB
APRPPV:	JSP	T1,ERRPTU
	ASCIZ	/Proprietary violation/
	JRST	APRSCD
;SUBROUTINE TO PRINT JOB NUMBER AND PROG NAME ON OPR
;CALL:	MOVEI	T1,JOB STATUS BIT (JS.MPE OR JS.DPM)
;	MOVE	U,LINE DATA BLOCK FOR CTY OR OPR
;	PUSHJ	P,OPRPJN	;PRINT JOB NUMBERS
;	ALWAYS RETURN

OPRPJN:	PUSH	P,T1		;SAVE JOB STATUS BIT TO TEST FOR MESSAGE
	PUSHJ	P,INLMES##	;TELL HIM JOB NOS. SO HE WILL RESTART
				; SYSTEM JOBS IF THEY HAVE PROBLEM
	ASCIZ	/ for job/
	MOVE	J,HIGHJB##	;HIGHEST JOB NUMBER
;LOOP TO PRINT JOB NOS. AND PROGRAM NAME OF ALL JOBS WITH BAD PARITY
; OR DAEMON PROBLEM MESS
PARLP1:	MOVE	T1,JBTSTS##(J)	;JOB STATUS WORD
	TDNE	T1,(P)		;DOES THIS JOB HAVE BAD PARITY OR DAEMON
				; PROBLEM? (DEPENDING ON CALLERS ARG)
	PUSHJ	P,PRJBNM	;YES, PRINT JOB# AND PROGRAM NAME
	SOJG	J,PARLP1	;ANY MORE JOBS?
	POP	P,T1		;RESTORE STACK
	PJRST	CRLF##		;NO, PRINT CRLF AND RETURN

;SUBROUTINE TO PRINT SWAP OUT MEM PAR ERROR
;CALL:	MOVE	J,JOB USING HIGH SEG (WHETHER IN CORE OR NOT)
;	PUSHJ	P,SWOMES
;	ALWAYS RETURN JOB SWAPPED, DAEMON CALLED

SWOMES::MOVSI	T1,JERR		;SET JERR SO WE DO NOT
	IORM	T1,JBTSTS##(J)	;TRY TO INTERCEPT
	JSP	T1,ERRPNT	;PRINT MESSAGE
	ASCIZ	/Swap out channel memory parity error/
	PJRST	APRSCD		;PRINT PC AND STOP JOB

;SUBROUTINE TO PRINT <SPACE> JOB NO. [PROG. NAME]
;CALL:
;	MOVE	J,JOB NUMBER
;	MOVE	U,LDB FOR OPR OR CTY
;	PUSHJ	P,PRJBNM		;PRINT JOB NO. AND PROG. NAME
;	ALWAYS RETURN
PRJBNM::PUSHJ	P,PRSPC##	;YES, PRINT LEADING SPACE
	MOVE	T1,J		;PRINT JOB NO.
	PUSHJ	P,RADX10##	;AS DECIMAL
	PUSHJ	P,PRLBK##	;PRINT LEFT BRACKET
	MOVE	T2,JBTPRG##(J)	;PROGRAM NAME
	PUSHJ	P,PRNAME##	;PRINT SO OPER WILL RECOGNIZE HIS JOBS
	PJRST	PRRBK##		;PRINT RIGHT BRACKET AND RETURN TO CALLER
;SUBROUTINE TO CHECK IF JOB HAS BEEN WAITING FOR TWO SUCCESSIVE
; MINUTE CHECKS FOR DAEMON.  CALLED ONCE A MINUTE FOR EACH JOB
;CALL:	MOVE	J,JOB NUMBER
;	PUSHJ	P,DPMJOB
;	  YES	RETURN - MESSAGE PRINTED ON JOB CONSOLE
;	NO RETURN

DPMJOB::MOVE	T1,JBTSTS##(J)	;JOB STATUS WORD
	TRNN	T1,JS.DPM	;THIS JOB BEEN WAITING FOR 2 CONSECUTIVE MIN?
	JRST	CPOPJ1##	;NO
	PUSHJ	P,STDAEM##	;START DAEMON
	  PJRST	DAEDON##	;NO DAEMON
	PUSHJ	P,TTYFND##	;YES, FIND CONTROLLING TTY
	JUMPE	U,CPOPJ##
	PUSHJ	P,DAEPRB	;PRINT PROBLEM WITH DAEMON
	PUSHJ	P,INLMES##	;TELL USER WHAT SYSTEM IS DOING ABOUT IT
	ASCIZ	/, operator action requested
/
	PJRST	TTYSTR##	;START TTY

;SUBROUTINE TO PRINT ON OPR PROBLEM WITH DAEMON
;CALLED ONCE A MIN ONLY IF A JOB IS STILL WAITING
;CALL:	PUSHJ	P,DPMOPR

DPMOPR::MOVE	U,OPRLDB##	;OPR LINE DATA BLOCK HDR
	PUSHJ	P,DAEPRB	;PRINT PROBLEM WITH DAEMON
	MOVEI	T1,JS.DPM	;JOB STATUS BIT - NEED DAEMON PROB MESS.
	PJRST	OPRPJN		;TELL OPR WHICH JOBS ARE STUCK

;SUBROUTINE TO PRINT PROBLEM WITH DAEMON
;CALL:	MOVE	U,LINE DATA BLOCK ADR
;	PUSHJ	P,DAEPRB

DAEPRB:	PJSP	T1,CONMES##	;PRINT MESSAGE AND RETURN
	ASCIZ	/
%Problem with DAEMON/
APRPDL:	TRNE	S,AP.POV	;PUSHDOWN OVERFLOW?
	JRST	PRTPOV		;YES - PRINT USER ERROR MESSAGE

	TRNN	S,AP.FOV!AP.AOV	;ARITHMETIC OR FLOATING OVERFLOW?
	JRST	APRLTH		;NO, SEE IF LOOP
	JSP	T1,ERRPTU	;OUTPUT MESSAGE
	ASCIZ	/Arithmetic overflow at extended/
	JRST	APRSCD		;GIVE PC

APRLTH:	TRNN	S,XP.LTH	;LOOP IN TRAP HANDLER?
	STOPCD	CPOPJ##,DEBUG,SAC, ;++STRANGE APR CONDITION
	JSP	T1,ERRPTU	;TYPE MESSAGE
	ASCIZ	/Loop in trap handler/
	JRST	APRSCD		;AND PC OF ERROR

PRTPOV:
	SIGNAL	C$PLOV		;SEE IF USER CARES
	  SKIPA			;DOESN'T
	POPJ	P,		;HE DOES

	JSP	T1,ERRPTU	;PRINT ERROR MESSAGE
PDLMES::ASCIZ	/Push down list overflow/
APRSCD:	DMOVE	T1,.CPAPC##	;PRINT APR PC
	JRST	DPCPNT		;AS:
				; 1)"AT USER LOC XXX" OR
				; 2)"AT EXEC LOC XXX; EXEC CALLED FROM
				; EXEC/USER LOC YYY
SUBTTL	PDL OVERFLOW RECOVERY CODE

;THIS CODE WILL EXTEND A UUO LEVEL PDL; IT SHOULD BE JRSTD TO (IN SECTION 1
;FOR FTXMON MONITORS) FROM K?SER ON A PDL OVERFLOW TRAP.  THE PDL IS EXTENDED
;USING FUNNY SPACE.  THE FOLLOWING RESTRICTIONS APPLY:
;
;1)	IF SUFFICIENT FUNNY SPACE IS NOT AVAILABLE (INSUFFICIENT CONTIGUOUS
;	FREE SLOTS, NO SWAP SPACE, ETC.) THE PDLOVF STOPCODE WILL STILL OCCUR.
;
;2)	IF A PDL OVERFLOW OCCURS WHILE UP.EPL IS LIT IN .USBTS, THE CODE WILL
;	NOT ATTEMPT TO RECOVER AND A PDLOVF STOPCODE WILL RESULT.  THIS IS
;	CURRENTLY TRUE ONLY WHILE THE JOB IS IN THE RECOVERY CODE ITSELF.
;
;ADDITIONALLY, THERE IS A THIRD RESTRICTION WHICH COULD BE REMOVED IF IT IS
;DEEMED NECESSARY, AND THE APPROPRIATE CHECKS ARE MADE:
;
;3)	IF THE STACK IS ALREADY EXTENDED, WE WILL NOT ATTEMPT TO EXTEND THE
;	STACK AGAIN.  THE CODE CAN DO THIS, HOWEVER, IN ORDER TO DO THIS, IT
;	IS NECESSARY TO MOVE THE ORIGIN OF THE STACK.  PAGES ALLOCATED TO THE
;	OLD STACK WILL BE RECLAIMED AT THAT TIME.  CODE ELSEWHERE IN THE MONITOR
;	WHICH PASSES AROUND AN ADDRESS ON THE STACK WILL THEREFORE NO LONGER
;	POSSESS A VALID ADDRESS IN THAT POINTER.  ALTHOUGH THE STACK IS MOVED
;	FROM JOBPDO WHEN EXTENDED THE FIRST TIME, PAGES ARE NOT RECLAIMED SO
;	ANY POINTERS THUS SET UP ARE STILL VALID EVEN THOUGH THE STACK HAS
;	MOVED.  TRVAR AND OTHER T-20 MACROS USE ONE AC FOR THIS PURPOSE (FP),
;	THE ROUTINES AND MACROS WHICH SET UP AND CLEAR THE USE OF FP COULD
;	SET FLAGS SO THAT CODE COULD BE ADDED TO THIS ROUTINE TO GET FP ADJUSTED
;	IF THE STACK MOVES.  THERE ARE, HOWEVER, OTHER PLACES (AT LEAST ONE
;	IN FEDSER) WHICH ALSO WOULD NEED TO BE FIXED; THE EXISTENCE OF OTHER
;	PLACES NEEDS ALSO TO BE RESEARCHED FURTHER BEFORE ANY OF THIS CAN
;	BE IMPLEMENTED.
;
;TO REMOVE RESTRICTION THREE, REMOVE THE LINE OF CODE UNDER "REPEAT 1" AT
;EXTPDL+1 AND ADD THE APPROPRIATE CODE ENUMERATED IN RESTRICTION 3 ABOVE.

EXTPDL::
	MOVEI	P,UP.EPL	;ARE WE ALREADY TRYING TO RECOVER?
REPEAT 1,<			;UNTIL FRAME POINTERS EXIST,
	SKIPN	.USEPL		;WE CAN'T MOVE AN EXTENDED STACK
>				;(SEE COMMENTS ABOVE)
	TDNE	P,.USBTS	;?
	JRST	EPOSTP		;YES, ERROR
	IORM	P,.USBTS	;FLAG IN EMERGENCY PDL
	DMOVEM	T1,.CPSTT##	;SAVE A COUPLE OF ACS
	MOVE	T1,.CPAPC##+1	;GET PC
	MOVEM	T1,.USMUP	;PUT IT BACK IN CASE WE NEED IT LATER
	MOVE	T1,-1(T1)	;GET INSTRUCTION WHICH OVERFLOWED
	TLNN	T1,(<Z	<17^!P>,>) ;BE SURE IT'S P THAT OVERFLOWED
	TLNN	T1,(<Z	P,>)
	JRST	EPOSTP		;NO, ERROR
	MOVE	P,@.CPEPL##	;GET OVERFLOWED PDL
	HLRE	T1,P		;MAKE IT ONLY OVERFLOW BY 1 WORD (ADJSP)
	MOVNS	T1
	ADJSP	P,(T1)
	HRLI	P,-EPDLEN	;THEN SET UP FOR EMERGENCY AREA
	DMOVE	T1,.CPSTT
	PUSHJ	P,EXTPD2	;MUST DO THE FOLLOWING AS A SUBROUTINE
	MOVE	P,@.CPEPL##	;REAL PDL TO RESTART USER WITH
	AOS	EPOREC##	;INCREMENT # OF EPOS RECOVERED FROM
	XJRSTF	.USMUO		;RESTORE FLAGS AND RETURN
;HERE TO DO THE REAL WORK OF EXTENDING THE STACK

EXTPD2:	PUSHJ	P,SAVT##	;SAVE ALL TS
	MOVE	T1,@.CPEPL##	;IN CASE IT GETS CHANGED WHEN WE BLOCK
IFN FTMP,<
	PUSHJ	P,MMOWN##	;OWN MM?
	  PUSHJ	P,GGVMM##	;NO, MUST HAVE IT FOR THE FOLLOWING
>
	PUSH	P,T1		;SAVE OVERFLOWED STACK POINTER
	HLRZ	T2,(P)		;MINIMUM # OF WORDS WE NEED -1
	SKIPN	T1,.USEPL	;IF MOVING FROM JOBPDO
	ADDI	T2,PDLLEN	;INCLUDE PDLLEN HERE (TAKEN CARE OF LATER
				;IF ALREADY EXTENDED)
	LSH	T2,W2PLSH	;MINIMUM # OF PAGES WE NEED, -1
	AOS	T2		;# OF PAGES WE NEED
	JUMPE	T1,DOPDL2	;NOT ALREADY EXTENDED, PROCEED
	MOVE	T3,T2		;SAVE IT
	HRRZS	T1		;CLEAR LEFT HALF
	LSH	T1,W2PLSH	;PAGE # PREVIOUS TO PAGE WHERE EPL STARTS
	SUBI	T1,FYSORG/PAGSIZ ;PAGE # RELATIVE TO FUNNY SPACE
DOPDL0:	SKIPE	.UPMP+.UMORG(T1) ;IS PREVIOUS PAGE FREE?
	JRST	DOPDL1		;NO, MUST MOVE PDL AGAIN
	SOJLE	T2,DOPDL7	;YES, JUST USE PREVIOUS PAGE(S)
	SOJGE	T1,DOPDL0	;CHECK PREVIOUS PAGE IF THERE IS ONE
DOPDL1:	HLRE	T2,.USEPL	;# OF WORDS IN CURRENT EXTENDED STACK
	ASH	T2,W2PLSH	;CONVERT TO PAGES
	SUBM	T3,T2		;# OF ADDITIONAL PAGES WE NEED
DOPDL2:	MOVNI	T2,(T2)
	MOVSI	T2,(T2)		;AOBJN COUNTER
	MOVEI	T1,.UMWSB-.UMORG-1 ;START LOOKING AT THE TOP OF FUNNY SPACE
DOPDL3:	SKIPN	.UPMP+.UMORG(T1) ;IS THIS SLOT FREE?
	JRST	DOPDL5		;YES
	TRNN	T2,-1		;ALREADY STARTED A CONTIGUOUS BLOCK?
	JRST	DOPDL4		;NO
	MOVEI	T3,(T2)		;RESET THE AOBJN POINTER
	HRLS	T3
	SUB	T2,T3
DOPDL4:	SOJGE	T1,DOPDL3	;NO, CHECK NEXT
	JRST	EPOSTP		;FAILED
DOPDL5:	AOBJN	T2,DOPDL4	;CONTINUE IF NEED MORE PAGES
	TLOA	T1,(1B0)	;FLAG WE ALREADY KNOW ENTIER PDL SIZE

;HERE WE HAVE FOUND ENOUGH PAGES TO EXTEND THE PDL.  T3=# OF PAGES, T1=FIRST
;PAGE NUMBER RELATIVE TO BEGINNING OF FUNNY SPACE
;(WE ALSO FALL INTO THIS CODE FROM ABOVE WITH T2=# OF PAGES AND IGNORE THE
;FIRST INSTR WHICH LOADS T2 FROM T3)

DOPDL7:	MOVEI	T2,(T3)		;GET # OF PAGES FROM T3
	SETZ	T3,		;CACHE IT
	PUSH	P,T1		;SAVE RELATIVE PAGE #+FLAG
	MOVEI	T1,.MCFV/PAGSIZ(T1) ;PAGE # OF THE PAGE DESIRED
	PUSH	P,T2		;SAVE T2 (# OF PAGES REQUIRED)
	PUSHJ	P,GETMPG##	;GET PAGES FOR THE JOB'S PDL
	  JRST	EPOSTP		;LOSE IF CAN'T ALLOCATE IT
	POP	P,T2		;RESTORE T2 (# OF PAGES ADDED)
	POP	P,T1		;RESTORE STARTING ADDRESS
	TLZE	T1,(1B0)	;ADDED PAGES OR CREATED NEW SET?
	JRST	DOPD12		;CREATED NEW SET
	HLRE	T3,.USEPL	;-# OF WORDS IN OLD STACK
	MOVNS	T3		;# OF WORDS IN OLD STACK
	MOVEI	T3,PG.BDY(T3)	;FOR ROUNDING TO # OF PAGES
	LSH	T3,W2PLSH	;PAGES
	ADD	T2,T3		;# OF PAGES IN NEW (EXTENDED) STACK
	TDZA	T3,T3		;FLAG NO DELETE OF OLD STACK
;HERE ON A NON-RECOVERABLE PDL OVERFLOW

EPOSTP::
	MOVE	P,.CPEPL##	;GET NEW PDL POINTER
	HRLI	P,-<EPLLEN##-1>
	STOPCD	.,JOB,PDLOVF,	;++EXEC PDL OVERFLOW
;HERE TO MOVE THE CURRENT PDL TO SOME NEW ADDRESS.  T1 CONTAINS THE
;PAGE # RELATIVE TO FYSORG/PAGSIZ WHERE NEW STACK WILL BE, T2 CONTAINS # OF PAGES

DOPD12:	SETO	T3,		;DELETE OLD STACK IF NOT JOBPDO
	MOVEI	T1,FYSORG/PAGSIZ(T1) ;MAKE FIRST PAGE #
	LSHC	T1,P2WLSH	;CONVERT TO WORDS
	PUSH	P,T3		;SAVE DELETE FLAG
	PUSH	P,T2		;SAVE # OF WORDS IN NEW STACK (INCLUDES EPDLEN)
	HRRZ	T3,P		;FINAL WORD TO MOVE FROM
	PUSH	P,T1		;SAVE WORD ADDR
	SKIPN	T4,.USEPL	;ALREADY EXTENDED?
	MOVEI	T4,.JDAT+JOBPDL## ;NO, MOVE FROM JOBPDL
	HRLI	T1,1(T4)	;MAKE BLT POINTER
	SUBI	T3,1(T4)	;# OF WORDS TO MOVE
	ADDI	T3,(T1)		;FINAL ADDRESS TO MOVE TO
	BLT	T1,(T3)		;MOVE THE STACK
	SUBI	T2,EPDLEN	;# OF WORDS IN NEW PDL (LEAVING EMERGENCY ROOM)
	MOVNS	T2		;-# OF WORDS
	POP	P,T4		;NEW STACK POINTER ORIGIN
	SOS	T4
	HRLI	T4,(T2)		;NEW STACK POINTER COUNT
	MOVEI	T1,(P)		;CURRENT ADDRESS OF OLD TOP OF STACK
	HRRI	P,(T3)		;NEW STACK POINTER
	SUBI	T3,(T1)		;NEW STACK-OLDSTACK
	ADDM	T3,-2(P)	;UPDATE OVERFLOWED POINTER
	POP	P,T1		;TOTAL # OF WORDS IN NEW STACK
	SUBI	T1,EPDLEN	;SUBTRACT OUT EMERGENCY ROOM
	SKIPN	T3,.USEPL	;# OF WORDS IN OLD STACK
	MOVSI	T3,MJOBPD##	;IF MOVING FROM JOBPDL
	HLLZS	T3		;-# WORDS IN OLD STACK,,0
	MOVNS	T1		;-# OF WORDS IN NEW STACK
	HRLZS	T1		;-# OF WORDS IN NEW STACK,,0
	SUB	T1,T3		;-NEW--OLD=OLD-NEW
	ADDM	T1,-1(P)	;-OLD+(OLD-NEW)=-NEW
	POP	P,T3		;NODELETE FLAG
	POP	P,@.CPEPL	;PUT IT FOR RECOVERY CODE TO FIND
	EXCH	T4,.USEPL	;SET NEW STACK POINTER
	JUMPE	T4,DOPD14	;NO OLD PAGES TO DELETE
	JUMPE	T3,DOPD14
	PUSHJ	P,SAVE2##
	AOS	P1,T4		;-# WORDS IN OLD STACK,,1ST PAGE
	ASH	P1,W2PLSH	;-# PAGES IN OLD STACK,,JUNK(9)1ST PAGE(9)
	TRZ	P1,-1^!<PG.BDY>	;CLEAR JUNK
DOPD13:	MOVEI	P2,(P1)		;PAGE TO RETURN
	PUSHJ	P,DLTFSP##	;DELETE FUNNY PAGE
	AOBJN	P1,DOPD13
DOPD14:	MOVEI	T1,UP.EPL
	ANDCAM	T1,.USBTS
	POPJ	P,
;HERE TO GO BACK TO THE NORMAL STACK
;THIS MAY BE CALLED AT EITHER UUO OR CLOCK LEVEL, BUT IF CALLED
;AT CLOCK LEVEL THE CPU MUST POSSESS THE MM.

ZAPEPL::SKIPN	T1,.USEPL	;ANY EXTENDED STACK?
	POPJ	P,		;NO, NOTHING TO DO THEN
	PUSHJ	P,SAVE2##	;NEED TO USE THE PS
	MOVEI	T1,1(T1)	;ADDRESS OF STACK
	HRLI	P1,(T1)		;FIRST WORD TO MOVE FROM
	MOVEI	P2,(T1)		;ONE MORE COPY
	PUSHJ	P,INTLVL##	;IF AT UUO LEVEL,
	  JRST	ZAPEP0		;TAKE STACK FROM CURRENT P
	SKIPN	JBTADR##(J)	;IF THERE IS NO CORE FOR JOB
	JRST	ZAPEP1		;JUST GET RID OF THE PAGES
	HRRZ	T3,.JDAT+JOBDAC##+P	;GET P FROM JOB DATA AREA
	JRST	ZAPEP3
ZAPEP0:
IFN FTMP,<
	PUSHJ	P,MMOWN##	;OWN THE MM?
	  PUSHJ	P,GGVMM##	;GET IT IF WE DON'T
>
	MOVEI	T3,(P)
ZAPEP3:	CAIL	T3,.JDAT+JOBPDL##+1 ;IS IT IN FUNNY SPACE OR .UUPMP?
	JRST	ZAPEP1		;.UUPMP, SOMEONE (COMCON) MUST HAVE PUT IT BACK
	SUBI	T1,(T3)		;-# OF WORDS IN CURRENT STACK
	MOVNS	T3,T1		;NEGATE AND SAVE (MAKE POSITIVE)
	CAILE	T1,PDLLEN	;ONLY GET RID OF EXTENDED STACK IF WHAT'S THERE FITS
	POPJ	P,
	ADDI	T1,.JDAT+JOBPDL##+1 ;LAST WORD TO MOVE TO
	HRRI	P1,.JDAT+JOBPDL##+1 ;FIRST WORD TO MOVE FROM
	BLT	P1,(T1)		;MOVE THE STACK
	MOVE	T1,[MJOBPD##,,.JDAT+JOBPDL##]
	ADJSP	T1,1(T3)	;MAKE CURRENT
	PUSHJ	P,INTLVL##	;AT UUO LEVEL?
	  SKIPA	P,T1		;YES, SET UP P
	MOVEM	T1,.JDAT+JOBDAC##+P	;NO, STORE NEW P
ZAPEP1:	HLRE	P1,.USEPL	;# OF WORDS IN EXTENDED PDL (NEGATIVE)
	SUBI	P1,EPDLEN	;INCLUDING EMERGENCY WORDS
	LSH	P1,^D18+W2PLSH	;-# OF PAGES
	LSH	P2,W2PLSH	;1ST PAGE
	HRRI	P1,(P2)		;SAVE IN P1
	SE1ENT
ZAPEP2:	MOVEI	P2,(P1)		;PAGE #
	PUSHJ	P,DLTFSP##	;DELETE PAGE
	AOBJN	P1,ZAPEP2
	SETZM	.USEPL		;NO MORE EXTENDED PDL
	POPJ	P,
;ADDRESS CHECK ERROR AT ANY LEVEL
;F MUST BE SET UP TO POINT TO OFFENDING DEVICE

ADRERR::LDB	J,PJOBN##	;OFFENDING JOB'S JOB NUMBER
	PUSH	P,F		;GIVRES CLOBBERS F
	PUSHJ	P,GIVRES	;RETURN ANY RESOURCES THE JOB MIGHT HAVE
	POP	P,F		;RESTORE F
	SIGNAL	C$ADCK		;SEE IF USER ENABLED FOR ADDRESS CHECK
	  SKIPA			;USER DOESN'T WANT TRAP
	JRST	ERRGOU		;GO TO USER

	JSP	T1,ERRDEV	;GET JOB NO. FROM DEVICE DATA BLOCK
	ASCIZ	/Address check for /
	JRST	DEVEXC		;PRINT "DEVICE XXX; EXEC CALLED FROM
				; EXEC/USER LOC YYY"
				; THEN STOP JOB
;SUBROUTINE TO CLEAR ALL DDB'S, IO CHARS
;CALL WITH JOB NUMBER IN J
ZAPHIM:	PUSHJ	P,SVEUB##	;MAKE HIM ADDRESSABLE
ZAPHER::PUSHJ	P,SWPCLN##	;ZAP THE ACCESS TABLES
	PUSHJ	P,GIVRSC	;GIVE UP RESOURCES
	PJRST	ZAPUSC		;PITCH INITED DDB'S
ZAPUSR::JUMPE	J,CPOPJ##
	PUSHJ	P,GIVRSC	;GIVE UP ANY INTERLOCKS JOB MAY OWN
	NTGIVE			;RELEASE NETSER INTERLOCK TOO
	CAMN	J,.CPJOB##	;CURRENT JOB?
	POPJ	P,		;YES, GIVE UP INITED DDB'S ON RESET
				; (ALL SHARED RESOURCES ALREADY GIVEN UP)
ZAPUSC::PUSHJ	P,CTXJCJ##	;GET CURRENT CONTEXT NUMBER FOR TARGET JOB
	  MOVEI	T1,(J)		;???
	PUSH	P,T1		;SAVE
	PUSHJ	P,ZAPDSK##	;REMOVE ALL DDBS OWNED BY JOB FROM UNI/CHN Q'S
IFN FTNET,<SETOM NETZAP##>	;AVIOD WEM STOPCODES
ZAPUS1:	HLRZ	F,DEVLST##	;LOC OF FIRST DDB
ZAPUS2:	LDB	T1,PJCHN##	;OWNER OF DDB
	JUMPE	T1,ZAPUS3	;DON'T TRY TO ZAP IT IF NOT OWNED (MPXDDB)
	MOVEI	T2,DEPMSG	;IS THIS DDB CONTROLLED BY MPX
	TDNN	T2,DEVMSG(F)	;IF SO, GIVE IT UP WHEN WE ZAP MPX
	CAME	T1,(P)		;RIGHT GUY OWN IT
	JRST	ZAPUS3		;NO, DON'T RELEASE
	CAIE	F,DSKDDB##	;NO, DON'T RELEASE IT (TRYING TO RELEASE DSKDDB
				; WILL CAUSE AN IME
	PUSHJ	P,RELEA4##	;YES, RELEASE IT
	JUMPE	F,ZAPUS1	;F=0 IF NETWORK DDB WAS RELEASED
ZAPUS3:	HLRZ	F,DEVSER(F)
	JUMPN	F,ZAPUS2
IFN FTNET,<SETZM NETZAP##>	;CLEAR FLAG
	JRST	TPOPJ##		;PRUNE STACK AND RETURN

;SUBROUTINE TO RESET A JOB WHOSE ASSOCIATED
;HISEG HAD A SWAP INPUT ERROR

ZAPHGH::SKIPN	JBTADR##(J)
	POPJ	P,
	PUSHJ	P,CLRJOB##
	PUSHJ	P,ZAPUSR
	PJRST	ERRSWP
;SUBROUTINE TO RETURN ALL RESOURCES
;CALL WITH J=JOB#
GIVRES::NTGIVE			;RETURN THE NETWORK INTERLOCK
	JUMPE	J,CPOPJ##
	CAMN	J,.CPJOB##	;NO DEVICES ACTIVE IF NOT CURRENT JOB
	PUSHJ	P,IOWAIT##	;WAIT FOR ANY ACTIVE DEVICES TO FINISH
GIVRSC::HLRZ	F,SWPDDB##+DEVSER ;START AT FIRST DSK
GIVRS0:	MOVE	T1,DEVMOD(F)	;IS THIS A DISK?
	TLNN	T1,DVDSK
	SKIPGE	DEVSPL(F)	;NO, SPOOLED DDB?
	CAIA			;YES
	JRST	GIVRS3		;NO
	MOVE	S,DEVIOS(F)
	LDB	T1,PJOBN##	;YES, THIS JOB OWN IT?
	CAMN	T1,J
	PUSHJ	P,RETRES##	;YES, RETURN ANY RESOURCES IT OWNS
GIVRS3:	PUSHJ	P,NXDDB##	;AND TRY NEXT DDB
	  JRST	[JUMPE F,GIVRS1 ;DONE IF 0
		 CAMN J,.USJOB
		 JRST GIVRS0	;CONTINUE IF JOB IS ADDRESSABLE
		 JRST GIVRS1]	;NEXT ADDRESSABLE - DONE
	JRST	GIVRS0		;TRY NEXT
GIVRS1:	SETZ	T1,		;START WITH FIRST RESOURCE
	DPB	T1,PJBSTS##	;MAKE SURE THAT JOB DOESN'T APPEAR
				; TO HAVE ACTIVE DISK I/O
GIVRS2:	CAMN	J,USRTAB##(T1)	;OWNED BY JOB?
	PUSHJ	P,DVFREE##(T1)	;YES--FREE IT UP
	CAIGE	T1,AVLNUM##	;DONE YET?
	AOJA	T1,GIVRS2	;NO--CONTINUE
	PUSHJ	P,ADFREE##	;RETURN AU, DA, AND FA IF OWNED
	PUSHJ	P,IPCULK##	;GIVE ANY IPCF INTERLOCK WE OWN
	PUSHJ	P,DTXFRE##	;AND ANY DECTAPE KONTROLLERS
	PUSHJ	P,DWNCX##	;CX IF OWNED
	PUSHJ	P,TPFREE##	;FREE UP TAPE KONTROLLERS
IFN FTKL10,<
	PUSHJ	P,GIVPMR##	;DOES THIS JOB HAVE THE PERFORMANCE METER?
				;NO, SO DON'T GIVE IT UP.
				;YES, GIVE IT BACK SO OTHERS MAY MEASURE
>;END IFN FTKL10
IFN	FTLOCK,<
	PUSHJ	P,UNLOCK##	;UNLOCK THE JOB IF LOCKED
	  JFCL
>
	POPJ	P,		;RETURN
NPDUFL::STOPCD	.,STOP,NPU,	;++NULL PUSH-DOWN-LIST UNDERFLOW

;JSR TO HERE FROM INTRPT LOC
	$LOW
PIERR::0
	EXCH	P,PIEPDL
	STOPCD	.,CPU,PIE,	;++PRIORITY INTERRUPT ERROR
PIEPDL::XWD	0,.
	BLOCK	1
	$HIGH
SUBTTL	COMMON ROUTINES FOR HANDLING ERRORS IN MEMORY

;SUBROUTINE - ABSOLUTE ADDRESS TO SEGMENT NUMBER
;CALL:	MOVE	P1,ABSOLUTE ADDRESS
;	PUSHJ	P,CPIASN
;	  ERROR RETURN IF NOT IN MONITOR OR A HIGH OR LOW SEGMENT OR A UPMP
;	OK RETURN J=0 IF IN MONITOR, OR HIGH OR LOW SEG NO., OR -J IF JOB'S UPMP
;ENTER AT CPIASP IF T1 ALREADY CONTAINS PAGE #

CPIASN::LDB	T1,[POINT 13,P1,26] ;SET REL. ADR. FROM ABS. ADR IN MONITOR
CPIASP::SE1ENT			;PAGTAB LIVES IN MS.MEM, HAVE TO RUN EXTENDED
	MOVE	T3,T1		;AND IN CASE WE NEED IT...
	SETZB	T2,J		;ASSUME IN MONITOR (JOB 0 NOT A LEGAL JOB #)
	MOVE	T1,@[IW MS.MEM,PAGTAB(T1)] ;GET PAGTAB ENTRY FOR THIS PAGE
	TLNE	T1,MONTRB	;IS THIS A MONITOR PAGE?
	JRST	CPOPJ1##	;YES, GIVE OK RETURN WITH J=0
	SSX	T3,MS.MEM	;POINT TO MEMTAB SECTION
	MOVSI	T1,(P2.TRN)	;TRANSIENT PAGE?
	TDNN	T2,PT2TAB(T3)	;?
	JRST	CPIAS2		;NO
	LDB	J,[POINT MT.SJB,MEMTAB(T3),^L<MT.JOB>+MT.SJB-1] ;GET JOB
	JRST	CPOPJ1##	;FOUND JOB
CPIAS2:	HRRZ	T2,PT2TAB(T3)	;POINT TO PREVIOUS PAGE
	JUMPE	T2,CPIAS3	;FOUND STARTING PAGE
	HRRI	T3,(T2)		;POINT BACK ANOTHER PAGE
	JRST	CPIAS2

CPIAS3:	MOVEI	T2,JOBMAX##	;SCAN TO SEE IF BAD ADDRESS IS IN A UPMP
AUPLOP:	HRRZ	T1,JBTUPM##(T2)	;T1=PAGE NUMBER OF THE UPMP
	CAIE	T1,(T3)		;BAD WORD IN THIS UPMP OR MAP?
	SOJG	T2,AUPLOP	;NO, SCAN ALL USER PAGE MAP PAGES
AUPLO1:	JUMPG	T2,[MOVN J,T2	;IF YES, NEGATIVE JOB NUMBER TO J
		PJRST CPOPJ1##] ;SKIP RETURN
	MOVEI	J,1		;NOW SCAN ALL HIGH/LOW SEGS. STARTING WITH JOB 1
ASNLOP:	SKIPN	JBTADR##(J)	;IS THIS JOB OR HIGH SEG IN CORE?
	JRST	ASNAOJ		;NO, LOOK AT THE NEXT SEGMENT
	MOVEI	T1,0		;ASSUME PARITY ERROR IS IN PAGE 0 OF THIS SEGMENT
	MOVSI	T2,SHRSEG	;SHARABLE SEGMENT BIT
	CAILE	J,JOBMAX##	;IS THIS A LOW SEGMENT?
	TDNE	T2,JBTSTS##(J)	;NO--THEN IT IS A SHARABLE HIGH SEG?
	CAIA			;LOW SEG OR SHARABLE HIGH SEG
	JRST	ASNAOJ
	LDB	T2,JBYSSA##	;;GET FIRST PAGE OF SEGMENT
	CAIN	T2,(T3)		;IS THIS PAGE THE SAME PAGE WHICH CONTAINED AN ERROR?
	JRST	ASNMAP		;YES--SEE IF A MAP
ASNAOJ:	CAIG	J,JBTMAX##	;LOOKED AT ALL SEGMENTS?
	AOJA	J,ASNLOP	;NO, LOOK AT NEXT SEGMENT
	POPJ	P,		;NOT IN MONITOR OR ANY JOB

ASNMAP:	CAILE	J,JOBMAX	;A JOB?
	  JRST	CPOPJ1##	;NO, NOT A MAP IF A HIGH SEG
	PUSHJ	P,SVEUB##	;MAP THIS USER
	MOVE	T3,P1		;GET WORD IN QUESTION AGAIN
	LSH	T3,W2PLSH	;CONVERT TO PAGE
	MOVE	T1,[-<MXSECN+1>,,.UPMVP/PAGSIZ]
	AOBJP	T1,CPOPJ1##	;NOT A MAP; S0 CAUGHT ABOVE
	SE1ENT			;FOR PAGE MAP REFERENCES
	SKIPA	T4,[.UPMVP/PAGSIZ]
ASNMP1:	AOSA	T4		;INCREMENT
	PUSHJ	P,GMPTR##	;GET ENTRY (FIRST TIME)
	MOVE	T2,(T4)		;GET NEXT ENTRY
	TLZ	T2,(PM.NAD^!PM.COR)
	TLZE	T2,(PM.COR)	;IN-CORE POINTER?
	CAIE	T2,(T3)		;AND THE ONE WE WANT?
	AOBJN	T1,ASNMP1	;NO, LOOK ON
	SKIPGE	T1		;FIND IT?
	MOVNS	J		;YES, IS A MAP, NEGATIVE JOB #
	JRST	CPOPJ1##

;SUBROUTINE TO CHECK IF THE PAGE IN T1 IS A HIGH SEG MAP.  IF SO, RETURN
;CPOPJ1 WITH J CONTAINING AOBJN PTR FOR SEG IN QUESTION,
;ELSE J UNCHANGED WITH CPOPJ RETURN
;CALL WITH J=0 FIRST TIME, J=PREVIOUS POINTER RETURNED SUCCEEDING TIMES

CKHMAP::PUSHJ	P,SAVE1##	;SAVE P1
	PUSH	P,J		;SAVE J
	SKIPN	J		;IF NOT FIRST TIME
	MOVE	J,SEGPTR##	;POINT TO HIGH SEGS
CKHM1:	HRRZ	T2,JBTUPM##(J)	;GET MAP
	CAIE	T1,(T2)		;PAGE MATCH?
	AOBJN	J,CKHM1		;NO
	JUMPGE	J,JPOPJ##	;NOT FOUND AS ANY HIGH SEG MAP
	MOVEM	J,(P)		;RETURN THIS VALUE FOR J
	JRST	JPOPJ1##	;GIVE GOOD RETURN
;SUBROUTINE TO FIX CORE ALLOCATION TABLES AFTER PAGES HAVE BEEN
; MARKED OUT IN NXMTAB DUE TO PARITY ERRORS OR NXM'S
;CALLING SEQUENCE:
;	MAKE NXMTAB REFLECT CURRENT STATE OF MEMORY, GIVE BACK CORE
;	BELONGING TO ALL SEGMENTS WHICH OVERLAP NXM, AND
;	PUSHJ	P,CPLNXF	;FIX UP RELEVANT TABLES AND VARIABLES
;RETURNS CPOPJ IF NEW VALUE OF CORMAX .LE. OLD VALUE OF CORMAX (SOME
; JOB MAY BE TOO BIG TO SWAP IN), CPOPJ1 IF ALL IS OK.
;MUST HAVE THE MM RESOURCE-CALLER'S RESPONSIBILITY

CPINXF::SE1ENT			;PAGTAB AND MEMTAB ARE IN THE SKYSEG
	PUSHJ	P,SAVE2##	;SAVE WORKING ACS
	SETZB	T1,T2		;INITIALIZE INDEXS INTO PAGTAB AND NXMTAB
	MOVSI	T3,400000	;FIRST BIT TO LOOK AT IN NXMTAB
	LDB	T4,[POINT 14,MEMSIZ##,26]
	MOVSI	P1,NXMBIT	;LOOK FOR NON-EXISTANT PAGES
	HRROI	P2,-PAGSIZ	;DECREASE MAXMAX BY 1 PAGE FOR EACH NON-EXISTANT PAGE SEEN
CPINX1:	TDNN	P1,@[IW MS.MEM,PAGTAB(T1)] ;PAGE ALREADY MARKED AS NON-EXISTANT?
	TDNN	T3,NXMTAB##(T2)	;NO, IS IT NON-EXISTANT NOW?
	JRST	CPINX2		;NO, FORGE AHEAD
	SKIPL	@[IW MS.MEM,PAGTAB(T1)] ;IS THIS NON-EXISTANT PAGE ON THE FREE CORE LIST?
	STOPCD	.,STOP,NPN,	;++NON-EXISTANT PAGE NOT FREE
	ADDM	P2,MAXMAX##	;DECREASE MAXMAX BY 1 PAGE
	ADDM	P2,RMCMAX##	;AND REAL MAXIMUM CORMAX
	HLLM	P1,@[IW MS.MEM,PAGTAB(T1)] ;AND MARK THIS PAGE AS NON-EXISTANT
CPINX2:	ADDI	T1,1		;NEXT PAGE
	ROT	T3,-1		;NEXT BIT POSITION IN NXMTAB
	SKIPG	T3		;CROSSED A WORD BOUNDARY?
	ADDI	T2,1		;YES, BUMP TO NEXT WORD IN NXMTAB
	SOJG	T4,CPINX1	;LOOP OVER ALL PAGES
CPINX3:	MOVE	T1,PAGPTR##	;POINTER TO THE FREE CORE LIST
	JUMPE	T1,CPINX5	;JUMP IF THERE ARE CURRENTLY NO PAGES ON THE FREE LIST
	TDNN	P1,@[IW MS.MEM,PAGTAB(T1)] ;IS THIS PAGE NOW NON-EXISTANT?
	JRST	CPINX5		;NO
	MOVE	T2,@[IW MS.MEM,PAGTAB(T1)] ;YES, LINK FREE CORE LIST AROUND IT
	HRRZM	T2,PAGPTR##	;STORE NEW FIRST PAGE ON FREE CORE LIST
	SOS	CORTAL##	;DECREMENT COUNT OF POTENTIALLY FREE PAGES
	SOS	BIGHOL##	;DECREMENT COUNT OF FREE PAGES
	JRST	CPINX3		;CONTINUE TO LOOK AT PAGES AT THE BEGINNING
				; OF THE FREE CORE LIST
CPINX4:	HRRZ	T1,T2		;CURRENT INDEX INTO PAGTAB
CPINX5:	HRRZ	T2,@[IW MS.MEM,PAGTAB(T1)] ;NEXT PAGE IN PAGTAB
	JUMPE	T2,CPINX6	;JUMP IF THIS IS THE END OF THE FREE CORE LIST
CPNX5A:	TDNN	P1,@[IW MS.MEM,PAGTAB(T2)] ;IS THIS PAGE NOW NON-EXISTANT?
	JRST	CPINX4		;NO
	HRRZ	T2,@[IW MS.MEM,PAGTAB(T2)] ;YES, LINK FREE CORE LIST AROUND IT
	HRRM	T2,@[IW MS.MEM,PAGTAB(T1)] ; ..
	SOS	CORTAL##	;DECREMENT THE COUNT OF POTENTIALLY FREE PAGES
	SOS	BIGHOL##	;AND THE COUNT OF FREE PAGES
	SKIPE	T2
	HRRM	T1,@[IW MS.MEM,PT2TAB(T2)]
	JUMPN	T2,CPNX5A	;LOOP OVER THE ENTIER FREE CORE LIST
CPINX6:	MOVEI	T1,0		;INITIALIZE COUNT OF EXISTANT UNLOCKED PAGES
	MOVE	T2,MEMSIZ##	;PREVIOUS HIGHEST ADDRESS + 1
	SUB	T2,SYSSIZ##	;RANGE OF USERS CORE
	LSH	T2,W2PLSH	;NUMBER OF PAGES FROM TOP OF THE MONITOR
				; TO THE PREVIOUS TOP OF MEMORY
	MOVE	T3,SYSSIZ##	;WHERE TO START LOOKING FOR UNLOCKED EXISTANT PAGES
	LSH	T3,W2PLSH	;PAGE NUMBER TO START AT
CPINX7:	MOVE	P1,@[IW MS.MEM,PAGTAB(T3)] ;PAGE DESCRIPTOR BITS FROM PAGTAB
	TLNE	P1,LKBITS-MONTRB;IS THIS PAGE LOCKED OR NON-EXISTANT?
	JRST	CPINX8		;YES, DON'T CONSIDER IT IN COMPUTING NEW CORMAX
	MOVEI	T4,1(T3)	;HIGHEST EXISTANT PAGE + 1 THAT WAS SEEN
	TLNN	P1,MONTRB	;IS THIS A MONITOR PAGE?
	ADDI	T1,PAGSIZ	;NO, INCREASE NEW CORMAX BY ONE PAGE
CPINX8:	ADDI	T3,1		;NEXT PAGE IN PAGTAB
	SOJG	T2,CPINX7	;LOOP OVER ALL PAGES
	MOVEI	T2,PAGTAB-1(T4)	;BYTE POINTER TO HIGHEST PAGE
	SSX	T2,MS.MEM	;SECTION NUMBER IN LEFT HALF
	MOVEM	T2,CORLST##	;STORE THAT FOR CHKTAL
	LSH	T4,P2WLSH	;HIGHEST EXISTANT ADDRESS + 1
	MOVEM	T4,MEMSIZ##	;STORE THAT AS THE SIZE OF MEMORY
	MOVE	T2,RMCMAX##	;REAL MAXIMUM CORMAX INCLUDING FUNNY SPACE
	CAMLE	T1,T2		;ROOM FOR FUNNY PAGES?
	MOVE	T1,T2		;NO, MAKE ROOM
	CAML	T1,CORMAX##	;NEW CORMAX LESS THAN THE OLD CORMAX?
	AOSA	(P)		;NO, INDICATE ALL JOBS CAN STILL RUN
	MOVEM	T1,CORMAX##	;YES, STORE NEW VALUE OF CORMAX AND GIVE
				; A NON-SKIP RETURN TO INDICATE THAT SOME
				; JOBS MAY BE TOO LARGE TO BE SWAPPED IN
	POPJ	P,		;RETURN
SUBTTL	ERROR REPORTING FOR CHANNEL ERRORS
IFN FTKL10,<
;SUBROUTINE TO STORE CHANNEL DATA ON ALL HARD AND SOFT ERRORS
;CALL:	MOVE	F,DEVICE DATA BLOCK ADR
;	MOVE	U,UNIT DATA BLOCK ADR
;	MOVE	P1,CHANNEL DATA BLOCK ADDRESS(CHN'N'CB)
;	MOVE	T1,ADDRESS OF FIRST CCW IN CCW LIST
;	PUSHJ	P,CHEMPE OR CHENXM (MEMORY PARITY OR NXM)
;	RETURN WILL ALL REGISTERS PRESERVED EXCEPT T1-T4

;SUBROUTINE FOR MEMORY PARITY
CHEMPE::AOS	CHNMPE(P1)	;INCREMENT NO. OF MEM PARITY ERRORS
	PUSHJ	P,SAVE4##	;SAVE P REGISTERS
	SETO	P4,		;INDICATE PARITY ERROR
	JRST	CHNCOM		;JOIN COMMON CODE

;SUBROUTINE FOR NXM
CHENXM::AOS	CHNNXM(P1)	;INCREMENT NO. OF NXMS
	PUSHJ	P,SAVE4##	;SAVE P REGISTERS
	SETZ	P4,		;INDICATE NXM ERROR
CHNCOM:	SETOM	.CPCHE##	;FLAG CHANNEL ERROR CODE IS RUNNING
	HRRM	U,CHNLUE(P1)	;SAVE UNIT DATA BLOCK ADR
	HRRM	F,CHNLDE(P1)	;SAVE DEVICE DATA BLOCK ADR
	PUSH	P,U		;SAVE U
	HRRZ	U,.CPCTN##	;GET CPU'S CTY LINE NUMBER
	MOVE	U,LINTAB##(U)	;GET CTY'S LDB
	PUSHJ	P,CHNCCW	;COLLECT CCW DATA
	SKIPE	P4		;IS THIS A NXM ERROR?
	PUSHJ	P,CHNDAT	;NO--COLLECT DATA WORDS ALSO
	MOVEI	T1,SDELIM	;GET ADRESS OF TEXT
	PUSHJ	P,CONMES##	;PRINT START DELIMITER
	MOVE	T2,.CPLOG##	;GET THIS CPU'S NAME
	PUSHJ	P,PRNAME##	;PRINT IT
	SKIPE	P4		;NXM ERROR?
	SKIPA	T1,[[ASCIZ / channel memory parity error on /]] ;NO--PARITY ERROR
	MOVEI	T1,[ASCIZ / channel non-existent memory error on /] ; YES--NXM
	PUSHJ	P,CONMES##	;PRINT ERROR TYPE
	PUSHJ	P,DATIME##	;APPEND DATE AND TIME
	PUSHJ	P,PCRLF##	;AND A CRLF
	MOVEI	T1,[ASCIZ /Device in use is /] ;GET TEXT
	PUSHJ	P,CONMES##	;PRINT DEVICE PREFIX MESSAGE
	MOVE	T2,DEVMOD(F)	;GET DEVICES CHARACTERISTICS
	HRR	T2,CHNLUE(P1)	;UDB OF DEVICE WHERE ERROR HAPPENED
	TLNE	T2,DVDSK	;IS THIS A DISK?
	SKIPA	T2,(T2)		;YES--GET NAME FROM UDB
	MOVE	T2,DEVNAM(F)	;NO--GET DEVICE NAME FROM DDB
	PUSHJ	P,PRNAME##	;APPEND IT
	MOVEI	T1,[ASCIZ /
Channel type is /] ;GET TEXT
	PUSHJ	P,CONMES##	;PRINT CHANNEL TYPE PREFIX MESSAGE
	MOVE	T2,CHNTYP(P1)	;GET CHANNEL TYPE BITS
	MOVEI	T1,[ASCIZ /DF10-C/] ;ASSUME A DF10-C
	TLNE	T2,CP.DX1	;IS IT A DX10?
	MOVEI	T1,[ASCIZ /DX10/] ;YES--GET ITS TEXT
	TLNE	T2,CP.RH2	;IS IT AN RH20?
	MOVEI	T1,[ASCIZ /RH20/] ;YES--GET ITS TEXT
	TLNE	T2,CP.KLP	;IS IT A KLIPA?
	MOVEI	T1,[ASCIZ /CI20/] ;YES--GET ITS TEXT
	TLNE	T2,CP.KNI	;IS IT A KLNI?
	MOVEI	T1,[ASCIZ /NIA20/] ;YES--GET ITS TEXT
	TLNE	T2,CP.SAX	;IS IT AN SA10?
	MOVEI	T1,[ASCIZ /SA10/] ;YES--GET ITS TEXT
	PUSHJ	P,CONMES##	;APPEND CHANNEL TYPE
	MOVEI	T1,[ASCIZ /
Termination channel program address = /] ;GET TEXT
	PUSHJ	P,CONMES##	;PRINT TERM. CCW ADDRESS MESSAGE
	HLRZ	T1,CHNFCW(P1)	;GET LH TERMINATION CCW
	LSH	T1,-4		;ONLY 14 BITS ARE CCW ADDRESS
	PUSHJ	P,OCTPNT##	;PRINT IT
	MOVEI	T1,[ASCIZ /
Termination data transfer address = /] ;GET TEXT
	PUSHJ	P,CONMES##	;PRINT TERM. DATA ADDRESS MESSAGE
	MOVE	T1,CHNFCW(P1)	;GET RH TERMINATION CCW
	TLZ	T1,777760	;GET JUST DATA ADDRESS (22 BITS)
	PUSHJ	P,PRT22A##	;PRINT IT
	MOVEI	T1,[ASCIZ /
Last three channel commands executed are:
/]
	PUSHJ	P,CONMES##	;PRINT THIS
	MOVE	T1,CHNCW0(P1)	;ARE ALL CCW'S ZERO?
	IOR	T1,CHNCW1(P1)	;...
	IOR	T1,CHNCW2(P1)	;...
	SKIPE	T1		;...
	JRST	CHNCO1		;NO--GO PRINT THEM OUT
	PUSHJ	P,PR3SPC##	;YES--INDENT
	MOVEI	T1,[ASCIZ /** Indeterminate **
/]
	PUSHJ	P,CONMES##	;TELL THEM WE DON'T KNOW
	JRST	CHNCO3		;CONTINUE
CHNCO1:	MOVSI	P2,-3		;FORM AOBJN POINTER
	HRRI	P2,CHNCW2(P1)	; TO SAVED CCW'S
CHNCO2:	PUSHJ	P,PR3SPC##	;INDENT
	MOVE	T1,(P2)		;PICK UP CCW
	PUSHJ	P,HWDPNT##	;PRINT IT
	PUSHJ	P,CRLF##	;PRINT CRLF
	AOBJN	P2,CHNCO2	;LOOP IF MORE
CHNCO3:	MOVEI	T1,EDELIM	;GET ENDING DELIMITER
	PUSHJ	P,CONMES##	;PRINT IT
	POP	P,U		;RESTORE U
	PUSH	P,J		;SAVE AN AC
	MOVE	J,P1		;CUZ XFRSEB NEEDS P1
	SETZM	.CPCHE##	;CLEAR CHANNEL ERROR IN PROGRESS FLAG
	SETZ	T1,		;LET XFR ROUTINE ALLOCATE
	XMOVEI	T2,CPETBL	;POINT TO TRANSFER TABLE
	PUSHJ	P,XFRSEB	;COPY DATA
	  JFCL			;NO CORE
	POP	P,J		;RESTORE J
	POPJ	P,		;RETURN

CPETBL:	SEBTBL	(.ERCPE,CPEEND,<EX.QUE!EX.SYE>)
	MOVE	UDBNAM(U)	;(R00) UNIT NAME
	MOVE	CHNNXM(J)	;(R01) NXM COUNT
	MOVE	CHNMPE(J)	;(R02) MEM PAR ERROR COUNT
	SETZ			;(R03) DEVICE PARITY ERRORS (OBSOLETE)
	MOVE	CHNICW(J)	;(R04) INITIAL CONTROL WORD
	MOVE	CHNFCW(J)	;(R05) FINAL CONTROL WORD
	MOVE	CHNCW2(J)	;(R06) COMMAND WORD -2
	MOVE	CHNCW1(J)	;(R07) COMMAND WORD -1
	MOVE	CHNCW0(J)	;(R10) COMMAND WORD
	MOVE	CHNDW2(J)	;(R11) DATA WORD -2
	MOVE	CHNDW1(J)	;(R12) DATA WORD -1
	MOVE	CHNDW0(J)	;(R13) DATA WORD
	MOVE	CHNTCW(J)	;(R14) EXPECTED TERMINATION CONTROL WORD
CPEEND:!			;END OF TABLE
;ROUTINE TO STORE CCW DATA FOR CHANNEL ERRORS
CHNCCW:	MOVE	T3,CHNTYP(P1)	;PICK UP CHANNEL TYPE BITS
	MOVE	T2,0(T1)	;GET FIRST CCW IN LIST
	MOVEM	T2,CHNICW(P1)	;SAVE IN CDB FOR F.S.
	TLNN	T3,CP.RH2	;IS THIS AN RH20?
	JRST	CHNCC1		;NO--PROCEED
	HRRZ	T2,1(T1)	;YES--GET LAST CCW ADDR + 1
	MOVE	P3,2(T1)	;GET TERMINATION CCW
	MOVEM	P3,CHNFCW(P1)	;SAVE IN CDB FOR F.S.
	JRST	CHNCC4		;CONTINUE
CHNCC1:	TLNN	T3,CP.DX1	;IS THIS A DX10?
	JRST	CHNCC2		;NO--PROCEED
	DPB	P2,[POINT 14,P3,13] ;YES--COMBINE IN TERM. CHANNEL PROGRAM COUNTER
	JRST	CHNCC3		;CONTINUE
CHNCC2:	MOVE	P3,1(T1)	;GET TERMINATION CCW FOR DF10/DF10-C
CHNCC3:	MOVEM	P3,CHNFCW(P1)	;SAVE IN CDB FOR F.S.
	HLRZ	T2,P3		;GET ADDRESS OF LAST CCW
	LSH	T2,-4		;ONLY 14 BITS ARE CCW ADDRESS
CHNCC4:	TLNE	T3,CP.RH2	;IS THIS AN RH20?
	SOS	T2		;BACK UP LAST CCW ADDRESS BY 1
	MOVE	P2,T2		;SAVE REAL FINAL CCW ADDRESS HERE
	CAIL	T2,2		;IS FIRST SOURCE ABOVE LOC 0?
	CAML	T2,MEMSIZ##	;YES, IS LAST SOURCE ADR IN BOUNDS?
	JRST	CHNCC6		;NO--JUNK DATA, DON'T ATTEMPT RETRIEVAL
CHNCC5:	MOVE	P3,CHNCW0(P1)	;PUSH EVERYBODY DOWN ONE
	EXCH	P3,CHNCW1(P1)	;...
	MOVEM	P3,CHNCW2(P1)	;...
	MOVE	P3,(T1)		;GET THIS CCW
	MOVEM	P3,CHNCW0(P1)	; AND SAVE AS LAST CCW
	CAMN	P2,T1		;DOES ITS ADDRESS MATCH THE CHANNEL TERM ADDR?
	JRST	CHNCC7		;YES--WE'RE DONE, STOP CHASING LIST
	TLNE	P3,577777	;IS CCW A DATA TRANSFER?
	AOJA	T1,CHNCC5	;YES--BUMP CCW ADDRESS AND GO AROUND AGAIN
	JUMPE	P3,CHNCC6	;NO--IF IT'S A HALT, WE'VE RUN OUT UNEXPECTEDLY
	TLNE	T3,CP.DX1	;IS THIS A DX10?
	TLNE	P3,200000	;YES--IS THIS A DX10 DEVICE COMMAND CCW?
	SKIPA			;NO--NOT DX10 OR IT'S A DX10 JUMP
	AOJA	T1,CHNCC5	;YES--BUMP CCW ADDRESS AND GO AROUND AGAIN
	MOVE	T1,(T1)		;IT'S A JUMP, GET NEXT CCW ADDRESS
	TLZ	T1,777760	;GET JUST ADDRESS (22-BITS)
	JRST	CHNCC5		; AND GO AROUND AGAIN
CHNCC6:	SETZM	CHNCW2(P1)	;ZERO THE CCW LOCATIONS
	SETZM	CHNCW1(P1)	;...
	SETZM	CHNCW0(P1)	;...
CHNCC7:	MOVE	T2,CHNTCW(P1)	;GET EXPECTED TERMINATION CCW
	MOVEM	T2,CHNETW(P1)	;SAVE FOR F.S.
	POPJ	P,		;RETURN
;HERE TO COLLECT RELEVANT DATA WORDS ON PARITY ERROR
CHNDAT:	MOVE	T4,CHNFCW(P1)	;GET TERMINATION CCW
	TLZ	T4,777760	;GET JUST ADDRESS (22-BITS)
	CAIL	T4,2		;IS LAST DATA ADR ABOVE 0?
	CAML	T4,MEMSIZ##	;YES, IS IT IN BOUNDS?
	JRST	CHNDA2		;NO--JUNK DATA, DON'T ATTEMPT RETRIEVAL
	PUSHJ	P,MAPLOC	;GET EVA SLOT
	SUBI	T4,2		;BACK UP STARTING ADDRESS BY TWO
	MOVEI	P2,CHNDW2(P1)	;PLACE TO STORE DATA WORDS
	HRLI	P2,-3		;MAKE AOBJN PNTR
CHNDA1:	LDB	P3,[POINT 13,T4,26] ;GET PAGE NUMBER
	TLO	P3,(<PM.DCD>B2+PM.WRT+PM.PUB) ;BITS
	DPB	P3,T1		;MAP THIS PAGE
	CLRPGT			;CLEAR PAGING MEMORY
	DPB	T4,[POINT 9,T3,35] ;SET LINE # IN PAGE
	MOVE	P3,(T3)		;FETCH DATA WORD
	MOVEM	P3,(P2)		;STASH IN CDB
	ADDI	T4,1		;ADVANCE TO NEXT LOC
	AOBJN	P2,CHNDA1	;LOOP TILL DONE
	MOVEI	T2,^D50		;WAIT FOR ANY PARITY INTERRUPTS
	SOJG	T2,.		;TO HAPPEN (IF ANY)
	PUSHJ	P,UNMAP		;RESTORE EXEC MAP SLOT
	POPJ	P,		;AND RETURN
CHNDA2:	SETZM	CHNDW0(P1)	;ZERO THE DATA LOCATIONS
	SETZM	CHNDW1(P1)	;...
	SETZM	CHNDW2(P1)	;...
	POPJ	P,		;RETURN
>;END IFN FTKL10

IFN FTKS10,<
CHEMPE::
CHENXM::POPJ	P,
>;END IFN FTKS10
;ROUTINE TO MAKE AVAILABLE A PAGE MAP SLOT IN EVA SPACE
;MAY BE CALLED AT UUO OR INTERRUPT LEVEL
;CALLING SEQUENCE:
;	PUSHJ	P,MAPLOC
;	RETURN HERE
;   C(T1) := BYTE PNTR TO EPMP SLOT
;   C(T3) := VIRTUAL ADDRESS OF START OF MAPPED PAGE
;CALL UNMAP TO RETORE PREVIOUS CONTENTS OF THE MAP SLOT

MAPLOC::MOVE	T3,.CPMAP##	;ADDRESS OF CURRENT CPU'S EXEC MAP
	MOVE	T1,[POINT 36,.ERPIL/PAGSIZ,35]
	ADD	T1,T3
	MOVE	T2,.ERPIL/PAGSIZ(T3) ;CURRENT CONTENTS OF THE MAP SLOT
	EXCH	T2,(P)		;SAVE CURRENT CONTENTS OF THE MAP SLOT
	MOVEI	T3,.ERPIL	;VIRTUAL ADDRESS OF THE PAGE TO BE RETURNED
	PJRST	(T2)		;AND RETURN

;ROUTINE TO RESTORE THE CONTENTS OF A MAP SLOT AFTER HAVING CALLED MAPLOC
;CALLING SEQUENCE:
;	PUSHJ	P,UNMAP
;	RETURNS HERE
;PRESERVES ALL ACS

UNMAP::	EXCH	T1,-1(P)	;GET PREVIOUS CONTENTS OF THE MAP
	PUSH	P,T2		;SAVE A WORKING AC
	MOVE	T2,.CPMAP##	;ADDRESS OF THIS CPU'S EXEC MAP
	MOVEM	T1,.ERPIL/PAGSIZ(T2) ;RESTORE MAP SLOT CONTENTS
	POP	P,T2
	CLRPT	.ERPIL		;MAKE OLD MAPPING VISABLE AGAIN
	POP	P,T1		;RETURN ADDRESS
	EXCH	T1,(P)		;RESTORE T1, STORE RETURN ADDRESS ON STACK
	POPJ	P,		;AND RETURN
	SUBTTL	SYSTEM ERROR BLOCK SUPPORT


;ROUTINE TO ALLOCATE A SYSTEM ERROR BLOCK.
;CALL:
;	T1/ LENGTH OF DATA SEGMENT (NOT INCLUDING HEADER)
;	PUSHJ	P,ALCSEB
;RETURN:
;	CPOPJ IF CAN'T ALLOCATE BLOCK
;	CPOPJ1 IF BLOCK ALLOCATED WITH:
;	T1/ ADDRESS OF ERROR BLOCK
;CLOBBERS T2-T4

	$CSENT	(ALCSEB::)
	SKIPE	DINITF##	;OUT OF ONCE CODE YET?
	POPJ	P,		;NO, TAKE IMMEDIATE ERROR RETURN
	PUSH	P,T1		;SAVE THE LENGTH
	MOVEI	T2,.EBHDR(T1)	;LENGTH INCLUDING HEADER TO T2
	PUSHJ	P,GETWDS##	;GET SOME SECTION 0 SPACE
	  JRST	[AOS	ERRLAP## ;COUNT THIS AS A DAEMON OVERRUN
		 JRST	TPOPJ##] ;CLEAN STACK AND RETURN
	POP	P,T2		;GET LENGTH BACK
	HRRZM	T2,.EBTYP(T1)	;STORE IN TYPE WORD
	MOVEI	T2,.EBHDR-.EBTYP ;LENGTH OF HEADER
	DPB	T2,[POINT 3,.EBTYP(T1),26] ;STORE HEADER LENGTH
	MOVE	T2,DATE##	;GET NOW IN UNIVERSAL FORMAT
	MOVEM	T2,.EBDTM(T1)	;STORE
	MOVE	T2,SYSUPT##	;GET SYSTEM UPTIME
	PUSHJ	P,SEBTIM	;CONVERT TO A UDT-STYLE INTERVAL
	MOVEM	T2,.EBUPT(T1)	;STORE
	MOVE	T2,.CPASN##	;GET APR SERIAL NUMBER OF THIS CPU
	MOVEM	T2,.EBASN(T1)	;STORE
	JRST	CPOPJ1##	;SKIP RETURN
;ROUTINE TO CALL TO DELETE EXPIRED SYSTEM ERROR BLOCKS
;CALLED FROM MINUTE IN CLOCK1

SEBMIN::PUSHJ	P,SAVE1##	;SUPERSTITION
	MOVNI	T2,SEBAGE##	;GET MINUS NUMBER OF MINUTES OF SEB LIFETIME
	JUMPE	T2,CPOPJ##	;THE FOOL WANTS THEM TO CLOG CORE FOREVER?!?
	IMUL	T2,TICMIN##	;CONVERT FROM MINUTES TO JIFFIES
	ADD	T2,SYSUPT##	;GET SYSTEM UPTIME N MINUTES AGO
	JUMPLE	T2,CPOPJ##	;WE HAVEN'T BEEN UP THAT LONG--GO AWAY
	PUSHJ	P,SEBTIM	;CONVERT TO A UDT-STYLE VALUE FOR COMPARISONS
	MOVE	P1,T2		;KEEP THE EXPIRATION TIME SAFE
SEBMI1:	CONO	PI,PI.OFF	;DON'T ALLOW RACES
IFN FTMP,<
	SKIPGE	SEQLOK		;IF INTERLOCK ISN'T TOO BUSY,
	AOSE	SEQLOK		;TRY TO GET IT
	JRST	.-2		;WAIT FOR IT
>
	SKIPE	T2,SEQTOP	;GET THE HEAD OF THE QUEUE
	CAMG	P1,.EBUPT(T2)	;IS IT FROM THE ANCIENT PAST?
	JRST	SEBMI2		;NO--WE'RE DONE
	HRRZ	T1,.EBLNK(T2)	;YES--GET ITS FORWARD POINTER
	MOVEI	T3,SEQTOP	;PREPARE TO RESET BOTTOM POINTER JUST IN CASE
	SKIPN	T1		;IF EMPTYING THE QUEUE,
	MOVEM	T3,SEQBOT	;FIX THE TAIL POINTER
	MOVEM	T1,SEQTOP	;ADVANCE THE LIST
IFN FTMP,<SETOM SEQLOK>		;RELEASE THE INTERLOCK
	CONO	PI,PI.ON	;INTERRUPTS ARE OK AGAIN
	LDB	T1,[POINT 9,.EBTYP(T2),35] ;GET LENGTH OF ERROR BLOCK BODY
	ADDI	T1,.EBHDR	;INCLUDE HEADER AND LINK WORD
	PUSHJ	P,GIVWDS##	;RETURN THE BLOCK TO FREE CORE
	AOS	ERRLAP##	;COUNT THIS AS A DAEMON OVERRUN
	JRST	SEBMI1		;LOOP UNTIL WE FIND NO MORE OVERRIPE PACKETS
SEBMI2:
IFN FTMP,<SETOM SEQLOK>		;RELEASE THE INTERLOCK
	CONO	PI,PI.ON	;INTERRUPTS ARE OK AGAIN
	POPJ	P,		;BACK TO CLOCK1
;SUBROUTINE TO CONVERT AN UPTIME IN JIFFIES TO A UDT-STYLE UPTIME NUMBER
;CALL:
;	MOVEI	T2,UPTIME-IN-TICKS
;	PUSHJ	P,SEBTIM
;RETURN:
;	CPOPJ ALWAYS
;CLOBBERS T2-T4
;PRESERVES T1

SEBTIM::SETZ	T3,		;CLEAR FOR ASHC
	ASHC	T2,-^D17	;JIFFIES*2**18 IN T3
	MOVE	T4,TICSEC##	;TICKS PER SECOND
	IMULI	T4,^D24*^D3600
	DIV	T2,T4		;DAYS IN LH, FRACTION IN RH
	POPJ	P,		;GIVE IT BACK
;ROUTINE TO COPY DATA INTO A SYSTEM ERROR BLOCK
;CALL:	MOVE	T1, SEB ADDRESS OR ZERO
;	MOVE	T2, ADDRESS OF TRANSFER TABLE
;	PUSHJ	P,XFRSEB
;	<NON-SKIP>		;NO CORE (IF ALLOCATING) OR DISABLED BY DEPDEL
;	<SKIP>			;ERROR RECORD FILLED
;PRESERVES T2-T4 ON SUCCESS UNLESS QUESEB IS CALLED

	$CSENT	(XFRSEB::)
	ADJSP	P,4		;MAKE ROOM TO SAVE ACS
	DMOVEM	P1,-3(P)	;SAVE SOME NOW
	MOVEI	P2,EX.DEL	;BIT TO TEST
	TDNN	P2,.EXFLG(T2)	;WANT TO CHECK FOR DIABLED LOGGING?
	JRST	XFRSE1		;NO
	MOVEI	P2,DEPDEL	;BIT TO TEST
	TDNN	P2,DEVSTA(F)	;ERROR LOGGING DISABLED?
	JRST	XFRSE1		;NO
	AOS	DELCNT##	;COUNT IT
	DMOVE	P1,-3(P)	;RESTORE ACS
	ADJSP	P,-4		;TRIM STACK AGAIN
	SKIPN	T2,T1		;COPY SEB ADDR
	POPJ	P,		;RETURN IF NO BLOCK ALLOCATED YET
	LDB	T1,[POINT 9,.EBTYP(T2),35] ;GET LENGTH OF ERROR BLOCK BODY
	ADDI	T1,.EBHDR	;INCLUDE HEADER AND LINK WORD
	PJRST	GIVWDS##	;RETURN CORE

XFRSE1:	MOVEI	P2,EX.SYE	;BIT TO TEST
	TDNE	P2,.EXFLG(T2)	;WANT TO COUNT UP A SYSTEM ERROR?
	AOS	SYSERR##	;YES
	MOVE	P2,T2		;COPY TRANSFER TABLE ADDRESS
	JUMPN	T1,XFRSE2	;JUMP IF ALREADY HAVE SEB
	HLRE	T1,.EXFLG(P2)	;GET -VE LENGTH
	MOVMS	T1		;MAKE POSITIVE
	DMOVEM	T3,-1(P)	;SAVE SOME MORE CALLER ACS
	PUSHJ	P,ALCSEB	;ALLOCATE SYSTEM ERROR BLOCK
	  TRNA			;NO CORE--FIX STACK
	JRST	XFRSE2		;GOT IT--GO USE IT
	DMOVE	P1,-3(P)	;RESTORE ACS
	DMOVE	T3,-1(P)	; ...
	ADJSP	P,-4		;TRIM STACK
	POPJ	P,		;PROPAGATE ERROR RETURN

XFRSE2:	MOVE	P1,T1		;COPY SEB ADDRESS
	DMOVE	T3,-1(P)	;RESTORE SOME CALLER ACS
	DMOVEM	P3,-1(P)	;SAVE OTHER ACS THAT WE'LL USE
	XMOVEI	P3,.EBHDR(P1)	;POINT TO START OF DATA STORAGE
	HLL	P3,.EXFLG(P2)	;MAKE AN AOBJN POINTER
	MOVE	T1,.EXREC(P2)	;GET RECORD TYPE CODE
	DPB	T1,[POINT 9,.EBTYP(P1),8] ;STORE IN HEADER
	MOVE	T1,.EXFLG(P2)	;GET FLAGS FROM TABLE HEADER
	MOVSI	T2,EH.CRS	;GET THE "FROM A CRASH" BIT
	TRNE	T1,EX.CRS	;THIS ENTRY FROM THE CRASH READER?
	IORM	T2,.EBTYP(P1)	;YES, TELL DAEMON
	XMOVEI	P4,.EXHDR(P2)	;POINT BEYOND TABLE HEADER
	EXCH	P1,-3(P)	;SAVE POINTER AND RESTORE AC
	EXCH	P2,-2(P)	;SAME WITH P2

XFRSE3:	MOVE	T2,(P4)		;GET PARTIAL INSTRUCTION
	TLO	T2,(Z T1,)	;INCLUDE AC
	EXCH	P3,-1(P)	;SWAP ACS AGAIN
	EXCH	P4,(P)		; ...
	XCT	T2		;FETCH DATA
	EXCH	P3,-1(P)	;SWAP ACS AGAIN
	EXCH	P4,(P)		; ...
	MOVEM	T1,(P3)		;STORE WORD IN ERROR RECORD
	AOS	P4		;ADVANCE POINTER TO NEXT STORAGE
	AOBJN	P3,XFRSE3	;LOOP FOR ALL WORDS
	DMOVE	P3,-1(P)	;RESTORE CALLER ACS
	MOVE	T2,-2(P)	;AND XFER TABLE ADDRESS
	ADJSP	P,-3		;TRIM ALL BUT SEB ADDRESS
	MOVEI	T1,EX.QUE	;BIT TO TEST
	TDNN	T1,.EXFLG(T2)	;WANT TO QUEUE THIS BLOCK UP?
	JRST	TPOPJ1##	;NO
	POP	P,T1		;YES, RESTORE SEB ADDRESS
	PUSHJ	P,QUESEB	;SEND RECORD TO DAEMON
	SETZB	T1,T2		;ADDRESSES NO LONGER VALID
	JRST	CPOPJ1##	;RETURN
;ROUTINE TO BUILD A STANDARD SOFTWARE EVENT RECORD CONSISTING
;OF A SINGLE EVENT-SPECIFIC DATA WORD
;CALL:	MOVE	T1, EVENT CODE
;	MOVE	T2, DATA WORD
;	PUSHJ	P,SWESEB

	$CSENT	(SWESEB::)
	PUSHJ	P,SAVT##	;SAVE SOME ACS
	PUSH	P,T1		;SAVE EVENT CODE
	PUSH	P,T2		;SAVE DATA WORD
	SETZ	T1,		;CAUSE SEB ALLOCATION TO HAPPEN
	XMOVEI	T2,SWETBL	;POINT TO TRANSFER TABLE
	PUSHJ	P,XFRSEB	;LOAD UP THE RECORD
	  JRST	TTPOPJ##	;NO CORE
	POP	P,.EBHDR+6(T1)	;STORE EVENT-SPECIFIC DATA WORD
	POP	P,.EBHDR+0(T1)	;STORE SOFTWARE EVENT CODE
	PUSH	P,F		;SAVE F
	PUSH	P,U		;SAVE U
	PUSH	P,S		;SAVE S (NOTHING IS SAFE FROM SCNSER)
	PUSH	P,T1		;SAVE T1
	PUSHJ	P,TTYSRC##	;FIND TTY DDB
	  CAIA			;MUST BE DETACHED
	PUSHJ	P,GTNTS0##	;GET NODE,,LINE
	  SETZ	T1,		;TTY NOT CONNTECTED
	SETZ	T2,		;CLEAR TEMP
	DPB	T1,[POINT 12,T2,23] ;PUT LINE IN A STRANGE PLACE
	HLRZS	T1		;GET NODE
	DPB	T1,[POINT 12,T2,11] ;PUT IN AN EQUALLY STRANGE PLACE
	MOVE	T1,T2		;COPY DATA
	EXCH	T1,(P)		;GET SEB ADDR BACK
	POP	P,.EBHDR+4(T1)	;STORE POSSIBLE NODE,,LINE
	POP	P,S		;RESTORE S
	POP	P,U		;RESTORE U
	POP	P,F		;RESTORE F
	PJRST	QUESEB		;QUEUE UP BLOCK AND RETURN


;COMMON TRANSFER TABLE FOR SOFTWARE EVENTS
;THIS TABLE DEFINES A RECORD WHERE THE STANDARD ONE WORD IS
;RESERVED FOR EVENT-SPECIFIC DATA.  IF THIS IS INSUFFICIENT,
;THE CALLER MUST ADJUST THE POINTER IN R05 AND COMPUTE THE
;ADDITIONAL WORDS NECESSARY TO ALLOCATE A RECORD.

SWETBL::SEBTBL	(.ERSWE,SWEEND,)
	SETZ			;(R00) SOFTWARE EVENT CODE
	MOVE	J		;(R01) JOB NUMBER
	MOVE	JBTPPN##(J)	;(R02) PPN
	MOVE	JBTNAM##(J)	;(R03) PROGRAM NAME
	SETZ			;(R04) NODE,,LINE
	HRROI	6		;(R05) POINTER TO FUNCTION SPECIFIC DATA
	SETZ			;(R06) RESERVE WORD FOR DATA
SWEEND:!			;END OF TABLE
;ROUTINE TO QUEUE A SYSTEM ERROR BLOCK TO DAEMON.
;CALL:
;	T1/ ADDRESS OF ERROR BLOCK
;	PUSHJ	P,QUESEB
;RETURN:
;	CPOPJ ALWAYS

	$CSENT	(QUESEB::)
	CONI	PI,T2		;READ PI STATUS
	CONO	PI,PI.OFF	;TURN OFF INTERRUPTS
IFN FTMP,<
	SKIPGE	SEQLOK		;GIVE OTHER CPUS A CHANCE
	AOSE	SEQLOK		;GET THE INTERLOCK
	JRST	.-2		;WAIT
>; END IFN FTMP
	SETZM	.EBLNK(T1)	;MAKE SURE LINK TO NEXT BLOCK IS ZERO
	MOVEM	T1,@SEQBOT	;APPEND THIS ENTRY TO BOTTOM OF QUEUE
	MOVEM	T1,SEQBOT	;MAKE THIS THE NEW LAST ENTRY
IFN FTMP,<
	SETOM	SEQLOK		;RELEASE THE INTERLOCK
>; END IFN FTMP
	TRNE	T2,PI.ON	;WAS PI SYSTEM ON BEFORE?
	CONO	PI,PI.ON	;YES, TURN IT BACK ON
	PUSHJ	P,STDAEM##	;PROD THE DEVIL INTO ACTION
	  JFCL			;DON'T CARE IF HE'S NOT THERE
	POPJ	P,		;RETURN

	$LOW
SEQTOP::0			;POINTER TO FIRST ENTRY IN QUEUE
SEQBOT:	SEQTOP			;POINTER TO LAST ENTRY IN QUEUE
IFN FTMP,<
SEQLOK:	-1			;INTERLOCK
>; END IFN FTMP
	$HIGH
;SEBLK. UUO USED BY DAEMON TO RETURN THE NEXT ERROR BLOCK FROM THE
;SYSTEM ERROR BLOCK QUEUE.  THE BLOCK IS COPIED INTO THE CALLER'S
;ARGUMENT BLOCK, AND TRUNCATED IF NECESSARY.
;CALL:
;	MOVE	AC,[LENGTH,,ADDRESS]
;	SEBLK.	AC,
;	  ERROR RETURN, AC/ ZERO
;	NORMAL RETURN, AC/ LENGTH OF BLOCK

USEBLK::PUSHJ	P,PRVJ##	;IS THIS GUY PRIVILEGED?
	  SKIPA			;YES
	JRST	RTZER##		;NO, RETURN A ZERO
	HLRE	T2,T1		;GET LENGTH OF CALLER'S ARGUMENT BLOCK
	CAIG	T2,.EBHDR	;ROOM FOR AT LEAST A ONE WORD ENTRY?
	JRST	UADERR		;NO, ZAP THE FOOL
	CONO	PI,PI.OFF	;PREVENT RACES
IFN FTMP,<
	SKIPGE	SEQLOK		;GIVE OTHER CPUS A CHANCE
	AOSE	SEQLOK		;GET THE INTERLOCK
	JRST	.-2		;WAIT
>; END IFN FTMP
	SKIPN	T2,SEQTOP	;IS THERE A FIRST ENTRY?
	JRST	SEBLK2		;NO
	MOVE	T2,.EBLNK(T2)	;GET LINK TO NEXT BLOCK
	JUMPN	T2,SEBLK1	;JUMP IF MORE ENTRIES IN QUEUE
	MOVEI	T3,SEQTOP	;QUEUE NOW EMPTY, RESET BOTTOM POINTER
	MOVEM	T3,SEQBOT	;...
SEBLK1:	EXCH	T2,SEQTOP	;SAVE NEW FIRST BLOCK ADDRESS, GET OLD
SEBLK2:
IFN FTMP,<
	SETOM	SEQLOK		;RELEASE INTERLOCK
>; END IFN FTMP
	CONO	PI,PI.ON	;ALLOW INTERRUPTS AGAIN
	JUMPE	T2,ECOD1##	;RETURN AN ERROR IF NO BLOCKS QUEUED
	HLRE	T4,T1		;GET LENGTH OF CALLER'S ARGUMENT BLOCK AGAIN
	LDB	T3,[POINT 9,.EBTYP(T2),35] ;GET LENGTH OF ERROR BLOCK BODY
	ADDI	T3,.EBHDR-.EBTYP ;INCLUDE HEADER LENGTH
	PUSH	P,T3		;SAVE LENGTH FOR RETURN TO USER
	CAMGE	T3,T4		;IF ERROR BLOCK LONGER THAN USER'S BLOCK,
	MOVE	T4,T3		; ONLY COPY AS MUCH AS THEY CAN HANDLE
	HRRZS	T1		;KEEP JUST CALLER'S ADDRESS
	ADD	T4,T1		;COMPUTE END ADDRESS
	HRLI	T1,.EBTYP(T2)	;SOURCE ADDRESS OF ERROR BLOCK HEADER
	EXCTXU	<BLT T1,-1(T4)>	;COPY THE ERROR BLOCK TO THE USER
	  ERJMP	SEBLK3		;ADDRESS CHECK, NAUGHTY USER
	LDB	T1,[POINT 9,.EBTYP(T2),35] ;GET LENGTH OF ERROR BLOCK BODY
	ADDI	T1,.EBHDR	;INCLUDE HEADER AND LINK WORD
	PUSHJ	P,GIVWDS##	;RETURN THE BLOCK TO FREE CORE
	POP	P,T1		;RESTORE THE LENGTH OF THE BLOCK
	PJRST	STOTC1##	;STORE IN USER'S AC AND SKIP RETURN

SEBLK3:	LDB	T1,[POINT 9,.EBTYP(T2),35] ;GET LENGTH OF ERROR BLOCK BODY
	ADDI	T1,.EBHDR	;INCLUDE HEADER AND LINK WORD
	PUSHJ	P,GIVWDS##	;RETURN THE BLOCK TO FREE CORE
	JRST	UADERR		;ZAP THE NAUGHTY USER
SUBTTL	STOPCODE PROCESSING

;ROUTINE TO RECOVER/RELOAD AFTER AN INTERNAL
; SYSTEM ERROR.  CALLED ONLY BY STOPCD MACRO
; (SEE S.MAC) WITH:
;	PUSHJ	P,DIE
;
;SEE ALSO ROUTINE PERISH

	$CSUB			;MUST BE ADDRESSABLE BY ALL CODE SEGMENTS

DIE::	AOSE	.CPDWD##	;INTERLOCK STOPCD CODE
	STOPCD	.,HALT,REH,	;++RECURSION IN ERROR HANDLER
	POP	P,.CPSPC##+1	;GET PC OF STOPCD
	XSFM	.CPSPC##	; AND FLAGS
	JRST	@[0,,DIE0]	;JOIN COMMON CODE

;ANOTHER ROUTINE TO RECOVER/RELOAD AFTER AN INTERNAL SYSTEM ERROR.
;  CALLED ONLY BY TRAPCD MACRO (SEE S.MAC) WITH:
;
;	XPCW	CROAK		;(CROAK IS PSUEDONYM FOR .CPSPC)
;
;SEE ALSO ROUTINE DIE

	$HIGH			;REACHED ONLY IN SECTION 0

PERISH::AOSE	.CPDWD##	;INTERLOCK STOPCD CODE
	STOPCD	.,HALT,RID,	;++RECURSION IN DIE
;	JRST	@[0,,DIE0]	;JOIN COMMON CODE [ALREADY IN SECTION 0]

;RUNNING IN SECTION 0

DIE0:	SKIPE	.UONCE##	;IS THIS USRONC?
	JRST	DIE00		;YES--SKIP THE ILLEGAL UUOS
	CONI	PI,.CPCPI##	;SAVE STATE OF MACHINE
	CONO	PI,PI.TFP+177	; ..
	JSR	.CPSVA##	;SAVE ALL AC SETS
	JRST	DIE001		;SKIP USER-MODE STUFF
DIE00:	MOVEM	17,CRSHAC##+17	;SAVE AN AC
	MOVEI	17,CRSHAC##	;POINT TO SAVE ACS BLOCK
	MOVEM	17,.CPACA##	;NOTE WHERE WE'RE SAVING THE ACS
	BLT	17,CRSHAC##+16	;SAVE THE REST
DIE001:	MOVSI	T1,^-MXSECN	;MASK OF EVERYTHING BUT PC COUNTER
	ANDCAB	T1,.CPSPC##+1	;CLEAR SPURIOUS BITS
IFN FTXMON,<
	TLNE	T1,MXSECN	;STOPCODE IN NON-ZERO SECTION?
	XJRST	[MCSEC1+DIE01]	;YES, ENTER SECTION 1 FOR STOPCODE PROCESSING
>; END IFN FTXMON
;RUNNING IN SECTION 1

DIE01:	SKIPE	.UONCE##	;IF USER-MODE,
	JRST	DIE01A		;CAN'T REFERENCE .UPMP
	HRLZ	T1,.USMUO	;GET MUUO OPCODE AND AC
	IOR	T1,.USMUE	;INCLUDE EFFECTIVE ADDRESS
	MOVEM	T1,.CPTRP##	;STORE
DIE01A:	SKIPN	T1,.CPSPC##+1	;GET PC OF STOPCD
	MOVEI	T1,DIEBPC+1	;POINT AT A GENERIC STOPCODE
	MOVEM	T1,.CPSUP##	;STORE IN CDB
	MOVE	M,-1(T1)	;GET XCT INSTRUCTION
	TLC	M,(XCT)		;CLEAR THE XCT OUT OF WORD
	TLNE	M,-1		;MAKE SURE NOTHING IS LEFT
	MOVEI	M,DIEBAD	;OOPS. SOMETHING BAD, POINT TO GENERIC RELOAD.
IFN FTXMON,<
	HLL	M,.CPSPC##+1	;GET SECTION OF STOPCODE
>; END IFN FTXMON
	MOVE	P,.CPEPD##	;SET UP ERROR STACK
	LDB	T1,[POINT 4,2(M),17]	;GET STOPCODE TYPE
	CAIL	T1,S$STOP	;IS IT IN RANGE?
	CAILE	T1,STPMAX	;BOTH WAYS?
	MOVEI	T1,S$STOP	;BAD--DON'T MAKE THINGS WORSE
	MOVEM	T1,.CPSTY##	;SAVE AS LAST STOPCODE TYPE
	SKIPE	.UONCE##	;IS THIS USER-MODE?
	JRST	DIE010		;YES--SKIP BAD THINGS
	MOVE	T1,PRCTAB(T1)	;GET CONTROL BITS
	TLNN	T1,(S%NCSB)	;SUPPRESS CPU/DEVICE STATUS BLOCK STUFF?
	S0PSHJ	RCDSTB##	;READ CPU AND DEVICE STATUS BLOCKS
IFN FTKL10,<
	PUSHJ	P,CSDMP##	;MAKE SURE IT'S ALL IN CORE
	PUSHJ	P,SKPMRN##	;SKIP IF MASTER -11 IS RUNNING
	STOPCD	.,HALT,MNR,	;++MASTER -11 NOT RUNNING
>
DIE010:	PUSHJ	P,DIE1		;CALL MAIN PROCESSING ROUTINE AS A SUBROUTINE
	SKIPE	.UONCE##	;USER-MODE?
	JRST	DIE011		;YES--SKIP JUNK
	PUSHJ	P,DIELOG	;MAKE AN ERROR LOG ENTRY
	MOVEI	T1,177		;ALL PI BITS
	AND	T1,.CPCPI##	;TURN ON ONLY
	IORI	T1,PI.TNP	;ONES WHICH WERE ON
	MOVEM	T1,.CPCPI##	;SAVE FOR CONO
DIE011:	HRLZ	17,.CPACA##	;WHERE TO RESTORE THE AC'S FROM
	BLT	17,17		;RESTORE THEM ALL
	.CREF	DF.SBD		;(FLAG BIT TESTED)
	SKIPL	DEBUGF##	;WANT DDT?
	JRST	DIE02		;DEFINITELY NOT, DON'T WASTE TIME
;	PUSH	P,T1		;SAVE T1 (CAN'T, SINCE STACK MAY NOW BE BAD)
	MOVE	T1,.CPSTY##	;GET STOPCODE TYPE
	SKIPGE	PRCTAB(T1)	;BUGINF IN DRAG?
	.CREF	S%FAST		; (NOTE BIT WE TESTED)
	JRST	[MOVE	T1,.CPACA##	;WHERE THE AC'S WERE STORED
		 MOVE	T1,T1(T1)	;RESTORE T1
		 JRST	DIE02]	;FINISH UP
	MOVE	T1,.CPACA##	;WHERE THE AC'S WERE STORED
	MOVE	T1,T1(T1)	;RESTORE T1
	XCT	.CPDDT##	;CALL ON DDT
DIE02:	SETOM	.CPDWD##	;ALLOW STOPCD'S
	DIENLK			;NO LONGER THE OWNER OF THE INTERLOCK
;IF STACK IS TRASHED, THIS IS WHERE WE GENERATE ANOTHER STOPCODE.
;SINCE WE HAVE RETURNED THE INTERLOCKS, THIS IS REASONABLY SAFE.

DIECON::
GOBACK::PUSH	P,.CPSPC##	;SAVE RETURN FLAGS
	PUSH	P,.CPSPC##+1	;SAVE RETURN PC
	SETZM	.CPSPC##+1	;LEAVE RECOGNIZABLE TRASH
	SKIPN	.UONCE##	;IF EXEC MODE,
	CONO	PI,@.CPCPI##	;TURN ON PI SYSTEM
	SETZM	SYSSNP##	;THIS COULD BE WHY WE GOT HERE.
	ADJSP	P,-2		;LEAVE STACK THE WAY IT WAS
	SKIPE	2(P)		;MAKE SURE WE HAVE A REAL RETURN ADDRESS
	XJRSTF	1(P)		;RETURN TO CALLER

DIEBPC:	STOPCD	.,STOP,DIEBAD,	;++ BAD PC IN DIE
;RUNNING IN SECTION 1 IF STOPCODE WAS IN A NON-ZERO SECTION

DIE1:	SKIPE	.UONCE##	;IF USER-MODE,
	JRST	DIE2		;DON'T TRY TO TALK TO THE -11
	MOVE	T1,.CPSTY##	;GET STOPCODE TYPE
	SKIPL	PRCTAB(T1)	;DO WE WANT SECONDARY PROTOCOL?
	.CREF	S%FAST		;NOTE BIT WE TESTED
	PUSHJ	P,SVPPC##	;YES, SAVE PROTOCOL & FORCE SECONDARY

DIE2:
IFN FTMP,<
	;DIELOK			;CAN'T USE MACRO AS WE TEST CRSHWD BELOW
	AOSE	.CPDIE##	;ALREADY OWN THE INTERLOCK?
	JRST	DIE2B		;YES
	SKIPE	.UONCE##	;IF USER-MODE,
	JRST	DIE2B		;WE OWN IT NOW
DIE2A:	SKIPE	CRSHWD##	;RELOADING?
	S0JRST	REBOOT##	;YES
	SKIPGE	INTDIE##	;IS INTERLOCK AVAILABLE?
	AOSE	INTDIE##	;YES, TRY TO GET IT
	JRST	DIE2A		;COULDN'T, LOOP TO TRY AGAIN
	APRID	INODIE##	;MAKE ME THE OWNER OF THE INTERLOCK
DIE2B:	SETZM	DIEFLG##	;CLEAR TYPE FLAG (JUST IN CASE)
	MOVE	T1,.CPSTY##	;GET STOPCODE TYPE AGAIN
	SKIPL	PRCTAB(T1)	;IS IT REAL?
	.CREF	S%FAST		;(FLAG BIT TESTED)
	SOSA	DIEFLG##	;YES, GO NEGATIVE
	AOS	DIEFLG##	;NO, GO POSITIVE
> ;END IFN FTMP

;THE FOLLOWING CODE IS EXPLICITLY TO MAKE IT EASIER TO AUTOMATICALLY MAP IN
;A CRASH. THE USUAL SEQUENCE WOULD BE TO USE A DDT FILE WHICH (FOR KL PAGING)
;WOULD SAY:
;	DIECDB[$Q+.CPEPT-.CPCDB[$Q'1000$U
;	SPTTAB$6U
;	.CPACA[$Q$5U

	MOVE	T1,.CPSLF##	;GET PHYSICAL POINTER TO THE CDB
	MOVEM	T1,DIECDB##	;SAVE WHERE FILDDT WILL BE ABLE TO FIND IT

;THE FOLLOWING IS TO ALLOW FILDDT TO SETUP MAPPING FOR A CRASHED CPU
;AUTOMATICALLY.  THIS REQUIRES A CORRESPONDING EDIT TO FILDDT, BUT WHY NOT

	PUSH	P,.JBEDV##	;SAVE OLD VALUE FOR SYMBOL MAPPING IN EDDT
	ADDI	T1,.CPEDV##-.CPCDB## ;RELOCATE TO OUR EDV
	MOVEM	T1,.JBEDV##	;SAVE FOR FILDDT
	MOVE	T1,1(M)		;GET NAME OF STOPCODE
	MOVEM	T1,.CPSNM##	;SAVE NAME IN CDB
	MOVEM	T1,%SYSCD##	;AND IN SYSTEM WIDE LOCATION
	MOVE	T1,.CPSUP##	;GET STOPCODE PC
	MOVEM	T1,%SYSPC##	;STORE IN TRADITIONAL WORD
	MOVE	T1,.CPSTY##	;GET STOPCODE TYPE AGAIN
	MOVEM	T1,%SYSTY##	;STORE IN SYSTEM WIDE LOCATION
	MOVE	T1,DATE##	;GET UDT
	MOVEM	T1,.CPSDT##	;SAVE AS LAST STOPCD DATE-TIME
	MOVEM	T1,%SYSDT##	;BOTH PER-CPU AND SYSTEM-WIDE
	MOVE	T1,.CPCPN##	;GET OUR CPU NUMBER
	MOVEM	T1,%SYSCP##	;STORE AS LAST CPU THAT DID A STOPCD
	HRRZ	T1,2(M)		;GET CONTINUATION ADDRESS
	SKIPE	T1		;IS THERE ANY?
	HRRM	T1,.CPSPC##+1	;YES, SAVE AS SECTION LOCAL CONTINUATION
	PUSH	P,.CPTOA##	;SAVE ADDRESS OF TYPEOUT ROUTINE
	MOVE	T1,.CPSTY##	;RECOVER STOPCODE TYPE
	SKIPN	DINITF##	;UNLESS IN ONCE-ONLY,
	SKIPL	PRCTAB(T1)	;LEAVE IT ALONE FOR EVENTS
	.CREF	S%FAST		;(NOTE TESTED BIT)
	SKIPA	T2,[CTYWAT##]	;NOPE, REPLACE IT WITH ONE THAT DOESN'T USE PI'S
	MOVEI	T2,DIETYO	;YEP, USE OUR OWN HANDY TYPEOUT ROUTINE
	SKIPE	.UONCE##	;UNLESS USER-MODE,
	MOVEI	T2,XTYO##	;THEN USE OUTCHR'S
	MOVEM	T2,.CPTOA##	;MODIFY SCNSER
	MOVE	T1,PRCTAB(T1)	;GET ITS CONTROL BITS
	TLNN	T1,(S%EVNT)	;IS IT AN EVENT?
	JRST	DIE3		;NO, IT'S A REAL STOPCODE
	PUSHJ	P,INLMES##	;YES, TYPE HEADER
	ASCIZ	/
%% Event /
	MOVE	T2,.CPSNM##	;GET STOPCODE NAME
	PUSHJ	P,PRNAME##	;PRINT IT OUT
	JRST	DIE4		;RE-JOIN COMMON CODE
DIE3:	MOVEI	T2,^D10		;TYPE SOME BELLS
	PUSHJ	P,BELLEN	; ...
	PUSHJ	P,INLMES##	;PRINT MESSAGE
	ASCIZ	/
?Stopcode /
	MOVE	T2,.CPSNM##	;GET STOPCODE NAME
	PUSHJ	P,PRNAME##	;PRINT IT OUT
	PUSHJ	P,INLMES##	;SAY WHICH KIND
	ASCIZ	/, type=/
	MOVE	T1,.CPSTY##	;GET STOPCODE TYPE AGAIN
	MOVE	T2,STPTYP(T1)	;GET STOPCODE TYPE NAME
	PUSHJ	P,PRNAME##	;PRINT IT OUT
	MOVEI	T3,","		;A SEPARATOR
	PUSHJ	P,COMTYO##	;TYPE IT
DIE4:	PUSHJ	P,INLMES##	;SEPARATION
	ASCIZ	/ on /
	MOVE	T2,.CPLOG##
	PUSHJ	P,PRNAME##
	PUSHJ	P,INLMES##	;SEPARATION
	ASCIZ	/ at /
	PUSHJ	P,DATIME##	;SAY WHEN
	PUSHJ	P,PCRLF##	;ADD A CRLF
	MOVE	T1,.CPSTY##	;GET STOPCODE TYPE AGAIN
	MOVE	T1,PRCTAB(T1)	;GET ITS CONTROL BITS
	SKIPN	.UONCE##	;NO DDB STUFF IN USER MODE
	TLNE	T1,(S%NDDB)	;SUPPRESS JOB TYPEOUT?
	JRST	NODDB		;YES, SKIP THIS
	MOVE	J,.CPJOB##
	MOVEI	S,PI.IPA	;GET PI ON MASK
	AND	S,.CPCPI##	;MASK OUT ALL ELSE
	SKIPN	S		;INTERRUPT LEVEL?
	PUSHJ	P,WHATJB	;NO--GIVE INFO
	TLZ	F,-1		;CLEAR LH BITS
	PUSHJ	P,CHKDDB	;MAKE SURE THAT F POINTS TO A DDB
	  JRST	NODDB		;IT DOESN'T, DON'T PRINT THE INFORMATION
	LDB	T1,PJOBN##	;GET JOB #
	CAILE	T1,JOBMAX##	;TOO BIG?
	JRST	NODDB		;YES--NOT A DDB
	JUMPE	T1,NODDB	;WANT REAL JOB #
	PUSHJ	P,INLMES##
	ASCIZ	/File /
	PUSHJ	P,PRTDDB##	;PRINT DDB STUFF
	PUSHJ	P,CRLF##	;ADD CRLF
	JUMPE	S,NODDB		;UUO LEVEL-SAID THIS
	LDB	J,PJOBN##	;GET JOB #
	PUSHJ	P,WHATJB	;PRINT IT
NODDB:	MOVE	T1,2(M)		;GET BITS FIELD
	TLNE	T1,400000	;ADDITIONAL INFORMATION
	SKIPN	T1,3(M)		;TYPE OUT ROUTINE
	JRST	NOTYPE		;JUMP IF NO ADDITIONAL TYPEOUT
IFN FTXMON,<
	HLL	T1,.CPSPC##+1	;GET CALLER'S SECTION
>; END IFN FTXMON
	PUSH	P,T1		;PUT SOMEWHERE SO WE CAN GET AT IT
IFN P-1,<PRINTX ? DIE REQUIRES THAT P=1>
;NOTE AC VALUE ASSUMPTIONS HERE!!
	MOVE	17,.CPACA##	;POINT TO SAVED ACS
	MOVE	0,0(17)		;LOAD UP S
	MOVSI	17,2(17)	;SOURCE ADDRESS
	HRRI	17,2		;ONE PAST P
	BLT	17,17		;RESTORE ALL BUT P
	PUSHJ	P,@(P)		;CALL THE ROUTINE
	POP	P,T1		;BALANCE THE STACK
	PUSHJ	P,CRLF##	;TERMINATE LINE
NOTYPE: MOVSI	T1,(DF.RIP)	;IS A RELOAD IN PROGRESS?
	TDNE	T1,DEBUGF##
	JRST	NOCSB		;YES, DON'T TYPE OUT MEANINGLESS CSB
	MOVE	T1,.CPSTY##	;GET ERROR TYPE
	MOVE	T1,PRCTAB(T1)	;GET CONTROL BITS
	SKIPN	.UONCE##	;NO CSB IN USER MODE
	TLNE	T1,(S%NCSB)	;SUPPRESS CSB TYPEOUT?
	JRST	NOCSB		;YES, DON'T TYPE CSB FOR TRIVIAL ERRORS
	SKIPGE	DEBUGF##	;WANT DDT?
	JRST	NOCSB		;YES, DON'T BOTHER WITH EXTRA TYPEOUT
	PUSHJ	P,TYPCSB##	;TYPE CPU STATUS BLOCK INFO ON THE CTY
NOCSB:	MOVE	T1,.CPSTY##	;GET ERROR TYPE
	HRRZ	T1,PRCTAB(T1)	;GET PROCESSOR TO HANDLE THIS
	PUSHJ	P,(T1)		;CALL IT
DIERS0:	MOVE	T1,.CPSTY##	;GET STOPCODE TYPE AGAIN
	HRRZ	T2,SCTTAB(T1)	;GET COUNTER LOCATIONS
	AOS	(T2)		;COUNT UP PER-CPU LOCATION
	HLRZ	T2,SCTTAB(T1)	;CHANGE POINTER
	AOS	(T2)		;COUNT UP SYSTEM-WIDE LOCATION
	MOVE	T2,PRCTAB(T1)	;GET CONTROL BITS
	MOVEI	T1,BUGCON	;POINT AT CONTINUATION MESSAGE
	TLNN	T2,(S%EVNT)	;IF A STOPCODE,
	PUSHJ	P,CONMES##	;ANNOUNCE THAT THE SHOW WILL GO ON
	POP	P,.CPTOA##	;RESTORE SCNSER
	POP	P,.JBEDV##	;RESTORE EDDT SYMBOL MAPPING
	POPJ	P,		;RETURN TO RESTORE PROTOCOL LEVEL
;DIE ERROR LOGGING
DIELOG:	PUSHJ	P,SAVT##	;SAVE SOME ACS
	HLLZ	T1,DELTBL+.EXFLG ;GET -VE LENGTH OF XFER TABLE
	HLRES	T1		;MOVE TO RH
	MOVMS	T1		;MAKE POSITIVE
	ADDI	T1,20+1		;PLUS STORAGE FOR AC BLOCK AND PI STATUS
	PUSHJ	P,ALCSEB	;ALLOCATE A SYSTEM ERROR BLOCK
	  POPJ	P,		;NO CORE
	HRLZ	T2,.CPACA##	;GET AC STORAGE
	HRRI	T2,.EBHDR+20(T1) ;SET UP TO COPY ACS WHICH WERE ACTIVE
	BLT	T2,.EBHDR+37(T1) ;(R20-R37) AT TIME OF STOPCODE
	MOVE	T2,.CPCPI##	;GET PI STATUS
	MOVEM	T2,.EBHDR+40(T1) ;(R40) AND SAVE IT
	XMOVEI	T2,DELTBL	;POINT TO TRANSFER TABLE
	PUSHJ	P,XFRSEB	;COPY AND QUEUE IT UP
	  JFCL			;DON'T CARE IF IT FAILS
	POPJ	P,		;RETURN


DELTBL:	SEBTBL	(.ERMSE,DELEND,EX.QUE)
	MOVE	CONFIG##+0	;(R00) ASCIZ
	MOVE	CONFIG##+1	;(R01)  SYSTEM
	MOVE	CONFIG##+2	;(R02)   NAME
	MOVE	CONFIG##+3	;(R03)    ...
	MOVE	CONFIG##+4	;(R04)     ...
	MOVE	SYSDAT##+0	;(R05) ASCIZ MONITOR
	MOVE	SYSDAT##+1	;(R06)  BUILD DATE
	MOVE	.CPASN##	;(R07) CPU SERIAL NUMBER
	MOVE	CNFDVN##	;(R10) MONITOR VERSION NUMBER
	MOVE	%SYSCD##	;(R11) STOPCODE NAME
	MOVE	%SYSJN##	;(R12) JOB NUMBER
	MOVE	%SYSTN##	;(R13) TTY NAME
	MOVE	%SYSPN##	;(R14) PROGRAM NAME
	MOVE	%SYSPP##	;(R15) PPN
	MOVE	%SYNJS##	;(R16) NUMBER OF JOB STOPCODES
	MOVE	%SYNDS##	;(R17) NUMBER OF DEBUG STOPCODES
DELEND:!			;END OF TABLE
;HERE TO TYPE OUT DURING S%FAST TYPE STOPCODES

DIETYO:	PUSH	P,U		;SAVE LDB ADDRESS
	HRRZ	U,.CPCTN##	;GET OUR CTY'S LINE NUMBER
	MOVE	U,LINTAB##(U)	;POINT TO ITS LDB
	PUSHJ	P,CCTYO##	;STUFF CHARACTER INTO A CHUNK
	JRST	UPOPJ##		;RESTORE AC AND RETURN
;HERE ON A DEBUG STOPCD

BUGCHK:	PUSHJ	P,STCLIM	;EXCEED STOPCD LIMIT?
	  JRST	SCLEXC		;YES
	MOVSI	T1,(DF.RDC)	;DO WE WANT TO
	TDNE	T1,DEBUGF##	; RELOAD?
	JRST	RELOAD		;YES--GO RELOAD
	MOVSI	T1,(DF.DDC)	;WANT TO DUMP ON
	TDNN	T1,DEBUGF##	;  THIS TYPE OF STOPCD?
	PUSHJ	P,CRSDMP	;DUMP SYSTEM AND RETURN
	POPJ	P,		;RETURN TO DIERS0

;HERE ON A BUGINF (NODUMP STOPCD)
INFSTP==CPOPJ##

;MESSAGE THAT SHOWS SYSTEM CONTINUATION
BUGCON:	ASCIZ	/[Continuing system]
/

;HERE ON A JOB ERROR STOPCD

ZAPJOB:	PUSHJ	P,STCLIM	;STOPCD LIMIT EXCEEDED?
	  JRST	SCLEXC		;YES
	MOVEI	S,PI.IPA	;GET PI ON MASK
	SKIPN	.UONCE##	;IF EXEC MODE,
	AND	S,.CPCPI##	;MASK OUT ALL ELSE
	MOVSI	T1,(DF.RJE)	;IS RELOAD ON JOB ERROR
	TDNN	T1,DEBUGF##	; REQUESTED?
	SKIPE	S		; OR PI LEVEL?
	JRST	RELOAD		;YES--GO RELOAD
	SKIPE	.USJOB		;CAN'T STOP THE NULL JOB
	SKIPE	.CPISF##	;IN SCHEDULER CONTEXT?
	JRST	RELOAD		;YES, CAN'T REALLY STOP A JOB
	MOVSI	T1,(DF.DJE)	;WANT TO DUMP ON
	TDNN	T1,DEBUGF##	;  THIS TYPE OF STOPCD?
	PUSHJ	P,CRSDMP	;DUMP SYSTEM AND RETURN
	PUSHJ	P,INLMES##	;NO--ZAP JOB
	ASCIZ	/[Aborting job]
/
	PUSHJ	P,GIVLOK##	;GIVE BACK LOCKS THIS CPU OWNS
	MOVEI	T1,BUGSTP	;ROUTINE TO KILL OFF JOB
	MOVEM	T1,.CPSPC##+1	;SAVE AS RETURN ADDRESS SO THIS JOB GETS NAILED
	POPJ	P,		;RETURN TO DIERS0
;HERE ON A CPU STOPCD

IFN FTMP,<
CPUSTP:	PUSHJ	P,STCLIM	;STOPCD LIMIT EXCEEDED?
	  JRST	SCLEXC		;YES
	MOVSI	T2,(DF.CP1)	;BIT FORCING CPU STOPCDS TO CAUSE RELOAD
	PUSHJ	P,LSTCPU##	;LAST OR ONLY CPU RUNNING IN SYSTEM?
	TDNE	T2,DEBUGF##	;NO, WANT TO RELOAD ON CPU STOPCDS?
	JRST	RELOAD		;YES, RELOAD THE SYSTEM
	MOVSI	T1,(DF.DCP)	;WANT TO DUMP ON
	TDNN	T1,DEBUGF##	;  THIS TYPE OF STOPCD?
	PUSHJ	P,CRSDMP	;DUMP SYSTEM AND RETURN
	PUSHJ	P,INLMES##	;TELL OF OUR ACTION
	ASCIZ	/[Stopping CPU]
/
	AOS	.CPSNC##	;COUNT UP NUMBER OF TIMES THIS CPU STOPPED
	AOS	%SYNCS##	;AND NUMBER OF TIMES ANY CPU STOPPED
	PUSHJ	P,KILUSR	;INSURE THAT THE CURRENT JOB IS STOPPED
				;  TO AVOID A REPEAT OF THE STOPCD IF
				;  HE STARTS TO RUN ON ANOTHER CPU
	MOVE	T1,-1(P)	;GET SAVED TYPEOUT ADDRESS
	MOVEM	T1,.CPTOA##	;RESTORE FOR SCNSER
	MOVE	T1,-2(P)	;GET SAVED EDV
	MOVEM	T1,.JBEDV##	;RESTORE FOR EDDT
	SKPCPU(1)		;SLAVE CPU?
	JRST	CPUST2		;NO, DO BOOT DEATH THINGS
	SKIPGE	.CPOK##		;DID EVERYONE THINK WE WERE DEAD?
	SETZM	.CPOK##		;NO, LET THEM KNOW (ESPECIALLY LSTCPU)
	HRRZ	T1,.CPSLF##	;POINT TO OURSELVES
	PUSHJ	P,BRKLOK##	;DECLARE OURSELVES DOWN (DOES A DIENLK)
CPUST1:	MOVEI	T1,SR.DIE	;TELL CP1CRS THAT WE WANT THE OPERATOR
	IORM	T1,.CPSBR##	;  TO MANUALLY RESTART THIS CPU
	S0JRST	REBOOT##	;SAVE STATE OF THE MACHINE
CPUST2:	SETOM	.CPOK##		;SINCE BOOT, MAKE SURE BECOM0 WILL BE CALLED
;	DIENLK			;NO LONGER HAVE INTERLOCK
	SETOM	.CPDIE##	;RESET DIE INTERLOCK NESTING COUNT
	PUSHJ	P,BRKDIE##	;MAKE SURE ALL LEVELS ARE RETURNED
CPUST3:	MOVEI	T1,^D10000	;NUMBER OF TIMES TO LOOP WHILE WAITING
CPUST4:	SKPCPU(0)		;STILL THE POLICY CPU?
	PJRST	CPUST1		;NO, SAVE STATE OF THE MACHINE
	SOJG	T1,CPUST4	;YES, LOOP
	PUSHJ	P,LSTCPU##	;LOOP EXPIRED, DID ALL THE OTHERS GO AWAY?
	  JRST	CPUST3		;NO, LOOP SOME MORE
	MOVEI	T1,CTYWAT##	;REPLACE IT WITH ONE
	MOVEM	T1,.CPTOA##	;THAT DOESN'T NEED PI
	MOVSI	T1,(DF.RAD)	;RELOAD AFTER DUMP BIT
	IORM	T1,DEBUGF##	;LIGHT IT FOR MONBTS (DON'T DUMP TWICE)
	PJRST	RELOAD		;AND GO RELOAD THE SYSTEM
>
;HERE IF WE EXCEEDED ONE OF THE STOPCD-PER-UNIT-TIME LIMITS TO RELOAD
;THE SYSTEM.

SCLEXC:	PUSHJ	P,INLMES##	;TELL WHAT HAPPENED
	ASCIZ	/?Stopcode limit exceeded
/


;HERE TO RELOAD THE SYSTEM

IFE FTMP,<
CPUSTP:
>
RELOAD:	.CREF	DF.SBD		;(FLAG BIT TESTED)
	SKIPGE	DEBUGF##	;WANT DDT?
	XCT	.CPDDT##	;CALL ON DDT
	MOVSI	T1,(DF.RLD)	;INDICATE RELOAD
	IORM	T1,DEBUGF##	;FOR CRSCPY
	MOVE	T1,.CPSNM##	;GET STOPCODE NAME
	MOVEM	T1,CRSWHY##	;SAVE REASON FOR ONCE AFTER RELOAD
	SKIPE	.UONCE##	;IF USER-MODE,
	CALLI	12		;EXIT
	PUSHJ	P,INLMES##
	ASCIZ	/Reload monitor
/
	MOVEI	T2,^D20		;20 BELLS
	PUSHJ	P,BELLS		;..
	MOVE	T1,.CPSUP##	;GET CRASH PC
	MOVEM	T1,CRSHWD	;SAVE PC
	SOS	CRSHWD##	;FOR SYSTAT/X
	S0JRST	REBOOT##	;RELOAD NOW
COMMENT @
"Recent findings have shown bugs that are adaptive and intelligent.
The study of such bugs has been hampered by the probablity that these
bugs themselves have bugs, producing erratic buglike behavior.  If
this is indeed true, it provides the first demonstration that Murphy's
Law is recursive, that it can invoke itself."

IEEE Spectrum, September 1984
@

;TABLES FOR DRIVING STOPCODE PROCESSING


S%FAST==1B0		;FLAG FOR STOPCODE VS. EVENT (SVPPC)
S%NDDB==1B1		;FLAG TO SUPPRESS DDB/JOB TYPEOUT
S%NCSB==1B2		;FLAG TO SUPPRESS CSB TYPEOUT
S%EVNT==1B3		;FLAG TO TYPE "EVENT" RATHER THAN "STOPCODE"

DEFINE	STPTAB,<
STP	HALT,RELOAD,0,0,
STP	STOP,RELOAD,0,0,
STP	JOB,ZAPJOB,.CPSNJ##,%SYNJS##,
STP	DEBUG,BUGCHK,.CPSND##,%SYNDS##,
STP	CPU,CPUSTP,.CPSNC##,%SYNCS##,
STP	INFO,INFSTP,.CPSNI##,%SYNIS##,<NDDB,NCSB,FAST>
STP	EVENT,INFSTP,.CPSNI##,%SYNIS##,<EVNT,NDDB,NCSB,FAST>
>

STPTYP:
	DEFINE	STP(TYP,RTN,CPLOC,SYLOC,FLAGS),<
	IFN <.-STPTYP>-S$'TYP,<PRINTX ? STOPCODE TYPE TYP IS OUT OF ORDER>
	EXP SIXBIT \TYP\
>
	STPTAB
  STPMAX==.-STPTYP-1	;MAXIMUM LEGAL STOPCODE TYPE

PRCTAB:
	DEFINE	STP(TYP,RTN,CPLOC,SYLOC,FLAGS),<
	ZZ==0
	IRP	FLAGS,<ZZ==ZZ!S%'FLAGS>
	EXP	ZZ ! RTN
	PURGE	ZZ
>
	STPTAB

SCTTAB:	DEFINE	STP(TYP,RTN,CPLOC,SYLOC,FLAGS),<XWD SYLOC,CPLOC>
	STPTAB
;HERE TO STOP AN ILL FATED USER
BUGSTP:	MOVE	J,.USJOB	;JOB NUMBER
	PUSHJ	P,ZAPUSR	;GIVE UP LOCKS AND DEVICES
	JSP	T1,ERRPTU	;PRINT MESSAGE
	ASCIZ	/Monitor error/
	PJRST	UUOPCP		;PRINT SOME PC'S


;ROUTINE TO KILL THE CURRENT JOB RUNNING ON THIS CPU TO MAKE SURE
;THAT IT DOESN'T CONTINUE TO CAUSE THE SAME CRASH OVER AND OVER AGAIN.
;MUST NOT BE CALLED WITH A UUO LEVEL STACK SINCE ZAPPGM WILL GIVE
;BACK THE PAGE MAP.

KILUSR:	PUSHJ	P,GIVLOK##	;RETURN INTERLOCKS OWNED BY THIS CPU
	SKIPN	J,.CPJOB##	;ANY JOB RUNNING ON THIS CPU?
	POPJ	P,		;NO, JUST RETURN
IFN FTMP,<
	MOVE	T1,.CPCPN##	;GET OUR CPU NUMBER
	LSH	T1,11		;SLIDE IT OVER SO WE CAN SAVE THE
	ADD	T1,J		;JOB NUMBER WITH IT
	MOVE	T2,[KILZAP,,1]	;CALL KILZAP AFTER ONE TIC
	SYSPIF			;MAKE A CLOCK QUEUE ENTRY
	IDPB	T2,CLOCK##	;ROUTINE AND INTERVAL (ONE TIC)
	IDPB	T1,CLOCK##	;DATA (CPU AND JOB NUMBERS)
	SETOM	CLKNEW##	;FLAG NEW ENTRY
	SYSPIN
> ;END IFN FTMP
ZAPZAP::PUSHJ	P,ZAPHER	;GIVE UP LOCKS AND DEVICES
	PUSH	P,JBTSTS##(J)	;SAVE CURRENT STATE OF JBTSTS
	MOVSI	T1,JLOG		;CLEAR JLOG TEMPORARILY SO THAT
	ANDCAM	T1,JBTSTS##(J)	;  ZAPPGM WILL GIVE BACK ALL OF THE
	ANDM	T1,0(P)		;  USER'S CORE.  I KNOW IT'S UGLY BUT...
	PUSHJ	P,ZAPPGM##	;GIVE BACK ALL OF HIS CORE
	POP	P,T1		;GET BACK STATE OF JLOG BIT
	IORM	T1,JBTSTS##(J)	;SET IT IF IT WAS SET BEFORE
	POPJ	P,		;RETURN

IFN FTMP,<
KILZAP:	MOVE	J,T1		;NEED JOB NUMBER
	TRZ	J,777000	;JUST THE JOB NUMBER
	LSH	T1,-11		;CPU NUMBER
	IMULI	T1,.CPLEN##	;CDB OFFSET
	MOVEI	P1,.C0CDB##(T1)	;ACTUAL CDB ADDRESS
	PJRST	CPUZAP##	;MAKE THE JOB RUNNABLE AGAIN AND TELL HIM
				;ABOUT THE CPU FAILURE
> ;END IFN FTMP
;SUBROUTINE TO SEND C(T2) BELLS
;CLOBBERS T1, T2, T3, T4
BELLEN:	HRRZ	T1,.CPTOA##	;GET TYPEOUT ROUTINE
	CAIE	T1,DIETYO	;DOES IT BUFFER FOR US?
BELLS:	TDZA	T1,T1		;NO, FLAG IT
	MOVEI	T1,1		;YES, FLAG THAT
	PUSH	P,T1		;SAVE FLAG
	PUSH	P,T2		;NUMBER OF BELLS TO OUTPUT
BELOOP:	MOVEI	T3,"G"-100	;BELL
	PUSHJ	P,COMTYO##	;DING
	SOSG	(P)		;DECREMENT NUMBER OF BELLS TO OUTPUT
	JRST	TTPOPJ##	;DONE
	SKIPN	.UONCE##	;DON'T LOOP IN USER MODE (IT WON'T HELP)
	SKIPE	-1(P)		;CHECK FLAG
	JRST	BELOOP		;DON'T LOOP IF PI'S STILL ON
IFN FTKL10,MOVSI T1,1		;LOOP 2^18 TIMES ON A KL10
IFN FTKS10,MOVEI T1,200000	;LOOP 2^16 TIMES ON A KS10
	DMOVE	T2,BECODE	;PUT TIMING CODE IN ACS TO AVOID ERRATIC TIMING
	JRST	T2		;  DUE TO PRESENCE OR ABSENCE OF CACHE

BECODE:	SOJG	T1,T2		;(T2) DECREMENT T1 AND LOOP
	JRST	BELOOP		;(T3) OUTPUT ANOTHER BELL WHEN DONE

;ROUTINE TO CHECK A DDB ADDRESS BEFORE USING IT TO TYPE FILE INFORMATION
;DURING DIE PROCESSING.
;CALL:	MOVEI	F,ADDRESS
;	PUSHJ	P,CHKDDB
;	  RETURN HERE IF ADDRESS IS ILLEGAL FOR SOME REASON
;	RETURN HERE IF ADDRESS IS OK

CHKDDB:	CAMGE	F,SYSSIZ##	;LARGER THAN THE LOW SEG?
	CAIG	F,1000		;OR TOO SMALL?
	CAIA			;YES, MAY STILL BE IN FUNNY SPACE
	JRST	CPOPJ1##	;GIVE SKIP RETURN
	CAIL	F,.FPMC		;LEGAL ADDRESS IN
	CAIL	F,.FPMC+NWMCP	;  FUNNY SPACE?
	POPJ	P,		;NO, BAD DDB ADDRESS
	MAP	T1,(F)		;MAP THE ADDRESS
	PUSHJ	P,FLTCHK##	;WILL REFERENCE FAULT?
	  POPJ	P,		;YES, BAD ADDRESS
	MAP	T1,DEVSFD##(F)	;LAST ADDRESS IN DDB REFERENCED BY PRTDDB
	PJRST	FLTCHK##	;CHECK ADDRESS AND RETURN
;ROUTINE TO SEE IF THIS STOPCD HAS CAUSED US TO EXCEED ON OF THE
;STOPCDS-PER-UNIT-TIME LIMITS.
;CALL:	PUSHJ	P,STCLIM
;	  RETURN HERE IF A LIMIT HAS BEEN EXCEEDED
;	  RETURN HERE IF NOT

STCLIM:	SKIPN	.UONCE##	;NO LIMITS IN USER MODE
	SKIPGE	DEBUGF##	;IF DEBUGGING
	JRST	CPOPJ1##	;THEN NOSTOPCD LIMITS
	MOVSI	T1,-SCCTBL##	;BUILD AOBJN POINTER TO TABLE
STCLI1:	AOS	T2,SCCTAB##(T1)	;INCREMENT NEXT COUNT
	HRRZ	T3,SCLTAB##(T1)	;GET THE LIMIT
	CAIL	T2,(T3)		;EXCEED THE LIMIT?
	POPJ	P,		;YES
	AOBJN	T1,STCLI1	;NO, LOOP FOR NEXT
	HLRZ	T1,SCLTAB##+0	;GET PERIOD OF LOWEST ENTRY IN TABLE
	IMUL	T1,TICSEC##	;SETUP CLOCK REQUEST TO DECREMENT THE
	HRLI	T1,DECSCC	;  1 MINUTE STOPCD COUNT. DECSCC WILL,
	MOVEI	T2,0		;  IN TURN, PUT IN A CLOCK REQUEST TO DECREMENT
	IDPB	T1,CLOCK##	;  THE NEXT ONE, AND SO ON, UNTIL ALL
	IDPB	T2,CLOCK##	;  LEVELS OF COUNTS HAVE BEEN DECREMENTED.
	SETOM	CLKNEW##	;I REALIZE THE CLOCK QUEUE HASN'T BEEN
				;  INTERLOCKED WITH SYSPIF BUT BY THE
				;  TIME THE FIRST CHARACTER OF THE STOPCD
				;  MESSAGE HAS TYPED ON THE CTY, ALL OTHER
				;  CPU'S SHOULD HAVE SEEN INTDIE GO NON-ZERO
	JRST	CPOPJ1##	;GIVE SKIP RETURN


;ROUTINE TO DECREMENT A STOPCD COUNT AND RESUBMIT A CLOCK QUEUE REQUEST
;FOR THE NEXT HIGHER COUNT, IF ONE EXISTS.
;CALL:	MOVEI	T1,INDEX INTO SCCTAB
;	PUSHJ	P,DECSCC
;	  RETURN HERE ALWAYS


DECSCC::SOSGE	SCCTAB##(T1)	;DECREMENT COUNT
	SETZM	SCCTAB##(T1)	;LEAVE ZERO IF IT WAS ZERO
	AOS	T1		;INCREMENT LEVEL
	CAIL	T1,SCCTBL##	;DONE THE LAST LEVEL?
	POPJ	P,		;YES, RETURN NOW
	MOVE	T2,SCLTAB##(T1)	;GET WORD WITH NEW PERIOD
	SUB	T2,SCLTAB##-1(T1) ;SUBTRACT OLD PERIOD
	HLRZS	T2		;KEEP JUST DIFFERENCE IN PERIODS
	IMUL	T2,TICSEC##	;CONVERT TO TICKS
	HRLI	T2,DECSCC	;WANT TO COME BACK HERE
	SYSPIF			;INTERLOCK THE QUEUE
	IDPB	T2,CLOCK##	;STORE REQUEST
	IDPB	T1,CLOCK##	;  AND DATA
	SETOM	CLKNEW##	;FLAG A NEW REQUEST
	PJRST	ONPOPJ##	;RETURN INTERLOCK AND POPJ
;ROUTINES FOR STOPCODE MACRO TYPE OUT
;ALL ROUTINES WILL HAVE THE FORM DIE???::
;WHERE ??? ARE 3 LETTERS DESCRIPTIVE OF THE ROUTINE
;AN AUTOMATIC CARRIAGE RETURN/LINE FEED IS DONE BY CALLER

;ROUTINE TO TYPE OUT UNINAM(U) DURING STOPCD
DIEUNI::PUSHJ	P,INLMES##	;START THE OUTPUT
	ASCIZ	\Unit = \
	MOVE	T2,UDBNAM(U)	;GET UNIT NAME
	PJRST	PRNAME##	;PRINT OUT SIXBIT AND RETURN


; ROUTINE TO TYPE OUT STRNAM(P2) DURING A STOPCODE
DIESTR::PUSHJ	P,INLMES##	;TYPE INTRODUCTION
	ASCIZ	|Structure = |
	MOVE	T2,STRNAM##(P2)	;GET STR NAME
	PJRST	PRNAME##	;TYPE IT AND RETURN
;ROUTINE TO TYPE OUT ADDITIONAL DATA DURING BUGINF (OR BUGCHK OR ...)
;
;CALLED VIA JSP T1,BGCTYP
;DATA TO BE TYPED FOLLOWS

	$CSUB			;MUST BE ADDRESSABLE BY ALL CODE SEGMENTS

BGCTYP::MOVE	P1,T1		;COPY POINTER TO DATA
IFN FTXMON,<
	TLNE	T1,MXSECN	;CALLED FROM NON-ZERO SECTION?
	XJRST	[MCSEC1+BUGTY1]	;YES, ENTER SECTION 1 FOR OUTPUT ROUTINES
>; END IFN FTXMON
	JRST	BUGTY1		;STAY IN CALLER'S SECTION

	$HIGH

BUGTY1:	SKIPE	.UONCE##	;IF USER-MODE,
	JRST	BUGTY2		;ASSUME WON'T FAULT
	MAP	T1,(P1)		;MAKE SURE LOCATION IS ACCESSIBLE
	PUSHJ	P,FLTCHK##	;MAKE SURE WON'T FAULT
	  POPJ	P,		;WILL FAULT, END LIST NOW
BUGTY2:	SKIPN	(P1)		;HIT END OF DATA ITEMS?
	POPJ	P,		;YES, END LIST NOW
	PUSHJ	P,PR3SPC##	;A LITTLE SPACING
	MOVE	T2,(P1)		;GET ITEM NAME
	PUSHJ	P,PRNAME##	;PRINT IT
	PUSHJ	P,INLMES##	;A LITTLE NOISE
	ASCIZ	/: /
	SKIPE	.UONCE##	;AGAIN,
	JRST	BUGTY3		;USER MODE IS BRAVE
	MAP	T1,1(P1)	;MAKE SURE THIS WON'T FAULT
	PUSHJ	P,FLTCHK##
	  POPJ	P,		;END OF LIST FORCED
BUGTY3:	MOVE	T1,1(P1)	;GET ADDRESS OF ITEM
	MOVE	T2,.CPACA##	;GET ADDRESS OF SAVED AC'S
	ADD	T2,T1		;OFFSET TO SAVED ITEM IF IN CRASH AC'S
	CAIG	T1,17		;ITEM IN CRASH AC'S?
	SKIPA	T1,(T2)		;YES, FETCH FROM PROPER LOCATION
	MOVE	T1,(T1)		;NO, GET DIRECTLY
	PUSHJ	P,PRTXWD##	;PRINT IT AS HALFWORDS
	ADDI	P1,1		;LOOP FOR NEXT ITEM
	AOJA	P1,BUGTY1	;UNTIL DONE
;ROUTINE TO CALL BUGDMP TO TAKE A CONTINUABLE STOPCD DUMP
;AND THEN SET DF.RQC IN DEBUGF WHICH WILL CAUSE CRSCPY
;TO BE CALLED BY THE BOOT CPU AT THE NEXT TICK.  WE
;CAN'T CALL CRSCPY DIRECTLY BECAUSE THE SCNSER INTERLOCK
;MAY NOT BE FREE.
;ENTER AT FRCCPY TO JUST SET DF.RQC (FROM ADDSDL)
;CALL:	PUSHJ	P,CRSDMP
;	RETURN HERE ALWAYS

CRSDMP:	SKIPE	.UONCE##	;IF USER-MODE,
	POPJ	P,		;IGNORE THIS
	SE1ENT			;ENTER SECTION 1
	PUSH	P,JOBSYM##	;KEEP DAEMON FROM THINKING THIS IS A
	SETZM	JOBSYM##	;RELOAD BY ZEROING THE FLAG THAT IT LOOKS AT
	PUSHJ	P,BTDUMP##	;TAKE DUMP
	  JFCL			;IGNORE ERROR RETURN
	POP	P,JOBSYM##	;RESTORE SYMBOL TABLE POINTER

FRCCPY::MOVSI	T1,(DF.RQC)	;IF THE CRSCPY REQUEST HAS NOT BEEN
	MOVSI	T2,(DF.DCC)	; DISABLED VIA THE /NOCOPY STARTUP
	TDNN	T2,DEBUGF##	; SWITCH, SET DF.RQC IN DEBUGF WHICH
	IORM	T1,DEBUGF##	; WILL CAUSE CRSCPY TO BE CALLED ON
	ANDCAM	T2,DEBUGF##	; THE NEXT CLOCK TICK
	POPJ	P,		;RETURN


;ROUTINE TO START UP THE CRASH COPY PROGRAM TO COPY
;A DUMP.
;CALL:	PUSHJ	P,CRSCPY
;	RETURN HERE ALWAYS

CRSCPY::SKIPGE	DEBUGF##	;DON'T DO ANYTHING
	POPJ	P,		; IF DEBUGGING
	PUSHJ	P,FRCSET##	;SETUP TO STORE CHARACTERS IN FRCLIN
	MOVE	T2,CCPNAM##	;GET NAME OF PROGRAM TO RUN
	PUSHJ	P,PRNAME##	;STORE NAME
	PJRST	CRLF##		;ADD CRLF AND RETURN
WHATJB:	JUMPLE	J,CPOPJ##	;GET JOB NUMBER
	CAILE	J,JOBMAX##	;RANGE CHECK IT.
	POPJ	P,		;IGNORE IF FUNNY.
	PUSHJ	P,INLMES##	;GIVE THE JOB NUMBER
	ASCIZ	/Job /		; ..
	MOVE	T1,J		; ..
	MOVEM	T1,%SYSJN##
	MOVEM	T1,.CPSJN##
	PUSHJ	P,RADX10##	;IN DECIMAL
	PUSHJ	P,INLMES##	;PRINT OUT THE
	ASCIZ	/ on /		; TTY NAME
	MOVE	T2,@TTYTAB##(J)	;GET TTY NAME
	MOVEM	T2,%SYSTN##
	MOVEM	T2,.CPSTN##
	PUSHJ	P,PRNAME##	; AND PRINT IT.
	PUSHJ	P,INLMES##	;PRINT OUT
	ASCIZ	/ running /	; THE CUSP NAME
	MOVE	T2,JBTPRG##(J)	; SO OPERATOR
	MOVEM	T2,%SYSPN##
	MOVEM	T2,.CPSPN##
	PUSHJ	P,PRNAME##	; CAN FIND HIS JOBS
	PUSHJ	P,INLMES##
	ASCIZ	/ User /
	MOVE	T2,JBTPPN##(J)	;GET USER'S PPN
	MOVEM	T2,%SYSPP##	;AND SAVE FOR DAEMON
	MOVEM	T2,.CPSPP##
	PUSHJ	P,PRTPPN##	;PRINT PPN
	JUMPN	S,CRLF##
	PUSHJ	P,INLMES##	;NEW LINE
	ASCIZ	/
UUO is /
	MOVE	T1,.CPTRP##	;PICK UP UUO
	MOVEM	T1,%SYSUU##
	MOVEM	T1,.CPSUU##
	PUSHJ	P,HWDPNT##	;PRINT IN OCTAL
	DMOVE	T1,.JDAT+JOBPD1## ;GET PC FROM PUSH DOWN LIST
	MOVEM	T2,%SYSUP##
	MOVEM	T2,.CPSUP##
	PUSHJ	P,DPCP		;LIST THE LOCATION
	PJRST	CRLF##		;RETURN ON A NEW LINE
SUBTTL	UUO LEVEL ERROR ROUTINES

;INPUT UUO FOR OUTPUT DEVICE
;CALLED AT UUO LEVEL ONLY


ILLINP::JSP	T1,ERRPTU
	ASCIZ	/Output /
	PUSHJ	P,ERNAM		;PRINT "DEVICE XXX"
	JSP	T1,UUOMES	;PRINT MESSAGE,UUOPC,STOP JOB
	ASCIZ	/ cannot do input/

;OUTPUT UUO FOR INPUT DEVICE
;CALLED AT UUO LEVEL ONLY


ILLOUT::JSP	T1,ERRPTU
	ASCIZ	/Input /
	PUSHJ	P,ERNAM		;PRINT "DEVICE XXX"
	JSP	T1,UUOMES	;PRINT MESSAGE,UUOPC,STOP JOB
	ASCIZ	/ cannot do output/

;ILLEGAL DEVICE DATA MODE (INIT, OPEN, OR SETSTS UUOS)
;CALLED AT UUO LEVEL ONLY


ILLMOD::JSP	T1,ERRPTU
	ASCIZ	/Illegal data mode for /
	JRST	DEVEXC		;PRINT "DEVICE XXX",UUO PC

;ILLEGAL INBUF/OUTBUF (NON-ZERO SECTION)

ILLBUF::JSP	T1,ERRPTU
	ASCIZ	\Illegal INBUF/OUTBUF for \
	JRST	DEVEXC		;PRINT "DEVICE XXX", UUO PC

;IO UUO TO USER CHANNEL WITH NO PREVIOUS INIT OR OPEN
;CALLED AT UUO LEVEL ONLY


IOIERR::JSP	T1,ERRPTU
	ASCIZ	/IO to unassigned channel/
	JRST	UUOPCP		;PRINT UUO PC
;ILLEGAL UUO
;CALLED AT UUO LEVEL ONLY
;SERVES TWO PURPOSES - A) TO WARN WHEN MOVING FROM A LOCATION WITH SPECIAL INSTALLATION
;UUOS TO ONE WITH LACKS THEM
;B) TO WARN OF OLD UUO'S WITH NONSKIP "GOOD" RETURNS WHICH
;HAVE BEEN "DE-IMPLEMENTED"

UUOERR::EXCH	T1,.USMUO	;GET UUO PC FLAGS
	TLNN	T1,USRMOD	;FROM EXEC?
	JRST	EMUERR		;YES
	EXCH	T1,.USMUO	;PUT THINGS BACK
ILLUUO:	PUSH	P,.USMUO	;PC FLAGS
	PUSH	P,.USMUP	;NOW PUSH USER PC ON STACK JUST LIKE UUO
				; (LEAVE STACK UNTOUCHED BEFORE HALT)
				; (START PRESERVES PC FLAGS IN LH)
	PUSHJ	P,GIVRES	;GIVE UP INTERLOCKS
	SIGNAL	C$IUUO		;SIGNAL ILLEGAL UUO
	  SKIPA			;DOESN'T WANT THE TRAP
	JRST	ERRGOU		;INTERCEPT THE UUO
	JSP	T1,ERRPTU
	ASCIZ	/Illegal UUO/
	DMOVE	T1,.USMUO	;GET UUO PC
	SOJA	T2,DPCPNT	;AND PRINT, PRINT USER UUO PC IF DIFF.
IFE FTMP,<
;UUO ERROR-MONITOR ERROR AT UUO LEVEL
;CALLED AT UUO LEVEL ONLY

UUOER1::JSP	T1,ERRPTU
	ASCIZ	/UUO error/
	JRST	UUOPCP
>
;HERE ON AN EXEC MODE UUO ERROR

EMUERR:	EXCH	T1,.USMUO
	MOVEM	P,.CPEMU##+1	;SAVE STACK POINTER
	MOVEI	P,.CPEMU##-1	;GET A SHORT STACK FOR CALLING DIE
	CONSZ	PI,PI.IPA	;AT UUO LEVEL?
	STOPCD	.,STOP,UIL,DIEEMU, ;++UUO AT INTERRUPT LEVEL
	STOPCD	.+1,JOB,EUE,DIEEMU, ;++EXEC UUO ERROR
	MOVE	P,.CPEMU##+1	;RESTORE STACK POINTER
	PUSHJ	P,GIVLOK##	;RETURN SOFTWARE INTERLOCKS
	MOVE	J,.CPJOB##	;GET JOB NUMBER
	JRST	ILLUUO		;PRINT ERROR MESSAGE

DIEEMU:	PUSHJ	P,INLMES##
	ASCIZ	/MUUO Flags, Opcode, AC = /
	MOVE	T1,.USMUO	;GET FLAGS,OPCODE,AC
	PUSHJ	P,HWDPNT##	;PRINT IT
	PUSHJ	P,INLMES##
	ASCIZ	/
MUUO PC = /
	MOVE	T2,.USMUP	;GET PC
	PUSHJ	P,UDPCP		;PRINT IT
	PUSHJ	P,INLMES##
	ASCIZ	/   MUUO EA = /
	MOVE	T2,.USMUE	;GET EA
	PJRST	UDPCP		;PRINT IT AND RETURN
;HERE IF THE USER DIES IN GETWRD OR PUTWRD

UADERR::MOVE	J,.CPJOB##
	PUSHJ	P,GIVRES	;RETURN INTERLOCKS
	JSP	T1,ERRPTU
	ASCIZ	/Illegal address in UUO/
	JRST	UUOPCP
;ILLEGAL INSTRUCTION
;HALT INSTRUCTION IS A SPECIAL CASE WHICH STOPS JOB BUT
;THE USER MAY CONTINUE FROM IT(EFFECTIVE ADR.)
;CALLED AT UUO LEVEL WITH A JRST


ILLINS::LDB	T1,[POINT 9,M,8] ;OPCODE
IFN FTKL10,<
	CAIN	T1,<<EXTEND>_-^D27> ;IS THIS AN EXTEND INSTRUCTION?
	JRST	OINKSR##	;YES, CHECK FOR GFLOAT EXTEND OPCODE.
>
	CAIL	T1,130		;WITHIN LONG FLOATING POINT RANGE?
	CAILE	T1,177
	JRST	ILLIN1		;NO, ILLEGAL INSTRUCTION
	CAIL	T1,133		;A BYTE INSTR?
	CAILE	T1,137
	CAIA			;NO
	JRST	ILLIN1		;YES
	MOVSI	T2,(JS.FPS)	;WANT SIMULATION BIT
	SKIPE	[M.FPS##]	;SIMULATION ROUTINE LOADED?
	TDNN	T2,JBTST2##(J)	;AND DOES THE USER WANT SIMULATION?
	CAIA			;NO
	JRST	KALFPS##	;YES, SIMULATE THE KA FP INSTRUCTIONS
	SIGNAL	C$IUUO		;SIGNAL ILL INSTRS
	  CAIA			;PROGRAM ISN'T INTERESTED
	JRST	ERRGOU		;GO TO THE USER

	JSP	T1,ERRPTU	;TELL THE USER TO FIX THE PROGRAM
	ASCIZ	/KA10 floating point instruction/
	JRST	UUOPCP
ILLIN1::
	SIGNAL	C$IUUO		;SIGNAL ILL UUO
	  SKIPA			;USER DOESN'T WANT THE TRAP
	JRST	ERRGOU		;GO TO THE USER

	HLRZ	T1,M		;ILLEGAL OPCODE
	TRZ	T1,(SECMSK)	;CLEAR POSSIBLE SECTION NUMBER
	CAIN	T1,(HALT)	;IS IT A HALT?
	JRST	HALTI		;YES, PRINT DIFFERENT MESSAGE
IFN FTKS10,<
	LSH	T1,-9		;MAKE T1=OPCODE
IFN FTKS10,<
KSIBEG==102
KSIEND==110
	MOVSI	T2,314000	;MASK FOR KL-ONLY INSTRS
	CAIG	T1,KSIEND	;IF TOO LARGE, DON'T SHIFT
	LSH	T2,-KSIBEG+1(T1)	;SHIFT MASK BY OPCODE
>
	JUMPGE	T2,ILLKAI	;KA10 ILL INST IF SIGN NOT 1
	JSP	T1,ERRPTU
	ASCIZ	/KL10 only instruction/
	JRST	UUOPCP
> ;END FTKI10!FTKS10
ILLKAI:	JSP	T1,ERRPTU
	ASCIZ	/Illegal instruction/
	JRST	UUOPCP		;PRINT UUO PC AND STOP JOB

HALTI:	JSP	T1,ERRPTU
	ASCIZ	/HALT/
	DMOVE	T1,.JDAT+JOBPD1##
	SOS	T2		;UUOPC=LOC OF HALT+1
	PUSHJ	P,DPCP		;PRINT "USER LOC XXX"
	HRR	M,.USMUO+2	;CHKINT CLOBBERS M
	HRRM	M,.JDAT+JOBPD1##+1 ;SAVE EFFECTIVE ADDRESS OF HALT
	PUSH	P,U
	PUSHJ	P,TTYSRC##	;GETTTY
	STOPCD	.,STOP,LNT,	;NONE?!
	JUMPE	U,HALTI1	;JUMP IF JOB DETACHED
	POP	P,U
	PUSHJ	P,TSETBI##	;CLEAR TYPE-AHEAD
	PUSHJ	P,HOLDW##	;START TTY WITH STANDARD RESPONSE,, STOP
				;JOB, LEAVE TTY IN MONITOR MODE
				;DO NOT SET ERROR BIT SO CAN CONTINUE
	JRST	ERRGOU		;RETURN TO USER
HALTI1:	POP	P,U
	PUSHJ	P,CRLF##	;HERE TO HANDLE HALT IN DET'D JOB
	PUSHJ	P,ESTOP3##	;STOP JOB WITH CONTINUABILITY
	PUSHJ	P,WSCHED##	;WAIT FOR USER
	JRST	ERRGOU		;RESUME NORMAL FLOW

;ILLEGAL TRAP INSTRUCTION
ILLTIN::MOVE	P,[MJOBPD##,,.JDAT+JOBPDL##]
	PUSH	P,.USMUO	;PC FLAGS

	PUSH	P,.USMUP
	JSP	T1,ERRPTU
	ASCIZ	/Illegal trap instruction/
	JRST	UUOPCP		;PRINT TRAP INSTR PC AND STOP THE JOB
SUBTTL	I/O ERROR HANDLING ROUTINES

;ROUTINE FOR HUNG IO DEVICE
;CALL	MOVE F,ADDRESS OF DEVICE DATA BLOCK
;	PUSHJ P,DEVHNG


DEVHNG::PUSHJ	P,SVEUF##	;MAKE SURE JOB DATA AREA IS ADDRESSABLE

	LDB	J,PJOBN##	;JOB NUMBER
	JUMPN	J,DEVHN0	;DON'T CLEAR IOW UNLESS JOB 0
	PUSHJ	P,CLRACT##	;TURN OFF IO DEVICE ACTIVE BIT IN
				;MEMORY AND S
	JRST	DEVHN2		;GO TYPE THE MESSAGE

DEVHN0:	MOVEI	T1,IR.HNG	;HUNG CONDITION
	TSNN	T1,DEVPSI##(F)	;PROGRAM ENABLED?
	JRST	DEVHN1		;NO
	TRZ	S,IOACT		;CLEAR IOACT (LEAVE IOW ALONE)
	PUSHJ	P,STORS7##	;MAKE SURE IOS IS IN MEMORY
	PUSHJ	P,PSIDVB##	;SIGNAL HUNG DEVICE
	PUSHJ	P,RTNEVM##	;RETURN ANY EVM DEVICE HAS FOR I/O
	MOVE	S,DEVIOS(F)	;RESTORE S
	TRO	S,IOIMPM!IOBKTL!IODERR!IODTER ;ALL ERRORS
	PUSHJ	P,SETIOD##	;GET THE JOB GOING
	HLLZS	JBTDDB##(J)	;NOT IN IOWAIT NOW (FOR ^T'ERS)
	PJRST	STOIOS##	;STORE BITS AND RETURN

DEVHN1:	PUSHJ	P,CLRACT##	;BLOW AWAY IOACT AND IOW
	MOVSI	T1,JERR		;FLAG SO USER DOESN'T
	IORM	T1,JBTSTS(J)	;GET IF TRAP ENABLED
DVHN1A:
IFN FTMP,<
	CPLOCK	(SCD)		;GET SCHEDULER LOCK
>
	MOVEI	T1,STOPQ##
	DPB	T1,PJBSTS##
	PUSHJ	P,ANYCPU##	;IS HE RUNNING ANYWHERE NOW?
	  SKIPA			;YES MUST DELAY HANGING HIM
	JRST	DVHN1C		;NO, CAN STOP HIM NOW
	MOVEI	T2,1		;GET A WORD
	PUSHJ	P,GETWDS##	;OF FREE CORE
	  JRST	DVHN1C		;FAILED BLAST JOB ANYWAY
	MOVEM	F,(T1)		;STORE F
	HRLM	J,(T1)		;AND J
	MOVE	T2,.CPCPN##
	DPB	T2,[POINT 3,T1,3] ;CPU IS US
	TLO	T1,400000	;INDICATE CPU-SPECIFIC
	SYSPIF
	SETZM	CLKMIN##(T2)	;INDICATE NEW REQUEST IN QUEUE
	MOVE	T2,[DVHN1B,,1]	;COME BACK IN A TIC
	IDPB	T2,CLOCK##
	IDPB	T1,CLOCK##
	SYSPIN
IFN FTMP,<
	CPUNLK	(SCD)
>
	POPJ	P,		;AND RETURN FOR NOW
DVHN1B:	HLRZ	J,(T1)		;RESTORE J
	HRRZ	F,(T1)		;+F
	MOVEI	T2,(T1)		;RETURN FREE CORE
	MOVEI	T1,1
	PUSHJ	P,GIVWDS##
	PUSHJ	P,SVEUB##	;MAKE JOB ADDRESSABLE
	JRST	DVHN1A		;CHECK TO SEE IF HE'S STILL HERE
DVHN1C:	PUSHJ	P,ZAPDSK##	;REMOVE ALL DDBS OWNED BY JOB FROM UNI/CHN Q'S
	PUSH	P,F		;GIVSRC CLOBBERS F
	PUSHJ	P,GIVRSC	;RETURN RESOURCES, COULD HAVE SOME, IF STR YANKED
	POP	P,F		;RESTORE F
	MOVEI	T1,STOPQ##
	DPB	T1,PJBSTS##
IFN FTMP,<
	CPUNLK	(SCD)
>
DEVHN2:	JSP	T1,ERRDEV
	ASCIZ	/Hung /
	JRST	DEVEXC

;BAD DECTAPE DIRECTORY
;CALLED AT INTERRUPT AND UUO LEVELS WITH F AND J SETUP

BADDIR::PUSHJ	P,SVEUF##	;MAKE JOB DATA AREA ADDRESSABLE

	JSP	T1,ERRPNT
	ASCIZ	/Bad directory for /

;ROUTINE TO PRINT "DEVICE XXX; EXEC CALLED FOR EXEC/USER YYY"
;THEN STOP JOB
;TO BE USED BY DEVICE DEPENDENT ERROR MESSAGES AFTER JSP T1,DEVERR


DEVEXC::PUSHJ	P,ERNAM		;PRINT "DEVICE XXX"
	PUSHJ	P,TTYKLQ##	;KILL OFF TTY DDB IF NECESSARY
	SKIPE	JBTADR##(J)	;CHECK FOR JOB IN CORE
	JRST	EXCALP		;PRINT "EXEC CALLED FROM EXEC/USER LOC YYY"
	JRST	PCSTOP		;JUST STOP THE JOB

;ROUTINE TO HALT A JOB WHEN A DEVICE IS NOT READY FOR I/O
;CALLED FROM XXXSER AT UUO LEVEL
;CALL	MOVE F,ADDR. OF DEV. DDB
;	PUSHJ P,HNGSTP
;WILL DISPATCH TO USER'S AREA IF JOBINT IS NON-0


HNGSTP::PUSH	P,M
	PUSH	P,J
	PUSHJ	P,HNGSTX
	POP	P,J
	PJRST	MPOPJ##
HNGSTX:	PUSHJ	P,SAVE3##	;SAVE P1-P3
	SKIPE	P3,DEVEVM(F)	;DOES DEVICE HAVE EVM?
	SETO	P3,		;NO
	PUSHJ	P,RTNEVM##	;RETURN ANY EVM DEVICE HAS FOR I/O
				; P3=-1 IF DEVICE HAD NO EVM, 0 IF IT DID
	SOS	.JDAT+JOBPD1##+1 ;BACK UP PC
	HRRZ	T4,DEVSER(F)	;DISK?
	CAIE	T4,DSKDSP##
	JRST	HNGSTZ		;NO
	MOVEI	T4,.EROFL	;ASSUME OFF-LINE
	HRRZ	P1,DEVUNI##(F)	;IS IT?
	MOVE	P1,UNIDES##(P1)
	TLNN	P1,UNPOFL##
HNGSTZ:	MOVEI	T4,.ERIDV	;PROBLEM ON DEVICE
	TLO	M,(1B0)
	PUSHJ	P,PSIJBI##	;CALL PSISER
	  PJSP	P1,HNGST1	;P1 NON-ZERO TO INDICATE INTERCEPTING
	TLZ	M,(1B0)

	SETO	T2,		;MAKE T2 NON-ZERO SO LATER CHECKS WILL WORK
	LDB	J,PJOBN##
	SKIPE	T3,JBTSTS##(J)
	TRNN	T3,JS.ASA
	PUSHJ	P,CHKINT	;SEE IF SET UP
	  SETZB	T2,T3		;NO
	MOVE	P1,T2		;SAVE LOCATION
	PUSHJ	P,DOINT		;PREPARE INTERCEPT
	JUMPN	T2,HNGST1	;IF NOT INTERCEPTING
	PUSHJ	P,INCPD1##
HNGST1:	JUMPL	T3,HNGST3	;YES, DOES HE WANT THE ERROR MESSAGE?
	PUSH	P,W
	PUSH	P,S
	PUSH	P,U
	PUSH	P,F		;SAVE DEV'S S WORD & DDB
	PUSHJ	P,FNDPDS##	;FIND PDB AND PUT IT'S ADDRESS IN W
				; IF NONE HALT.
	EXCH	F,0(P)		;GET F FROM DEVICE
	LDB	T1,PDVSTA##	;GET JOB'S LOCATION
	EXCH	F,0(P)		;GET F FOR TTY BACK
	JUMPE	T1,HNGST2	;CENTRAL SITE IF 0 (DISK)
IFN FTNET,<
	PUSHJ	P,STBOPR##	;GET OPR LINE
>
IFE FTNET,<
	MOVE	U,OPRLDB##
	SE1XCT	<LDB T1,LDPLNO##>
>
	SKIPA	U,LINTAB##(T1)	;GET LDB ADDR
HNGST2:	MOVE	U,OPRLDB##	;CENTRAL STA OPR
	PUSHJ	P,INLMES##	;OUTPUT START OF MESSAGE
	ASCIZ	/
%Problem on /
	PUSHJ	P,ERNAM		;PRINT PHYSICAL DEVICE NAME (USING -1(P))
	PUSHJ	P,INLMES##	;LOGICAL DEVICE OPR
	ASCIZ	/ for job /
	PUSHJ	P,PJOB##
	PUSHJ	P,CRLF##
	PUSHJ	P,DETJCK	;DETACHED?
	JRST	HNGST8		;YES,NO MESSAGES
	PUSHJ	P,TTYFUW##	;FIND CURRENT JOB'S TTY
	PUSHJ	P,CRLF##	;START A NEW LINE
	PUSHJ	P,ERNAM		;PRINT "DEVICE XXX"
	PUSHJ	P,INLMES##	;AND MSG.
	ASCIZ	/, OPR/
IFN FTNET,<
	EXCH	F,(P)		;GET POINTER DDB
	LDB	T1,PDVSTA##	;GET DEVICES LOCATION
	EXCH	F,(P)
	S0PSHJ	CVTSBT##	;CONVERT TO SIXBIT
	MOVE	T2,T1		;GET SIXBIT FOR PRNAME
	PUSHJ	P,PRNAME##	;AND PRINT IT
>
	PUSHJ	P,INLMES##
	ASCIZ	/ action requested
/


	MOVEI	T1,TTYSTR##	;UNLESS ERROR INTERCEPTING
	SKIPN	P1		;CALL HOLD0 (STOP JOB,START TTY)
HNGST8:	MOVEI	T1,HNGST4	;SET UP ROUTINE TO CALL
	PUSHJ	P,(T1)		;START TTY TYPING ERR MESSAGE
				; LEAVE IN COMMAND MODE
				;DO NOT SET JOB ERROR SO CAN CONTINUE
	POP	P,F		;BRING BACK DEV DDB & S WORD
	POP	P,U
	POP	P,S
	POP	P,W
	JUMPN	P1,HNGST3	;DO INTERCEPT IF WANTED
	PUSHJ	P,WSCHED##	;RESCHEDULE
	HRRZ	T1,DEVSER(F)	;IS THIS A DISK?
	CAIE	T1,DSKDSP##
	 JRST	HNGST9		;NO, SKIP THIS
	PUSHJ	P,CHEKU##	;YES, WAS F/S YANKED?
	  PJRST	DEVHNG		;YES, SAY IT'S HUNG
HNGST9:	AOJN	P3,CPOPJ##	;DEVICE HAVE EVM WHEN THE ERROR OCCURRED?
	MOVE	M,-5(P)		;RESTORE M FOR ADDRESS CHECK
	PJRST	RSTEVM##	;YES, RESTORM EVM FOR I/O
HNGST3:	MOVEI	T1,DEPOND!DEPIND ;NON-BLOCKING I/O NOT DONE BITS
	ANDCAM	T1,DEVAIO(F)	;CLEAR THEM SO THAT IN/OUT UUOS WILL WIN
	MOVEI	P1,1(M)		;SAVE 1(INTERCEPT LOC)
	LDB	T1,PIOMOD##	;MODE
	MOVE	T4,DEVADV(F)
	TLNN	T4,DEPADV
	CAIL	T1,SD		;DUMP?
	JRST	HNGST7		;YES, NO BUFFERS TO FIX
	HRR	M,DEVBUF(F)	;BUFFERED, FIX UP BUFFER HDR
	TLNE	S,IO		; SO REPEATING THE UUO WILL WIN
	HLR	M,DEVBUF(F)	; (THEY WERE ALREADY ADVANCED)
	HRRZ	T4,M		;SAVE LOCATION OF THE HDR
	JUMPE	T4,HNGST7	;JUMP IF NO BUFFERS YET SET UP
	PUSHJ	P,GETWRD##	;GET LOCATION OF FIRST BUFFER
	JRST	HNGST7		;ADDRESS CHECK - CAN'T FIX THE RING
	MOVE	P2,T1		;P2=ADDRESS OF FIRST BUFFER
	MOVEI	T3,10000	;END OF LOOP INSURANCE
HNGST5:	HRR	M,T1		;M=ADDRESS OF THIS BUFFER
	PUSHJ	P,GETWRD##	;GET THE ADDRESS OF THE NEXT ONE
	  JRST	HNGST7		;ADDRESS CHECK, FORGET IT
	CAIE	P2,(T1)		;THE ONE WE WANT?
	SOJGE	T3,HNGST5	;NO, STEP TO NEXT
	JUMPL	T3,HNGST7	;YES, JUMP IF RING WAS NOT CLOSED
	HRR	P2,M		;P2=POINTER TO NEXT BUFFER
	TLO	T1,IOUSE	;INDICATE "FULL" FOR TEST AT INPUT
	PUSHJ	P,PUTWDU##	;STORE THAT
	HRR	M,T4		;RESTORE HEADER ADDRESS
	MOVE	T1,P2		;T1=DEADVANCED BUFFER POINTER
	PUSHJ	P,PUTWDU##	;STORE THAT IN THE HDR
HNGST7:	HRRI	M,(P1)		;M=ADDRESS OF THIRD WORD OF INT. BLOCK
	PUSHJ	P,GETWDU##	;FETCH IT
	HLR	T1,.USCTA
	SKIPL	M		;SKIP IF PSISER TRAP
	PUSHJ	P,PUTWDU##	;STORE FOR INTERRUPT ROUTINE
QKUSXT::
ERRGOU::HRRI	P,.JDAT+JOBPD1##+1 ;SET P FOR NORMAL EXIT
				;(POP P,UUO0 ; JRST @UUO0)
	SETZB	F,.CPISF##	;NO LONGER AT SCHEDULER LEVEL
	SETZM	.CPSCF##	;CLEAR FORCED RESCHEDULE FLAG
	NTGIVE			;RETURN NETWORK INTERLOCK
	PJRST	USRXIT##	;LET UUOCON RETURN TO USER
HNGST4:	MOVEI	T1,JDCON	;NO ERROR INTERCEPT
	IORM	T1,JBTSTS##(J)	; SO SET DEV CONT BIT

	MOVSI	T1,(UP.DST)	;MAKE THIS JOB LOOK DETACHED
	IORM	T1,.USBTS	; SO IT'S TERMINAL IS NOT PUT
				; AT COMMAND LEVEL.
	PJRST	STOP1C##	;STOP JOB-SETUP TO RESCHEDULE
				; BUT DO NOT CALL WSYNC

;ROUTINE TO SEE IF A JOB'S TTY IS DETACHED, CPOPJ1 IF ATTACHED
;CLOBBERS T1

DETJCK::PUSH	P,U		;SAVE SOME ACS
	PUSH	P,S
	PUSH	P,F
	PUSH	P,J
	PUSHJ	P,TTYSRC##	;FIND JOB'S TTY
	  CAIA			;NONE
	SKIPN	U		;OR DETACHED
	SOS	-4(P)		;DETACHED PRIV'ED JOB RETURN
	POP	P,J
	POP	P,F
	POP	P,S
	JRST	UPOPJ1##
;CHKINT -- ROUTINE TO SETUP FOR JOBINT USAGE
;CALL:	MOVEI	T4,ERROR TYPE (CLASS)
;	PUSHJ	P,,CHKINT
;SKIP RETURNS	M = RELATIVE BLOCK ADDRESS+2 (WHERE OLD PC IS STORED)
;		T1 = NEW PC
;		T3 = CONTENTS OF BITS,,CLASS
;STORES ERROR TYPE IN BLOCK+3.

CHKINT::SKIPN	JBTADR##(J)	;JOB HAVE CORE?
	POPJ	P,		;NO - THEN NO JOBINT
	MOVE	T1,JBTSTS##(J)	;JOB STATUS
	TLNN	T1,SWP		;IS JOB SWAPPED OR
	TRNE	T1,JS.ASA	;EXEC MODE UUO IN PROGRESS?
	POPJ	P,		;YES, DON'T TRAP
	HRR	M,.JDAT+JOBINT##  ;GET ERROR LOCATION
				; SET M FOR GETWRD/PUTWRD
	HRRZ	T1,M		;CHECK FIRST WORD OF INTERRUPT VECTOR
	TRNE	M,-1		;NO INTERRUPT IF JOBINT NOT SET
	PUSHJ	P,FLTST##	;IN-CORE?
	  POPJ	P,		;NO
	ADDI	T1,3		;LAST WORD OF VECTOR
	PUSHJ	P,FLTST##	;IN-CORE?
	  POPJ	P,		;NO
	PUSHJ	P,GETWRD##	;GET NEW PC
	  POPJ	P,		;ADDRESS CHECK - GIVE UP
	HRL	T4,T1		;SAVE NEW PC
	PUSHJ	P,GETWR1##	;GET BITS,,CLASS
	  POPJ	P,		;OUT OF BOUNDS
	MOVE	T3,T1		;SAVE THOSE
	PUSHJ	P,GETWR1##	;GET OLD PC
	  POPJ	P,		;ADDRESS CHECK - GIVE UP
	TRNE	T4,-1		;IF SPECIAL,
	TRNE	T3,(T4)		;  SEE IF USER OMITTED IT
	SKIPE	T1		;SEE IF IN USE ALREADY
	POPJ	P,		;YES - GIVE UP
	PUSHJ	P,GETWR1##	;GET THE OLD WORD
	  POPJ	P,0		; ADDRESS CHECK
	TLO	T1,(T4)		;TURN ON THE NEW BIT
	TRNE	T4,.ERQEX!.ERFUL!.EROFL!.ERIDV ;IS THERE A CHANNEL ASSOCIATED?
	HLR	T1,.USCTA	;YES, RETURN ASSOCIATED CHANNEL
	PUSHJ	P,PUTWRD##	;  STORE ERROR BITS
	  POPJ	P,		;ADDRESS CHECK - GIVE UP
	HLRZ	T1,T4		;GET NEW PC
	JUMPE	T1,CPOPJ##	;GIVE UP IF JUNK
	SOJA	M,CPOPJ1##	;OK RETURN

;DOINT -- ROUTINE TO PERFORM THE JOBINT
;CALL:	MOVE	T1,NEW PC
;	MOVEI	M,USER VIRTUAL ADDRESS OF INTERRUPT BLOCK + 2
;RETURN WITH JOBPD1 UPDATED

DOINT::	JUMPE	T2,CPOPJ##	;IF NO BLOCKS, GIVE UP
DOINT1::EXCH	T1,.JDAT+JOBPD1##+1 ;GET THE TRAP PC
	PUSH	P,T2		    ;FREE AN AC
	HLLZ	T2,.JDAT+JOBPD1##   ;GET THE UUO FLAGS
	TLO	T2,(XC.USR)	    ;MAKE SURE USER MODE IS ON
	HLLM	T2,.JDAT+JOBPD1##   ;REMEMBER IT
	IOR	T1,T2		;ONE WORD OLD PC WITH FLAGS AND SECTION NUMBER
	POP	P,T2		;RESTORE AN AC
	PJRST	PUTWDU##	;STORE OLD PC AND RETURN
;ROUTINE TO PRINT "SWAP READ ERROR"
;CALLED FROM SWAPPER AT CLOCK LEVEL (USUALLY)
;CALL:	MOVE J,JOB NUMBER
;	PUSHJ P,ERRSWP
;	ALWAYS RETURN TO SWAPPER


ERRSWP::PUSHJ	P,SVEUB##	;LOAD UBR
	MOVSI	T1,JERR		;SET JERR SO WE DO NOT
	IORM	T1,JBTSTS##(J)	;TRY TO INTERCEPT
	AOS	T1,SWETOT##	;COUNT ANOTHER ERROR
	CAMG	T1,SWEECT##	;OVER THE THRESHOLD?
	JRST	ERRSW1		;NO
	PUSH	P,U		;SAVE U
	MOVE	U,OPRLDB##	;WHERE TO TYPE MESSAGE
	PUSHJ	P,INLMES##	;PRINT SOME WARNING ON CTY
	ASCIZ	/
?Swap read error for job/
	PUSHJ	P,PRJBNM	;PRINT THE INFO
	PUSHJ	P,CRLF##	;END THE LINE
	POP	P,U		;RESTORE U
ERRSW1:	JSP	T1,ERRPNT	;PRINT MESSAGE
	ASCIZ	/Swap read error/
	PJRST	PCSTOP		;START TTY AND SET JERR BIT SO
				; JOB CANNOT CONTINUE. PI 7 WILL NOT
				; BE REQUESTED SINCE SWAPPING JOB CANNOT
				; BE CURRENT JOB.
				;ERRPNT PUSHED TWO AC'S. PCSTOP REMOVES THEM

SUBTTL	COMMON ERROR MESSAGE ROUTINES

;COMMON ERROR MESSAGE SETUP ROUTINES
;CALL:	JSP T1,ERRPTU, ERRDEV, OR ERRPNT
;	ASCIZ /message/
;	RETURNS HERE WITH F SAVED 0(P)
;	C(F)=TTYDDB, U TO TTY OUTPUT BUFFER POINTER
;	J=JOB NUMBER, W=ADDR OF PDB

;USE ERRPTU IF AT UUO LEVEL FOR SURE
;ERRDEV IF ERROR FOR AN ASSIGNED DEVICE AT ANY LEVEL
;ERRPNT WITH J ALREADY SET TO OFFENDING JOB NUMBER
;THE JSP CALL IS USED IN CASE PUSHDOWN SPACE BECOMES CRITICAL
;AGAIN AND ERRPNT HAS TO WIPE EXISTING LIST OUT


ERRPTU::SKIPA	J,.CPJOB##	;BLAME CURRENT JOB IF NOT 0.
ERRDEV::LDB	J,PJOBN##	;JOB NO. FROM DEVICE DATA BLOCK
ERRPNT::PUSHJ	P,FNDPDB##	;FIND PDB FOR THIS JOB
	  HRRZ	W,JBTPDB##	;USE NULL JOB'S PDB
	SKIPN	J		;ERROR IN NULL JOB?
	SETOM	.CPNJE##	;YES, SET FLAG FOR ERROR IN NULL JOB
				; SO STATE OF NULL JOB WILL BE REESTABLISHED
				; WHEN IS IT RUN AGAIN(SEE CLOCK1)

	CAILE	J,JBTMAX##	;JOB NUMBER OR SEGMENT NUMBER
	STOPCD	.,STOP,SOR,	;++SEG OUT OF RANGE


	PUSH	P,U		;SAVE CALL TO ERROR(JSP U,ERROR)
	PUSH	P,F		;SAVE ADR. OF DEV. DATA BLOCK
	PUSH	P,T1		;SAVE RETURN FROM ERRPNT
	MOVE	T1,JBTSTS##(J)
	TDNE	T1,[JERR,,JS.ASA]
	JRST	ERRPT1
	PUSHJ	P,USREIJ##	;SIGNAL USER ERROR
	  JRST	ERRGOU

	MOVEI	T4,.EREIJ	;DOES THIS JOB WANT
	PUSHJ	P,CHKINT	; TRAP ALL ERRORS?
	  JRST	ERRPT1		;NO--BOMB HIM OUT
	JUMPGE	T3,ERRPT1	;JUMP IF HE WANTS MESSAGE
	MOVE	T2,M		;NO MESSAGE
	PUSHJ	P,DOINT		;PREPARE INTERCEPT
;***NEED TO STORE ERROR CODE***
	PJRST	QKUSXT		;BACK TO USER

ERRPT1:	PUSHJ	P,TTYERP##	;FIND TTY FOR THIS ERROR (VIA J)
	  PUSHJ	P,ERINDJ	;ERROR IN DETACHED JOB
	PUSHJ	P,INLMES##
	ASCIZ	/?
/
	PUSHJ	P,PRQM##	;PRINT QUESTION MARK ON NEXT LINE
				; FOR BATCH AND SCRIPT
	PJRST	INLMES##	;PRINT MESSAGE SPECIFIED BY CALLER
				; AND RETURN TO LOC. AFTER MESSAGE

ERINDJ::JUMPE	J,ERINNJ	;JUMP IF NULL JOB
	PUSHJ	P,INLMES##	;PRINT ERROR MESSAGE
	ASCIZ	/?Error in detached job/
	PUSHJ	P,PRJBNM	;PRINT JOB # AND PROGRAM NAME
	PJRST	CRLF##		;PRINT <CRLF> AND RETURN
ERINNJ:	PUSHJ	P,INLMESS##	;PRINT ERROR MESSAGE
	ASCIZ	/?Error in job 0 (null job)
/
	POPJ	P,
;ROUTINE TO PRINT UUO PC AND STOP JOB
;IF IN USER MODE PC WILL PRINT AS "AT USER LOC XXX"
;IF IN EXEC MODE "AT EXEC LOC XXX; EXEC CALLED FORM EXEC/USER/ LOC YYY


UUOMES:	PUSHJ	P,CONMES##	;PRINT MESSAGE POINTED TO BY T1
UUOPCP::DMOVE	T1,.JDAT+JOBPD1## ;UUO PC STORED IN JOB DATA AREA
				; FIRST LOC ON PD LIST
	SOJA	T2,DPCPNT	;DECREMENT TO POINT TO UUO IN USER AREA


;ROUTINE TO PRINT ONE OF THREE MESSAGES AND STOP JOB
;1) "AT EXEC LOC XXX; EXEC CALLED FROM EXEC LOC YYY"
;2) "AT EXEC LOC XXX; EXEC CALLED FORM USER LOC YYY"
;3) "AT USER LOC YYY"

;CALL:	MOVE T2, XXX		;WITH PC FLAGS IN LH
;	PUSHJ P,PCPNT
;	NEVER RETURN IF AT UUO LEVEL


PCPNT:	TLNE	T2,USRMOD	;MAKE SURE CONTROL-T
	MOVEM	T2,JBTPC##(J)	; GIVES CORRECT ANSWER
	PUSHJ	P,PCP		;PRINT " AT EXEC XXX" OR " AT USER "
	TLNE	T2,USRMOD	;WAS PC IN USER MODE?
	JRST	PCSTOP		;YES, ENOUGH INFO.
	JRST	EXCALP		;NO, GIVE UUO INFO

;SAME AS PCPNT EXCEPT PRINTS A DOUBLE WORD PC IN T1 AND T2
DPCPNT:	TLNE	T1,USRMOD	;MAKE SURE CONTROL-T
	MOVEM	T2,JBTPC##(J)	; GIVES CORRECT ANSWER
	PUSH	P,T1		;DPCP WIPES T1
	PUSHJ	P,DPCP		;PRINT " AT EXEC XXX" OR " AT USER "
	POP	P,T1		;GET FLAGS BACK
	TLNE	T1,USRMOD	;WAS PC IN USER MODE?
	JRST	PCSTOP		;YES, ENOUGH INFO.
;ROUTINE TO PRINT "; UUO AT [EXEC or USER] PC XXXXXX" AND STOP JOB
;CALL:	PUSHJ P,EXCALP
;	NEVER RETURNS IF AT UUO LEVEL
EXCALP:	PUSHJ	P,INLMES##
	ASCIZ	/; UUO/
	DMOVE	T1,.JDAT+JOBPD1##	;UUO PC IN JOB DATA AREA
	SUBI	T2,1		;BACK IT UP TO POINT TO UUO
	PUSHJ	P,DPCP		;PRINT "EXEC LOC " OF USER LOC
PCSTOP::PUSH	P,U
	JUMPN	J,PCSTP5	;NULL JOB?
	PUSHJ	P,TTYERP	;YES--FIND THE OPR
	  JRST	PCSTP6		;WE HAVE A VALID LINE
	STOPCD	.,STOP,NJT,	;NULL JOB HAS TTY
PCSTP5:	PUSHJ	P,TTYSRC##	;SET TTY
	STOPCD	.,STOP,LN1,	;NONE?!
	JUMPE	U,PCSTP2	;IS IT DETACHED?
PCSTP6:	SKIPE	T1,F		;SKIP IF NO DDB
	LDB	T1,PJOBN##	;GET JOB #
	CAMN	T1,J		;IS THIS THE TTY OF THE LOOSER
	PUSHJ	P,TSETBI##	;CLEAR TYPE-AHEAD
PCSTP2:
	MOVE	T1,JBTSTS##(J)	;GET JOB STATUS
	TDNE	T1,[JERR,,JS.ASA]	;CAN WE INTERCEPT
	JRST	PCSTP1		;NO--STOP JOB

	PUSHJ	P,PSIERR##
	  JRST	PCSTP4		;AT CLOCK LEVEL, CATCH IT AT CIPXIT
	  JRST	ERRGOU		;AT UUO LEVEL, CATCH IT AT USRXIT

	MOVEI	T4,.EREIJ	;DOES THIS JOB WANT
	CAMN	J,.CPJOB##	;CANT INTERCEPT IF ON CLOCK LEVEL
	PUSHJ	P,CHKINT	; TRAP ALL ERRORS?
	  JRST	PCSTP1
	PUSHJ	P,DOINT1	;PREPARE INTERCEPT
	PJRST	QKUSXT		;BACK TO USER

PCSTP1:	JUMPN	U,PCSTP3	;IS JOB DET'D
	POP	P,U
	PUSHJ	P,CRLF##	;YES,
	PUSHJ	P,ESTOP##	;STOP JOB
	JRST	ECONT		;RESUME FLOW
PCSTP3:	PUSHJ	P,HOLD##	;STOP JOB SET ERROR BIT
PCSTP4:	POP	P,U
;HERE TO CONTINUE AFTER ERROR (IF AT PI LEVEL OR USER TYPES CONT)
ECONT:	POP	P,F		;RETURN ONLY IF AT INTERRUPT LEVEL
	JRST	TPOPJ##		;REMOVE ERROR CALL AND RETURN
				;ALTHOUGH U WAS PUSHED, POP INTO T1, PERSERVE LINE NUMBER
;ROUTINE TO PRINT PC AS:
;1) "EXEC PC XXX" OR "USER PC XXX"
;CALL:	MOVE T2,PC TO PRINT(LH=PC FLAGS)
;	PUSHJ P,PCP


XMODE:	ASCIZ	/ at exec PC /
UMODE:	ASCIZ	/ at user PC /

PCP::	MOVEI	T1,XMODE	;ASSUME PC IN EXEC MODE
	TLNE	T2,USRMOD	;IS IT?
PCPU:	MOVEI	T1,UMODE	;NO, USER MODE
	PUSHJ	P,CONMES##	;PRINT ONE OR OTHER
	HRRZ	T1,T2		;PRINT RIGHT HALF IN OCTAL
	PJRST	OCTPNT##	; FALL INTO OCTPNT

;ROUTINE TO PRINT A DOUBLE WORD PC
;CALL:	MOVEI	U,LDB
;	DMOVE	T1,[EXP FLAGS,PC]
;	PUSHJ	P,DPCP

DPCP::	TLNN	T1,(XC.USR)	;PC IN USER MODE?
	SKIPA	T1,[XMODE]	;NO, TYPE AT EXEC MUMBLE
	MOVEI	T1,UMODE	;YES, TYPE AT USER MUMBLE
	PUSHJ	P,CONMES##	;TYPE IT
UDPCP::	HRRZ	T1,T2		;ONLY EIGHTEEN BITS IF NOT AN XADR
	TLNN	T2,(SECMSK)	;NON-ZERO SECTION?
	PJRST	OCTPNT##	;NO, PRINT IT IN THE TRADITIONAL WAY
	PUSH	P,T1		;SAVE LOW EIGHTEEN BITS
	HLRZ	T1,T2		;SECTION NUMBER
	PUSHJ	P,PRTDI8##	;PRINT THAT
	MOVEI	T1,[ASCIZ /,,/]	;ZERO SUPPRESSED OCTAL PAIRS
	PUSHJ	P,CONMES##	;PRINT SEPERATER
	POP	P,T1		;LOW EIGHTEEN BITS OF PC
	PJRST	OCTPNT##	;FINALLY PRINT THAT
;ROUTINE TO PRINT "DEVICE XXX"
;CALL	MOVE U,ASCII OUTPUT BYTE POINTER
;	PUSH P,F
;	PUSHJ P,ERNAM


ERNAM::	PUSHJ	P,INLMES##
	ASCIZ	/device /
	SKIPN	T2,-1(P)	;IS F = 0?
	PJRST	PRNAM1##	;YES, MESSAGE WITHOUT NAME (PRINT A SPACE)
	HRRZ	T1,DEVSER(T2)	;IS THIS A DISK?
	CAIE	T1,DSKDSP##
	JRST	ERNAM1		;NOT DISK, GET PHYSICAL DEVICE NAME
	SKIPN	T1,DEVUNI##(T2)	;GET CURRENT UNIT DATA BLOCK ADDRESS
	SKIPE	T1,DEVFUN##(T2)	;IF UNIT REMOVED, GET SAVED ADDRESS
	SKIPA	T2,UDBNAM(T1)	;GET PHYSICAL UNIT NAME AND SKIP TO PRNAM1
ERNAM1:	MOVE	T2,DEVNAM(T2)	;NO, GET DEVICE NAME
	PJRST	PRNAME##	;FALL INTO PRNAME
	SUBTTL	THE END

	LIT

ERREND:	PRGEND
TITLE	CRSINI - WRITE CRASH FILE ENTRIES FOR DAEMON - V001
SUBTTL	CRSINI -- RCB/	29-DEC-89
	SEARCH	F,S,DEVPRM
	$RELOC
	$HIGH

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
; COPYRIGHT (C) 1989,1990 BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
XP VCRSIN,001		;PUT VERSION NUMBER IN GLOB AND LOADER MAP
	ENTRY	CRSINI
	$LOW
CRSFIL::BLOCK	7+3		;SPACE FOR SYSINI TO COPY FROM BOOT
CRSRLD::BLOCK	1		;SPACE FOR A SEB FROM SYSRLD
CRSAVL::BLOCK	1		;SPACE FOR A SEB FROM SYSAVL
	$HIGH			;BACK TO PURE CODE

;I KNOW THIS ISN'T KOSHER, BUT....
BLKSIZ==:200			;AGREES WITH COMMOD, WHICH OUGHT TO BE A .UNV
W2BLSH==-7			;LSH VALUE TO CONVERT #WORDS TO #BLOCKS
B2WLSH==-W2BLSH			;LSH VALUE TO CONVERT #BLOCKS TO #WORDS

CRSINI::SETZ	T1,		;NO DATA WORDS NEEDED
	PUSHJ	P,EXPALC##	;GET AN EXEC COMMAND BLOCK
	 STOPCD	CPOPJ##,INFO,CRSIAF,	;++CRSINI ALLOCATION FAILURE
	MOVE	T2,['CRSINI']	;WHO WE ARE
	MOVEM	T2,.EPNAM##(T1)	;SAVE IN THE BLOCK
	XMOVEI	T2,CRSINU	;ADDRESS OF OUR UUO-LEVEL ROUTINE
	MOVEM	T2,.EPULA##(T1)	;SAVE FOR CLOCK1
	PJRST	EXPQUE##	;QUEUE UP THE .EXEC REQUEST AND RETURN

;MACRO TO ALLOCATE STORAGE IN THE FUNNY PAGE WE USE FOR SCRATCH SPACE
%%X==.FPMC			;WHERE ALLOCATION STARTS
DEFINE	X(NAM,LEN<1>),<
	IFNB<NAM>,<NAM=%%X>
	%%X==%%X+<LEN>
>

X	DATBEG,0		;WHERE OUR DATA BEGINS
X	DSKLEN			;SIZE OF CRASH FILE FOR REDDSK
X	PHYFLG			;FLAG FOR PEKDSK TO DO PHYSICAL CORE
X	CURBLK			;CURRENT FILE PAGE IN DSKBUF
X	GTBSTA			;START OF OUR COPY OF NUMTAB
X	GTBLIM			;MAX. OFFSET INTO COPIED NUMTAB
X	RNGTBB			;WHERE TO STORE RNGTAB BASE
X	%VMPPB			;WHERE TO STORE .FPPP
X	%VMPPE			;WHERE TO STORE .LPPP
X	%CNPDB			;SPACE TO STORE CRASH ADDRESS OF JBTPDB
X	%CNDVN			;CRASH VALUE OF CNFDVN
X	%FTERR			;.GTFET ENTRY FROM CRASH
X	%CNBCP			;BOOTCP FROM CRASH
X	%CCTOS			;ADDRESS OF EPT// .EPSTB POINTER
X	EPTADR			;ADDRESS OF EPT
X	EMPADR			;CRASH ADDRESS OF EXEC SECTION 0/1 MAP
X	EMPPAG			;ITS PAGE NUMBER
X	%CNSJN			;JBTMXL FROM CRASH
X	%LDSEB			;NEXT SYSTEM ERROR BLOCK TO PROCESS
X	CURSEB			;WHERE WE'RE STORING
X	%SYERR			;SYSTEM ERROR COUNT
X	CRSINF,CRSGTL		;A BLOCK OF CRASH INFORMATION
X	LSTSTP			;LAST SUBTABLE POINTER
X	LSTSTV			;LAST SUBTABLE VALUE
X	DATEND,0		;END OF OUR INITIAL CORE BLOCK

DATLEN==DATEND-DATBEG		;HOW MUCH DATA WE NEED TO ALLOCATE

CRSINU:	PUSHJ	P,SAVE4##	;PRESERVE FOR CLOCK1
	PUSHJ	P,SETASA##	;MAKE MONITOR UUOS EASY IN THIS JOB
	MOVEI	T2,DATLEN	;A RANDOM AMOUNT OF CORE
	SKIPE	CRSFIL		;IF NO SAVED CRASH SPEC, SKIP THE OVERHEAD
	PUSHJ	P,GTFWDC##	;GET SOME FUNNY SPACE
	  JRST	CRSINX		;PUNT IF CAN'T GET IT
	CAIE	T1,.FPMC	;BETTER BE THE FIRST FOR THIS JOB
	JRST	CRSINX		;PUNT IF NOT
	MOVE	T1,CRSFIL	;GET THE DEVICE TO USE
	MOVEM	T1,.JDAT+1	;SAVE
	SETZM	.JDAT+2		;NO BUFFERS
	MOVE	T1,[1B0!17]	;DUMP MODE, PHYSICAL DEVICE
	MOVEM	T1,.JDAT	;SET FOR MODE
	OPEN	0,0		;TRY TO GET A CHANNEL POINTING TO IT
	  JRST	CRSINX		;NO CAN DO
	MOVSI	T1,CRSFIL+3	;POINT TO THE PATH BLOCK FROM BOOT
	HRRI	T1,.JDAT+146	;AND TO THE ONE WE'LL USE
	BLT	T1,.JDAT+146+6	;COPY THE PATH
	DMOVE	T1,CRSFIL+1	;GET FILE+EXT
	DMOVEM	T1,.JDAT+140	;SET IN PSEUDO-RIB
	MOVEI	T1,144		;POINT TO PATH BLOCK HEADER IN USER CORE
	MOVEM	T1,.JDAT+143	;SAVE IN OLD-FORMAT POINTER WORD
	LOOKUP	0,140		;TRY TO FIND THE FILE
	  JRST	CRSINX		;DIDN'T WORK
	HLRE	T1,.JDAT+143	;GET SIZE OF FILE
	SKIPL	T1		;IF POSITIVE,
	ASH	T1,B2WLSH	;CONVERT BLOCKS TO WORDS
	MOVMM	T1,DSKLEN	;SAVE FOR CONSISTENCY CHECKING
NDPAGS==2			;.EXEDIR+DATA
DSKBUF==NDPAGS*PAGSIZ-PAGSIZ	;USER CORE ADDRESS OF OUR PAGE BUFFER
	MOVEI	T1,NDPAGS*PAGSIZ-1 ;MINIMUM ACCEPTABLE .JBREL VALUE
	MOVEM	T1,.JDAT	;SAVE FOR UUO
	CALLI	0,200011	;PHYSICAL-ONLY CORE UUO
	  JRST	CRSINX		;PUNT IF CAN'T DO IT
	MOVSI	T1,-BLKSIZ	;IOWD LH IS SIZE OF A DISK BLOCK
	HRRI	T1,.JBDA##-1	;STARTING AT .JBDA
	MOVEM	T1,.JDAT	;SAVE IN THE AC
	SETZM	.JDAT+1		;TERMINATE THE I/O LIST
	IN	0,0		;READ A BLOCK FROM THE .EXE FILE
	 TRNA			;SKIP OVER THE ERROR
	  JRST	CRSINX		;PUNT IF CAN'T DO IT
	HLRZ	T1,.JDAT+.JBDA## ;GET START OF DIR. ENTRY
	HRRZ	T2,.JDAT+.JBDA## ;AND ITS LENGTH
	CAIN	T1,SV.DIR	;IS IT AN .EXE DIRECTORY?
	CAIL	T2,BLKSIZ	;AND SMALL ENOUGH FOR US?
	JRST	CRSINX		;PUNT IF BAD FORMAT
	USETI	0,PAGSIZ/BLKSIZ+1 ;SET TO READ DUMP JOBDAT
	MOVSI	T1,-BLKSIZ	;(WE KNOW HOW BOOT WORKS)
	HRRI	T1,.JBDA##+BLKSIZ-1 ;STARTING AFTER THE .EXE DIRECTORY
	MOVEM	T1,.JDAT	;SET FOR THE UUO
	IN	0,0		;READ THE PAGE
	 TRNA			;SKIP OVER THE ERROR
	  JRST	CRSINX		;PUNT IF CAN'T
	SKIPN	.JDAT+.JBDA##+BLKSIZ+116 ;IS IT AN UNPROCESSED DUMP?
	JRST	CRSINX		;NO--GET OUT WHILE THE GETTING'S GOOD
	SETOM	PHYFLG		;YES--TELL PEKDSK WE'RE NOT SET UP YET
	SETOM	CURBLK		;MAKE SURE TO READ THE FILE
	MOVEI	T1,ABSTAB##	;LOCATION TO READ
	PUSHJ	P,PEKDSK	;DO IT
	  JRST	CRSINQ		;PUNT IF CAN'T
	TLNN	T1,-1		;MUST BE IN SECTION 0
	CAIG	T1,410		;AND ABOVE ABSTAB ITSELF
	JRST	CRSINX		;NOT A MONITOR DUMP
	MOVEM	T1,GTBSTA	;SAVE PRESUMED START OF NUMTAB
	ADDI	T1,23		;POINT TO .GTSLF
	PUSHJ	P,PEKDSK	;FETCH IT
	  JRST	CRSINQ		;PUNT IF I/O FAILURE
	HRRZ	T2,T1		;ISOLATE ADDRESS PORTION
	CAME	T2,GTBSTA	;DOES IT MATCH?
	JRST	CRSINX		;NO--NOT A CRASH FILE
	LSH	T1,-^D27	;YES--ISOLATE MAXIMUM OFFSET
	CAIL	T1,PAGSIZ	;IF IT DOESN'T FIT OUR LIMITS,
	MOVEI	T1,PAGSIZ-1	;MAKE IT FIT
	MOVEM	T1,GTBLIM	;SAVE SO WE KNOW OUR LIMITS
	MOVSI	P1,1(T1)	;GET +VE LENGTH OF TABLE TO FILL
	MOVNS	P1		;MAKE -VE LENGTH,,0
	MOVEI	T2,1(T1)	;GET SIZE OF TABLE WE WANT TO FILL
	PUSHJ	P,GTFWDC##	;GRAB SOME CORE
	  JRST	CRSINQ		;PUNT IF CAN'T
	MOVE	P2,T1		;COPY THE TABLE ADDRESS
	MOVE	P3,T1		;GET ANOTHER COPY TO USE FOR STORING
CRSGT0:	HRRZ	T1,P1		;WHICH ENTRY
	ADD	T1,GTBSTA	;OFFSET INTO CRASH'S NUMTAB
	PUSHJ	P,PEKDSK	;READ IT
	  JRST	CRSINQ		;PUNT
	MOVEM	T1,(P3)		;SAVE IN NUMTAB TABLE
	AOJ	P3,		;UPDATE STORAGE POINTER
	AOBJN	P1,CRSGT0	;LOOP OVER ALL ENTRIES
	HRLI	P2,(IFIW (P3))	;MAKE IT EASY FOR GTBDSK TO FETCH
	MOVEM	P2,GTBSTA	;SAVE START OF OUR GETTAB STORAGE
.GTIDX==154			;INDEX OF THE RANGE TABLE
	MOVE	T1,GTBLIM	;GET LIMIT WORD AGAIN
	CAIGE	T1,.GTIDX	;BETTER BE BIG ENOUGH
	JRST	CRSINQ		;PUNT
	HRRZ	T1,.GTIDX(P2)	;YES--GET ADDRESS OF RNGTAB
	MOVEM	T1,RNGTBB	;SAVE IT
	MOVE	T1,[32,,113]	;%VMPPB -- GET .FPPP
	PUSHJ	P,GTBDSK	;FROM THE DISK
	  JRST	CRSINQ		;PUNT ON ERROR
	MOVEM	T1,%VMPPB	;SAVE IT AWAY
	MOVE	T1,[33,,113]	;ARG TO GET .LPPP
	PUSHJ	P,GTBDSK	;FETCH FROM THE CRASH FILE
	  JRST	CRSINQ		;PUNT
	MOVEM	T1,%VMPPE	;SAVE IT AWAY
	HRRZ	T1,162(P2)	;BASE ADDRESS FROM .GTPDB
	MOVEM	T1,%CNPDB	;SAVE FOR GETTAB SIMULATION
	MOVE	T1,[71,,11]	;GETTAB ARGUMENT
	PUSHJ	P,GTBDSK	;READ IT
	  JRST	CRSINQ		;PUNT
	MOVEM	T1,%CNDVN	;SAVE IT
	MOVE	T1,[4,,71]	;GETTAB ARGUMENT
	PUSHJ	P,GTBDSK	;READ IT
	  JRST	CRSINQ		;PUNT
	MOVEM	T1,%FTERR	;SAVE IT
F%KS10==1B21			;BIT WE'LL WANT LATER
	MOVE	T1,[137,,11]	;UUO ARG
	PUSHJ	P,GTBDSK	;READ IT
	  SETZ	T1,		;FOO
	MOVEM	T1,%CNBCP	;SAVE IT
	LSH	T1,1		;OFFSET FOR PER-CPU TABLES
	ADD	T1,[3,,55]	;UUO ARG FOR EPT ADDRESS
	PUSHJ	P,GTBDSK	;READ IT
	  JRST	CRSINQ		;PUNT
	MOVEM	T1,%CCTOS	;SAVE FOR NOW
	PUSHJ	P,PEKDSK	;GET THAT PAGE INTO CORE
	  JRST	CRSINQ		;PUNT IF I/O ERROR
	MOVEI	T2,2*PAGSIZ	;WE NEED SOME CORE
	PUSHJ	P,GTFWDC##	;GRAB IT
	  JRST	CRSINQ		;SIGH
	MOVEM	T1,EPTADR	;SAVE ITS ADDRESS
	MOVE	T2,T1		;COPY THE ADDRESS
	HRLI	T2,DSKBUF	;WHERE OUR I/O HAPPENS
	EXCTUX	<BLT T2,PAGSIZ-1(T1)> ;COPY TO MONITOR PAGE
	MOVE	T1,SECTAB(T1)	;FETCH THE SECTION 0/1 SECTION MAP ENTRY
	LDB	T2,[POINT 3,T1,2] ;GET THE POINTER TYPE
	CAIE	T2,PM.DCD	;DIRECT?
	JRST	CRSINQ		;NO--PUNT
	ANDI	T1,-1		;YES--ISOLATE PAGE NUMBER
	MOVEM	T1,EMPPAG	;SAVE FOR VIRTUAL PEKDSK
	LSH	T1,P2WLSH	;CONVERT TO ADDRESS
	PUSHJ	P,PEKDSK	;GET THAT PAGE INTO CORE
	  JRST	CRSINQ		;PUNT ON I/O ERROR
	MOVE	T1,EPTADR	;GET ADDRESS OF OUR CORE BLOCK
	ADDI	T1,PAGSIZ	;WHERE THE SECTION MAP WILL GO
	MOVEM	T1,EMPADR	;SAVE FOR LATER
	MOVE	T2,T1		;COPY POINTER
	HRLI	T2,DSKBUF	;SOURCE ADDRESS IS OUR I/O BLOCK
	EXCTUX	<BLT T2,PAGSIZ-1(T1)> ;COPY INTO MONITOR PAGE
	MOVSI	T1,(IFIW (T1))	;INDIRECTION CONVENIENCE
	HLLM	T1,EMPADR	;SAVE FOR FETCHING MAP ENTRIES
	HRRI	T1,SECTAB	;OFFSET FOR SECTION MAP FETCHING
	ADD	T1,EPTADR	;FROM OUR VIRTUAL PAGE
	MOVEM	T1,%CCTOS	;RECYCLE THIS WORD FOR SECTION MAPPING
	MOVE	T1,[15,,11]	;UUO ARG FOR -SEGN,,JOBN
	PUSHJ	P,GTBDSK	;FETCH IT
	  JRST	CRSINQ		;PUNT
	HLRE	T2,T1		;GET -SEGN IN FULLWORD
	SUBI	T2,-1(T1)	;MAKE -(SEGN+JOBN-1)
	MOVNM	T2,%CNSJN	;SAVE JBTMXL FOR GETTAB SIMULATION
	SETZM	PHYFLG		;PEKDSK WILL NOW DO VIRTUAL MAPPING
	MOVE	T1,[167,,11]	;GETTAB ARGUMENT FOR %CNDAE
	PUSHJ	P,GTBDSK	;FETCH IT
	  SETZ	T1,		;FOO
	CAME	T1,CNFDAE##	;CAN WE DEAL WITH IT?
	STOPCD	CRSINQ,INFO,OLDMON,PRTDDB##, ;++OLD MONITOR FOUND IN CRASH FILE
	MOVE	T1,[140,,16]	;GETTAB ARGUMENT FOR LIST HEADER
	PUSHJ	P,GTBDSK	;READ IT
	  JRST	CRSINQ		;PUNT
	JUMPE	T1,RSEBLE	;SKIP THIS IF NO BLOCKS
	JRST	RSEBL2		;YES--FIND THE FIRST ENTRY
RSEBL0:	MOVEM	T1,%LDSEB	;SAVE IT AWAY
	ADDI	T1,.EBTYP	;OFFSET TO LENGTH WORD
	PUSHJ	P,PEKDSK	;READ IT
	  JRST	CRSINQ		;PUNT
	ANDI	T1,777		;ISOLATE ENTRY LENGTH
	MOVEI	T2,.EBHDR(T1)	;GET REAL BLOCK LENGTH IN PROPER AC
	MOVEI	P2,-1(T2)	;KEEP A COPY (OFFSET)
	PUSHJ	P,GETWDS##	;ALLOCATE A NEW SEB
	  JRST	CRSINQ		;PUNT IF NO CORE
	MOVEM	T1,CURSEB	;SAVE THE ADDRESS
	MOVE	P3,T1		;COPY IT
	MOVE	P4,%LDSEB	;AND COPY THE CRASH FILE'S ADDRESS
RSEBL1:	AOS	T1,P4		;GET NEXT CRASH ADDRESS TO COPY
	PUSHJ	P,PEKDSK	;READ THE WORD
	  JRST	CRSINQ		;PUNT
	MOVEM	T1,1(P3)	;SAVE IN OUR COPY
	SOSLE	P2		;IF NOT DONE COPYING,
	AOJA	P3,RSEBL1	;LOOP
	MOVE	T1,CURSEB	;GET OUR ADDRESS AGAIN
	MOVSI	T2,EH.CRS	;THIS ENTRY IS FROM A CRASH
	IORM	T2,.EBTYP(T1)	;SO FLAG IT THAT WAY
	PUSHJ	P,QUESEB##	;HAND THIS ENTRY OFF TO DAEMON
	MOVE	T1,%LDSEB	;GET ADDRESS OF LINK WORD
RSEBL2:	PUSHJ	P,PEKDSK	;ADVANCE THE LIST POINTER
	  JRST	CRSINQ		;PUNT IF I/O ERROR
	JUMPN	T1,RSEBL0	;LOOP OVER ALL SE BLOCKS IN THE CRASH
RSEBLE:
	MOVEI	T1,<0,,51>	;%SYERR INDEX
	PUSHJ	P,GTBDSK	;FETCH ERROR COUNT
	  JRST	CRSINQ		;PUNT
	MOVEM	T1,%SYERR	;SAVE
	MOVE	P1,CRSGTB	;GET POINTER TO TABLE OF GETTABS
	MOVEI	P2,CRSINF	;POINT TO OUR STORAGE
	SETZM	LSTSTP		;NO LAST SUBTABLE
	PUSHJ	P,CRSDMP	;DUMP THE STUFF
	SKIPGE	P1,CRSGT1	;IF ANY CUSTOMER ENTRIES,
	PUSHJ	P,CRSDMP	;DUMP THESE AS WELL
	SETZ	T1,		;NO BLOCK YET ALLOCATED
	XMOVEI	T2,CRSTBL	;POINT TO OUR XFER TABLE
	PUSHJ	P,XFRSEB##	;DO THE BLOCK
	  JRST	CRSINQ		;SIGH--NO CORE
	PUSHJ	P,DMPDSK	;DUMP THE DISK STATS
IFN FTKS10,<
	PUSHJ	P,DMPHSB	;DUMP HALT STATUS BLOCK IF CRASH WAS ON A KS
>
	PJRST	CRSINQ		;GO FINISH UP
;ROUTINE TO DUMP RANDOM DISK ENTRIES

DSCNBK==<PG.BDY-.EBHDR-1>/<ZUSCL-XUSCL+1> ;NUMBER OF UNITS THAT FIT IN ONE BLOCK
DSCNEN==^D250/DSCNBK		;LIMIT THE NUMBER OF UNITS TO 250 IN CASE OF
				; LOOPS IN THE UDB CHAIN

DMPDSK:	MOVEI	P3,DSCNEN	;GET MAXIMUM NUMBER OF ENTRIES TO DUMP
	MOVE	T1,[7,,16]	;%LDUNI
	PUSHJ	P,GTBDSK	;GET POINTER TO UDB CHAIN
	  POPJ	P,		;FORGET IT
	HLRZ	P2,T1		;GET ADDRESS WHERE IT BELONGS
	JUMPE	P2,CPOPJ##	;DONE IF NO UNITS
DMPDS1:	MOVSI	P1,-DSCNBK	;AOBJN POINTER FOR NUMBER OF BLOCKS PER ENTRY
	XMOVEI	P4,CRSINF	;WHERE TO STORE
DMPDS2:	MOVE	T2,XUSCL	;GET AOBJN POINTER OF WORDS IN BLOCK
	HLLZ	T1,T2		;COPY -WORDS,,0
	PUSH	P4,T1		;STORE IT
	PUSHJ	P,UNIDMP	;DUMP UNIT WORDS FOR THIS BLOCK
	MOVEI	T1,UNISYS(P2)	;POINT TO LINK WORD
	PUSHJ	P,PEKDSK	;FETCH IT
	  SETZ	T1,		;ASSUME DONE
	HLRZ	P2,T1		;PUT IT WHERE IT BELONGS
	AOBJP	P1,DMPDS3	;FINISH ENTRY IF FULL
	JUMPN	P2,DMPDS2	;LOOP IF HAVE ANOTHER UNIT
DMPDS3:	MOVEI	P1,(P1)		;ISOLATE NUMBER DONE IN THIS ENTRY
	MOVSI	P4,(P1)		;COPY AS LEN,,0
	MOVNS	P4		;MAKE -COUNT,,0
	HRRI	P4,1		;INCLUDE OFFSET
	IMULI	P1,ZUSCL-XUSCL+1 ;CHANGE FROM COUNT TO LENGTH
	MOVEI	T1,1(P1)	;MAKE TOTAL DATA LENGTH OF ENTRY
	PUSHJ	P,ALCSEB##	;GET A SYSTEM ERROR BLOCK
	  POPJ	P,		;NO CORE--PUNT
	MOVEM	P4,.EBHDR(T1)	;(R00) SUB-POINTER
	MOVSI	P4,.ERDSC_9!EH.CRS ;DISK STATISTICS FROM A CRASH
	HLLM	P4,.EBTYP(T1)	;SETUP THE ENTRY
	MOVSI	P4,CRSINF	;SOURCE OF DATA
	HRRI	P4,.EBHDR+1(T1)	;WHERE TO STORE IT
	ADDI	P1,(T1)		;GET OFF-BY-HEADER ENDING ADDRESS
	BLT	P4,.EBHDR(P1)	;MOVE THE DATA
	PUSHJ	P,QUESEB##	;GIVE THIS BLOCK TO DAEMON
	SOSLE	P3		;QUIT IF DUMPED TOO MANY
	JUMPN	P2,DMPDS2	;ELSE LOOP IF MORE BLOCKS
	POPJ	P,		;DONE

;SUBROUTINE TO DUMP ITEMS FOR DMPDSK

UNIDMP:	MOVEI	T1,@(T2)	;GET ADDRESS TO DUMP
	PUSHJ	P,PEKDSK	;FETCH THE VALUE
	  SETZ	T1,		;SIGH
	PUSH	P4,T1		;STICK IT INTO THE DATA BUFFER
	AOBJN	T2,UNIDMP	;LOOP OVER ALL REQUESTED ENTRIES
	POPJ	P,		;DONE

;TABLE FOR VALUES TO DUMP

XUSCL:	.-ZUSCL,,.+1		;AOBJN WORD FOR TABLE WRITTEN BY DMPDSK
	Z	UDBNAM(P2)	;(R01) DEVICE NAME
	Z	UNIHID(P2)	;(R02) PACK ID
	Z	UNIHCT(P2)	;(R03) HARD ERROR COUNT
	Z	UNISCT(P2)	;(R04) SOFT ERROR COUNT
	Z	UNIPCT(P2)	;(R05) SEEK ERROR COUNT
	Z	UNIHNG(P2)	;(R06) HUNG COUNTS
	Z	UNIMCT(P2)	;(R07) SOFTWARE-DETECTED ERRORS
	Z	UNIBRC(P2)	;(R10) BUFFERED READS
	Z	UNIBWC(P2)	;(R11) BUFFERED WRITES
	Z	UNIDRC(P2)	;(R12) DUMP READS
	Z	UNIDWC(P2)	;(R13) DUMP WRITES
	Z	UNIMRC(P2)	;(R14) MONITOR READS
	Z	UNIMWC(P2)	;(R15) MONITOR WRITES
	Z	UNIICT(P2)	;(R16) SWAP READS
	Z	UNIOCT(P2)	;(R17) SWAP WRITES
	Z	UNIMSC(P2)	;(R20) MONITOR SEEKS
	Z	UNIUSC(P2)	;(R21) USER SEEKS
ZUSCL==.-1
;ROUTINE TO DUMP THE HALT STATUS BLOCK IF THE CRASH WAS ON A KS10

IFN FTKS10,<

DMPHSB:	MOVEI	T1,F%KS10	;GETTAB BIT FOR FTKS10
	TDNN	T1,%FTERR	;WAS THE DUMP ON A KS?
	POPJ	P,		;NO--DONE HERE
	MOVEI	T1,424		;YES--GET LOCATION OF HALT STATUS BLOCK
	PUSHJ	P,PEKDSK	;FETCH IT
	  POPJ	P,		;PUNT IF I/O ERROR
	JUMPE	T1,CPOPJ##	;DONE HERE IF NONE RECORDED
	SETZ	T1,		;GET HALT STATUS CODE
	PUSHJ	P,PEKDSK	;(LOC 0)
	  POPJ	P,		;PUNT ON I/O ERROR
	MOVEM	T1,CRSINF	;SAVE IT
	MOVEI	T1,1		;GET HALT PC
	PUSHJ	P,PEKDSK
	  POPJ	P,		;PUNT ON I/O ERROR
	MOVEM	T1,CRSINF+1
	MOVSI	P1,-22		;NUMBER OF WORDS WE STORE FROM HSB
	MOVEI	P2,CRSINF+2	;WHERE WE START STORING
DMPHS0:	MOVEI	T1,424(P1)	;ADDRESS OF NEXT WORD TO DUMP
	PUSHJ	P,PEKDSK	;FETCH IT
	  POPJ	P,		;PUNT ON I/O ERROR
	MOVEM	T1,(P2)		;SAVE IT AWAY
	AOJ	P2,		;ADVANCE STORAGE POINTER
	AOBJN	P1,DMPHS0	;LOOP OVER ALL THE WORDS WE WANT TO SAVE
	SETZ	T1,		;NO BLOCK ALLOCATED YET
	XMOVEI	T2,HSBTBL	;HALT STATUS BLOCK XFER TABLE
	PUSHJ	P,XFRSEB##	;GIVE THE INFO TO DAEMON
	  TRN			;NO CORE
	POPJ	P,		;DONE EXTRACTING THE HALT STATUS BLOCK

> ;END IFN FTKS10
;ROUTINE TO EXTRACT GETTAB ITEMS FROM A CRASH
;CALL:	MOVE	P1,AOBJN POINTER TO TABLE OF GETTABS
;	MOVEI	P2,START OF STORAGE SPACE
;	PUSHJ	P,CRSDMP
;RETURN:
;	CPOPJ	ALWAYS

CRSDMP:	MOVE	T1,(P1)		;FETCH NEXT GETTAB ARGUMENT
	TLNN	T1,-1		;IF LH IS 0, THIS IS A SUBTABLE
	JRST	CRSDM1		;HANDLE THAT DIFFERENTLY
	MOVE	P3,T1		;SAVE TABLE IN CASE OF FOLLOWING SUBTABLE
	PUSHJ	P,GTBDSK	;FETCH FROM THE DISK
	  MOVE	T1,[252525,,252525] ;FETCH FUNKY PATTERN FOR SPEAR
	JRST	CRSDM2		;GO HANDLE STORAGE AS COMMON WITH SUBTABLE CASE
CRSDM1:	MOVE	T3,P3		;COPY BASE TABLE
	MOVE	T2,T1		;MOVE SUBTABLE INDEX TO T2
	HRLI	T2,56		;.GTC0V--ONLY DO CPU0 'CAUSE SPEAR EXPECTS THAT
	PUSHJ	P,GSUBTB	;GET VALUE FROM SUBTABLE
	  MOVE	T1,[252525,,252525] ;FETCH FUNKY PATTERN FOR SPEAR
CRSDM2:	MOVEM	T1,(P2)		;SAVE DATUM IN MONITOR CORE
	AOJ	P2,		;ADVANCE STORAGE POINTER
	AOBJN	P1,CRSDMP	;LOOP OVER ENTIRE GETTAB ARG LIST
	POPJ	P,		;FINALLY DONE


;SUBROUTINE TO GET DATA FROM GETTAB SUB-TABLE
;ARGS	T3= GETTAB ARG FOR SUB-TABLE POINTER
;	T2= SUBTABLE ARG: TABLE# CONTAINING SUBTABLE,,ITEM #
;VALUE	T1= DESIRED ITEM
;SKIP RETURN IF ITEM DEFINED

GSUBTB:	PUSH	P,T3		;SAVE THAT ARG
	CAMN	T3,LSTSTP	;SAME SUBTABLE POINTER AS LAST TIME?
	JRST	[MOVE	T1,LSTSTV ;YES, GET LAST VALUE
		 JRST	GSUBT1]	  ;AND JOIN COMMON CODE
	MOVEM	T3,LSTSTP	;SAVE THIS SUBTABLE POINTER FOR NEXT TIME
	MOVE	T1,T3		;GET SUBTABLE POINTER
	PUSHJ	P,GTBDSK
	  JRST	GSUBTX		;TOO BAD, NO SUBTABLE
	MOVEM	T1,LSTSTV	;SAVE VALUE OF POINTER FOR QUICK CHECK
GSUBT1:	JUMPE	T1,GSUBTX	;NO SUBTABLE EXISTS
	LDB	T3,[POINT 9,T1,8] ;GET UPPER LIMIT ON SUBTABLE
	CAIGE	T3,0(T2)	;COMPARE DESIRED ITEM #
	JRST	GSUBTX		;OOPS, OFF THE END
	HRRZS	T1		;SUBTABLE POINTER IS AN ITEM NUMBER
	ADD	T1,T2		;WITH SUB-ITEM AND TABLE
	MOVSS	T1		;SWAP TO GETTAB FORM
	PUSHJ	P,GTBDSK	;GETTAB THAT
	  JRST	GSUBTX		;LOSE
	AOS	-1(P)		;WIN, TAKE SKIP RETURN
GSUBTX:	POP	P,T3		;RESTORE T3
	POPJ	P,
;THIS IS THE TABLE OF GETTAB ITEMS TO BE EXTRACTED FROM A CRASH.
;ADDITIONAL ITEMS SHOULD NOT BE ADDED HERE BY A SITE BECAUSE IT WILL
;CONFUSE SPEAR VERY BADLY. USE THE TABLE CRSGT1 INSTEAD.
;  ";***" INDICATES A SUBTABLE ITEM

CRSGTB:	XWD	.-CRSGTE,.+1	;PNTR FOR TABLE LENGTH
	10,,11	;%CNTIM		;(R3) TIME OF DAY
	12,,11	;%CNSIZ		;(R4) SYSTEM MEMORY SIZE
	41,,11	;%CNPOK		;(R5) LAST ADDR POKED
	54,,11	;%CNLNM		;(R6) # JOBS LOGGED IN
	44,,11	;%CNTIC		;(R7) #TICKS PER SECOND
	34,,11	;%CNVER		;(R10) MONITOR VERSION
	65,,11	;%CNDBG		;(R11) DEBUG STATUS WORD
	121,,11	;%CNHSO		;(R12) START OF MONITO HIGH SEG
	123,,11	;%CNNWC		;(R13) #OF WORDS OF CORE
	15,,12	;%NSUPT		;(R14) UPTIME IN TICKS
	23,,12	;%NSMMS		;(R15) MEMORY SIZE
	24,,12	;%NSTPE		;(R16) TOTAL MEM PAR ERRORS
	25,,12	;%NSSPE		;(R17) TOTAL SPURIOUS PARITY ERRORS
	26,,12	;%NSMPC		;(R20) MULTIPLE PARITY ERRORS
	27,,12	;%NSMPA		;(R21) LAST PARITY ADDR
	30,,12	;%NSMPW		;(R22) LAST PARITY WORD
	31,,12	;%NSMPP		;(R23) LAST PARITY PC
	32,,12	;%NSEPO		;(R24) # UNREC EXEC PDL OV
	33,,12	;%NSEPR		;(R25) # RECOVERED EXEC PDL OV
	5,,13	;%SWERC		;(R26) SWAP ERROR COUNT
	2,,51	;%SYDEL		;(R27) DISABLED HARDWARE ERROR COUNT
	15,,51	;%SYSCD		;(R30) LAST STOPCD
	4,,51	;%SYNDS		;(R31) # DEBUG STOPCDS
	5,,51	;%SYNJS		;(R32) # JOB STOPCDS
	7,,51	;%SYSJN		;(R33) LAST STOPCD-JOB NUMBER
	11,,51	;%SYSPN		;(R34) LAST STOPCD-PROGRAM NAME
	12,,51	;%SYSUU		;(R35) LAST STOPCD-UUO
	14,,51	;%SYSPP		;(R36) LAST STOPCD-P,PN
	12,,55	;%CCPAR		;(R37) PARITY SUBTABLE
	0	;%CVPLA		;(R40) **HIGHEST ADDR OF PARITY ERROR
	1	;%CVPMR		;(R41) **ADDRES IN SEGMENT OF PAR ERR
	2	;%CVPTS		;(R42) **PAR ERRORS THIS SWEEP
	3	;%CVPSC		;(R43) **#SWEEPS
	4	;%CVPUE		;(R44) **USER ENABLED
	5	;%CVPAA		;(R45) **LOGICAL AND  OF ADDR
	6	;%CVPAC		;(R46) **LOGICAL AND OF WORDS
	7	;%CVPOA		;(R47) **LOG OR OF ADDR
	10	;%CVPOC		;(R50) **LOG OR OF DATA
	11	;%CVPCS		;(R51) **COUNT OF SPUR CHANNEL ERROS
	13,,55	;%CCRSP		;(R52) ADDR OF RESPONSE SUBTABLE
	0	;%CVRSO		;(R53) **SUM TTY OUT UUO RES
	1	;%CVRNO		;(R54) **NUM TTY OUT UUO
	2	;%CVRHO		;(R55) **HI-SUM SQ TTY OUT UUO
	3	;%CVRLO		;(R56) **LO-SUM	"    "
	4	;%CVRSI		;(R57) **SUM TTY INP UUO
	5	;%CVRNI		;(R60) **NUMBER TTY INP UUO
	6	;%CVRHI		;(R61) **HI-SUM SQ TTY INP UUO
	7	;%CVRLI		;(R62) **LO-SUMSQ TTY INP UUO
	10	;%CVRSR		;(R63) **SUM QUANTUM REQ RES
	11	;%CVRNR		;(R64) **NUMBER QUANTUM REQ RES
	12	;%CVRHR		;(R65) **HI-SUM SQ QUANTUM RES
	13	;%CVRLR		;(R66) **LO-SUM SQ QUANTUM REQ RES
	14	;%CVRSX		;(R67) **SUM ONE OF ABOVE
	15	;%CVRNX		;(R70) **NUMBER ONE OF ABOVE
	16	;%CVRHX		;(R71) ** HI-SUM SQ ONE OF ABOVE
	17	;%CVRLX		;(R72) **LO-SUM SQ ONE OF ABOVE
	20	;%CVRSC		;(R73) **SUM CPU RES
	21	;%CVRNC		;(R74) **NUMBER CPU RES
	22	;%CVRHC		;(R75) **HI-SUM CPU RES
	23	;%CVRLC		;(R76) **LO-SUM CPU RES
	5,,56	;%CVUPT		;(R77) UPTIME
	12,,56	;%CVLST		;(R100) LOST TIME
	37,,56	;%CVNUL		;(R101) NULTIME
	42,,56	;%CVOHT		;(R102) OVERHEAD TIME IN JIFFIES
	46,,56	;%CVTUC		;(R103) TOTAL UUO COUNT
	47,,56	;%CVTJC		;(R104) TOTAL JOB CONTEXT SWITCH COUNT
	50,,56	;%CVTNE		;(R105) TOTAL NXM
	51,,56	;%CVSNE		;(R106) TOTAL SPUR NXM
	52,,56	;%CVNJA		;(R107) # JOBS AFFECTED LAST NXM
	53,,56	;%CVMNA		;(R110) FIRST ADDR LAST NXM
	CRSGTE==.-1		;END OF TABLE

CRSGT1:	XWD .-CRSGT2, .+1	;PNTR FOR TABLE TO BE DEFINED BY CUSTOMER
			;SPEAR WILL LIST TESE ITEMS IN OCTAL ONLY, IFF PRESENT

	CRSGT2==.-1

CRSGTL==<<CRSGT2-CRSGT1>+<CRSGTE-CRSGTB>> ;TOTAL STORAGE LENGTH IN CRSINF
IFL CRSGTL-<PG.BDY-.EBHDR>,<CRSGTL==PG.BDY-.EBHDR> ;FOR DMPDSK
;SEB TRANSFER TABLES FOR THINGS READ FROM THE CRASH

CRSTBL:	SEBTBL	(.ERCIN,CRSTBE,EX.CRS!EX.QUE)
	MOVE	CRSFIL+0	;(R00) DEVICE FROM CRASH
	MOVE	%SYERR		;(R01) SYSTEM-WIDE ERROR COUNT
	MOVE	[CRSGTB-CRSGTE,,1] ;(R02) SUB-POINTER
 ZZ==-1
 REPEAT <CRSGTE-CRSGTB>,<MOVE CRSINF+<ZZ==ZZ+1>> ;(R03-110) ;GETTAB ENTRIES
	SETZ			;(R111) NO LONGER PUT DISK STUFF HERE
 REPEAT <CRSGT2-CRSGT1>,<MOVE CRSINF+<ZZ==ZZ+1>> ;(R112+) CUSTOMER GETTABS
CRSTBE:!

;HERE FOR HALT STATUS BLOCK
IFN FTKS10,<
HSBTBL:	SEBTBL	(.ERHSB,HSBTBE,EX.CRS!EX.QUE)
	MOVE	CRSINF+0	;(R00) HALT REASON
	MOVE	CRSINF+1	;(R01) HALT PC
	MOVE	[-22,,4]	;(R02) SUB-POINTER
	SETZ			;(R03) ??
 ZZ==1
 REPEAT 22,<MOVE CRSINF+<ZZ==ZZ+1>> ;(R04-25) THE HSB ITSELF
HSBTBE:!
> ;END IFN FTKS10
;ROUTINE TO PERFORM GETTAB SIMULATION FROM A CRASH FILE.
;DOES NOT HANDLE -1 AND -2 INDEXING INTO JOB/SEGMENT TABLES.
;CALL:
;	MOVE	T1,GETTAB ARGUMENT
;	PUSHJ	P,GTBDSK
;RETURN:
;	CPOPJ ON ERROR
;	CPOPJ1 WITH DATUM IN T1 ON SUCCESS

GTBDSK:	PUSHJ	P,SAVE3##	;PRESERVE SOME ACS
	HRRZ	P3,T1		;COPY TABLE NUMBER
	HLRES	T1		;ISOLATE THE INDEX
	SKIPL	GTBLIM		;IF NO MAXIMUM GETTAB
	CAMLE	P3,GTBLIM	;OR THIS IS OUT OF RANGE,
	POPJ	P,		;FAIL
	MOVE	P3,@GTBSTA	;FETCH ENTRY FROM COPIED NUMTAB
	LDB	P2,[POINT 3,P3,11] ;GET TYPE OF GETTAB
	CAIN	P2,GT.PDB	;IS DATUM IN THE PDB?
	JRST	GTBDS3		;YES--GO GET IT
	CAIN	P2,GT.SEG	;INDEXED BY JOB/SEGMENT NUMBER?
	SKIPA	P1,%CNSJN	;YES--GET JBTMXL
	LDB	P1,[POINT 9,P3,8] ;NO--GET MAXIMUM FROM NUMTAB ENTRY
	CAIE	P2,GT.RNG	;IS THIS A RANGE-TABLE ENTRY?
	JRST	GTBDS2		;NO--HAVE 0,,MAX IN P1
	ADD	P1,RNGTBB	;YES--INDEX INTO RNGTAB
	EXCH	P1,T1		;SAVE INDEX
	PUSHJ	P,PEKDSK	;FETCH MIN,,MAX
	  POPJ	P,		;PUNT
	EXCH	P1,T1		;RESTORE INDEX, PUTTING MIN,,MAX IN P1
GTBDS2:	HRRE	P2,P1		;GET MAXIMUM TABLE OFFSET
	CAMLE	T1,P2		;.LE. MAX?
	POPJ	P,		;NO--FAIL
	HLRE	P2,P1		;GET MIN OFFSET
	CAMGE	T1,P2		;.GE. MIN?
	POPJ	P,		;NO--FAIL
	ADDI	T1,(P3)		;YES--INDEX INTO TABLE
	PJRST	PEKDSK		;AND RETURN THE WORD WE WANT

GTBDS3:	SKIPN	%CNPDB		;DO WE HAVE THE JBTPDB ADDRESS?
	POPJ	P,		;NO--PUNT
	ADD	T1,%CNPDB	;OFFSET TO THIS JOB'S PDB POINTER
	PUSHJ	P,PEKDSK	;READ THE PDB ADDRESS
	  POPJ	P,		;PUNT
	JUMPE	T1,CPOPJ1	;NO PDB IS A GOOD RETURN OF ZERO
	ADDI	T1,(P3)		;INDEX INTO IT
	HRRZS	T1		;ISOLATE THE ADDRESS
	PJRST	PEKDSK		;RETURN THE WORD DESIRED
;ROUTINE TO READ A WORD FROM THE CRASH FILE
;CALL:
;	MOVE	T1,MONITOR ADDRESS
;	PUSHJ	P,PEKDSK
;RETURN:
;	CPOPJ ON ERROR
;	CPOPJ1 WITH DATUM IN T1 ON SUCCESS

PEKDSK:	ADJSP	P,3		;MAKE SOME SPACE
	DMOVEM	T2,-2(P)	;SAVE SOME TEAS
	MOVEM	T4,(P)		;AND ANOTHER
	PUSHJ	P,PEKDS0	;FETCH THE VALUE
	  TRNA			;PROPAGATE NON-SKIP
	AOS	-3(P)		;AND SKIP
	DMOVE	T2,-2(P)	;RESTORE SOME TEAS
	MOVE	T4,(P)		;AND ANOTHER
	ADJSP	P,-3		;TRIM STACK
	POPJ	P,		;AND RETURN THE VALUE OBTAINED

PEKDS0:	SKIPE	PHYFLG		;IF NOT READY FOR VIRTUAL TRANSLATION,
	JRST	REDDSK		;THEN JUST FIND THE FILE PAGE
	PUSHJ	P,SAVE4##	;YES--SAVE SOME ACS
	TLNN	T1,^-1		;IF SECTION 0/1,
	HRRZS	T1		;MAKE SECTION 0
	MOVE	P1,T1		;COPY THE ADDRESS TO FIND
	HLRZS	T1		;ISOLATE SECTION NUMBER
	MOVE	T1,@%CCTOS	;FETCH SECTION MAP ENTRY
	LDB	P2,[POINT 3,T1,2] ;GET POINTER TYPE
	CAIE	P2,PM.DCD	;DIRECT?
	POPJ	P,		;NO--FAIL
	HRRZS	T1		;YES--ISOLATE PAGE NUMBER
	CAME	T1,EMPPAG	;IS IT THE ONE WE HAVE IN CORE?
	JRST	PEKDS1		;NO--GO DO IT THE HARD WAY
	LDB	T1,[POINT 9,P1,35-9] ;YES--GET PAGE WITHIN SECTION
	MOVE	T1,@EMPADR	;FETCH FROM OUR COPY OF THE SECTION MAP
	JRST	PEKDS2		;SKIP AROUND THE HARD CASE
PEKDS1:	LSH	T1,P2WLSH	;CONVERT TO ADDRESS
	LDB	P2,[POINT 9,P1,35-9] ;GET PAGE WITHIN SECTION
	ADD	T1,P2		;COMPUTE PHYSICAL ADDRESS OF MAP POINTER
	PUSHJ	P,REDDSK	;READ THE PAGE POINTER
	  POPJ	P,		;PROPAGATE FAILURE
PEKDS2:	LDB	P2,[POINT 3,T1,2] ;GET POINTER TYPE
;***SOMEDAY WE MIGHT WANT TO HANDLE FUNNY SPACE HERE, BUT SINCE WE DON'T DO
;  ANY REFERENCES TO IT IN THIS MODULE, IT SEEMS POINTLESS ***
	CAIE	P2,PM.DCD	;IF NOT DIRECT,
	POPJ	P,		;GIVE FAILURE
	HRRZS	T1		;ISOLATE PHYSICAL PAGE NUMBER
	LSH	T1,P2WLSH	;CONVERT TO PHYSICAL ADDRESS
	ANDI	P1,PG.BDY	;ISOLATE OFFSET WITHIN PAGE
	ADDI	T1,(P1)		;FINALLY HAVE FINISHED ADDRESS TRANSLATION
;;	PJRST	REDDSK		;NOW RETURN THE WORD FROM THE FILE

;HERE TO READ A WORD FROM THE DISK
;SHOULD BE CALLED ONLY FROM PEKDSK

REDDSK:	PUSHJ	P,SAVE4##	;SAVE SOME ACS AGAINST UUOCON
	IDIVI	T1,PAGSIZ	;SEPARATE PAGE NUMBER AND OFFSET
	MOVE	P4,T2		;PRESERVE THE OFFSET
	PUSHJ	P,FNDPAG	;LOCATE THE PAGE IN THE .EXE DIRECTORY
	  POPJ	P,		;NOT THERE--FAIL
	SKIPN	T1,P2		;IF ABZ PAGE,
	JRST	CPOPJ1##	;RETURN ZERO
	LSH	T1,P2WLSH	;MAKE AN ADDRESS
	ADDI	T1,(P4)		;INCLUDE THE OFFSET
	CAMLE	T1,DSKLEN	;IS THE FILE THAT BIG?
	POPJ	P,		;NO--FAIL
	CAMN	P2,CURBLK	;IF THIS PAGE IS THE ONE WE HAVE,
	JRST	REDDS3		;JUST GO USE IT
	MOVEM	P2,CURBLK	;NO--REMEMBER FOR NEXT TIME
	TRZ	T1,PG.BDY	;TRIM ADDRESS BACK TO PAGE BOUNDARY
	LSH	T1,W2BLSH	;CONVERT ADDRESS TO BLOCK NUMBER
	USETI	0,1(T1)		;TELL FILSER WHENCE TO READ
	MOVE	T1,[IOWD PAGSIZ,DSKBUF] ;OUR I/O WORD
	MOVEM	T1,.JDAT	;SET FOR THE UUO
	IN	0,0		;READ THE BLOCK
	JRST	REDDS3		;GOT IT--GO USE IT
	SETOM	CURBLK		;FORGET CURRENT BLOCK ON ERROR
	POPJ	P,		;FAIL
REDDS3:	UMOVE	T1,DSKBUF(P4)	;FETCH WORD FROM USER CORE
	ERJMP	CPOPJ##		;JUST IN CASE
	JRST	CPOPJ1##	;SUCCEED

;ROUTINE TO FIND THE FILE PAGE FROM THE PHYSICAL CORE PAGE
;CALLED ONLY BY REDDSK

FNDPAG:	HRLZ	P1,.JDAT+.JBDA## ;GET LENGTH OF .EXE DIRECTORY
	MOVNS	P1		;THEN -VE LENGTH FOR AOBJN
	HRRI	P1,.JDAT+.JBDA##+1 ;INCLUDE ADDRESS+1
FNDPA1:	HRRZ	P2,(P1)		;GET FILE PAGE NUMBER OF DESCRIPTOR
	HRRZ	P3,1(P1)	;AND CORE PAGE NUMBER
	LDB	T2,[POINT 9,1(P1),8] ;PLUS REPEAT COUNT
	ADD	T2,P3		;MAKE UPPER BOUND TO GO WITH LOWER BOUND
	CAML	T1,P3		;IS THE PAGE WE WANT IN THIS RANGE?
	CAMLE	T1,T2		; ??
	JRST	FNDPA2		;NO--FIND NEXT
	JUMPE	P2,CPOPJ1##	;YES--IF ABZ SUCCEED WITH ZERO
	SUB	T1,P3		;COMPUTE OFFSET IN THIS DESCRIPTOR
	ADD	P2,T1		;COMPUTE FILE PAGE NUMBER
	JRST	CPOPJ1##	;SUCCEED
FNDPA2:	AOBJP	P1,.+1		;ACCOUNT FOR TWO-WORD ENTRIES
	AOBJN	P1,FNDPA1	;LOOP OVER ALL DIRECTORY ENTRIES
	POPJ	P,		;FAIL IF NOT FOUND
;HERE TO CLEAN UP.  COME TO CRSINQ IF WE MIGHT NEED TO CLEAR 116 IN THE
;DUMP.  COME TO CRSINX IF WE JUST WANT OUT.

CRSINQ:	SKIPN	.JDAT+140+BLKSIZ+116 ;DO WE NEED TO RE-WRITE THE FILE?
	JRST	CRSINX		;NO--SKIP THIS STUFF
	SETZM	.JDAT+140+BLKSIZ+116 ;YES--CLEAR THE WORD
	USETI	0,PAGSIZ/BLKSIZ+1 ;POINT TO THE RIGHT BLOCK AGAIN
	MOVE	T1,[IOWD BLKSIZ,.JDAT+140+BLKSIZ] ;OUR I/O WORD
	MOVE	T2,DEVBLK##(F)	;GET THE BLOCK NUMBER FOR OUR I/O
	PUSHJ	P,MONWRU##	;RE-WRITE THE BLOCK DESPITE RIPNDL
CRSINX:	RELEAS	0,		;GIVE BACK THE DDB
	PUSHJ	P,CLRASA##	;MAKE THE JOB WELL-BEHAVED AGAIN
	SKIPE	T1,CRSRLD	;IF SYSRLD GAVE US SOMETHING,
	PUSHJ	P,QUESEB##	;THEN QUEUE IT UP
	SETZM	CRSRLD		;IN CASE SOMEONE CALLS US BY HAND
	SKIPE	T1,CRSAVL	;IF SYSAVL WORKED,
	PUSHJ	P,QUESEB##	;THEN QUEUE ITS BLOCK AS WELL
	SETZM	CRSAVL		;IN CASE SOMEONE CALLS US BY HAND
	SKIPGE	DAEJOB##	;IF THIS IS THE FIRST TIME HERE,
	SETZM	DAEJOB##	;LET DAEMON START NOW
	POPJ	P,		;FINALLY BACK TO CLOCK1 TO LOG OURSELVES OUT
	SUBTTL	THE END

	LIT

CRSEND:	END