Trailing-Edge
-
PDP-10 Archives
-
BB-BT99S-BB_1990
-
10,7/mon/aprser.mac
There are 8 other files named aprser.mac in the archive. Click here to see a list.
TITLE APRSER - PROCESSOR DEPENDENT CODE - V55
SUBTTL JOSEPH A. DZIEDZIC /JAD 02-JAN-90
SEARCH F,S,DEVPRM
IFN FTKL10,<SEARCH DTEPRM>
$RELOC
$HIGH
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION
; 1973,1974,1975,1976,1977,1978,1979,1980,1982,1984,1986,1988.
;ALL RIGHTS RESERVED.
.CPYRT<1973,1988>
;APRSER WAS CREATED FROM KLSER AND KSSER. AUTHORS OF THOSE MODULES:
;KLSER - J.M. FLEMMING/JMF & D.A. LEWINE/DAL/EVS
;KSSER - DMCC/DBD
XP VAPRSR,55 ;PUT VERSION NUMBER IN GLOB LISTING AND MAP
APRSER::ENTRY APRSER ;LOAD APRSER IF LIBRARY SEARCH
SUBTTL TRAP HANDLING
;HERE TO PROCESS USER ARITHMETIC OVERFLOW TRAPS
SAROVF::DMOVE T1,.USMUO ;GET PC DBL WRD
MOVE T3,.JDAT+JOBENB## ;GET USER'S ENABLE BITS
TRNN T3,AP.AOV ;OVERFLOW - IS THE USER ENABLED?
TLNE T1,(XC.FOV) ;TRAP CAUSED BY FOV?
CAIA ;YES,
JRST SAROV3 ;NOT ENABLED, IGNORE IT
HRRI T3,AP.AOV+AP.FOV ;ASSUME FLOATING OVERFLOW
TLNN T1,(XC.FOV) ;WAS IT A FLOATING OVERFLOW TRAP?
TRZ T3,AP.FOV ;NO, INTEGER OVERFLOW
;HERE WITH T1,T2=PC, T3=APRENB BITS
SAROV1: TLNE T2,MXSECN ;IN A NON-ZERO SECTION?
JRST SAROV5 ;CAN'T TRAP IT THIS WAY THEN
HLLM T1,.JDAT+JOBTPC## ;SAVE OLD PC
HRRM T2,.JDAT+JOBTPC## ;..
MOVEM T3,.JDAT+JOBCNI## ;LIKE CONI ON THE KA-10
MOVE T3,.JDAT+JOBENB## ;GET USER'S ENABLE BITS
TRNE T3,XP.DDU ;USER WANT TRAPS REENABLED?
JRST SAROV2 ;YES, LEAVE AS IS
HLLZS .JDAT+JOBENB## ;CLEAR USER'S ENABLE BITS SO MUST DO APRENB AGAIN
MOVSI T3,(JFCL) ;NOP
MOVEM T3,.USAOT ;IGNORE ARITHMETIC TRAPS
MOVEI T3,UP.PDT
MOVEM T3,.USPDT ;EXEC WILL FIELD PDL OVERFLOWS
SETZM .CPCN1## ;CLEAR POSSIBLE NXM OR CLOCK ENABLES
SAROV2: MOVEI T3,XP.CLK ;ALWAYS DISABLE CLOCK
ANDCAM T3,.CPCN1##
HRRZ T3,.JDAT+JOBAPR## ;PC IN TRAP ROUTINE?
CAIE T3,0(T2)
CAIN T3,-1(T2)
JRST SAROV4 ;YES
HRR T2,.JDAT+JOBAPR## ;GET USER'S TRAP ADDRESS
TLZ T1,(XC.OVF+XC.FOV+XC.FUF+XC.NDV+IC.BIS+IFN FTKL10,<IC.AFI>)
TLO T1,(XC.USR+IFN FTKL10,<XC.PUB>) ;INSURE PUBLIC AND USER MODE SET
SAROV3: DMOVEM T1,.USMUO ;NEW PC WITH TRAP CAUSING BITS CLEARED
MOVE P,[XWD MJOBPD##,.JDAT+JOBPDL##] ;SET UP A STACK
PUSHJ P,SCDCHK## ;CHECK IF WE SHOULD RESCHEDULE
USERAC ;SET USER AC BLOCK
XJRSTF .USMUO ;EXIT TO THE USER'S TRAP HANDLER
SAROV4: MOVEI T3,XP.LTH ;STUCK IN LOOP BIT
SAROV5: DMOVEM T1,.CPAPC## ;SAVE OLD PC FOR ERROR MESSAGE
HRRM T3,.CPAEF##
JRST SEPDL2
;HERE TO PROCESS EXEC STACK OVERFLOW TRAPS
SEPDLO::EXCH T1,.USMUP ;GET THE PC
MOVEM T1,.CPAPC##+1 ;STORE PC
HLLZ T1,.USMUO ;FLAGS
MOVEM T1,.CPAPC## ;SET AS ERROR FLAGS FOR ERRCON
TLNN T1,(XC.USR) ;WAS THIS IN USER MODE?
JRST DOPDL ;NOPE, EXEC, SOMETHING'S WRONG, CRASH
HRRI T1,AP.POV ;SET PUSH DOWN OVERFLOW FLAG
SEPDL1: HRRM T1,.CPAEF## ;IN .CPAEF SO ERRCON WILL GET CALLED
MOVE T1,.USMUP ;RESTORE T1
SEPDL2: SETOM .CPSCF## ;SET FORCED RESCHEDULING FLAG
SETOM .CPCKF## ;AND CLOCK FLAG
CONO PI,XI.RQC## ;REQUEST A CLOCK INTERRUPT
JRST . ;WAIT UNTIL CLOCK LEVEL HAPPENS AND THE JOB
; IS STOPPED IN USER MODE.
;SEE IF WE CAN EXTEND THE JOB'S PDL
DOPDL: EXCH T1,.USMUP ;SAVE PC AND RESTORE T1
MOVEM P,@.CPEPL## ;SAVE OLD P
HRRZS P ;SEE IF
CAMLE P,SYSSIZ## ;UUO OR INTERRUPT LEVEL
XJRST [MCSEC1+EXTPDL##] ;UUO, TRY TO EXTEND THE PDL
JRST EPOSTP## ;CAN'T RECOVER ON INTERRUPT LEVEL
;HERE TO PROCESS PAGE FAILURE TRAPS
SEILM:: SKIPE .CPPFT## ;IS THERE A PRE-EMPTIVE FAULT HANDLER?
XJRST .CPPFT## ;YES, TRANSFER CONTROL TO IT
CONI PI,.CPTPI## ;SAVE THE PI STATE
IFN FTKL10,<
CONSO PI,PI.ON ;IS THE PI SYSTEM ON?
JRST SEIL2 ;NO--PROCESS TRAP IMMEDIATELY
CONSZ PI,AP.ACO## ;APR CHANNEL ON?
CONSZ PI,AP.APP## ;YES--DID THIS TRAP HAPPEN AT CPU PI LEVEL?
JRST SEIL1 ;YES--PROCESS TRAP IMMEDIATELY
CONSZ APR,LP.PAR!LP.NXM ;NO--IS AN MB PARITY OR NXM INTERRUPT COMING?
JRST .-1 ;YES--LET IT RUN AND THEN CONTINUE THE TRAP
>; END IFN FTKL10
SEIL1:: CONO PI,PI.OFF ;NOW INSURE THAT PI'S ARE OFF
SEIL2: DATAI PAG,.CPTCX## ;SAVE THE TRAP CONTEXT
EXECAC ;WANT MONITOR'S AC BLOCK
JRSTF @[IC.UOU+.+1] ;INSURE USRIOT IS ON SO PXCT WORKS
MOVEM T1,.CPSTT## ;SAVE T1 TEMPORARILY
MAP T1,.UPMP ;IS THE UPT ACCESSIBLE?
;WOULD BE NICE TO CALL FLTCHK HERE BUT WE DON'T HAVE A P
TLNE T1,(MP.BAD) ;BAD MAPPING?
JRST SEILUP ;YES
TLNE T1,(MP.WRT) ;MUST BE WRITABLE, TOO
TLNN T1,(MP.BTS) ;VALID MAPPING?
JRST SEILUP ;NO, REALLY BAD, QUIT NOW
LDB T1,[POINT 5,.USPFW,5] ;PICK UP PF CODE
IFN FTKL10,<CAIE T1,PF.ABF> ;IS THIS AN ADDRESS BREAK?
CAIGE T1,20 ;IS THIS A REAL PAGE FAULT
JRST SEILMA ;YES--GO PROCESS IT
IFN FTKL10,<CAIL T1,PF.ARP> ;IS IT A PARITY TRAP?
IFN FTKS10,<CAIL T1,PF.PAR> ;IS IT A PARITY OR NXM TRAP?
JRST PRTRP ;YES--GO PROCESS
CAIN T1,PF.PTP ;IS IT PAGE TABLE PARITY?
JRST PTPAR ;YES--GO PROCESS
IFN FTKL10,<
CAIN T1,PF.IID ;IS IT AN ILLEGAL INDIRECT ADDRESS?
JRST SEILMA ;YES--GO PROCESS IT
CAIE T1,PF.ISN ;IS IT AN ILLEGAL SECTION NUMBER?
CAIN T1,PF.PRV ;IS IT A PROPRIETARY VIOLATION?
JRST SEILMA ;YES--GO PROCESS
CAIN T1,PF.PRF ;IS IT A PAGE REFILL FAILURE?
STOPCD .,CPU,PRF ;++PAGE REFILL FAILURE
>; END IFN FTKL10
IFN FTKS10,<
CAIN T1,PF.IOP ;IS IT A UBA FAILURE?
JRST SEILMU ;YES, PROCESS
>; END IFN FTKS10
STOPCD .,CPU,IPC ;++ILLEGAL PAGE FAILURE TRAP CODE
;HERE ON A UNIBUS ADDRESSING FAILURE
;A USER MODE FAILURE CAN OCCUR IF THE USER HAS IOT, AND MAKES A
;STRAY REFERENCE. WE DON'T WANT TO KILL THE SYSTEM. ALLOW THE
;USER TO INTERCEPT (NOT APRENB, BUT PSI) SO CAN CHECK WHETHER A
;DEVICE IS PRESENT.
IFN FTKS10,<
SEILMU: DMOVEM T2,.CPST1## ;SAVE SOME MORE ACS
DMOVE T1,.USPFP ;FETCH THE PC THAT FAILED
SKIPE .USJOB## ;IF NULL JOB, IT'S EXEC MODE
TLNN T1,(XC.USR) ;USER MODE?
STOPCD .,STOP,UAF,DIEUAF ;++UNIBUS ADDRESSING FAILURE
DMOVEM T1,.CPAPC## ;USER MODE, CAN SIMPLY STOP JOB (USER HAS IOT)
MOVE T1,.USPFW ;GET THE ADDRESS THAT FAILED
MOVEM T1,.USMUP ;SAVE IT IN CASE NON-EXISTANT UBA
TLZ T1,^-17 ;KEEP ONLY THE UBA NUMBER
HRRI T1,UNBSTW ;POINT TO THE UBA STATUS REGISTER
XMOVEI T3,UBNOGD ;GET PAGE FAIL HANDLER
EXCH T3,.CPPFT## ;IN CASE OF ILLEGAL UBA
MOVEI T2,UNBNED!UNBTMO ;NON-EXISTANT DEVICE AND TIMEOUT
BCIO T2,(T1) ;CLEAR THE BITS
MOVEM T3,.CPPFT## ;RESTORE THE USUAL PAGEFAIL HANDLER
DMOVE T2,.CPST1## ;AND THE EXTRA ACS
MOVE T1,.CPSTT## ;RESTORE T1
EXCH T1,.USMUP ;AND PUT IT WHERE SEPDL1 WANTS IT
MOVEM T1,.USPFW ;RESTORE ORIGINAL PFW IN CASE OF PSI TRAP
MOVEI T1,AP.ILM ;ILL MEM REF BIT
WRPI PI.ON ;RESTORE PI SYSTEM
JRST SEPDL1 ;AND GIVE ?ILL MEM REF AT PC MUMBLE
DIEUAF: PUSHJ P,INLMES## ;ADD SOME TEXT
ASCIZ /UBA = /
LDB T1,[POINT 4,.USPFW,17] ;GET UBA NUMBER
PUSHJ P,PRTDI8## ;PRINT IT
PUSHJ P,INLMES## ;MORE TEXT
ASCIZ /, register address = /
HRRZ T1,.USPFW ;GET ADDRESS
PJRST PRTDI8## ;PRINT AND RETURN
>; END IFN FTKS10
;HERE ON AR OR ARX PARITY TRAP (PAGE FAIL CODE 36 OR 37)
PRTRP: SKIPE .CPPSP## ;CORE SWEEP IN PROGRESS?
JRST SWTRP ;YES, JUST SAVE LOCATION OF FAILURE AND DISMISS
IFN FTKL10,<
MOVEI T1,@.CPEBR## ;NORMAL EBR
TRZ T1,LG.CSW ;TURN OFF CACHE LOAD BIT
CONO PAG,(T1) ;TURN OFF CACHE LOAD AND CLEAR PAGE TABLE
>; END IFN FTKL10
MOVE T1,.CPSTT## ;RESTORE T1
MOVEM 17,.CPA17## ;SAVE AC 17
MOVEI 17,.CPA00## ;MAKE BLT POINTER
BLT 17,.CPA17##-1 ;SAVE AC'S IN CPU DATA BLOCK
MOVE P,.CPEPD## ;SET UP ERROR STACK
DIELOK ;GRAB THE DIE INTERLOCK
PUSHJ P,CPUSTS## ;READ CPU STATUS
PUSHJ P,DVCSTS## ; AND DEVICE STATUS
MOVE J,.CPJOB## ;SET UP J WITH CURRENT JOB RUNNING
MOVE T1,JBTPPN##(J) ;GET ITS PPN
MOVEM T1,.CPEJN## ; AND SAVE IT
MOVE T1,JBTNAM##(J) ;GET ITS PROGRAM NAME
MOVEM T1,.CPEPN## ; AND SAVE IT
AOS .CPNPT## ;COUNT TOTAL NUMBER OF AR/ARX PARITY TRAPS
DMOVE T1,.USPFP ;GET THE PAGE FAIL PC
DMOVEM T1,.CPMDP## ;FOR ERROR IN JOB MESSAGES
DMOVEM T1,.CPPPD## ;STORE TROUBLE PC
TDZ T1,[7777,,-1] ;HOKEY IT UP
IOR T1,T2 ;SINCE A ONE WORD GETTAB
MOVEM T1,.CPPPC## ;SAVE THE PC FOR DAEMON
MOVEM T1,.CPMPP## ;ALSO OLD PLACE
MOVE T3,.USPFW ;GET THE PAGE FAIL WORD
MOVEM T3,.CPPFW## ;SAVE THE PAGE FAIL WORD FOR DAEMON
LDB T4,[POINT 5,T3,5] ;GET THE PAGE FAIL CODE
IFN FTKS10,<
CAIN T4,PF.NXM ;IS IT AN NXM?
SKIPA P4,[UE.NXM] ;YES, SET UP NXM FLAG
>; END IFN FTKS10
MOVEI P4,UE.PEF ;NO, SET UP PARITY ERROR FLAG
IFN FTKL10,<
SUBI T4,PF.ARP ;CONVERT TO INDEX INTO AC BLOCK 7
DATAO PAG,[LG.LAB+7B11] ;SET PREVIOUS ACS TO BLOCK 7
PXCT PX.MEM,[MOVE T4,(T4)] ;PICK UP BAD DATA WORD FROM BLOCK 7
>; END IFN FTKL10
IFN FTKS10,<
TRNE P4,UE.NXM ;IS THIS AN NXM?
JRST PRTRP2 ;YES--THEN THERE'S NO DATA TO PICK UP
WRUBR [SG.LAB+7B11] ;NO--SET PREVIOUS ACS TO BLOCK 7
PXCT PX.MEM,[MOVE T4,0] ;PICK UP BAD DATA WORD FROM BLOCK 7
>; END IFN FTKS10
EXECAC ;RESTORE MONITOR AC SETTINGS
MOVEM T4,.CPTBD## ;SAVE BAD DATA FOR DAEMON
IFN FTKL10,<
TLNE T1,(XC.USR) ;IS THE TRAP FROM EXEC MODE?
JRST PRTRP2 ;NO--CONTINUE
SKIPE .CPCHE## ;IS TRAP FROM CHANNEL ERROR REPORTING?
JRST PRTCHN ;YES--SPECIAL HANDLING
TLZ T2,-1-MXSECN ;GET JUST THE ADDRESS OF OFFENDING INSTRUCTION
TLZ T3,-1-MXSECN ;GET JUST THE ADDRESS OF OFFENDING REFERENCE
CAMN T2,T3 ;IS AN INSTRUCTION FETCH AT FAULT?
JRST PRTRP2 ;YES--CONTINUE
MOVE T1,(T2) ;NO--PICK UP THE OFFENDING INSTRUCTION
TLNN T1,740 ;IS THE AC FIELD NON-ZERO?
JRST PRTRP2 ;NO--CONTINUE
LSH T1,-^D27 ;YES--GET JUST THE OP CODE
CAIE T1,(XCT_-^D9) ;IS THIS A PXCT THEN?
JRST PRTRP2 ;NO--CONTINUE
MOVE T1,(T2) ;YES, GET THE PXCT BACK
TLZ T2,-1 ;ONLY 18 BITS
TLNN T1,37 ;SAFE TO FETCH THE OPERAND?
CAIN T2,(T1)
JRST PRTRP1 ;NO, NONE OF THESE ARE BLTS ANYWAYS
LDB T3,[POINT 9,(T1),8] ;GET OP-CODE OF PXCT'ED INSTRUCTION
CAIE T3,(BLT_-^D9) ;IS IT A BLT?
JRST PRTRP1 ;NO
TLNN T1,PX.SRC*40 ;BLT FROM USER TO EXEC?
JRST PRTRP2 ;NO, EXEC TO USER
PRTRP1: MOVSI T3,(PF.USR) ;YES--GET THE USER REFERENCE BIT
IORB T3,.CPPFW## ; AND FIX THE PAGE FAIL WORD (HARDWARE IS WRONG)
JRST PRTRP4 ;REFERENCE WAS VIRTUAL
>; END IFN FTKL10
PRTRP2: MOVE P1,.CPPFW## ;GET THE PAGE FAIL WORD
MOVE T3,.CPMAP## ;GET EPT ADDRESS FOR THIS CPU
PUSH P,.ERPIL/PAGSIZ(T3) ;SAVE MAPPING FOR TEMP SLOT
;THE CODE BETWEEN HERE AND PRTRP5 IS AN ELABORATE NOOP SINCE THE MICROCODE
; DOES NOT INDICATE A PHYSICAL REFERENCE IN THE PAGE FAIL WORD EVEN IF THE
; PARITY ERROR OCCURRED AS A RESULT OF THE MICROCODE MAKING A PHYSICAL REFERENCE.
; IT'S INCLUDED IN CASE THE MICROCODE GETS FIXED
; ACTUALLY, THE MICROCODE SHOULDN'T BE BLAMED SINCE ITS A HARDWARE BUG
IFN FTKL10,<
; TLNE P1,(PF.PHY) ;A PHYSICAL REFERENCE?
; JRST PRTRP4 ;NO, CALCULATE PHYSICAL FROM VIRTUAL ADDRESS
;HERE TO PRETEND PF.PHY WAS ON AND REFERENCE POSSIBLE PHYSICAL LOCATIONS
TLZ P1,(MP.NAD) ;ISOLATE PHYSICAL ADDRESS
CAILE P1,PG.BDY ;COULD THE REFERENCE HAVE BEEN TO A PAGE MAP?
JRST PRTRP3 ;NO, THEN P1 IS THE REAL PHYSICAL ADDRESS
;IF THE PAGE FAIL WORD IS LESS THAN 777, THE REFERENCE COULD HAVE BEEN
; AN EPT OR UPT RELATIVE PHYSICAL REFERENCE MADE BY THE MICROCODE. TRY
; REFERENCING THAT LOCATION IN THE APPROPRIATE MAP TO SEE IF BAD PARITY
SKIPL .CPPFW## ;REFERENCE TO THE EXEC ADDRESS SPACE?
CONI PAG,P1 ;YES, GET THE PAGE NUMBER OF THE EPT
SKIPGE .CPPFW## ;OR A REFERENCE TO USER ADDRESS SPACE?
DATAI PAG,P1 ;YES, GET THE PAGE NUMBER OF THE UPT
ANDI P1,LG.UPT ;ISOLATE THE PAGE NUMBER
LSH P1,P2WLSH ;PHYSICAL ADDRESS OF THE MAP
IOR P1,.CPPFW## ;PHYSICAL ADDRESS OF REFERENCE
TLZ P1,(MP.NAD) ;CLEAR CRUFT
PUSHJ P,TRYREF ;TRY REFERENCING THE LOCATION IN THE MAP
JRST PRTRP5 ;FAILED, STORE IT
JRST PRTRP4 ;DIDN'T FAIL, ASSUME REFERENCE TO USER OR EXEC
; PAGE 0
;EVEN THOUGH NOT A REFERENCE TO PAGE 0, STILL COULD BE A PHYSICAL REFERENCE
;(SPT,CST)
PRTRP3: PUSHJ P,TRYREF ;SEE IF BAD PARITY IN PHYSICAL LOCATION
JRST PRTRP5 ;YES, STORE PHYSICAL ADDRESS
>; END IFN FTKL10
;HERE IF WE BELIEVE THAT THE ADDRESS IN THE PAGE FAIL WORD IS REALLY A
; VIRTUAL ADDRESS. MUST BE TRUE OR THE PARITY ERROR WAS SPURIOUS
PRTRP4: MOVE T4,[PXCT PX.MEM,[MAP P1,(P1)]] ;SET UP PXCT OF MAP INSTRUCTION
SKIPL .CPPFW## ;IS THIS A USER CONTEXT REFERENCE?
TLZ T4,(PX.MEM,) ;NO--THEN PXCT BECOMES REGULAR XCT
MOVE P1,.CPPFW## ;NOT PHYSICAL REFERENCE, GET VIRTUAL ADDRESS
XCT T4 ;DO A MAP TO TURN PF WORD INTO PHYS ADDR IN P1
PRTRP5: MOVEM P1,.CPPBA## ;SAVE BAD PHYSICAL ADDR FOR DAEMON
TLZ P1,(MP.NAD) ;GET RID OF LEFT HALF STUFF
ROT P1,W2PLSH ;TURN RH OF P1 INTO PAGE NUMBER OF BAD LOC
PUSHJ P,MAPREF ;SETUP MAPPING FOR RETRY REFERENCES
LSH P1,-^D27 ;TURN P1 INTO WORD NUMBER WITHIN PAGE
ADDI P1,.ERPIL ;AND GET PAGE NUMBER CORRESPONDING TO MAP SLOT
IFN FTKL10,<MOVEI T1,[ASCIZ . AR/ARX parity trap.]>
IFN FTKS10,<
TRNE P4,UE.NXM ;IS THIS AN NXM?
SKIPA T1,[[ASCIZ / non-existent memory trap/]] ;YES
MOVEI T1,[ASCIZ / parity trap/] ;NO
>; END IFN FTKS10
PUSHJ P,PRMPC ;ANNOUNCE ERROR
MOVEI T1,[ASCIZ /Page fail word = /]
MOVE T2,.CPPFW##
PUSHJ P,PRMHW ;PRINT THE PAGE FAIL WORD
MOVEI T1,[ASCIZ /Mapped page fail address = /]
MOVE T2,.CPPBA##
PUSHJ P,PRMHW ;PRINT THE MAP WORD (PHYS. ADDRESS)
MOVEI T1,[ASCIZ /Incorrect contents = /]
MOVE T2,.CPTBD##
IFN FTKS10,<TRNN P4,UE.NXM> ;NO DATA TO PRINT ON NXM
PUSHJ P,PRMHW ;PRINT THE BAD DATA
MOVEI T1,[ASCIZ /CONI PI, = /]
MOVE T2,.CPTPI##
PUSHJ P,PRMHW ;PRINT THE CONI PI BITS
SETZ P2, ;CLEAR FLAG REGISTER
IFN FTKL10,<
CONSO PAG,LG.CSL ;IS THE CACHE ON?
JRST PRTRP6 ;NO
TRO P2,PFCPF3 ;REMEMBER IT'S IN USE
SWPVA ;SWEEP WRITTEN ENTRIES BACK TO MEMORY
CONSO APR,LP.CSD ;SWEEP BUSY?
JRST .-1 ;WAIT FOR DONE
CONO APR,LP.CSF!LP.CSD+APRCHN## ;CLEAR CACHE SWEEP DONE
CONSO APR,LP.PAR ;MB PARITY DURING SWEEP?
JRST PRTRP6 ;NO--START RETRIES
TRO P2,PFCPF4 ;YES--REMEMBER THIS PROBLEM
MOVEI T1,[ASCIZ /MB parity error occurred during cache sweep prior to retry attempt.
ERA = /]
RDERA T2 ;PICK UP THE ERA
PUSHJ P,PRMHW ;PRINT MESSAGE AND ERA
PUSHJ P,CLRSBD## ;CLEAR MEMORY CONTROLLERS
CONO APR,LP.CSF!LP.SBE!LP.PAR+APRCHN## ;CLEAR THE APR
;HERE TO START RETRIES-FIRST WITH CACHE OFF
PRTRP6: MOVE T1,.CPPBA## ;BAD PHYSICAL ADDRESS
TLZ T1,(MP.NAD) ;CLEAR LEFT HALF JUNK
LSH T1,W2PLSH ;CONVERT TO PAGE NUMBER
IDIVI T1,^D36 ;INDEX INTO NXM TABLE
MOVE T2,BITTBL##(T2) ;BIT IN NXM TABLE
TDNE T2,NXMTAB##(T1) ;PAGE ALREADY KNOWN TO BE IN NON-EXISTANT MEMORY?
JRST [SETZ P1,
JRST PRHMX] ;DON'T REFERENCE NON-EXISTANT MEMORY
MOVEI T1,@.CPEBR## ;GET NORMAL CONO PAG, BITS
TRZ T1,LG.CSW!LG.CSL ;TURN OFF LOOK AND LOAD
CONO PAG,(T1) ;MAKE SURE CACHE IS OFF
>; END IFN FTKL10
PUSHJ P,PRTRY ;REFERENCE LOCATION WITHOUT CACHE
JRST PRHMF ;RETRIES FAILED! HARD MEMORY FAILURE
;HERE WE KNOW WE CAN RECOVER THE USER
MOVEM T1,.CPTGD## ;SAVE THE GOOD DATA FOR ERROR REPORTING
AOS .CPSAR## ;UPDATE COUNTER OF SOFT AR/ARX PARITY ERRORS
HRRM T3,.CPPTR## ;STORE RETRY COUNT
IFN FTKL10,<
TRNN P2,PFCPF3 ;WAS CACHE ON WHEN WE STARTED?
JRST PRTRP8 ;NO--GO FINISH UP
;HERE RESTORE GOOD DATA TO THE CACHE LOCATION
MOVEI W,@.CPEBR## ;GET NORMAL EBR
MOVE U,W ;2ND COPY
TRZ U,LG.CSW ;TURN OFF LOAD IN THIS ONE
MOVE S,T1 ;SETUP GOOD DATA TO WRITE TO CACHE
MOVE T1,[CONO PAG,(W)] ;TURN ON CACHE LOOK & LOAD
MOVE T2,[MOVEM S,(P1)] ;REWRITE GOOD DATA TO CACHE
MOVE T3,[CONO PAG,(U)] ;TURN OFF CACHE LOAD
MOVE T4,[JRST PRTRP7] ;GET BACK TO THIS CODE
JRST T1 ;EXECUTE THE INSTRUCTIONS IN THE AC'S
;SO THEY DON'T GET INTO POSSIBLY BAD CACHE
;NOW RETRY REFERENCE WITH CACHE ON, CACHE STILL HAS LOOK BIT ON BUT LOAD OFF
PRTRP7: PUSHJ P,PRTRY ;REFERENCE LOCATION
JRST PRHCF ;RETRIES FAILED! HARD CACHE FAILURE
SWPIA ;INVALIDATE CACHE BUT DON'T TOUCH CORE
CONSO APR,LP.CSD ;SWEEP BUSY?
JRST .-1 ;WAIT FOR DONE
CONO APR,LP.CSF!LP.CSD+APRCHN## ;CLEAR CACHE SWEEP DONE
CONO PAG,@.CPEBR## ;TURN ON CACHE LOOK & LOAD
>; END IFN FTKL10
;HERE IF RETRIES WERE SUCCESFUL, LOG SOFT ERROR AND DISMISS
PRTRP8:
IFN FTKS10,<TRO P2,PFCPF0> ;INDICATE WE'RE A KS10
HRLM P2,.CPPTR## ;SAVE STATUS FLAGS FOR ERROR REPORTING
IFN FTKL10,<DPB T3,[POINT 9,.CPPTR##,26]> ;PUT CACHE RETRY COUNT HERE
MOVE T3,.CPMAP## ;GET EPT ADDRESS FOR THIS CPU
POP P,.ERPIL/PAGSIZ(T3)
IFN FTKL10,<
PUSHJ P,CLRSBD## ;CLEAR MEMORY CONTROLLERS
CONO APR,LP.CSF!LP.SBE!LP.PAR+APRCHN## ;CLEAR ANY APR ERRORS
>; END IFN FTKL10
MOVEI T1,[ASCIZ /Retry successful! Correct contents = /]
MOVE T2,.CPTGD
PUSHJ P,PRMHW ;PRINT SUCCESS AND GOOD DATA
MOVEI T1,EDELIM## ;GET ADDRESS OF TEXT
PUSHJ P,PRMSG ;PRINT END DELIMITER
PUSHJ P,DAELOG ;LOG THE ERROR
JRST PTXIT ;EXIT THE TRAP
;LOCAL ROUTINE TO SETUP A MAP SLOT TO MAKE PHYSICAL REFERENCES
;RETURNS +1 ALWAYS
;PRESERVES LEFT HALF OF P1, CLOBBERS RIGHT HALF
MAPREF: MOVE T3,.CPMAP## ;GET PAGE NUMBER OF EPMP FOR THIS CPU
HRRM P1,.ERPIL/PAGSIZ(T3) ;PAGE NUMBER
HRRI P1,(<PM.DCD>B2+PM.WRT+PM.PUB) ;ACCESSIBLE AND WRITABLE
HRLM P1,.ERPIL/PAGSIZ(T3)
CLRPT .ERPIL ;CLEAR OUT OLD ENTRY FOR .ERPIL
POPJ P, ;RETURN
;LOCAL ROUTINE TO REFERENCE A PHYSICAL ADDRESS
;ENTER WITH P1 = PHYSICAL ADDRESS TO BE REFERENCED
;RETURNS +1 IF LOCATION CONTAINS BAD PARITY
;RETURNS +2 IF CONTENTS OK
TRYREF: PUSHJ P,SAVE1## ;SAVE PHYSICAL ADDRESS
LSH P1,W2PLSH ;PAGE TO MAP
PUSHJ P,MAPREF ;SETUP MAPPING TO REFERENCE PHYSICAL ADDRESS
MOVE P1,-1(P) ;GET BACK PHYSICAL ADDRESS
ANDI P1,PG.BDY ;WORD NUMBER WITHIN THE PAGE
ADDI P1,.ERPIL ;VIRTUAL ADDRESS OF WORD TO TRY
; PJRST PRTRY ;REFERENCE THE WORD AND SEE IF IT CONTAINS
; BAD PARITY
;LOCAL RETRY ROUTINE
;RETURNS +1 IF RETRIES FAIL
;RETRUNS +2 IF ANY RETRY WINS
; T1/GOOD DATA
; T3/RETRY WHICH SUCCEEDED (FIRST =1)
PRTRY: MOVEI T3,1 ;INIT RETRY COUNTER
XMOVEI T2,TRYBAD ;GET TEST TRAP ADDRESS
EXCH T2,.CPPFT## ;EXCHANGE WITH WHAT'S THERE NOW
PUSH P,.USPFP ;IF A TRAP HAPPENS, HOW WE GOT HERE IS LOST
PUSH P,.USPFP+1 ;SECOND HALF
PRTY1: TRO P2,PFCPF0 ;NOTE THIS IS TEST REFERENCE
IFN FTKS10,<WREBR @.CPEBR##> ;INVALIDATE CACHE
MOVE T1,0(P1) ;TRY THE REFERENCE
TRZ P2,PFCPF0 ;CLEAR THE REFERENCE FLAG
TRZN P2,PFCPF2 ;ERROR DURING REFERENCE?
JRST PRTY2 ;NO--GIVE A GOOD RETURN
CAIGE T3,TRPTRY ;YES--RETRY COUNT EXHAUSTED?
AOJA T3,PRTY1 ;NO--TRY AGAIN
SKIPA ;YES--GIVE AN ERROR RETURN
PRTY2: AOS -2(P) ;SET FOR SKIP RETURN
POP P,.USPFP+1 ;AND SECOND WORD
POP P,.USPFP ;RESTORE OLD CONTENTS
MOVEM T2,.CPPFT## ;RESTORE STANDARD TRAP ADDRESS
POPJ P, ;EXIT
;HERE ON TRAPS OCCURING DURING RECOVERY ATTEMPTS
TRYBAD: TRNN P2,PFCPF0 ;ARE WE HERE BECAUSE OF TEST REFERENCE?
STOPCD .,STOP,UPF ;++UNEXPECTED PAGE FAIL
LDB T1,[POINT 5,.USPFW,5] ;GET PAGE FAIL CODE
IFN FTKL10,<CAIE T1,PF.ARP> ;AR PARITY ERROR?
IFN FTKS10,<CAIGE T1,PF.PAR> ;PARITY ERROR OR NXM?
STOPCD .,STOP,WPT ;++WRONG PARITY TRAP
TRO P2,PFCPF2 ;YES--INDICATE ERROR
AOS .USPFP+1 ;RETURN TO TEST REFERENCE + 1
XJRSTF .USPFP ;RETURN
;CACHE HAS LOOK ON BUT NOT LOAD
;HERE IF CACHE RETRIES FAIL WE MAY TURN OFF CACHE NOW
IFN FTKL10,<
PRHCF: SWPIA ;INVALIDATE CACHE BUT DON'T TOUCH CORE
CONSO APR,LP.CSD ;SWEEP BUSY?
JRST .-1 ;WAIT FOR DONE
CONO APR,LP.CSF!LP.CSD+APRCHN## ;CLEAR CACHE SWEEP DONE
MOVEI T1,@.CPEBR## ;INITIAL EBR
TRZ T1,LG.CSL!LG.CSW ;TURN OFF THE LOOK BIT FOR SAFETY
CONO PAG,(T1) ;MAY LEAVE IT OFF
TRO P2,PFCPF2 ;SET THE CACHE FAILED BIT FOR ERROR REPORTING
AOS T1,.CPCEC## ;COUNT THIS FAILURE
CAIGE T1,CCHEMX ;EXCEEDED ALLOWABLE?
JRST PRHC1 ;NO-TURN IT BACK ON
MOVEI T1,[ASCIZ /Three non-recoverable cache parity errors
have occurred since processor started.
*** CACHE HAS BEEN TURNED OFF. ***/]
PUSHJ P,PRMSG ;ANNOUNCE CACHE DESELECT
MOVEI T1,LG.CSL!LG.CSW;TURN OFF LOOK & LOAD BITS
ANDCAM T1,.CPEBR## ;BITS NOW CLEARED SO OTHERS
; CAN'T TURN IT ON BY ACCIDENT
TRO P2,PFCPF5 ;SET CACHE DESELECTED FLAG FOR ERROR REPORTING
JRST PRTRP8 ;NOW CLEAN UP AND RETURN TO USER
;HERE TO TURN THE CACHE BACK ON
PRHC1: CONO PAG,@.CPEBR## ;TURN IT ON
JRST PRTRP8 ;AND RETURN TO USER
>; END IFN FTKL10
;HERE WHEN RETRIES FROM MEMORY FAIL
PRHMF:
IFN FTKS10,<TRNN P4,UE.NXM> ;DON'T ZERO IF NXM
SETZM (P1) ;ZERO (AND RE-WRITE) THE ROTTEN LOCATION ALSO
PUSH P,P2 ;SAVE P2
PUSH P,T3 ;SAVE T3
PUSHJ P,PRTRY ;NOW SEE IF IT'S REALLY HARD (MEMORY BROKEN)
TDZA P1,P1 ;IT IS, SET P1 = 0
SETO P1, ;IT'S NOT, SET P1 = -1
POP P,T3 ;RESTORE T3
POP P,P2 ;RESTORE P2
PRHMX: SETZM .CPTGD## ;ZERO "GOOD DATA" SINCE WE DIDN'T GET ANY
MOVE T1,.CPMAP## ;GET EPT ADDRESS FOR THIS CPU
POP P,.ERPIL/PAGSIZ(T1)
AOS .CPHPT## ;BUMP HARD (AR/ARX) PARITY TRAP COUNT
IFN FTKL10,<
SWPIA ;INVALIDATE CACHE BUT DON'T TOUCH CORE
CONSO APR,LP.CSD ;SWEEP BUSY?
JRST .-1 ;WAIT FOR DONE
PUSHJ P,CLRSBD## ;CLEAR MEMORY CONTROLLERS
CONO APR,LP.CSF!LP.SBE!LP.PAR!LP.CSD+APRCHN## ;CLEAR THE APR
>; END IFN FTKL10
TRO P2,PFCPF1+IFN FTKS10,<PFCPF0> ;SAY HARD ERROR FOR ERROR REPORTING
HRLM P2,.CPPTR## ;SAVE FLAGS
HRRM T3,.CPPTR## ;SAVE RETRY COUNT FOR ERROR REPORTING
IFN FTKL10,<CONO PAG,@.CPEBR##> ;TURN THE CACHE BACK ON
IFN FTKS10,<
TRNE P4,UE.NXM ;IF THIS IS A NXM, MESSAGE IS DIFFERENT
SKIPA T1,[[ASCIZ /Retry unsuccessful./]]
>; END IFN FTKS10
MOVEI T1,[ASCIZ /Retries unsuccessful. Offending location zeroed./]
PUSHJ P,PRMSG ;ANNOUNCE FAILURE
PUSHJ P,DAELOG ;CALL DAEMON TO LOG THE ERROR
MOVE T1,.CPPPC## ;GET THE TRAP PC
TLNE T1,(XC.USR) ;IS THE TRAP FROM USER MODE?
JRST PRHMF2 ;YES--GO KILL USER
HRRZ T1,.CPPFW## ;GET THE PROBLEM ADDRESS
SKIPGE .CPPFW## ;IS THIS A USER CONTEXT REFERENCE?
JRST PRHMF1 ;YES--GO CHECK IF AT SCHED OR PI LEVEL
MOVE T2,SYSLEN## ;NO--GET LENGTH OF MONITOR'S HIGH SEG
ADDI T2,MONORG##-1 ;FORM EVA OF THE TOP OF THE HIGH SEG
CAIL T1,MONORG## ;IS THE ERROR IN THE
CAILE T1,(T2) ; MONITOR'S HIGH SEGMENT?
JRST PRHMF1 ;NO--GO CHECK OTHER THINGS
LSH T1,W2PLSH ;YES--FORM THE EXEC VIRTUAL PAGE NUMBER
MOVE T2,.CPPBA## ;GET THE MAPPED PHYSICAL ADDRESS
TDZ T2,[MP.NAD+PG.BDY] ;ONLY WANT BASE ADDRESS OF PAGE
PUSHJ P,PAGRPL## ;TRY TO REPLACE THIS CODE PAGE
JRST PARHLT## ;IT DIDN'T WORK
MOVEI T1,[ASCIZ /Replaced monitor code page from disk./] ;GET TEXT
PUSHJ P,PRMSG ;PRINT IT
MOVEI T1,EDELIM## ;GET END DELIMITER
PUSHJ P,PRMSG ;PRINT IT
PJRST PTXIT ;EXIT THE TRAP
PRHMF1: SETOM .CPREP## ;SET PARITY MSG FLAG IN CASE THIS IS FATAL
IFN FTKS10,<
TRNE P4,UE.NXM ;IS THIS A NXM?
SETZM .CPREP## ;YES--SET FLAG PROPERLY
>; END IFN FTKS10
SKIPN .CPISF## ;ARE WE IN THE SCHEDULER
CONSZ PI,PI.IPA ; OR ARE WE AT INTERRUPT LEVEL?
JRST PARHLT## ;YES--SORRY BUT WE CAN'T DO A THING
SKIPGE .CPPFW## ;WAS THIS A MONITOR REF TO USER SPACE AT UUO LVL?
JRST PRHMF4 ;YES--TREAT AS USER ERROR
CAIL T1,FYSORG ;NO--IS THE ERROR IN THE
CAILE T1,.LPPP-1 ; USER PER PROCESS AREA?
JRST PARHLT## ;NO--IT'S IN THE MONITOR DATA BASE, FATAL!
SETZ P2, ;YES, CALL IT A LOWSEG ERROR
JRST PRHMF7 ;TREAT AS FATAL USER ERROR
PRHMF2: TDNN P4,.CPCN1## ;IS USER ENABLED TO HANDLE THIS HIMSELF?
JRST PRHMF4 ;NO--GO ON
MOVE T2,JBTSTS##(J) ;YES--GET JOB STATUS WORD
TLNE T2,JACCT ;IS JOB PRIVILEGED?
JRST PRHMF3 ;YES--TRAP TO HIM
MOVE T2,JBTPPN##(J) ;NO--GET HIS PPN
CAME T2,FFAPPN## ;IS IT THE OPERATOR PPN
CAMN T2,UMDPPN## ; OR THE USER MODE DIAG PPN?
JRST PRHMF3 ;YES--LET'S TRAP TO HIM AS REQUESTED
JRST PRHMF4 ;NO--THEN WE IGNORE HIS TRAP REQUEST
PRHMF3: MOVEI T1,EDELIM## ;GET END DELIMITER
PUSHJ P,PRMSG ;PRINT IT
DIENLK ;RETURN THE DIE INTERLOCK
CONO PI,PI.ON ;TURN PI'S BACK ON
DMOVE T1,.CPPPD## ;GET THE PROBLEM PC
HRRZ T3,P4 ;PUT PARITY/NXM BIT HERE
JRST SAROV1 ;GO TRAP TO USER
PRHMF4: SETZ P2, ;SET FLAG ASSUMING LOW SEG ERROR
MOVE J,.CPJOB## ;GET THE OFFENDING JOB #
PUSH P,P1 ;SAVE P1
MOVE P1,.CPPFW## ;SECTION # IN RIGHT HALF
TLZ P1,-1^!MXSECN ;KEEP ONLY SECTION # IN LEFT HALF
TDZA T1,T1 ;START AT THE BEGINNING
PRHMF5: POP P,T1 ;LAST HIGH SEG LOOKED AT
MOVSS P1 ;PUT SECTION # IN RIGHT HALF
PUSHJ P,NXSSP1## ;FIND A(NOTHER) SEGMENT IN THAT SECTION
JRST PRHMF6 ;NO MORE
PUSH P,T1 ;SAVE HIGH SEG DATA BLOCK ADDR
PUSHJ P,HSVAD## ;GET LIMITS OF THAT HIGH SEG
MOVSS P1 ;SWAP HALVES AGAIN
CAIG T2,(P1) ;FAULT ADDR ABOVE BEGINNING OF HIGH SEG?
CAIL T1,(P1) ;AND BELOW TOP
JRST PRHMF5 ;NO, CHECK NEXT
POP P,J ;HIGH SEG DATA BLOCK ADDR
HRRZ J,.HBSGN(J) ;GET SEGMENT #
SETO P2, ;SET FLAG INDICATING HIGH SEG ERROR
PUSHJ P,HGHPAR## ;GO PROCESS JOBS USING THIS SEGMENT
PRHMF6: POP P,P1 ;RESTORE P1
PRHMF7: JUMPN P1,PRHMF8 ;IF MEMORY IS OK, DON'T MARK OUT PAGE
LDB T1,[POINT 13,.CPPBA##,26] ;GET THE PAGE NUMBER TO MARK OFF-LINE
PUSH P,T1 ;SAVE PAGE NUMBER
IDIVI T1,^D36 ;COMPUTE NXMTAB INDEX AND BITTBL INDEX
MOVE T2,BITTBL##(T2) ;GET CORRECT BIT TO SET
TDNE T2,NXMTAB##(T1) ;ALREADY A NON-EXISTANT PAGE?
JRST PRHMF8 ;YES, COULD HAPPEN IF REFERENCE TO A NON-EXISTANT ADDRESS
MOVE T3,[NXMTAB##,,OLDNXM##] ;SET UP BLT TO COPY NXMTAB
BLT T3,NXMTAB##+NXMTBL##-1 ;MAKE "OLD" COPY OF ERROR LOGGING
IORM T2,NXMTAB##(T1) ;MARK OUT PAGE IN NXMTAB
MOVEI T1,[ASCIZ /Location still bad after zeroing.
Setting off-line physical page /] ;GET TEXT
POP P,T2 ; AND PAGE NUMBER
PUSHJ P,PRMOC ;TELL HIM WHAT WE DID
MOVEI T1,.CSCPO ;CONFIG STATUS CHANGE CODE
PUSHJ P,MEMELG ;MAKE AN ERROR LOG ENTRY
PRHMF8: MOVEI T1,EDELIM## ;GET END DELIMITER
PUSHJ P,PRMSG ;PRINT IT
MOVE J,.CPJOB## ;GET JOB NUMBER
JUMPE P2,PRHMF9 ;GO STOP THIS JOB IF LOW SEG ERROR
MOVEI T1,JS.MPE ;DID HGHPAR SAY THAT THIS JOB
TDNE T1,JBTSTS##(J) ; COULDN'T BE SAVED?
JRST PRHMF9 ;YES--JUST GO STOP IT
DIENLK ;RETURN THE DIE INTERLOCK
CONO PI,PI.ON ;TURN THE PI'S BACK ON
IFN FTKS10,<
HLLZ T1,.CPMPS## ;GET CPU REQUESTS MEMORY SCAN BITS
HRRI T1,(P4) ;SET PARITY OR NXM BIT
IORM T1,.CPAEF## ;SET REQUEST
>; END IFN FTKS10
DMOVE T1,.USPFP ;GET PC/FLAGS DOUBLEWORD
DMOVEM T1,.CPPC## ;SAVE PC FOR RESCHEDULE
PJRST CLKSPD## ;RESCHEDULE THIS JOB TO RE-RUN WITH NEW HI SEG
PRHMF9: MOVSI T1,JACCT ;CLEAR JACCT SO DAMAGED PROGRAM
ANDCAM T1,JBTSTS##(J) ; WON'T HAVE PRIVILEGES
MOVEI T1,JS.MPE ;ASSUME PARITY ERROR IN JOB
IFN FTKS10,<
TRNE P4,UE.NXM ;IS IT A NXM?
MOVEI T1,JS.NXM ;YES--GET NXM IN JOB STATE BIT
>; END IFN FTKS10
IORM T1,JBTSTS##(J) ;SET IN JOB STATUS WORD
IFN FTKL10,<MOVSI T1,(CP.PXX)> ;GET PRINT REQUEST BIT
IFN FTKS10,<HLLZ T1,.CPMPS##> ;GET CPU REQUESTS MEMORY SCAN BITS
HRRI T1,(P4) ;SET PARITY OR NXM BIT
IORM T1,.CPAEF## ;SET REQUEST FOR PI 7
SETOM .CPSCF## ;FORCE RESCHEDULE
SETOM .CPCKF## ;SET FLAG FOR PI 7 INTERRUPT
DIENLK ;RETURN THE DIE INTERLOCK
CONO PI,XI.RQC## ;REQUEST PI 7
CONO PI,PI.ON ;ALLOW INTERRUPTS NOW (MAINLY PI 7)
PJRST ESTOP## ;GO STOP THIS JOB
;HERE ON TRAP DURING PARITY SWEEP
SWTRP: EXCH T1,.CPSTT## ;RESTORE T1, SAVE TRAP CODE
PUSH P,T1 ;SAVE T1
HRRZ T1,.USPFP+1 ;GET PC OF TRAP
CAIE T1,APRMPI ;BETTER MATCH THE SWEEP BLT ADDRESS
STOPCD .,STOP,NPI ;++NOT PARITY INSTRUCTION
MOVE T1,.USPFW ;GET THE PAGE FAIL WORD
MOVEM T1,.CPPFW## ;AND SAVE IT
IFN FTKL10,<
MOVE T1,.CPAER## ;GET ERA FROM INTERRUPT THAT SHOULD HAVE HAPPENED
MOVEM T1,.CPSTE## ;SAVE AS ERA CORRESPONDING TO THIS SWEEP TRAP
MOVE T1,.CPSTT## ;GET PAGE FAIL CODE
SUBI T1,PF.ARP ;CONVERT TO INDEX INTO AC BLOCK 7
DATAO PAG,[LG.LAB+07B11] ;SET PREVIOUS AC BLOCK TO 7
PXCT PX.MEM,[MOVE T1,(T1)] ;GET BAD DATA WORD FOR DAEMON
>; END IFN FTKL10
IFN FTKS10,<
WRUBR [SG.LAB+07B11] ;SET PREVIOUS AC BLOCK TO 7
PXCT PX.MEM,[MOVE T1,0] ;GET BAD DATA WORD FOR DAEMON
>; END IFN FTKS10
EXECAC ;RESTORE MONITOR'S AC BLOCK
MOVEM T1,.CPTBD## ;SAVE BAD DATA
SETOM .CPPTH## ;INDICATE ERROR ON SWEEP
MOVEI T1,3 ;BUMP RETURN PC BY 3 TO
ADDM T1,.USPFP+1 ; INDICATE A TRAP HAPPENED
POP P,T1 ;RESTORE T1
JRST PTXIT1 ;EXIT BACK TO SWEEP ROUTINE
;HERE ON TRAPS FROM CHANNEL ERROR REPORTING CODE
;NOTE: P3 IS THE AC USED IN THE CHANNEL ERROR CODE TO ACCESS DATA IN CORE
IFN FTKL10,<
PRTCHN: CONO PAG,@.CPEBR## ;RESTORE CACHE SETTINGS
DATAO PAG,.CPTCX## ;SET AC BLOCK TO ONE IN USE AT TIME OF TRAP
MOVE P3,.CPTBD## ;PUT ACCESSED DATA (THOUGH BAD) IN P3
EXECAC ;BACK TO MONITOR AC SETTINGS
AOS .USPFP+1 ;BUMP RETURN PC OVER MOVE INSTRUCTION
JRST PTXIT ;EXIT THE TRAP
>; END IFN FTKL10
;ROUTINE TO PRINT A MESSAGE PREFIXED BY "CPUx" AND
;FOLLOWED BY "AT EXEC(USER) PC XXXXXX"
; T1=MESSAGE ADDRESS
PRMPC: PUSHJ P,SAVE1## ;SAVE P1 TO REMEMBER ADDRESS OF MESSAGE
MOVE P1,T1 ;SAVE
IFN FTKL10,<PUSHJ P,SVPPC##> ;SWITCH TO SECONDARY PROTOCOL
PUSH P,.CPTOA## ;SAVE COMMAND OUTPUT ADDRESS
MOVEI T2,CTYWAT## ;GET ONE THAT DOESN'T USE PI SYS
MOVEM T2,.CPTOA##
MOVEI T1,SDELIM## ;GET ADDRESS OF TEXT
PUSHJ P,CONMES## ;PRINT START DELIMITER
MOVE T2,.CPLOG## ;GET THIS CPU'S NAME
PUSHJ P,PRNAME## ;PRINT IT
MOVE T1,P1 ;GET ADDRESS OF MESSAGE IN T1
PUSHJ P,CONMES## ;PRINT MESSAGE
DMOVE T1,.CPPPD## ;GET SAVED PC
PUSHJ P,DPCP## ;PRINT "AT EXEC/USER XXXXXX"
MOVEI T1,[ASCIZ / on /] ;SEPARATE FROM DATE/TIME
PUSHJ P,CONMES## ;PRINT IT
PUSHJ P,DATIME## ;PRINT DATE AND TIME
PUSHJ P,PCRLF## ;AND A CRLF
MOVEI T1,[ASCIZ /Job/];TELL THEM WHO WAS RUNNING
PUSHJ P,CONMES## ;PRINT "JOB"
PUSHJ P,PRJBNM## ;PRINT JOB INFO
MOVEI T1,[ASCIZ / was running
/]
PUSHJ P,CONMES## ;PRINT "WAS RUNNING"
PRMPC1: POP P,.CPTOA## ;RESTORE SCNSER ADDRESS
POPJ P, ;RETURN
;ROUTINES TO PRINT A MESSAGE FOLLOWED BY NUMBER IN HALFWORD OR OCTAL FORMAT
; T1=MESSAGE ADDRESS, T2=NUMBER
PRMOC: PUSHJ P,SAVE3## ;SAVE P1-P3
MOVEI P3,OCTPNT## ;GET ADDRESS OF OCTAL PRINT ROUTINE
JRST PRMHW1 ;GO TO COMMON CODE
PRMHW: PUSHJ P,SAVE3## ;SAVE P1-P3
MOVEI P3,HWDPNT## ;GET ADDRESS OF HALFWORD PRINT ROUTINE
PRMHW1: MOVE P1,T1 ;SAVE
MOVE P2,T2 ;SAVE
IFN FTKL10,<PUSHJ P,SVPPC##> ;SWITCH TO SECONDARY PROTOCOL
PUSH P,.CPTOA## ;SAVE COMMAND OUTPUT ADDRESS
MOVEI T2,CTYWAT## ;GET ONE THAT DOESN'T USE PI SYS
MOVEM T2,.CPTOA##
MOVE T1,P1 ;GET ADDRESS OF MESSAGE IN T1
PUSHJ P,CONMES## ;PRINT MESSAGE
MOVE T1,P2 ;GET NUMBER TO PRINT (IF ANY)
PUSHJ P,(P3) ;PRINT NUMBER IN DESIRED FORMAT
PUSHJ P,CRLF## ;END WITH CRLF
PJRST PRMPC1 ;FINISH UP
;ROUTINE TO PRINT A MESSAGE
; T1=MESSAGE ADDRESS
PRMSG: PUSHJ P,SAVE2## ;SAVE P1,P2 TO REMEMBER ADDRESS OF MESSAGE
MOVE P1,T1 ;SAVE
IFN FTKL10,<PUSHJ P,SVPPC##> ;SWITCH TO SECONDARY PROTOCOL
PUSH P,.CPTOA## ;SAVE COMMAND OUTPUT ADDRESS
MOVEI T2,CTYWAT## ;GET ONE THAT DOESN'T USE PI SYS
MOVEM T2,.CPTOA##
MOVE T1,P1 ;GET ADDRESS OF MESSAGE IN T1
PUSHJ P,CONMES## ;PRINT MESSAGE
PUSHJ P,CRLF## ;END WITH CRLF
PJRST PRMPC1 ;FINISH UP
;ROUTINE TO LOG AN ERROR + CPU AND DEVICE STATUS BLOCKS
DAELOG: SETZ T1, ;CAUSE ALLOCATION TO HAPPEN
XMOVEI T2,PARTBL ;POINT TO TRANSFER TABLE
PUSHJ P,XFRSEB## ;ALLOCATE CORE AND LOAD UP TABLE
JFCL ;NO CORE?
IFN FTKS10,<
MOVEI T3,.ERKSN ;GET NXM CODE
TRNE P4,UE.NXM ;IT IT AN NXM?
DPB T3,[POINT 9,.EBTYP(T1),8] ;OVERWRITE PARITY CODE
>; END IFN FTKS10
PUSHJ P,QUESEB## ;QUEUE UP BLOCK FOR DAEMON
PJRST RCDSTD## ;GO READ AND LOG CSB & DEVICE STATUS
PARTBL: SEBTBL (.ERKPT,PAREND,EX.SYE)
MOVE .CPPHY## ;(R00) PHYSICAL CPU NAME
MOVE .CPPPC## ;(R01) PC AT TIME OF TRAP
MOVE .CPPFW## ;(R02) PAGE FAIL WORD
MOVE .CPPBA## ;(R03) MAPPED PHYSICAL ADDRESS
MOVE .CPTBD## ;(R04) INCORRECT DATA
MOVE .CPTPI## ;(R05) CONI PI, AT TRAP
MOVE .CPEJN## ;(R06) JOB NUMBER
MOVE .CPEPN## ;(R07) JOB NAME
MOVE .CPTGD## ;(R10) CORRECT DATA
MOVE .CPPTR## ;(R11) RETRY WORD
MOVE .CPSAR## ;(R12) NUMBER OF RECOVERABLE TRAPS
MOVE .CPHPT## ;(R13) NUMBER OF NON-RECOVERABLE TRAPS
PAREND:! ;END OF TABLE
;HERE TO LOG MEMORY ONLINE/OFFLINE CHANGES
;CALL: MOVE T1, CODE ;CONFIGURATION STATUS CHANGE CODE
; PUSHJ P,MEMLOG
; <RETURN>
MEMELG::PUSH P,T1 ;SAVE CODE
MOVEI T1,3+<NXMTBL*2> ;3 DATA WORDS + 2 COPIES OF NXMTAB
PUSHJ P,ALCSEB## ;ALLOCATE CORE
JRST MEMEL1 ;NONE AVAILABLE?
XMOVEI T2,MELTBL ;POINT TO TRANSFER TABLE
PUSHJ P,XFRSEB## ;LOAD IT UP
JFCL ;SHOULDN'T FAIL
MOVE T2,(P) ;GET CODE BACK
HRLM T2,.EBHDR+2(T1) ;STORE CONFIG STATUS CHANGE CODE
MOVSI T2,OLDNXM## ;POINT TO OLD COPY OF NXMTAB
HRRI T2,.EBHDR+3(T1) ;MAKE A BLT POINTER
MOVEI T3,.EBHDR+3+NXMTBL##(T1) ;COMPUTE END OF BLT
BLT T2,-1(T3) ;COPY OLD NXMTAB INTO RECORD
HRLI T2,NXMTAB## ;POINT TO CURRENT NXMTAB
ADDI T3,NXMTBL## ;COMPUTE END OF BLT
BLT T2,-1(T3) ;COPY CURRENT NXMTAB INTO RECORD
PUSHJ P,QUESEB## ;QUEUE UP RECORD FOR ERROR LOGGING
MEMEL1: MOVE T2,[NXMTAB##,,OLDNXM##] ;SET UP BLT
BLT T2,OLDNXM##+NXMTBL##-1 ;MAKE A "NEW" OLD COPY
JRST TPOPJ## ;PHASE STACK AND RETURN
;MEMORY ONLINE/OFFLINE TRANSFER TABLE FOR ERROR.SYS LOGGING
MELTBL: SEBTBL (.ERCSC,MELEND,<EX.SYE!EX.AVL>)
MOVE [-NXMTBL##,,10] ;(R00) OFFSET TO OLD NXMTAB
MOVE [-NXMTBL##,,10+NXMTBL##] ;(R01) OFFSET TO NEW NXMTAB
MOVEI 1 ;(R02) REASON CODE,,PAGING MACHINE
MELEND:! ;END OF TABLE
;HERE ON PAGE TABLE PARITY TRAP (PF CODE 25)
PTPAR: CONO PAG,@.CPEBR## ;CLEAR THE PAGE TABLE
AOS .CPPTP## ;COUNT A PAGE TABLE PARITY ERROR
MOVE T1,.CPSTT## ;RESTORE T1
MOVEM 17,.CPA17## ;SAVE 17
MOVEI 17,.CPA00## ;MAKE BLT POINTER
BLT 17,.CPA17##-1 ;SAVE ACS IN CPU DATA BLOCK
MOVE P,.CPEPD## ;SET UP ERROR STACK
DIELOK ;GRAB THE DIE INTERLOCK
SKIPGE T1,.CPPTF## ;PICK UP COUNT OF PAGE TABLE FAILURES
MOVEI T1,^D4 ;NONE YET, INITIALIZE FOR 3 RETRIES
SOJG T1,PTPAR1 ;IF COUNT HASN'T EXPIRED, JUST RETRY.
; COUNTER IS RESET ON EVERY CLOCK TICK.
MOVE J,.CPJOB## ;CURRENT JOB
MOVE T1,.CPPPD## ;PC
TLNE T1,(XC.USR) ;IN USER MODE?
JRST PRHMF9 ;YES, JUST ZAP THE JOB
DIENLK ;UNLOCK SO CAN CALL DIE
STOPCD .,CPU,PGTPAR, ;++PAGE TABLE PARITY
PTPAR1: MOVEM T1,.CPPTF## ;REMEMBER COUNTER
DMOVE T1,.USPFP ;GET PAGE FAIL PC
DMOVEM T1,.CPPPD## ;SAVE FOR PRINT ROUTINE
MOVE J,.CPJOB## ;SET UP J WITH CURRENTLY RUNNING JOB
MOVEI T1,[ASCIZ / page table parity trap/]
PUSHJ P,PRMPC ;ANNOUNCE ERROR
MOVEI T1,[ASCIZ /Page fail word = /]
MOVE T2,.USPFW
MOVEM T2,.CPPFW## ;FOR CRASH
PUSHJ P,PRMHW ;PRINT THE PAGE FAIL WORD
MOVEI T1,[ASCIZ /CONI PI, = /]
MOVE T2,.CPTPI##
PUSHJ P,PRMHW ;PRINT THE CONI PI BITS
MOVEI T1,EDELIM## ;GET ADDRESS OF TEXT
PUSHJ P,PRMSG ;PRINT END DELIMITER
PTXIT: DIENLK ;RETURN THE DIE INTERLOCK
MOVSI 17,.CPA00## ;BLT POINTER TO RESTORE ACS
BLT 17,17 ;RESTORE AC'S
PTXIT1: DATAO PAG,.CPTCX## ;RESTORE THE CONTEXT AT TIME OF TRAP
EXCH T1,.CPTPI## ;GET PI'S AT TRAP ENTRY, SAVE T1
TRNE T1,PI.ON ;WERE THE PI'S ON?
CONO PI,PI.ON ;YES--TURN PI'S BACK ON
EXCH T1,.CPTPI## ;RESTORE T1
XJRSTF .USPFP ;RESTORE FLAGS AND RETURN
;HERE ON REAL PAGE FAULTS OR ADDRESS BREAKS
SEILMA: MOVE T1,.CPSTT## ;RESTORE T1
CONO PI,PI.ON ;TURN PI SYSTEM BACK ON
SKIPN .CPTPC## ;SKIP NEXT IF EXEC PAGE FAULT IN PROGRESS
DMOVEM T1,.CPST1## ;SAVE T1 AND T2 IN CASE OF CRASH
DMOVE T1,.USPFP ;GET THE PAGE FAIL PC
DMOVEM T1,.CPAPC## ;STORE IT AS POTENTIAL ERROR PC
MOVE T2,.USPFW ;GET THE USER PAGE FAIL WORD
MOVEM T2,.CPPFW## ;SAVE PAGE FAULT WORD FOR CRASH
TLNE T1,(XC.USR) ;PAGE FAULT IN EXEC MODE?
JRST SEILM1 ;NO, PROCEED
IFN FTKL10,<
LDB T2,[POINT 5,T2,5] ;CLEAR ALL BUT THE PAGE FAIL CODE
CAIN T2,PF.ABF ;WAS THE PAGE FAULT AN ADDRESS BREAK?
JRST SEILM2 ;YES, REMEMBER IT AND GO AWAY
>; END IFN FTKL10
JRST SEJLM1 ;NO, EXEC ILL MEM REF, LOOK FOR ERJMP
;HERE ON EXEC MODE ADDRESS BREAK (ACS RESTORED)
IFN FTKL10,<
SEILMX: DATAO APR,[EXP 0] ;TURN OFF ADDRESS BREAK
DMOVE T1,.CPST1## ;RELOAD T1 & T2
MOVEM 17,.CPA17## ;SAVE AC 17
MOVEI 17,.CPA00## ;MAKE BLT POINTER
BLT 17,.CPA17##-1 ;SAVE AC'S IN CPU DATA BLOCK
LDB T1,[.CPABS##+S$PTRT] ;GET STOPCODE TYPE
EXCH T1,.CPST1## ;PUT IN A SAFE PLACE AND RESTORE T1
SKIPE .CPST1## ;ZERO MEANS NO STOPCODE
XCT .CPABS## ;CREATE SOME CHATTER
MOVEM T1,.CPST1## ;SAVE T1 AGAIN
XCT .CPABI## ;EXECUTE INSTRUCTION TO CALL SUBROUTINE
JFCL ;INCASE OF SKIP RETURN
MOVSI T1,(XC.AFI) ;ADDRESS FAILURE INHIBIT
IORM T1,.USPFP ;ALLOW INSTRUCTION TO BE EXECUTED
SKIPL .CPABW## ;WANT REPETITIVE ENABLE?
PUSHJ P,ABKCLM ;CLEAR ADDRESS BREAK CONDITIONS
MOVE T1,.CPABW## ;GET ADRESS BREAK CONDITIONS + ADDRESS
TLZE T1,(AB.REP) ;REPETITIVE ENABLE?
DATAO APR,T1 ;YES
MOVSI 17,.CPA00## ;SET UP BLT
BLT 17,17 ;RESTORE THE ACS
XJEN .USPFP ;AND PROCEED FROM ADDRESS BREAK
> ;END IFN FTKL10
;HERE IF USER PAGE FAULT
SEILM1: MOVE P,[XWD MJOBPD##,.JDAT+JOBPDL##] ;SETUP A PUSH DOWN LIST
SKIPN .USJOB ;NULL JOB?
STOPCD .,CPU,PFN ;++PAGE FAULT IN NULL JOB
PUSH P,.USPFP+1 ;SAVE USER'S PC
MOVE T3,T2 ;FAULT WAS IN USER MODE, SAVE PFC FOR
; POSSIBLE CALL TO USRFLT
LDB T2,[POINT 5,T2,5] ;CLEAR ALL BUT THE PAGE FAIL CODE
IFN FTKL10,<
CAIN T2,PF.ABF ;ADDRESS BREAK?
JRST SEILM2 ;YES, GO PROCESS
>; END IFN FTKL10
MOVE T4,.JDAT+JOBENB## ;GET APR ENABLE BITS
TRNE T4,AP.ILM ;IS USER ENABLED?
JRST SUILM ;YES--DO SUILM INSTEAD
HRRI T1,AP.ILM ;ILLEGAL MEMORY REFERENCE
IFN FTKL10,<
CAIN T2,PF.ISN ;ILLEGAL SECTION?
JRST SEPDL1 ;YES
CAIN T2,PF.PRV ;WAS IT A PROPRIETARY VIOLATION?
JRST [HRRI T1,AP.PPV ;INDICATE PROP VIO
JRST SEPDL1]
>; END IFN FTKL10
DMOVE T1,.USPFP ;GET DOUBLE WORD PC
PUSHJ P,USRFLT## ;SEE IF PAGE FAULT FOR A VM USER
; WILL NOT RETURN IF SO (DISPATCH TO USER)
HRRI T1,AP.ILM ;COULDN'T HANDLE IT - USER GETS ILL MEM REF
JRST SEPDL1 ;GO SAY "ILL. MEM. REF."
;HERE ON ADDRESS BREAK
IFN FTKL10,<
SEILM2: SKIPGE .CPABF## ;EXEC MODE ADDRESS BREAK ENABLED?
SKIPN .CPABW## ;AND AN ADDRESS SET?
CAIA ;DO NORMAL USER STUFF
JRST SEILMX ;HANDLE ADDRESS BREAK
DMOVE T1,.USPFP ;GET FAULT DOUBLE WORD PC
TLO T1,(XC.AFI) ;INHIBIT ADDRESS BREAK WHEN INSTR IS EXECUTED
DMOVEM T1,.CPPC## ;STASH WHERE PSISER CAN FIND IT
EXCH J,.CPJOB## ;GET JOB
PUSH P,W ;SAVE W IN CASE IN EXEC MODE
PUSHJ P,FNDPDS## ;FIND THE PDB
LDB T2,[POINT 9,.PDTMI##(W),17] ;GET THE PROCEED COUNT
SOSL T2 ;DECREMENT
DPB T2,[POINT 9,.PDTMI##(W),17] ;STORE IT BACK IF POSITIVE
POP P,W ;RESTORE W
JUMPG T2,SEILM6 ;CONTINUATION PC
;DON'T BREAK IF PROCEED COUNT .GT. 0
MOVE T2,JBTSTS##(J) ;IS THIS A JACCT
TLNN T2,JACCT ;JOB
JRST SEILM3 ;NOT JACCT
MOVE T2,JBTPPN##(J) ;YES, BUT IS
CAME T2,FFAPPN## ; HE GOD?
JRST SEILM6 ;NO-IGNORE BREAK
SEILM3: EXCH J,.CPJOB## ;UNDO LAST EXCH
TLNN T1,(XC.USR) ;PC IN USER MODE?
JRST SEILM5 ;NO, REMEMBER BREAK AND GO AWAY
MOVEM T1,.JDAT+JOBPD1## ;SAVE FLAGS
PUSH P,.CPPC##+1 ;AND PC
MOVE R,.CPADR## ;SETUP R
MOVE J,.CPJOB## ;JOB NUMBER FOR PSISER
SIGNAL C$ADRB ;SIGNAL THAT AN ADDRESS BREAK HAS OCCURED
SKIPA ;USER DOESN'T WANT TRAP
JRST SEILM8 ;INTERRUPT TO THE USER
PUSHJ P,TTYFUW## ;FIND THE USER'S TTY
PUSHJ P,INLMES## ;REPORT THE ADDRESS BREAK
ASCIZ /
%Address break/
DMOVE T1,.JDAT+JOBPD1## ;GET THE USER'S PC
PUSHJ P,DPCP## ;TELL HIM WHERE THE BREAK OCCURED
PUSHJ P,PSIERR## ;PENDING INTERRUPT?
JFCL
PJRST ERRGOU## ;YES, GIVE IT TO THE USER
;FALL INTO SEILM4
SEILM4: DMOVE T1,.JDAT+JOBPD1## ;GET USERS PC
DMOVEM T1,.CPPC## ;COULD HAVE CHANGED IF WE HAD TO WAIT
PUSHJ P,HOLD0## ;STOP THE JOB IN A CONTINUABLE STATE
PJRST WSCHD3##
SEILM5: MOVEI T2,JS.ASA ;AC'S ARE IN THE SHADOW AREA BIT
EXCH J,.CPJOB## ;JOB NUMBER
TDNE T2,JBTSTS##(J) ;SAVE/GET IN PROGRESS?
JRST SEILM6 ;YES, DON'T BOTHER THE USER WITH BREAKS ON THAT
MOVEI T2,JS.ABP ;ADDRESS BREAK HAPPENED DURING UUO PROCESSING BIT
IORM T2,JBTST2##(J) ;REMEMBER THAT THE BREAK HAPPENED
SEILM6: EXCH J,.CPJOB## ;RESTORE J
>; END IFN FTKL10
SEILM7: MOVE T1,.CPPC## ;GET FLAGS OF PC
TLNE T1,(XC.USR) ;BREAK OUT OF USER MODE?
JRST SEILM8 ;YES
DMOVE T1,.CPST1## ;RESTORE T1 AND T2
XJRSTF .CPPC## ;GO AWAY AND TELL THE USER ABOUT THE BREAK
; AT UUO EXIT
SEILM8: USERAC ;USER'S AC BLOCK
XJRSTF .CPPC## ;EXIT TO USER
;HERE IF AN ILL MEM REF OCCURED IN EXEC MODE, CHECK FOR ERJMP OR
;ERCAL BEFORE CALLING IT AN IME
SEJLM1: CONSO PI,PI.IPA ;AT INTERRUPT LEVEL?
JRST SEJLM2 ;NO, UUO LEVEL, OK
CONSO PI,PI.IPA-PI.IP7 ;YES - LEVEL 7?
SKIPN .CPISF## ;YES, FROM SCHEDULER?
JRST SEILME ;PI1 - PI6 OR NON-SCHEDULER PI7
SEJLM2: SKIPE .CPTPC## ;NESTING?
JRST @[0,,SEJLM6] ;YES, IT'S AN IME
.CREF PF.USR ;NOTE BIT WE'RE TESTING
SKIPL T2,.CPPFW## ;GET PAGE FAULT WORD, SKIP IF USER REF
JRST SEJLM3 ;NOT USER REFERENCE
PUSHJ P,UUOLVL## ;YES, AT UUO LEVEL?
JRST SEJLM3 ;NO
IFN FTPEEKSPY,<
PUSHJ P,SEJSPG ;SEE IF REFERENCE TO A SPY PAGE (PRESERVES ACS)
JRST UADERR## ;YES, BLAME THE USER
>; END IFN FTPEEKSPY
TLNN T2,(PF.ACC) ;VALID MAPPING?
JRST SEJLM3 ;NO, PROBABLY A REFERENCE TO A PAGE WITH AA OFF
TLNE T2,(PF.WRT) ;PAGE FAIL A WRITE VIOLATION?
PUSHJ P,[PUSHJ P,SAVT## ;SAVE VOLATILE ACS
MOVE T3,T2 ;PAGE FAIL WORD - ARGUMENT TO WLPFLT
PJRST WLPFLT##] ;WRITE ENABLE THE PAGE IF POSSIBLE
JRST SEJLM3 ;SPY PAGE OR PAGE IN A WRITE LOCKED HI SEG
DMOVE T1,.CPST1## ;RESTORE ACS
XJRSTF .USPFP ;TRY AGAIN WITH PAGE WRITE ENABLED
;LOOK FOR "ERJMP" OR "ERCAL" FOLLOWING FAILED INSTRUCTION
SEJLM3: DMOVE T1,.USPFP ;GET PC DOUBLEWORD AT FAULT
DMOVEM T1,.CPTPC## ;SAVE "TOP LEVEL" FAULT ADDRESS FOR ERJMP RETRY
MOVE T1,.USPFW ;GET PAGE FAIL WORD AT FAULT
MOVEM T1,.CPTPF## ;SAVE "TOP LEVEL" PAGE FAIL WORD
IFN FTXMON,<
TLNE T2,-1 ;FAULT OCCUR IN A NON-ZERO SECTION?
XJRST [MCSEC1+.+1] ;YES, GO INTO SECTION 1
>; END IFN FTXMON
LDB T1,[POINT 22,T2,35] ;GET ADDRESS PART OF PAGE FAIL WORD
SKIP (T1) ;TOUCH PAGE FAULT PC LOCATION AND
LDB T2,[POINT 13,1(T1),12] ;GET INSTRUCTION FOLLOWING
; IF THE PC JUMPED OFF INTO THE BOONIES
; THEN THIS WILL PAGE FAULT AND WE WILL
; KNOW WE HAVE A REAL IME
CAIE T2,<ERJMP>_-^D23 ;IS IT AN ERJMP?
JRST SEJLM6 ;NO, THEN WE HAVE AN IME
MOVE T2,1(T1) ;GET ENTIRE ERJMP EXPRESSION
MOVEM T2,.CPEJT## ;SAVE WHERE WE CAN FIND IT
IFN FTXMON,<
TLNN T1,-1 ;NON ZERO SECTION?
JRST SEJLM4 ;NO, DO SECTION 0 CALCULATION
TLZ T2,777740 ;NON-ADDRESSING PART OF ERJMP
TLO T2,(IFIW) ;MAKE A USABLE INDIRECT
MOVEM T2,.CPEJT## ;SAVE WHERE WE CAN FIND IT
DMOVE T1,.CPST1## ;RESTORE T1&T2
XMOVEI T1,@.CPEJT## ;RESOLVE ADDRESS OF ERJMP
JRST SEJLM5 ;JOIN COMMON CODE
>; END IFN FTXMON
SEJLM4: DMOVE T1,.CPST1## ;RESTORE T1&T2
MOVEI T1,@.CPEJT## ;RESOLVE ADDRESS OF ERJMP
;IF THIS IMES .CPTPC/.CPTPF HAVE ORIGINAL
; TRAP PC AND PAGE FAIL WORD
SEJLM5: MOVEM T1,.CPAPC##+1 ;SET CONTINUATION ADDRESS
MOVE T1,.CPST1## ;RESTORE T1
SETZM .CPTPC## ;CLEAR NESTING FLAG
DATAO PAG,.CPTCX## ;RESTORE TRAP CONTEXT
XJRSTF .CPAPC## ;CONTINUE AT PC FROM "ERJMP"
;HERE ON NESTED IME, "RESTORE" THE FIRST IME AND STOPCD
SEJLM6: DMOVE T1,.CPTPC## ;PAGE FAULT PC DOUBLEWORD
DMOVEM T1,.USPFP ;RESTORE CONTEXT OF FIRST IME
DMOVEM T1,.CPAPC## ;SET TRUE ERROR PC
MOVE T2,.CPTPF## ;PAGE FAIL WORD
MOVEM T2,.CPPFW## ;SET TRUE PAGE FAULT WORD
MOVEM T2,.USPFW ;ALSO MAKE UPT LOOK RIGHT
SEILME: SETZM .CPTPC## ;CLEAR NESTING FLAG
DMOVE T1,.CPST1## ;RESTORE AC'S AT TRAP
STOPCD .,JOB,IME,DIEIME, ;++ILL MEM REF FROM EXEC
;NEVER CONTINUES HERE
DIEIME: PUSHJ P,INLMES## ;ADD SOME TEXT
ASCIZ /Page fail word = /
MOVE T1,.USPFW ;GET PAGE FAIL WORD
PUSHJ P,HWDPNT## ;PRINT AS HALF-WORDS
PUSHJ P,INLMES## ;ADD SOME TEXT
ASCIZ /, page fail PC = /
MOVE T2,.USPFP+1 ;GET PAGE FAIL PC
PJRST UDPCP## ;PRINT AND RETURN
;ROUTINE TO SEE IF A REFERENCE WAS TO A SPY PAGE
;CALL WITH PAGE FAIL WORD IN T2, NON-SKIP RETURN IF A SPY PAGE
;REFERENCE, SKIP RETURN IF NOT A SPY PAGE REFERENCE.
;PRESERVES T1-T4
IFN FTPEEKSPY,<
SEJSPG: PUSHJ P,SAVT## ;SAVE VOLATILE ACS
MOVE T1,T2 ;VIRTUAL ADDRESS
LSH T1,W2PLSH ;PAGE NUMBER
ANDI T1,HLGPGS
MOVE T4,T1 ;PAGE #
LSH T4,P2SLSH ;ISOLATE SECTION #
SKIPE .UPMP+SECTAB(T4) ;IF SECTION NXS, NOT SPY
PUSHJ P,TSSPT## ;FAULT ON A SPY PAGE?
AOS (P) ;NO, SKIP RETURN
POPJ P, ;RETURN
>; END IFN FTPEEKSPY
;HERE IF AN EXEC BREAK OCCURED WHILE IN EXEC MODE.
;CALLED FROM USRRET IN UUOCON WITH T1 CONTAINING JS.ABP.
IFN FTKL10,<
EXCABK::ANDCAM T1,JBTST2##(J) ;CLEAR BREAK HAPPENED IN EXEC MODE BIT
PUSHJ P,FNDPDS## ;FIND THIS JOB'S PDB
MOVSI T1,(OC.BCM) ;BREAK ON MUUO REFERENCES BIT
TDNN T1,.PDABS##(W) ;IS THE USER INTERESTED?
POPJ P, ;NO, GO AWAY
DMOVE T1,.JDAT+JOBPD1## ;GET UUO PC
DMOVEM T1,.CPPC## ;STORE IT WHERE PSISER EXPECTS IT
SIGNAL C$ADRB ;SIGNAL THAT AN ADDRESS BREAK OCCURED
SKIPA ;USER DOESN'T WANT TRAP
POPJ P, ;USER IS ENABLED, UUO EXIT WILL INTERRUPT TO HIM
PUSHJ P,TTYFUW## ;FIND THE USER'S TTY
PUSHJ P,INLMES## ;REPORT THE ADDRESS BREAK
ASCIZ /
%Address break/
DMOVE T1,.CPAPC##
PUSHJ P,DPCP## ;TELL HIM THAT
MOVEI T1,[ASCIZ/; UUO/]
PUSHJ P,CONMES##
DMOVE T1,.JDAT+JOBPD1## ;GET THE UUO PC
PUSHJ P,DPCP## ;REPORT IT SO HE WILL KNOW WHAT UUO BROKE
PUSHJ P,PSIERR## ;PENDING INTERRUPT?
JFCL
POPJ P, ;YES
POP P,(P) ;POP OFF THE PUSHJ TO EXCABK
JRST SEILM4 ;AND STOP THE JOB IN A CONTINUABLE STATE
>; END IFN FTKL10
;HERE FROM SEILM IF PAGE FAULT IS IN USER MODE AND APRENB DONE
;T3=PAGE FAULT WORD
SUILMX::DMOVE T1,.USMUO ;GET PC FROM "UUO"
JRST SUILM1
SUILM: DMOVE T1,.USPFP ;GET DOUBLE WORD PC
SUILM1: MOVE R,.CPADR## ;GET THE ADDRESS OF THE USER'S JOB DATA AREA
PUSHJ P,USRFLT## ;SEE IF PAGE FAULT FOR VM USER
; WILL NOT RETURN IF SO (DISPATCH TO PFH)
MOVEI T3,AP.ILM ;SET ILM BIT FOR USER
JRST SAROV1 ;FINISH UP
SUPDLO::DMOVE T1,.USMUO ;GET FLAGS & PC
MOVEI T3,AP.POV ;SET POV BIT FOR USER
JRST SAROV1 ;FINISH UP
;HERE FROM SEILM ON A PAGE FAULT WHEN THE UPT IS NOT ADDRESSABLE
;(ODD ERROR CONDITION). DON'T LOOP FOREVER TRYING TO REFERENCE
;THE UPT WHICH WILL LEAD TO ANOTHER PAGE FAULT.
SEILUP: EXCH T1,.CPSTT## ;RESTORE T1, SAVE RESULTS OF MAP INSTRUCTION
MOVEM 17,.CPA17## ;SAVE 17
MOVEI 17,.CPA00## ;MAKE BLT POINTER
BLT 17,.CPA17##-1 ;SAVE ACS IN CPU DATA BLOCK
MOVE P,.CPEPD## ;SET UP ERROR STACK
MOVE T1,.CPSTT## ;GET RESULTS OF MAP INSTRUCTION BACK
HRRZ T2,JBTUPM##+0 ;GET PAGE NUMBER OF NULL JOB'S UPT
EXCH T2,@.CPSPT## ;POINT SPT AT NULL JOB, SAVE OLD CONTENTS IN T2
DATAO PAG,NULDOP## ;MAKE SURE SOME UPT IS ADDRESSABLE
STOPCD .,STOP,UNA, ;++UPT NOT ADDRESSABLE
;T1/ RESULTS OF MAP .UPMP
;T2/ OLD CONTENTS OF @.CPSPT
SUBTTL APR INTERRUPT PROCESSING -- KL10
IFN FTKL10,<
;APR CHANNEL INTERRUPT
APRINT::CONSO APR,LP.CSD ;CACHE SWEEP DONE?
JRST APRIN1 ;NO
CONO APR,LP.CSF+LP.CSD+APRCHN## ;YES, CLEAR SWEEP DONE FLAG
AOS .CPCSN## ;COUNT A CACHE SWEEP COMPLETED
EXCH T1,.CPSCS## ;SAVE T1, GET DOORBELL BIT
IORM T1,DOORBL## ;DING!
EXCH T1,.CPSCS## ;RESTORE T1
XJEN @.CPCHL## ;DISMISS INTERRUPT
APRIN1: CONSZ APR,LP.NXM!LP.CDP!LP.ADP!LP.SBE!LP.PAR!LP.PWF!LP.IOF
;TIMER TIMEOUT, MEM PARITY, POWER FAIL,
; ADDRESS BREAK, IO PAGE FAIL?
JRST APRUNS ;YES, GO PROCESS UNUSUAL INTERRUPTS
PJRST APRDDT ;GO CHECK FOR EDDT ENTRY AND DISMISS INTERRUPT
;STILL UNDER FTKL10
;STILL UNDER FTKL10
;PROCESS UNUSUAL INTERRUPTS
APRUNS: CONSZ APR,LP.PWF ;POWER FAIL?
JRST APRPWF ;YES
CONSZ APR,LP.ADP!LP.CDP ;ADDRESS OR CACHE DIRECTORY PARITY?
JRST APRNHT ;YES
CONSZ APR,LP.NXM ;NON-EXISTANT MEMORY
JRST APRNXM ;YES
CONSZ APR,LP.PAR ;MB PARITY ERROR?
JRST APRDDT ;YES (IGNORE)
CONSZ APR,LP.IOF ;IO PAGE FAILURE?
JRST APRIOP ;YES
CONSZ APR,LP.SBE ;SBUS ERROR?
JRST APRSBE ;YES
JRST APREXT ;NO, EXIT INTERRUPT
;NXM INTERRUPT
APRNXM: CONO APR,LP.CSF!LP.PAR!LP.SBE ;CLEAR ALL BUT INTERESTING STUFF
SWPUA ;SWEEP CACHE (NXM LEAVES BAD PARITY IN CACHE)
CONSZ APR,LP.CSB ;CACHE SWEEP DONE?
JRST .-1 ;WAIT FOR IT TO FINISH
JRST APRDDT ;PROCESS LIKE A NXM (IGNORE)
;STILL UNDER FTKL10
;STILL UNDER FTKL10
;I/O PAGE FAILURE
APRIOP: DATAI PAG,.CPIPG## ;SAVE AC SET INFO
DATAO PAG,[LG.LAB+0B8+7B11] ;EXEC AC SET 0, USER AC SET 7
MOVEM P,.CPSP## ;PRESERVE P
PXCT PX.MEM,[MOVE P,2] ;GET AC 2, BLOCK 7 (API FUNCTION WORD)
MOVEM P,.CPIOP## ;SAVE FOR ANALYSIS
EXECAC ;EXEC AC SET 0, USER AC SET 1
CONO APR,LP.CSF!LP.IOF ;CLEAR I/O PAGE FAILURE
MOVE P,.CPAPP## ;SET TO PD LIST FOR THIS CPU
PUSHJ P,IOPSTP ;ANALYZE THE FAILURE, SKIP RETURN IF RECOVERABLE
STOPCD .,CPU,IOP, ;++I/O PAGE FAILURE
MOVE P,.CPSP## ;RESTORE P
DATAO PAG,.CPIPG## ;RESTORE AC SETS
JRST APREXT ;DISMISS INTERRUPT
;STILL IN IFN FTKL10
;STILL IN IFN FTKL10
;ROUTINE TO ANALYZE I/O PAGE FAILURE AND TAKE APPROPRIATE ACTION.
;IF THE FAILURE WAS CAUSED BY A NON-MASTER DTE20 THE DTE IS SIMPLY
;RELOADED. ANY OTHER CAUSE LEADS TO A FATAL STOPCODE. THE API
;FUNCTION WORD HAS BEEN STORED BY THE INTERRUPT HANDLER AT .CPIOP.
;CALL:
; PUSHJ P,IOPSTP
; <NON-SKIP> ;RETURN IF NON-RECOVERABLE ERROR (MASTER FE)
; <SKIP> ;RETURN IF RECOVERABLE ERROR (OTHER FE)
;
;ON AN I/O PAGE FAILURE AC BLOCK 7, AC 2 HAS THE FOLLOWING CONTENTS:
;0:2 ADDRESS SPACE:
; 0 = EPT RELATIVE
; 1 = EXECUTIVE VIRTUAL
; 4 = PHYSICAL
;3:5 FUNCTION:
; 0 = STANDARD (40+2N)
; 1 = STANDARD (40+2N)
; 2 = VECTOR (XCT INSTRUCTION AT ADDRESS 13:35)
; 3 = INCREMENT/DECREMENT (INTERLOCKED) (Q -- DECREMENT)
; 4 = DATAO (Q -- PROTECTED)
; 5 = DATAI (Q -- PROTECTED)
; 6 = BYTE (Q -- TO -10)
; 7 = PHYSICAL INCREMENT (INTERLOCKED)
;6: QUALIFIER (SEE ABOVE)
;7:10 DEVICE NUMBER ON EBUS:
; 0 - 7 = INTERNAL CHANNEL 0 - 7
; 10 - 13 = DTE20 0 - 3
; 14 - 16 = EXTERNAL DEVICE
; 17 = DIA20
;13:35 ADDRESS
IOPSTP: PUSHJ P,SAVT## ;PRESERVE FROM AC CORRUPTION
LDB T1,[POINT 4,.CPIOP##,10] ;GET DEVICE NUMBER
CAIL T1,10 ;IS THIS A DTE20?
CAILE T1,13 ;...
POPJ P, ;NO, THEN THIS IS A FATAL IOP STOP
PUSH P,F ;GETETD STEPS ON F
MOVEI F,-10(T1) ;GET DTE NUMBER
HRL F,.CPCPN## ;MAKE CPU NUMBER,,DTE NUMBER
PUSHJ P,GETETD## ;GET DTE CONTROL BLOCK ADDRESS
PJRST FPOPJ## ;ERROR? UNLIKELY, BUT ASSUME MASTER FE
MOVSI T1,(ED.DTM) ;IS THIS THE MASTER FE?
TDNE T1,ETDSTS(F) ;IF SO, NOTHING WE CAN DO
PJRST FPOPJ## ; SO NON-SKIP RETURN AND DIE
STOPCD .,INFO,DTEIOP,DIEIOP, ;++DTE20 I/O PAGE FAILURE
MOVEI T1,.+1 ;GET A PC
PUSHJ P,DTERLD## ;RELOAD THE DTE
PJRST FPOPJ1## ;RESTORE F AND RETURN
;HERE FROM ERRCON ON THE DTEIOP STOPCD
DIEIOP: PUSHJ P,INLMES##
ASCIZ .I/O page failure for .
PJRST DTEPDI## ;PRINT DTE INFORMATION AND RETURN
;STILL UNDER FTKL10
;STILL UNDER FTKL10
;SBUS ERROR
APRSBE: SKIPN [M.MOS##] ;MOS MEMORY SUPPORT?
JRST APRNHT ;NO, COLLECT ERROR INFO AND HALT
CONO APR,LP.CSF+LP.SBE ;CLEAR SBUS ERROR EARLY IN CASE
MOVEM P,.CPSP## ; SINGLE BIT ERROR IN ERROR ANALYSIS CODE
MOVE P,.CPAPP## ;SET TO PD LIST FOR THIS CPU
PUSHJ P,SBERR## ;DO ERROR ANALYSIS AND RECORD ERRORS FOR THGA
MOVE P,.CPSP## ;RESTORE P
JRST APREXT ;EXIT INTERRUPT
;HALT ON APR ERROR CONDITION--DO SBDIAG AND RDERA FIRST
APRNHT: MOVEM P,.CPSP## ;GET A VALID PDL
MOVE P,.CPAPP## ;SET TO PD LIST FOR THIS CPU
RDERA .CPAER## ;READ ERA INTO CPU DATA BLOCK
CONI APR,.CPAEF## ;SAVE CONI APR,
SBDIAG .CPSB0## ;GET SBDIAG FUNCTIONS 1+2
SBDIAG .CPSB1## ; ...
SWPUA ;CACHE SWEEPS SO WE CAN SEE DATA
CONSZ APR,LP.CSB ;SWEEP FINISHED?
JRST .-1 ;WAIT FOR IT TO COMPLETE
CONSZ APR,LP.SBE ;SBUS ERROR?
STOPCD .,CPU,SBE, ;++SBUS ERROR
CONSZ APR,LP.CDP ;CACHE DIRECTORY OR ADDRESS PARITY?
STOPCD .,CPU,CDE, ;++CACHE DIRECTORY PARITY ERROR
STOPCD .,CPU,APE, ;++ADDR. PARITY ERROR
;STILL UNDER FTKL10
;STILL UNDER FTKL10
PWFPIS==0 ;CONI PI,
PWFPAG==1 ;DATAI PAG,
PWFMTR==2 ;CONI MTR,
PWFLEN==:3 ;NUMBER OF WORDS SAVED
;POWER FAIL
APRPWF: CONI PI,.CPPFD##+PWFPIS ;SAVE STATE OF PI SYS
CONO PI,PI.OFF ;TURN OFF INTERRUPTS
MOVEM P,.CPSP## ;SAVE P
MOVE P,.CPEBR## ;GET CURRENT EBR
ANDI P,-1-<LG.CSL!LG.CSW> ;TURN OFF CACHE
CONO PAG,(P) ;...
SWPUA ;SWEEP CACHE
CONSZ APR,LP.CSB ;WAIT FOR SWEEP BUSY TO CLEAR
JRST .-1
DATAI PAG,.CPPFD##+PWFPAG ;SAVE UBR, CURRENT & PREVIOUS AC BLOCKS
CONI MTR,.CPPFD##+PWFMTR ;SAVE METER
MOVE P,.CPSP## ;RESTORE P
JSR .CPSVA## ;SAVE ALL AC SETS
MOVSI P,(JRST) ;ALLOW -20F TO RESTART US
IFE FTMP,<HLLM P,ARSLOC##>
IFN FTMP,<HLLM P,.CPRES##>
MOVE P,.CPAPP## ;SET TO PD LIST FOR THIS CPU
PUSHJ P,DTEPWF## ;TELL F.E. WE HAVE A POWER FAILURE
MOVEI 17,700000 ;GET A SHORT COUNT
SOJG 17,. ;MAKE SURE POWER HAS FAILED
PJRST APRRES## ;IT HASN'T
;POWER FAIL RESTART
APRPFR::SWPIA ;CLEAR OUT CACHE
CONSZ APR,LP.CSB ;WAIT FOR SWEEP BUSY TO CLEAR
JRST .-1
CONO PAG,@.CPEBR## ;TURN ON CACHE, TRAP ENABLE
MOVEM P3,@.CPSPT## ;RESTORE SPT
MOVE P,.CPPFD##+PWFPIS ;GET CONI PI, WORD
ANDI P,377 ;JUST SYS ON, OFF AND CHANNELS ON, OFF
CONO PI,PI.TNP(P) ;TURN ON CHANNELS AND SYS, IF IT WAS ON BEFORE
MOVE P,.CPPFD##+PWFPAG ;GET UPT INFO
TRO P,LG.IAM ;INHIBIT UPDATING OF ACCOUNTING METERS
DATAO PAG,P ;RESTORE UBR FOR METERS
MOVE P,.CPPFD##+PWFMTR ;GET METER INFO
CONO MTR,MO.LAC(P) ;LOAD ACCOUNTING CONTROL, PI
MOVSI P,(HALT) ;PREVENT -20F FROM RESTARTING US
IFN FTMP,<HLLM P,.CPRES##>
IFE FTMP,<HLLM P,ARSLOC##>
MOVE P,.CPAPP## ;SET TO PD LIST FOR THIS CPU
PUSHJ P,DTEPFC## ;RE-ESTABLISH PRIMARY PROTOCOL
JSP T4,ZAPICH## ;PUT INTERNAL CHANNELS BACK TOGETHER
PUSHJ P,DSKRCL## ;CAUSE HOME BLOCKS TO BE REREAD
RESTOR (0,.CPCAC##) ;RESTORE AC'S
RESTOR (1,.CPCA1##)
RESTOR (2,.CPCA2##)
RESTOR (3,.CPCA3##)
RESTOR (4,.CPCA4##)
CONO TIM,TO.CTD!TO.CIT!TO.SIT!^D1667 ;SET FOR FIRST CLOCK TICK
DATAO PAG,.CPPFD##+PWFPAG ;RESTORE UBR/AC SETS
CONO APR,APRNUL## ;CLEAR POWER FAIL, ENABLE FOR GOOD STUFF
PJRST APREXT ;DISMISS INTERRUPT
> ;END IFN FTKL10
SUBTTL APR INTERRUPT PROCESSING -- KS10
IFN FTKS10,<
;APR CHANNEL INTERRUPT
APRINT::SKIPE CRSHWD ;OPR DEPOSIT 30 NON-ZERO?
JRST SYSCRH## ;YES, TAKE CRASH DUMP
CONSZ APR,SP.NXM!SP.HMP!SP.PWF ;NXM, HARD PARITY OR POWER FAIL?
JRST APRUNS ;YES
APRIN2: DMOVEM P,.CPSP## ;SAVE ACS P & P+1
CONSO APR,SP.ITI ;CLOCK TICK?
PJRST CLKDDR ;NO
JSP P+1,TIMINT ;PROCESS TIMER INTERRUPT
DMOVE P,.CPSP## ;RESTORE ACS
PJRST APRDDT ;CHECK FOR EDDT ENTRY AND DISMISS INTERRUPT
;PROCESS UNUSUAL INTERRUPTS
APRUNS: CONSZ APR,SP.PWF ;POWER FAIL?
JRST APRPWF ;YES
CONSZ APR,SP.NXM!SP.HMP ;NXM OR PARITY ERROR?
JRST APRIN2 ;YES--GO PROCESS IT
JRST APREXT ;DISMISS INTERRUPT
;STILL UNDER FTKS10
;STILL UNDER FTKS10
PWFPIS==0 ;CONI PI,
PWFPAG==1 ;DATAI PAG,
PWFMTR==2 ;CONI MTR,
PWFLEN==:3 ;NUMBER OF WORDS SAVED
;POWER FAIL
APRPWF: RDPI .CPPFD##+PWFPIS ;SAVE STATE OF PI SYS
WRPI PI.OFF ;TURN OFF PI'S
RDUBR .CPPFD##+PWFPAG ;SAVE UDB, CURRENT & PREVIOUS AC BLOCKS
RDTIME .CPPFD##+PWFMTR ;SAVE TIME BASE
JSR .CPSVA## ;SAVE ALL AC SETS
MOVE P,[JRST APRRES##] ;POWER FAIL AUTO RESTART INTSTRUCTION
MOVEM P,ARSLOC## ;SET IT UP
HALT . ;STOP
;FE RESTARTS US AT 70 WHICH EVENTUALLY
; GETS US HERE
;POWER FAIL RESTART
APRPFR::WRUBR .CPPFD##+PWFPAG ;RESTORE UBR AND AC BLOCKS IN USE
SETZ 0, ;CLEAR CURRENT AC BLOCK FOR USE
MOVEI 17,1 ;...
BLT 17,17 ;...
MOVE P,.CPAPP## ;SET TO PD LIST FOR THIS CPU
PUSHJ P,UBAPIS## ;RESET UBA'S
MOVE T1,.CPPFD##+PWFPIS ;GET CONI PI, WORD
ANDI T1,377 ;JUST SYS ON, OFF AND CHANNELS
WRPI PI.TNP(T1) ;RESTORE PI SYSTEM
MOVEI T1,<^D16>B23 ;RESTART INTERVAL TIMER
WRINT T1 ;SET IT
MOVE T1,[HALT ARSLOC##] ;HALT AT 70 INSTRUCTION
MOVEM T1,ARSLOC## ;DISABLE 70 RESTART
MOVE U,OPRLDB## ;OPR'S LDB
MOVEI T1,[ASCIZ /
%Power fail restart
/]
PUSHJ P,CONMES## ;ANNOUNCE RESTART
PUSHJ P,ENAKAL ;ENABLE KEEP ALIVE FUNCTION
PUSHJ P,DSKRCL## ;CAUSE HOME BLOCKS TO BE REREAD
RESTOR (0,.CPCAC##) ;RESTORE AC'S
RESTOR (1,.CPCA1##)
RESTOR (2,.CPCA2##)
RESTOR (3,.CPCA3##)
RESTOR (4,.CPCA4##)
ZERO (5) ;CLEAN OUT REST OF AC BLOCKS
ZERO (6)
ZERO (7)
WRUBR .CPPFD##+PWFPAG ;RESTORE UBR AND AC BLOCKS IN USE
WRTIME .CPPFD##+PWFMTR ;RESTORE TIME BASE
WRAPR APRNUL## ;CLEAR POWER FAIL, ENABLE FOR GOOD STUFF
PJRST APREXT ;DISMISS INTERRUPT
> ;END IFN FTKS10
SUBTTL APR INTERRUPT PROCESSING -- COMMON INTERRUPT EXIT
;CHECK FOR EDDT ENTRY
APRDDT: DMOVEM P,.CPSP## ;SAVE AC P
IFN FTMP,<
MOVE P,.CPCPN## ;GET OUR CPU NUMBER
CAMN P,BOOTCP## ;ARE WE THE BOOT CPU?
> ;END IFN FTMP
APRCLK: SKIPN CLKDDT ;AND IS 21 NON-ZERO
JRST CLKDDR ;NO--PRECEED
MOVE P,.CPSP## ;RELOAD P
SETZM CLKDDT ;CLEAR FLAG
XCT SYSDDT## ;GO TO EDDT IF POSSIBLE
CLKDDR::MOVE P,.CPAPP## ;SET TO PD LIST FOR THIS CPU
PUSHJ P,APRSUB## ;GO PROCESS INTERRUPT
DMOVE P,.CPSP## ;RESTORE P
;EXIT FROM INTERRUPT
APREXT: CONO APR,APRCHN## ;SET APR PI
XJEN @.CPCHL## ;DISMISS INTERRUPT
SUBTTL TIMER INTERRUPT PROCESSING -- KL10
;ENTERED VIA XPCW FROM EPT WHEN TIMER INTERRUPTS
IFN FTKL10,<
TIMINT::SKIPE CRSHWD ;OPR DEPOSIT 30 NON-ZERO?
JRST SYSCRH## ;YES, TAKE CRASH DUMP
IFN FTMP,<
SKIPN CPNDDT ;ANY CPU HIT A BREAKPOINT?
JRST TIMIN2 ;NO, SKIP OVER THIS
MOVEM P,.CPSP## ;YES, SAVE FOR A BIT
SKIPE BPTMSK## ;ANY CPU ALLOWED TO ENTER EDDT?
JRST TIMIN1 ;YES, CONTINUE
MOVEI P,.CPKFP##-1 ;SET UP A PDL
STOPCD .,EVENT,CPNDDN,DIECPN, ;++CPNDDT NON-ZERO
SETZM CPNDDT ;PREVENT HEARTBURN AND DEAD SYSTEMS
MOVE P,.CPSP## ;RESTORE P
JRST TIMIN2 ;CONTINUE ONWARD
TIMIN1: MOVE P,.CPCPN## ;GET OUR CPU NUMBER
MOVE P,BITTBL##(P) ;GET CORRESPONDING BIT
TDNN P,CPNDDT ;IS THIS JUST A FLUKE DURING $X?
SKIPA P,.CPSP## ;NO, RESTORE AC
SKIPA P,.CPSP## ;YES, RESTORE AC
JRST CPNBPT## ;OTHER CPU IN A BREAKPOINT, WAIT FOR IT
APRABK::!
> ;END IFN FTMP
TIMIN2: DMOVEM P,.CPSP## ;SAVE P
DMOVE P,@.CPTMI## ;GET INTERRUPTING PC
DMOVEM P,@.CPCHL## ;SAVE AT APR PI CHANNEL XPCW
MOVSI P,(ST.CYC) ;BIT TO TEST
TDNN P,STATES## ;50HZ?
JRST TIMIN3 ;NO
MOVEI P,^D2000 ;SET UP 20000 MICROSECONDS FOR 50HZ
JRST TIMIN4 ;AND CONTINUE
TIMIN3: MOVEI P,^D1666 ;60HZ, SO ASSUME LEAP JIFFY
AOSG .CPTCT## ;COUNT TRIAD COUNTER (-1,0,1)
AOJA P,TIMIN4 ;NOT LEAP TICK UNLESS TRIAD COUNT IS 1
SETCMM .CPTCT## ;COUNT REACHED 1, SET BACK TO -2
TIMIN4: SKIPE .CPITP## ;SOMEONE PATCHED INTERVAL TIMER?
XCT .CPITP## ;YES--CALL THEM
CONO TIM,TO.CTD!TO.SIT(P) ;SET INTERVAL OF TIMER AGAIN
SETOM .CPTIM## ;SOFTWARE CLOCK FLAG FOR KL'S
PJRST APRCLK ;CHECK FOR EDDT ENTRY AND DISMISS INTERRUPT
IFN FTMP,<
DIECPN: PUSHJ P,INLMES## ;PRINT SOME GARBAGE
ASCIZ /CPNDDT non-zero; contents /
MOVE T1,CPNDDT ;GET IT
PJRST HWDPNT## ;PRINT IN HALF-WORDS
>; END IFN FTMP
> ;END IFN FTKL10
SUBTTL TIMER INTERRUPT PROCESSING -- KS10
;ENTERED VIA JSP P+1, FROM APRINT
IFN FTKS10,<
TIMINT: MOVSI P,(ST.CYC) ;BIT TO TEST
TDNN P,STATES## ;50HZ CLOCK SIMULATION?
JRST TIMIN1 ;NO
MOVEI P,^D20 ;SET UP 20 MILLISECONDS FOR 50HZ
JRST TIMIN2 ;GO SET INTERVAL
TIMIN1: MOVEI P,^D16 ;60HZ, SO ASSUME LEAP JIFFY
AOSG .CPTCT## ;COUNT TRIAD COUNTER (-1,0,1)
AOSA P ;NOT LEAP TICK UNLESS TRIAD COUNT IS 1
SETCMM .CPTCT## ;COUNT REACHED 1, SET BACK TO -2
TIMIN2: SKIPE .CPITP## ;SOMEONE PATCHED INTERVAL TIMER?
XCT .CPITP## ;YES--CALL THEM
ADDM P,.CPLMC## ;ADD THIS INTERVAL TO LEAP MSEC COUNT
SKIPL .CPLMC## ;IS IT STILL NEGATIVE?
ADDI P,1 ;NO--IT'S TIME FOR A LEAP MSEC
LSH P,^D12 ;SHIFT TO LOAD INTO TIMER REGISTER
WRINT P ;SET INTERVAL OF TIMER AGAIN
WRAPR SP.CSF!SP.ITI ;CLEAR INTERVAL TIMER INTERRUPT FLAG
SETOM .CPTIM## ;SET SOFTWARE CLOCK TICK FLAG
SKIPGE P,.CPLMC## ;IS THIS A LEAP MSEC?
JRST (P+1) ;NO--RETURN
ADD P,[-^D1024] ;YES--COMPUTE NEXT LEAP MSEC COUNT
MOVEM P,.CPLMC## ;RESET IT
JRST (P+1) ;RETURN
> ;END IFN FTKS10
SUBTTL TIMER INTERRUPT PROCESSING -- PATCH SUPPORT
;HERE ON FROM SETUUO DISPATCH TO SET OR CLEAR THE INTERVAL TIMER PATCH
;CALL: MOVE AC,[.STITP,,ADDR]
; SETUUO AC, ;OR CALLI AC,75
; <ERROR> ;NO PRIVS, BAD CPU ARG, PATCH IN USE
; <SKIP> ;SUCCESS
;
;ADDR: CPU NUMBER
; INSTR TO XCT
SETITP::MOVSI T1,JP.POK ;BIT TO TEST
PUSHJ P,PRVBIT## ;POKE PRIVS, [1,2], OR JACCT?
CAIA ;SUITABLY PRIVILEGED
JRST ECOD0## ;GIVE UP
HRR M,T2 ;GET ADDR OF USER ARGUMENTS
PUSHJ P,GETWDU## ;FETCH CPU#
MOVEI T3,(T1) ;COPY TO A BETTER PLACE
CAIL T3,M.CPU## ;WITHIN RANGE?
POPJ P, ;NO
IMULI T3,.CPLEN## ;COMPUTE CDB OFFSET
PUSHJ P,GETWD1## ;GET INSTRUCTION TO PATCH (ZERO IF CLEAR)
SKIPGE .C0OK##(T3) ;CPU ALIVE?
PUSHJ P,LOKEVC## ;AND LOCKED CONTIGUOUSLY IN EVM?
JUMPN T1,ECOD0## ;ERROR IF SETTING, ELSE OK
SKIPN T1 ;INSERTING?
TDZA T2,T2 ;NO--STORE A ZERO FOR JOB NUMBER
MOVEI T2,(J) ;ELSE PICK UP JOB NUMBER
SYSPIF ;AVOID RACES BETWEEN JOBS
SKIPE .C0ITJ##(T3) ;NO OWNER?
CAMN J,.C0ITJ##(T3) ;OR THIS JOB OWN THE PATCH?
TDZA T4,T4 ;YES TO EITHER
SKIPA T4,. ;ERROR
DMOVEM T1,.C0ITP##(T3) ;SET/CLEAR PATCH INSTRUCTION & JOB
SYSPIN ;RELEASE INTERLOCK
JUMPN T4,ECOD0## ;RETURN ERROR DIDN'T GET IT
JRST CPOPJ1## ;ELSE SKIP
;HERE TO FORCIBLY CLEAR THE INTERVAL TIMER PATCH
CLRITP::PUSH P,T2 ;SAVE T2
PUSH P,T3 ;SAVE T3
MOVEI T1,ZAPITP ;SUBROUTINE TO EXECUTE OVER ALL CPUS
SETZB T2,T3 ;WILL CLEAR TWO ADJACENT CDB LOCS
PUSHJ P,CPUAPP## ;DO IT FOR ALL CPUS
POP P,T3 ;RESTORE T3
POP P,T2 ;RESTORE T2
POPJ P, ;RETURN
ZAPITP: CAMN J,.CPITJ##-.CPCDB##(P1) ;JOB WHICH PATCHED INTERVAL TIMER?
DMOVEM T2,.CPITP##-.CPCDB##(P1) ;CLEAR PATCH INSTRUCTION & JOB
POPJ P, ;RETURN
SUBTTL KEEP-ALIVE TRAP HANDLER
APRKAF::MOVEM P,.CPSVP## ;SAVE P
MOVEI P,.CPKFP##-1 ;SET UP STACK
STOPCD .,CPU,KAF, ;++KEEP ALIVE FAILURE
SUBTTL CONTEXT SWITCHING
;ROUTINE TO SET HARDWARE AND SOFTWARE RELOCATION INFORMATION FOR CURRENT USER
;CALLING SEQUENCE:
; PUSHJ P,SETREL
; ... RETURN HERE
;J = CURRENT JOB NUMBER
;R = PROTECTION,,RELOCATION FOR THE LOW SEGMENT
SETRLH::
SETREL::MOVE J,.CPJOB## ;J = CURRENT JOB NUMBER
SETRL1::MOVE R,JBTADR##(J) ;R = XWD PROTECTION,,EXEC VIRTUAL ADDRESS
; OF THE FIRST PAGE OF THE LOW SEGMENT
MOVE T2,.CPADR## ;PREVIOUS JOB'S CORE, 0 IF NONE
MOVEM R,.CPADR## ;SET .CPADR FOR QUICK ACCESS AT APR LEVEL
HLRZM R,.CPREL## ;SET .CPREL FOR ADDRESS CHECKING
SKIPE T1,.CPSTS## ;HAS TIMESHARING BEEN STOPPED VIA TRPSET?
CAIE T1,(J) ;YES, WAS IT THIS JOB?
JUMPN T1,SETRLZ ;NO, DON'T CHANGE THE UBR
SKIPE J ;NULL JOB ALWAYS HAS A UPMP
JUMPE R,SETRLZ ;THERE IS NO UPMP IF THE JOB HAS NO CORE
HRRZ T1,JBTUPM##(J) ;PAGE NUMBER OF THE CURRENT JOB'S UPMP
JUMPE T1,SETRL3 ;DON'T CHANGE ANYTHING IF THERE ISN'T ONE
IFN FTKL10,<HRLI T1,(LG.LUB+LG.LPC+LG.KPM)> ;SET THE LOAD BIT, PCS = 0
IFN FTKS10,<HRLI T1,(SG.LUB)> ;SET THE LOAD BIT
IFN FTRTTRP,<MOVEM T1,.CPHRP##> ;SAVE FOR RTTRP INTERRUPT LEVEL USE
CONO PI,PI.OFF ;MAKE CHANGING ADDRESSABILITY ATOMIC
HRRM T1,@.CPSPT##
IFN FTKL10,<
SKIPN T2 ;LAST JOB STILL HAVE CORE?
DATAO PAG,NULDOP## ;DUMP THE METERS
>; END IFN FTKL10
DATAO PAG,T1 ;SETUP THE UBR, UPDATE METERS
CONO PI,PI.ON ;CONTEXT SWITCH NOW DONE
JUMPE R,SETRLZ ;DONE IF NULL JOB
HLRZM R,.USHVA ;SET .UPHVA FOR ADDRESS CHECKING AT IRP LEVEL
SKIPN T1,.USREL ;HOLEY PROGRAM?
HLR T1,R
HRRZM T1,.JDAT+JOBREL## ;STORE HIGHEST CORE-UUO ADDRESS IN JOBREL
MOVSI T3,REDOMP ;FORCING THE MAP TO BE REDONE?
AND T3,JBTSGN##(J) ;GET STATE OF BIT
ANDCAM T3,JBTSGN##(J) ;CLEAR IT (WE'LL REDO SEGMENT IN A MINUTE)
SKIPE T3 ;WAS IT ON?
PUSHJ P,MAPHGH## ;YES, REDO THE HIGH SEGMENT PART OF THE MAP
SETRLZ: PUSHJ P,FNDPDS## ;SET UP W
IFN FTKL10,<
MOVE T3,JBTPDB##+0 ;NULL JOB PDB
SKIPE T2,.PDABS##(W) ;DOES THE USER HAVE ADDRESS BREAK SETTINGS?
TLNN T2,(OC.ABE) ;YES, IS HE ENABLED FOR BREAKS
JRST SETRL2
TLZ T2,(OC.BSU) ;CLEAR SET BY UUO
TLZE T2,(1B0) ;CHANGE NEW HARDWARE INTO
TLO T2,(1B9) ; OLD. OR CHANGE OLD
TLZE T2,(1B1) ; SOFTWARE INTO NEW
TLO T2,(1B10) ; ..
TLZE T2,(1B2) ; ..
TLO T2,(1B11) ; ..
TLZE T2,(1B6) ; ..
TLO T2,(1B12) ; ..
CAIA ;
SETRL2: SETZ T2,
SKIPL .PDABS##(T3) ;CAN USERS USE ADDRESS BREAK?
DATAO APR,T2 ;YES, SETUP BREAK CONDITIONS AND BREAK ADDRESS
MOVEM T2,.CPAPR## ;STORE BREAK CONDITIONS FOR SSEUB
>; END IFN FTKL10
SETRL3: SKIPN R,JBTADR##(J) ;RESTORE R - JOB HAVE CORE IN CORE?
TDZA T1,T1 ;NO, MUST BE THE NULL JOB OR CORE 0
MOVE T1,.JDAT+JOBENB## ;JOB'S APR ENABLE BITS
PJRST SETCNA## ;SETUP APR ENABLE BITS FOR THE USER
; NO ENABLES IF NULL JOB OR NO CORE IN CORE
;ROUTINE TO SETUP USER AND EXEC BASE REGISTERS FOR A JOB
;CALLING SEQUENCE:
; MOVE J,JOB NUMBER
; PUSHJ P,STEUB
;ENTER AT MKADD TO JUST MAKE THE JOB ADDRESSABLE
MKADD:: CAME J,.USJOB ;GO AWAY IF ALREADY ADDRESSABLE
STEUB:: CAILE J,JOBMAX## ;IS THIS A HIGH SEGMENT?
POPJ P, ;YES, THE UBR MUST ALREADY BE SETUP
; OR DOESN'T NEED TO BE (ADDRESSES WILL BE
; MAPPED THROUGH THE EXEC MAP)
PUSH P,T1 ;SAVE A TEMPORARY
HRRZ T1,JBTUPM##(J) ;T1 = THE PAGE NUMBER OF THE USER PAGE MAP PAGE
CONO PI,PI.OFF ;NO INTERRUPTS WHILE CHANGING UBR/SPT
SKIPE T1 ;IF NOT ZERO,
HRRM T1,@.CPSPT## ; SETUP NEW SPT
IFN FTKL10,<TLO T1,(LG.LUB+LG.KPM)> ;REQUEST LOADING OF UBR
IFN FTKS10,<TLO T1,(SG.LUB)> ;REQUEST LOADING OF UBR
IFN FTKL10,<TRNE T1,LG.UPT> ;IS THERE A UPT?
IFN FTKS10,<TRNE T1,SG.UPT> ;IS THERE A UPT?
DATAO PAG,T1 ;SET FOR CURRENT USER AND CLEAR THE AM
CONO PI,PI.ON ;BOTH THE SPT AND UBR HAVE BEEN CHANGED
JRST TPOPJ## ;RESTORE T1 AND RETURN
IFN FTXMON,<
;ROUTINES TO SETUP PCS FROM DEVISN.
;CALLING SEQUENCE:
; MOVE F,DDB ADDRESS
; PUSHJ P,SPCS
;ROUTINES CALLING THIS ROUTINE SHOULD CALL SVEU? SO THAT PCS WILL BE
; RESTORED ON A POPJ FROM THE CALLING ROUTINE
SPCS:: PUSH P,T1 ;SAVE A TEMP
HRRZ T1,DEVISN(F) ;GET SECTION NUMBER FOR I/O
MOVSI T1,<(LG.LPC)>(T1) ;LOAD PREVIOUS CONTEXT SECTION
DATAO PAG,T1 ;PREVIOS CONTEXT IS ADDRESSABLE
JRST TPOPJ## ;RESTORE T1 AND RETURN
>
IFE FTXMON,<
SPCSB==:SVEUB
SPCSF==:SVEUF
SPCS==:CPOPJ##
>
SUBTTL KL ACCOUNTING METERS
IFN FTEMRT,<
;ROUTINES TO HANDLE ACCOUNTING METERS
;RETURN EBOX COUNTS FROM CURRENT UPT IN T1 AND T2
GETEBT::RDEACT T1 ;READ EBOX COUNTS INTO T1,T2
POPJ P, ;RETURN
GETMBT::RDMACT T1 ;SAME FOR MBOX COUNTS
POPJ P,
;ROUTINE TO TURN ACCOUNTING METERS ON AND OFF
; CALLED BY CLOCK1 TO EXCLUDE MONITOR OVERHEAD FROM USER RUNTIME
; ACCMON AND ACCMOF PRESERVE ALL ACS
ACCMON::PUSH P,T1
PUSH P,T2 ;SAVE T1,T2
CONI MTR,T1 ;GET PI ASSIGNMENT, TIME BASE ON/OFF
TRO T1,MO.LAC!MO.AEN!MO.AIP!MO.AO ;MAKE SURE LOAD ACCT, EXEC NO PI
; PI, ACCT METER ON
MOVE T2,CNFST2## ;GET CNFST2
TRNE T2,ST%XPI ;EXCLUDE PI FROM USER RUNTIME?
TRZ T1,MO.AIP ;YES, THEN DON'T INCLUDE
CONO PI,PI.OFF ;TURN OFF PI'S SO ACCOUNTING METER AND PERF METER
; WILL STAY IN SYNC
CONO MTR,(T1) ;SET STUFF, TURN METER ON
SKIPE .CPAPS## ;IF ACCT/PERF METER SYNC,
PUSHJ P,SCDPMR ;GO TURN PERFORMANCE METER ON IF NECESSARY
CONO PI,PI.ON ;BACK ON
POP P,T2 ;RESTORE T2
JRST TPOPJ## ;T1 AND RETURN
;TURN OFF ACCOUNTING METER
ACCMOF::PUSH P,T1 ;SAVE AN AC
CONI MTR,T1 ;GET PI ASSIGNMENT, OTHER STUFF
ANDI T1,7 ;ONLY PI ASSIGNMENT
TRO T1,MO.LAC ;LOAD ACCOUNTING ENABLES - ZILCH
CONO PI,PI.OFF ;TURN OFF PI'S
CONO MTR,(T1) ;STOP THE CLOCK
SKIPE .CPAPS## ;ACCOUNTING/PERF SYNC?
PUSHJ P,STPPMR ;YES, TURN OFF PERFORMANCE METER
CONO PI,PI.ON ;PI BACK ON AGAIN
PJRST TPOPJ## ;RESTORE T1 AND RETURN
;STILL IN FTEMRT CONDITIONAL
;CLEAR EBOX, MBOX COUNT FOR CURRENT UPT
; THESE ROUTINES PRESERVE ALL AC'S
CLREMB::DATAI PAG,1(P) ;WRITE OUT ALL THE BITS
DATAO PAG,1(P)
SETZM .UPMP+.LMEBL ;LOW ORDER BITS FIRST SO NO OVERFLOW
SETZM .UPMP+.LMEBH ;THEN HIGH ORDER
SETZM .UPMP+.LMMBL ;LOW ORDER FIRST
SETZM .UPMP+.LMMBH ;THEN HIGH
POPJ P, ;RETURN
>;END IFN FTEMRT
SUBTTL KS ONCE A SECOND CODE
IFN FTKS10,<
KSSEC:: PUSHJ P,MEMCHK ;CHECK FOR MEMORY ERRORS
PUSHJ P,UBACHK ;CHECK THAT UNIBUS ADAPTERS HAVE THEIR PIAS
;COUNT THE KEEP ALIVE COUNTER FOR THE 8080 FRONT END
LDB T1,BKPALV ;GET THE CURRENT COUNT
AOS T1 ;INCREMENT IT
;NOT NECESSARY TO MASK SINCE DPB WILL DO THAT FOR US
; ANDI T1,377 ;WE COUNT IT MODULO 8 BITS
DPB T1,BKPALV ;PUT IT IN ITS PROPER PLACE
POPJ P, ;RETURN
BKPALV: POINT 8,RLWORD,27 ;BYTE POINTER TO KEEP ALIVE COUNT
UBACHK: PUSHJ P,SAVE1## ;FREE UP AN AC
MOVEI P1,1 ;START WITH FIRST ADAPTER
UBACK1: MOVS T1,P1 ;GET ADAPTER NUMBER,,0
HRRI T1,UNBSTW ;ADDRESS OF STATUS REGISTER
PUSHJ P,UBGOOD ;IS UBA ALIVE?
JRST UBACK2 ;NO--THEN DON'T TRY TO ACCESS IT
RDIO T3,(T1) ;YES--GET UBA STATUS
ANDI T3,UNBDTR!77 ;MASK OFF EXTRA BITS
MOVE T2,UBAPIT##-1(P1) ;GET PI ASSIGNMENT FOR THIS ADAPTER
IORI T2,UNBDTR ;SET DISABLE XFER BIT FOR COMPARE/SET
CAMN T3,T2 ;ARE ALL THE BITS RIGHT ?
JRST UBACK2 ;ALL OK
STOPCD .+1,DEBUG,ULP,DIEULP ;++UBA LOST ITS PI ASSIGNMENT
WRIO T2,(T1) ;REASSIGN LEVELS
UBACK2: CAIGE P1,MAXUBA ;DONE ALL ADAPTERS?
AOJA P1,UBACK1 ;NO, DO NEXT
POPJ P,
DIEULP: PUSHJ P,INLMES##
ASCIZ /UBA #/
MOVE T1,P1 ;COPY THE NUMBER
PJRST RADX10## ;PRINT AND RETURN
MEMCHK: PUSHJ P,SAVE1## ;SAVE P1
MOVEI P1,MEMSTS ;GET ADDRESS OF MEMORY STATUS REGISTER
RDIO T2,(P1) ;READ IT
TLNN T2,(MR.HLD) ;HOLDING ERROR INFORMATION?
POPJ P, ;NO
HLLZ T1,T2 ;GET A COPY
TLZ T1,^-<(MR.HLD!MR.ECC!MR.PWF)> ;TURN OFF ALL ERROR BITS
WRIO T1,(P1) ;CLEAR ERROR BITS
MOVE P1,T2 ;COPY STATUS BITS
TLNN P1,(MR.BAD!MR.REF!MR.PAR!MR.PWF) ;"HARD" ERROR?
JRST MEMCK1 ;NO
AOS .CPHME## ;INCREMENT COUNT OF HARD ERRORS
MOVEM P1,.CPHMS## ;SAVE LAST HARD ERROR STATUS
STOPCD MEMCK2,INFO,KSHME,DIEKSH, ;++KS HARD MEMORY ERROR
MEMCK1: AOS .CPSME## ;INCREMENT COUNT OF SOFT ERRORS
MOVEM P1,.CPSMS## ;SAVE LAST SOFT ERROR STATUS
MEMCK2: TLNN P1,(MR.BAD!MR.REF!MR.PAR!MR.PWF) ;"HARD" ERROR?
TDZA T2,T2 ;NO, PUT ZERO IN U
MOVEI T2,1 ;REMEMBER IT WAS A HARD ERROR
MOVEM T2,.CPMFL## ;SAVE FLAG TO INDICATE LAST ERROR TYPE
SETZ T1, ;LET XFR ROUTINE ALLOCATE
XMOVEI T2,KSMTBL ;POINT TO TRANSFER TABLE
PUSHJ P,XFRSEB## ;COPY DATA
JFCL ;NO CORE
POPJ P, ;RETURN
KSMTBL: SEBTBL (.ERKSM,KSMEND,<EX.QUE!EX.SYE>)
MOVE .CPSME## ;(R00) NUMBER OF SOFT MEMORY ERRORS
MOVE .CPSMS## ;(R01) MEM STATUS REG AT LAST SOFT ERROR
MOVE .CPHME## ;(R02) NUMBER OF HARD MEMORY ERRORS
MOVE .CPHMS## ;(R03) MEM STATUS REG AT LAST HARD ERROR
MOVE .CPSMC## ;(R04) NUMBER OF SOFT ERRORS IN LAST MINUTE
MOVE .CPMFL## ;(R05) LAST MEMORY ERROR FLAG (0=SOFT, 1=HARD)
KSMEND:! ;END OF TABLE
DIEKSH: PUSHJ P,INLMES## ;START THE NOISE
ASCIZ /Hard memory error/
MOVEI T1,[ASCIZ / (Bad Data)/]
TLNE P1,(MR.BAD) ;BIT SET?
PUSHJ P,CONMES## ;YES
MOVEI T1,[ASCIZ / (Refresh Error)/]
TLNE P1,(MR.REF) ;BIT SET?
PUSHJ P,CONMES## ;YES
MOVEI T1,[ASCIZ / (Parity Error)/]
TLNE P1,(MR.PAR) ;BIT SET?
PUSHJ P,CONMES## ;YES
MOVEI T1,[ASCIZ | (Power/Battery Backup Failure)|]
TLNE T1,(MR.PWF) ;BIT SET?
PUSHJ P,CONMES## ;YES
POPJ P, ;RETURN
>; END IFN FTKS10
SUBTTL KS ONCE PER MINUTE CODE
IFN FTKS10,<
KSMIN:: MOVE T1,.CPSME## ;GET NUMBER OF SOFT ERRORS DURING LAST MINUTE
CAMG T1,.CPSMC## ;ANY HAPPEN DURING THE LAST MINUTE?
POPJ P, ;NO, NOTHING TO DO
MOVSI T1,(ST%NSE) ;GET THE BIT
TDNN T1,CNFST2## ;WANT TO SUPPRESS MESSAGES?
STOPCD .+1,EVENT,KSSME,DIEKSS, ;++KS SOFT MEMORY ERROR
MOVE T1,.CPSME## ;GET CURRENT COUNT
MOVEM T1,.CPSMC## ;SAVE FOR NEXT MINUTE
POPJ P, ;RETURN
DIEKSS: MOVE P1,.CPSME## ;GET CURRENT COUNT
SUB P1,.CPSMC## ;SUBTRACT PREVIOUS TO GET NUMBER LAST MINUTE
MOVE T1,P1 ;COPY HERE FOR RADX10
PUSHJ P,RADX10## ;PRINT THE TOTAL
PUSHJ P,INLMES## ;START THE NOISE
ASCIZ / ECC correctable memory error/
MOVEI T1,[ASCIZ /s/] ;MAYBE PLURAL
CAIE P1,1 ;BUT NOT IF ONE
PUSHJ P,CONMES## ;LET'S BE GRAMMATICAL OUT THERE
PUSHJ P,INLMES## ;PRINT ADDRESS
ASCIZ / last minute
Last ERA = /
LDB T1,[POINT 22,.CPSMS##,35] ;GET ERA
PUSHJ P,PRT22A## ;PRINT IT
PUSHJ P,INLMES## ;MORE NOISE
ASCIZ /, correction code = /
LDB T1,[POINT 7,.CPSMS##,11] ;GET CORRECTION CODE
PJRST PRTDI8## ;PRINT IT AND RETURN (ERRCON ADDS CRLF)
;HERE FROM COMCON TO DISABLE SOFT MEMORY ERROR MESSAGES
MEMSIL::MOVSI T1,(ST%NSE) ;GET THE BIT
IORM T1,CNFST2## ;SET IT
JRST CPOPJ1## ;SKIP RETURN
>; END IFN FTKS10
SUBTTL DTESER SIMULATION
;ROUTINES TO TURN KEEP ALIVE FUNCTION ON AND OFF WITH 8080 FRONT END
IFN FTKS10,<
$LOW
SVPPC:: PUSH P,T1 ;SAVE T1
MOVSI T1,(KPACT) ;KEEP ALIVE ACTIVE BIT
TDNN T1,RLWORD ;ARE WE GOING TO GET KAF'ED?
JRST DISKA1 ;NO, JUST BE A LONG NO-OP
ANDCAM T1,RLWORD ;YES, CLEAR THE BIT
MOVE T1,(P) ;RESTORE T1
ADJSP P,-2 ;BALANCE STACK
PUSHJ P,@1(P) ;CALL OUR CALLER
JRST ENAKAL ;PROPAGATE NON-SKIP
AOS (P) ;AND SKIP
;FALL INTO ENAKAL
ENAKAL::PUSH P,T1 ;SAVE T1
MOVSI T1,(KPACT) ;KEEP ALIVE ACTIVE BIT
IORM T1,RLWORD ;SET IT
PJRST DISKA1 ;RETURN
DISKAL::PUSH P,T1 ;SAVE T1
MOVSI T1,(KPACT) ;KEEP ALIVE ACTIVE BIT
ANDCAM T1,RLWORD ;CLEAR IT
DISKA1: POP P,T1 ;CAN'T USE TPOPJ SINCE
POPJ P, ; WE MAY NOT BE MAPPED
$HIGH
;ROUTINE TO GET DATE AND TIME FROM THE FRONT END
;
;IN OUR CASE, THIS (MIGHT BE) A TCU150 ON THE UNIBUS
SPCGDT::MOVE T1,[EXP CLKCSR] ;GET IO ADDRESS OF CSR
PUSHJ P,UBGOOD ;SEE IF INSTALLED
POPJ P, ;NOT INSTALLED, CAN'T HELP
MOVE T1,[EXP CLKCSR] ;RESTORE IO ADDRESS
RDIO T2,0(T1) ;GET DATE
RDIO T3,2(T1) ;GET TIME
HRL T2,T3 ;SAVE TIME,,DATE
RDIO T3,4(T1) ;GET SECOND
LDB T1,[POINT 7,T2,26] ;GET YEARS SINCE 1900
ADDI T1,^D1900 ;MAKE INTO REAL YEAR
CAIGE T1,^D1964 ;BASIC SANITY CHECK
POPJ P, ;CLOCK IS BAD
MOVEM T1,LOCYER## ;SAVE YEAR
LDB T1,[POINT 4,T2,30] ;GET MONTH
SKIPE T1 ;SANE?
CAILE T1,^D12 ;...
POPJ P, ;NO
MOVEM T1,LOCMON## ;YES, SAVE MONTH
SOJ T1, ;MAKE INTO TABLE OFFSET
LDB T4,PMONTB## ;GET DAYS IN MONTH - 1
AOJ T4, ;MAKE ONE-BASED
SOJN T1,SPGDT1 ;IF FEBRUARY
MOVE T1,LOCYER## ;GET YEAR
TRNN T1,3 ;AND IF LEAP YEAR
AOJ T4, ;ALLOW FOR EXTRA DAY
SPGDT1: LDB T1,[POINT 5,T2,35] ;GET DAY OF MONTY
SKIPE T1 ;CHECK FOR SANITY
CAMLE T1,T4 ;...
POPJ P, ;BAD CLOCK
MOVEM T1,LOCDAY## ;SAVE DAY OF MONTH
LDB T1,[POINT 5,T2,9] ;GET HOUR
CAILE T1,^D24 ;SEE IF MAKES SENSE
POPJ P, ;SIGH
CAIN T1,^D24 ;MIDNIGHT?
SETZ T1, ;YES, USE OUR CONVENTION
MOVEM T1,LOCHOR## ;SAVE HOUR
LDB T1,[POINT 6,T2,17] ;GET MINUTE
CAILE T1,^D59 ;MAKE SURE IT'S NOT JUNK
POPJ P, ;PARANOIA 1, CLOCK 0
MOVEM T1,LOCMIN## ;SET MINUTE
LDB T1,[POINT 6,T3,35] ;GET SECOND
CAILE T1,^D59 ;FINAL CHECK
POPJ P, ;FAILED
MOVEM T1,LOCSEC## ;SET SECOND AND VALID FLAG
JRST CPOPJ1## ;SUCCESS
>; END IFN FTKS10
SUBTTL IOCSS - I/O SERVICE SUBROUTINES (UUOCON AND DEVICE ROUTINES)
;ROUTINE TO SAVE AND OPTIONALLY SET UP THE USER BASE REGISTER
; AND RESTORE IT ON A CPOPJ OR CPOPJ1 RETURN
;CALLING SEQUENCE:
; PUSHJ P,SVEUB ;TO SAVE USER BASE REGISTER
;OR
; PUSHJ P,SVEUB ;TO SAVE USER BASE REGISTER AND SETUP
; ;USER BASE REGISTER FOR JOB IN J
;ALWAYS RETURN HERE
SVEUF:: PUSH P,T1 ;SAVE A TEMPORARY
PUSH P,@.CPSPT##
DATAI PAG,T1 ;GET THE USER BASE REGISTER
PUSH P,J ;SAVE J
LDB J,PJOBN## ;GET THE JOB NUMBER OF JOB CURRENTLY USING
; THIS DEVICE
PUSHJ P,MKADD ;SETUP THE UBR SO CURRENT JOB IS ADDRESSABLE
POP P,J ;RESTORE J
JRST SSEU1 ;SAVE THE PREVIOUS CONTENTS OF THE UBR AND EBR
SVEUB:: PUSH P,T1 ;SAVE A TEMPORARY
PUSH P,@.CPSPT##
DATAI PAG,T1 ;GET THE CONTENTS OF THE USER BASE REGISTER
PUSHJ P,MKADD ;SETUP THE UBR FOR THE JOB WHOSE JOB NUMBER
; IS IN J
JRST SSEU1 ;SAVE THE PREVIOUS CONTENTS OF THE UBR
SSEUB:: PUSH P,T1 ;SAVE A TEMPORARY
PUSH P,@.CPSPT##
DATAI PAG,T1 ;GET THE CONTENTS OF THE USER BASE REGISTER
SSEU1:
IFN FTKL10,<PUSHJ P,ABKCHK> ;CHECK & POSSIBLY SET EXEC MODE ADDRESS BREAK
EXCH T1,-2(P) ;GET THE CALLER'S PC AND SAVE THE CONTENTS
; OF THE UBR
MOVEM T1,1(P) ;SAVE THE CALLER'S PC IN A TEMPORARY LOCATION
; ON THE STACK
MOVE T1,-1(P) ;RESTORE T1 TO ITS CONTENTS ON ENTRY
IFN FTKL10,<
SKIPGE .CPABF## ;EXEC MODE ADDRESS BREAK ENABLED?
SKIPN .CPABW## ;AND AN ADDRESS SET?
CAIA ;DO NORMAL USER STUFF
JRST SSEU3 ;YES
DATAI APR,-1(P) ;SAVE ORIGINAL BREAK CONDITIONS
; THIS DOES NOT STORE BREAK ADDR
DATAO APR,[0] ;NO ADDRESS BREAKS
SSEU3:
>; END IFN FTKL10
PUSHJ P,@1(P) ;RETURN TO THE CALLER LEAVING .+1 ON THE
; STACK SO WHEN THE CALLER DOES A POPJ OR
; A CPOPJ1, CAN RESTORE THE PREVIOUS CONTENTS
; OF THE UBR
CAIA ;CPOPJ RETURN
AOS -3(P) ;CPOPJ1 RETURN - BUMP RETURN PC
CONO PI,PI.OFF ;DON'T ALLOW INTERRUPTS UNTIL UBR/SPT AGREE
POP P,@.CPSPT##
EXCH T1,-1(P) ;GET THE PREVIOUS CONTENTS OF THE UBR
DATAI PAG,1(P) ;READ INTO A TEMP
CAMN T1,1(P) ;GOING TO CHANGE IT TO WHAT IT IS?
JRST SSEU2 ;YES, DON'T CLEAR THE PAGING MEMORY
IFN FTKL10,<TLO T1,(LG.KPM)> ;"KEEP ME"
DATAO PAG,T1 ;RESTORE THE UBR
SSEU2: CONO PI,PI.ON ;SAFE TO ALLOW INTERRUPTS
IFN FTKL10,<
MOVSI T1,777740 ;EVERYTHING BUT THE ADDRESS
ANDM T1,(P) ;JUST USER BREAK CONDITIONS
ANDCA T1,.CPAPR## ;USER BREAK ADDRESS
IOR T1,(P) ;BREAK CONDITIONS + BREAK ADDRESS
SKIPGE .CPABF## ;EXEC MODE ADDRESS BREAK ENABLED?
SKIPN .CPABW## ;AND AN ADDRESS SET?
DATAO APR,T1 ;NO, RE-ENABLE USER ADDRESS BREAK
>; END IFN FTKL10
POP P,(P) ;CLEAR JUNK
JRST TPOPJ## ;RESTORE T1 AND RETURN
;SUBROUTINE TO SAVE CURRENT PCS, SET IT TO (T1) AND RESTORE IT TO PREVIOUS
; VALUE ON CPOPJ OR CPOPJ1 RETURN
IFN FTXMON,<
SVPCS:: PUSH P,(P) ;COPY AS SECOND WORD OF PC
XSFM -1(P) ;READ FLAGS AND PCS
PUSH P,-1(P) ;COPY OLD FLAGS AND PCS TO TOP OF THE STACK
HRRM T1,-2(P) ;STORE DESIRED (NEW) PCS
PUSH P,T1 ;SAVE ARGUMENT
HRLOI T1,MXSECN ;IN CASE IN SECTION 0,
ANDM T1,-2(P) ; IN PC SO WE DON'T XJRSTF INTO THE BOONIES
POP P,T1 ;RESTORE ARGUMENT
PUSHJ P,[XJRSTF -3(P)] ;CALL CALLER AS A COROUTINE WITH NEW PCS SETUP
CAIA ;NON-SKIP RETURN
AOS -3(P) ;SKIP RETURN, PROPAGATE IT
PUSH P,-3(P) ;COPY RETURN PC TO THE TOP OF THE STACK
PUSH P,T1 ;SAVE T1 AS RETURNED FROM SUBROUTINE CALL
HRLOI T1,MXSECN ;CLEAR FLAGS
ANDM T1,-1(P) ; IN CASE IN SECTION 0
POP P,T1 ;RESTORE T1
ADJSP P,-5 ;RESET STACK
XJRSTF 4(P) ;RESTORE OLD PCS AND RETURN
;COROUTINE TO SAVE THE CALLER'S PCS, AND RESTORE IT UPON THE CORETURN.
;CALLING SEQUENCE:
; PUSHJ P,SSPCS
; ALWAYS RETURNS HERE
;RESTORES PCS ON RETURN
SSPCS:: EXCH T1,(P) ;SAVE CALLER'S T1, GET RETURN PC
MOVEM T1,1(P) ;PUT IT WHERE COROUTINES DO
XSFM T1 ;GET CURRENT PCS
ANDI T1,MXSECN ;KEEP ONLY SECTION NUMBER
EXCH T1,(P) ;SAVE FOR CORETURN AND RESTORE CALLER'S T1
PUSHJ P,@1(P) ;CALL CALLER
CAIA ;PROPAGATE NON-SKIP
AOS -1(P) ; VS SKIP RETURN
EXCH T1,(P) ;SAVE T1 AND GET ORIGINAL PCS
MOVSI T1,<(LG.LPC)>(T1) ;LOAD PREVIOUS CONTEXT SECTION
DATAO PAG,T1 ;SET UP PCS
JRST TPOPJ## ;RESTORE T1 AND RETURN TO CALLER'S CALLER
;ROUTINE TO SETUP PCS AS DESIRED BY THE CALLER
;CALLING SEQUENCE:
; MOVEI T1, SECTION #
; PUSHJ P,STPCS
; ALWAYS RETURN HERE WITH PCS SETUP
;PRESERVES ALL REGISTERS
STPCS:: PUSH P,T1 ;IN CASE OF BITS
ANDI T1,MXSECN ;MASK DOWN TO JUST SECTION NUMBER
MOVSI T1,<(LG.LPC)>(T1) ;LOAD PREVIOUS CONTEXT SECTION
DATAO PAG,T1 ;SETUP PCS AS DESIRED
JRST TPOPJ## ;RESTORE T1 AND RETURN
>; END IFN FTXMON
;ROUTINE TO CONVERT AN IOWD TO ABSOLUTE IOWDS
;FOLLOWING THE PAGING OF A JOB
;CALLING SEQUENCE:
; MOVE T2,IOWD
; MOVEI P1,0 ;FIRST CALL
; MOVE P3,LOC OF CHANNEL DATA BLOCK
; MOVE P4,FRAME-COUNT,,CHARS/WD
; MOVE F,DDB ADDRESS
; PUSHJ P,MAPIOW
; RETURN HERE IF NOT ENOUGH MONITOR FREE CORE
; RETURN HERE - P2=ADDRESS OF FIRST IOWD
; P1=WHERE NEXT IOWD WILL BE STORED
; P2=LOC OF IOWD WE JUST STORED, IF A DX10
;*** BE CAREFUL! DXFIX AND RH2FIX *KNOW* THE LAYOUT OF THE STACK.
IFN FTKL10,<
MAPIO:: TLNN T2,-1 ;0 OR CHANNEL JUMPS ARE ILLEGAL
STOPCD CPOPJ##,DEBUG,IEZ, ;++IOWD EQUALS ZERO
PUSH P,U ;SAVE U
HLLZ U,CHNTYP(P3) ;GET CHANNEL-TYPE WORD
TLNE U,CP.RH2!CP.KLP!CP.KNI ;INTERNAL CHANNEL DEVICE?
TROA U,2 ;YES
LDB U,[POINT 1,U,1] ;NO, GET DF10/DX10 FLAG (0 OR 1)
HLL U,P4 ;PRESERVE FRAMECOUNT
PUSH P,T1 ;SAVE ALL ACS THAT ARE USED SINCE THEY
PUSH P,P4 ; ARE PROBABLY IMPORTANT TO THE CALLERS
PUSH P,P3 ; OF MAPIOW
PUSH P,T2 ; ..
PUSH P,T3 ; ..
PUSH P,T4 ; ..
JUMPN P1,MAPIO1 ;P1 IS NON-ZERO IF NOT THE FIRST CALL
PUSHJ P,GCH4WD ; ..
JRST MAPIOX ;NONE AVAILABLE
MOVE P1,T1 ;ADDRESS OF THE FOUR WORD BLOCK
MOVE P2,T1 ;ADDRESS OF THE IOWD LIST
HRLI P1,-3 ;THE NUMBER OF WORDS LEFT IN THIS BLOCK
TRNE U,2 ;INTERNAL CHANNEL DEVICE?
SETZM CHNTCW(P3) ;ACCUMULATE WORD-COUNT IN CHNTCW (FOR RH20)
MAPIO1: PUSHJ P,CHKMOR ;GET ANOTHER FOUR WORD BLOCK AND LINK IT
; TO THE CURRENT BLOCK IF ABOUT TO USE
; THE LAST WORD OF THE CURRENT BLOCK
JRST MAPIO9 ;NO MORE FOUR WORD BLOCKS
MOVE P4,-2(P) ;RESTORE THE IOWD TO P4
MOVE T2,P4 ;T2 AND P4 = IOWD
HLROS P4 ;P4 = -WORD COUNT
ADDI T2,1 ;POINT AT REAL ADR
LDB P3,DEYISN## ;GET RUNNING SECTION FOR I/O
ADDM P3,DEVISN(F) ;UPDATE DEVISN FOR THIS I/O OPERATION
SETZ P3, ;NO RUNNING TOTAL NOW
DPB P3,DEYISN## ;ZAP REMEMBERANCE OF CROSSING SECTION BOUNDARIES
HRRZ P3,T2 ;VIRTUAL ADDRESS WITHIN SECTION
MAPIO2: PUSHJ P,V2PADR ;T3 = CURRENT ABSOLUTE ADDRESS
SKIPGE USRHCU## ;IF A SAVE IS IN PROGRESS,
SKIPA ; THEN, THIS IS OK
XCT AAO ;ACCESS ALLOWED OFF
MOVEI T1,0 ;T1 = AMOUNT ACCUMULATED SO FAR
MOVE T2,T3 ;T2 = ABSOLUTE ADDRESS (IOWD STYLE)
SUBI T2,1 ;MAKE AN IOWD
PUSH P,T2 ;SAVE THE ADDRESS
ANDI T2,PG.BDY ;EXTRACT THE WORD NUMBER
SUBI T2,PG.BDY ;CALCULATE THE NUMBER OF WORDS TO DO INTO THIS PAGE
SKIPN T2 ;IF ITS ZERO DO A WHOLE PAGE WORTH
MAPIO3: MOVNI T2,PAGSIZ ; ..
SUB P4,T2 ;ADD -NUMBER OF WORDS ON THIS PAGE TO
; IOWD WORD COUNT
ADD T1,T2 ;ACCUMULATE IN TOTAL WORD COUNT
JUMPGE P4,MAPIO6 ;JUMP IF THE ORIGIONAL WORD COUNT IS EXHAUSTED
SUB P3,T2 ;UPDATE VIRTUAL ADDRESS BY AMOUNT DONE
MOVN T4,T2 ;SET T4 SO TEST WILL FAIL IF 22-BIT CHAN AND
CAML T1,[EXP -37777+PAGSIZ] ;OTHERWISE SET T3=CURRENT PAGE
ADD T4,T3 ;T4 = CURRENT PHYSICAL ADDRESS WITHIN SEGMENT
PUSHJ P,V2PADR ;T3 = NEXT PHYSICAL ADDRESS WITHIN PAGE
STOPCD .,JOB,AAO, ;++ACCESS ALLOWED IS OFF
MOVNI T2,PAGSIZ ;ASSUME WILL DO ANOTHER WHOLE PAGE
CAMLE P4,[-PAGSIZ] ;LESS THAN A PAGE LEFT IN USER IOWD
MOVE T2,P4 ;YES, WILL JUST DO THAT MUCH
ADD T2,T1 ;GET UPDATED WORD COUNT
CAME T2,[-600000] ;DON'T GENERATE IOWD WHOSE LH
CAMN T2,[-030000] ; LOOKS LIKE AN RH20 CHANNEL JUMP
JRST MAPIO5
MAPIO4: CAMN T4,T3 ;ARE THE TWO PAGES ADJACENT IN PHYSICAL MEMORY?
JRST MAPIO3 ;YES, CONTINUE ON CURRENT IOWD
MAPIO5: POP P,(P1) ;STORE THE IOWD ABSOLUTE ADDRESS
HRRZ T4,U ;GET CHANNEL TYPE INDEX
PUSHJ P,@[EXP DFFIX,DXFIX,RH2FIX](T4) ;ADJUST THE IOWD AS APPROPRIATE
JRST MAPIO8 ;NO SPACE
JUMPL U,MAPIO7 ;DONE IF FRAMECOUNT EXHAUSTED
AOBJN P1,MAPIO2 ;CONTINUE IF THERE IS ROOM IN THE FOUR WORD BLOCK
PUSHJ P,GETMOR ;GET ANOTHER FOUR WORD BLOCK
JRST MAPIO8 ;WHOOPS! NONE AVAILABLE
JRST MAPIO2 ;MAP THE REST OF THE IOWD
MAPIO6: POP P,(P1) ;STORE THE IOWD ABSOLUTE ADDRESS
ADDB P4,T1 ;ADD THE RESIDUAL WORD COUNT TO THE ACCUMULATED
; WORD COUNT
HRRZ T4,U ;GET CHANNEL TYPE INDEX
PUSHJ P,@[EXP DFFIX,DXFIX,RH2FIX](T4) ;ADJUST THE IOWD AS APPROPRIATE
JRST MAPIO8 ;OUT OF SPACE
MAPIO7: AOBJN P1,.+1 ;BUMP THE POINTER TO THE NEXT FREE WORD
SETZM (P1) ;ZERO IT SO THE LIST IS TERMINATED
AOS -7(P) ;SET FOR SKIP (WIN) RETURN
MAPIO8: HLRZS P3 ;CURRENT SECTION OFFSET FROM DEVISN
HLRE T1,-2(P) ;GET WORD COUNT
MOVNI T1,-1(T1) ;POSITIVE WORD COUNT + 1
ADD T1,-2(P) ;+ STARTING ADDRESS - 1
TRNN T1,-1 ;I/O END AT A SECTION BOUNDARY?
ADDI P3,1 ;YES, THEN START NEXT OP IN NEXT SECTION
DPB P3,DEYISN## ;SAVE THAT FOR NEXT TIME
MAPIO9: SKIPGE -3(P) ;IF WE WANT IT STORED,
TRNE U,3 ;DF10-STYLE CHANNEL?
JRST MAPIOX ;NO, DON'T DO NEXT
HRRZS U ;CLEAR POSSIBLE FRAMECOUNT
LSH U,-1
MOVE T3,P1 ;GET ADDR OF LAST IOWD FOR BYTE PTR'S
LDB T1,ADRPT2##(U) ;GET ADDR FIELD FROM LAST IOWD
HLRO P4,-1(T3) ;WORD COUNT
ASH P4,@ASH22B##(U) ;4 BITS DON'T COUNT IF 22-BIT
SUB T1,P4 ;DETERMINE ENDING DATA ADDRESS
DPB P1,ADRPT4##(U) ;PUT ADDR OF END OF IOWD LIST
MOVE T4,-3(P)
MOVEM T1,CHNTCW(T4)
MAPIOX: POP P,T4 ;RESTORE ACS
POP P,T3 ; ..
POP P,T2 ; ..
POP P,P3 ; ..
POP P,P4 ; ..
POP P,T1 ; ..
PJRST UPOPJ## ;GIVE WIN OR LOSE RETURN
;ROUTINE TO FINISH UP AN RH20 IO LIST
;PRESEVES T1
RH2ND:: PUSHJ P,SAVU## ;PRESERVE U
PUSH P,T1
MOVEI U,2 ;TELL THE WORLD IT AN RH20
MOVEI T3,BLKSIZ##-1
ANDB T3,CHNTCW(P3) ;NO SWEAT IF AN EVEN MULTIPLE OF 200 WORDS
JUMPE T3,RH2ND1
TLNE S,IOSUPR## ;SUPER I/O?
TRNN S,UDSX## ;ASSUME USER KNOWS IF HE'S FORMATTING
PUSHJ P,CHKMOR ;NOT EVEN MULTIPLE, HAVE TO INSERT A THROW-AWAY WORD
JRST RH2ND1 ;NO MORE ROOM, LET IT GO ANYWAY
MOVN T3,CHNTCW(P3) ;COMPUTE NO OF WORDS TO 0-FILL
ADDI T3,BLKSIZ##+<(INSVL.(.CCFTH,CC.OPC)_-4)> ;NO OF WORDS AND LAST+TRA
LSH T3,^D22 ;POSITION IT
MOVEM T3,(P1) ;STORE THE THROW-AWAY IOWD
TLZ T3,077777 ;JUST LAST+TRA
AOBJN P1,RH2ND2 ;STORE TCW AND EXIT (AOBJN ALWAYS JUMPS)
RH2ND1: MOVSI T3,(CC.HLT) ;LIGHT LAST-BIT IN IOWD
IORB T3,-1(P1)
LDB T2,[POINT 11,T3,13] ;GET WORDCOUNT
TDNE T3,[CC.ADR] ;ADR = 0 IS SPECIAL
ADD T3,T2 ;ADDR + N
TLZ T3,(CC.WDC) ;WDCNT SHOULD GO TO 0
RH2ND2: MOVEM T3,CHNTCW(P3) ;SAVE EXPECTED TERM WORD
PJRST TPOPJ## ;AND RETURN TO CALLER
;ROUTINE TO CONVERT A VIRTUAL ADDRESS (USER OR EXEC) TO A PHYSICAL ADDRESS
;CALLING SEQUENCE:
; MOVE F,ADDRESS OF DDB WITH DEVISC (SECTION NUMBER FOR I/O)
; SETUP IN IT
; MOVE P3,VIRTUAL ADDRESS
; PUSHJ P,V2PADR
; RETURNS HERE IF PAGE NOT ACCESSIBLE
; RETURNS HERE, T3 = PHYSICAL ADDRESS CORRESPONDING TO C(DEVISN)B18+(P3)
V2PADR: SKIPL DEVISN(F) ;IOWD ALLOWED TO CROSS A SECTION BOUNDARY?
TLNN P3,-1 ;NO, DOES IT?
SKIPA T3,T1 ;IOWD IS OK, SAVE T1
POPJ P, ;IOWD CROSSES SECTION BOUNDARY WHEN IT SHOULDN'T
HRLZ T1,DEVISN(F) ;SECTION NUMBER WHERE ORIGINAL IOWD STARTED
MOVE T2,P3 ;COPY VIRTUAL ADDRESS
ADD T2,T1 ;SECTION NUMBER FOR I/O
HLRZ T1,T2 ;PCS SECTION
PUSHJ P,SVPCS ;SAVE PCS AND SET IT TO SECTION NUMBER FOR I/O
MOVE T1,T3 ;RESTORE T1
MOVE T3,DEVMOD(F) ;GET DEVICE TYPE BITS
SKIPL DEVSPL(F) ;SPOOLED DDBS ARE ALWAYS A DSK
TLNE T3,DVDSK ;IF A DSK
CAIA ;SPOOLED DDB OR DSK
SKIPN T3 ;MONITOR I/O IF REREADING HOME BLOCKS
SKIPL S ;MONITOR I/O?
SKIPA T3,[PXCT PX.MEM,[MAP T3,(T2)]] ;USER ADDRESS
MOVSI T3,(MAP T3,(T2)) ;EXEC ADDRESS
SE1ENT ;SAVE CALLER'S SECTION, ENTER SECTION 1
XCT T3 ;MAP OR PXCT OF A MAP
TLNN T3,(MP.BAD) ;BAD FAIL OR
TLNN T3,(MP.BTS) ; INACCESSIBLE?
POPJ P, ;YES TO EITHER, WILL FAULT
TLZ T3,(MP.NAD) ;CLEAR NON-ADDRESS BITS
JRST CPOPJ1## ;REF OK. WIN.
;ROUTINE USED TO HANDLE 22-BIT CHNLS AND PERFORM IOWD TRANSFORMATIONS
;FOR THE DX10 TAPE CHL. CALLING SEQUENCE:
; MOVE T1,-WDS TO XFER
; MOVE P1,ADDRS OF CURRENT IOWD
; CHARS/WD WAS FOUND IN THE ORIGINAL CALL TO MAPIO
; PUSHJ P,DXFIX
; ... ;RETURN HERE IF NO MORE FREE SPACE
; ... ;RETURN HERE IF OK
DXFIX: MOVE T4,-5(P) ;RESTORE CHAR/WD
IMULI T1,0(T4) ;CONVERT TO BYTE COUNT
AOS 0(P1) ;DX10 LIKES ADDRS RATHER THAN ADDRS-1
HLRZ T3,U ;FRAME COUNT USER SET
JUMPE T3,DXFIX0 ;NONE
MOVNS T3
CAML T3,T1 ;MORE THAN HE WANTS?
MOVE T1,T3 ;YES, GET WHAT WAS REQUESTED
HRLZ T3,T1 ;FRAMECOUNT
ADDB T3,U ;UPDATE MAX LEFT
TLNN T3,-1 ;ROOM FOR MORE?
HRROS U ;NO, INDICATE WE'RE DONE
DXFIX0: CAML T1,[-17777] ;ROOM FOR THIS
JRST DXFIX2 ;YES - JUST STORE AND EXIT
MOVE T3,MCHTAB(T4) ;MAX CHARS / XFER CMD
SUB T1,T3 ;SUBTRACT MAX FOR THIS ONE
DPB T3,WDCPNT##(U) ;STORE IN IOWD
PUSH P,0(P1) ;SAVE PNTR
AOBJN P1,DXFIX1 ;SEE IF ROOM FOR MORE
PUSH P,T1 ;NO -SAVE COUNT
PUSHJ P,GETMOR ;GET MORE SPACE
JRST DXFIX3 ;RAN OUT OF SPACE
POP P,T1 ;RESTORE COUNT
DXFIX1: POP P,T3 ;GET LAST POINTER
MOVE T4,-5(P) ;RESTORE T4 (CHARS/WD)
ADD T3,MWDTAB(T4) ;ADD MAX WORDS OFFSER
MOVEM T3,0(P1) ;NEW PARTIAL PNTR
JRST DXFIX0 ;5ROCEED
DXFIX2: DPB T1,WDCPNT##(U) ;STORE RESIDUE
HRL P2,P1 ;LOC OF THE IOWD
JRST CPOPJ1## ;SUCCESS RETURN
DXFIX3: POP P,T1 ;PRUNE PDL
JRST TPOPJ## ;PRUNE & EXIT (FAIL)
;THE BYTE PACKING MODES OF THE DX10 WILL ALLOW 4,5 & 6 BYTES / WORD
;THESE TABLES ARE USED TO TRANSLATE THIS INFO INTO 1) THE MAX CHARS
;THAT WILL EXACTLY FILL THE 2) MAX NO. OF WDS PER IOWD
;ALLOWING 2^13-1 BYTES / IOWD.
MCHTAB=.-4
-<17777/4>*4 ;4 BYTE/WD = 8188 BYTES
-<17777/5>*5 ;5 BYTE/WD = 8190 BYTES
-<17777/6>*6 ;6 BYTE/WD = 8190 BYTES
MWDTAB=.-4
17777/4 ;4 BYTE/WD = 2047 WDS
17777/5 ;5 BYTE/WD = 1638 WDS
17777/6 ;6 BYTE/WD = 1365 WDS
;ROUTINE TO HANDLE DF10C-STYLE CHANNELS
DFFIX: DPB T1,WDCPNT##(U) ;STORE WORD COUNT
JRST CPOPJ1## ;SKIP RETURN
;ROUTINE TO HANDLE RH20 CHANNELS
RH2FIX: SKIPE (P1) ;UNLESS THROW-AWAY IOWD
AOS (P1) ;RH20 LIKES ADDRESS
MOVNS T1 ; AND POSITIVE WRDCNT
HLRZ T3,U ;GET FRAME COUNT
JUMPE T3,RH2FX0 ;DO WE HAVE FC?
MOVE T4,-5(P) ;YES, RESTORE CHAR/WD
IDIVI T3,(T4) ;FC TO WC
SKIPE T4 ;EXTRA FRAMES?
ADDI T3,1 ;YES, ADD A WORD
CAMLE T1,T3 ;TAKE SMALLER
MOVE T1,T3
RH2FX0: MOVE T3,-4(P)
ADDM T1,CHNTCW(T3) ;ACCUMULATE WDCNT
RH2FX1: CAIG T1,3600 ;IF LESS THAN 12 BITS,
JRST RH2FX3 ; DONT HAVE TO FIDDLE WITH IT
MOVEI T3,3600+<(INSVL.(.CCFDT,CC.OPC)_-4)>;ONLY CAN DO 11 BITS IN ONE IOWD
DPB T3,WDCPNT##(U) ;SAVE THIS IOWD
SUBI T1,3600 ;ACCUMULATE WHAT WE'VE DONE SO FAR
PUSH P,(P1) ;SAVE PARTIAL IOWD
AOBJN P1,RH2FX2 ;GO IF ROOM FOR ANOTHER IOWD
PUSH P,T1 ;SAVE WDCNT
PUSHJ P,GETMOR ;GET ANOTHER 4-WORD BLOCK
JRST DXFIX3 ;NO MORE - GIVE LOSE RETURN
MOVEI T2,0 ;RESET T2 TO BEGINNING OF PAGE
POP P,T1 ;RESTORE COUNT
RH2FX2: POP P,T3 ;RESTORE PARTIAL IOWD
TDNE T3,[CC.ADR] ;IF NOT A SKIP-IOWD
ADDI T3,3600 ;UPDATE ADDR
MOVEM T3,(P1) ;SAVE NEW IOWD (ONLY ADR USED)
JRST RH2FX1 ;AND SET WDCNT FOR NEXT PIECE
RH2FX3: TRO T1,<(INSVL.(.CCFDT,CC.OPC)_-4)> ;INDICATE THIS IS A DATA-IOWD
DPB T1,WDCPNT##(U) ;STORE WDCNT AND TRA-BIT
JRST CPOPJ1## ;INDICATE WE WON
;SUBROUTINE TO REVERSE THE IOWDS FOR A READ-OPPOSITE
;WORKS ONLY FOR AN RH20 DEVICE
;CALL WITH T1=IORB T2=WORDCOUNT T3=ICWA
;RETURNS WITH T1=IORB, THE LIST REVERSED
;RETURNS T2=ORIGINAL LH OF IOWD WHICH GOT CHANGED,,ITS ADDRESS
REVCCW::JUMPE T2,CPOPJ## ;WORDCOUNT OF 0 WILL CAUSE A CRASH
PUSHJ P,SAVE4##
SETZ P1,
PUSH P,T3
REVCC1: SKIPN P2,(T3) ;GET A CCW
SOJA T3,REVCC5 ;ZERO INDICATES END OF LIST
TLNE P2,(CC.WDC) ;WORDCOUNT EQUAL 0?
AOJA P1,REVCC2 ;NO, CAN'T BE JUMP
HRRZ T3,P2 ;GET JUMP ADDRESS
JRST REVCC1 ;KEEP LOOKING
REVCC2: LDB T4,CNTPP2 ;GET WORD COUNT
CAMLE T4,T2 ;MORE THAN WHAT IS LEFT?
JRST REVCC3 ;YES
SUB T2,T4 ;SUBTRACT THAT AMOUNT
JUMPE T2,REVCC4 ;DONE IF WORDCOUNT GOES TO ZERO
TLNE P2,(CC.HLT) ;THIS CCW HAVE THE HALT BIT SET?
JRST REVCC5 ;YES, END
AOJA T3,REVCC1 ;KEEP LOOKING
REVCC3: DPB T2,CNTPP2 ;STORE WORD COUNT
REVCC4: TLO P2,(CC.HLT) ;SET HALT BIT IN LAST CCW
REVCC5: MOVE P4,T3
HLL P4,(P4)
MOVEM P2,(T3)
POP P,T2
;HERE WITH P1= # OF IOWDS, T2 POINTS AT 1ST IOWD, T3 POINTS AT LAST IOWD
REVCC6: SOJLE P1,REVCC9
MOVE P3,(T3)
MOVE P2,(T2)
TLZE P3,(CC.HLT) ;HALT BIT SET?
TLO P2,(CC.HLT) ;YES, PROPAGATE IT
PUSHJ P,REVIOW
MOVEM P2,(T3)
MOVE P2,P3
PUSHJ P,REVIOW
MOVEM P2,(T2)
SOJLE P1,REVCCA
ADDI T2,1
MOVE T4,(T2)
TLNN T4,(CC.WDC) ;WORDCOUNT EQUAL 0?
HRR T2,T4
MOVEI P3,-1(P1)
HRRZ T3,T2
REVCC7: AOSA T3
REVCC8: HRR T3,T4
MOVE T4,(T3)
TLNN T4,(CC.WDC) ;WORDCOUNT EQUAL 0?
JRST REVCC8
SOJG P3,REVCC7
JRST REVCC6
REVCC9: JUMPL P1,REVCCA
MOVE P2,(T2)
PUSHJ P,REVIOW
MOVEM P2,(T2)
REVCCA: MOVE T2,P4
POPJ P,
REVIOW: LDB T4,CNTPP2 ;GET WORDCOUNT
TLCE P2,(CC.REV) ;COMPLEMENT REVERSE BIT, IS IT SET?
JRST [SUBI P2,-1(T4)
POPJ P,]
ADDI P2,-1(T4)
POPJ P,
CNTPP2: POINT 11, P2, 13 ;EXTRACT WORD COUNT FROM P2
;SUBROUTINE TO CHECK TO SEE IF THE CURRENT FOUR WORD BLOCK IS EXHAUSTED
; AND IF SO GET ANOTHER ONE IF ANY ARE AVAILABLE. IF THE NEXT FOUR WORD
; BLOCK IT OBTAINS IS ADJACENT TO THE CURRENT ONE, IT SIMPLY RETURNS. IF
; IT IS NOT, A LINK WORD LINKING THE CURRENT FOUR WORD BLOCK TO THE
; NEW FOUR WORD BLOCK IS SETUP IN THE FOURTH WORD OF THE CURRENT BLOCK
;CALLING SEQUENCE:
; MOVE P1,AOBJN POINTER TO CURRENT BLOCK
; MOVEI U,2 IF RH20/INTERNAL CHANNEL
; 1 IF DX10
; 0 IF DF10C-STYLE CHANNEL
; PUSHJ P,CHKMOR
; ... RETURN HERE IF NO MORE FOUR WORD BLOCKS
; ... RETURN HERE IF CURRENT FOUR WORD BLOCK NOT FILLED OR
; NEXT FOUR WORD BLOCK OBTAINED
;P1 = AOBJN POINTER TO CURRENT OR NEW BLOCK
CHKMOR::JUMPL P1,CPOPJ1## ;CONTINUE IF ANY WORDS LEFT IN THIS BLOCK
GETMOR::PUSHJ P,GCH4WD ;GET 1 CORE BLOCK
POPJ P, ;NO MORE AVAILABLE
CAIE T1,1(P1) ;IS THIS BLOCK ADJACENT TO THE LAST BLOCK?
JRST GETMR1 ;NO, ADD A LINK
HRLI P1,-4 ;YES, FOUR WORDS LEFT TO GO (LAST WORD IN
; THE LAST BLOCK AND THREE WORDS IN NEW BLOCK)
JRST CPOPJ1## ;RESTORE T2 AND GIVE OK RETURN
GETMR1: TRNE U,2 ;RH20?
HRLI T1,(INSVL.(.CCJMP,CC.OPC)) ;YES, MAKE RIGHT STYLE JUMP-WORD
TRNE U,1 ;IF DX10 CHANNEL,
HRLI T1,CCHJGO## ; DX10 STYLE CHL JUMP
MOVEM T1,0(P1) ;LINK TO THE NEW BLOCK
MOVE P1,T1 ;P1 = POINTER TO NEW BLOCK
HRLI P1,-3 ;NUMBER OF WORDS LEFT TO GO IN THE CURRENT BLOCK
JRST CPOPJ1## ;AND SKIP RETURN
;ROUTINE TO RETURN FREE CORE USED FOR MAPPING IOWDS.
;CALLING SEQUENCE:
; MOVE T1,ADDRESS OF IOWD LIST
; PUSHJ P,RTNIOW
; ALWAYS RETURN HERE
RTNIOW::PUSHJ P,SAVE1## ;SAVE P1
HRRZ P1,T1 ;P1 = ADDRESS OF THE IOWD LIST
RTNIO1: MOVEI T1,1 ;GIVE BACK ONE FOUR WORD BLOCK
HRRZ T2,P1 ;ADDRESS OF THE BLOCK
MOVE T3,3(P1) ;LAST WORD OF BLOCK
TLNN T3,577777 ;AN IOWD?
SKIPA P1,T3 ;NO, THEN THIS IS THE LAST BLOCK
; OR A LINK TO THE NEXT BLOCK
ADDI P1,4 ;ADDRESS OF THE NEXT BLOCK
; (ITS ADJACENT TO THE CURRENT BLOCK)
PUSHJ P,RCH4WD ;RETURN BLOCK TO MONITOR FREE CORE
JUMPE P1,CPOPJ## ;JUMP IF THIS IS THE LAST BLOCK
JRST RTNIO1 ;GIVE UP ALL THE BLOCKS
;ROUTINE TO OBTAIN A LOWER-CORE 4-WORD BLOCK
GCH4WD::MOVE T1,NOIOWD## ;IF WE ARE LOW ON IOWD SPACE
CAMGE T1,NUMKON## ; ONLY GIVE AN IOWD
JUMPN P1,CPOPJ## ; FOR THE INITIAL IOWDS
MOVEI T1,1 ;JUST WANT 1 BLOCK
MOVEI T2,LOWPTR## ;POINT TO LOWER-CORE FREE-CORE TABLE
PUSHJ P,GETBIT## ;GET, SET THE BIT
POPJ P, ;NONE AVAILABLE, LOSE
SOS NOIOWD## ;1 LESS IOWD BLOCK
LSH T1,2 ;CONVERT TO 4-WORD STYLE
ADD T1,LOWLOC## ;CONVERT TO ACTUAL ADDRESS
SETZM 3(T1) ;ZERO THE LAST WORD OF THE CURRENT BLOCK
PJRST CPOPJ1## ;AND TAKE GOOD RETURN
;ROUTINE TO RETURN LOWER-CORE 4-WORD BLOCKS
RCH4WD::SUB T2,LOWLOC## ;CONVERT TO RELATIVE ADDRESS
LSH T2,-2 ;/4 TO CONVERT TO BITS
IDIVI T2,^D36 ;COMPUTE WORD ADR, POSITION IN WORD
HRLS T2
ADD T2,LOWPTR## ;SET AOBJN POINTER FOR SETZRS
ADDM T1,NOIOWD## ;1 MORE IOWD BLOCK
PJRST SETZRS## ;CLEAR THE BITS AND RETURN
>; END IFN FTKL10
;ROUTINE TO SET UP UNIBUS ADAPTER MAPPING REGISTERS FOR A GIVEN
;IOWD FOLLOWING THE PAGING OF A JOB. PRESERVES T1-T4, P3, P4.
;
;CALL MOVE T2,IOWD
; MOVEI P1,0 ;FIRST CALL
; MOVE P3,LOC OF CHANNEL DATA BLOCK
; MOVE P4,FRAME-COUNT,,CHARS/WD IF TU45
; PUSHJ P,MAPIO
;RETURN CPOPJ IF IOWD EXCEEDS AVAILABLE PAGING REGISTERS
; CPOPJ1 P2=ADDRESS OF FIRST PAGING REGISTER USED
; P1=ADDRESS OF NEXT PAGING REGISTER TO BE USED
IFN FTKS10,<
MAPIO:: TLNN T2,-1 ;0 OR CHANNEL JUMPS ARE ILLEGAL
STOPCD CPOPJ##,DEBUG,IEZ, ;++IOWD EQUALS ZERO
PUSHJ P,SVEUB ;SAVE AND SETUP UBR
PUSHJ P,SAVT## ;SAVE T REGS
PUSH P,U ;SAVE U
MOVE P1,CHNIMR(P3) ;UBA #,,1ST ASSIGNED PAGING REGISTER
HRRZI T4,-UBAEXP(P1) ;OFFSET FROM BASE OF UBA PAGING REGISTERS
LSH T4,P2WLSH ;CONVERT TO PAGES
MOVE U,T2 ;SAVE IOWD IN U
AOS T2 ;ACCOUNT FOR FACT THAT IOWD'S ARE ADDR-1
ANDI T2,PG.BDY ;GET LOW 9 BITS OF STARTING ADDRESS
ADD T4,T2 ;FORM STARTING "DOUBLE-WORD" -11 ADDRESS
LSH T4,2 ;TURN INTO BYTE ADDRESS
MOVEM T4,CHNIEA(P3) ;AND SAVE IN CHANNEL DATA BLOCK
MOVE T4,CHNMRC(P3) ;GET MAPPING REGISTER COUNT
MOVE T2,U ;T2 AND U = IOWD
HLROS U ;U = -WORD COUNT
MOVEI T2,1(T2) ;STARTING ADDRESS
PUSHJ P,V2PADR ;SEE WHAT KIND OF REFERENCE THIS IS
JFCL ;ILLEGAL, WE'LL CATCH IT LATER
TLZE P1,(1B0) ;EXEC?
CAIE T2,1 ;YES, "NO DATA XFER" TYPE IOWD? (INCREMENTED)
JRST MAPIO1 ;NO, CONTINUE
MOVEI T2,CHNDBF(P3) ;YES, POINT TO ADDRESS OF DUMMY BUFFER
SETOM CHNNXF(P3) ;SET FLAG FOR DEVICE DRIVER TO SET ADDRESS INH
MAPIO1: MOVE T1,T2 ;ANOTHER ADDRESS (THIS BECOMES A FLAG)
MAPIO2: PUSHJ P,V2PADR ;GET PHYSICAL ADDRESS IN T3
SKIPGE USRHCU## ;IF SAVE IN PROGRESS
SKIPA ;THEN, WE LET ERROR PASS
STOPCD .,JOB,AAO, ;++ACCESS ALLOWED OFF (BUT THE IOWD ADDRESS CHECKED)
TLZ P1,(1B0) ;CLEAR EXEC ADDRESS FLAG
LSH T3,W2PLSH ;GET PAGE NUMBER FOR UBA MAPPING
PUSHJ P,SETUBB ;GO SET PROPER UBA BITS IN T3
WRIO T3,(P1) ;AND LOAD THE PAGING RAM
JUMPE T1,MAPIO3 ;IF NOT FIRST PAGE, DO WHOLE PAGE
ANDI T1,PG.BDY ;EXTRACT THE WORD NUMBER
SUBI T1,PAGSIZ ;CALCULATE THE NUMBER OF WORDS DONE IN FIRST PAGE
CAIA ;SKIP PASS 2 CODE
MAPIO3: MOVNI T1,PAGSIZ ;(- # DONE)
SUB U,T1 ;-#LEFT = -#LEFT --#DONE
JUMPGE U,MAPIO4 ;JUMP IF THE ORIGIONAL WORD COUNT IS EXHAUSTED
MOVEI T1,0 ;START NEXT PAGE AT ADDRESS 0
ADDI P1,1 ;POINT TO NEXT MAPPING REGISTER
ADDI T2,PAGSIZ ;STEP TO NEXT PAGE
SOJG T4,MAPIO2 ;CONTINUE IF THERE IS ROOM
SETZ P1, ;INDICATE NONE
STOPCD UPOPJ##,JOB,OMR ;++OUT OF MAPPING REGISTERS
;HERE WITH ENTIRE IOWD MAPPED
;U/ NUMBER OF WORDS OF LAST PAGE MAPPED BUT NOT USED
MAPIO4: HRRZ P2,P1 ;GET LAST USED REGISTER ADDRESS
MOVNS U ;NEGATE U (NOW - XTRA WDS MAPPED)
ANDI U,PG.BDY ;WORDS INTO LAST PAGE TO TRANSFER
SKIPN U ;JUST CROSSED PAGE BOUNDARY?
AOS P2 ;YES, ACCOUNT FOR IT
LSH U,2 ;MAKE INTO AN ELEVEN STYLE ADDRESS
HRRZI P2,-UBAEXP(P2) ;GET OFFSET INTO MAPPING REGISTERS
IMULI P2,UBAMUL ;MAKE INTO 11 STYLE ADDRESSING
ADDB P2,U ;FORM ADDRESS OF LAST WORD TO TRANSFER
SUB U,CHNIEA(P3) ;MINUS STARTING ADDRESS
TLNE P4,-1 ;USER FRAME COUNT?
HLRZ U,P4 ;YES, BELIEVE USER
MOVEM U,CHNBTC(P3) ; AND SAVE THE TOTAL BYTE COUNT
SKIPGE CHNNXF(P3) ;IS THIS A NO-XFER REQUEST?
MOVE P2,CHNIEA(P3) ;YES--THEN ENDING ADDRESS WILL EQUAL STARTING ADDR
SKIPGE P3 ;WANT TERMINATION EXPECTED?
MOVEM P2,CHNTCW(P3) ;STORE FOR LATER CHECKING
MOVE P2,CHNIMR(P3) ;GET ADDRESS OF INITIAL MAPPING REGISTER
PJRST UPOPJ1## ;SKIP RETURN
;ROUTINE TO SET THE PROPER BITS FOR A UBA PAGING RAM ENTRY WHICH IS IN T3.
;THE BIT SETTINGS DEPEND ON WHAT KIND OF A DEVICE IS BEING RUN THROUGH MAPIO.
SETUBB: PUSHJ P,SAVE1## ;SAVE P1
SKIPN P1,DEVMOD(F) ;PICK UP DEVICE CLASSES
MOVEI P1,DVDSK ;MUST BE READING HOME BLOCKS
TRO T3,UNBVBT ;ALWAYS SET VALID
SKIPE CHNRRV(P3) ;ARE WE DOING A READ REVERSE OPERATION?
TRO T3,UNBRRV ;YES--SET READ REVERSE
SKIPL DEVSPL(F) ;SPOOLED DDB'S ARE ALWAYS DISKS
TLNE P1,DVDSK ; OR IF A "REAL" DISK DDB
TRO T3,UNB36B ; SET FAST XFER MODE
SKIPGE DEVSPL(F) ;IF A SPOOLED DDB (I.E. DISK)
POPJ P, ; WE'RE DONE
TLNE P1,DVLPT!DVCDR ;IF AN LP20 OR CD20
TRO T3,UNBD18 ; SET 18 BITS DISABLE (16 BIT MODE)
POPJ P, ;RETURN
;ROUTINE TO TURN A VIRTUAL ADDRESS INTO A PHYSICAL ONE.
;WORRIES ABOUT WHAT SORT OF VIRTUAL ADDRESS IT MIGHT BE (EXEC, USER...)
;
;CALL: T2/ADDRESS TO MAP
; F/DDB THAT WANTS IO
; PUSHJ P,V2PADR
; HERE WHEN PAGE ISN'T ACCESSIBLE (USUALLY RESULTS IN AN AAO)
; HERE WHEN MAPS OK, T3 IS PHYSICAL ADDRESS.
;
;ONLY T3 IS TRASHED
V2PADR: MOVE T3,DEVMOD(F) ;GET DEVMOD
SKIPL DEVSPL(F) ;SPOOLED DDBS ARE ALWAYS A DSK
TLNE T3,DVDSK!DVLPT!DVCDR ;IF A DSK (OR LP20 OR CD20)
CAIA ;MONITOR IO IS POSSIBLE
SKIPN T3 ;IF MIGHT BE READING HOME BLOCK
SKIPL S ; SKIP IF MONITOR IO
SKIPA T3,[PXCT PX.MEM,[MAP T3,(T2)]] ;NOT MONITOR SPACE, MAP AS USER
TLOA P1,(1B0) ;REMEMBER THIS IS EXEC
TLZA P1,(1B0) ;THIS IS NOT
MOVSI T3,(MAP T3,(T2));MONITOR IO, MAP AS EXEC ADDRESS
IFN FTXMON,< ;SHOULD A KS EVER DO EXTENDED SECTIONS
HRL T2,DEVISN(F) ;SECTION NUMBER FOR IO
SE1ENT ;SAVE CALLER'S SECTION, ENTER SECTION 1
>
XCT T3 ;MAP EXEC OR USER, RESULT IN T3
TLNN T3,(1B8) ;PAGED REFERENCE? (OUGHTA BE 1)
JRST V2PAD1 ;NO, WILL NOT FAULT
TLNN T3,(MP.BAD) ;HARD PAGE FAILURE?
TLNN T3,(MP.BTS) ;...
POPJ P, ;YES TO EITHER, ACCESS DENIED
V2PAD1: TLZ T3,(MP.NAD) ;ACCESS IS OK, CLEAR NON-ADDRESS BITS
JRST CPOPJ1## ;RETURN SUCCESS
>; END IFN FTKS10
;HERE TO CHECK FOR EXISTENCE OF UBA DEVICES
; CALL MOVE T1,<ADR> OF DEVICE TO CHECK
; PUSHJ P,UBGOOD
; LOSE RETURN
; WIN RETURN
IFN FTKS10,<
UBGOOD::PUSHJ P,SAVT## ;RESPECT T REGS
PUSH P,.USPFW ;SAVE PAGE FAIL LOCATIONS SINCE A TRAP
PUSH P,.USPFP ; COULD CLOBBER THEM AND THEY COULD
PUSH P,.USPFP+1 ; BE IMPORTANT (TIMFLT FOR INSTANCE)
PUSH P,.CPPFT## ;SAVE PRE-EMPTIVE FAULT HANDLER
SETZ T2, ;BITS FOR TIOE
XMOVEI T3,UBNOGD ;TEMP PAGE FAIL TRAP ADDR
RDPI T4 ;SAVE STATE OF PI'S
WRPI PI.OFF ;DISABLE INTERRUPTS
MOVEM T3,.CPPFT## ;SET TEMPORARY PAGE FAIL TRAP ADR
TIOE T2,(T1) ;CHECK FOR DEVICE
SKIPA ;FAILED
AOS -4(P) ;WIN, CAUSE SKIP RETURN
MOVEI T2,UNBNED!UNBTMO ;CLEAR NED IN UNIBUS ADAPTER
HRRI T1,UNBSTW ;GET BASIC ADDRESS OF UNIBUS
BSIO T2,(T1) ;CLEAR FLAGS
TRNE T4,PI.ON ;WERE PI'S ON?
WRPI PI.ON ;YES--THEN ENABLE THEM
POP P,.CPPFT## ;RESTORE PRE-EMPTIVE FAULT HANDLER
POP P,.USPFP+1 ;RESTORE PAGE FAIL LOCATIONS
POP P,.USPFP ; ..
POP P,.USPFW ; ..
POPJ P, ;RETURN
;HERE WHEN ADDRESS IS BUM
UBNOGD: AOS .USPFP+1 ;SKIP LOSING INSTRUCTION
JRST @.USPFP+1 ;JUST RETURN (NONSKIP)
>; END IFN FTKS10
;ROUTINE TO INVALIDATE ENTIRE CACHE AND VALIDATE CORE
; ALWAYS RETURN CPOPJ, RESPECTS ALL ACS
; LOOP IN ACS WHILE WAITING FOR FLUSH COMPLETION TO MINIMIZE
; MEMORY INTERFERENCE.
CSDMP::
IFN FTKL10,<
SWPUA ;SWEEP - UPDATE ALL PAGES, INVALIDATE CACHE
PUSHJ P,SAVE3## ;SAVE E3 ACCUMULATORS
DMOVE P1,CSHWAT ;CACHE WAITING INSTRUCTIONS
MOVE P3,CPOPJ##
PJRST P1 ;WAIT IN ACS
CSHWAT: CONSZ APR,LP.CSB ;WAIT FOR CACHE SWEEP TO HAPPEN
JRST P1
>; END IFN FTKL10
IFN FTKS10,<
WREBR @.CPEBR## ;CAUSE CACHE FLUSH
AOS .CPCSN## ;COUNT THE SWEEP
POPJ P, ;RETURN
>; END IFN FTKS10
IFN FTKL10,<
;SUBROUTINE TO CHASE A LINE OUT OF THE CACHE
;ENTER T1=ADDRESS
;EXIT WITH THAT LOCATION NOT IN THE CACHE
;PRESERVES T2-T4
$LOW ;UNCACHED & WRITABLE FOR CPNSER
OUCHE:: ANDI T1,PG.BDY ;GET LINE NUMBER
OUCHTB::SKIP MONORG##+0*PAGSIZ(T1)
SKIP MONORG##+1*PAGSIZ(T1)
SKIP MONORG##+2*PAGSIZ(T1)
SKIP MONORG##+3*PAGSIZ(T1)
SKIP MONORG##+4*PAGSIZ(T1)
SKIP MONORG##+5*PAGSIZ(T1)
SKIP MONORG##+6*PAGSIZ(T1)
SKIP MONORG##+7*PAGSIZ(T1)
POPJ P,
$HIGH
>; END IFN FTKL10
SUBTTL ERRCON - ERROR HANDLING MODULE
;SUBROUTINE TO SWEEP MEMORY TO FIND ADDRESS AND CONTENTS OF BAD WORDS
;IT CALLS CPU INDEPENDENT SUB.(PARERR) TO RECORD DATA ON EACH BAD WORD
;CALL: PUSHJ P,@.CPMPS##
; ALWAYS RETURN WHEN SWEEP OVER (EVEN IF SERIOUS ERROR)
;SWEEP CORE IN ASCENDING ADDRESSES EVEN THOUGH SLOWER, SO DATA STORED ASCENDING
; FOR ERROR REPORTING WITH DAEMON
APRMPS::PUSHJ P,MAPLOC## ;GET EXEC MAP SLOT
MOVE W,T1 ;SAVE BYTE POINTER TO EXEC MAP SLOT
MOVSI P3,(<PM.DCD>B2+PM.WRT+PM.PUB) ;GET MAP BITS, START WITH PAGE 0
LDB T4,[POINT 14,NWCORE##,26] ;T4=NUMBER OF PAGES TO SCAN
SKIPA P4,[POINT 1,NXMTAB##] ;BYTE POINTER TO NXM TABLE
MPSLP1: AOS P3 ;STEP TO NEXT PAGE
SOJL T4,MPSLP3 ;RESTORE T1 AND RETURN IF SCANNED ALL OF MEMORY
ILDB T1,P4 ;DOES THIS PAGE EXIST?
JUMPN T1,MPSLP1 ;IF NOT, GO BACK FOR NEXT
DPB P3,W ;MAP THE CURRENT PAGE
MOVE P1,T3 ;EVA FOR BEGINNING OF PAGE
CLRPT (P1) ;CLEAR HDW PAGE TABLE FOR NEW MAPPING
MOVEI T2,PAGSIZ ;NO. OF WORDS/PAGE TO SCAN
PUSHJ P,CSDMP ;SWEEP CACHE
IFN FTKL10,<
MOVEI T1,@.CPEBR## ;GET EBR
TRZ T1,LG.CSL+LG.CSW ;TURN OFF LOOK AND LOAD
CONO PAG,(T1) ;DISABLE THE CACHE
>; END IFN FTKL10
SETOM .CPPSP## ;SET SWEEPING FLAG
APRMPI: MOVE P2,(P1) ;TEST NEXT LOCATION
MPSLP2: SOJLE T2,MPSLP1 ;IF CURRENT PAGE DONE, MAP NEXT
AOJA P1,APRMPI ;GO TEST NEXT WORD IN PAGE
;HERE ON BAD WORD FOUND (NXM OR PARITY) - TRAP HAPPENED AND ADDED 3 TO PC
MAP T1,(P1) ;GET THE PHYSICAL ADDRESS OF BAD WORD
PUSH P,P1 ;SAVE THE EVA
PUSH P,T2 ;SAVE THE WORD NUMBER IN CURRENT PAGE
PUSH P,T3 ;SAVE THE POSITION IN THE MAP
PUSH P,T4 ;SAVE # OF PAGES TO SCAN
LDB P1,[POINT 22,T1,35] ;GET JUST THE PHYSICAL ADDRESS OF BAD WORD
PUSHJ P,CPIASN## ;CONVERT TO SEG NUMBER IN J
TDZA T1,T1 ;INDICATE NO ERROR IN MONITOR OR A JOB
SETO T1, ;INDICATE AN ERROR IN MONITOR OR A JOB
MOVE P2,.CPTBD## ;GET BAD DATA WORD STORED BY THE TRAP ROUTINE
PUSHJ P,PARRBD## ;RECORD BAD DATA
POP P,T4 ;RESTORE T4
POP P,T3 ; AND T3
POP P,T2 ; AND T2
POP P,P1 ; AND P1
SETZM .CPPTH## ;CLEAR FLAG THAT TRAP HAPPENED
JRST MPSLP2 ;GO CONTINUE THE SWEEP
MPSLP3: SETZM .CPPSP## ;CLEAR SWEEPING FLAG
IFN FTKL10,<CONO PAG,@.CPEBR##> ;TURN CACHE BACK ON
PUSHJ P,UNMAP## ;RESTORE EXEC MAP SLOT
POPJ P, ;AND RETURN
SUBTTL BACKGROUND KL10 PERFORMANCE ANALYSIS
IFN FTKL10,<
IFN FTRSP,<
;BPAUPD -- UPDATE BACKGROUND PERFORMANCE ANALYSIS COUNTS
;CALLED BY CLOCK1 AT CLOCK INTERUPT LEVEL
;
;PRESERVES ALL ACS.
BPAUPD::SKIPE .CPPJB## ;PERFORMANCE METER IN USE BY PERF.?
POPJ P, ;YES, WE CAN'T USE IT THEN
PUSHJ P,SAVT## ;SAVE THE T AC'S
SKIPN T1,.CPBPI## ;PICK UP WHERE WE LAST LEFT OFF
JRST BPAUP5 ;NEVER BEEN HERE, INITIALIZE FIRST
HRRZ T2,T1 ;GET PACTAB INDEX
LSH T2,2 ;AND MAKE INTO 4-WORD .CPBPV INDEX
;NOW SEE HOW MUCH TIME HAS ELAPSED SINCE WE STARTED THIS ITEM COUNTING
CONO PI,PI.OFF ;VALID TIMINGS
RDTIME T3 ;GET TOTAL ELAPSED TIME
DSUB T3,.CPBPT## ;T3:=INCREMENTAL SINCE STARTED
DADD T3,.CPBPV##(T2) ;T3:=TOTAL ITEM ELAPSED TIME
DMOVEM T3,.CPBPV##(T2) ;STORE FOR INTERESTED PARTIES
;NOW READ THE PERFORMANCE METER COUNT AND SAVE IT AWAY
RDPERF T3 ;T3:=INCREMENTAL PERFORMANCE COUNTER
CONO PI,PI.ON ;LET SYSTEM GO AGAIN
DADD T3,.CPBPV##+2(T2) ;T3:=TOTAL PERFORMANCE COUNT FOR THIS ITEM
DMOVEM T3,.CPBPV##+2(T2) ;SAVE IT FOR INTERESTED READERS
;NOW SELECT NEXT CONDITION TO WATCH
AOBJN T1,.+2 ;NEXT ITEM IN BPATAB
BPAUP5: MOVSI T1,-BPATLN## ;INITIALIZE AT START OF BPATAB
WRPAE [PE.CLR] ;ZAP THE COUNTER
MOVE T4,.CPEPT## ;GET ADDRESS OF EPT FOR THIS CPU
SETZM .EPPAC(T4) ;CLEAR HIGH ORDER PERF ANAL COUNT
SETZM .EPPAC+1(T4) ;CLEAR LOW ORDER PERF ANAL COUNT
CONO PI,PI.OFF ;AGAIN, NO INTERRUPTS
RDTIME .CPBPT## ;REMEMBER WHEN THIS CONDITION SELECTED
WRPAE BPATAB##(T1) ;TURN ON PERFORMANCE METER
CONO PI,PI.ON ;AND ONCE AGAIN LET SYSTEM GO
MOVEM T1,.CPBPI## ;REMEMBER WHERE IN BPATAB WE ARE
MOVN T4,.CPBPC## ;TICK COUNT BETWEEN SAMPLES
MOVEM T4,.CPBPF## ;SET SAMPLING INTERVAL
SETZM .CPMJ1## ;NO NEED TO STOP METER ANYMORE!
POPJ P, ;BACK TO CLOCK1
> ;END OF IFN FTRSP
SUBTTL PERF. UUO FUNCTIONS TO HANDLE KL10 PERFORMANCE METER
COMMENT &
THE KL10 PERFORMANCE METER IS ASSUMED TO BE AN INTEGRAL PART OF
THE KL10 PROCESSOR, AND THUS ITS DATA BASE IS FOUND IN THE
CDB. FOR THE PURPOSES OF DOCUMENTATION AND IN THE EVENT THAT
A FUTURE CPU CAN HAVE MORE THAN ONE TYPE OF PERFORMANCE METER,
A LIST OF THE CDB LOCATIONS USED FOR THE PERFORMANCE METER
FOLLOWS:
.CPPJB - JOB WHICH OWNS PERFORMANCE METER ON THIS CPU, 0 IF FREE
.CPMJB - JOB ENABLE CONDITION, SET BY UUO. -2 = NULL JOB, 0 = DONT CARE
.CPMJ1 - JOB ENABLE CONDITION, ONLY SET IF METER IS RUNNING.
THIS IS THE VARIABLE WHICH CLOCK1 USES TO TURN THE
METER ON AND OFF TO SIMULATE A JOB ENABLE CONDITION.
THIS VARIABLE IS NEEDED BECAUSE THE METER CAN BE
STOPPED AND THEN STARTED WITH THE SAME JOB ENABLE
.CPPMR - SET NONZERO WHENEVER THE PERFORMANCE METER IS RUNNING
USED IN CHECKING FOR STARTING METER TWICE
.CPPAE - USED TO STORE THE PERFORMANCE ANALYSIS ENABLES FOR METER
.CPPRQ - SEMAPHORE USED IN TESTING AND GIVING METER AWAY
.CPAPS - FLAG THAT CAUSES THE PERFORMANCE METER TO BE TURNED
ON AND OFF WITH THE ACCOUNTING METER
.CPMM0
.CPMM1 - DOUBLE WORD LOCATION THAT CONTAINS THE NUMBER OF
MBOX REFERENCES WHILE METER WAS ON AND ENABLED
JOB CONDITION TERM WAS TRUE. USEFUL FOR MEASURING
CACHE HIT RATE.
THE FORMAT OF THESE METER FUNCTIONS WAS SETUP TO ACCOMODATE FUTURE
METERS IF NECESSARY: EVERY ENABLE CONDITION IS A SEPARATE WORD.
THE ORDER OF THE ENABLES WERE SPECIALLY CHOSEN SUCH THAT THE
MOST FREQUENTLY USED ENABLES ARE FIRST. SINCE UNSPECIFIED ARGUMENTS
ALWAYS DEFAULT TO ZERO, THIS SAVES SPACE IN THE USER PERFORMANCE
PROGRAM.
INSTEAD OF CHECKING FOR TERMINATION OF THE ARGUMENT LIST EVERY TIME
A WORD IS FETCHED OR STORED IN THESE ROUTINES, THE SPECIAL ROUTINES
PF?WDU, PF?WD1 (?=G, GET OR P,PUT) ARE USED, WHICH RETURN 0 (DONT CARE)
ON GETTING AFTER ARGS ARE EXHAUSTED OR ARE NOOPS WHEN AN ATTEMPT IS MADE
BY THE FUNCTION ROUTINES TO PLACE A VALUE BEYOND THE LIMIT OF WHAT
THE CALLER ASKED FOR.
&;END OF COMMENT
;THE FOLLOWING PERF. UUO FUNCTIONS ARE IN KLSER:
;THE FOLLOWING ERROR ROUTINES ARE CALLED BY PERF. UUO FUNCTIONS
; IN KLSER, AND ARE FOUND IN UUOCON
;FUNCION 1 - GET METER AND SETUP METER CONDITIONS
;
;FORMAT OF ARGUMENT BLOCK:
;
;ADDR: ;NUMBER OF WORDS FOLLOWING
;ADDR+1: ;CPU TYPES (1B0=PDP6,1B1=KA10,ETC.)
;ADDR+2: ;CPU NUMBER,,MODE
;ADDR+3: ;CACHE ENABLES
;ADDR+4: ;PI CHANNEL ENABLES
;ADDR+5: ;PC ENABLES
;ADDR+6: ;MICROCODE ENABLES
;ADDR+7: ;PROBE ENABLES
;ADDR+10: ;JOB
;ADDR+11: ;RH20 CHANNEL ENABLES
;ZERO ALWAYS INDICATES DON'T CARE. FOR DETAILS ON WHAT THE
; ENABLE BITS ARE, REFER TO KL10 INTERNAL CLOCK SUPPORT FUNCTIONAL SPEC.
PMRSET::PUSHJ P,CHKPMS ;CHECK CPU TYPE STUFF AND SETUP P4
POPJ P, ;ERROR OF SOME SORT (SEE CHKPMS)
PUSHJ P,GETPMR ;GET METER
JRST PREMIU## ;**METER BUSY**
; PUSHJ P,ONCPP4 ;RESCHEDULE TO CPU IN P4
PUSHJ P,STPPMJ ;STOP METER
TRZE T4,1B35 ;T4 HAS EVENT/DURATION STATE.
;TEST BORROWED BIT (CLEAR/DON'T CLEAR)
PUSHJ P,CLRPMR ;ZERO OUT PERFORMANCE COUNT
;CACHE ENABLES
PUSHJ P,PFGWD1 ;GET CACHE ENABLES FROM USER
SKIPN T1 ;DON'T CARE??
TLO T4,(PE.CCI) ;YES, SET CACHE DON'T CARE
TLZE T1,(1B4) ;ACCOUNTING METER/PERFORMANCE METER SYNC BIT?
SETOM .CPAPS## ;YES, SET THE FLAG
LSH T1,<-<^L<PE.CCR>>-<^D18>> ;SHIFT INTO POSITION
TRC T1,(PE.CCR!PE.CCF!PE.EWB!PE.SWB) ;ACCOUNT FOR THE FACT
; THAT THESE BITS ARE ZERO WHEN THE
; CONDITION IS ENABLED!
ANDI T1,(PE.CCR!PE.CCF!PE.EWB!PE.SWB) ;PREVENT OTHER BITS FROM SETTING
TSO T4,T1 ;SET DESIRED BITS
;PI ENABLES
PUSHJ P,PFGWD1 ;GET PI ENABLES
SKIPN T1 ;DON'T CARE??
TRO T4,PE.PPI ;PI IGNORE IF ZERO ARG
LSH T1,<-<^L<PE.PP0>>> ;SHIFT INTO POSITION
ANDI T1,PE.PPI ;CLEAR OUT ERRONEOUS BITS
TDO T4,T1 ;AND SET THEM IN T4
;PC ENABLES
PUSHJ P,PFGWD1 ;GET THEM
TLCE T1,(1B0!1B1) ;IF ALL BITS ARE ZERO OR
TLNN T1,(1B0!1B1) ;IF BOTH ARE SET
TRO T4,PE.PCI ;SET PC IGNORE
TLNN T1,(1B0) ;IN ANY CASE, WANT USER PC?
TRO T4,PE.PCU ;YES, SET PC USER (NN BECAUSE BITS ARE COMP.)
;MICROCODE ENABLES
PUSHJ P,PFGWD1 ;GET UCODE ENABLES
TLNN T1,(1B0) ;SKIP IF UCODE STATE ENABLED
TLO T4,(PE.UCI) ;NOT ENABLED, SET UCODE IGNORE BIT
;PROBE ENABLES
PUSHJ P,PFGWD1 ;GET THEM
TLCE T1,(1B0!1B1) ;IF BOTH OFF OR
TLNN T1,(1B0!1B1) ;BOTH ON
TLO T4,(PE.PRI) ;IGNORE PROBE
TLNN T1,(1B0) ;IN ANY CASE, WANT PROBE LOW? (COMP)
TLO T4,(PE.PRL) ;YES, ENABLE PROBE LOW
;JOB ENABLE
PUSHJ P,PFGWD1 ;JOB ENABLE
JUMPE T1,PMRST1 ;IGNORE IS OK
CAMN T1,[-1] ;SELF?
MOVE T1,J ;YES
CAMN T1,[-2] ;NULL JOB?
JRST PMRST1 ;YES, DON'T CALL LGLPRC
PUSHJ P,LGLPRC## ;IS THIS A LEGAL NUMBER?
JRST PREBJN## ;BAD JOB NUMBER
PMRST1: MOVEM T1,.CPMJB## ;EVERYTHING'S OK, STORE JOB ENABLE
;NOW FOR CHANNEL ENABLES
PUSHJ P,PFGWD1 ;GET THEM
SKIPN T1 ;DON'T CARE?
TLO T4,(PE.CPI) ;YES, SET ALL BITS FOR DON'T CARE
LSH T1,<-<^L<PE.CP0>>-<^D18>> ;POSITION (IN RH)
ANDI T1,PE.PPI ;CLEAR UNWANTED BITS
TSO T4,T1 ;AND SET THE BITS
;ADD FURTHER ENABLE LOGIC HERE
MOVEM T4,.CPPAE## ;AT LAST
JRST CPOPJ1## ;BYE.
;FUNCTION 2 - START METER
;
;THE METER MUST BE OWNED BY THE CALLING JOB (CHECKED BY PRFCPU).
; SPECIAL CARE IS TAKEN NOT TO START THE METER IF THE CALLING JOB DOES NOT
;SATISFY THE JOB ENABLE CONDTION. AFTER THE METER IS STARTED,
; THE FUNCTION RETURNS THE DOUBLE WORD TIME BASE AND PERFORMANCE COUNT
; IN THE ARGUMENT BLOCK, WHICH HAS THE FOLLOWING FORMAT:
;
;ADDR: ;COUNT OF WORDS FOLLOWING
;ADDR+1: ;CPU NUMBER
;ADDR+2: ;HIGH ORDER TIME BASE RETURNED HERE
;ADDR+3: ;LOW ORDER TIME BASE RETURNED HERE
;ADDR+4: ;HIGH ORDER PERFORMANCE METER VALUE
;ADDR+5: ;LOW ORDER " "
;ADDR+6: ;HIGH ORDER MBOX REFERENCE COUNT
;ADDR+7: ;LOW ORDER MBOX REFERENCE COUNT
PMRSTR::PUSHJ P,PRFCPU ;CHECK CPU SPEC, SETUP P4, MAKE SURE METER IS OWNED
POPJ P, ;SORRY, SOMETHING WENT WRONG
SKIPE .CPPMR## ;SKIP IF METER IS NOT STARTED ALREADY
JRST PREMAS## ;**METER ALREADY STARTED**
; PUSHJ P,ONCPP4 ;MUST RESCHEDULE ON THE RIGHT CPU TO START METER
CONO PI,PI.OFF ;TURN OFF PI SO WE CAN START AND READ
;METER WITHOUT INTERRUPTIONS
PUSHJ P,STRPMJ ;START METER IF WE'RE SUPPOSED TO
;FALL INTO STORPT
STORPT: PUSHJ P,REDPMT ;READ TIME BASE AND PERF METER INTO T1-T4
PUSH P,.CPMM1## ;ALSO SAVE MEMORY REFERENCE COUNT BEFORE
PUSH P,.CPMM0## ; PI SYSTEM IS TURNED BACK ON
CONO PI,PI.ON ;TURN PI BACK ON
PUSHJ P,PFPWD1 ;STORE HIGH ORDER TIME BASE
MOVE T1,T2
PUSHJ P,PFPWD1 ;STORE LOW ORDER TIME BASE
MOVE T1,T3
PUSHJ P,PFPWD1 ;STORE HIGH ORDER PERFORMANCE COUNT
MOVE T1,T4
PUSHJ P,PFPWD1 ;STORE LOW ORDER PERF COUNT
POP P,T1 ;GET HIGH ORDER MEMORY REFERENCE COUNT BACK
PUSHJ P,PFPWD1 ;GIVE THAT TO USER
POP P,T1 ;NOW GET LOW ORDER MEM REF COUNT
AOS (P) ;GIVE SKIP RETURN
PJRST PFPWD1 ;STORE LOW ORDER MBOX COUNT AND RETURN
;FUNCTION 3 - READ PERFORMANCE METER
;
;FORMAT OF ARGUMENT LIST SAME AS FUNCTION 2, START METER
PMRRED::PUSHJ P,PRFCPU ;CHECK AND SETUP CPU STUFF, METER OWNER
POPJ P, ;SOMETHING WENT WRONG
; PUSHJ P,ONCPP4 ;RESCHEDULE ONTO PROPER CPU FOR THIS METER
PJRST STORPT ;STORE TIME BASE, PERF COUNT AND RETURN
;FUNCTION 4 - STOP METER
;
;FORMAT OF ARG LIST SAME AS START AND READ FUNCTIONS
;
PMRSTP::PUSHJ P,PRFCPU ;SETUP P4, CHECK METER OWNERSHIP
POPJ P, ;OOOPS
; PUSHJ P,ONCPP4 ;PUT OURSELVES ONTO PROPER CPU
SKIPN .CPPMR## ;IS METER RUNNING?
JRST PREMNR## ;**METER NOT RUNNING** (SO WHY STOP IT?)
PUSHJ P,STPPMJ ;STOP METER
PJRST STORPT ;STORE GOOD STUFF AND RETURN
;FUNCTION 5 - RELEASE METER
;FORMAT OF ARGUMENT BLOCK:
;
;ADDR: ;NUMBER OF WORDS FOLLOWING
;ADDR+1: ;CPU NUMBER OF METER TO RELEASE
PMRREL::PUSHJ P,PRFCPU ;GOOD CPU? THEN SETUP P4 AFTER WE KNOW WE OWN METER
POPJ P, ;SORRY CHARLIE
; PUSHJ P,ONCPP4 ;RESCHEDULE ONTO PROPER CPU
PUSHJ P,STPPMJ ;STOP METER
MOVE T1,.CPSLF## ;POINT T1 AT THIS CPU'S CDB
AOS (P) ;SET FOR SKIP RETURN
PJRST RELPMR ;AND RELEASE, RETURN
;FUNCTION 6 - TURN OFF BACKGROUND PERFORMANCE ANALYSIS
;FUNCTION 7 - TURN ON BACKGROUND PERFORMANCE ANALYSIS
;FORMAT OF ARGUMENT BLOCK:
;
;ADDR: ;NUMBER OF WORDS FOLLOWING
;ADDR+1: ;CPU TYPES
;ADDR+2: ;CPU NUMBER,,MODE (1B19 = CLEAR COUNTS)
;ADDR+3: ;SAMPLING INTERVAL (CLOCK TICKS PER SAMPLE ITEM)
IFN FTRSP,< ;ONLY IF RESPONSE NUMBERS WANTED
PMRBPF::PUSHJ P,CHKPMS ;VERIFY AND GET TO CPU DESIRED
POPJ P, ;SOMETHING DIDN'T MAKE IT
SETZM .CPBPF## ;CLEAR CLOCK-LEVEL COUNTER
JRST CPOPJ1## ;SUCCESSFUL RETURN
PMRBPN::PUSHJ P,CHKPMS ;VERIFY AND GET TO CPU DESIRED
POPJ P, ;SOMETHING DIDN'T MAKE IT
SETZM .CPBPF## ;AVOID CLOCK-LEVEL RACE
TRNN T4,1B35 ;USER WANT TO "CLEAR" THE COUNTER(S)?
JRST PMBPN2 ;NO, ACCUMULATE SYSTEM TOTALS
SETZM .CPBPV## ;YES, CLEAR FIRST WORD OF BPA BLOCK
MOVE T1,[.CPBPV##,,.CPBPV##+1] ;BLT POINTER TO
BLT T1,.CPBPV##+<BPATLN##*4>-1 ;CLEAR OUT ALL OF THE BPA BLOCK
PMBPN2: PUSHJ P,PFGWD1 ;GET SAMPLING INTERVAL
CAIG T1,0 ;USEFUL NUMBER SUPPLIED?
MOVE T1,.CPBPC## ;NO, USE LAST SPECIFIED FOR THIS CPU
CAIG T1,0 ;USEFUL NUMBER YET?
MOVEI T1,3 ;NO, SET INTERVAL TO 3 TICKS
MOVEM T1,.CPBPC## ;TELL BPAUPD HOW LONG TO SAMPLE EACH ITEM
SETZM .CPBPI## ;TELL BPAUPD TO RE-INITIALIZE ITSELF
SETOM .CPBPF## ;TELL CLOCK-LEVEL TO START UP BPAUPD
JRST CPOPJ1## ;RETURN SUCCESSFULLY
> ;END OF IFN FTRSP
;ROUTINE TO CHECK INITAL CPU/METER SPECIFICATION
; CALL WITH M SETUP TO POINT TO ADDRESS BEFORE CPU TYPE WORD.
; SMASHES T1-T3, RETURNS T4 WITH EVENT MODE BIT EITHER SET OR CLEAR
; DEPENDING ON THE MODE ARGUMENT THE CALLER SUPPLIES.
; THIS ROUTINE ALSO BORROWS BIT 35 TO INDICATE WHETHER OR NOT THE
; PERFORMANCE METER COUNT SHOULD BE CLEARED OR NOT. THIS BIT
; SHOULD BE CLEARED IMMEDIATELY AFTER CHECKING, SINCE IT MIGHT
; BE USED BY THE HARDWARE
;
;AN ERROR RETURN IS GIVEN FROM THIS ROUTINE IF THE CPU SPECIFICATION
; IS INCORRECT OR A CPU NUMBER CORRESPONDING TO A NON-EXISTANT CPU IS GIVEN.
; THE CALLER MUST ACTUALLY GET CONTROL OF THE METER.
CHKPMS: PUSHJ P,PFGWD1 ;GET CPU TYPES ACCEPTABLE
MOVE T3,T1 ;SAVE IN T3
PUSHJ P,PFGWD1 ;GET CPU NUMBER,,MODE
TLNN T3,(1B3) ;CPU TYPE MUST BE KL10 FOR THIS FUNCTION
JRST PREICT## ;**IMPROPER CPU TYPE**
SETZ T4, ;START WITH ZERO FOR PERFORMANCE ENABLE WORD
TRNN T1,1B18 ;SKIP IF NOT EVENT MODE
MOVEI T4,PE.EVM ;IS EVENT MODE, SET THE BIT
TRNE T1,1B19 ;CLEAR METER COUNT?
TRO T4,1B35 ;YES, BORROW A BIT TO TELL ABOUT IT
HLRZS T1
CAILE T1,M.CPU##-1
JRST PRENXC##
IFN FTMP,<
PUSHJ P,ONCPUS##
JRST PRENXC##
>
PJRST CPOPJ1## ;AND GIVE SKIP RETURN
;THIS ROUTINE IS USED IN THE START, READ, STOP, AND RELEASE ROUTINES.
; IT CHECKS THE CPU NUMBER FOR LEGALITY, AND GIVES ERROR RETURN IF
; CPU NUMBER IS BAD. IT ALSO GIVES AN ERROR RETURN IF
; THE CALLER (WHOSE JOB IS IN AC J) DOES NOT OWN THE METER.
; THIS ROUTINE DISTINGUISHES BETWEEN THE CASES OF METER IN USE
; AND METER NOT SETUP WHEN IT DISCOVERS THAT THE CALLER DOES NOT
; OWN THE METER. M SHOULD BE SETUP TO POINT TO THE ITEM COUNT
; OF THE ARG BLOCK. AC'S T3-T4 ARE PRESERVED. P4 IS SETUP TO BE
; THE CPU DATA BLOCK OF THE SPECIFIED CPU.
PRFCPU: PUSHJ P,PFGWD1 ;GET CPU NUMBER
MOVEI T2,M.CPU##
CAIGE T2,1(T1)
JRST PRENXC##
IFN FTMP,<
PUSHJ P,ONCPUS##
JRST PRENXC##
>
CAMN J,.CPPJB##
JRST CPOPJ1## ;YES, RETURN
SKIPE .CPPJB## ;IS METER OWNED BY SOMEONE ELSE??
JRST PREMIU## ;**METER IN USE**
JRST PREMNS## ;**METER NOT SETUP**
;SPECIAL ROUTINES TO PICK UP ARGUMENTS FOR PERFORMANCE METER FUNCTIONS.
; IF THE COUNT GIVEN BY THE CALLER (IN P2) IS EXHAUSTED, THE PUTTER
; ROUTINE DOES NOTHING AND THE GETTER ROUTINE RETURNS A ZERO
; (DON'T CARE). THIS SAVES SOME CHECKING ELSEWHERE.
PFPWD1: SOJL P2,CPOPJ## ;IF COUNT IS GONE, DO NOTHING
PJRST PUTWD1## ;ELSE DO PUTWD1
PFGWD1: SETZ T1, ;CLEAR T1 IN CASE COUNT IS GONE
SOJL P2,CPOPJ## ;RETURN ZERO IF COUNT EXHAUSTED
PJRST GETWD1## ;ELSE DO GETWD1
;ROUTINE TO READ IN TIME BASE AND PERFORMANCE METER COUNT AT THE
; SAME TIME, MAKING SURE NO INTERRUPTS INTERFERE.
;
;RETURNS TIME BASE HI AND LO IN T1,T2 AND PERF COUNT IN T3,T4
;
;MUST BE ON CPU OF TARGET METER - CALLER'S RESPONSIBILITY
;
;PRESERVES P AC'S, T1-T4 ARE DESTROYED
REDPMT::CONSO PI,PI.IPA ;PI OFF ALREADY?
JRST REDPM2 ;YES, DON'T TURN IT ON AGAIN
PUSHJ P,REDPM1 ;NO, TURN IT ON AFTER WERE THROUGH
PJRST ONPOPJ##
REDPM1: SYSPIF ;TURN OFF PI
REDPM2: RDTIME T1 ;HI AND LO INTO T1,T2
RDPERF T3 ;HI AND LO PERF INTO T3,T4
POPJ P, ;RETURN
;ROUTINE TO START PERFORMANCE METER USED BY PERF. UUO
; SETS UP JOB CONDITION FOR CLOCK1 AND THEN USES SCDPR1
; TO START THE METER IF THE JOB ENABLE CONDITION IS SATISFIED.
; PRESERVES ALL AC'S EXECPT T1. MUST BE CALLED ON CPU OF DESIRED METER,
; PRESERVES STATE OF PI SYSTEM (ON,OFF)
STRPMJ::PUSH P,.CPMJB## ;PUT METER ENABLE INTO
POP P,.CPMJ1## ;PROPER WORD
SETOM .CPPMR## ;SAY THAT METER IS RUNNING
PJRST SCDPR1 ;START METER IF WE'RE SUPPOSED TO AND RETURN
;ROUTINE TO START PERFORMANCE METER USED BY CLOCK1, CALLED BY STRPMJ.
; THIS ROUTINE ACTUALLY STARTS THE PERFORMANCE METER ACCORDING TO
; THE CONDITIONS IN .CPPAE. PRESERVES ALL AC'S, STATE OF PI SYSTEM.
; CALL WITH P4 = CPU DATA BLOCK, MUST BE ON CPU OF TARGET METER.
STRPMR::WRPAE .CPPAE## ;THIS IS ALL THAT'S NECESSARY
POPJ P, ;THERE, THAT WAS EASY
;ROUTINE TO STOP METER USED BY PERF UUO.
; STOPS METER AND CLEARS JOB ENABLE FLAG FOR CLOCK1 SO IT DOESN'T
; TURN THE METER ON. USES ACS T1,T2. PRESERVES STATE OF PI SYSTEM.
; CALL ON CPU OF TARGET METER WITH P4 = CPU DATA BLOCK
STPPMJ::PUSHJ P,CHKPMJ ;WERE WE PART OF THE JOB ENABLE CONDITION?
JRST STPPJ1 ;NO, DON'T UPDATE MBOX REFERENCE COUNT
PUSHJ P,GETMBT ;GET MBOX REFERENCES IN T1,T2
DADD T1,.CPMM0## ;UPDATE COUNT
DMOVEM T1,.CPMM0##
STPPJ1: SETZM .CPMJ1## ;CLEAR JOB ENABLE THAT CLOCK1 LOOKS AT
SETZM .CPPMR## ;AND SAY THAT METER IS NOW STOPPED
; PJRST STPPMR ;STOP METER AND RETURN
;ROUTINE TO STOP PERF METER. DOESN'T TOUCH JOB ENABLE, SO CLOCK1
; CAN CALL IT TO START AND STOP METER FOR JOB ENABLE LOGIC.
; PRESERVES ALL AC'S, STATE OF PI SYSTEM. CALL ON CPU OF TARGET METER
; WITH P4 SETUP ACCORDINGLY.
STPPMR::WRPAE [0] ;ZERO STOPS THE METER
POPJ P, ;ANOTHER COMPLICATED ROUTINE
;ROUTINE TO GET THE PERFORMANCE METER USED BY PERF. UUO
; CALL WITH JOB NUMBER OF CALLER IN J, ADDRESS OF CPU DATA
; BLOCK OF CPU OF TARGET METER IN P4. MUST BE ON THE
; CPU OF TARGET METER. NON-SKIP RETURN IF METER IS ALREADY IN
; USE, SKIP RETURN IF ALREADY OWN METER OR METER WAS FREE.
GETPMR: CAMN J,.CPPJB## ;ALREADY OWN IT?
JRST CPOPJ1## ;YES, GOOD RETURN
AOSE .CPPRQ## ;AVAILABLE?
POPJ P, ;NO, NOT NOW.
MOVEM J,.CPPJB## ;YES, PUT OUR NAME ON THE METER
; NOTE THIS WILL ALSO TURN OFF ANY
; BACKGROUND PERF ANALYSIS PENDING
JRST CPOPJ1## ;GOOD RETURN
;ROUTINE TO RELEASE PERFORMANCE METER USED BY PERF. UUO AND
; EMERGENCY ROUTINES (RESET, SWAP READ ERROR, ETC.)
; CALL WITH P4 = CPU DATA BLOCK OF TARGET PERF METER. NEED NOT
; BE RUNNING ON TARGET CPU (SO SWAPPER CAN CALL, RESET, ETC.)
; CLEARS ALL METER VARIABLES FOR SPECIFIED CPU.
; ALL AC'S PRESERVED.
RELPMR: SETZM .CPAPS##-.CPCDB##(T1) ;CLEAR PERF/ACC METER SYNC FLAG
SETZM .CPMJB##-.CPCDB##(T1) ;CLEAR MEASURED JOB
SETOM .CPMJ1##-.CPCDB##(T1) ;-1 IS FLAG FOR CLOCK1 TO STOP METER
SETZM .CPPJB##-.CPCDB##(T1) ;CLEAR OWNING JOB
SETZM .CPPAE##-.CPCDB##(T1) ;AND PERFORMANCE ENABLES
SETOM .CPPRQ##-.CPCDB##(T1) ;NOW MAKE METER AVAILABLE
SETZM .CPBPI##-.CPCDB##(T1) ;TELL BACKGROUND UPDPAC TO REINIT
SKIPLE .CPBPC##-.CPCDB##(T1) ;BACKGROUND PERF ANAL ON FOR CPU?
SETOM .CPBPF##-.CPCDB##(T1) ;YES, RESTART AT NEXT CLOCK TICK
POPJ P, ;ONLY RETURN
;(ALWAYS SUCCEEDS!)
;ROUTINE TO CLEAR PERFORMANCE METER COUNT
; USED BY PERF. UUO AT METER SETUP TIME. CALLER SHOULD
; MAKE SURE THAT IT OWNS THE METER INVOLVED.
; CALLER MUST MAKE SURE HE IS RUNNING ON CPU OF TARGET
; METER. CALLER SHOULD ALSO MAKE SURE METER IS STOPPED.
CLRPMR: WRPAE [PE.CLR] ;CLEAR HARDWARE COUNTER
MOVE T1,.CPEPT##
SETZM .EPPAC(T1) ;CLEAR HI PERF COUNT
SETZM .EPPAC+1(T1) ;AND LO
SETZM .CPMM0## ;CLEAR OUT MBOX COUNT ALSO
SETZM .CPMM1## ;HIGH AND LOW ORDERS
POPJ P, ;RETURN
;ROUTINE CALLED AFTER SCHEDULER IN CLOCK1 TO IMPLEMENT JOB ENABLE CONDITION.
; .CPMJ1 CONTAINS THE ENABLE CONDITION. -2 IS NULL JOB, -1 IS A SPECIAL
; CODE MEANING STOP THE METER (USED IF A RESET IS DONE BEFORE METER
; IS RELEASED), 0 MEANS THE JOB ENABLE IS DON'T CARE, AND NON-ZERO
; MEANS LEAVE THE METER RUNNING IF AND ONLY IF THE JOB NUMBER
; IN .CPMJ1 IS ABOUT TO BE RUN. ALL ACS PRESERVED.
SCDPMR::PUSH P,T1 ;SAVE T1
PUSHJ P,SCDPR1 ;CALL THE ROUTINE
JRST TPOPJ## ;RESTORE T1 AND RETURN
SCDPR1: MOVE T1,.CPMJ1## ;GET JOB ENABLE CONDITION
AOJE T1,STPPMJ ;IT WAS A REQUEST TO STOP METER, DO IT.
SKIPN .CPPJB## ;METER OWNED BY ANYONE?
POPJ P, ;NO, LEAVE THE METER ALONE
PUSHJ P,CHKPMJ ;CHECK THE JOB ENABLE CONDITION.
PJRST STPPMR ;NOT SATISFIED, STOP THE CLOCK
PJRST STRPMR ;IS SATISFIED, START UP THE CLOCK, EVEN
;THOUGH IT MAY BE STARTED ALREADY (SO WHAT)
;ROUTINE TO CHECK ON THE JOB ENABLE CONDITION.
; CALL WITH JOB NUMBER TO BE TESTED IN J, CPU DATA BLOCK ADDR IN P4.
; GIVES SKIP RETURN IF THE JOB IN J CAUSES THE CPU ENABLE CONDITION
; FOR THE PERFORMANCE METER TO BE SATISFIED, NON-SKIP IF THE CONDITION
; IS NOT SATISFIED OR SOMEONE IS TRYING TO STOP THE METER (-1 IN .CPMJ1).
;USES T1.
CHKPMJ::SKIPN T1,.CPMJ1## ;GET JOB ENABLE. IS IT ZERO?
JRST CPOPJ1## ;YES, CONDITION IS DON'T CARE, GIVE SKIP RETURN
CAMN J,T1 ;NO, DOES .CPMJ1 CONTAIN JOB NUMBER WHICH
; IS IN J?
JRST CPOPJ1## ;YES, GIVE SKIP RETURN
AOJGE T1,CPOPJ## ;IF T1 = -1, SOMEONE WANTS METER STOPPED.
; CALLER'S RESPONSIBILITY TO STOP IT
; IF T1 WAS .GT. ZERO, CONDITION FOR JOB IS NOT MET, SO
; GIVE NON-SKIP RETURN
PJUMPE J,CPOPJ1## ;JOB ENABLE MUST HAVE BEEN NULL JOB.
; IF J .EQ. 0, ENABLE CONDITION IS SATISFIED.
POPJ P, ;SORRY, CONDITION NOT SATISFIED
;ROUTINE TO GIVE UP THE PERFORMANCE METER ON THE CPU'S THIS JOB OWNS IT ON
GIVPMR::MOVEI T1,.C0CDB## ;START WITH CPU0
GIVPM1: CAMN J,.CPPJB##-.CPCDB##(T1) ;OWN THE PERFORMANCE METER ON THIS CPU?
PUSHJ P,RELPMR ;YES, RELEASE IT
HLRZ T1,.CPCDB##-.CPCDB##(T1) ;NEXT CPU
JUMPN T1,GIVPM1 ;JUMP IF ALL CPU'S HAVEN'T BEEN CHECKED
POPJ P, ;RETURN
>; END IFN FTKL10
SUBTTL SET KL CACHE STRATEGY
;ROUTINE CALLED TO SET KL CACHE STRATEGY AS SPECIFIED TO KLI.
;SETS/CLEARS LG.CSL!LG.CSW IN .CPEBR AS APPROPRIATE, PRINTS A
;WARNING MESSAGE ON THE CTY IF CACHE WAS DISABLED.
IFN FTKL10,<
SETCSH::MOVE T1,.CPSPF## ;GET SECONDARY PROTOCOL FLAG WORD
TRNN T1,DF.CSH ;DID OPERATOR SPECIFY TO ENABLE CACHE?
SKIPA T1,[ANDCAB T2,.CPEBR##] ;NO, GET CLEAR INSTRUCTION
MOVE T1,[IORB T2,.CPEBR##] ;YES, GET SET INSTRUCTION
MOVEI T2,LG.CSL!LG.CSW ;GET THE CACHE STRATEGY BITS
XCT T1 ;SET/CLEAR IN .CPEBR AS APPROPRIATE
TRNE T2,LG.CSL!LG.CSW ;CACHE STRATEGY OFF?
POPJ P, ;NO, NOTHING TO WARN
PUSHJ P,CTYERM## ;SET FOR OUTPUT TO CTY
MOVEI T1,[ASCIZ /
%% Cache is disabled/]
PUSHJ P,CONMES## ;START MESSAGE
MOVEI T1,M.CPU## ;GET NUMBER OF CPUS IN THIS MONITOR
SOJE T1,PCRLF## ;DON'T PRINT CPU NUMBER IF THERE'S ONLY ONE
MOVEI T1,[ASCIZ / on /] ;SEPARATOR
PUSHJ P,CONMES## ;PRINT IT
MOVE T2,.CPLOG## ;GET THE CPU NAME
PUSHJ P,PRNAME## ;PRINT IT
PJRST PCRLF## ;PRINT CR-LF AND RETURN
>; END IFN FTKL10
SUBTTL OINKSR - KL10 MODULE TO SUPPORT G-FLOATING INSTRUCTIONS
Comment @
This module simulates some G-floating conversion instructions which
the KL-10 uCode does not presently handle. At one time, the uCode
did handle these, but we reclaimed the uCode space for other fixes.
The instructions currently handled are:
DGFIX
GFIX
DGFIXR
GFIXR
which are all EXTEND opcodes.
This code is ripped off from the TOPS-20 module APRSRV, and should be kept
in sync; If this code is changed, Please change the tops-20 code also.
@
IFN FTKL10,<
OPDEF CALL [PUSHJ P,0] ;CALL
OPDEF RET [POPJ P,0] ;RETURN
.NODDT CALL,RET
GFLT%O==1B1 ;GFLOAT OVERFLOW FLAG
GFLT%2==1B2 ;GFLOAT TWO AC STORE FLAG
PC%TP1==1B10 ;TRAP 1. USED ONLY BY GFLOAT
OPDEF DGFIX [023000,,0] ;GFLT TO DOUBLE INTEGER
OPDEF GFIX [024000,,0] ;GFLT TO INTEGER
OPDEF DGFIXR [025000,,0] ;GFLT TO DOUBLE INTEGER ROUNDED
OPDEF GFIXR [026000,,0] ;GFLT TO INTEGER ROUNDED
OINKSR:: ;[TOPS10]
GFLT0: ;HERE TO CHECK FOR GFLT'S
MOVE M,.USMUE ;GET GLOBAL ADDRESS
PUSHJ P,GETEWD## ;FETCH THE EXTEND SUB-OPCODE
JRST UADERR## ;ILLEGAL ADDRESS
LDB T3,[POINT 9,T1,8];GET THE EXTENDED OPCODE
CAIL T3,<<DGFIX>_-^D27> ;IS IT A GFLT INSTRUCTION?
CAILE T3,<<GFIXR>_-^D27>
JRST ILLIN1## ;NO, GIVE HIM AN ILL UUO
SUBI T3,<<DGFIX>_-^D27> ;CONVERT TO GFLTD OFFSET
PUSHJ P,GFLTXX ;DISPATCH TO WORKER ROUTINES
TLNE T4,(GFLT%O) ;DID IT OVERFLOW
JRST GFLT1 ;YES...GO HANDLE IT
LDB T3,[POINT 4,.USMUO,30] ;GET THE AC THE USER USED
UMOVEM T1,(T3) ;SAVE THE FIRST AC
TLNN T4,(GFLT%2) ;IS IT A TWO AC RESULT?
JRST USRXIT## ;NO...SO WE ARE DONE
ADDI T3,1 ;YES...SO BUMP THE AC VALUE
ANDI T3,17 ;MAKE ADDITION MODULO 16
UMOVEM T2,(T3) ;SAVE THE SECOND AC RESULT
JRST USRXIT## ;RETURN TO USER
GFLT1:
MOVSI T1,(XC.OVF!PC%TP1) ;CAUSE AN OVERLOW TRAP.
IORM T1,.JDAT+JOBPD1## ;BY CHANGING THE USER FLAGS.
JRST USRXIT## ;AND RETURN
GFLTXX: HLRZ T2,.USMUE ;GET DEFAULT SECTION-OF-REFERENCE
MOVE T4,.USMUE ;GET UUO EFFECTIVE ADDRESS
TDNN T4,[^-1,,^-17] ;IF AN AC
TLNN T4,-1 ;AND NOT FROM S0
JRST GFLTX1 ;NO, IT'S OK
MOVE M,.USMUP ;YES, HAVE TO GET SECTION OF REFERENCE
HRRI M,-1(M) ;BACK OFF TO PC OF EXTEND INSTRUCTION
PUSHJ P,GETMWD## ;FETCH ORIGINAL INSTRUCTION WORD
JRST UADERR## ;HOW CAN THIS HAPPEN?
PUSHJ P,CHKINS## ;GET EA AND SECTION-NESS
JRST UADERR## ;SHOULD NEVER FAIL
CAME T1,.USMUE ;BETTER MATCH
JRST UADERR## ;BLAME USER IF NOT
MOVE M,T1 ;YES, GET FOR FETCH ROUTINE
PUSHJ P,GETXWD## ;RESTORE EXTEND SUB-OPCODE
JRST UADERR## ;SOMETHING BAD HAPPENED
GFLTX1: PUSHJ P,CHKINX## ;DO AN EA-CALC WITH THE SECTION FROM T2
JRST UADERR## ;EA-CALC FAILURE
HRLI T1,(T2) ;MAKE SURE OF GLOBAL ADDRESS
PUSHJ P,SXPCS## ;SETUP FOR ARG FETCHING
JRST UADERR## ;BAD ADDRESS
SKIPL T2 ;IF LOCAL REFERENCE,
HRLI T1,(IFIW) ;SETUP FOR FETCH ROUTINES
MOVE M,T1 ;COPY POINTER
PUSHJ P,GETEWD## ;GET FIRST WORD OF PAIR
JRST UADERR## ;INVALID ADDRESS
MOVE T2,T1 ;SAVE IT
PUSHJ P,GETEW1## ;GET SECOND WORD OF PAIR
JRST UADERR## ;ILLEGAL ADDRESS
EXCH T1,T2 ;SWAP THEM BACK AROUND
SETZ T4, ;CLEAR ALL FLAGS.
PJRST @GFLTD(T3) ;DISPATCH TO WORKER ROUTINE
GFLTD: IFIW .DGFX ;DGFIX
IFIW .GFX ;GFIX
IFIW .DGFXR ;DGFIXR
IFIW .GFXR ;GFIXR
COMMENT @
***********************************
***** N N OOO TTTTT EEEEE *****
***** NN N O O T E *****
***** N N N O O T EEE *****
***** N NN O O T E *****
***** N N OOO T EEEEE *****
***********************************
The following routines are copied verbatim from TOPS20 APRSRV. If either
changes, please update the other.
@
.DGFXR: ;GFLT TO DOUBLE INTEGER ROUNDED
MOVSI T4,(GFLT%2) ;SET THE DOUBLE AC FLAG
CALL DGFXR0 ;GO TO COMMON CODE
JUMPG T3,DGFXR1 ;IF SHIFT POSITIVE THEN SHIFT LEFT
CAMG T3,[-^D70] ;SHIFT INSTS ARE MOD 256 SO REDUCE
MOVNI T3,^D70 ;EXPONENT IF ITS TOO LARGE
ASHC T1,1(T3) ;SHIFT ROUNDING BIT INTO RIGHTMOST OF T2
DADD T1,[EXP 0,1] ;ROUND
ASHC T1,-1 ;SHIFT ROUNDING BIT OUT
RET ;RETURN TO CALLER
DGFXR1: CAILE T3,^D11 ;CHECK EXPONENT SIZE
JRST DGFXR3 ;TOO BIG THEN OVERFLOW
DGFXR2: ASHC T1,(T3) ;SHIFT LEFT NO ROUNDING
RET ;RETURN TO CALLER
DGFXR3: CAIN T3,^D12 ;CHECK FOR LARGEST NEGATIVE INTEGER
JUMPL T1,[CAMN T1,[777740000000]
JUMPE T2,DGFXR2 ;LET THAT ONE THROUGH
JRST .+1] ;OVERFLOW ON ALL OTHERS
DGFXR4: TLO T4,(GFLT%O) ;SET THE OVERFLOW FLAG
RET ;AND RETURN TO CALLER
DGFXR0: ;COMMON CODE FOR DGFIXR AND DFIXR
LDB T3,[POINT 11,T1,11] ;GET THE EXPONENT
TLNE T1,(1B0) ;PROPAGATE SIGN THROUGH EXPONENT BITS
TLOA T1,777700 ;NEGATIVE SET TO ONES
TLZA T1,777700 ;POSITIVE SET TO ZEROES
TRC T3,3777 ;UNCOMPLEMENT EXPONENT IF NEGATIVE
SUBI T3,2000+^D59 ;GET SHIFT VALUE TO ALIGN INTEGER PART
RET ;RETURN TO CALLER
.GFXR: ;GFLOAT TO SINGLE INTEGER ROUNDED
SETZ T4, ;RESET FLAG AC
CALL DGFXR0 ;GO TO COMMON CODE
JUMPG T3,DFXR1 ;IF SHIFT COUNT POSITIVE GO SHIFT LEFT
CAMG T3,[-^D70] ;SHIFT INSTS ARE MOD 256 SO REDUCE
MOVNI T3,^D70 ;NEW EXPONENT IF IT WAS TOO LARGE
ASHC T1,1(T3) ;SHIFT ROUNDING BIT INTO T2
DADD T1,[EXP 0,1] ;ROUND
ASHC T1,-1 ;SHIFT ROUNDING BIT OUT
JRST DFXR3 ;GO CONVERT TO SINGLE INTEGER
DFXR1: CAILE T3,^D11 ;CHECK EXPONENT SIZE
JRST DGFXR4 ;GO DO OVERFLOW STUFF
DFXR2: ASHC T1,(T3) ;SHIFT LEFT NO ROUNDING NEEDED
DFXR3: CAME T1,[-1] ;HIGH WORD MUST BE ALL SIGN BITS
JUMPN T1,DGFXR4 ;IF IT ISNT THEN OVERFLOW
MOVE T1,T2 ;GET WORD INTO CORRECT AC
RET ;RETURN TO CALLER
.GFX: ;GFLOAT TO SINGLE INTEGER
SETZ T4, ;RESET FLAG AC
PUSH P,T1 ;SAVE ORIGINAL SIGN
SKIPGE T1 ;IS NUMBER POSITIVE?
DMOVN T1,T1 ;NO...GET ABSOLUTE VALUE
LDB T3,[POINT 11,T1,11] ;GET THE EXPONENT
TLZ T1,777700 ;CLEAR EXPONENT FROM NUMBE
SUBI T3,2000+^D59 ;GET SHIFT AMOUNT TO ALIGN INTEGER PART
CAMG T3,[-^D70] ;SHIFT INSTS ARE MOD 256 SO REDUCE
MOVNI T3,^D70 ;EXPONENT IF ITS LARGE
CAILE T3,^D11 ;CHECK EXPONENT SIZE
JRST GFX2 ;TOO BIG...OVERFLOW
ASHC T1,(T3) ;SHIFT FRACTION OFF
SKIPGE 0(P) ;CHECK ORIGINAL SIGN
DMOVN T1,T1 ;IF NEGATIVE COMPLEMENT RESULT
TLNE T1,(1B0) ;COPY HIGH SIGN INTO LOW WORD
TLO T2,(1B0)
CAME T1,[-1] ;HIGH WORD MUST BE ALL SIGN BITS
JUMPN T1,GFX2 ;ELSE OVERFLOW
MOVE T1,T2 ;PUT RESULT INTO PROPER AC FOR RETURN
GFX1: ADJSP P,-1 ;FIX STACK
RET ;AND RETURN TO CALLER
GFX2: TLO T4,(GFLT%O) ;HERE ON OVERFLOW...SET THE FLAG
JRST GFX1 ;AND RETURN TO USER
.DGFX: ;GFLOAT TO DOUBLE INTEGER
MOVSI T4,(GFLT%2) ;SET THE TWO ACS FLAG
PUSH P,T1 ;SAVE THE ORIGINAL SIGN
JUMPGE T1,DGFX1 ;IS NUMBER POSITIVE?
DMOVN T1,T1 ;NO...SO GET ABSOLUTE VALUE
CAMN T1,[210740000000] ;CHECK FOR -2^70
JUMPE T2,DGFX5 ;IT IS SPECIAL SO HANDLE IT
DGFX1: LDB T3,[POINT 11,T1,11] ;GET THE EXPONENT
TLZ T1,777700 ;CLEAR THE EXPONENT FIELD
SUBI T3,2000+^D59 ;GET SHIFT AMOUNT TO ALIGN INTEGER PART
CAMG T3,[-^D70] ;SHIFT INSTS ARE MOD 256
MOVNI T3,^D70 ;REDUCE EXPONENT IF IT IS LARGE
CAILE T3,^D11 ;CHECK EXPONENT SIZE
JRST DGFX4 ;TOO BIG SO OVERFLOW
ASHC T1,(T3) ;SHIFT FRACTION OFF
SKIPGE 0(P) ;CHECK ORIGINAL SIGN
DMOVN T1,T1 ;IF NEGATIVE THEN COMPLEMENT
TLNE T1,(1B0) ;COPY HIGH SIGN INTO LOW WORD
TLO T2,(1B0)
DGFX2: ADJSP P,-1 ;FIX UP THE STACK
RET ;AND RETURN TO CALLER
DGFX4: TLO T4,(GFLT%O) ;SET THE OVERFLOW FLAG
JRST DGFX2 ;AND RETURN
DGFX5: MOVSI T1,(1B0) ;-2^70 SPECIAL CASE
MOVE T2,T1
JRST DGFX2 ;AND GO RETURN
>; END IFN FTKL10
SUBTTL EXEC MODE ADDRESS BREAK CONTROL
IFN FTKL10,<
;ADDRESS BREAK CONDITIONS
AB.REP==:1B0 ;REPETITIVE ENABLE
AB.FET==:1B9 ;FETCH
AB.RED==:1B10 ;READ
AB.WRT==:1B11 ;WRITE
AB.USR==:1B12 ;USER ADDRESS
AB.ADR==:37,,777777 ;ADDRESS MASK
ABKCHK::SKIPN .CPABW## ;WANT TO SET ADDRESS BREAK ON THIS CPU?
POPJ P, ;NO
SKIPLE .CPABF## ;NEED TO INIT ADDRESS BREAK?
PUSHJ P,ABKINI ;YES--DO IT NOW
PUSH P,T1 ;SAVE ALL ACS
HLRZ T1,.CPABF## ;GET STOPCODE TYPE
DPB T1,[.CPABS##+S$PTRT] ;UPDATE INCASE PATCH CHANGED IT
MOVE T1,.CPABW## ;GET ADDRESS BREAK WORD
TLZ T1,(AB.REP) ;CLEAR FAKE BIT
DATAO APR,T1 ;ENABLE EXEC MODE ADDRESS BREAK
JRST TPOPJ## ;RESTORE & RETURN
STOPCD .,EVENT,ABK,ABKDIE ;++ ADDRESS BREAK
ABKDIE: MOVEI T1,[ASCIZ /Exec mode address break at PC /]
PUSHJ P,CONMES## ;PRINT TEXT
DMOVE T1,.USPFP ;GET PC DOUBLE-WORD
PUSHJ P,UDPCP## ;PRINT PC
MOVEI T1,[ASCIZ /, Conditions = /]
PUSHJ P,CONMES## ;PRINT TEXT
LDB T1,[POINT 3,.CPABW##,11] ;GET CONDITIONS
MOVE T1,ABKTBL-1(T1) ;AND ASSOCIATED TEXT
PJRST CONMES## ;PRINT TEXT AND RETURN
ABKTBL: [ASCIZ /Write/]
[ASCIZ /Read/]
[ASCIZ /Read + Write/]
[ASCIZ /Fetch/]
[ASCIZ /Fetch + Write/]
[ASCIZ /Fetch + Read/]
[ASCIZ /Fetch + Read + Write/]
;INITIAL ADDRESS BREAK ON OTHER CPUS
ABKINI:
IFN FTMP,<
SYSPIF ;INTERLOCK AGAINST RACES
SKIPG .CPABF## ;NEED TO SETUP OTHER CPUS?
JRST ONPOPJ## ;NO--RELEASE INTERLOCK AND RETURN
> ;END IFN FTMP
PUSHJ P,SAVT## ;SAVE SOME ACS
HLRZ T1,.CPABF## ;GET STOPCODE TYPE
CAIE T1,S$HALT ;NEVER GENERATE HALT STOPCODES
CAILE T1,S$MAXT ;RANGE CHECK
MOVEI T1,S$EVENT ;DEFAULT IT
HRLM T1,.CPABF## ;UPDATE
SKIPN T1,.CPABI## ;GET INSTRUCTION TO XCT
MOVSI T1,(CAIA) ;THE FOOL FORGOT TO GIVE ONE
MOVEM T1,.CPABI## ;UPDATE
HRLZ T1,S..ABK ;GET STOPCODE BLOCK ADDRESS
HRRI T1,.CPABS## ;WHERE TO PUT IT
BLT T1,.CPABS##+S$MAXL-1 ;COPY STOPCODE BLOCK
HLRZ T1,.CPABF## ;GET STOPCODE TYPE
DPB T1,[.CPABS##+S$PTRT] ;SET IT
MOVSI T1,(AB.USR) ;USER ADDRESS BIT
ANDCAM T1,.CPABW## ;NEVER TURN THIS ONE ON
MOVSI T1,400000 ;GET A BIT
IORM T1,.CPABF## ;INDICATE STUFF ALL CHECKED OUT
IFN FTMP,<
MOVE T2,.CPCPN## ;GET OUR CPU NUMBER
IMULI T2,.CPLEN## ;LENGTH OF A CDB (MAKE OFFSET)
HRROI T1,ABKSCP ;SUBROUTINE TO DO THE DIRTY WORK
PUSHJ P,CPUAPP## ;SET UP OTHER CPUS
SYSPIN ;RELEASE INTERLOCK
> ;END IFN FTMP
POPJ P, ;RETURN
;CLEAR ADDRESS BREAK ON OTHER CPUS
ABKCLM: SKIPA T2,.CPBIT## ;GET OUR CPU BIT
ABKCLR: MOVEI T2,-1 ;ALL CPU MASK
SYSPIF ;INTERLOCK AGAINST RACES
HRRM T2,.CPABF## ;STUFF MASK IN FLAG WORD
MOVEI T1,ABKCCP ;SUBROUTINE TO DO THE DIRTY WORK
PUSHJ P,CPUAPP## ;SET UP OTHER CPUS
SYSPIN ;RELEASE INTERLOCK
POPJ P, ;RETURN
ABKCCP: TDNN T2,.CPBIT##-.CPCDB##(P1) ;WANT TO CLEAR ON THIS CPU?
POPJ P, ;NO
SETZM .CPABF##-.CPCDB##(P1) ;ZAP FLAGS
SETZM .CPABW##-.CPCDB##(P1) ;AND BREAK WORD
SETZM .CPABI##-.CPCDB##(P1) ;AND INSTRUCTION TO XCT
POPJ P, ;RETURN
IFN FTMP,<
ABKSCP: MOVE T3,.C0ABF##(T2) ;GET CPU MASK
TDNN T3,.CPBIT##-.CPCDB##(P1) ;WANT TO SET ON THIS CPU?
POPJ P, ;NO
MOVEM T3,.CPABF##-.CPCDB##(P1) ;SAVE FLAGS
MOVSI T3,.C0ABS##(T2) ;STOPCODE CODE
HRRI T3,.CPABS##-.CPCDB##(P1) ;DESTINATION
BLT T3,.CPABS##-.CPCDB##+S$MAXL-1(P1) ;COPY
MOVE T3,.C0ABI##(T2) ;GET BREAKPOINT INSTRUCTION
MOVEM T3,.CPABI##-.CPCDB##(P1) ;SET MINE
MOVE T3,.C0ABW##(T2) ;GET ADDRESS BREAK WORD
MOVEM T3,.CPABW##-.CPCDB##(P1) ;SET WORD FOR CPUN
POPJ P, ;RETURN
> ;END IFN FTMP
> ;END IFN FTKL10
SUBTTL THE END
APRLIT: $LIT
APREND: END