Trailing-Edge
-
PDP-10 Archives
-
BB-JR93K-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 - V1266
SUBTTL T. HASTINGS/TH/CHW/TW/RCC/DAL 02-JAN-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,1266 ;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
MOVSI T2,EH.AVL ;GET DAEMON'S AVAIL.SYS BIT
MOVE T1,.EXFLG(P2) ;GET FLAGS FROM TABLE HEADER
TRNE T1,EX.AVL ;IS THIS TO BE PROPAGATED TO AVAIL.SYS?
IORM T2,.EBTYP(P1) ;YES, TELL DAEMON
MOVSI T2,EH.NER ;GET THE "NO ERROR.SYS" BIT
TRNE T1,EX.NER ;SUPPRESS WRITING TO ERROR.SYS?
IORM T2,.EBTYP(P1) ;YES, TELL DAEMON
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
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
;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