Trailing-Edge
-
PDP-10 Archives
-
tops10_703a_sys_ap115_bb-ju01b-bb
-
errcon.x15
There are 2 other files named errcon.x15 in the archive. Click here to see a list.
TITLE ERRCON - MONITOR DETECTED ERROR HANDLING ROUTINES - V1216
SUBTTL T. HASTINGS/TH/CHW/TW/RCC/DAL 30 JULY 86
SEARCH F,S
$RELOC
$HIGH
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
.CPYRT<1973,1986>
;COPYRIGHT (C) 1973,1974,1975,1976,1977,1978,1979,1980,1982,1984,1986
;BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
;ALL RIGHTS RESERVED.
;
XP VERRCN,1216 ;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
>
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,@.CPMPS## ;CALL CPU DEPENDENT CORE 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 /Nothing was found.
***************
/] ;NO--TELL THEM THAT
PUSHJ P,CONMES## ;PRINT IT
MOVEI T1,.ERSPR ;GET CODE FOR DAEMON
HRL T1,.CPSLF## ;GET CPU CDB
PUSHJ P,DAEEIM## ;POKE DAEMON
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
;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,DAYTIM## ;FINISH WITH DATE AND TIME
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,@.CPMPS## ;SWEEP CORE
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 /Nothing was found.
***************
/] ;NO--TELL THEM THAT
PUSHJ P,CONMES## ;PRINT IT
MOVEI T1,.ERSNX ;GET DAEMON CODE
HRL T1,.CPSLF## ;GET CPU CDB
PUSHJ P,DAEEIM## ;POKE DAEMON
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 /***************
/
;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
MOVE T1,T2 ;SAVE THAT
PUSH P,J ;SAVE THE JOB NUMBER
MOVEI T2,0 ;ASSUME THAT THE JOB DOESN'T HAVE A HIGH SEGMENT
SKIPLE J,JBTSGN##(J) ;DOES IT?
PUSHJ P,SEGSIZ## ;YES, GET THE SIZE OF THE HIGH SEGMENT
POP P,J ;RESTORE THE JOB NUMBER
ADD T1,T2 ;SIZE OF THE JOB IN PAGES
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
IFN FTPI,<
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##>+777]
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
IFN FTPI,<
SIGNAL C$NXM ;SIGNAL JOB
SKIPA ;NOT INTERRESTED
POPJ P, ;TRAP TO USER
> ;END FTPI
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
PUSHJ P,PRRBK## ;PRINT RIGHT BRACKET
POPJ P, ;RETURN
;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:
IFN FTPI,<
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,PAGSIZ##-1(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^!<PAGSIZ##-1> ;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::
IFN FTPI,<
LDB J,PJOBN## ;OFFENDING JOB'S JOB NUMBER
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
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
IFN FTSPL,<
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 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
>
PUSH P,W ;SAVE W
PUSHJ P,FNDPDB## ;FIND JOBS PDB
JRST WPOPJ## ;RETURN IF NONE
SKIPLE .PDDVL##(W) ;ANY LOGICAL NAMES AROUND
PUSHJ P,SETDVF## ;YES,BLAST THEM
JRST WPOPJ## ;RESTORE W AND 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
CPIASN::SE1ENT ;PAGTAB LIVES IN MS.MEM, HAVE TO RUN EXTENDED
SETZB T2,J ;ASSUME IN MONITOR (JOB 0 NOT A LEGAL JOB #)
LDB T1,[POINT 13,P1,26] ;SET REL. ADR. FROM ABS. ADR IN MONITOR
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
MOVE T3,P1 ;SET T3=ABSOLUTE ADDRESS OF ERROR WORD
LSH T3,W2PLSH## ;T3=ABSOLUTE PAGE NUMBER OF PAGE CONTAING BAD WORD
MOVEI T2,JOBMAX## ;SCAN TO SEE IF BAD ADDRESS IS IN A UPMP
AUPLOP: HRRZ T1,JBTUPM##(T2) ;T1=PAGE NUMBER OF THE UPMP
HRRZ T4,@[IW MS.MEM,PAGTAB(T1)] ;PAGE MAP
CAIN T4,(T3) ;WORD IN THAT PAGE?
JRST AUPLO1 ;YES
CAIE T1,(T3) ;BAD WORD IN THIS UPMP?
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: 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?
SKIPN JBTADR##(J) ;IS THIS JOB OR HIGH SEG IN CORE?
JRST ASNAOJ ;NO, LOOK AT THE NEXT SEGMENT
LDB T2,JBYHSA## ;ASSUME ITS A HIGH SEG, GET STARTING PAGE NO.
CAIG J,JOBMAX## ;IS IT A HIGH SEGMENT?
LDB T2,JBYLSA## ;NO--GET STARTING PAGE NUMBER OF LOW SEGMENT
ASNHGH: CAIN T2,(T3) ;IS THIS PAGE THE SAME PAGE WHICH CONTAINED AN ERROR?
JRST ASNMAP ;YES--SEE IF A MAP
HRRZ T2,@[IW MS.MEM,PAGTAB(T2)] ;T2=PAGE NO. OF NEXT PAGE IN THIS SEGMENT
SKIPE T2 ;IS IT THE LAST PAGE IN THIS SEGMENT?
AOJA T1,ASNHGH ;NO, LOOK AT ALL THE PAGES IN THIS SEGMENT
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 T1,[-<MXSECN+1>,,.UPMVP/PAGSIZ##]
AOBJP T1,CPOPJ1## ;NOT A MAP; S0 CAUGHT ABOVE
SE1ENT ;FOR PAGE MAP REFERENCES
MOVEI T4,(T1) ;FOR GMPTR
PUSHJ P,GMPTR## ;GET ENTRY
CAIA
ASNMP1: AOS T4 ;INCREMENT
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 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,MPGSIZ## ;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,CHNMPE OR CHNNXM (MEMORY PARITY OR NXM)
; RETURN WILL ALL REGISTERS PRESERVED EXCEPT T1-T4
;SUBROUTINE FOR MEMORY PARITY
CHNMPE::AOS .CHMPE(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
CHNNXM::AOS .CHNXM(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,.CHLUE(P1) ;SAVE UNIT DATA BLOCK ADR
HRRM F,.CHLDE(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,DAYTIM## ;APPEND DATE AND TIME
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,.CHLUE(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,CHB22B##(P1) ;GET CHANNEL TYPE BITS
TLNN T2,CP.22B## ;22-BIT CHANNEL?
SKIPA T1,[[ASCIZ /DF10/]] ;NO--DEFINITELY A DF10
MOVEI T1,[ASCIZ /DF10-C/] ;YES--POSSIBLY 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
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,.CHFCW(P1) ;GET LH TERMINATION CCW
SKIPGE CHB22B##(P1) ;IS THIS A 22-BIT CHANNEL?
LSH T1,-4 ;YES--THEN 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,.CHFCW(P1) ;GET RH TERMINATION CCW
SKIPGE CHB22B##(P1) ;IS THIS A 22-BIT CHANNEL?
TLZA T1,777760 ;YES--GET JUST DATA ADDRESS (22 BITS)
TLZ T1,-1 ;NO--GET JUST DATA ADDRESS (18 BITS)
PUSHJ P,PRT22A ;PRINT IT
MOVEI T1,[ASCIZ /
Last three channel commands executed are:
/]
PUSHJ P,CONMES## ;PRINT THIS
MOVE T1,.CHCW0(P1) ;ARE ALL CCW'S ZERO?
IOR T1,.CHCW1(P1) ;...
IOR T1,.CHCW2(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,.CHCW2(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
SETZM .CPCHE## ;CLEAR CHANNEL ERROR IN PROGRESS FLAG
MOVEI T1,.ERCPE ;CHANNEL ERROR CODE
HRL T1,P1 ;GET CDB ADDRESS
PUSH P,J ;SAVE J
PUSHJ P,DAEEIM## ;POKE DAEMON
POP P,J ;RESTORE J
POPJ P, ;RETURN
;ROUTINE TO STORE CCW DATA FOR CHANNEL ERRORS
CHNCCW: MOVE T3,CHB22B##(P1) ;PICK UP CHANNEL TYPE BITS
MOVE T2,0(T1) ;GET FIRST CCW IN LIST
MOVEM T2,.CHICW(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,.CHFCW(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,.CHFCW(P1) ;SAVE IN CDB FOR F.S.
HLRZ T2,P3 ;GET ADDRESS OF LAST CCW
TLNE T3,CP.22B## ;IS THIS A 22-BIT CHANNEL?
LSH T2,-4 ;YES--THEN 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,.CHCW0(P1) ;PUSH EVERYBODY DOWN ONE
EXCH P3,.CHCW1(P1) ;...
MOVEM P3,.CHCW2(P1) ;...
MOVE P3,(T1) ;GET THIS CCW
MOVEM P3,.CHCW0(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
TLNE T3,CP.22B## ;IS THIS A 22-BIT CHANNEL?
TLZA T1,777760 ;YES--GET JUST ADDRESS (22-BITS)
TLZ T1,-1 ;NO--GET JUST ADDRESS (18-BITS)
JRST CHNCC5 ; AND GO AROUND AGAIN
CHNCC6: SETZM .CHCW2(P1) ;ZERO THE CCW LOCATIONS
SETZM .CHCW1(P1) ;...
SETZM .CHCW0(P1) ;...
CHNCC7: MOVE T2,CHNTCW##(P1) ;GET EXPECTED TERMINATION CCW
MOVEM T2,.CHTCW(P1) ;SAVE FOR F.S.
POPJ P, ;RETURN
;HERE TO COLLECT RELEVANT DATA WORDS ON PARITY ERROR
CHNDAT: MOVE T4,.CHFCW(P1) ;GET TERMINATION CCW
SKIPGE CHB22B##(P1) ;IS THIS A 22-BIT CHANNEL?
TLZA T4,777760 ;YES--GET JUST ADDRESS (22-BITS)
TLZ T4,-1 ;NO--GET JUST ADDRESS (18-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,.CHDW2(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 (0) ;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 .CHDW0(P1) ;ZERO THE DATA LOCATIONS
SETZM .CHDW1(P1) ;...
SETZM .CHDW2(P1) ;...
POPJ P, ;RETURN
>;END IFN FTKL10
IFN FTKS10,<
CHNMPE::
CHNNXM::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
CLRPGT (0,.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
ALCSEB::SKIPE DINITF## ;OUT OF ONCE CODE YET?
POPJ P, ;NO, TAKE IMMEDIATE ERROR RETURN
IFN FTXMON,<
PUSHJ P,SSEC0## ;GET OUT OF SECTION 1 IF NECESSARY
>; END IFN FTXMON
PUSH P,T1 ;SAVE THE LENGTH
MOVEI T2,.EBHDR(T1) ;LENGTH INCLUDING HEADER TO T2
PUSHJ P,GETWDS## ;GET SOME SECTION 0 SPACE
JRST TPOPJ## ;ERROR, 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
SETZ T3, ;CLEAR FOR ASHC
ASHC T2,-^D17 ;JIFFIES*2**18 IN T3
DIV T2,[JIFSEC##*^D24*^D3600] ;DAYS IN LH, FRACTION IN RH
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 QUEUE A SYSTEM ERROR BLOCK TO DAEMON.
;CALL:
; T1/ ADDRESS OF ERROR BLOCK
; PUSHJ P,QUESEB
;RETURN:
; CPOPJ ALWAYS
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
CAME T1,SEQTOP ;WAS THIS THE FIRST ENTRY IN THE QUEUE?
POPJ P, ;NO, DAEMON ALREADY KNOWS
MOVEI T1,.ERSEB ;CODE FOR DAEMON
PUSH P,J ;SAVE J AS DAEEIM STEPS ON IT
S0PSHJ DAEEIM## ;PROD DAEMON INTO ACTION
JRST JPOPJ## ;RESTORE J AND 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
SEBLK.::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
;DISPATCHED TO HERE BY DIE AND PERISH IN COMMON
;RUNNING IN SECTION 0
DIE0:: CONI PI,.CPCPI## ;SAVE STATE OF MACHINE
CONO PI,PI.TFP+177 ; ..
JSR .CPSVA## ;SAVE ALL AC SETS
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: HRLZ T1,.USMUO ;GET MUUO OPCODE AND AC
IOR T1,.USMUE ;INCLUDE EFFECTIVE ADDRESS
MOVEM T1,.CPTRP## ;STORE
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
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
>
PUSHJ P,DIE1 ;CALL MAIN PROCESSING ROUTINE AS A SUBROUTINE
PUSHJ P,DAEEST## ;TELL DAEMON OF STOPCD
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
HRLZ 17,.CPACA## ;WHERE TO RESTORE THE AC'S FROM
BLT 17,17 ;RESTORE THEM ALL
PUSH P,T1 ;SAVE T1
MOVE T1,.CPSTY## ;GET STOPCODE TYPE
CAIE T1,S$INFO ;INFORMATIONAL?
CAIN T1,S$EVENT ;BUGINF IN DRAG?
JRST [POP P,T1 ;RESTORE T1
JRST DIE02] ;FINISH UP
POP P,T1 ;RESTORE T1
SKIPGE DEBUGF## ;WANT DDT?
.CREF DF.SBD ;(FLAG BIT TESTED)
XCT .CPDDT## ;YES
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
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: 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
IFN FTMP,<
DIE2: ;DIELOK ;CAN'T USE MACRO AS WE TEST CRSHWD BELOW
AOSE .CPDIE## ;ALREADY OWN THE INTERLOCK?
JRST DIE2B ;YES
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
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,DAYTIM## ;SAY WHEN
MOVE T1,.CPSTY## ;GET STOPCODE TYPE AGAIN
MOVE T1,PRCTAB(T1) ;GET ITS CONTROL BITS
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
TLNE T1,(S%NCSB) ;SUPPRESS CSB TYPEOUT?
JRST NOCSB ;YES, DON'T TYPE CSB FOR TRIVIAL ERRORS
SKIPGE DEBUGF## ;WANT DDT?
JRST DIERS0 ;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
;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
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: 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
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## ;YES, 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
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: 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,UNINAM##(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
;DISPATCHED TO BY BGCTYP IN COMMON
;POINTER TO DATA IS IN P1
BUGTY1::MAP T1,(P1) ;MAKE SURE LOCATION IS ACCESSIBLE
PUSHJ P,FLTCHK## ;MAKE SURE WON'T FAULT
POPJ P, ;WILL FAULT, END LIST NOW
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 /: /
MAP T1,1(P1) ;MAKE SURE THIS WON'T FAULT
PUSHJ P,FLTCHK##
POPJ P, ;END OF LIST FORCED
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: 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
IFN FTPI,<
SIGNAL C$IUUO ;SIGNAL ILLEGAL UUO
SKIPA ;DOESN'T WANT THE TRAP
JRST ERRGOU ;INTERCEPT THE UUO
> ;END FTPI
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
CONSZ PI,PI.IPA ;AT UUO LEVEL?
STOPCD .,STOP,UIL,DIEEMU, ;++UUO AT INTERRUPT LEVEL
STOPCD .+1,DEBUG,EUE,DIEEMU, ;++EXEC UUO ERROR
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
IFN FTPI,<
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::
IFN FTPI,<
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:
IFN FTPI,<
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
MOVEI T2,1 ;IN ATIC
HRLI T2,DVHN1B
SYSPIF
IDPB T2,CLOCK##
IDPB T1,CLOCK##
SETOM CLKNEW##
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: 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
IFN FTPI,<
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
PUSHJ P,FLTST## ;IN-CORE?
POPJ P, ;NO
ADDI T1,3 ;LAST WORD OF VECTOR
PUSHJ P,FLTST## ;IN-CORE?
POPJ P, ;NO
TRNE M,-1 ;NO INTERRUPT IF JOBINT NOT SET
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: PUSH P,T1 ;THIS COULD BE CHEAPER IF 2 ACS COULD BE USED, BUT?
GETPC T1,.JDAT+JOBPD1## ;GET UUO PC
TLO T1,(XC.USR) ;MAKE SURE USER MODE IS ON
HLLM T1,(P) ;COPY FLAGS FOR THE USER
EXCH T1,(P) ;PC TO TRAP TO
PUTPC T1,.JDAT+JOBPD1## ;STORE NEW PC
POP P,T1 ;RESTORE OLD PC
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
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
IFN FTPI,<
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:
IFN FTPI,<
MOVE T1,JBTSTS##(J) ;GET JOB STATUS
TDNE T1,[JERR,,JS.ASA] ;CAN WE INTERCEPT
JRST PCSTP1 ;NO--STOP JOB
>
IFN FTPI,<
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 TYPE A NUMBER AS HALFWORDS SEPARATED BY COMMAS.
;CALL: MOVE T1,NUMBER
; PUSHJ P,HWDPNT
; RETURN
HWDPNT::PUSH P,T1 ;SAVE T1 FOR RH
HLRZS T1 ;KEEP JUST LH
PUSHJ P,OCTPNT ;PRINT AS 6 OCTAL DIGITS
PUSHJ P,INLMES ;PRINT THE TWO COMMAS
ASCIZ /,,/ ;...
POP P,T1 ;RESTORE T1 FOR RH
PJRST OCTPNT ;PRINT RH AND RETURN
;ROUTINE TO TYPE A NUMBER AS HALFWORDS SEPARATED BY COMMAS.
;DIFFERES FROM HWDPNT IN THAT THE NUMBERS ARE NOT ZERO FILLED.
;CALL: MOVE T1,NUMBER
; PUSHJ P,PRTXWD
; RETURN
PRTXWD::TLNN T1,-1 ;ANYTHING IN LH?
PJRST PRTDI8 ;NO, THEN JUST LET PRTDI8 DO ITS THING
PUSH P,T1 ;SAVE T1
HLRZS T1 ;GET LEFT HALF
PUSHJ P,PRTDI8 ;PRINT IT
PUSHJ P,INLMES## ;ADD SOME NOISE
ASCIZ /,,/ ;...
POP P,T1 ;RESTORE T1
HRRZS T1 ;KEEP JUST RH
PJRST PRTDI8 ;PRINT RH AND RETURN
;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
; FALL INTO OCTPNT
;ROUTINE TO PRINT 6 DIGIT OCTAL NUMBER
;CALL: MOVEI LINE,LINE DATA BLOCK ADDRESS FOR TTY
; HRR T1, OCTAL NUMBER
; PUSHJ P,OCTPNT
; RETURN T2,PRESERVED,T1 DESTROYED
OCTPNT::HRLZ T1,T1 ;MOVE TO LH FOR ROTATING
TRO T1,700000 ;SETUP AN END FLAG
OCTP1: ROT T1,3 ;GET NEXT OCTAL DIGIT
TLNN T1,777777 ;WAS THAT FLAG?
POPJ P, ;YES, DO NOT PRINT IT
PUSH P,T1 ;SAVE T1 OVER I/O ROUTINE
PUSHJ P,PRTNUM ;NO, PRINT OCTAL DIGIT
POP P,T1 ;RESTORE T1
HRRI T1,0 ;CLEAR RH
JRST OCTP1 ;GET NEXT OCTAL DIGIT
;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 ADD 1 TO T1 AND PRINT DECIMAL
;SAME CALL AS OCTPNT
DECP1:: AOJA T1,RADX10 ;ADD 1 AND GO PRINT
;ROUTINE TO PRINT DECIMAL
;CALL: SAME AS OCTPNT
;T2: PRESERVED
RADX10::PUSH P,T2 ;SAVE T2
PUSHJ P,PRTDIG ;PRINT DECIMAL DIGITS
PJRST T2POPJ## ;RESTORE T2 AND RETURN
;RECURSIVE DECIMAL PRINT ROUTINE
;CALL: MOVE T1,DECIMAL NO.
; PUSHJ P,PRTDIG
PRTDIG::
IFN FTXMON,<
PUSHJ P,SSEC0## ;RUN IN SECTION 0
>
PRTDGX: IDIVI T1,12 ;DIVIDE BY 10
HRLM T2,(P) ;RT ON PD LIST
JUMPE T1,.+2 ;FINISHED?
PUSHJ P,PRTDGX ;NO, CALL S OR F
PRTNMM: HLRZ T1,(P) ;YES, GET LAST NUMBER
PRTNUM: MOVEI T3,"0"(T1) ;CONVERT TO ASCII
PJRST COMTYO## ;AND TYPE IT OUT
;RECURSIVE OCTAL PRINT ROUTINE
;CALL: SAME AS PRTDIG
PRTDI8::
IFN FTXMON,<
PUSHJ P,SSEC0## ;RUN IN SECTION 0
>
PRTD8X: IDIVI T1,10 ;DIVIDE BY 8
HRLM T2,(P) ;PUT ON STACK
JUMPE T1,PRTNMM ;FINISHED?
PUSHJ P,PRTD8X ;NO - LOOP
PJRST PRTNMM ;OUTPUT
;SUBROUTINE TO PRINT 22 BIT OCTAL ADDRESS
;CALL: MOVE T1,22 BIT ADDRESS
; PUSHJ P,PRT22A
; ALWAYS RETURN
PRT22A::PUSH P,T1 ;SAVE 22 BIT ADDRESS
HLRZ T1,(P) ;GET HIGH ORDER HALF
JUMPE T1,PRT22B ;IS IT 0 (USUALLY EXCEPT BIG SYSTEMS)
PUSHJ P,PRTDI8 ;NO, PRINT AS LEADING 0 SUPPRESSED OCTAL
PRT22B: POP P,T1 ;GET LOW ORDER HALF
PJRST OCTPNT ;PRINT AS NON ZERO SUPPRESSED OCTAL (RH ONLY)
;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
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,UNINAM##(T1) ;GET PHYSICAL UNIT NAME AND SKIP TO PRNAM1
ERNAM1: MOVE T2,DEVNAM(T2) ;NO, GET DEVICE NAME
;ROUTINE TO PRINT SIXBIT NAME
;CALL MOVE U,ASCII OUTPUT BYTE POINTER
; MOVE T2,NAME
; PUSHJ P,PRNAME
PRNAM1: MOVEI T1,0
LSHC T1,6 ;SHIFT IN NEXT CHAR.
MOVEI T3,40(T1) ;ASCII VERSION INTO CHREC FOR OUTCHS
PUSHJ P,COMTYO## ;OUTPUT CHARACTER
PRNAME::JUMPE T2,CPOPJ##
JRST PRNAM1
;ROUTINE TO PRINT SIXBIT WORD WITH TRAILING SPACES
;CALL: SAME AS PRNAME.
PRSIXB::MOVEI T3,6
PUSH P,T3
PRSIX0: SETZ T3,
ROTC T2,6
ADDI T3,40
PUSHJ P,COMTYO##
SOSLE (P)
JRST PRSIX0
JRST T3POPJ##
LIT
ERREND: END