Trailing-Edge
-
PDP-10 Archives
-
AP-D543V_SB
-
kiser.mac
There are 6 other files named kiser.mac in the archive. Click here to see a list.
TITLE KISER - KI10 PROCESSOR DEPENDENT CODE -V5254
SUBTTL J.M. FLEMMING/JMF/DAL TS 17 OCT 78
SEARCH F,S
$RELOC
$HIGH
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1973,1974,1975,1976,1977,1978 BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
XP VKISER,5254
; PUT VERSION NUMBER IN GLOB LISTING AND LOADER STORAGE MAP
ENTRY KISER ;LOAD KISER IF LIBRARY SEARCH
KISER:
SUBTTL CLOCK1 - INTERFACE TO JOB STARTUP, STOP, AND CONTEXT SWITCHING ROUTINES
;HERE AT CLK INTERRUPT LEVEL
;THIS CODE IS DUPLICATED IN CP1SER FOR CPU1
CK0INT::SKIPN .C0CKF## ;CLK INTERRUPT REQUEST?
JRST CK0INT ;NO, CHECK OTHER DEVICES
CONO PI,II.CCI## ;CLEAR SOFTWARE INITIATED CLOCK INTERRUPT FLAG
MOVEM 17,.C0S17## ;SAVE AC 17
MOVE 17,CK0CHL## ;IS CURRENT JOB IN USER MODE?
TLNE 17,(XC.USR)
JRST CK0IN1 ;YES, DON'T NEED TO SAVE THE ACS
MOVE 17,.C0S17## ;IN EXEC MODE, ASSUME NOT FORCED RESCHEDULE
SKIPN .C0SCF## ;SKIP IF THE FORCED RESCHEDULING FLAG IS ON
JEN @CK0CHL## ;INTERRUPTED OUT OF A UUO, LEAVE CLOCK FLAG
; SET AND DISMISS
SKIPN 17,.C0ADR## ;CURRENT JOB DATA AREA, IS THERE ONE?
MOVE 17,.C0NJD## ;NO, MUST BE KJOB OR CORE 0, RUNS AT UUO
; LEVEL AND REQUESTS A CLOCK INTERRUPT TO STOP
MOVEM 16,JOBD16##(17) ;SAVE AC 16 IN DUMP AREA OF JOB DATA AREA
MOVEI 16,JOBDAC##(17) ;SOURCE = 0, DESTINATION = DUMP AC 0
BLT 16,JOBD15##(17) ;SAVE ACS 0-15 IN DUMP AC AREA
MOVE T1,.C0S17## ;NOW SAVE 17 IN THE JOB DATA AREA
MOVEM T1,JOBD17##(17) ;ALONG WITH THE OTHER DUMP ACS
MOVE 17,CK0CHL## ;RESTORE INTERRUPT PC
CK0IN1: MOVEM 17,.C0PC## ;SAVE PC IN PROTECTED PART OF SYSTEM DATA
; STORAGE FOR CURRENT JOB
CK0SPD::MOVE P,.C0NPD## ;SETUP PUSH DOWN LIST IN NULL JOB DATA AREA
;TURN ON USER IOT SO XCTP WORKS RIGHT
CK0IN2: JRSTF @[IC.UOU+CHKAPE##] ;CHECK FOR APR ERRORS, CALL THE COMMAND
; DECODER, AND RESCHEDULE
CIP8B:: MOVE T1,.C0PC## ;GET THE PC FOR THE CURRENT JOB
TLNE T1,(XC.USR) ;IS IT IN USER MODE?
JEN @.C0PC## ;YES, ACS ARE ALREADY SETUP
MOVSI 17,JOBDAC##(R) ;NO, RESTORE EXEC MODE ACS
BLT 17,17 ; FROM THE DUMP AC AREA
JEN @.C0PC## ;RETURN TO THE INTERRUPTED EXEC MODE PROGRAM
;ROUTINE TO SAVE THE USER'S ACS IN AC BLOCK 1 IN THE SHADOW AC
; AREA IN THE JOB DATA AREA ON A CONTEXT SWITCH
;CALLING SEQUENCE:
; SETUP THE USER BASE REGISTER TO POINT TO THE CURRENT JOB'S UPMP
; PUSHJ P,SAVUAC
; ALWAYS RETURN HERE
SAVUAC::PUSH P,J ;SAVE CURRENT JOB NUMBER
MOVE J,U ;J 2 JOB NUMBER OF THE LAST JOB RUN
PUSHJ P,SETUPR ;SETUP R TO POINT TO SHADOW AREA
JRST JPOPJ## ;NO CORE IN CORE
MOVEI T1,(R) ;SOURCE = USER AC 0,
; DESTINATION = AC 0 IN SHADOW AREA
EXCTUX <BLT T1,17(R)>
;SAVE USER ACS 0-17
JRST JPOPJ## ;RETURN
;ROUTINE TO RESTORE THE USER'S ACS TO AC BLOCK 1 FROM THE SHADOW AC
; AREA IN THE JOB DATA AREA ON A CONTEXT SWITCH
;CALLING SEQUENCE:
; SETUP THE USER BASE REGISTER TO POINT TO CURRENT JOB'S UPMP
; PUSHJ P,RESUAC
; ALWAYS RETURN HERE
RESUAC::PUSHJ P,SETUPR ;SETUP R TO POINT TO SHADOW AREA
POPJ P, ;NO CORE IN CORE
MOVSI T1,(R) ;SOURCE = AC 0 IN THE SHADOW AREA,
; DESTINATION = USER AC 0
EXCTXU <BLT T1,17> ;RESTORE USER ACS 0-17
POPJ P, ;RETURN
;SUBROUTINE TO SETUP R TO POINT TO SHADOW AC AREA FOR THE CURRENT JOB
;CALLING SEQUENCE:
; MOVE J,JOB NUMBER OF CURRENT JOB
; PUSHJ P,SETUPR
; RETURN HERE IF NOT THE NULL JOB BUT HAS NO CORE (CORE 0,KJOB)
; RETURN HERE - R POINTS TO THE CURRENT JOBS SHADOW ACS
SETUPR: MOVEI T1,JS.ASA ;DON'T SAVE ACS IF THE SHADOW AREA ISN'T FREE
TDNE T1,JBTSTS##(J) ;IS IT?
POPJ P, ;NO
SETRUP: SKIPN R,JBTADR##(J) ;SETUP R - DOES THE JOB HAVE CORE IN CORE?
JUMPN J,CPOPJ## ;NO, IF J IS NON-ZERO (I.E., NOT THE NULL
; JOB) GIVE NON-SKIP RETURN (JOB HAS NO ACS)
JUMPN R,CPOPJ1## ;IS IT THE NULL JOB?
MOVE R,.CPNJD##(P4) ;YES, RETURN ADDRESS OF NULL JOBS SHADOW AREA
ADDI R,JOBDAC## ; ..
JRST CPOPJ1## ;GIVE SKIP (THERE IS A PLACE TO STORE ACS) RETURN
;ROUTINE TO ENABLE/DISABLE APR FOR TRAPPING TO USER AND EXEC
;CALL: MOVEI T1, APR CONSO FLAGS FOR USER TRAPPING
; PUSHJ P,SETAPR
; RETURN WITH APR RESET AND INTERRUPT LOCATION CONSO'S SET
SETAPR::PUSH P,P4 ;SAVE P4
MOVEI P4,.C0CDB## ;SET UP CDB INDEX FOR CPU0
SETAP1::PUSHJ P,SETRP ;SETUP THE TRAP LOCATIONS (PAGE FAULT,
; ARITHMETIC, PDL OVF)
SETAP2: PUSHJ P,SETCNA ;SET USER ENABLES FOR NXM AND CLOCK AND
; SET THE APR PIA
POP P,P4 ;RESTORE P4
POPJ P, ;EXIT
;ROUTINE TO SETUP USER TRAP LOCATIONS AS SPECIFIED BY USER ENABLE BITS
; PAGE FAULT (ILL. MEM. REF.), ARITHMETIC (INTEGER OVERFLOW, FLOATING
; POINT OVERFLOW OR UNDERFLOW, AND DIVIDE CHECK), PUSH DOWN LIST OVERFLOW
; TRAP 3 IS ALWAYS IGNORED IN USER MODE.
;CALLING SEQUENCE:
; MOVE T1,USER ENABLE BITS
; PUSHJ P,SETRP
; ALWAYS RETURN HERE
;T1 IS PRESERVED.
SETRP: TRNE T1,AP.AOV+AP.FOV;IS HE?
TDZA T2,T2 ;YES, SET TO FIELD TRAPS
MOVSI T2,(JFCL) ;IGNORE ARITHMETIC TRAPS IF USER NOT ENABLED
IFN FTPI,<
HRRI T2,SAROVF ;SET DISPATCH ADDRESS
MOVEM T2,.UPMP+.UPAOT ;STORE IN UPT
>
IFE FTPI,<
HLLM T2,.UPMP+.UPAOT ;FIELD OR IGNORE USER AOF TRAPS
>
MOVEI T2,SEPDLO ;IF USER NOT ENABLED FOR POV HANDLE LIKE EXEC POV
TRNE T1,AP.POV ;IS HE ENABLED?
MOVEI T2,SUPDLO ;YES, HANDLE DIFFERENTLY
HRRM T2,.UPMP+.UPPDT ;YES, SET FOR SEPDLO OR SUPDLO TO HANDLE PDL OV
MOVEI T2,SEILM ;SAME PROCEDURE FOR ILM
TRNE T1,AP.ILM ;IS USER ENABLED FOR ILM?
MOVEI T2,SUILM ;YES, GIVE USER CONTROL ON ILM REFERENCE
HRRM T2,.UPMP+.UPPFT ;PAGE FAULT TRAP LOCATION IS SEILM OR SUILM
IFE FTPI,<
POPJ P, ;RETURN
>
IFN FTPI,<
PJRST APPSI## ;SETUP TRAP LOCATIONS FOR ANY INTERRUPTS THE
; USER IS ENABLED FOR
>
;SUBROUTINE TO SETUP USER'S APR CONSO MASK AND THE APR PIA
;CALLING SEQUENCE:
; MOVE T1,USER'S APR ENABLE BITS
; PUSHJ P,SETCNA
; ALWAYS RETURN HERE
SETCNA::HRL T1,T1 ;COPY ENABLE BITS TO LEFT HALF
TLZ T1,-1-XP.CLK-UE.PEF ;CLEAR ALL BITS EXCEPT CLOCK FLAG
; AND USER ENABLED MEM PARITY
TRNE T1,AP.NXM ;DOES USER WANT NXM ENABLED?
TLO T1,IP.NXM ;YES, ENABLE THAT FOR HIM
HRRI T1,IP.TTO+IP.PAR+IP.PWF+XP.CLK+IP.ABK+IP.NXM+IP.IOF
;SET MONITOR ENABLE BITS
MOVEI T2,IP.ECI ;ENABLE CLOCK INTERRUPT
ADDI T2,@.CPAPI##(P4) ;ADD IN APR PIA
CONO PI,PIOFF## ;DISALLOW INTERRUPTS WHILE CHANGING APR BITS
HLRM T1,.CPCN1##(P4) ;USER'S ENABLE BITS
HRRM T1,.CPCON##(P4) ;MONITOR'S ENABLE BITS
CONO APR,(T2) ;SET CLOCK ENABLE AND APR PIA
CONO PI,PION## ;RESTORE PI
POPJ P, ;RETURN
;ROUTINE TO CAUSE CLK ROUTINE TO RESCHEDULE
;CALLED AT ANY LEVEL
;CALL: PUSHJ P,STOP2
; RETURN IMMEDIATELY EXCEPT IF AT UUO LEVEL
; IF AT UUO LEVEL, RETURN WHEN JOB IS RUNABLE AGAIN
STOP2:: CONO PI,PIOFF## ;PREVENT CLOCK INTERRUPT DURING STOP2 CODE
SETOM .C0CKF## ;SET FLAG TO INDICATE CLK INTERRUPT
; EVEN THOUGH CLK INTERRUPT IS NOT A TIME INTERRUPT
CONO PI,PICLK## ;TURN PI BACK ON AND REQUEST INTERRUPT TO
; CLK PI CHANNEL(LOWEST PRIORITY CHANNEL)
CONSZ PI,II.IPA ;AT INTERRUPT LEVEL?
POPJ P, ;YES, RETURN IMMEDIATELY
PUSH P,T1 ;NO, AT UUO LEVEL
STOP3: CONI PI,T1 ; MAKE SURE CLOCK LEVEL PROCESSING
TLNE T1,CLKBIT## ; HAPPENS BEFORE DOING ANYTHING ELSE
JRST STOP3 ; SINCE MAY NOT HAVE ANY CORE
JRST TPOPJ## ;RETURN
TSTREL::MOVEI T1,JS.ASA ;WHAT DOES REFERENCE TO USER 0-17 REALLY MEAN BIT
TRNN M,777760 ;IS THIS REFERENCE TO USER 0-17?
TDNN T1,JBTSTS##(J) ;YES, IS IT TO USER'S ACS OR THE SHADOW ACS?
AOS (P) ;USER'S ACS
POPJ P, ;GIVE SHADOW ACS OR USER AC SET RETURN
SAROVF::MOVEI P4,.C0CDB## ;ASSUME CPU0
IFN FTMS,<
SKPCPU (0) ;IS THIS CPU0?
MOVEI P4,.C1CDB## ;NO, POINT P4 AT CPU1'S CDB
>
EXCH R,.CPADR##(P4) ;GET ADDRESS OF USER'S JOB DATA AREA
MOVEM T1,.UPMP+.UPMUO ;SAVE A TEMPORARY
HLLZ T1,.UPMP+.UPMUP ;GET PC ERROR FLAGS
HRR T1,JOBENB##(R) ;GET USER'S ENABLE BITS
TLZ T1,3637 ;CLEAR NON-EXISTANT KA10 BITS FOR COMPATABLITY
TRNN T1,AP.AOV ;OVERFLOW - IS THE USER ENABLED?
TLNE T1,(XC.FOV) ;TRAP CAUSED BY FOV?
JRST SAROV2 ;YES, GO TRAP TO HIM
SAROV1: MOVE T1,.UPMP+.UPMUP ;USER IS NOT ENABLED FOR THIS EXCEPTION - RESTORE THE
JRST SAROV6 ; TRAP PC AND DISMISS TO THE INTERRUPTED PROGRAM
SAROV2: HRRI T1,AP.AOV+AP.FOV;ASSUME FLOATING OVERFLOW
TLNN T1,(XC.FOV) ;WAS IT A FLOATING OVERFLOW TRAP?
TRZ T1,AP.FOV ;NO, INTEGER OVERFLOW
HRRZM T1,JOBCNI##(R) ;SIMULATE KA10 CONI APR,JOBCNI(R)
HRR T1,.UPMP+.UPMUP ;RESTORE TRAP PC
MOVEM T1,JOBTPC##(R) ;STORE IT FOR TRAP HANDLING ROUTINE
JRST SAROV4 ;FINISH UP
SAROV3: HRRZM T1,JOBCNI##(R) ;LIKE CONI ON THE KA-10
SAROV4: HRR T1,JOBENB##(R) ;GET USER'S ENABLE BITS
TRNE T1,XP.DDU ;USER WANT TRAPS REENABLED?
JRST SAROV5 ;YES, LEAVE AS IS
HLLZS JOBENB##(R) ;CLEAR USER'S ENABLE BITS SO MUST DO APRENB AGAIN
HRRI T1,SEILM ;NO
HRRM T1,.UPMP+.UPPFT ;EXEC WILL FIELD ILM
HRRI T1,(JFCL)
HRLM T1,.UPMP+.UPAOT ;IGNORE ARITHMETIC TRAPS
HRRI T1,SEPDLO
HRRM T1,.UPMP+.UPPDT ;EXEC WILL FIELD PDL OVERFLOWS
SETZM .CPCN1##(P4) ;CLEAR POSSIBLE NXM OR CLOCK ENABLES
SAROV5: HRR T1,.CPCN1##(P4) ;CLEAR CLOCK ENABLE SO THAT WON'T INTERRUPT HIM
TRZ T1,XP.CLK
HRRZM T1,.CPCN1##(P4) ;NEW USER ENABLE BITS
HRR T1,JOBAPR##(R) ;GET USER'S TRAP ADDRESS
SAROV6: TLZ T1,(XC.OVF+XC.FOV+XC.FUF+XC.NDV)
TLO T1,(XC.PUB) ;INSURE PUBLIC IS SET
EXCH T1,.UPMP+.UPMUO ;NEW PC WITH TRAP CAUSING BITS CLEARED
EXCH R,.CPADR##(P4) ;RESTORE R
JEN @.UPMP+.UPMUO ;EXIT TO THE USER'S TRAP HANDLER
SEPDLO::MOVEM P4,.UPMP+.UPMUO ;SAVE P4
MOVEI P4,.C0CDB## ;ASSUME CPU0
IFN FTMS,<
SKPCPU (0) ;ON CPU1?
MOVEI P4,.C1CDB## ;YES, POINT P4 AT CPU1'S CDB
>
EXCH T1,.UPMP+.UPMUP ;GET THE PC
MOVEM T1,.CPAPC##(P4) ;SET AS ERROR PC FOR ERRCON
HRRI T1,AP.POV ;SET PUSH DOWN OVERFLOW FLAG
SEPDL1: TLNN T1,(XC.USR) ;WAS THE PDL OVF IN USER MODE?
JRST SEPDL2 ;NO
HRRZM T1,.JDAT+JOBCNI## ;STORE THE PDL OVF BIT
MOVE T1,.CPAPC##(P4) ;GET THE USER'S PC
MOVEM T1,.JDAT+JOBTPC## ;STORE IT FOR LATER REPORTING
MOVEI T1,JS.APE ;APR ERROR IN JOB BIT
EXCH J,.CPJOB##(P4) ;GET THE CURRENT JOB'S JOB NUMBER
IORM T1,JBTSTS##(J) ;LIGHT APR ERROR BIT
IFN FTMS,<
MOVE P,[MJOBPD##,,.JDAT+JOBPDL##] ;SETUP A PUSH DOWN LIST
PUSHJ P,CP1APE## ;MAKE SURE THE JOB IS RUNNABLE ON CPU0
; SO IT WILL GET STOPPED AND ERROR WILL BE REPORTED
>
EXCH J,.CPJOB##(P4) ;RESTORE J
JRST SEPDL3 ;AND PROCEDE
SEPDL2: HRRM T1,.CPAEF##(P4) ;IN .CPAEF SO ERRCON WILL GET CALLED
SEPDL3: MOVE T1,.UPMP+.UPMUP ;RESTORE T1
CONO PI,PIOFF ;NO INTERRUPTS UNTIL P4 IS RESTORED
SETOM .CPSCF##(P4) ;SET FORCED RESCHEDULING FLAG
SETOM .CPCKF##(P4) ;AND CLOCK FLAG
MOVE P4,.UPMP+.UPMUO ;RESTORE P4
CONO PI,PICLK## ;REQUEST A CLOCK INTERRUPT AND TURN THE PI SYSTEM ON
CONSZ PI,II.IPA ;ANY PIS IN PROGRESS?
STOPCD .,STOP,PIP, ;++PI IN PROGRESS
JRST . ;WAIT UNTIL CLOCK LEVEL HAPPENS AND THE JOB
; IS STOPPED IF IN USER MODE. IF THE PC IS IN
;EXEC MODE, ERRCON WILL CONTINUE AT
; (.CPAPC(P4)) INSTEAD OF HERE
SEILM:: MOVEM P4,.UPMP+.UPMUO ;SAVE P4
MOVEI P4,.C0CDB## ;ASSUME ON CPU0
IFN FTMS,<
SKPCPU (0) ;ARE WE?
MOVEI P4,.C1CDB## ;NO, POINT P4 AT CPU1'S CDB
>
EXCH T1,.UPMP+.UPMUP ;SAVE T1 AND GET THE PC
MOVEM T1,.CPAPC##(P4) ;STORE IT AS POTENTIAL ERROR PC
EXCH T2,.UPMP+.UPUPF ;GET THE USER PAGE FAIL WORD
TLNN T1,(XC.USR) ;DID THE PAGE FAULT OCCUR IN USER MODE?
SKIPA T2,.UPMP+.UPEPF ;NO, GET THE EXEC PAGE FAIL WORD
MOVE T3,T2 ;USER PAGE FAULT, SAVE PC FOR POSSIBLE CALL TO USRFLT
JUMPL T2,SEILM4 ;INSURE AGAINST HARDWARE STORING -1 A P.F. WORD
ANDI T2,37 ;CLEAR ALL BUT THE PAGE FAIL CODE
TLNE T1,(XC.USR) ;PAGE FAULT IN EXEC MODE?
JRST SEILM0 ;NO, PROCEED
CAIE T2,PF.ABF ;WAS THE PAGE FAULT AN ADDRESS BREAK?
STOPCD .+1,JOB,IME, ;++ILL MEM REF FROM EXEC
JRST SEILM1 ;YES, REMEMBER IT AND GO AWAY
SEILM0: MOVE P,[XWD MJOBPD##,.JDAT+JOBPDL##] ;SETUP A PUSH DOWN LIST
CAIN T2,PF.ABF ;ADDRESS BREAK?
JRST SEILM1 ;YES, GO PROCESS
IFN FTVM,<
MOVE T4,T1 ;PC WORD INTO T4 FOR USRFLT
>
HRRI T1,AP.ILM ;ILLEGAL MEMORY REFERENCE
CAIN T2,PF.PRV ;WAS IT A PROPRIETARY VIOLATION?
IFE FTVM,<
TRO T1,AP.PPV ;YES, INDICATE THAT
>
IFN FTVM,<
TROA T1,AP.PPV ;INDICATE PROPRIETARY VIOLATION (AVOID CALL TO USRFLT)
PUSHJ P,USRFLT## ;SEE IF PAGE FAULT FOR A VM USER
; WILL NOT RETURN IF SO (DISPATCH TO USER)
MOVEM T4,.CPAPC##(P4) ;STORE ERROR PC
>
MOVE T2,.UPMP+.UPUPF ;RESTORE T2
JRST SEPDL1 ;GO SAY "ILL. MEM. REF."
SEILM1: TLO T1,(IC.AFI) ;INHIBIT ADDRESS BREAK WHEN INSTRUCTION IS
; EXECUTED AGAIN
EXCH J,.CPJOB##(P4) ;GET JOB
PUSH P,W ;SAVE W IN CASE IN EXEC MODE
PUSHJ P,FNDPDS## ;FIND THE PDB
LDB T2,[POINT 9,.PDABS##(W),17] ;GET THE PROCEED COUNT
SOSL T2 ;DECREMENT
DPB T2,[POINT 9,.PDABS##(W),17] ;STORE IT BACK IF POSITIVE
POP P,W ;RESTORE W
JUMPG T2,SEILM3 ;DON'T BREAK IF PROCEED COUNT .GT. 0
MOVE T2,JBTSTS##(J) ;IS THIS A JACCT
TLNE T2,JACCT ;JOB
JRST SEILM3 ;YES-IGNORE BREAK
EXCH J,.CPJOB##(P4) ;UNDO LAST EXCH
TLNN T1,(XC.USR) ;PC IN USER MODE?
JRST SEILM2 ;NO, REMEMBER BREAK AND GO AWAY
MOVE R,.CPADR##(P4) ;SETUP R
MOVEM T1,.CPAPC##(P4) ;STORE THE PC WITH IFA ON
IFN FTPI,<
MOVE J,.CPJOB##(P4) ;JOB NUMBER FOR PSISER
SIGNAL C$ADRB ;SIGNAL THAT AN ADDRESS BREAK HAS OCCURED
JRSTF @.CPAPC##(P4) ;THE USER IS ENABLED, INTERRUPT HIM
> ;END FTPI
PUSH P,.CPAPC##(P4) ;SAVE PC ON STACK
IFN FTMS,<
PUSHJ P,ONCPU0## ;MUST BE ON CPU0 TO REPORT THE BREAK
>
PUSHJ P,TTYFUW## ;FIND THE USER'S TTY
PUSHJ P,INLMES## ;REPORT THE ADDRESS BREAK
ASCIZ /
%Address break at user PC /
HRRZ T1,(P) ;GET THE USER'S PC
PUSHJ P,OCTPNT## ;TELL HIM WHERE THE BREAK OCCURED
IFN FTPI,<
PUSHJ P,PSIERR## ;PENDING INTERRUPT?
JFCL
PJRST ERRGOU## ;YES, GIVE IT TO THE USER
>
PJRST HOLDW## ;STOP THE JOB IN A CONTINUABLE STATE
SEILM2: MOVEI T2,JS.ASA ;AC'S ARE IN THE SHADOW AREA BIT
EXCH J,.CPJOB##(P4) ;JOB NUMBER
TDNE T2,JBTSTS##(J) ;SAVE/GET IN PROGRESS?
JRST SEILM3 ;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
SEILM3: EXCH J,.CPJOB##(P4) ;RESTORE J
SEILM4: EXCH T1,.UPMP+.UPMUP ; AND T1
MOVE T2,.UPMP+.UPUPF ; AND T2
MOVE P4,.UPMP+.UPMUO ; AND P4
JRSTF @.UPMP+.UPMUP ;GO AWAY AND TELL THE USER ABOUT THE BREAK
; AT UUO EXIT
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
IFN FTPI,<
PUSHJ P,CPUCDB## ;SETUP P4 TO POINT TO THE CURRENT CPU'S CDB
MOVE T2,JOBPD1##(R) ;GET UUO PC
MOVEM T2,.CPAPC##(P4) ;STORE IT WHERE PSISER EXPECTS IT
SIGNAL C$ADRB ;SIGNAL THAT AN ADDRESS BREAK OCCURED
POPJ P, ;USER IS ENABLED, UUO EXIT WILL INTERRUPT TO HIM
>
IFN FTMS,<
PUSHJ P,ONCPU0## ;MUST BE ON CPU0 TO WRITE A MESSAGE
>
PUSHJ P,TTYFUW## ;FIND THE USER'S TTY
PUSHJ P,INLMES## ;REPORT THE ADDRESS BREAK
ASCIZ /
%Address break at exec PC /
HRRZ T1,.UPMP+.UPMUP ;GET THE PC WHERE THE LAST BREAK OCCURED
PUSHJ P,OCTPNT## ;TELL HIM THAT
MOVEI T1,[ASCIZ/; UUO/]
PUSHJ P,CONMES##
MOVE T2,JOBPD1##(R) ;GET THE UUO PC
PUSHJ P,PCP## ;REPORT IT SO HE WILL KNOW WHAT UUO BROKE
IFN FTPI,<
PUSHJ P,PSIERR## ;PENDING INTERRUPT?
JFCL
POPJ P, ;YES
>
POP P,(P) ;POP OFF THE PUSHJ TO EXCABK
PJRST HOLDW## ;AND STOP THE JOB IN A CONTINUABLE STATE
SUILM: MOVEI P4,.C0CDB## ;ASSUME FAULT OCCURED ON CPU0
IFN FTMS,<
SKPCPU (0) ;DID IT?
MOVEI P4,.C1CDB## ;NO, ON CPU1
>
MOVE R,.CPADR##(P4) ;GET THE ADDRESS OF THE USER'S JOB DATA AREA
MOVEM T1,.UPMP+.UPMUO ;SAVE A TEMPORARY
MOVE T1,.UPMP+.UPMUP ;GET ILM PC
MOVE T2,.UPMP+.UPUPF ;GET THE PAGE FAIL WORD
ANDI T2,37 ;PAGE FAIL CODE
CAIN T2,PF.ABF ;ADDRESS BREAK?
JRST SEILM0 ;YES, GO PROCESS IT
IFN FTVM,<
MOVE T3,.UPMP+.UPUPF ;GET THE USER PAGE FAIL WORD
MOVE T4,T1 ;MOVE THE PC TO T4 FOR USRFLT
MOVE P,[XWD MJOBPD##,.JDAT+JOBPDL##] ;SETUP A PUSH DOWN LIST
PUSHJ P,USRFLT## ;SEE IF PAGE FAULT FOR VM USER
; WILL NOT RETURN IF SO (DISPATCH TO PFH)
>
TLZ T1,3637 ;CLEAR NON-EXISTANT KA-10 BITS FOR COMPATABILITY
MOVEM T1,JOBTPC##(R) ;SAVE ERROR PC FOR USER
HRRI T1,AP.ILM ;SET ILM BIT FOR USER
JRST SAROV3 ;FINISH UP
SUPDLO: MOVEI P4,.C0CDB## ;ASSUME ON CPU0
IFN FTMS,<
SKPCPU (0) ;ARE WE?
MOVEI P4,.C1CDB## ;NO, ON CPU1
>
EXCH R,.CPADR##(P4) ;GET ADDRESS OF USER'S JOB DATA AREA
MOVEM T1,.UPMP+.UPMUO ;SAVE A TEMPORARY
MOVE T1,.UPMP+.UPMUP ;GET ERROR PC
TLZ T1,3637
MOVEM T1,JOBTPC##(R) ;SAVE FOR USER TO LOOK AT
HRRI T1,AP.POV ;SET POV BIT FOR USER
JRST SAROV3 ;FINISH UP
;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::MOVE J,.C0JOB## ;J=CURRENT JOB NUMBER
MOVEI T1,0
DPB T1,JBYHSS## ;FORCE MAP TO BE REDONE
SETREL::PUSH P,P4 ;SAVE P4
MOVEI P4,.C0CDB## ;SETUP P4 TO POINT TO CPU0 CDB
SKIPA J,.C0JOB## ;J = CURRENT JOB NUMBER
SETRL1::PUSH P,P4 ;SAVE P4
MOVE R,JBTADR##(J) ;R = XWD PROTECTION,,EXEC VIRTUAL ADDRESS
; OF THE FIRST PAGE OF THE LOW SEGMENT
MOVEM R,.CPADR##(P4) ;SET .CPADR FOR QUICK ACCESS AT APR LEVEL
HLRZM R,.CPREL##(P4) ;SET .CPREL FOR ADDRESS CHECKING
IFN FTTRPSET,<
SKIPE .CPSTS##(P4) ;HAS TIME-SHARING BEEN STOPPED BY A TRPSET UUO?
JRST 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
PUSHJ P,STEUB ;NO, SET THE USER BASE REGISTER
JUMPE R,SETRLZ ;IF NULL JOB OR CORE 0, DON'T STORE IN
; NON-EXISTANT JOB DATA AREA
LDB T1,JBYLSS## ;GET THE PREVIOUS SIZE OF THE LOW SEGMENT
LDB T2,[POINT 9,R,8];GET THE CURRENT SIZE
CAIE T1,(T2) ;IS IT THE SAME SIZE AS IT WAS THE LAST
; TIME THIS JOB WAS RUN?
PUSHJ P,MAPLOW ;NO, REDO THE MAP
IFE FTVM,<
HLRZM R,JOBREL##(R) ;SET THE SIZE OF THE LOW SEGMENT FOR THE USER
>
IFN FTVM,<
SKIPN T1,.UPMP+.UPREL ;HOLEY PROGRAM?
HLR T1,R
HRRZM T1,JOBREL##(R) ;STORE HIGHEST CORE-UUO ADDRESS IN JOBREL
>
IFN FT2REL,<
SKIPL T1,JBTSGN##(J) ;JOB HAVE A REAL HIGH SEGMENT?
SKIPA T1,JBTADR##(T1) ;YES
HRLZS T1 ;SIZE OF SPY SEGMENT OR ZERO IF NOT SPY SEGMENT
LDB T2,[POINT 9,T1,8];CURRENT SIZE -1 OF THE HIGH SEGMENT
SKIPE T1 ;IS THERE A SPY OR HIGH SEGEMNT?
ADDI T2,1 ;YES, ITS ACTUALLY ONE PAGE BIGGER
LDB T1,JBYHSS##
CAIE T1,(T2) ;HAS THE HIGH SEGMENT SIZE CHANGED SINCE THE
; LAST TIME THIS JOB WAS RUN?
PUSHJ P,MAPHGH ;YES, REDO THE HIGH SEGMENT PART OF THE MAP
>
SETRLZ:
IFN FTSET,<
PUSHJ P,FDNJP ;FIND THE NULL JOB'S PDB
MOVE T3,T1 ;SAVE THE ADDRESS OF THE NULL JOB'S PDB
PUSHJ P,FNDPDS ;FIND THE CURRENT JOB'S PDB
>
HRRZ T1,JBTUPM##(J) ;PAGE NUMBER OF THE CURRENT JOB'S UPMP
JUMPE T1,SETRL2 ;DON'T CHANGE ANYTHING IF THERE ISN'T ONE
MOVSI T1,<(PG.LUB)>(T1)
IFN FTRTTRP,<
MOVEM T1,.CPDTO##(P4) ;SAVE FOR RTTRP INTERRUPT LEVEL USE
>
TLO T1,(PG.ACE+PG.AC1) ;USER ADDRESS COMPARE ENABLE AND USER AC SET 1
IFN FTSET,<
.SKIPE T2,.PDABS##(W) ;DOES THE USER HAVE ADDRESS BREAK SETTINGS?
TLNN T2,(OC.ABE) ;YES, IS HE ENABLED FOR BREAKS
MOVE T2,[EXP OC.FEP+CURJOB##] ;NO, DISPLAY JOB NUMBERS
>
DATAO PAG,T1 ;SETUP THE UBR
IFN FTSET,<
TLZ T2,777(OC.BSU) ;CLEAR PROCEED COUNTER AND SET BY UUO
.SKIPL .PDABS(T3) ;CAN USERS USE ADDRESS BREAK?
DATAO PTR,T2 ;YES, SETUP BREAK CONDITIONS AND BREAK ADDRESS
>
SETRL2: 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,JOBENB##(R) ;JOB'S APR ENABLE BITS
JRST SETAP2 ;SETUP APR ENABLE BITS FOR THE USER
; NO ENABLES IF NULL JOB OR NO CORE IN CORE
;ROUTINE CALLED BY SWAPPER TO ENSURE IT HAS A PAGE MAP SET UP
GETUBR::MOVE J,.CPJOB##(P4) ;CURRENT JOB
HRRZ J,JBTUPM##(J) ;GET PAGE MAP PAGE
JUMPN J,CPOPJ## ;IF ALREADY SET UP
;; PJRST STEUB ;FALL THRU TO SET UP NULL JOB'S MAP
;ROUTINE TO SETUP USER AND EXEC BASE REGISTERS FOR A JOB
;CALLING SEQUENCE:
; MOVE J,JOB NUMBER
; PUSHJ P,STEUB
STEUB:: CAILE J,JOBMAX## ;IS THIS A LOW SEGMENT?
POPJ P, ;NO, 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
TRNN T1,17777 ;IS THERE A UPMP
JRST TPOPJ## ;NO, DON'T CLOBBER UBR
MOVSI T1,<(PG.LUB+PG.AC1)>(T1)
DATAO PAG,T1 ;SET FOR CURRENT USER AND CLEAR THE AM
JRST TPOPJ## ;RESTORE T1 AND RETURN
SUBTTL COMCON - INTERFACE TO COMMAND DECODER MODULE
;ROUTINE TO SETUP THE USER BASE REGISTER FOR COMMAND PROCESSING
;CALLING SEQUENCE:
; PUSHJ P,COMUBR
; ... ALWAYS RETURN HERE - UBR POINTS TO THE UPMP OF THE
; JOB THAT TYPED A COMMAND
COMUBR::MOVE T1,.C0JOB## ;T1=JOB NUMBER OF CURRENTLY RUNNING JOB
HRRZ T2,JBTUPM##(T1) ;JOB HAVE A UPMP? (NO, ONLY IF THE CURRENT
; JOB DID LOGOUT UUO GIVING BACK ALL
; OF ITS CORE)?
JUMPE T2,STEUB ;NO, DON'T SAVE THE UBR SINCE IT POINTS
; A UPMP WHICH HAS BEEN RETURNED
; TO THE FREE CORE LIST - JUST POINT THE
; UBR AT THE UPMP OF THE JOB THAT THE
; COMMAND IS BEING DONE FOR
JRST SVEUB ;SAVE AND SETUP THE UBR
;HERE IF THE USER TYPED SET BREAK
IFN FTSET,<
SETBRK::PUSHJ P,SAVE2## ;SAVE P1,P2
PUSHJ P,FNDPDS## ;FIND THE PDB FOR THIS USER
PUSHJ P,CTEXT## ;GET THE FIRST ARGUMENT
JUMPE T2,NOTENF## ;IF NONE, COMPLAIN
PUSHJ P,GETNUM ;SEE IF ARGUMENT TYPED IS A NUMBER
JRST SETBR2 ;NOT A NUMBER, LOOK FOR LEGAL TEXT
SETBR1: CAIN P1,-1 ;DON'T ALLOW -1 FOR THE TIME BEING SINCE IT
; CONFUSES THE HARDWARE
JRST COMERA## ;COMPLAIN
.HRRM P1,.PDABS##(W) ;STORE THE BREAK ADDRESS
PUSHJ P,CTEXT## ;GET THE NEXT ARGUMENT
JUMPN T2,SETBR2 ;JUMP IF ONE WAS TYPED
SKIPN P2,P1 ;BREAK ADDRESS ZERO?
JRST SETB10 ;YES, TREAT SET BREAK 0 WITH NO CONDITION LIKE NONE
.HLLZ P2,.PDABS##(W) ;GET PREVIOUS CONDITIONS IF ANY
SETB1A: TLNN P2,(OC.BCI+OC.BCD+OC.BCW+OC.BCM) ;WERE THERE ANY PREVIOUSLY?
TLO P2,(OC.BCI+OC.BCD+OC.BCW) ;NO, ASSUME ALL
JRST SETBR8 ;ENABLE BREAK, STORE CONDITIONS, AND GO AWAY
SETBR2: MOVE T1,[-4,,BRKLS1] ;TABLE LENGTH,,ADDRESS OF THE TABLE
PUSHJ P,FNDNAM## ;RECOGNIZABLE TEXT ARGUMENT?
JRST SETBR5 ;NO, POSSIBLY IN ANOTHER CONTEXT
MOVE P2,T1 ;INDEX INTO BRKTBL
JUMPN T1,SETBR3 ;JUMP IF THE USER DIDN'T TYPE 'NONE'
;HERE WHEN THE USER TYPED 'NONE'
JUMPGE P1,COMERA## ;IF A NUMBER WAS TYPED WE SHOULDN'T BE HERE
JRST SETB10 ;GO CLEAR BREAK CONDITIONS
SETBR3: PUSHJ P,CTEXT## ;GET THE NEXT TEXT ARGUMENT
JUMPE T2,NOTENF## ;IF WE'RE HERE THERE HAS TO BE ONE
JRST .(P2) ;DISPATCH TO THE APPROPRIATE PROCESSOR
JRST SETBR4 ;USER TYPED 'AT'
JRST SETBR5 ;USER TYPED 'ON'
JRST SETBR6 ;USER TYPED 'NO'
;HERE WHEN THE USER TYPED 'AT'
SETBR4: JUMPGE P1,COMERA## ;NO PREVIOUS NUMBERS ALLOWED IF WE GET HERE
PUSHJ P,GETNUM ;CONVERT THE NUMBER FROM SIXBIT TO OCTAL
JRST COMERA## ;IT MUST BE A NUMBER BUT ISN'T SO COMPLAIN
JRST SETBR1 ;LOOK FOR THE NEXT TEXT ARGUMENT
;HERE WHEN THE USER TYPED 'ON'
SETBR5: SKIPA P1,[TDO P2,BRKTBL-1(T1)]
;HERE WHEN THE USER TYPED 'NO'
SETBR6: MOVE P1,[TDZ P2,BRKTBL-1(T1)]
.HLLZ P2,.PDABS##(W) ;GET CURRENT BREAK CONDITIONS
SETBR7: MOVE T1,[-7,,BRKLS2] ;TABLE LENGTH,,TABLE ADDRESS
PUSHJ P,FNDNAM## ;GET A BREAK CONDITION
JRST COMERA## ;IT CAN'T BE ANYTHING ELSE
JUMPE T1,SETB11 ;JUMP IF 'USERS'
CAIN T1,AFTERX
JRST SETB12
XCT P1 ;SET OR CLEAR THE CONDITION
PUSHJ P,CTEXT## ;GET THE NEXT ARGUMENT
JUMPN T2,SETBR7 ;LOOP BACK IF THERE WAS ONE
TLZ P2,(OC.ABE+OC.FUP) ;ASSUME NO CONDITIONS
TLNN P2,(OC.BCI+OC.BCD+OC.BCW+OC.BCM) ;ANY CONDITIONS DESIRED?
JRST SETB10 ;NO, DECREMENT NUMBER OF USERS USING ADDRESS BREAK
SETBR8: PUSHJ P,BRKAV ;SEE IF ADDRESS BREAK IS AVAILABLE AND INCREMENT
; THE COUNT OF USERS USING IT IF SO
JRST NOBRAK ;NOT AVAILABLE, COMPLAIN
SETBR9: TLOA P2,(OC.ABE+OC.FUP) ;ENABLE THE USER FOR ADDRESS BREAK
SETB10: PUSHJ P,BRKDEC ;DECREMENT THE COUNT OF USERS USING ADDRESS BREAK
.HLLM P2,.PDABS##(W) ;STORE THE NEW CONDITIONS
POPJ P, ;AND RETURN TO COMCON
;HERE WHEN THE USER TYPED 'USERS', MUST BE PRIVILEGED
SETB11: PUSHJ P,SETLGL## ;USER SUFFICIENTLY PRIVILEDGED TO MONOPOLIZE
; ADDRESS BREAK?
JRST COMERA## ;NO, COMPLAIN
PUSHJ P,FDNJP ;FIND THE NULL JOB'S PDB
MOVSI T2,400000 ;SET TO TURN ON OR OFF ADDRESS BREAK
CAME P1,[TDZ P2,BRKTBL-1(T1)] ;WAS 'USERS' WITHOUT A 'NO' TYPED?
JRST [.ANCAM T2,.PDABS##(T1) ;YES, ALLOW USERS TO USE ADDRESS BREAK
POPJ P,] ;RETURN
;HERE WHEN THE USER TYPED 'NO USERS'
.SKPLE .PDABS##(T1) ;IS ADDRESS BREAK CURRENTLY BEING USED?
JRST NOBRAK ;DON'T ALLOW HIM TO YANK IT OUT FROM UNDER THEM
.IORM T2,.PDABS##(T1) ;DON'T ALLOW USERS TO USE ADDRESS BRAEK
POPJ P, ;RETURN TO COMCON
;HERE WHEN THE USER TYPED 'AFTER'
SETB12: PUSHJ P,DECIN## ;GET THE NEXT ARGUMENT
PJRST NOTENF## ;THERE MUST BE ONE
JRST COMERA## ;NOTHING BUT A NUMBER IS LEGAL
CAILE T2,^D510 ;IS IT TOO BIG?
JRST COMERA## ;YES
ADDI T2,1
DPB T2,[POINT 9,P2,17] ;SAVE THE REPEAT COUNT
JRST SETB1A ;STORE IT AND GO AWAY
;HERE ON A SET ADDRESS BREAK UUO
SETABR::PUSHJ P,SAVE2## ;SAVE P1,P2
HRR M,T2 ;ADDRESS OF USER'S ARGUMENT
PUSHJ P,GETWDU## ;GET THE ARGUMENT
HRRM T1,.PDABS##(W) ;STORE THE BREAK ADDRESS
MOVE P2,T1 ;P2 = BREAK CONDITIONS
TLZ P2,(OC.FEP) ;HE ISN'T ALLOWED TO SET FOLLOW EXEC PAGING
TLO P2,(OC.BSU) ;INDICATE SET BY UUO
AOS (P) ;PREPARE TO GIVE GOOD RETURN
TLNN P2,(OC.BCI+OC.BCD+OC.BCW+OC.BCM)
JRST [PUSHJ P,SETB10 ;TURNING OFF BREAK
PJRST SETRL1]
PUSHJ P,BRKAV ;IS ADDRESS BREAK AVAILABLE?
SOSA (P) ;NO, ERROR RETURN
JRST [PUSHJ P,SETBR9 ;YES, SETUP BREAK CONDITIONS
PJRST SETRL1]
POPJ P, ;GIVE ERROR RETURN
;HERE ON RESET TO CLEAR BREAK ADDRESS AND CONDITIONS
; IF SET BY UUO
CLRBRK::SKIPE T1,.PDABS##(W) ;BREAK IN USE AT ALL?
TLNN T1,(OC.BSU) ;AND SET BY UUO?
POPJ P, ;NO
PUSHJ P,BRKDEC ;YES, DECREMENT COUNT OF USERS
SETZM .PDABS##(W) ;CLEAR ADDRESS AND CONDITIONS
POPJ P, ;AND RETURN
;THE ORDER OF AND THE NUMBER OF ENTRIES
; IN THE FOLLOWING TABLES CANNOT BE CHANGED
; WITHOUT CHANGING THE CODE IN SETBRK
BRKLS1: SIXBIT /NONE/
SIXBIT /AT/
SIXBIT /ON/
SIXBIT /NO/
BRKLS2: SIXBIT /USERS/
SIXBIT /EXECUT/
SIXBIT /READ/
SIXBIT /WRITE/
SIXBIT /MUUO/
SIXBIT /ALL/
BRKLS3: SIXBIT /AFTER/
AFTERX==BRKLS3-BRKLS2
;THE ENTRIES IN THIS TABLE CORRESPOND IN ORDER
; TO THE ENTRIES IN THE ABOVE TABLE
BRKTBL: EXP OC.BCI
EXP OC.BCD
EXP OC.BCW
EXP OC.BCM
EXP OC.BCI+OC.BCD+OC.BCW
;SUBROUTINE TO DETERMINE IF THE SIXBIT STRING IN
; T2 IS A LEGAL OCTAL NUMBER
;CALLING SEQUENCE:
;
; MOVE T2,SIXBIT STRING
; PUSHJ P,GETNUM
;NON-SKIP RETURN IF T2 DOES NOT CONTAIN A
; NUMBER, P1.LT.0, AND T2 PRESERVED
;SKIP RETURN P1=NUMBER IF T2 CONTAINS A NUMBER
;NEVER RETURNS IF T2 CONTAINS A MALFORMED
; NUMBER
;N.B. P1 MUST BE SAVED BEFORE CALLING THIS
;SUBROUTINE
GETNUM: MOVSI P1,400000 ;INDICATE NO NUMBER SEEN
MOVEI T3,0 ;CLEAR RESULT SO FAR
MOVE T4,[POINT 6,T2] ;BYTE POINTER TO PICKUP CHARACTERS
GETNM1: ILDB T1,T4 ;GET THE NEXT CHARACTER
CAIL T1,'0' ;IS THE CHARACTER .LT. ZERO?
CAILE T1,'7' ;OR G.GE. 7?
JRST GETNM2 ;YES, ITS NOT AN OCTAL DIGIT
LSH P1,3 ;MULTIPLY ACCUMULATED RESULT BY 8
ADDI P1,-'0'(T1) ;ADD IN THE CURRENT CHARACTER
JRST GETNM1 ;AND GET THE NEXT DIGIT
GETNM2: JUMPL P1,CPOPJ## ;NON-SKIP RETURN IF NOT A NUMBER
JUMPN T1,COMERP## ;NUMBERS WHICH TERMINATE WITH NON-DIGITS ARE
; NOT NUMBERS
JRST CPOPJ1## ;GIVE NUMBER FOUND RETURN
;SUBROUTINE TO DETERMINE WHETHER ADDRESS BREAK IS AVAILABLE TO USERS
;CALLING SEQUENCE:
; PUSHJ P,BRKAV
;NON-SKIP RETURN IF NOT AVAILABLE BECAUSE MEMORY
; INDICATORS ARE DISABLED OR ADDRESS BREAK IS BEING
; USED BY SYSTEM PROGRAMMERS FOR MONITOR DEBUGGING
;SKIP RETURN IF ADDRESS BREAK IS AVAILABLE TO USERS, COUNT OF THE NUMBER
;OF USERS USING ADDRESS BREAK HAS BEEN UPDATED
;PRESERVES T2
BRKAV: PUSHJ P,FDNJP ;FIND THE NULL JOB'S PDB
MOVSI T4,(IP.MID) ;MI PROG DIS
PUSHJ P,CP0RC## ;SEE IF THE JOB IS RUNNABLE ON CPU0
TLNE P2,(OC.BCM) ;ITS NOT, BUT IF HE IS ENABLED FOR UUOS, SOME
; MUST HAPPEN ON CPU0
TDNN T4,.C0APR## ;IS MI PROG DIS ON ON CPU0?
SKIPGE .PDABS##(T1) ;OR HAS ADDRESS BREAK BEEN DISABLED BY THE OPR?
POPJ P, ;YES, LOSE
IFN FTMS,<
PUSHJ P,CP1AC## ;IF RUNNABLE ON CPU1, MI PROG DIS MUST BE OFF ON CPU1
POPJ P, ;HE IS AND IT ISN'T, SO LOSE
>
.MOVE T3,.PDABS##(W) ;GET HIS CURRENT ADDRESS BREAK SETTINGS
TLNN T3,(OC.ABE) ;IS HE ALREADY BREAKING?
.AOS .PDABS##(T1) ;NO, COUNT UP THE NUMBER OF USERS USING ADDRESS BREAK
JRST CPOPJ1## ;AND GIVE THE HAPPY RETURN
;SUBROUTINE TO DECREMENT THE COUNT OF THE NUMBER
; OF USERS USING ADDRESS BREAK
BRKDEC: .MOVE T1,.PDABS##(W) ;GET HIS CURRENT BREAK SETTINGS
TLNN T1,(OC.ABE) ;IS HE ENABLED FOR ADDRESS BREAK?
POPJ P, ;NO, NOTHING TO DO
PUSHJ P,FDNJP ;FIND THE PDB FOR THE NULL JOB
.SOS .PDABS##(T1) ;DECREMENT THE COUNT OF USERS USING ADDRESS BREAK
POPJ P, ;AND RETURN
NOBRAK: PJSP T1,CONMES## ;SORRY FOLKS!
ASCIZ /?Not available
/
;SUBROUTINE TO RETURN THE ADDRESS OF THE NULL JOB'S PDB IN T1
;PRESERVES T2-T4
FDNJP: MOVEI T1,0 ;NULL JOB'S JOB NUMBER
PUSHJ P,FPDBT1## ;FIND THE NULL JOB'S PDB, RETURN ITS ADDRESS IN T1
JFCL ;IT MUST HAVE ONE
POPJ P, ;RETURN TO THE CALLER
> ;END IFN FTSET
SUBTTL IOCSS - I/O SERVICE SUBROUTINES (UUOCON AND DEVICE ROUTINES)
;ROUTINE TO DETERMINE WHETHER A DEVICE NEEDS THE USER AREA
;REPRESENTED IN THE CURRENT I/O OPERATION TO BE
;MAPPED IN EXEC VIRTUAL MEMORY
;CALLING SEQUENCE:
;
; MOVE F,ADDRESSS OF DEVICE DATA BLOCK
; PUSHJ P,MAPDEV
; RETURN HERE IF NO MAPPING REQUIRED
; RETURN HERE IF BUFFERS OR IOWDS MUST BE MAPPED
MAPDEV::PUSH P,T1 ;SAVE P1
MOVEI T1,DEPEVM ;GET "DEVICE DOESN'T NEED EVM" BIT
TDNN T1,DEVTYP(F) ;SKIP IF MAPPING NOT REQUIRED
PJRST TPOPJ1## ;PTY, TTY, AND CHANNEL DEVICES ARE NOT
; MAPPED IN EXEC VIRTUAL MEMORY
PJRST TPOPJ## ;ALL I/O BUS DEVICE REQUIRE MAPPING IN
; EXEC VIRTUAL MEMORY
;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
DATAI PAG,T1 ;GET THE USER AND EXEC BASE REGISTERS
PUSH P,J ;SAVE J
LDB J,PJOBN## ;GET THE JOB NUMBER OF JOB CURRENTLY USING
; THIS DEVICE
PUSHJ P,STEUB ;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
DATAI PAG,T1 ;GET THE CONTENTS OF THE USER AND EXEC BASE REGISTERS
PUSHJ P,STEUB ;SETUP THE UBR FOR THE JOB WHOSE JOB NUMBER
; IS IN J
JRST SSEU1 ;SAVE THE PREVIOUS CONTENTS OF THE UBR AND THE EBR
SSEUB: PUSH P,T1 ;SAVE A TEMPORARY
DATAI PAG,T1 ;GET THE CONTENTS OF THE USER AND EXEC BASE REGISTERS
SSEU1: EXCH T1,-1(P) ;GET THE CALLER'S PC AND SAVE THE CONTENTS
; OF THE UBR AND EBR
MOVEM T1,1(P) ;SAVE THE CALLER'S PC IN A TEMPORARY LOCATION
; ON THE STACK
POP P,T1 ;RESTORE T1 TO ITS CONTENTS ON ENTRY
PUSHJ P,@2(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 AND THE EBR
CAIA ;CPOPJ RETURN
AOS -1(P) ;CPOPJ1 RETURN - BUMP RETURN PC
EXCH T1,(P) ;GET THE PREVIOUS CONTENTS OF THE UBR
TDO T1,[EXP PG.LUB+PG.LEB]
DATAO PAG,T1 ;RESTORE THE UBR AND THE EBR
JRST TPOPJ## ;RESTORE T1 AND RETURN
;ROUTINE TO MAP USER AREA IN THE EXEC MAP
;CALLING SEQUENCE:
;
; MOVE T1,PAGE NUMBER OF STARTING PAGE IN THE EXEC MAP
; MOVE T2,NUMBER OF PAGES
; MOVE T3,USER VIRTUAL ADDRESS
; PUSHJ P,MAPUEV
;OR
; PUSHJ P,MAPUEI IF AT INTERRUPT LEVEL SO EBR,UBR WILL BE
; RESTORED SO DO NOT NEED TO PURGE ASSOCIATIVE MEMORY
; RETURNS HERE - T1=PAGE NUMBER IN THE EXEC MAP, T3=EXEC VIRTUAL
; ADDRESS WHICH CORRESPONDS TO USER VIRTUAL ADDRESS,
; AND ASSOCIATIVE MEMORY IS PURGED
MAPUEV::PUSHJ P,SAVE3## ;SAVE P1-P3
PUSHJ P,MAPUE1 ;MAP THE USER IN EXEC VIRTUAL MEMORY
CLRPGT (0) ;RESET THE EXEC BASE REGISTER SO THAT
; THE ASSOCIATIVE MEMORY WILL BE FLUSHED
; AND THE NEW MAPPING WILL BE IN AFFECT
POPJ P, ;RETURN
MAPUEI::PUSHJ P,SAVE3## ;SAVE P1-P3
MAPUE1: MOVE P1,T1 ;P1 = THE PAGE NUMBER OF THE FIRST PAGE
; IN THE EVM THAT BELONGS TO THIS JOB
SUBI P1,400 ;MAPPED ADDRESSES START AT 128K
ROT P1,-1 ;DIVIDE BY 2 AND PUT THE REMAINDER IN HIGH ORDER BIT
MOVEI P2,.EPPM##(P1) ;FORM A BYTE POINTER TO THE EXEC MAP
TLO P2,442200 ;ASSUME AN EVEN PAGE
SKIPGE P1 ;WAS IT EVEN?
HRLI P2,222200 ;NO, START WITH THE RIGHT HALF WORD
LDB P1,[POINT 9,T3,26]
ROT P1,-1 ;DIVIDE BY 2 AND PUT THE REMAINDER IN HIGH ORDER BIT
MOVEI P3,.UPMP(P1) ;FORM A BYTE POINTER TO THE USER'S MAP
SKIPL P1 ;FIRST PAGE EVEN
TLOA P3,442200 ;YES, THE FIRST PAGE IS MAPPED BY THE LEFT HALF WORD
HRLI P3,222200 ;NO, MAPPED BY THE RIGHT HALF WORD
MAPUE2: ILDB P1,P3 ;COPY A PORTION OF THE USER'S MAP TO
TRZ P1,760000 ;CLEAR ALL ACCESS BITS
TRO P1,PM.ACC+PM.WRT ;ACCESS ALLOWED, CONCEALED, AND WRITEABLE
IDPB P1,P2 ; THE EXEC MAP
SOJG T2,MAPUE2 ;COPY AS MANY PAGES AS ARE TO BE MAPPED IN EVM
DPB T1,[POINT 9,T3,26]
;FORM AN EXEC VIRTUAL ADDRESS FROM THE EXEC
; PAGE NUMBER AND THE USER VIRTUAL ADDRESS
POPJ P, ;RETURN
;ROUTINE TO MAP A USER BUFFER IN EXEC VIRTUAL MEMORY
;CALLING SEQUENCE:
; MOVE T1,BUFFER SIZE
; MOVE T3,USER VIRTUAL ADDRESS OF BUFFER
; MOVE F,ADDRESS OF THE DDB
; PUSHJ P,GTEVBF
; RETURN HERE ONLY IF REQUEST COULD NEVER BE SATISFIED (THERE WILL
; NEVER BE ENOUGH SLOTS AVAILABLE IN THE EXEC MAP)
; RETURN HERE - T1=BYTE (18)0(9) EXEC VIRTUAL PAGE # (9) # OF EXEC PAGES
; T3 = THE EXEC VIRTUAL ADDRESS OF THE BUFFER
GTEVBF::SUBI T1,2 ;COMPUTE THE UPPER BOUND ON THE NUMBER OF PAGES
IDIVI T1,PAGSIZ##+2 ; OF EXEC VIRTUAL MEMORY WHICH MIGHT BE
ADDI T1,2 ; REQUIRED TO COVER THIS BUFFER OR IOWD
CAMLE T1,EVBMAX## ;WILL THAT NUMBER OF PAGES EVER BE AVAILABLE?
POPJ P, ;NO, ERROR RETURN
PUSH P,T1 ;SAVE NUMBER OF PAGES BEING REQUESTED
GTEVB1: PUSH P,T3 ;SAVE THE USER VIRTUAL ADDRESS
PUSHJ P,GETEVM ;ATTEMPT TO GET ENOUGH PAGES TO SATISFY THE REQUEST
JRST GTEVBW ;NOT ENOUGH AVAILABLE (WAIT FOR SOME TO BE FREED UP)
POP P,T3 ;RESTORE THE USER'S VIRTUAL ADDRESS
MOVE T2,(P) ; AND THE NUMBER OF PAGES
PUSHJ P,MAPUEV ;MAP THE BUFFER OR IOWD IN THE EXEC MAP
MOVE T1,T3 ;T1 = EXEC VIRTUAL ADDRESS OF THE BUFFER OR IOWD
POP P,T2 ;MAKE T1 = EXEC VIRTUAL ADDRESS OF SAME
DPB T2,[POINT 9,T1,35]
JRST CPOPJ1## ;GIVE OK RETURN
GTEVBW: POP P,T3 ;RESTORE T3
PUSHJ P,EVWAIT## ;WAIT UNTIL SOME EVM IS FREED UP
MOVE T1,(P) ;RESTORE THE NUMBER OF PAGES REQUIRED
JRST GTEVB1 ;TRY AGAIN
;SUBROUTINE TO GET EXEC VIRTUAL MEMORY
;CALLING SEQUENCE:
;
; MOVE T1,NUMBER OF CONTIGOUS PAGES REQUIRED
; PUSHJ P,GETEVM
; ... ERROR RETURN - NOT ENOUGH AVAILABLE, T1 = LARGEST NUMBER SEEN
; ... OK RETURN - T1 = PAGE NUMBER OF FIRST AVAILABLE PAGE
GETEVM::MOVEI T2,EVMPTR## ;POINT TO EXEC-MAP USAGE TABLE
PUSHJ P,GETBIT## ;GET, SET BITS IN THE TABLE FOR THESE PAGES
POPJ P, ;NOT ENOUGH AVAILABLE, RETURN WITH T1= LARGEST HOLE
MOVEI T1,400(T1) ;MAKE RELATIVE LOCATION IN THE MAP INTO PAGE NUMBER
JRST CPOPJ1## ;AND GIVE SUCCESS RETURN
;ROUTINE TO GIVE BACK SLOTS IN THE EXEC MAP
;CALLING SEQUENCE:
; MOVE T1,NUMBER OF PAGES
; MOVE T2,EXEC VIRTUAL ADDRESS
; PUSHJ P,GIVEVM
; ALWAYS RETURN HERE
GIVEVM::LDB T2,[POINT 9,T2,26]
SUBI T2,400 ;CHANGE PAGE NUMBER INTO BIT POSITION
IDIVI T2,^D36 ;WHICH WORD
HRLS T2 ;PUT WORD NUMBER IN THE LEFT HALF
ADD T2,EVMPTR## ;MAKE AOBJN POINTER POINT TO THE WORD CONTAINING
; THE FIRST BIT TO CLEAR
PUSH P,T4 ;SETZRS CLOBBER T4
PUSHJ P,SETZRS## ;GIVE BACK THE EVM
PUSHJ P,EVFREE## ;WAKE UP ALL WAITERS FOR EVM
SETZM EVREQ## ;SO NEXT CALLER TO EVWAIT WILL WAIT (IMMEDIATELY)
JRST T4POPJ## ;RETURN
;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
; LH(P3)=1 IF STORE EXPECTED CHAN TERM WORD
; MOVE P4,FRAME-COUNT,,CHARS/WD IF DX10 CHL
; 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
MAPIO:: TLNN T2,-1 ;0 OR CHANNEL JUMPS ARE ILLEGAL
STOPCD CPOPJ,DEBUG,IEZ, ;++IOWD EQUALS ZERO
PUSHJ P,SVEUB ;SAVE AND SETUP UBR
PUSH P,U ;SAVE U
LDB U,[POINT 2,CHB22B##(P3),1]
IFN FT22BIT,<
;GET CHL TYPE INFO
HLL U,P4 ;PRESERVE FRAME-COUNT
>
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 MAPIO9 ;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
SETZM 3(P1) ;ZERO THE LAST WORD OF THE BLOCK
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 MAPIO8 ;NO MORE FOUR WORD BLOCKS
MOVE P4,-2(P) ;RESTORE THE IOWD TO P4
HRRZ T2,P4 ;ADDRESS-1 WHERE I/O WILL START
MOVE T3,DEVMOD(F)
IFE FTSPL,<
TLNN T3,DVDSK ;IF A DSK
>
IFN FTSPL,<
SKIPL DEVSPL(F) ;SPOOLED DDBS ARE ALWAYS A DSK
TLNE T3,DVDSK ;IS A DSK
CAIA
>
JRST MAPI1B
IFE FTVM<
SKIPL DEVSWP##(F) ;IF NOT THE SWAPPER
>
JUMPL S,MAPIO6 ; DONT UNRELOCATE IF MONITOR IO
MAPI1B: MOVE R,JBTADR##(J) ;ADDRESS OF THE JOB DATA AREA
PUSHJ P,CHKHS ;SEE IF A HIGH SEGMENT SAVE IS IN PROGRESS
IFE FTVM,<
CAIA
SKIPLE J,JBTSGN##(J) ;YES, J = HIGH SEGMENT NUMBER
SKIPN T1,JBTADR##(J) ;EXEC VIRTUAL ADDRESS OF THIS SEGMENT
; (DEVICE ROUTINES THINK THEY ARE RELOCATING
; THE IOWD BY ADDING THIS)
STOPCD .,JOB,IRE, ;++IOWD RELOCATION ERROR
CAILE J,JOBMAX## ;HIGH SEG?
MOVEI T1,342000 ;YES, USE STD ADDR
SUBI T2,-1(T1) ;SUBTRACT OUT "RELOCATION" AND ACCOUNT
; FOR THE FACT THAT IOWDS ARE ADDRESS-1
HRRZS T2 ;IN CASE OF MORE THAN 437 PAGES
LSH T2,W2PLSH## ;CONVERT TO PAGE NUMBER
PUSHJ P,SNPAGS ;GET THE ABSOLUTE PAGE NUMBER OF THIS PAGE
MOVE P3,T1 ;SAVE THAT IN P3
MOVE T2,P4 ;T2 AND P4 = IOWD+1
HLROS P4 ;P4 = -WORD COUNT
ADDI T2,1
MAPIO2: SKIPN T3,P3 ;T3 = CURRENT ABSOLUTE PAGE NUMBER
STOPCD .,JOB,APE, ;++ABSOLUTE PAGE EXCEEDED
; IOWD HAS BEEN ADDRESS CHECKED)
MOVEI T1,0 ;T1 = AMOUNT ACCUMULATED SO FAR
LSH T3,P2WLSH## ;MOVE PAGE NUMBER TO THE HIGH ORDER THIRTEEN
; BITS OF THE ADDRESS
ANDI T2,PG.BDY## ;GET THE STARTING WORD ADDRESS WITHIN THE PAGE
ADD T2,T3 ;T2 = ABSOLUTE ADDRESS
SUBI T2,1 ;MAKE T2 AN IOWD
PUSH P,T2 ;SAVE THE ADDRESS
ANDI T2,PG.BDY## ;EXTRACT THE WORD NUMBER
SUBI T2,PAGSIZ##-1 ;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,MAPIO4 ;JUMP IF THE ORIGIONAL WORD COUNT IS EXHAUSTED
IFN FT22BIT,<
SETZ T3, ;SET T3 SO TEST WILL FAIL IF 22-BIT CHAN AND
SKIPE U ; NO ROOM FOR ANOTHER PAGE IN THE IOWD
CAML T1,[EXP -37777+PAGSIZ##] ;OTHERWISE SET T3=CURRENT PAGE
>
MOVE T3,P3 ;T3 = CURRENT PAGE NUMBER WITHIN SEGMENT
HRRZ P3,PAGTAB(P3) ;P3 = NEXT PAGE NUMBER WITHIN SEGMENT
CAIN P3,1(T3) ;ARE THE TWO PAGES ADJACENT IN PHYSICAL MEMORY?
> ;END FTVM
IFN FTVM,<
JRST MAPI1C ;NO, GET VIRT ADR THE NORMAL WAY
MOVE T1,P4 ;YES, IOWD TO T1
SUBI T1,(R) ;UNRELOCATE IT
PUSHJ P,UVACK ;COMPUTE STARTING ADR FOR THIS PART
AOJA T2,MAPI1D ;AND CONTINUE
MAPI1C: SKIPN T1,JBTADR##(J) ;EXEC VIRTUAL ADDRESS OF THIS SEGMENT
; (DEVICE ROUTINES THINK THEY ARE RELOCATING
; THE IOWD BY ADDING THIS)
STOPCD .,JOB,IRE, ;++IOWD RELOCATION ERROR
SUBI T2,-1(T1) ;SUBTRACT OUT "RELOCATION" AND ACCOUNT
; FOR THE FACT THAT IOWDS ARE ADDRESS-1
HRRZS T2 ;NEEDED IF SEG GTR THAN 437 PAGES
MAPI1D: LSH T2,W2PLSH## ;CONVERT TO PAGE NUMBER
ROT T2,-1 ;SET UP A BYTE POINTER TO THE PAGE IN THE UPMP
ADDI T2,.UPMP
TLZE T2,400000
TLOA T2,(<POINT 18,0,35>)
TLO T2,(<POINT 18,0,17>)
MOVE P3,T2 ;SAVE POINTER IN P3
MOVE T2,P4 ;T2 AND P4 = IOWD
HLROS P4 ;P4 = -WORD COUNT
ADDI T2,1 ;POINT AT REAL ADR
MAPIO2: LDB T3,P3 ;T3 = CURRENT ABSOLUTE PAGE NUMBER
TRNN T3,PM.ACC
IFN FTEXE,<
SKIPGE USRHCU## ;IF A SAVE IS IN PROGRESS,
SKIPA ; THEN, THIS IS OK
>;END OF INF FTEXE
JRST S..AAO ;ACCESS ALLOWED OFF
; IOWD HAS BEEN ADDRESS CHECKED)
MOVEI T1,0 ;T1 = AMOUNT ACCUMULATED SO FAR
LSH T3,P2WLSH## ;MOVE PAGE NUMBER TO THE HIGH ORDER THIRTEEN
; BITS OF THE ADDRESS
ANDI T2,PG.BDY## ;GET THE STARTING WORD ADDDESS WITHIN THE PAGE
ADD 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,PAGSIZ##-1 ;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,MAPIO4 ;JUMP IF THE ORIGIONAL WORD COUNT IS EXHAUSTED
IFN FT22BIT,<
SETZ T3, ;SET T3 SO TEST WILL FAIL IF 22-BIT CHAN AND
SKIPE U ; NO ROOM FOR ANOTHER PAGE IN IOWD
CAML T1,[EXP -37777+PAGSIZ##] ;OTHERWISE SET T3=CURRENT PAGE
>
LDB T3,P3 ;T3 = CURRENT PAGE NUMBER WITHIN SEGMENT
ILDB T4,P3 ;T4 = NEXT PAGE NUMBER WITHIN SEGMENT
TRNN T4,PM.ACC ;ACCESS ALLOWED ON?
STOPCD .,JOB,AAO, ;++ACCESS ALLOWED IS OFF
TRZ T3,760000 ;CLEAR ACCESS BITS
TRZ T4,760000 ;CLEAR OUT THE ACCESS BITS
CAIN T4,1(T3) ;ARE THE TWO PAGES ADJACENT IN PHYSICAL MEMORY?
> ;END IFN FTVM
JRST MAPIO3 ;YES, CONTINUE ON CURRENT IOWD
MOVEI T2,0 ;T2 = FIRST ADDRESS
POP P,(P1) ;STORE THE IOWD ABSOLUTE ADDRESS
IFE FT22BIT,<
HRLM T1,(P1) ;AND THE WORD COUNT (NUMBER OF WORDS MAPPED SO FAR)
>
IFN FT22BIT,<
PUSHJ P,DXFIX ;ADJUST IOWD IF A DX10
JRST MAPIO8 ;NO SPACE
JUMPL U,MAPIO7 ;GO 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
MOVEI T2,0 ;START AT WORD NUMBER ZERO ON THIS PAGE
JRST MAPIO2 ;MAP THE REST OF THE IOWD
MAPIO4: POP P,(P1) ;STORE THE IOWD ABSOLUTE ADDRESS
ADD P4,T1 ;ADD THE RESIDUAL WORD COUNT TO THE ACCUMULATED
; WORD COUNT
IFE FT22BIT,<
HRLM P4,(P1) ;STORE WORD COUNT IN IOWD
>
IFN FT22BIT,<
MOVE T1,P4 ;PUT WD CNT INTO T1
PUSHJ P,DXFIX ;PERFORM FIXUPS FOR DX10
JRST MAPIO8 ;OUT OF SPACE
>
JRST MAPIO7 ;AND GIVE THE WIN RETURN
MAPIO6:
IFE FT22BIT,<
MOVEM P4,(P1) ;THE I/O IS INTO A MONITOR BUFFER SO STORE
>
IFN FT22BIT,<
MOVEM T2,0(P1) ;STORE ADDRESS
HLRE T1,P4 ;GET WORD COUNT
PUSHJ P,DXFIX ;FIDDLE WITH DX10 IOWDS
JRST MAPIO8 ;NO ROOM
>
; THE ALREADY ABSOLUTE IOWD AND RETURN
;AND FALL INTO MAPIO7
;MAPIO6 FALLS INTO HERE
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:
IFE FT22BIT,<
HLRE P4,-1(P1) ;GET NEG WORD CNT FROM LAST IOWD
HRRZ T1,-1(P1) ;GET START OF DATA FROM LAST IOWD
SUB T1,P4 ;DETERMINE ENDING DATA ADDRESS
HRL T1,P1 ;PUT ADDR OF END OF IOWD LIST
>
SKIPGE -3(P) ;IF WE WANT IT STORED,
TRNE U,1 ;TYPE 0 OR 2 CONTROLLER?
JRST MAPIO9 ;NO, DON'T DO NEXT
IFN FT22BIT,<
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 P3,-3(P)
MOVEM T1,CHNTCW##(P3)
MAPIO9: 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
;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
; 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:
IFN FT22BIT,<
TRC U,3
TRCN U,3 ;CHECK CHL TYPE
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
IFN FT22BIT,<
;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: HRRZ T4,U
CAIE T4,3 ;CHECK CHL TYPE
JRST [DPB T1,WDCPNT##(U)
JRST CPOPJ1##] ;HANDLE NON-DX10 CHLS
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 ;ANY LEFT?
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
MOVEI T2,0 ;RESTORE T2
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 ;PROCEED
DXFIX2: DPB T1,WDCPNT##(U) ;STORE RESIDUE
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
> ;END IFN FT22BIT
;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
MOVE P1,T1 ;P1 = ADDRESS OF THE IOWD LIST
RTNIO1: MOVEI T1,1 ;GIVE BACK ONE FOUR WORD BLOCK
MOVE T2,P1 ;ADDRESS OF THE BLOCK
MOVE T3,3(P1) ;LAST WORD OF BLOCK
TLNN T3,-1 ;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::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
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
PJRST SETZRS## ;CLEAR THE BITS AND RETURN
;SUBROUTINE TO CHECK TO SEE IF THE CURRENT I/O OPERATION IS A
; HIGH SEGMENT SAVE
;CALLING SEQUENCE:
; MOVE F,DDB ADDRESS
; MOVE R,LOW SEGMENT ADDRESS
; PUSHJ P,CHKHS
; RETURN HERE IF NORMAL I/O
; RETURN HERE IF HIGH SEGMENT SAVE
CHKHS: PUSHJ P,SAVE1## ;SAVE P1
MOVE P1,DEVMOD(F) ;DEVICE DESCRIPTORS
TLNE P1,DVDSK ;DSK I/O?
SKIPL DEVSWP##(F) ;YES, SWAPPING I/O?
SKIPL P1,JOBHCU##(R) ;NO, IS A SAVE OR GET IN PROGRESS?
POPJ P, ;NOT SAVE/GET
TLNE P1,3 ;DOING THE I/O TO SAVE A HIGH SEGMENT?
POPJ P, ;NO, NORMAL I/O
IFN FTEXE,<
PUSH P,J ;SAVE J
LDB J,PJOBN## ;GET CURRENT JOB NUMBER
PUSHJ P,CHKEXE## ;IS THIS AN EXE FILE SAVE?
JRST JPOPJ## ;YES, EXIT AND DO NOTHING
POP P,J ;NO, RESTORE J
>;END OF IFN FTEXE
PJRST CPOPJ1## ;YES, GIVE HIGH SEGMENT SAVE IN PROGRESS RETURN
;SUBROUTINE TO RETURN THE USER VIRTUAL ADDRESS OF THE
; CHECKSUM WORD
;CALLING SEQUENCE:
; MOVE T1,IOWD TO BE USED IN THE FILE TRANSFER (UNRELOCATED)
; MOVE R,LOW SEGMENT PROTECTION,, RELOCATION
; PUSHJ P,UVACKS
; ALWAYS RETURN HERE - T2 = UVA OF THE CHECKSUM
;PRESERVES T1
UVACK:
UVACKS::HRRZ T2,T1 ;ADDRESS I/O WILL BE DONE FROM OR TO
PUSHJ P,CHKHS ;SEE IF SAVING A HIGH SEGMENT
POPJ P, ;NO, NORMAL I/O RETURN
SUBI T2,.VJDT-.JDAT ;T2=ADDRESS WITHIN THE HIGH SEGMENT WHERE
; OUTPUT WILL START
PUSH P,T2 ;SAVE THAT
PUSH P,J ;SAVE J
PUSH P,T1 ;AND T1
LDB J,PJOBN## ;GET JOB NUMBER
PUSHJ P,HSVAD## ;GET THE STARTING VIRTUAL ADDRESS OF THE
; HIGH SEGMENT
POP P,T1 ;RESTORE T1
POP P,J ;AND J
ADDM T2,(P) ;(P)=UVA OF FIRST WORD -1 TO BE OUTPUT
JRST T2POPJ## ;T2=UVA, AND RETURN
;SUBROUTINE TO GET EVM IF NEEDED FOR OUTPUT
;CALLING SEQUENCE:
; MOVE F,DDB ADDRESS
; PUSHJ P,GTOEVM
; RETURN HERE
;NEVER RETURN IF TO MUCH EVM IS REQUIRED
GTOEVM::SKIPA T3,PDVOAD## ;POINTER TO UVA OF THE BUFFER
; PJRST GTBEVM ;MAP THE BUFFER IN EVM
;SUBROUTINE TO GET EVM IF NEEDED FOR INPUT
;CALLING SEQUENCE:
; MOVE F,DDB ADDRESS
; PUSHJ P,GTIEVM
; RETURN HERE
;NEVER RETURN IF TO MUCH EVM IS REQUIRED
GTIEVM::MOVE T3,PDVIAD## ;POINTER TO UVA OF THE BUFFER
; PJRST GTBEVM ;MAP THE BUFFER IN EVM
;FALL INTO GTBEVM
;SUBROUTINE TO ACCOUNT FOR THE FACT THAT BUFFERS
; ARE TWO WORDS LONGER THAN THE NUMBER OF DATA
; WORDS IN THE BUFFER AND THE FACT THAT THE LINK
; WORD IS REALLY THE SECOND WORD OF THE BUFFER
;CALLING SEQUENCE:
; MOVE T3,POINTER TO THE CURRENT BUFFER (UVA)
; PUSHJ P,GTBEVM
; RETURN HERE T1 = # OF PAGES + STARTING PAGE #, T3 = EVA OF BUFFER
;NEVER RETURN IF NOT ENOUGH EVM
GTBEVM: PUSHJ P,MAPDEV ;IS CURRENT DEVICE A PTY, TTY, OR ON A CHANNEL?
POPJ P, ;YES, DO NOT ALLOCATE ANY EVM
PUSH P,T3 ;SAVE THE USER VIRTUAL ADDRESS OF THIS BUFFER
; SO CAN RETURN EVM ON HUNG DEVICE, ETC.
HRRZ T3,@T3 ;USER VIRTUAL ADDRESS OF THE BUFFER
EXCTUX <HLRZ T1,(T3)> ;SIZE OF THE BUFFER
TRZ T1,IOUSE ;T1 = NUMBER OF DATA WORDS - USE BIT
SUBI T3,1 ;POINT TO ACTUAL FIRST WORD OF THE BUFFER
ADDI T1,2 ;ACCOUNT FOR THE TWO OVERHEAD WORDS IN
; THE BUFFER
PUSHJ P,GTEVBF ;MAP THE BUFFER IN EVM - WAIT UNTIL
; SOME IS AVAILABLE IF NECESSARY
JRST ADRERR## ;NEVER WILL BE ENOUGH EVM
HRL T1,@(P) ;SAVE USER VIRTUAL ADDRESS OF THE BUFFER
ADDI T3,1 ;BUMP BUFFER ADDRESS TO THE LINK WORD
CONO PI,PI.OFF ;GUARD AGAINST INTERRUPTS
MOVEM T1,DEVEVM(F) ;SAVE THE STARTING PAGE NUMBER AND NUMBER
; OF PAGES OF EVM FOR ADVANCING BUFFERS
; AND RETURNING EVM
DPB T3,(P) ;STORE THE EVA OF THE BUFFER FOR THE DEVICE ROUTINE
CONO PI,PI.ON ;NOW, ALLOW INTERRUPTS AGAIN
JRST T2POPJ## ;RETURN
;SUBROUTINE TO RESTORE EVM AFTER GIVING IT
; UP ON A CALL TO THE SCHEDULER (CONTROL BUSY, HUNG DEVICE, ETC.)
;CALLING SEQUENCE:
; MOVE F,ADDRESS OF DEVICE DATA BLOCK
; MOVE S,DEVIOS(F) ;DEVICE STATUS
; PUSHJ P,RSTEVM
; RETURN HERE IF NO ADDRESS CHECK WITH DEVEVM(F) SETUP
RSTEVM::LDB T1,PIOMOD## ;GET DATA MODE
CAIL T1,SD ;DUMP MODE?
PJRST DMPEV ;YES, GET EVM DUMP MODE STYLE
TLNE S,IO ;BUFFERED MODE, INPUT OR OUTPUT?
PJRST GTOEVM ;OUTPUT, GET BUFFERED OUTPUT EVM
PJRST GTIEVM ;INPUT, GET BUFFERED INPUT EVM
;SUBROUTINE TO DETERMINE IF A DEVICE NEEDS EVM TO DO DUMP
; MODE I/O AND IF SO TO SCAN THE IOWD LIST TO FIND THE
; IOWD WHICH HAS THE LARGEST WORD COUNT AND ALLOCATE
; ENOUGH EVM TO COVER THAT IOWD.
;CALLING SEQUENCE:
; MOVE M,USER VIRTUAL ADDRESS OF IOWD LIST
; MOVE F,ADDRESS OF DEVICE DATA BLOCK
; PUSHJ P,DMPEV
; RETURN HERE IF NO ADDRESS CHECK WITH DEVEVM(F) SETUP
;PRESERVES T1
DMPEV::
PUSHJ P,SAVE4## ;SAVE P1-P4
IFN FTVM,<
PUSH P,U ;SAVE U
MOVEI U,0 ;ASSUME THE DEVICE DOES NOT REQUIRE EXEC VIRTUAL
; MEMORY TO DO I/O (DSK, MTA, TTY, PTY)
>
PUSHJ P,MAPDEV ;NOT A KA10, NEED EVM TO DO I/O?
IFE FTVM,<
POPJ P, ;EVM NOT REQUIRED (KA10, CHANNEL DEVICE, TTY, OR PTY)
>
IFN FTVM,<
TLO U,400000 ;EVM NOT REQUIRED - SET U NEGATIVE
>
PUSH P,T1 ;SAVE DISPATCH ADDRESS
PUSH P,M ;SAVE THE UUO FOR THE DEVICE ROUTINE
SOS M ;COMPENSATE FOR GETWD1
MOVEI P2,0 ;LARGEST WORD COUNT SEEN SO FAR
MOVEI P3,10000 ;GUARD AGAINST A LOOP (GOTO IOWDS)
DMPEV1: PUSHJ P,GETWD1## ;GET AN IOWD
JUMPE T1,DMPEV4 ;JUMP IF LAST IOWD IN THE LIST
HLRO P1,T1 ;THIS IOWD'S WORD COUNT
TLNE T1,-1 ;A GOTO WORD?
JRST DMPEV2 ;NO, A REAL IOWD
HRRI M,-1(T1) ;A GOTO WORD (POINTS TO THE NEXT IOWD)
JRST DMPEV3 ;GET NEXT IOWD
DMPEV2: MOVNS P1 ;P1 = POSITIVE WORD COUNT FOR THIS IOWD
CAMLE P1,P2 ;GREATER THAN THE LARGEST WORD COUNT SEEN SO FAR?
MOVE P2,P1 ;YES, REMEMBER IT AS LARGEST SEEN
IFN FTVM,<
PUSHJ P,CHKHS ;HIGH SEGMENT SAVE?
JRST DMPE2A ;NO
PUSH P,T1 ;YES, SAVE IOWD
PUSHJ P,HSVAD## ;GET START ADR OF HI SEG
POP P,T1 ;RESTORE START ADR OF IOWD
ADDI T1,-1000(T2) ;POINT TO START OF HIGH SEG
DMPE2A: MOVEI T1,1(T1) ;START ADR OF THE IOWD
MOVE T2,P1 ;TOP ADR OF THE IOWD
ADDI T2,-1(T1)
PUSHJ P,TRNGE## ;MAKE SURE THE REQUIRED PAGES ARE IN CORE
>
DMPEV3: SOJG P3,DMPEV1 ;GET NEXT IOWD IN THE LIST
JRST ADRERR## ;TOO MANY IOWDS (PROBABLY A GOTO WORD LOOP,
; STOP THE JOB AND REPORT THE ERROR)
DMPEV4: POP P,M ;RESTORE THE UUO AND THE POINTER TO THE FIRST
; IOWD IN THE LIST
IFN FTVM,<
JUMPL U,DMPEV5 ;DONT ACTUALLY NEED EVM IF U NEGATIVE
>
PUSHJ P,GETWDU## ;GET THE FIRST IOWD IN THE LIST AGAIN
HRRZ T3,T1 ;USER VIRTUAL ADDRESS WHERE I/O WILL START
MOVE T1,P2 ;NUMBER OF WORDS OF EXEC VIRTUAL MEMORY REQUIRED
; TO COVER THE LARGEST IOWD FOUND IN THE IOWD
; LIST
PUSHJ P,GTEVBF ;GET ENOUGH EVM TO COVER THE LARGEST WORD IN
; THE LIST (WAIT UNTIL AVAILABLE IF NECESSARY)
JRST ADRERR## ;WHOOPS! NEVER WILL BE ENOUGH
MOVEM T1,DEVEVM(F) ;DEVEVM = BYTE (18)0(9)EV PAGE #(9)# OF PAGES
IFE FTVM,<
PJRST TPOPJ## ;RESTORE T1 AND RETURN
>
IFN FTVM,<
DMPEV5: POP P,T1 ;RESTORE DISPATCH ADDRESS
JRST UPOPJ## ;RESTORE U AND RETURN
>
;ROUTINE TO RETURN ANY EVM A DEVICE MAY HAVE WHEN A SHARABLE RESOURCE
; WHICH CURRENTLY BELONGS TO THE JOB WHICH HAS THE DEVICE IS GIVEN UP.
;CALLING SEQUENCE:
; MOVE F,ADDRESS OF DEVICE DATA BLOCK OR 0 IF NONE
; PUSHJ P,RTEVM
;ALL ACS ARE RESPECTED.
RTEVM:: SKIPE F ;IS THIS A RESOURCE ASSOCIATED WITH I/O?
; I.E., IS THERE A DEVICE DATA BLOCK?
SKIPN DEVEVM(F) ;DOES THE JOB HAVE EVM?
POPJ P, ;NO, JUST RETURN
PUSHJ P,SAVT## ;IT IS THE TRADITION NOT TO CLOBBER ACS HERE
HRRZ T1,P
CAMG T1,SYSSIZ## ;DON'T CHANGE UBR IF P POINTS TO USER
PUSHJ P,SVEUF ;SAVE THE UBR AND SET IT UP SO CAN ADDRESS CURRENT JOB
PJRST RTNEVM ;GIVE UP EVM FOR MAPPING I/O IF ANY
;HERE TO GIVE UP EVM THAT THIS DEVICE HAS FOR INPUT OPERATIONS
RTEVMI::HLRZ T3,DEVEVM(F) ;USER VIRTUAL ADDRESS OF CURRENT BUFFER
JUMPE T3,CPOPJ## ;ZERO MEANS NO EVM REQUIRED FOR THE I/O
HRLI T3,R ;LITE R IN THE LEFT HALF TO SIGNAL USER
; VIRTUAL ADDRESS
PJRST RTIEVM ;GIVE BACK THE EVM
;HERE TO GIVE UP EVM THAT THIS DEVICE HAS FOR OUTPUT OPERATIONS
RTEVMO::HLRZ T3,DEVEVM(F) ;USER VIRTUAL ADDRESS OF CURRENT BUFFER
JUMPE T3,CPOPJ## ;ZERO MEANS NO EVM REQUIRED FOR THE I/O
HRLI T3,R ;LITE R IN THE LEFT HALF TO SIGNAL USER
; VIRTUAL ADDRESS
PJRST RTOEVM ;GIVE BACK THE EVM
;ROUTINE TO RETURN SLOTS IN THE EXEC MAP USED TO MAP USER BUFFERS
;CALLING SEQUENCE:
;
; MOVE T3,USER VIRTUAL ADDRESS OF BUFFER
; PUSHJ P,RTNEVM
; ALWAYS RETURN HERE
RTNEVM::MOVS T3,DEVEVM(F) ;ANY EVM ALLOCATED TO THIS DEVICE?
JUMPE T3,CPOPJ## ;NO, JUST RETURN
TRNN T3,-1 ;DUMP MODE I/O?
JRST RTNEV1 ;YES, DON'T CLOBBER DEVXAD
HRLI T3,R ;LITE R IN THE LEFT HALF TO SIGNAL THAT
; DEVIAD/DEVOAD NOW CONTAINS A USER VIRTUAL ADDRESS
TLNN S,IO ;OUTPUT?
JRST RTIEVM ;NO, GO RETURN INPUT EVM
RTOEVM::DPB T3,PDVOAD## ;STORE UVA IN DEVOAD
JRST RTNEV1 ;RETURN EVM
RTIEVM::DPB T3,PDVIAD## ;STORE UVA IN DEVIAD
RTNEV1: HRRZ T2,DEVEVM(F) ;PAGE NUMBER AND NUMBER OF PAGES OF EVM
LDB T1,[POINT 9,T2,35]
SETZM DEVEVM(F) ;FLAG NO LONGER ANY EVM
PJUMPN T1,GIVEVM ;RETURN THE EVM TO THE FREE POOL AND TELL
; THE SCHEDULAR THAT EVM IS AVAILABLE IF ANY
; JOB IS WAITING FOR SOME
POPJ P, ;RETURN
;ROUTINE TO CALL THE SCHEDULER AND REMEMBER IF A JOB HAS EVM OR NOT.
; IF SO, RESTORE THE EVM WHEN THE JOB BECOMES RUNNABLE AGAIN.
;PRESERVES ALL ACS
RMEVM:: SKIPE F ;IS THERE A DDB?
SKIPN DEVEVM(F) ;AND DOES IT HAVE EVM?
PJRST WSCHD1## ;NO--JUST RESCHEDULE
TRNE S,IOACT ;DON'T RETURN EVM IF THE DDB
JRST WSCHD1## ; IS I/O ACTIVE
PUSHJ P,RTEVM ;YES--RETURN THE EVM SINCE JOB MAY GET SWAPPED
PUSHJ P,WSCHD1## ;RESCHEDULE
PUSHJ P,SAVT## ;SAVE T2-T4
PJRST RSTEVM ;RESTORE THE EVM
;ROUTINE TO ADVANCE A BUFFER IN EXEC VIRTUAL MEMORY
;CALLING SEQUENCE:
;
; MOVE T3,XWD NEXT BUFFER SIZE,NEXT USER VIRTUAL BUFFER ADDRESS
; RETURN HERE IF NOT ENOUGH PAGES ALLOCATED IN EXEC MAP TO ADVANCE BUFFER
; RETURN HERE - BUFFER ADVANCED
; T1 = EXEC VIRTUAL ADDRESS OF BUFFER
; T3 = USER VIRTUAL ADDRESS OF BUFFER
ADVEVM::PUSH P,T3 ;SAVE BUFFER SIZE,,BUFFER ADDRESS
HRRZ T1,DEVEVM(F) ;BYTE (18)0(9) EXEC VIRTUAL PAGE #(9)# OF EXEC PAGES
HRLM T3,DEVEVM(F) ;STORE UVA OF NEXT BUFFER
HLRZ T2,T3 ;GET BUFFER SIZE
;DON'T NEED TO SUBTRACT 2 SINCE THE BUFFER IS ACTUALLY
; TWO WORDS LONGER THAN THE NUMBER OF DATA WORDS IT CONTAINS
; SUBI T2,2 ;COMPUTE THE UPPER BOUND ON THE NUMBER
IDIVI T2,PAGSIZ##+2 ; OF PAGES WHICH MAY BE REQUIRED TO
ADDI T2,2 ; MAP THIS BUFFER IN EXEC VIRTUAL MEMORY
LDB T3,[POINT 9,T1,35]
CAMLE T2,T3 ;DOES THE DEVICE HAVE A ENOUGH EVM TO MAP THIS BUFFER?
JRST T3POPJ## ;NO, STOP THE I/O (ENOUGH PAGES WILL BE
; AQUIRED THE NEXT TIME AROUND AT UUO LEVEL)
LDB T1,[POINT 9,T1,26]
HRRZS T3,(P) ;T3 = USER VIRTUAL ADDRESS OF THE NEXT BUFFER
SOS T3 ;T3 = ADDRESS OF FIRST WORD OF THE BUFFER
PUSHJ P,MAPUEV ;MAP THE NEXT BUFFER IN THE EXEC MAP
EXCH T3,(P) ;RESTORE THE USER VIRTUAL ADDRESS OF THE
; BUFFER IN CASE I/O MUST BE STOPPED FOR
; SOME OTHER REASON
AOS (P) ;BUMP BUFFER POINTER TO THE LINK WORD
PJRST TPOPJ1## ;T1 = EXEC VIRTUAL ADDRESS OF THE BUFFER
SUBTTL SEGCON - SEGMENT CONTROL MODULE
;ROUTINE TO SAVE THE ABSOLUTE ADDRESS OF A HIGH SEGMENT AND RETURN
; ITS VIRTUAL ADDRESS (CALLED FROM REMAP)
; J=HI SEG NUMBER
; T1=NEW HI SIZE
; T2=WHERE,, NEW LOW SIZE
NEWHGH::PUSHJ P,SAVE3## ;SAVE P1-P3
HRRZ P2,T2 ;SAVE WHERE,,NEW LOW SEGMENT SIZE
HLRZS T2 ;WHERE TO PUT THE HIGH SEGMENT
ANDI T2,777000 ;MAKE SURE ITS ON A PAGE BOUNDARY
JUMPN T2,NEWHG0 ;JUMP IF HIGH SEGMENT STARTING ADDRESS SPECIFIED
TRNE P2,400000 ;IS THE LOW SEGMENT BIGGER THAN 128K?
SKIPA T2,P2 ;YES, HIGH SEGMENT ORIGIN IS FIRST PAGE ABOVE
; THE LOW SEGMENT
MOVEI T2,377777 ;NO, HIGH SEGMENT GOES AT 400000
MOVEI T2,1(T2) ;HIGH SEGMENT ORIGIN (ALSO CLEAR LEFT HALF OF T2)
NEWHG0: MOVE P3,.C0JOB## ;CURRENT JOB NUMBER
MOVEM R,JBTADR##(P3) ;STORE PREVIOUS PROTECTION,,JDAT IN CASE OF ERROR
IFN FTVM,<
MOVEI T3,1(T1) ;NUMBER OF WORDS IN NEW HIGH SEGMENT
MOVEI T1,1(P2) ;ADDRESS WHERE REMAP STARTS
LSHC T1,W2PLSH## ;T1=FROM PAGE, T2=TO PAGE
LSH T3,W2PLSH## ;NUMBER OF PAGES
HLRZ T4,SGAEXT##(R) ;FILE EXTENSION
SUBI T4,'SHR' ;T4=0 IF THE HIGH SEGMENT IS SHARABLE
PJRST NREMAP## ;REMAP IT
>
IFE FTVM,<
JUMPLE T2,CPOPJ## ;DON'T ALLOW HIGH SEGMENT AT PAGE ZERO
HRRZ P1,T1 ;NEW HIGH SEGMENT SIZE
ADDI P1,(T2) ;HIGH SEGMENT SIZE PLUS WHERE IT STARTS
TLNN P1,-1 ;WILL THE END OF THE HIGH SEGMENT BE OUTSIDE
; OF THE USER'S ADDRESSING SPACE? (.GT. 256K)
CAIG T2,(P2) ;OR WILL THE LOW SEGMENT AND HIGH SEGMENT OVERLAP?
POPJ P, ;YES, LOSE
HRLM P2,JBTADR##(P3) ;STORE NEW HIGHEST ADDRESS IN THE LOW SEGMENT
HRLI T1,.VJDT ;EXEC VIRTUAL ADDRESS OF THE VESTIGUAL JOB
; DATA AREA
LSH T2,W2PLSH## ;CONVERT HIGH SEGMENT ADDRESS TO PAGE NUMBER
DPB T2,JBYHSO## ;STORE ORIGIN OF THE HIGH SEGMENT
ROT P2,W2PLSH##-1 ;CONVERT TO PAGE NUMBER AND ODD OR EVEN PAGE
; IN THE HIGH ORDER BIT
TRZ P2,400000 ;DON'T LET BIT 8 OF USER-SPECIFIED
; HISEG ORIGIN SPILL OVER
MOVEI P1,.UPMP(P2) ;ADDRESS OF THE WORD IN THE MAP WHICH CONTAINS
; THE ABSOLUTE PAGE NUMBER OF THE LAST PAGE
; OF THE LOW SEGMENT
HRLI P1,222200 ;ASSUME AN EVEN PAGE NUMBER (I.E., MAPPED BY THE
; LEFT HALF WORD)
SKIPGE P2 ;IS IT EVEN?
HRLI P1,002200 ;NO, ODD - MAPPED BY THE RIGHT HALF WORD
LDB P2,P1 ;GET ABSOLUTE PAGE NUMBER OF LAST PAGE IN
; THE LOW SEGMENT
TRZ P2,760000 ;CLEAR ACCESS BITS
HLLZS PAGTAB(P2) ;INDICATE LAST PAGE IN THE LOW SEGMENT IN PAGTAB
ILDB T2,P1 ;GET THE ABSOLUTE PAGE NUMBER OF THE FIRST
; PAGE IN THE HIGH SEGMENT
DPB T2,JBYHSA## ;STORE IT FOR MAPPING THIS HIGH SEGMENT INTO
; FUTURE USER'S ADDRESSING SPACES
TRO T2,PM.ACC+PM.WRT;ACCESS ALLOWED AND WRITABLE
HRLM T2,.UPMP+.MVJDT ;MAP .VJDT IN THE PER-PROCESS MAP
JRST CPOPJ1## ;GIVE OK RETURN (HIGH SEGMENT WON'T OVERLAP
; LOW SEGMENT
>
;ROUTINE TO MAKE ANY WORD OF ANY JOB ADDRESSABLE
; (IN FACT WRITABLE) BY MAPPING IT THROUGH THE
; PER PROCESS MAP OF THE CURRENT JOB
;CALLING SEQUENCE:
; MOVE T2,USER VIRTUAL ADDRESS TO BE MAPPED
; MOVE J,JOB NUMBER OF JOB CONTAINING THE WORD
; PUSHJ P,MAPWRD
;OR PUSHJ P,MAPHC ;TO MAP JOBHCU
; ... RETURN HERE
;ON RETURN FROM CALL TO MAPWRD T2=EVA OF WORD
;ON RETURN FROM CALL TO MAPHC R=JOBHCU
;MAPHC PRESERVES T2
MAPHC:: PUSH P,T2 ;SAVE T2
IFE FTVM,<
MOVEI T2,0 ;JOB DATA AREA STARTS AT USER 0
>
IFN FTVM,<
MOVSI T2,1 ;UVA OF THE UPMP
>
PUSHJ P,MAPWRD ;MAKE THE JOB DATA AREA ADDRESSABLE
IFE FTVM,<
HRR R,T2 ;RH(R)=EVA OF JOB DATA AREA
>
IFN FTVM,<
HRRI R,.JDAT-.UPMP(T2)
>
JRST T2POPJ## ;RESTORE T2 AND RETURN
MAPWRD::
PUSHJ P,SCPCDB## ;POINT P4 AT THIS CPUSCDB
PUSH P,T2 ;SAVE UVA
ROT T2,W2PLSH##-1 ;CONVERT TO PAGE #/2 - REMAINDER IN HIGH BIT
MOVEI T1,.TEMP(T2) ;T1=ADDRESS OF TEMP. PP SLOT
HRLI T1,222200 ;ASSUME WORD IN EVEN PAGE
SKIPGE T2 ;IS IT?
HRLI T1,002200 ;NO - ODD PAGE
HRRZ T2,JBTUPM##(J) ;ADDRESS OF TARGET JOB'S UPMP
TRO T2,PM.ACC+PM.WRT;INSURE ACCESS ALLOWED
HRRM T2,.UPMP+.MTEMP ;MAKE THE TARGET JOB'S UPMP ADDRESSABLE
CLRPGT (P4) ;CLEAR THE AM SO NEW MAPPING
; IS USED
LDB T2,T1 ;GET MAPPING FOR PAGE CONTAINING WORD
TRO T2,PM.ACC+PM.WRT;MAKE SURE CAN WRITE
HRRM T2,.UPMP+.MTEMP ;MAKE THE WORD ADDRESSABLE
CLRPGT (P4) ;CLEAR THE AM SO NEW MAPPING
; IS IN EFFECT
MOVEI T1,.TEMP/1000 ;PAGE # IN EV ADDRESSING SPACE
DPB T1,[POINT 9,(P),26] ;EVA OF WORD
JRST T2POPJ## ;RESTORE EVA AND RETURN
;ROUTINE TO MAKE AVAILABLE A PAGE MAP SLOT IN EVA SPACE
;MAY ONLY BE CALLED AT INTERUPT LEVEL
;CALLING SEQUENCE:
; MOVE P4,ADR OF CPU DATA BLOCK
; PUSHJ P,MAPLOC
; RETURN HERE
; C(T1) := BYTE PNTR TO EPMP SLOT
; C(T3) := RELATIVE PAGE # IN EPMP
MAPLOC::CONI PI,T1 ;GET PIS IN PROGRESS
ANDI T1,II.IPA ;CLEAR ALL BITS EXCEPT PIS IN PROGRESS
JFFO T1,.+2 ;FIND OUT THE HIGHEST PI IN PROGRESS, I.E.,
; THE ONE THAT THIS CODE IS BEING EXECUTED AT
STOPCD .,STOP,NPP, ;++NO PI IN PROGRESS
; NO PAGE IN THE EXEC MAP FOR MAPPING THE SCAN
SUBI T2,25 ;T2=0-6 FOR PI 1-7 IN PROGRESS
MOVE T3,T2 ;CALCULATE THE EXEC VIRTUAL ADDRESS FOR
LSH T3,P2WLSH## ; USE IN THE SWEEP RELATIVE TO PI TEMPORARIES.
ROT T2,-1 ;DIVIDE BY 2 AND PUT THE REMAINDER IN HIGH ORDER BIT
MOVEI T1,.MERPL(T2)
ADD T1,.CPTOS##(P4) ;T1=ADDRESS IN THE MAP OF SLOT USED FOR SCAN
HRLI T1,(<POINT 18,0,17>) ;ASSUME LEFT HALF WORD
SKIPGE T2 ;IS IT AN ODD PAGE?
HRLI T1,(<POINT 18,0,35>) ;YES, THEN ITS THE RIGHT HALF WORD
POPJ P, ;RETURN
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: MOVE P4,ADR OF CPU DATA BLOCK
; PUSHJ P,@.CPMPS##(P4)
; 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
IFN FTMEMPAR,< ;MEMORY PARITY ANALYSIS
XP PARDLY,5 ;NO. OF SOJ INSTR. TO DELAY SO PARITY CAN BE TESTED
CPIMPS::PUSHJ P,SAVE4## ;SAVE P1-P4 FOR BAD ADR. CONTENTS AND WORKING ACS
PUSHJ P,MAPLOC ;GET EXEC MAP SLOT
PUSH P,T1 ;SAVE BYTE POINTER TO EXEC MAP SLOT
MOVEI P1,0 ;SCAN ALL OF MEMORY STARTING WITH FAST ACS
; FOR CONVENIENCE (KI10 ALWAYS HAS FAST ACS)
MOVEI P3,PM.ACC+PM.WRT
;START AT PAGE 0. PAGE ATTRIBUTES TO ALLOW
; ACCESS AND WRITING (TO ATTEMPT REPAIR BELOW)
LDB T4,[POINT 14,MEMSIZ##,26]
;T4=NUMBER OF PAGES TO SCAN (AVOID NXM)
SKIPA U,[POINT 1,NXMTAB##] ;BYTE POINTER TO TABLE REFLECTING EXISTANT MEMORY
MPSLP1: AOS P3 ;STEP TO NEXT PAGE
SOJL T4,TPOPJ## ;RESTORE T1 AND RETURN IF SCANNED ALL OF MEMORY
ILDB T1,U ;DOES THIS PAGE EXIST?
JUMPN T1,MPSLP1 ;JUMP IF NOT TO AVOID REFERENCING NON-EXISTANT
; PAGE
MOVEI P1,.ERPIL(T3) ;START AT THE BEGINNING OF THE PAGE
DPB P3,(P) ;MAP THE CURRENT PAGE
CLRPGT (P4) ;CLEAR THE ASSOCIATIVE SO THE NEW
; WILL BE USED
MOVEI T2,PAGSIZ## ;NO. OF WORDS TO SCAN BEFORE REMAPPING
IFN FTMONL,<
SKIPE MOFLPG## ;SETTING MEMORY ON-LINE IN PROGRESS?
MOVEI T2,MEMITL## ;YES, ONLY REFERENCE ENOUGH TO BE SURE
; INTERLEAVING IS RIGHT
>
MPSLP2: CONSZ PI,@.CPAPP##(P4) ;APR PI IN PROGRESS (I.E. SCANNING
; AT APR INTERRUPT LEVEL?
TDZA T1,T1 ;YES, DON'T WAIT AT THE SOJG.
MOVEI T1,PARDLY ;NO. OF SOJ TO INSURE PARITY FLAG INT. OR ON
;SPECIAL INSTRUCTION ADDRESS - REFERENCE MEMORY TO SEE IF BAD
XP CPIMPI,MPI+1 ;PC VALUE WHEN APR GETS PARITY INT.
;USED BY APR PI ROUTINE TO MAKE INSTR. SKIP
MPI: SKIP P2,(P1) ;DOES THIS LOC HAVE BAD PARITY (PICKUP IN P2)?
SOJG T1,. ;DELAY HERE SO APR INT. WILL OCCUR WITH
; PC AT A KNOWN PLACE IN MONITOR
JRST [IFN FTMEMNXM,<
TRNN S,UE.PEF
JRST [CONSO APR,IP.NXM
JRST MPSLP4
CONO APR,IP.CNM
JRST MPSLP3]>
CONSO APR,IP.PAR
JRST MPSLP4
CONO PI,XI.CPE
JRST .+1]
;HERE ON BAD WORD FOUND (NXM OR PARITY) - APR OR PI 7 (APR INTERRUPT ADDED 2 TO PC)
IFN FTMEMNXM,<
TRNE S,UE.PEF ;A PARITY ERROR?
>
MOVEM P2,(P1) ;FIX UP BAD PARITY SO THAT NUMBER OF BAD
; PARITY WORDS IN MEMORY IS MINIMIZED. THIS
; DECREASES CHANCES OF NOT DETECTING
; READ-PAUSE-WRITE SITUATION (0 ERRORS)
; BECAUSE ANOTHER BAD WORD IS PRESENT
MPSLP3: MAP T1,(P1) ;GET THE PAGE NUMBER OF THE PAGE WHICH
; CORRESPONDS TO THE EXEC VIRTUAL ADDRESS IN P1
PUSH P,T2
PUSH P,T3 ;SAVE THE POSITION IN THE MAP
PUSH P,T4 ;SAVE # OF PAGES TO SCAN
PUSH P,P1 ;SAVE THE EVA
DPB T1,[POINT 13,P1,26]
; P1=ABSOLUTE ADDRESS OF THE WORD WITH BAD PARITY
PUSHJ P,CPIASN ;CONVERT TO SEG NUMBER, (J), REL ADR (T1)
SETOM T1 ;FLAG ABS. ADR NEITHER IN MONITOR NOR A SEGMENT.
PUSHJ P,PARRBD## ;RECORD BAD DATA (T1=REL ADR, P1=BAD ADR,P2=
; BAD CONTENTS)
POP P,P1 ;RESTORE P1
POP P,T4 ; AND T4
POP P,T3 ; AND T3
POP P,T2 ; AND T2
MPSLP4: SOJLE T2,MPSLP1 ;IF CURRENT PAGE IS FINISHED, MAP THE NEXT PAGE
AOJA P1,MPSLP2 ;STEP TO NEXT ABSOLUTE ADDRESS
> ;STILL IN FTMEMPAR CONDITIONAL
IFN FTMEMPAR!FTLOCK!FTMEMNXM,<
;SUBROUTINE - ABSOLUTE (ADDRESS TO) SEGMENT NUMBER
;CALL: MOVE P1,ABS.ADR(18 BIT FOR KA-10, 22 BIT FOR KI10)
; TLO P1,400000 ;IF VIRTUAL ADDRESS IS NOT REQUIRED
; PUSHJ P,@CP.ASN(P4)
; ERROR RETURN IF NOT IN MONITOR OR A HIGH OR LOW SEGMENT,
; OK RETURN J=0 IF IN MONITOR, OR HIGH OR LOW SEG, T1=REL. ADR
;CAN BE CALLED AT APR PI OR CLK PI(7). CANNOT BE CALLED AT UUO LEVEL
;NOTE: REL ADR. IS NOT VIRTUAL ADR ON HIGH SEGS
; SINCE THAT IS JOB DEPENDENT IF LOW SEG GR 400000
CPIASN::SETZB T2,J ;ASSUME IN MONITOR (JOB 0 NOT A LEGAL JOB #)
LDB T1,[POINT 13,P1,26] ;SET REL. ADR. FROM ABS. ADR IN MONITOR
MOVE T1,PAGTAB(T1)
TLNE T1,MONTRB ;IS THIS A MONITOR PAGE?
JRST CPOPJ1## ;YES, GIVE OK RETURN WITH J=0
MOVE T3,P1 ;SET T3=ABSOLUTE ADDRESS OF ERROR WORD
LSH T3,W2PLSH## ;T3=ABSOLUTE PAGE NUMBER OF PAGE CONTAING BAD WORD
MOVEI T2,JOBMAX## ;SCAN TO SEE IF BAD ADDRESS IS IN A UPMP
AUPLOP: HRRZ T1,JBTUPM##(T2) ;T1=PAGE NUMBER OF THE UPMP
CAIE T1,(T3) ;BAD WORD IN THIS UPMP?
SOJG T2,AUPLOP ;NO, SCAN ALL USER PAGE MAP PAGES
JUMPG T2,CPOPJ1## ;JUMP IF THE PARITY ERROR WAS IN A UPMP
PUSHJ P,SSEUB
;LOOP - SCAN ALL HIGH AND LOW SEGS
ASNLOP: MOVEI T1,0 ;ASSUME PARITY ERROR IS IN PAGE 0 OF THIS SEGMENT
IFN FTVM,<
MOVSI T2,SHRSEG ;SHARABLE SEGMENT BIT
CAILE J,JOBMAX## ;A LOW SEGMENT?
TDNE T2,JBTSTS##(J) ;NO, IS IT SHARABLE
>
SKIPN JBTADR##(J) ;IS THIS JOB OR HIGH SEG IN CORE?
JRST ASNAOJ ;NO, LOOK AT THE NEXT SEGMENT
LDB T2,JBYHSA## ;ASSUME ITS A HIGH SEGMENT
; GET ITS STARTING PAGE NUMBER
CAILE J,JOBMAX## ;IS IT A HIGH SEGMENT?
JRST ASNHGH ;YES
PUSHJ P,STEUB ;NO, MAKE ITS FIRST PHYSICAL PAGE NUMBER ADDRESSABLE
; LOW SEGMENT ADDRESS IN THE UPMP IS
; VALID SINCE PARITY ERROR IS NOT IN A
; UPMP (VERIFIED ABOVE)
LDB T2,JBYLSA## ;STARTING PAGE NUMBER OF LOW SEGMENT
ASNHGH: CAIN T2,(T3) ;IS THIS PAGE THE SAME PAGE WHICH CONTAINED AN ERROR?
JRST ASNFND ;YES, COMPUTE THE RELATIVE ADDRESS OF THE
; WORD WITHIN THE SEGMENT WHICH CONTAINS THE ERROR
HRRZ T2,PAGTAB(T2) ;T2=PAGE NO. OF NEXT PAGE IN THIS SEGMENT
SKIPE T2 ;IS IT THE LAST PAGE IN THIS SEGMENT?
AOJA T1,ASNHGH ;NO, LOOK AT ALL THE PAGES IN THIS SEGMENT
ASNAOJ: CAIG J,JBTMAX## ;LOOKED AT ALL SEGMENTS?
AOJA J,ASNLOP ;NO, LOOK AT NEXT SEGMENT
POPJ P, ;NOT IN MONITOR OR ANY JOB
;HERE TO COMPUTE RELATIVE ADDRESS OF PARITY ERROR BY CONCATINATING RELATE
; PAGE NUMBER AND WORD NUMBER WITHIN THE PAGE
ASNFND: JUMPL P1,CPOPJ1## ;RETURN IF NOT INTERESTED IN VIRTUAL ADR
IFN FTVM,<
CAIG J,JOBMAX## ;A SHARABLE HIGH SEGMENT?
PUSHJ P,PHYPVP## ;NO, CONVERT FROM PHYSICAL TO VIRTUAL PAGE NUMBER
>
LSH T1,P2WLSH## ;MOVE PAGE NUMBER TO PAGE NUMBER FIELD
DPB P1,[POINT 9,T1,35]
; AND WORD NUMBER
JRST CPOPJ1## ;AND GIVE OKAY RETURN
> ;END IFN FTMEMPAR!FTLOCK!FTMEMNXM
IFN FTMEMNXM,<
;SUBROUTINE TO FIX CORE ALLOCATION TABLES AFTER NON-EXISTANT MEMORY
; IS ENCOUNTERED
;CALLING SEQUENCE:
; MAKE NXMTAB REFLECT CURRENT STATE OF MEMORY, GIVE BACK CORE
; BELONGING TO ALL SEGMENTS WHICH OVERLAP NXM, AND
; PUSHJ P,CPINXF ;FIX UP RELEVANT TABLES AND VARIABLES
;RETURNS CPOPJ IF NEW VALUE OF CORMAX .LE. OLD VALUE OF CORMAX (SOME
; JOB MAY BE TOO BIG TO SWAP IN), CPOPJ1 IF ALL IS OK.
CPINXF::PUSHJ P,SAVE2## ;SAVE WORKING ACS
SETZB T1,T2 ;INITIALIZE INDEXS INTO PAGTAB AND NXMTAB
MOVSI T3,400000 ;FIRST BIT TO LOOK AT IN NXMTAB
LDB T4,[POINT 14,MEMSIZ##,26]
MOVSI P1,NXMBIT ;LOOK FOR NON-EXISTANT PAGES
HRROI P2,MPGSIZ## ;DECREASE MAXMAX BY 1 PAGE FOR EACH NON-EXISTANT PAGE SEEN
CPINX1: TDNN P1,PAGTAB(T1) ;PAGE ALREADY MARKED AS NON-EXISTANT?
TDNN T3,NXMTAB##(T2) ;NO, IS IT NON-EXISTANT NOW?
JRST CPINX2 ;NO, FORGE AHEAD
SKIPL PAGTAB(T1) ;IS THIS NON-EXISTANT PAGE ON THE FREE CORE LIST?
STOPCD .,STOP,NPN, ;++NON-EXISTANT PAGE NOT FREE
ADDM P2,MAXMAX## ;DECREASE MAXMAX BY 1 PAGE
HLLM P1,PAGTAB(T1) ;AND MARK THIS PAGE AS NOW NON-EXISTANT
CPINX2: ADDI T1,1 ;NEXT PAGE
ROT T3,-1 ;NEXT BIT POSITION IN NXMTAB
SKIPG T3 ;CROSSED A WORD BOUNDARY?
ADDI T2,1 ;YES, BUMP TO NEXT WORD IN NXMTAB
SOJG T4,CPINX1 ;LOOP OVER ALL PAGES
CPINX3: MOVE T1,PAGPTR## ;POINTER TO THE FREE CORE LIST
JUMPE T1,CPINX5 ;JUMP IF THERE ARE CURRENTLY NO PAGES ON THE FREE LIST
TDNN P1,PAGTAB(T1) ;IS THIS PAGE NOW NON-EXISTANT?
JRST CPINX5 ;NO
MOVE T2,PAGTAB(T1) ;YES, LINK FREE CORE LIST AROUND THE PAGE
HRRZM T2,PAGPTR## ;STORE NEW FIRST PAGE ON THE FREE CORE LIST
SOS CORTAL## ;DECREMENT COUNT OF POTENTIALLY FREE PAGES
SOS BIGHOL## ;DECREMENT COUNT OF FREE PAGES
JRST CPINX3 ;CONTINUE TO LOOK AT PAGES AT THE BEGINNING
; OF THE FREE CORE LIST
CPINX4: MOVE T1,T2 ;CURRENT INDEX INTO PAGTAB
CPINX5: HRRZ T2,PAGTAB(T1) ;NEXT PAGE IN PAGTAB
JUMPE T2,CPINX6 ;JUMP IF THIS IS THE END OF THE FREE CORE LIST
TDNN P1,PAGTAB(T2) ;IS THIS PAGE NOW NON-EXISTANT?
JRST CPINX4 ;NO
HRRZ T2,PAGTAB(T2) ;YES, LINK THE FREE CORE LIST AROUND IT
HRRM T2,PAGTAB(T1) ; ..
SOS CORTAL## ;DECREMENT THE COUNT OF POTENTIALLY FREE PAGES
SOS BIGHOL## ;AND THE COUNT OF FREE PAGES
JRST CPINX5 ;LOOP OVER THE ENTIRE FREE CORE LIST
; STILL IN FTMEMNXM
CPINX6: MOVEI T1,0 ;INITIALIZE COUNT OF EXISTANT UNLOCKED PAGES
MOVE T2,MEMSIZ## ;PREVIOUS HIGHEST ADDRESS + 1
SUB T2,SYSSIZ## ;RANGE OF USERS CORE
LSH T2,W2PLSH## ;NUMBER OF PAGES FROM TOP OF THE MONITOR
; TO THE PREVIOUS TOP OF MEMORY
MOVE T3,SYSSIZ## ;WHERE TO START LOOKING FOR UNLOCKED EXISTANT PAGES
LSH T3,W2PLSH## ;PAGE NUMBER TO START AT
CPINX7: MOVE P1,PAGTAB(T3) ;PAGE DESCRIPTOR BITS FROM PAGTAB
TLNE P1,LKBITS-MONTRB;IS THIS PAGE LOCKED OR NON-EXISTANT?
JRST CPINX8 ;YES, DON'T CONSIDER IT IN COMPUTING NEW CORMAX
MOVEI T4,1(T3) ;HIGHEST EXISTANT PAGE + 1 THAT WAS SEEN
TLNN P1,MONTRB ;IS THIS A MONITOR PAGE?
ADDI T1,PAGSIZ## ;NO, INCREASE NEW CORMAX BY ONE PAGE
CPINX8: ADDI T3,1 ;NEXT PAGE IN PAGTAB
SOJG T2,CPINX7 ;LOOP OVER ALL PAGES
MOVEI T2,PAGTAB-1(T4) ;BYTE POINTER TO HIGHEST PAGE
HRRM T2,CORLST## ;STORE THAT FOR CHKTAL
LSH T4,P2WLSH## ;HIGHEST EXISTANT ADDRESS + 1
MOVEM T4,MEMSIZ## ;STORE THAT AS THE SIZE OF MEMORY
CAML T1,CORMAX## ;NEW CORMAX LESS THAN THE OLD CORMAX?
AOSA (P) ;NO, INDICATE ALL JOBS CAN STILL RUN
MOVEM T1,CORMAX## ;YES, STORE NEW VALUE OF CORMAX AND GIVE
; A NON-SKIP RETURN TO INDICATE THAT SOME
; JOBS MAY BE TO LARGE TO BE SWAPPED IN
POPJ P, ;RETURN
> ;END FTMEMNXM
IFN FTMONL,<
;HERE TO SET MEMORY ON LINE, T1 = FIRST PAGE TO SET ON LINE, T2 = LAST
; PAGE + 1
MEMONL::HRLZ S,T1 ;STARTING PAGE TO SET ON LINE
HRR S,T2 ;HIGHEST PAGE TO SET ON LINE
PUSH P,S ;SAVE THAT
SKIPN JBTADR##(J) ;DOES THIS JOB HAVE CORE?
PUSHJ P,GETMIN## ;NO, GET A MINIMUM AMOUNT FOR PDL, ETC.
JUMPE R,[POP P,(P) ;COULDN'T GET IT THIS TICK
JRST DLYCM##];GO AWAY AND TRY AGAIN NEXT TIME
POP P,S ;RESTORE RANGE OF ADDRESSES TO SET ON LINE
PUSHJ P,SAVCTX## ;SAVE THE JOB'S CONTEXT AND RETURN AT UUO LEVEL
; (THE JOB'S CONTEXT MUST BE SAVED BECAUSE
; IF SETTING THE MEMORY ON LINE CAUSES
; A NXM, THE JOB'S CONTEXT WILL BE DESTROYED)
HLRZ T1,S ;RESTORE THE STARTING PAGE TO SET ON LINE
HRRZ T2,S ;AND THE HIGHEST PAGE TO SET ON LINE
CAIG T2,1000 ;TRYING TO SET MEMORY ON LINE ABOVE 256K?
JRST MEMON5 ;NO, CAN DO THAT WITHOUT CHECKING
IFN FT22BIT,<;HERE IF SETTING MEMORY ON LINE ABOVE 256K TO SEE IF ANY CHANNEL IS IN
; 18 BIT MODE
HLRZ T3,SYSUNI## ;ADDRESS OF THE FIRST UDB IN THE SYSTEM
MEMON1: HRRZ T4,UNICHN##(T3) ;ADDRESS OF THE CHANNEL DATA BLOCK FOR THIS UNIT
SKIPL CHB22B##(T4) ;IS THE CHANNEL IN 22 BIT MODE?
JRST MEMON4 ;NO, CAN ONLY SET UP TO 256K ON LINE
HLRZ T3,UNISYS##(T3) ;ADDRESS OF THE NEXT UNIT DATA BLOCK
JUMPN T3,MEMON1 ;JUMP IF NOT THE LAST
SKIPN T3,CNFMTA## ;ANY MAGTAPES?
JRST MEMON5 ;NO
MEMON2: HLRZ U,TDVUDB##(T3) ;ADDRESS OF THE UDB FOR THIS DDB
HRRZ T4,TDVKDB##(T3) ;ADDRESS OF THE CONTROLLER DB FOR THIS UNIT
HRRZ T4,TKBCDB##(T4) ;ADDRESS OF THE CHANNEL DB FOR THIS CONTROLLER
JUMPE T4,MEMON3 ;JUMP IF NOT A CHANNEL DEVICE
SKIPL CHB22B##(T4) ;IS IT IN 22 BIT MODE?
JRST MEMON4 ;NO, CAN ONLY SET UP TO 256K ON LINE
MEMON3: HLRZ T3,DEVSER(T3) ;ADDRESS OF THE NEXT DDB
JUMPE T3,MEMON5 ;ALL DONE IF THIS IS THE LAST DDB
MOVE T4,DEVMOD(T3) ;DEVICE CHARACTERISTICS
TLNE T4,DVMTA ;IS THIS A MTA DDB?
JRST MEMON2 ;YES, MAKE SURE ALL CHANNELS ARE IN 22 BIT MODE
JRST MEMON5 ;NO, ALL DONE
> ;END FT22BIT
MEMON4: MOVEI T2,1000 ;REDUCE THE HIGHEST PAGE TO SET ON LINE
; TO 256K SINCE SOME CHANNEL IS IN 18 BIT MODE
;STILL IN FTMONL
;HERE WHEN OPR IS REQUESTING .LE. 256K OR IF .GT. 256K, NO DF10 IN
; 18 BIT MODE WAS FOUND
MEMON5: MOVE T3,MEMSIZ## ;CURRENT HIGHEST ADDRESS IN THE MACHINE
MOVE T4,NWCORE## ;HIGHEST ADDRESS THAT CAN BE SET ON LINE
; (CANNOT MAKE PAGTAB AND MEMTAB BIGGER)
LSHC T3,W2PLSH## ;CONVERT TO PAGES
CAMG T3,T4 ;PICK THE BIGGER OF THE TWO AS THE
MOVE T3,T4 ; HIGHEST ADDRESS THAT CAN BE SET ON LINE
TRZE T3,PG.BDY## ;ROUND UP TO A 256K BOUNDARY (IF NOT
ADDI T3,PAGSIZ## ; ALREADY ON A 256K BOUNDARY
CAMG T3,T2 ;IF ASKING FOR MEMORY ON LINE ABOVE THE
; HIGHEST WHICH CAN BE DONE,
MOVE T2,T3 ; SET ON UP TO THE HIGHEST THAT CAN BE DONE
CAML T1,T2 ;LOWEST PAGE ABOVE THE HIGHEST PAGE?
POPJ P, ;YES, NOTHING TO SET ON LINE
MOVE P1,T1 ;LOWEST PAGE TO SET ON LINE
IDIVI P1,^D36 ;COMPUTE BIT POSITION AND WORD NUMBER WITHIN NXMTAB
MOVNI P2,-^D35(P2) ;BIT POSITION BYTE POINTER STYLE
HRLI P1,(POINT 1,0,0);FORM A 1 BIT BYTE POINTER TO NXMTAB
DPB P2,[POINT 6,P1,5]
ADDI P1,NXMTAB## ;BYTE POINTER TO BIT CORRESPONDING TO FIRST PAGE TO SET ON
MOVSI T3,NXMBIT ;BIT INDICATING NON-EXISTANT PAGE
SETZB T4,P2 ;INITIALIZE FIRST AND HIGHEST NON-EXISTANT PAGES SEEN
MOVEI P3,PAGSIZ## ;TO UPDATE MAXMAX ON EACH PAGE SET ON LINE
MEMON6: TDNN T3,PAGTAB(T1) ;IS THIS PAGE NON-EXISTANT?
JRST MEMON8 ;NO, ITS ALREADY ON LINE
ADDM P3,MAXMAX## ;INCREASE THE MAXIMUM VALUE FOR CORMAX
DPB T3,P1 ;INDICATE THAT THIS PAGE EXISTS IN NXMTAB
SKIPN P2 ;SKIP IF NOT THE FIRST PAGE SET ON LINE
MOVE P2,T1 ;REMEMBER THE FIRST PAGE SET ON LINE
JUMPE T4,MEMON7 ;JUMP IF FIRST PAGE
HRRZM T1,PAGTAB(T4) ;LINK PAGES BEING SET ON LINE TOGETHER
MEMON7: MOVE T4,T1 ;REMEMBER LAST PAGE
MEMON8: IBP P1 ;BUMP BYTE POINTER TO NEXT PAGE IN NXMTAB
CAIE T1,-1(T2) ;LOOKED AT THE ENTIRE RANGE OF PAGES TO SET ON LINE?
AOJA T1,MEMON6 ;NO, LOOK AT THE NEXT PAGE
JUMPE P2,CPOPJ## ;RETURN DOING NOTHING IF ALL PAGES WERE ALREADY
; ON LINE
SETZM PAGTAB(T4) ;INDICATE END OF THE LIST OF PAGES SET ON LINE
; STILL IN FTMONL
;HERE WHEN MEMORY HAS BEEN MARKED ON LINE TO ADD ALL PAGES WHICH
; WERE OFF LINE TO THE FREE CORE LIST
MOVE T1,P2 ;FIRST PAGE IN THE LIST OF PAGES SET ON LINE
MOVE P1,T4 ;LAST PAGE FREED
LSH T4,P2WLSH## ;HIGHEST ADDRESS SET ON LINE
ADDI T4,PAGSIZ## ;ADDRESS OF PAGE FOLLOWING HIGHEST SET ON LINE
CAMLE T4,MEMSIZ## ;IS THAT GREATER THAN CURRENT MEMORY SIZE?
MOVEM T4,MEMSIZ## ;YES, SAVE NEW HIGHEST ADDRESS IN MEMORY + 1
MOVE T4,MEMSIZ## ;HIGHEST ADDRESS IN MEMORY + 1
LSH T4,W2PLSH## ;CONVERT TO HIGHEST PAGE
MOVEI T4,PAGTAB-1(T4) ;BYTE POINTER TO HIGHEST PAGE IN MEMORY
HRRM T4,CORLST## ;STORE THAT FOR CHKTAL
PUSHJ P,GVPAGS ;ADD THE PAGES SET ON LINE TO THE FREE CORE LIST
;HERE TO REFERENCE PAGES ADDED TO THE FREE CORE LIST SO IF THEY ARE
; OFF LINE, IT WILL BE DETECTED BEFORE THEY ARE ATTEMPTED TO BE USED
MEMON9: HRRZ T1,P2 ;FIRST PAGE SET ON LINE
IDIVI T1,^D36 ;COMPUTE WORD AND BIT POSITION WITHIN NXMTAB
MOVE T2,BITTBL##(T2) ;MASK CORRESPONDING TO THAT BIT POSITION
TDNE T2,NXMTAB##(T1) ;IS THIS PAGE NOW ON LINE?
JRST MEMO11 ;NO, FORGET IT
HRRZ T3,P2 ;YES, GET PAGE NUMBER
TRO T3,PM.ACC+PM.WRT;ACCESS ALLOWED AND WRITEABLE
HRLM T3,.EPMP##+.MEUPM
CLRPGT (0,.EUPMP) ;FLUSH PAGE TABLE SO NEW MAPPING IS IN EFFECT
;WORRY ABOUT INTERLEAVED MEMORY
XP NXMDLY,PARDLY ;TIME TO WAIT FOR NXM FLAG TO COME UP
MOVEI T3,MEMITL## ;NUMBER OF WAYS MEMORY CAN BE INTERLEAVED
MOVEI T4,NXMDLY ;TIME TO WAIT FOR NXM FLAG TO CAUSE AN IRP.
MOVEM J,MOFLPG## ;FLAG THAT MEMORY BEING SET ON LINE
; NXM AT THIS POINT ISN'T A SERIOUS ERROR
MEMO10: SETZM .EUPMP-1(T3) ;REFRENCE THE PAGE TO MAKE SURE ITS REALLY THERE
SOJG T4,. ;WAIT LONG ENOUGH FOR NXM INTERRUPT TO HAPPEN
MOVEI T4,NXMDLY ; IN CASE IT ISN'T THERE
TDNN T2,NXMTAB##(T1) ;IS THE PAGE STILL ON LINE?
SOJG T3,MEMO10 ;YES, CHECK NEXT WORD OF THE PAGE
; TO INSURE THAT THERE ISN'T AN INTERLEAVING PROBLEM
SETZM MOFLPG## ;NO LONGER CHECKING FOR OFF LINE PAGES
MEMO11: CAIN P2,(P1) ;REFERENCED ALL PAGES IN THE RANGE SET ON LINE?
IFN FTDAEM,<
JRST [MOVE T1,[10,,.ERCSC]
PJRST DAEEIM##];YES, TELL DAEMON CONFIGURATION HAS CHANGED AND RETURN
>
IFE FTDAEM,<
POPJ P, ;IF NO DAEMON, JUST RETURN
>
HRRZ P2,PAGTAB(P2) ;NO, GET THE NEXT PAGE SET ON LINE
JRST MEMON9 ;AND REFERENCE IT TO MAKE SURE ITS THERE
> ;END FTMEMONL
SUBTTL CORE1 - CORE ALLOCATION MODULE
;ROUTINE TO ALLOCATE PHYSICAL CORE IN CORE OR ON THE DISK
;CALLING SEQUENCE:
; MOVE R,XWD PROTECTION,RELOCATION
; MOVE T1,HIGHEST RELATIVE ADDRESS REQUESTED
; PUSHJ P,CORE1A
;ALWAYS SKIP RETURN - R = NEW PROTECTION,,RELOCATION
; R = 0 IF CORE IS ASSIGNED ON THE SWAPPING SPACE
CORE1A::JUMPE R,CORGT0 ;JUMP IF SEGMENT HAS NO CORE IN CORE
HLRZ T3,R ;T3 = CURRENT HIGHEST RELATIVE ADDRESS IN THE SEGMENT
SKIPN T1 ;IS ZERO CORE BEING REQUESTED?
MOVNI T1,1 ;YES, PRETEND -1 AND DEPEND ON BUG IN ASH
; WHICH MAKES -1 = -1 WHEN SHIFTED
SUB T3,T1 ;T3 = NUMBER OF WORDS OF INCREASE OR DECREASE IN
; SEGMENT SIZE
ASH T3,W2PLSH## ;CONVERT TO NUMBER OF PAGES OF INCREASE OR DECREASE
JUMPG T3,CORE1B ;JUMP IF SEGMENT IS GETTING SMALLER
MOVMS T3 ;T3 = NUMBER OF PAGES OF INCREASE
PUSHJ P,FRDCR## ;ARE THERE THAT MANY FREE PAGES AVAILABLE IN CORE?
JRST CORGT7 ;NO, MARK THE SEGMENT AS EXPANDING AND ALLOCATE
; THE REQUIRED NUMBER OF PAGES ON SWAP-IN
PUSH P,T3 ;SAVE THE NUMBER OF PAGES OF INCREASE
PUSHJ P,SCPAGS ;FIND THE LAST PAGE WHICH IS CURRENTLY
; ALLOCATED TO THE SEGMENT
MOVE T2,(P) ;T2 = NUMBER OF PAGES TO ADD TO THE SEGMENT
IFN FTVM,<
ADDM T2,JBTSWP##(J) ;INCREASE IMGIN BY THAT NUMBER OF PAGES
>
PUSHJ P,ADPAGS ;ALLOCATE ENOUGH PAGES TO SATISFY THE REQUEST
POP P,T2 ;RESTORE THE NUMBER OF PAGES OF INCREASE
LSH T2,^D18+P2WLSH##;CONVERT TO NUMBER OF WORDS OF INCREASE IN
; POSITION TO UPDATE CURRENT RELOCATION
ADD R,T2 ;R = NEW PROTECTION,,RELOCATION
JRST CORGT2 ;STORE NEW PROTECTION,,RELOCATION AND CLEAR
; PAGES JUST ADDED TO INSURE SECURITY
CORE1B: JUMPG T1,CORE1C ;REQUESTING 0K CORE IN CORE?
PUSHJ P,SVEUB ;YES, MAY BE FROM THE SWAPPER AND THE UPMP
; IS NOT NECESSARILY ADDRESSABLE SO MAKE SURE IT IS
PUSH P,T3 ;SAVE THE NUMBER OF PAGES OF DECREASE
MOVEI T2,0 ;FIND THE FIRST PAGE OF THE SEGMENT
PUSHJ P,SNPAGS ;T1 = FIRST PAGE TO RETURN TO FREE CORE LIST
JRST CORE1D ;GO RETURN PAGES
CORE1C: LDB T2,[POINT 9,R,8];T2 = THE CURRENT SIZE OF THE SEGMENT IN
; PAGES - 1
SUBI T2,(T3) ;COMPUTE THE RELATIVE PAGE NUMBER OF THE FIRST
; PAGE TO RETURN TO THE FREE CORE LIST
PUSH P,T3 ;SAVE THE NUMBER OF PAGES OF DECREASE
PUSHJ P,SNPAGS ;FIND THE ABSOLUTE PAGE NUMBER OF THE FIRST PAGE
; TO RETURN TO THE FREE CORE LIST
HRRZ T2,PAGTAB(T1) ;T2 = THE LINK TO THE FIRST PAGE TO FREE
HLLZS PAGTAB(T1) ;INDICATE THAT THIS IS NOW THE LAST PAGE
; OF THE SEGMENT
MOVE T1,T2 ;T1 = THE ABSOLUTE PAGE NUMBER OF FIRST PAGE TO FREE
CORE1D: PUSHJ P,GVPAGS ;RETURN FREED PAGES TO THE FREE CORE LIST
IFN FTVM,<
LDB T2,IMGOUT## ;SWAPPER DEALLOCATION?
JUMPN T2,CORE1E ;JUMP IF YES
MOVN T2,(P) ;NUMBER OF PAGES BEING DEALLOCATED
ADDM T2,JBTSWP##(J) ;UPDATE IMGIN TO REFLECT NUMBER OF PAGES ALLOCATED
CORE1E:>
POP P,T2 ;RESTORE THE NUMBER OF PAGES OF DECREASE
LSH T2,^D18+P2WLSH##;CONVERT TO NUMBER OF WORDS OF DECREASE AND
; POSITION TO UPDATE CURRENT RELOCATION
SUB R,T2 ;R = NEW PROTECTION,,RELOCATION
TLC R,-1 ;WERE ALL OF THE PAGES BELONGING TO THE SEGMENT
TLCN R,-1 ; RETURNED TO FREE CORE
SETZB T1,R ;YES, INDICATE SEGMENT HAS NO CORE IN CORE
CAILE J,JOBMAX## ;IS THIS SEGMENT A HIGH SEGMENT?
JUMPE R,CORGT1 ;YES, AND DOES IT STILL HAVE CORE IN CORE?
JUMPN R,CORGT2 ;NO, DOES LOW SEGMENT HAVE CORE IN CORE?
HRRZ T1,JBTUPM##(J) ;NO, RETURN UPMP TO THE FREE CORE LIST
SETZ R, ;INDICATE NO UPMP OR CORE IN CORE
HLLZS JBTUPM##(J)
PUSHJ P,GVPAGS ;GIVE UP THE PAGE ALLOCATED TO THE UPMP
JRST CORGT6 ;STORE R AND RETURN
;HERE WHEN THE SEGMENT IS EXPANDING FROM ZERO (CALLED BY THE SWAPPER AND ABOVE)
CORGET::PUSHJ P,SVEUB ;SAVE UBR ON CALL FROM THE SWAPPER
CORGT0: JUMPE T1,CPOPJ1## ;RETURN IF MULTIPLE CALLS TO RETURN CORE
AOS T2,T1 ;T2 = NUMBER OF WORDS OF CORE REQUIRED TO
; SATISFY REQUEST
LSH T2,W2PLSH## ;T2 = NUMBER OF PAGES REQUIRED
CAIG J,JOBMAX## ;IS THIS A LOW SEGMENT?
CAMGE T2,BIGHOL## ;YES, MUST ALLOCATE A UPMP ALSO
CAMLE T2,BIGHOL## ;NO, IS THERE ENOUGH FREE CORE IN CORE TO
; ACCOMODATE THE REQUEST?
SOJA T1,CORGT7 ;NO, MARK THE SEGMENT AS EXPANDING AND ALLOCATE
; THE REQUIRED NUMBER OF PAGES ON SWAP-IN
IFN FTVM,<
DPB T2,IMGIN## ;STORE THE NUMBER OF PAGES ALLOCATED IN CORE
>
HRLI R,-1(T1) ;R = NEW PROTECTION,,?
PUSHJ P,GTPAGS ;ALLOCATE THE PAGES TO SATIFY THE REQUEST
MOVEI T1,PM.ACC+PM.WRT(T1)
CAILE J,JOBMAX## ;IS THIS A LOW SEGMENT
JRST CORGT1 ;NO, UPMP HAS ALREADY BEEN ALLOCATED
PUSH P,T1 ;SAVE THE PAGE NUMBER OF FIRST PAGE OF THE LOW SEGMENT
MOVEI T2,1 ;ALLOCATE ONE PAGE FOR THE UPMP
PUSHJ P,GTPAGS ;GET ONE PAGE OFF THE FREE CORE LIST
HRRM T1,JBTUPM##(J) ;STORE IT AS THE ADDRESS OF THE UPMP
MOVEI T1,PM.ACC+PM.WRT(T1)
HRLM T1,.EPMP##+.MEUPM
CLRPGT (0,.EUPMP) ;THE UPMP IS NOW MAPPED THROUGH THE EXEC
; MAP. CLEAR THE AM SO THE NEW MAPPING
; WILL BE IN AFFECT
SETZM .EUPMP
MOVE T2,[.EUPMP,,.EUPMP+1]
BLT T2,.EUPMP+PG.BDY## ;ZERO THE ENTIRE UPMP
MOVSI T2,NLUPMP##+.MUPMP ;NOW SETUP THE REST OF THE MAP FROM THE
HRRI T2,.EUPMP+.MUPMP ; PROTOTYPE MAP (NULL JOB'S UPMP)
BLT T2,.EUPMP+NUPMPL##-1
HRLM T1,.EUPMP+.MUPMP;MAP THE UPMP IN THE PER-PROCESS MAP
POP P,T1 ;RESTORE THE MAPPING FOR THE FIRST PAGE OF THE
; LOW SEGMENT
PUSHJ P,STEUB ;MAKE THE UPMP ADDRESSABLE (SET THE UBR TO
; PONIT TO THIS PAGE)
HRLM T1,.UPMP ;STORE THE MAPPING FOR THE FIRST PAGE OF
; THE LOW SEGMENT
HRRM T1,.UPMP+.MJDAT ;AND MAKE THE JOB DATA AREA ADDRESSABLE THROUGH
; THE PER PROCESS MAP
JRST CORGT2 ;CLEAR THE PAGES JUST ALLOCATED
CORGT1: DPB T1,JBYHSA## ;STORE THE STARTING PAGE NUMBER OF THE HIGH SEGMENT
CORGT2: JUMPE R,CORGT6 ;ALL DONE IF THE SEGMENT HAS NO CORE AT THIS POINT
HLRZ T1,R ;T1 = HIGHEST RELATIVE ADDRESS SEGMENT CURRENTLY HAS
HLRZ T2,JBTADR##(J) ;T2 = HIGHEST RELATIVE ADDRESS SEGMENT PREVIOUSLY HAD
JUMPN T2,CORGT3 ;JUMP IF SEGMENT HAD CORE IN CORE
LDB T2,IMGOUT## ;T2 = AMOUNT OF CORE SEGMENT HAD WHEN LAST IN CORE
LSH T2,P2WLSH## ;CONVERT TO NUMBER OF WORDS
SOS T2 ;HIGHEST RELATIVE ADDRESS
CORGT3: CAMG T1,T2 ;CURRENT SEGMENT SIZE GREATER THAN PREVIOUS SIZE?
JRST CORGT5 ;NO, NOTHING TO CLEAR
SUB T1,T2 ;T1 = NUMBER OF WORDS OF INCREASE
ADDI T2,1 ;T2 = NUMBER OF WORDS PREVIOUSLY ALLOCATED THE SEGMENT
LSH T2,W2PLSH## ;CONVERT TO PAGE NUMBER OF LAST PAGE
; PREVIOUSLY ALLOCATED TO THE SEGMENT
IFN FTVM,<
PUSHJ P,ZERHGH## ;IF JOB HAS A NON-SHARABLE HI-SEG
JRST CORGT5 ; ZERO THE CORE DIFFERENTLY
>
IFN FTTIME,<
ADDM T1,CLRWRD## ;INCREASE COUNT OF NUMBER OF WORDS CLEARED
>
PUSHJ P,SNPAGS ;GET THE ABSOLUTE PAGE NUMBER OF THE FIRST
; NEW PAGE (PAGE TO BE CLEARED)
CORGT4: MOVEI T1,PM.ACC+PM.WRT(T1)
HRLM T1,.EPMP##+.MEUPM
CLRPGT (0,.EUPMP) ;THE PAGE IS ADDRESSABLE THROUGH THE EXEC MAP
; CLEAR THE AM SO THE MAPPING WILL BE IN AFFECT
MOVEI T2,.EUPMP+1 ;MAKE A BLT POINTER
HRLI T2,.EUPMP ;SET TO ZERO THE PAGE
SETZM .EUPMP ;ZERO THE FIRST WORD OF THE PAGE
BLT T2,.EUPMP+PAGSIZ##-1
;ZERO THE PAGE
TRZ T1,PM.ACC+PM.WRT;CLEAR THE ACCESS BITS
HRRZ T1,PAGTAB(T1) ;GET THE ABSOLUTE PAGE NUMBER OF THE
; NEXT PAGE OF THE SEGMENT
JUMPN T1,CORGT4 ;IF NOT THE LAST PAGE ZERO IT
CORGT5: HRRI R,.VJDT ;ASSUME A HIGH SEGMENT,.I.E., RH(R) = EVA
; OF THE VESTIGUAL JOB DATA AREA
CAILE J,JOBMAX## ;IS IT A HIGH SEGMENT?
JRST CORGT6 ;NO
HRRI R,.JDAT ;LOW SEGMENT, RH(R) = EVA OF JOB DATA AREA
IFN FTVM,<
MOVEM J,.UPMP+.UPJOB ;SAVE THE JOB NUMBER FOR DEBUGGING AND
; VIRCHK (FOR GIVING BACK HIGH SEG CORE)
>
HLRZM R,JOBREL##(R) ;STORE THE NEW SIZE OF THE LOW SEGMENT FOR THE
; USER SO HE WON'T GET CONFUSED ON EXAMINE COMMAND
CORGT6: SKIPE R ;GETTING CORE?
PUSHJ P,IICLNK## ;YES
SKIPN R ;GIVING UP CORE?
PUSHJ P,DICLNK## ;YES
MOVEM R,JBTADR##(J) ;STORE NEW PROTECTION,,RELOCATION
IFN FTTRACK,<
MOVEM J,LASCOR## ;STORE SEGMENT NUMBER OF LAST SEGMENT CORE
; ALLOCATION WAS DONE FOR FOR DEBUGGING
>
IFN FTVM,<
LDB T1,IMGOUT## ;CORE ALLOCATION FOR THE SWAPPER?
JUMPN T1,CPOPJ1## ;YES, ALL DONE
>
CAMN J,.C0JOB## ;IS THIS THE CURRENT JOB (CORE UUO)?
PUSHJ P,SETREL ;YES, SETUP THE MAP AND SOFTWARE RELOCTATION INFO.
AOS (P) ;GIVE SKIP (OK) RETURN
CAILE J,JOBMAX## ;IS THIS A HIGH SEGMENT?
PJRST CURHGH## ;YES SEE IF CORE WAS ALLOCATED FOR THE HIGH
; SEGMENT WHICH THE CURRENT JOB MIGHT BE SHARING
IFE FTVM,<
CAME J,.C0JOB## ;IS THIS THE CURRENT JOB?
>
IFN FTVM,<
CAMN J,.C0JOB## ;CURRENT JOB?
TLNN R,MPGSIZ## ; OR ONLY ONE PAGE ALLOCATED TO THE CURRENT JOB?
; IF ONLY 1 PAGE SETREL MIGHT NOT CALL MAPLOW
>
PJRST MAPLOW ;NO, SETUP THE MAP FOR E AND D COMMANDS
POPJ P, ;YES, MAP IS ALREADY SETUP
;HERE IF NOT ENOUGH FREE PAGES AVAILABLE IN CORE TO SATISFY REQUEST
; INDICATE JOB IS EXPANDING AND THE REQUIRED NUMBER OF PAGES WILL BE
; ALLOCATED WHEN THE SEGMENT IS NEXT SWAPPED IN
CORGT7:
AOS (P) ;SET FOR SKIP RETURN
PJRST XPAND## ;AND MARK THE JOB AS EXPANDING
;ROUTINE TO SETUP THE PORTION OF THE MAP WHICH MAPS THE
; LOW SEGMENT
;CALLING SEQUENCE:
; MOVE R,LOW SEGMENT PROTECTION,,RELOCATION
; PUSHJ P,MAPLOW
; ... ALWAYS RETURN HERE
MAPLOW:
IFN FTVM,<
LDB T1,JBYLSS## ;HIGHEST PAGE IN THE LOW SEGMENT
ADDI T1,1 ;LOW SEGMENT SIZE
PUSHJ P,CLRWS## ;CLEAR WORKING SET BITS
LDB T1,[POINT 9,R,8];NEW HIGHEST PAGE IN THE LOW SEGMENT
ADDI T1,1 ;NEW LOW SEGMENT SIZE
PUSHJ P,ADJWS## ;SET WORKING SET BITS FOR NEW SIZE
> ;END FTVM
MOVE T1,[POINT 18,.UPMP] ;START AT PAGE ZERO
MOVEI T2,PM.ACC+PM.WRT+PM.PUB ;ACCESSABLE, WRITABLE, AND PUBLIC
LDB T3,JBYLSA## ;FIRST PHYSICAL PAGE IN THE LOW SEGMENT
PUSHJ P,REMAP ;SETUP THE MAP FOR THE LOW SEGMENT
LDB T3,JBYLSS## ;PREVIOUS SIZE
PUSHJ P,ZERMAP ;CLEAR MAP SLOTS NO LONGER A PART OF THE LOW SEGMENT
DPB T2,JBYLSS## ;STORE NEW LOW SEGMENT SIZE
POPJ P, ;AND RETURN
;ROUTINE TO SETUP THE PORTION OF THE MAP WHICH MAPS THE HIGH SEGMENT
;CALLING SEQUENCE:
; PUSHJ P,MAPHGH
; ... ALWAYS RETURN HERE - R = PROTECTION,,RELOCATION OF LOW SEGMENT
SETMAP::SKIPA J,.C0JOB## ;CURRENT JOB NUMBER
REMHGH::TDZA T3,T3 ;NO HIGH SEGMENT NUMBER
MAPHGH::MOVE T3,JBTSGN##(J) ;HIGH SEGMENT NUMBER
PUSHJ P,SVEUB ;MAKE SURE THE JOB IS ADDRESSABLE
PUSHJ P,HSVAD## ;COMPUTE HIGH SEGMENT STARTING AND ENDING ADDRESSES
MOVE T4,T2 ;STARTING ADDRESS
SKIPL R,T3 ;SPY SEGMENT?
HLRZ R,JBTADR##(T3) ;NO, SIZE OF THE REAL HIGH SEGMENT
HRLZS R ;HIGH SEGMENT SIZE,,0
SKIPL JOBHCU##+.JDAT ;SAVE IN PROGRESS?
HRRM T1,JOBHRL##+.JDAT ;YES, DON'T CLOBBER IOWD IN COMPRESSED LOW SEGMENT
IFN FTVM,<
TLNN T3,SHRSEG+SPYSEG ;HIGH SEGMENT SHARABLE?
JUMPN T3,SCWEXO## ;NO, THE MAP IS RIGHT EXCEPT FOR W.E. AND PUBLIC BITS
>
ROT T4,W2PLSH##-1 ;CONVERT STARTING ADDRESS TO PAGE NUMBER/2
MOVEI T1,.UPMP(T4) ;WORD IN THE UPMP WHERE HIGH SEGMENT MAPPING STARTS
HRLI T1,442200 ;ASSUME HIGH SEGMENT STARTS AT AN EVEN PAGE NUMBER
SKIPGE T4 ;DOES IT?
HRLI T1,222200 ;NO, IT STARTS AT AN ODD PAGE NUMBER
MOVEI T2,PM.ACC+PM.WRT;ACCESS ALLOWED PLUS WRITABLE
TLNN T3,GTSSEG ;SEGMENT GETSEGED?
JRST SETM0A ;NO, ALWAYS PUBLIC
IFN FTFDAE,<
MOVSI T4,(JS.FXO) ;FILE DAEMON MADE IT EXECUTE ONLY BIT
TDNE T4,JBTST2##(J) ;IS IT EXECUTE ONLY?
JRST SETM0B ;YES, LEAVE IT CONCEALED
>
MOVE T4,JBTSTS##(J) ;JOB STATUS
TRNE T4,JS.XO ;EXECUTE ONLY?
TLNE T4,JACCT ;IF ALSO JACCT, FORGET ABOUT X.O.
SETM0A: TRO T2,PM.PUB ;JACCT OR NOT EXECUTE ONLY, SO MAKE PAGES PUBLIC
SETM0B: TLNN T3,UWPOFF ;USER WRITE PROTECT OFF?
TRZ T2,PM.WRT ;YES, MAKE THE SEGMENT WRITABLE
JUMPL T3,SETMP1 ;JUMP IF A SPY SEGMENT
LDB T3,[POINT 13,JBTHSA##(T3),35] ;FIRST PHYSICAL PAGE OF THE HIGH SEGMENT
MOVEI T4,PM.ACC+PM.WRT(T3) ;ACCESS ALLOWED PLUS WRITABLE
HRLM T4,.UPMP+.MVJDT ;MAKE THE HIGH SEGMENT VESTIGUAL JOB DATA AREA
; ADDRESSABLE VIA THE PER-PROCESS MAP
PUSHJ P,REMAP ;MAP THE HIGH SEGMENT INTO THE USER'S ADDRESS SPACE
JRST SETMP3 ;CONTINUE
SETMP1: LDB T3,[POINT 9,R,8];SIZE OF THE SPY SEGMENT
TRO T2,PM.PUB ;EXECUTE ONLY SPY SEG DOESN'T WORK
SETMP2: IDPB T2,T1 ;MAP MONITOR ADDRESSES INTO USER'S ADDRESS SPACE
AOS T2 ;STEP TO NEXT MONITOR PAGE
SOJGE T3,SETMP2 ;MAP AS MANY PAGES AS THE USER REQUESTED
SETMP3: LDB T3,JBYHSS## ;PREVIOUS HIGH SEGMENT SIZE
TLNE R,-1 ;IF THE HIGH SEGMENT SIZE ISN'T 0,
SUBI T3,1 ;HIGHEST PAGE IN THE HIGH SEGMENT
PUSHJ P,ZERMAP ;ZERO MAP SLOTS NO LONGER A PART OF THE HIGH SEGMENT
TLNE R,-1 ;IF THERE STILL IS A HIGH SEGMENT
ADDI T2,1 ;COMPUTE NEW NUMBER OF PAGES IN THE HIGH SEGMENT
DPB T2,JBYHSS## ;STORE NEW NUMBER OF PAGES IN THE HIGH SEGMENT
MOVE R,JBTADR##(J) ;LOW SEGMENT SIZE,,VIRTUAL ADDRESS
POPJ P, ;AND RETURN TO THE CALLER
;SUBROUTINE TO SETUP THE USER PAGE MAP PAGE TO REFLECT THE LOCATION
; OF THE PAGES OF A SEGMENT IN PHYSICAL MEMORY
;CALLING SEQUENCE:
; MOVE T1,BYTE POINTER TO THE MAP
; MOVE T2,PAGE ATTRIBUTES
; MOVE T3,ABSOLUTE PAGE NUMBER OF FIRST PAGE OF THE SEGMENT
; PUSHJ P,REMAP
; ... ALWAYS RETURN HERE
REMAP: HLRZ T4,R ;LENGTH - 1 OF THE SEGMENT
JUMPE T4,CPOPJ## ;IF THE SEGMENT IS ZERO LENGTH RETURN
LSH T4,W2PLSH## ;CONVERT TO NUMBER OF PAGES - 1
REMAP1: TRO T3,(T2) ;ABSOLUTE PAGE NUMBER PLUS ACCESS BITS
IDPB T3,T1 ;STORE PHYSICAL LOCATION OF THE PAGE AND
; THE ACCESS BITS IN THE MAP
TRZ T3,(T2) ;CLEAR ACCESS BITS
MOVE T3,PAGTAB(T3) ;GET THE ABSOLUTE PAGE NUMBER OF THE NEXT
; PAGE IN THE SEGMENT
SOJL T4,CPOPJ## ;RETURN IF ALL THE PAGES IN THE SEGMENT
; HAVE BEEN MAPPED
JUMPG T3,REMAP1 ;MAP ALL THE PAGES IN THE SEGMENT
STOPCD .,STOP,PMU, ;++PAGTAB MESSED UP
;ROUTINE TO DETERMINE IF THE SIZE OF A SEGMENT HAS CHANGED SINCE THE LAST
; TIME THE JOB WHOSE ADDRESSING SPACE CONTAINS THIS SEGMENT WAS RUN. IF THE
; SEGMENT IS SMALLER THAN THE IT PREVIOUSLY WAS, THE ROUTINE
; ZEROES THE LOCATIONS IN THE MAP WHICH CORRESPOND TO THE PAGES REMOVED FROM
; THE SEGMENT (OR ALL THE LOCATIONS IF THE SEGMENT WAS REMOVED) SO THE JOB
; WILL PAGE FAIL ON AN ILLEGAL MEMORY REFERENCE
;CALLING SEQUENCE:
; MOVE T3,PREVIOUS SEGMENT SIZE IN PAGES - 1
; MOVE R,JBTADR##(J)
; PUSHJ P,ZERMAP
; ... ALWAYS RETURN HERE - T2 = CURRENT SEGMENT SIZE IN PAGES - 1
ZERMAP: LDB T2,[POINT 9,R,8];CURRENT SIZE OF THE SEGMENT - 1 IN PAGES
SUBI T3,(T2) ;NEW SIZE MINUS OLD SIZE
JUMPLE T3,CPOPJ## ;RETURN IF THE SEGMENT IS THE SAME
; SIZE OR BIGGER THAN IT WAS THE LAST TIME
; THE JOB WAS RUN
MOVEI T4,0 ;ZERO THE MAP TO REFLECT THE NEW SMALLER
ZRMAP1: IDPB T4,T1 ; SEGMENT SIZE SO JOB WILL PAGE FAIL ON AN
SOJG T3,ZRMAP1 ; ILLEGAL MEMORY REFERENCE
POPJ P, ;RETURN
;SUBROUTINE TO RETURN PAGES TO THE LINKED LIST OF FREE PAGES AND UPDATE
; BIGHOL (THE TOTAL NUMBER OF FREE PAGES) AND CORTAL (THE TOTAL NUMBER
; OF FREE PAGES PLUS THE NUMBER OF PAGES OCCUPIED BY
; DORMANT OR IDLE SEGMENTS)
;CALLING SEQUENCE:
; MOVE T1,FIRST PAGE TO RETURN TO THE FREE CORE LIST
; PUSHJ P,GVPAGS
; ALWAYS RETURN HERE
GVPAGS::HRRZS T2,T1 ;T2 = FIRST PAGE TO RETURN (CLEAR ANY JUNK IN LH)
EXCH T1,PAGPTR## ;STORE FIRST PAGE TO FREE AS FIRST PAGE ON THE
; FREE CORE LIST AND GET FIRST PAGE ON CURRENT LIST
MOVEI T3,1 ;AT LEAST ONE PAGE IS BEING RETURNED
GVPAG1: MOVSI T4,FREPAG ;THIS PAGE IS ON THE FREE CORE LIST BIT
TDNE T4,PAGTAB(T2) ;PAGE MUST NOT BE FREE ALREADY
STOPCD .,STOP,ARF, ;++ATTEMPT TO RETURN FREE PAGE
IORB T4,PAGTAB(T2) ;MARK THIS PAGE AS BEING ON THE FREE CORE LIST
; AND GET THE NEXT PAGE TO BE RETURNED
TRNN T4,-1 ;LAST PAGE TO BE RETURNED?
JRST GVPAG2 ;YES, UPDATE BIGHOL AND CORTAL AND RETURN
HRRZ T2,T4 ;INDEX TO NEXT PAGE TO FREE
AOJA T3,GVPAG1 ;COUNT NUMBER OF PAGES FREED AND RETURN NEXT PAGE
GVPAG2: HRRM T1,PAGTAB(T2) ;LINK THE REST OF THE FREE CORE LIST TO THE PAGES
; FREED
ADDM T3,BIGHOL## ;UPDATE THE AMOUNT OF FREE CORE BY THE NUMBER
; OF PAGES FREED
ADDM T3,CORTAL## ;ALSO, UPDATE THE AMOUNT OF POTENTIALLY FREE CORE
POPJ P, ;AND RETURN
;SUBROUTINE TO FIND THE NTH PAGE FOR N.LT.THE NUMBER OF PAGES
; ASSIGNED TO THE JOB OR THE JOBS LAST PAGE
;CALLING SEQUENCE:
; PUSHJ P,SCPAGS ;TO FIND THE LAST PAGE OF THE JOB
;OR
; PUSHJ P,SNPAGS ;TO FIND THE NTH PAGE OF A JOB
; RETURN HERE - T1 = PAGE NUMBER OF THE NTH PAGE
SCPAGS::MOVEI T2,^D511 ;STOP AFTER SCANNING 512 PAGES
SNPAGS::LDB T3,JBYHSA## ;PHYSICAL PAGE NUMBER OF PAGE 0 IN THE LOW SEGMENT
CAIG J,JOBMAX## ;IS THIS A HIGH SEGMENT?
LDB T3,JBYLSA## ;YES, PHYSICAL PAGE NUMBER OF FIRST PAGE OF
; THE HIGH SEGMENT
SNPAG1: HRRZ T1,T3 ;CURRENT PAGE WITHIN THE SEGMENT
SKIPGE T3,PAGTAB(T1) ;GET NEXT PAGE IN THE SEGMENT
STOPCD .,STOP,PSF, ;++PAGE IN SEGMENT FREE
TRNE T3,-1 ;IS THIS THE LAST PAGE IN THE SEGMENT?
SOJGE T2,SNPAG1 ;NO, IS THIS THE NTH PAGE WITHIN THE SEGMENT?
POPJ P, ;YES, RETURN WITH T1 = NTH OR LAST PAGE
;SUBROUTINE TO GET PAGES FROM THE LINKED LIST OF FREE PAGES AND
; UPDATE CORTAL AND BIGHOL
;CALLING SEQUENCE:
; MOVE T1,WHERE TO BEGIN ALLOCATION IF ADDING PAGES
; MOVE T2,NUMBER OF PAGES TO ALLOCATE
; PUSHJ P,ADPAGS ;OR
; PUSHJ P,GTPAGS ;IF NO PAGES ARE CURRENTLY ALLOCATED
; ALWAYS RETURN HERE - T1 = PAGE NUMBER OF FIRST PAGE ALLOCATED
ADPAGS::MOVE T4,PAGPTR## ;FIRST FREE PAGE
HRRM T4,PAGTAB(T1) ;LINK IT TO THE PAGES CONTAINED IN THIS SEGMENT
GTPAGS: SKIPN T1,PAGPTR## ;GET FIRST FREE PAGE
STOPCD .,STOP,PEZ, ;++PAGPTR=0
MOVNS T2 ;MINUS NUMBER OF PAGES BEING ALLOCATED
ADDM T2,BIGHOL## ;DECREASE THE NUMBER OF FREE PAGES BY THAT AMOUNT
ADDM T2,CORTAL## ;AND THE NUMBER OF POTENTIALLY FREE PAGES
MOVE T3,T1 ;FIRST PAGE TO ADD OR GET
GTPAG1: HRRZ T4,T3 ;ALLOCATE THIS PAGE
MOVSI T3,FREPAG ;PREPARE TO MARK THIS PAGE AS IN-USE
SKIPN T4 ;END OF THE FREE CORE LIST?
STOPCD .,STOP,FPI, ;++FREE PAGE INUSE
ANDCAB T3,PAGTAB(T4) ;CLEAR THE BIT INDICATING A FREE PAGE AND GET
; THE NEXT PAGE ON THE FREE CORE LIST
AOJL T2,GTPAG1 ;LOOP UNTIL ALL PAGES REQUESTED ARE ALLOCATED
HRRZM T3,PAGPTR## ;STORE THE NEW FIRST PAGE IN THE FREE CORE LIST
HLLZS PAGTAB(T4) ;INDICATE THAT THIS IS THE LAST PAGE ALLOCATED
; TO THIS SEGMENT
POPJ P, ;AND RETURN TO THE CALLER
SUBTTL SWAP - USER PROGRAM SWAPPING ROUTINES
;SUBROUTINE TO SETUP THE MAP FOR A JOB WHICH WAS JUST SWAPPED IN
; THIS INCLUDES THE TRAP LOCATIONS AS WELL AS THE MAP ITSELF
;CALLING SEQUENCE:
; MOVE J,JOB NUMBER OF JOB JUST SWAPPED IN
; MOVE R,XWD LOW SEGMENT SIZE, EVA OF THE JOB DATA AREA
; SETUP THE USER BASE REGISTER TO POINT TO THIS JOB'S UPMP
; PUSHJ P,MAPUSR
; ALWAYS RETURN HERE
MAPUSR::PUSHJ P,SVEUB ;MAKE THE MAP ADDRESSABLE
MOVE R,JBTADR##(J) ;R=WXD LOW SEGMENT SIZE, ADDRESS OF JOB DATA AREA
MOVE T1,JOBPC##(R) ;JOBS PC
TLNN T1,(XC.USR) ;JOB IN EXEC MODE?
MOVEM R,JOBDPG##(R) ;YES, STORE POSSIBLY UPDATED R IN THE DUMP ACS
IFE FTVM,<
PUSHJ P,MAPLOW ;MAP THE LOW SEGMENT
>
PUSHJ P,MAPHGH ;MAP THE HIGH SEGMENT
MOVE T1,JOBENB##(R) ;GET THE JOBS ENABLE BITS
PJRST SETRP ;SETUP THE TRAP LOCATIONS
SUBTTL SWPSER - SWAPPING SERVICE ROUTINE
;SUBROUTINE TO MAKE THE FIRST WORD OF A SEGMENT ADDRESSABLE FOR JBTCHK
; CALLING SEQUENCE:
; MOVE T1,IOWD USED FOR SWAPPING
; MOVE J,SEGMENT NUMBER OF SEGMENT SWAPPED IN OR OUT
; PUSHJ P,GETCHK
; ALWAYS RETURN HERE
;T1 = EXEC VIRTUAL ADDRESS OF WORD 0 OF THE SEGMENT. IF THIS IS A LOW
; SEGMENT, JUST SETUP THE UBR SINCE T1 CONTAINS THE ADDRESS OF WORD 0
; OF THE SEGMENT MAPPED THROUGH THE PER PROCESS MAP. IF THIS IS A HIGH
; SEGMENT, MAP WORD 0 THROUGH THE EXEC MAP SINCE THE SEGMENT MAY BE
; DORMANT OR IDLE AND THUS NOT APPEAR IN ANY USERS MAP.
GETCHK::CAIG J,JOBMAX## ;IS THIS A HIGH SEGMENT?
JRST SVEUB ;NO, JUST SETUP THE UBR SINCE THE LOW SEGMENT
; IS ADDRESSABLE VIA THE PER PROCESS MAP
LDB T1,JBYHSA## ;GET THE ABSOLUTE PAGE NUMBER OF THE FIRST
; PAGE OF THE HIGH SEGMENT
TRO T1,PM.ACC+PM.WRT;SET ACCESS BITS
HRRM T1,.EPMP##+.MECKS
;MAP WORD 0 IN THE EXEC MAP
CLRPGT (0,.ECKSM) ;FLUSH THE ASSOCIATIVE MEMORY SO THE NEW MAPPING
; WILL BE IN EFFECT
MOVEI T1,.ECKSM ;T1 = EXEC VIRTUAL ADDRESS OF WORD 0 OF THE
; HIGH SEGMENT
POPJ P, ;RETURN
SUBTTL UUOCON - UUO HANDLING ROUTINES
IFN FTDAEM,<
;SUBROUTINE TO DO PROCESSOR DEPENDANT PORTION OF JOB PEEK UUO
;CALLING SEQUENCE:
; HRRI T4,0 IF SOURCE SEGMENT IS A SPY SEGMENT
; MOVE P1,FLAGS,,JOB NUMBER (FLAGS BIT0=0 IF READ, 1 IF WRITE)
; MOVE P2,NUMBER OF WORDS TO TRANSFER
; PUSHJ P,JOBPKD
; ALWAYS RETURN HERE
JOBPKD::PUSHJ P,GETWDU## ;GET SOURCE AND DESTINATION ADDRESSES
MOVSI T2,(XCT 3,) ;ASSUME SOURCE AND TARGET ADDRESSES ARE IN JOB DOING
CAIN J,(P1) ; THE JOBPEK (IF SO BOTH ARE ADDRESSABLE). ARE THEY?
JRST JOBPK3 ;YES, BLT FROM USER TO USER
MOVSI T2,(XCT 2,) ;ASSUME THE SOURCE SEGMENT IS A SPY SEGMENT
TRNN T4,-1 ; I.E., THE MONITOR. IS IT?
JRST JOBPK3 ;YES, BLT FROM MONITOR TO USER
HRRZ T2,JBTUPM##(P1) ;ADDRESS OF THE TARGET JOB'S UPMP
TRO T2,PM.ACC+PM.WRT;ALLOW ACCESS AND WRITING
HRRM T2,.UPMP+.MTEMP ;MAKE THE TARGET JOB'S UPMP ADDRESSABLE
CLRPGT (0,.JBPK) ;CLEAR THE A.M. SO NEW MAPPING IS IN AFFECT
HRRZ T3,T1 ;DESTINATION ADDRESS IF WRITING
TLNN P1,400000 ;WRITING?
HLRZ T3,T1 ;NO, READING. GET SOURCE ADDRESS
TLNE P1,200000 ;READING THE UPMP?
MOVSI T3,1 ;YES, VIRTUAL PAGE NUMBER 1000
MOVE T2,T3 ;GET ADDRESS IN TARGET JOB
ANDI T2,PG.BDY## ;KEEP ONLY REL WD IN PAGE
ADDI T2,PG.BDY##(P2) ;ADD AND ROUND NO. WDS TO TRANSFER
LSH T2,W2PLSH## ;MAKE NO. OF PAGES
LSH T3,W2PLSH## ;CONVERT TO VIRTUAL PAGE NUMBER
MOVNS T2 ;MINUS NUMBER OF PAGES TO MAKE ADDRESSABLE
HRL T2,T3 ;STARTING VIRTUAL PAGE NUMBER IN TARGET JOB
MOVSS T2 ;MAKE AN AOBJN POINTER
ROT T3,-1 ;INDEX INTO TARGET JOB'S MAP (REMAINDER IN HIGH BIT)
MOVEI T4,.TEMP(T3) ;FORM A BYTE POINTER TO THE TARGET JOB'S MAP
HRLI T4,442200 ;ASSUME AN EVEN STARTING PAGE
SKIPGE T3 ;IS IT AN EVEN PAGE?
HRLI T4,222200 ;NO, ODD
MOVEI T3,.UPMP+.MJBPK ;ADDRESS OF JOBPEK TEMPORARY SLOTS IN THE
; PER-PROCESS MAP
HRLI T3,442200 ;STARTING IN THE LEFT HALF WORD
JOBPK0: ILDB P3,T4 ;GET THE ENTRY FROM THE TARGET JOB'S MAP
IFN FTVM,<
TRNE P3,PM.ACC ;ACCESS ALLOWED?
JRST JOBPK1 ;YES, ZOOM ON
JUMPE P3,CPOPJ## ;ERROR RETURN IF PAGE DOESN'T EXIST
CAIN P3,PM.ZER ;ALLOCATED BUT ZERO PAGE?
POPJ P, ;YES, PAGE NOT IN CORE RETURN
HRRZ P3,T2 ;VIRTUAL PAGE WHICH HAS ACCESS ALLOWED OFF
IDIVI P3,^D36 ;WORD IN WSBTAB WHICH CONTAINS BIT FOR THIS PAGE
MOVE P4,BITTBL##(P4) ;BIT POSITION WITHIN THE WORD
TDNN P4,WSBTAB-.UPMP+.TEMP(P3) ;PAGE IN CORE WITH ACCESS ALLOWED OFF?
POPJ P, ;NO, JUST GIVE PAGE NOT IN CORE RETURN
LDB P3,T4 ;GET MAP ENTRY AGAIN
JOBPK1: TRO P3,PM.ACC!PM.WRT ;ALLOW ACCESS
>
IDPB P3,T3 ;STORE IT IN THIS JOB'S PER-PROCESS MAP
AOBJN T2,JOBPK0 ;MAP ENOUGH PAGES TO ALLOW THE TRANSFER
CLRPGT (0,.JBPK) ;CLEAR THE A.M. SO THAT THE NEW MAPPING IS IN AFFECT
MOVEI T2,.JBPK/1000 ;PAGE NUMBER IN THE EXEC VIRTUAL ADDRESS SPACE
TLNE P1,400000 ;READ OR WRITE?
JRST JOBPK2 ;WRITE
DPB T2,[POINT 9,T1,8] ;READ, MAKE SOURCE ADDRESS AN EXEC VIRTUAL ADDRESS
MOVSI T2,(XCT 2,) ;READ FROM EXEC, WRITE TO USER
JRST JOBPK3 ;GO DO THE BLT
JOBPK2: DPB T2,[POINT 9,T1,26] ;WRITING, MAKE DESTINATION AN EXEC VIRTUAL ADDRESS
MOVSI T2,(XCT 1,) ;READ FROM USER, WRITE TO EXEC
JOBPK3: ADDI P2,(T1) ;ENDING ADDRESS EQUALS NUMBER OF WORDS PLUS
; STARTING ADDRESS
HRRI T2,[BLT T1,-1(P2)] ;XCT 1, 2, OR 3 OF A BLT
XCT T2 ;MOVE THE DATA
IFN FTVM,<
AOS (P) ;INDICATE ALL PAGES WERE IN CORE AND THE DATA
; WAS TRANSFERED
>
POPJ P, ;RETURN
>
$LIT
KIEND: END