Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_SRC_3_19910112
-
monitor/getsav.mac
There are 28 other files named getsav.mac in the archive. Click here to see a list.
; UPD ID= 8522, RIP:<7.MONITOR>GETSAV.MAC.3, 9-Feb-88 15:52:26 by GSCOTT
;TCO 7.1218 - Update copyright date.
; *** Edit 7278 to GETSAV.MAC by MRASPUZZI on 31-Mar-86, for SPR #21196
; Make edit 7125 put the JFN only into T1 (instead of fork handle,,JFN)
; Edit 7125 to GETSAV.MAC by MOSER on 12-Aug-85
; FIX XCT ONLY GET BUG
;EDIT 7125 - ALWAYS SET UP T1 FOR CREADF/SREADF FIX XCT ONLY GET
; UPD ID= 2079, SNARK:<6.1.MONITOR>GETSAV.MAC.29, 3-Jun-85 14:38:02 by MCCOLLUM
;TCO 6.1.1406 - Update copyright notice.
; UPD ID= 1147, SNARK:<6.1.MONITOR>GETSAV.MAC.28, 4-Dec-84 10:41:37 by TBOYLE
;TCO 6.1.1070 (QAR 706281) Propogate FH%EPN when SS%EPN used at SSB10+...
; UPD ID= 4857, SNARK:<6.MONITOR>GETSAV.MAC.27, 20-Sep-84 09:16:05 by MOSER
;TCO 6.2220 - FIX ZERO COMPRESSED GET TO NOT CRASH IF BOGUS IOWDS
; UPD ID= 4802, SNARK:<6.MONITOR>GETSAV.MAC.26, 13-Sep-84 16:15:11 by MOSER
;TCO 6.2219 - SAVE ONLY PDVAS WITHIN RANGE OF PAGES SAVED
; UPD ID= 4711, SNARK:<6.MONITOR>GETSAV.MAC.25, 20-Aug-84 11:24:08 by LOMARTIRE
;TCO 6.2160 - Do not allow a GET on SRV:
;Also, fix error handling in previous edit.
; UPD ID= 4685, SNARK:<6.MONITOR>GETSAV.MAC.24, 14-Aug-84 10:11:09 by LEACHE
;In previous edit, leave last process error in T1
; UPD ID= 4632, SNARK:<6.MONITOR>GETSAV.MAC.23, 30-Jul-84 17:17:56 by MCCOLLUM
;TCO 6.2154 - Add ERJMP after PMAP in MAPIT to prevent NOSKTR BUGHLTs.
; UPD ID= 4520, SNARK:<6.MONITOR>GETSAV.MAC.22, 13-Jul-84 19:51:19 by PURRETTA
;Update copyright notice
; UPD ID= 3614, SNARK:<6.MONITOR>GETSAV.MAC.21, 1-Feb-84 09:45:08 by PURRETTA
;TCO 6.1962 - Check for errors returned by DVCHR at GTSVID.
;Make GTSVID return +1 failure, +2 sucess.
; UPD ID= 3488, SNARK:<6.MONITOR>GETSAV.MAC.19, 20-Jan-84 09:33:46 by CJOHNSON
;TCO 6.1902 - Make SSAVE properly fill out the EXE directory page with zeroes
; UPD ID= 2913, SNARK:<6.MONITOR>GETSAV.MAC.18, 20-Sep-83 15:20:32 by LOMARTIRE
;TCO 6.1781 - Do not allow a GET on a TTY or a PTY
; UPD ID= 2863, SNARK:<6.MONITOR>GETSAV.MAC.17, 23-Aug-83 15:37:22 by LOMARTIRE
;TCO 6.1709 - Make SSAVE save empty sections
; UPD ID= 2098, SNARK:<6.MONITOR>GETSAV.MAC.16, 28-Mar-83 17:38:46 by MURPHY
;Minor cleanup -- Change some numeric ACs to symbolic.
; UPD ID= 1646, SNARK:<6.MONITOR>GETSAV.MAC.15, 12-Jan-83 16:36:32 by CHALL.WIZARD
;TCO 6.1458 GET02- Fix CSKBUGs by not calling FUNLK twice on GETE2 error
;Also, create GETE0 and eliminate some literals which use GETE2.
; UPD ID= 1549, SNARK:<6.MONITOR>GETSAV.MAC.14, 21-Dec-82 08:08:57 by MOSER
;TCO 6.1409 - PREVENT FLKTIM-FLKNS
; UPD ID= 1470, SNARK:<6.MONITOR>GETSAV.MAC.13, 22-Nov-82 07:21:58 by GRANT
;TCO 6.1010 - Use MSEC1 instead of IFIW in SAVEB
; UPD ID= 1469, SNARK:<6.MONITOR>GETSAV.MAC.12, 19-Nov-82 14:26:24 by MOSER
;MORE TCO 6.1376
; UPD ID= 1465, SNARK:<6.MONITOR>GETSAV.MAC.11, 18-Nov-82 13:57:41 by MOSER
;TCO 6.1376 - PREVENT FLKTIM-FLKNS
; UPD ID= 167, SNARK:<5.MONITOR>GETSAV.MAC.10, 10-Sep-81 16:41:46 by MURPHY
;In CHKLOD - flush section from page ident before call to MSCANP
; UPD ID= 2211, SNARK:<5.MONITOR>GETSAV.MAC.9, 18-Jun-81 10:16:11 by OSMAN
;tco 5.1373 - Make GET into section 0 of self from section n of self
;work. (merely turn on PM%EPN im MAPIT)
; UPD ID= 1651, SNARK:<5.MONITOR>GETSAV.MAC.8, 5-Mar-81 15:50:57 by OSMAN
;tco 5.1270 - Prevent SAVE from crashing the system
; UPD ID= 1536, SNARK:<5.MONITOR>GETSAV.MAC.7, 9-Feb-81 09:18:35 by OSMAN
;Remove SAVEAC in GTSVIF so that GET% with 0 in lh AC1 returns correct error code
; UPD ID= 1519, SNARK:<5.MONITOR>GETSAV.MAC.6, 5-Feb-81 09:08:17 by OSMAN
;Don't fill in PPC left half in VECSET, since a CONTINUE will crash system
; UPD ID= 1512, SNARK:<5.MONITOR>GETSAV.MAC.5, 3-Feb-81 11:03:37 by OSMAN
;CALL RESPMP before CHKLOD after MAPIT to correctly handle overlay checking
; UPD ID= 1442, SNARK:<5.MONITOR>GETSAV.MAC.4, 15-Jan-81 15:52:52 by FLEMMING
;add code for SMAP/RSMAP
; UPD ID= 1329, SNARK:<5.MONITOR>GETSAV.MAC.3, 1-Dec-80 16:27:58 by OSMAN
;Check for valid section number
; UPD ID= 1293, SNARK:<5.MONITOR>GETSAV.MAC.2, 19-Nov-80 10:15:54 by OSMAN
;Fix high page default
; COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1976, 1988.
; ALL RIGHTS RESERVED.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
; ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE
; INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER
; COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
; OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY
; TRANSFERRED.
;
; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE
; AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT
; CORPORATION.
;
; DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
; SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL.
SEARCH PROLOG
TTITLE GETSAV
;GET AND SAVE ROUTINES
;AC USAGE:
; P5 - PTN OF UPT,,0
; P4 - File status save for execute-only GET
; P3 - UPPER LIMIT PAGE
; P2 - LOWER LIMIT PAGE
; P1 - FORK HANDLE,,JFN (AC1 ARG AFTER CHECKING)
; Q1, Q2, Q3 - Misc.
; F - FLAGS FROM CALL
;If GT%ARG is on in AC1, AC2 points to an argument block, whose contents
;are interpreted as follows:
;ARG+.GFLAG/ flags
; GT%LOW ;low address given
; GT%HGH ;high address given
; GT%BAS ;base given
; GT%CSH ;cache this program
; GT%CCH ;clear program cache
;ARG+.GLOW/ low address, used iff GT%LOW on
;ARG+.GHIGH/ high, used iff GT%HGH on
;ARG+.GBASE/ section to use, used iff GT%BAS on
;FPG0A USED AS WINDOW TO USER SPACE
.GET:: MCENT
TRVAR <CHKPN,CHKQAN,LUS,NGPDVS,<PDVARG,1+.POADE>,PDVBLK,PDVPTR,GHNJFN,DIRPAG,WRKPAG,DIRLPR,DIRCNT,CURPAG,SPCCNT,<ENTVCW,2>,GBASE,OURFGS,ADVSEC,PROPTR,<PSAVEM,4>>
;ENTVCW/ saved entry vector (2 words)
;GBASE/ -1 or base section to load single-section exe file into.
;OURFGS/ our flags.
GTFEXO==1B0 ;Doing execute-only GET
VRPRCF==1B1 ;Process is virgin
;ADVSEC/ first process section found in exe file.
;PROPTR/ pointer to process address space
;PSAVEM/ saved PMAP ac's
MOVX T1,VRPRCF ;Before we know better, process is virgin.
MOVEM T1,OURFGS ;Store initial flags.
SETOM LUS ;No computed section in SETP5 yet
SETOM ADVSEC ;No advertised section from file known yet
XCTU [HRRZ F,T1] ;Get user's flags.
TXZ F,GT%JFN ;KEEP ONLY THE FLAGS
TXZE F,GT%ARG ;ADDITIONAL FLAGS GIVEN?
XCTUU [IOR F,.GFLAG(T2)] ;YES, GET REST OF FLAGS FROM ARG BLOCK
MOVX T4,SC%WHL!SC%OPR ;YES.
TXNN F,GT%ADR ;ALL OF THE ADDRESS SPACE?
TDNN T4,CAPENB ;PRIVILEGED USER?
TXZ F,GT%CSH ;NO. CAN'T ADD TO CACHE THEN
TXNE F,GT%CCH ;CLEAR CACHE?
JRST FLSCSH ;YES, GO DO IT
MOVEI P3,777+FLD(MXSECN,VSECNO)_-9 ;HIGH PAGE DEFAULT IS LARGEST SECTION
MOVEI P2,0 ;LOW PAGE DEFAULT IS 0
TXNE F,GT%ADR ;USER GIVING LIMITS?
JRST [ XCTU [HLRZ P2,2] ;YES, GET THEM
XCTU [HRRZ P3,2]
JRST .+1]
TXNE F,GT%LOW ;LOW ADDRESS GIVEN IN ARG BLOCK?
XCTUU [MOVE P2,.GLOW(T2)] ;YES, GET IT
TXNE F,GT%HGH ;HIGH ADDRESS GIVEN
XCTUU [MOVE P3,.GHIGH(T2)] ;YES, GET IT FROM ARG BLOCK
MOVNI T1,1 ;FIRST ASSUME NO SPECIFIC BASE SECTION
TXNN F,GT%BAS ;GET IT IF GIVEN
JRST GET6 ;NOT GIVEN
XCTUU [SKIPL T1,.GBASE(T2)] ;IT'S GIVEN, PICK IT UP
CAILE T1,MXSECN ;CHECK FOR LEGAL SECTION NUMBER
ITERR (ARGX23) ;"INVALID SECTION NUMBER"
GET6: MOVEM T1,GBASE ;REMEMBER BASE
GET01:
CALL GTSVID ;CHECK PARAMETERS, ETC.
ITERR () ;Failed, return error in T1
MOVE P1,T4 ;COPY JFN
MOVEM T4,GHNJFN ;REMEMBER HANDLE,,JFN
LDB T4,[POINTR T3,DV%TYP] ;GET DEVICE TYPE
CAIE T4,.DVTTY ;IS IT A TTY?
CAIN T4,.DVPTY ;OR A PTY?
ITERR(GETX1) ;YES, ILLEGAL
CAIN T4,.DVSRV ;IS IT SRV:?
ITERR(GETX1) ;YES, THIS IS ALSO ILLEGAL
TXO T2,OF%RD ;Must have READ
TLNN T3,777 ;DISK?
TXO T2,OF%EX ;Yes, request READ and EXECUTE
OPENF ;OPEN FILE FOR INPUT (T1 set up by GTSVID)
JRST GET02 ;Error-- try for just EXECUTE
JRST GET03 ;OK-- Go get the file
; Try to open the file for execute-only access
GET02: MOVE T4,OURFGS ;GET OUR INTERNAL FLAGS
TXNN T4,VRPRCF ;ERROR IF NOT A VIRGIN PROCESS
ITERR
TLNN T3,777 ;Error if not a disk
TXNE F,GT%ADR ;Error if address limits given for execute-only
ITERR
HRRZ T1,P1 ;Get JFN
TXZ T2,OF%RD ;Try to open file without READ (just EXECUTE)
OPENF ; . . .
ITERR () ;If we can't even get EXECUTE, give up now
; File is open for only EXECUTE access
; Try to make process execute-only
CALL FLOCK ;Lock process structure
HLRZ T1,P1 ;Get specified process handle
CALL STJFKR ;Convert RFH to JRFN
JRST GETE0 ;Clean up and give error in AC T1
CALL SETEXO ;Set process as execute-only
JRST [CALL FUNLK ;Process not virgin-- unlock process structure
MOVX T1,VRPRCF ;Remember process is not virgin
ANDCAM T1,OURFGS ;by turning off virgin flag
HRRZ T1,P1 ;Get JFN back
TXO T1,CO%NRJ ;Don't release the JFN yet
CLOSF ;Close the file now
JFCL ; . . .
JRST GET01] ;Re-try the OPENF with READ and EXECUTE
;This time return the OPENF error
CALL FUNLK ;Unlock process structure
; The process is now execute-only
; Now set READ access and the execute-only GET bit (so PMAP works)
NOINT ;Protect the use of READ access and
; the execute-only GET bit
MOVX T1,GTFEXO ;Remember that we are doing all this stuff so
; we can undo it in the end
IORM T1,OURFGS
HRRZ T1,P1 ;Get the JFN
CALL SREADF ;Set READ access and restrict access to this process
MOVE P4,T2 ;Save old state of status
CALL SETGXO ;Enable this process for execute-only GET
; File is open. Check out the process.
GET03: CALL GTGLCK ;GET THE FORK LOCK
MOVE T4,GHNJFN ;GET HANDLE AND JFN FOR GTSVIF
CALL GTSVIF ;Setup PTN in P5
JRST GETE0 ;Clean up and give error in AC T1
; Now do the GET
GET2:
REPEAT 0,< ;OLD FAST GET CODE
CALL TSTFST ;SEE IF A FAST GET CAN BE DONE
SKIPA ;COULDN'T
JRST DONEG ;DID IT. ALL DONE THEN
> ;END OF OLD FAST GET CODE
HRRZ 1,P1 ;JFN
BIN ;GET IOWD COUNT,ADR
ERJMP GETE3 ;FAILED. GO CLEAN UP AND GIVE ERROR RETURN
MOVE Q2,2
HLRZ 2,2
CAIN 2,EXEFIL ;AN EXE FILE?
JRST GETEXE ;YES. GO DO IT THEN
TXNE F,GT%CSH ;DOING SPECIAL GET?
JRST GETE1 ;YES. MUST BE EXE FILE
CAIL 2,1000 ;CHECK FOR SHARE SAVE FILE
CAIL 2,10000
JRST .+2
JRST SGET ;SHARE SAVE
JUMPGE Q2,GET1 ;POSITIVE MEANS END
;FILE IS ZERO-COMPRESSED
ADDI Q2,1
NOINT ;BE NOINT WHILE PAGE MAPPED
CALL GET3 ;SET MAP FOR PAGE
JRST GET5
GET4: TRNN Q2,777 ;JUST CROSSED PAGE BOUNDARY?
CALL GET3 ;YES, REMAP
GET5: JUMPL Q1,[TLNE Q1,(1B1) ;GET A LOAD ERROR?
JRST GETE5 ;YES.
BIN ;NO. USE BIN TO SKIP THIS BLOCK
ERJMP GETE4 ;FAILED. GO CLEAN UP AND GIVE ERROR RETURN
AOBJN Q2,GET4 ;THROW WORD AWAY
JRST GET5A]
HRRZ 2,Q2 ;COMPUTE (NEG) NO. WDS LEFT ON PAGE
ANDI 2,PGSIZ-1
SUBI 2,PGSIZ
HLRE 3,Q2 ;GET (NEG) NO. WDS LEFT IN PTR
JUMPGE T3,[MOVEI T1,GETX1
JRST GETE6] ;NOT NEGATIVE IS BAD FORMAT
CAMGE 3,2 ;GET 'MINIMUM'
MOVE 3,2
PUSH P,3 ;SAVE IT
MOVE 2,Q1 ;CONSTRUCT IFIW FOR @
TXO 2,IFIW
MOVEI 2,@2 ;CONSTRUCT PTR TO DEST
HRLI 2,(<POINT 36,0>)
SIN ;MOVE WORDS TO DEST
ERJMP GETE4 ;FAILED. GO CLEAN UP AND GIVE ERROR RETURN
POP P,2 ;RECOVER STARTING COUNT
SUB 3,2 ;COMPUTE WORDS MOVED
HRL 3,3 ;PUT COUNT IN BOTH HALVES
ADD Q2,3 ;UPDATE AOBJN PTR
JUMPL Q2,GET4 ;LOOP UNLESS PTR EXHAUSTED
GET5A: CALL GET3X ;CLEAN UP MAPPINGS
JRST GET2 ;NEXT BLOCK
;CHECK AND REMAP PAGE
GET3: CALL GET3X ;UNDO PREVIOUS MAPPING IF ANY
NOINT ;BE NOINT WHILE PAGES MAPPED
LDB 2,[POINT 9,Q2,26] ;PAGE NUMBER NEXT REFERENCE
CAMG 2,P3 ;PAGE WITHIN LIMITS?
CAMGE 2,P2
JRST [ MOVSI Q1,(1B0) ;NO, SET FLAG TO PREVENT STORE
RET]
MOVE 1,2 ;PAGE NUMBER
TXNN F,GT%NOV ;WANT TO AVOID OVERLAYS?
JRST GET3N ;NO. GO ON THEN
HLL 1,P1 ;YES. GET FH
RPACS ;GET ACCESS INFO FOR THIS PAGE
TXNN 2,PA%PEX!PA%IND ;DOES THIS PAGE EXIST?
JRST GET3N ;NO. GO ON THEN
MOVSI Q1,(3B1) ;YES. GIVE ERROR
RET ;AND DONE
GET3N: HLL 1,P5 ;GET PTN OF USER PAGE TABLE
MOVE 2,[PTRW+FPG0A]
CALL SETMPG ;SETUP WINDOW TO USER PAGE
MOVE Q1,Q2 ;MAKE @Q1 POINT TO FPG0A
ANDI Q1,777000 ; I.E. FPG0-USERPAGE
MOVN Q1,5
ADDI Q1,FPG0A
HRLI Q1,Q2 ;GIVE IT AN INDEX
HRRZ 1,P1 ;RESTORE JFN TO 1
RET
;UNMAP WINDOW PAGE
GET3X: SETZ 1,
MOVEI 2,FPG0A
CALL SETMPG
OKINT
CALLRET CYGLCK ;CYCLE FORK LOCK AND RETURN
;HERE WHEN READ ENTRY VECTOR WORD (LAST WORD IN FILE)
GET1: HLRZ A,Q2 ;GET LENGTH OF ENTRY VECTOR
HRRZ B,Q2 ;AND ADDRESS
CALL VECSET ;SET THE ENTRY VECTOR
; Common exit for all flavors of GET
DONEG: CALL GETEND ;Clean up file, etc.
JRST MRETN
;ROUTINE TO LOCK THE FORK LOCK WHILE PRESERVING THE INTEGRITY OF THE EXECUTE
;ONLY FORK, IF ANY.
;
;THE FORK LOCK IS LOCKED ALL DURING GET TO PREVENT CALLING FLOCK FROM A LOWER
;LEVEL ROUTINE WHILE NOINT. THE CYGLCK ENTRY IS USED TO UNLOCK THE GET LOCK
;AND RELOCK IT WHICH ALLOWS INTS DURING A GET
CYGLCK: SAVEAC <T1,T2> ;SAVE ACS TRASHED BY SREADF
CALL FUNLK ;UNLOCK FORK LOCK
GTGLCK: MOVE T1,OURFGS ;GET OUR FLAGS
TXNN T1,GTFEXO ;DOING EXECUTE-ONLY GET?
CALLRET FLOCK ;NO JUST LOCK AND RETURN
MOVE T2,P4 ;GET OLD FILE STATUS
HRRZ T1,P1 ;[7125][7278] Get JFN only
CALL CREADF ;RESTORE STATE
CALL CLRGXO ;CLEAR XCT ONLY GET
OKINT ;UNDO NOINT
CALL FLOCK ;GET LOCK WHILE OKINT
NOINT ;NOINT AGAIN
HRRZ T1,P1 ;[7125][7278] Get JFN only
CALL SREADF ;ALLOW READ
CALLRET SETGXO ;SET XCT ONLY GET AND RETURN
;COMMON ROUTINE TO SET THE ENTRY VECTOR
;
;Accepts: A/ length of vector
; B/ address
VECSET: STKVAR <LENES,ADDES>
MOVEM A,LENES
MOVEM B,ADDES ;SAVE LENGTH AND ADDRESS
CALL FLOCK
HLRZ 1,P1 ;FORK HANDLE
CALL SETLFK ;MAP PSB
MOVE B,LENES ;GET LENGTH
MOVEM B,EVLNTH(A) ;STORE IT
MOVE B,ADDES ;GET ADDRESS
MOVEM B,EVADDR(A) ;STORE IT TOO
CALL CLRLFK
CALL FUNLK
RET ;AND DONE
;COMMON SETUP FOR GET, SAVE, SSAVE
; Sets up:
; T4/ User AC1 (XWD process handle, JFN)
; P5/ XWD PTN of process, 0
; T1, T2 for OPENF
; T3/ Device characteristics
GTSVI: STKVAR <<HLDT3,2>,<HLDT1,2>>
CALL GTSVID ;Do device stuff, setup T4, T1, T2, T3
ITERR () ;Failed, return error in T1
DMOVEM T1,HLDT1 ;GTSVIF clobbers ac's
DMOVEM T3,HLDT3 ;SAVE T3,T4 ACROSS CALL
CALL GTSVIF ;Do process stuff, setup P5
ITERR () ;Failed, return error in T1
DMOVE T1,HLDT1 ;RESTORE OPENF JFN AND MODE BITS
DMOVE T3,HLDT3 ;RESTORE T3
RET ;Return from GTSVI
;Setup device stuff: T4, T1, T2, T3
;Returns +1 (error code in T1), +2 (OK)
GTSVID:
UMOVE T4,1 ;SAVE ARG
TRZ T4,770000 ;FLUSH MISC BITS FROM JFN
HRRZ T1,T4 ;JFN
DVCHR ;GET DEVICE CHARACTERISTICS
ERJMP [MOVE T1,LSTERR ;Get error returned by DVCHR
RET] ;Return failure
MOVE T3,T2 ;Move device characteristics
HRRZ T1,T4 ;JFN
MOVSI T2,(^D36B5) ;BYTE SIZE FOR BIN/BOUT XFER
RETSKP ;Sucess, Return +2
;Setup process stuff: P5
;Returns +1 (error code in T1), +2 (OK)
GTSVIF: HLLZ T1,T4 ;Get process handle from call
MOVEI T2,0 ;Convert page number to PC section
CALL FKHPTX ;Convert RFH.0 to PTN.0 and check for execute-only
RET ;Bad process handle-- non-skip return
MOVEM T1,P5 ;Remember the PTN
RETSKP ;Return +2 from GTSVIF
;SETP5 sets the left half of P5 for a particular section
;This routine is clever about not recalculating if not necessary, so
;don't worry about calling it wherever P5 might need updating
;
;Accepts: T1/ section
;
;Returns+1: T1/ error code (all set for ITERR)
;Returns+2: P5 lh/ spt index of page table
SETP5: CAMN T1,LUS ;Have we done calculation yet?
RETSKP ;Yes, nothing to do.
MOVEM T1,LUS ;No, remember which section we're calculating
SETP51: LSH T1,9 ;FKHPTX wants page number
HLL T1,P1 ;Get process handle
MOVEI T2,0 ;Convert page number to PC section
CALL FKHPTX ;Get the info
JRST [ CAIE A,ARGX06 ;Invalid section?
RET ;No, other error, give error return
MOVEI A,0 ;Create private section
HLL B,P1 ;Get correct process to create section in
HRR B,LUS ;Say which section to create
MOVEI C,1 ;One per customer
SMAP% ;Create the section
MOVE T1,LUS ;Get section number again
JRST SETP51] ;Go get new section's index
HLL P5,T1 ;Remember spt index in lf P5
RETSKP
; GETEND - clean up at end of GET
GETEND: MOVE T2,OURFGS ;Get our flags
TXNN T2,GTFEXO ;Doing execute-only GET?
JRST GETEN1 ;No, just close file
MOVE T2,P4 ;Get old file status
HRRZ T1,P1 ;[7125][7278] Get JFN only
CALL CREADF ;Restore state to what it was at OPENF
CALL CLRGXO ;Disable execute-only GET
OKINT ;Now we can be interrupted
GETEN1:
HRRZ T1,P1 ;Get JFN
CLOSF ;Attempt to close file
JFCL ;Can't-- maybe pages still mapped
CALLRET FUNLK ;UNLOCK FORK LOCK AND RETURN
; Errors during GET . . .
;ERROR DURING GET. GO OKINT IF NOW NOINT AND SAVE ERROR CODE
GETE5: MOVEI 1,GETX3 ;SAY OVERLAY ERROR
GETE6: MOVEM 1,LSTERR ;MAKE THIS THE ERROR
GETE4: OKINT ;ALLOW INTERRUPTS
GETE3: MOVE Q1,LSTERR ;GET MOST RECENT ERROR
JRST GETE2 ;GO CLEAN UP AND TAKE ERROR RETURN
;GETE0- USE THE ERROR CODE IN AC T1
;GETE1- UNEXPECTED END OF FILE DURING GET
GETE0: SKIPA Q1,T1 ;GIVE THE ERROR IN AC T1
GETE1: MOVEI Q1,GETX1 ;FORCE RETURN OF ILLEGAL FILE FORMAT ERROR
;AN ERROR OCCURRED. AC Q1 HAS THE ERROR CODE. CLEAN UP AND TAKE ERROR RETURN
GETE2: CALL GETEND ;Close file and clean up
SETZ 1,
MOVEI 2,FPG0A
CALL SETMPG ;ENSURE TEMP PAGE CLEARED
CAIN Q1,IOX4 ;DID WE GET END OF FILE?
ITERR (GETX1) ;YES. RETURN ILLEGAL SAVE FILE FORMAT
MOVE 1,Q1 ;NO. RETURN THE REAL ERROR
ITERR
;THE FILE IS AN EXE FILE. THE FIRST BLOCK MUST BE A DIRECTORY IN
;ORDER FOR CONTROL TO REACH THIS CODE
;DEFINITIONS FOR EXE FILES
EXEEND==1777 ;END OF ALL BLOCKS
EXEFIL==1776 ;BLOCK TYPE FOR DIR AND FOR GETTING
;TO THIS CODE
EXEVEC==1775 ;ENTRY VECTOR BLOCK
EXEPDV==1774 ;PDV BLOCK
EXEWRB==1B2 ;WRITE REQUEST IN FLAG BITS
EXESHR==1B1 ;PAGE IS SHARABLE
EXEZRO==1B3 ;PAGE EXISTS BUT IS ZERO
;BITS IN Q1 REMEMBERED DURING PROCESSING
EXEDIR==1B0 ;SAW A DIRECTORY BLOCK
EXVEC==1B1 ;SAW AN ENTRY BLOCK
NDSK==1B2 ;IF ON, NOT A DISK
;FIELD DEFINITIONS FOR THE BLOCK CONTENTS
DEFSTR(EXADR,,35,27) ;FILE PAGE ADDRESS
DEFSTR(EXSEC,,26,18) ;SECTION NUMBER (I.E. WHICH 256K ADDRESS SPACE)
DEFSTR(EXCNT,,8,9) ;COUNT FIELD
DEFSTR(EXPAG,,35,27) ;PROCESS PAGE ADDRESS
GETEXE: SETZM SPCCNT
MOVX Q1,EXEDIR ;SAW A DIR
MOVEI Q2,0(Q2) ;GET COUNT OF DIR WORDS
SOS Q2 ;DISCOUNT THE HEADER
LSH Q2,-1 ;2 WORDS PER ENTRY
MOVEM Q2,DIRCNT ;NUMBER OF PAIRS
CALL CHECKG ;MUST BE ON DISK
SKIPA ;NOT DISK
JRST DOEN1 ;GO SEE ABOUT DIR ENTRIES
TXNE F,GT%CSH ;SPECIAL GET?
JRST GETE1 ;YES. CAN'T DO IT THEN
NOINT ;MUST BE NOINT FOR REMAINDER OF JSYS
TXO Q1,NDSK ;NOT A DISK
CALL ASGPGS ;GET DIR PAGE
JRST [MOVEI T1,GJFX22 ;JSB MUST BE FULL
JRST GETE6]
MOVEM A,WRKPAG ;REMEMBER SCRATCH PAGE FOR NON-DISK DEVICES
CALL ASGPGS ;GET DIR PAGE
JRST [MOVEI T1,GJFX22 ;JSB MUST BE FULL
JRST GETE6]
MOVEM A,DIRPAG ;SAVE PAGE
SOS A ;LOOPER WORD IS ONE LESS
HRLI A,-1000 ;# OF WORDS
MOVEM A,DIRLPR ;SET UP LOOP VALUE
OKINT ;ALLOW INTS NOW
MOVE B,DIRPAG ;THE DIRECTORY PAGE
HRLI B,(POINT ^D36,) ;MAKE IT A BYTE POINTER
MOVNI C,777 ;REST OF PAGE
CALL SINN ;READ IT IN
MOVEI A,1 ;THE CURRENT PAGE
MOVEM A,CURPAG ;REMEMBER THIS
DOEN1: JUMPE Q2,DOCAT ;IF NO DIR ENTRIES, GO AWAY
;LOOP TO PROCESS ALL OF THE DIRECTORY ENTRIES. EACH ENTRY IS TWO
;WORDS THE FIRST OF WHICH DESCRIBES THE FILE AND THE SECOND,
;DESCRIBING THE PROCESS
DOENT: CALL CYGLCK ;CYCLE FORK LOCK
CALL GTWRD ;GET FILE POINTER
MOVE Q3,B ;SAVE IT
CALL GTWRD ;GET PROCESS POINTER
MOVEM B,PROPTR ;REMEMBER PROCESS POINTER
LOAD A,EXSEC,B ;GET PROCESS DESTINATION SECTION
SKIPGE ADVSEC ;HAVE WE SET UP ADVERTISED SECTION YET?
MOVEM A,ADVSEC ;NO, SO THIS IS IT
CALL FIXSEC ;FIX SECTION NUMBER TO POSSIBLE ALTERNATE MAPPING
STOR A,EXSEC,PROPTR ;MAKE POSSIBLY-MODIFIED PROCESS DESIGNATOR
JE <EXEZRO,EXADR>,Q3,ALLZER ;IF NON-EX, IGNORE IT
SETZ C, ;CLEAR ACCESS BITS
TXO C,PM%RD!PM%EX ;TURN ON READ AND EXECUTE
TXNE Q3,EXEWRB!EXESHR ;WANT SOME FLAVOR OF WRITE?
TXO C,PM%CPY ;YES. GIVE HIM COPY ON WRITE
LOAD A,EXPAG,PROPTR ;GET PROCESS PAGE ADDRESS
LOAD D,EXCNT,PROPTR ;GET REPEAT COUNT
ADD D,A ;CALCULATE LAST PAGE TO AFFECT
MOVE B,A ;GET COPY OF FIRST PAGE IN GROUP
XOR B,D ;COMPARE SECTIONS AT BEGINNING AND END OF RANGE
TXNE B,VSECNO_-9 ;MAKE SURE WE'RE DEALING WITH A SINGLE SECTION
JRST [ MOVEI Q1,GETX5 ;WE DON'T HANDLE SECTION-CROSSING. REASONS:
JRST GETE2]
;1)MSCANP WON'T WORK RIGHT
;2)THE GETX4 CHECK WOULD HAVE TO BE CHANGED
;3)THE SMAP% IN SETP5 WOULD HAVE TO BE MORE CLEVER
;4)RDPAGE WOULD BE SLOWED DOWN BY HAVING TO CALL
; SETP5 IN LOOP INSTEAD OF BEFORE IT
CAML D,P2 ;WITHIN BOUNDS?
CAMLE A,P3 ;?
JRST ALLZER ;NO. DONT LOAD IT THEN
LOAD B,EXADR,Q3 ;STARTING FILE PAGE
CAMLE D,P3 ;VERIFY UPPER BOUND
MOVE D,P3 ;TOO LARGE. USE USER'S
CAMGE A,P2 ;VERIFY LOWER BOUND
CALL [ ADD B,P2 ;TOO LOW. COMPUTE PROPER FILE PAGE
SUB B,A ;""
MOVE A,P2 ;AND USE USER'S LIMIT
RET] ;AND PROCEED
SUB D,A ;GET NEW REPEAT COUNT
AOS D ;ONE MORE FOR GOOD MEASURE
JXE Q3,EXADR,[ SETOM B ;IF ALL ZERO, MAKE DELETE ARG
JRST DOENT0] ;AND PROCEED
TXNE Q1,NDSK ;IS THIS A DISK?
JRST [ CALL NTDISK ;NOT DISK
JRST ALLZER] ;DONE
DOENT0: EXCH A,B ;MAKE ARGS CORRECT
CALL MAPIT ;GET IT MAPPED
JRST GETE0 ;CLEAN UP AND GIVE ERROR IN AC T1
CAMN T1,[-1] ;DOING UNMAP ONLY?
REPEAT 0,< ;OLD FAST GET CODE
JRST [ TXNN F,GT%CSH ;YES. A SPECIAL GET?
JRST ALLZER ;NO. GO ON THEN
MOVE A,D ;YES. GET COUNT
CALL MAKPGS ;MAKE NON-EX POINTERS IN MAP
JRST ALLZER] ;DONE
> ;END OF OLD FAST GET CODE
JRST ALLZER
ADDM D,SPCCNT ;NO. ACCOUNT FOR PAGES
ALLZER: SOSLE DIRCNT ;MORE TO DO?
JRST DOENT ;YES. GO DO THEM
JRST DOCAT ;ALL DONE
;FIXSEC changes a process section that was read from the exe file into the
;process section we really want to load that section into.
;
;Accepts: A/ process section from file
;
;Returns+1: A/ real process section to use instead
FIXSEC: SKIPGE B,GBASE ;Is user relocating a one-section exe file?
RET ;No relocation, so don't change section
CAME A,ADVSEC ;Yes, make sure this file is only one section.
JRST [ MOVEI Q1,GETX4 ;Give error because attempt to relocate multiple sections
JRST GETE2]
MOVE A,GBASE ;Give caller the remapped section
RET
;ROUTINE TO GET NEXT WORD FROM DIRECTORY
GTWRD: TXNE Q1,NDSK ;A DISK?
JRST GTWRD1 ;NO
MOVEI A,0(P1) ;JFN
BIN ;GET ENTRY
ERJMP GETE3 ;FAILURE. GO CLEAN UP AND TAKE ERROR RETURN
RET ;ALL DONE
GTWRD1: MOVE A,DIRLPR ;CURRENT POINTER
AOBJP A,DRBAD ;MORE?
MOVE B,0(A) ;GET DATUM
MOVEM A,DIRLPR ;SAVE POINTER
RET ;AND DONE
;ROUTINE TO GET IN FILE PAGE FOR NON-DISK DEVICE AND TO PUT
;DATA IN PROPER USER'S PAGE
;ACCEPTS:
; A/ FIRST PROCESS PAGE NUMBER
; B/ FIRST FILE PAGE NUMBER
; D/ REPEAT COUNT
NTDISK: STKVAR <FPPN,FFPN,RPTCNT>
;FPPN - First process page number
;FFPN - First file page number
;RPTCNT - Repeat count
MOVEM A,FPPN ;SAVE ARGS
MOVEM B,FFPN ;SAVE B
MOVEM D,RPTCNT
LOAD A,VSECNO_-9,FPPN ;GET SECTION WE'RE LOADING INTO
CALL SETP5 ;CALCULATE ITS INDEX FOR SETMPG
CALL DIRERR ;FAILED, CLEAN UP
CALL CHKLOD ;CHECK FOR OVERLAYS
JRST DIREO3 ;GIVE ERROR BECAUSE THERE ARE CONFLICTS
MOVE B,FFPN ;GET FILE PAGE AGAIN
CAME B,CURPAG ;AT PROPER FILE PAGE?
JRST [ CAMG B,CURPAG ;NO. WANT TO MOVE FORWARD?
JRST DRBAD ;NO. ERROR
SUB B,CURPAG ;GET # OF PAGES TO WASTE
ADDM B,CURPAG ;NEW CURRENT
LSH B,^D9 ;*512
MOVNI C,0(B) ;NEGATIVE COUNT
MOVEI B,B ;DUMMY POINTER
MOVEI A,0(P1) ;JFN
CALL SINN ;GET DATA
JRST .+1] ;GO INLINE
RDPAGE: MOVE A,FPPN ;GET CURRENT PROCESS PAGE
HLL A,P1 ;FORK HANDLE
RPACS ;SEE ABOUT IT
TLNE B,(1B5) ;NON-EX?
TXNE B,PA%WT!PA%CPY ;HAVE WRITE ACCESS?
SKIPA ;YES. ALLOW IT
JRST WASTE ;NO. FORGET IT THEN
TRZ A,VSECNO_-9 ;SETMPG WANTS PAGE MODULO SECTION
HLL A,P5 ;GET PTN OF PROCESS'S UPT
MOVE B,WRKPAG ;GET WORK PAGE
TXO B,PA%WT ;NEED WRITE ACCESS
CALL SETMPG ;DO MAPPING
WASTE: MOVE B,WRKPAG
HRLI B,(POINT ^D36,) ;MAKE IT A POINTER
MOVNI C,1000 ;COUNT
CALL SINN ;GET PAGE
SETZ A, ;FOR THE UNMAP
MOVE B,WRKPAG ;THE PAGE ADDRESS
CALL SETMPG ;UNMAP WORK PAGE
AOS CURPAG ;HAVE STEPPED A PAGE
AOS FPPN ;NEXT PROCESS
AOS FFPN ;NEXT FILE PAGE
SOSG RPTCNT ;MORE?
RET ;NO
JRST RDPAGE ;YES
;ROUTINE TO EXECUTE A SIN AND CHECK FOR EOF AND ERROR
;ACCEPTS:
; B/ BP
; C/COUNT
SINN: MOVEI A,0(P1) ;GET JFN
SIN ;SO THE SIN
ERJMP DIRERR ;FAILED. GO CLEAN UP AND TAKE ERROR RETURN
RET ;OK
;LOOP TO READ THE NEXT BLOCK TYPE AND DISPATCH TO THE PROPER
;ACTION
DOCAT: CALL CYGLCK ;CYCLE FORK LOCK
CALL GTWRD ;GET NEXT DIR WORD
MOVE Q2,B ;SAVE IT
HLRZ B,Q2 ;TYPE
CAIN B,EXEPDV ;PDV BLOCK?
JRST SETPDV ;YES, GO GET PDVAS
CAIN B,EXEVEC ;VECTOR BLOCK?
JRST SETVEC ;YES. GO DO IT
CAIE B,EXEEND ;END OF INFORMATION?
JRST SKPBLK ;NO. UNKNOWN BLOCK
TXNE Q1,EXVEC ;AT THE END. SEEN A VECTOR TYPE YET?
JRST DONEG1 ;YES. ALL DONE THEN
DMOVE A,[EXP 254000,0] ;NO, MAKE UP ONE
CALL VECSET ;AND GO SET IT
DONEG1: TXNE F,GT%CSH ;DOING A SPECIAL GET?
CALL FSTENT ;YES. MAKE ENTRY IN CACHE THEN
TXNN Q1,NDSK ;A DISK?
JRST DONEG ;YES. ALL DONE
MOVE A,WRKPAG ;NO. RELEASE STORAGE
NOINT ;PROTECT STRUCTURES
CALL RELPGS ;RELEASE
MOVE A,DIRPAG ;THE OTHER PAGE
CALL RELPGS
OKINT ;ALLOW INTS
HRRZ A,P1 ;GET JFN
MOVEI B,.MOFWF ;SPACE FORWARD OVER TAPE MARK
MTOPR
ERJMP .+1 ;DONT CARE ABOUT ERRORS
JRST DONEG ;AND DONE
;UNKNOWN BLOCK TYPE. SKIP THE BLOCK
SKPBLK: MOVEI D,-1(Q2) ;NUMBER TO SKIP
JUMPE D,DOCAT ;IF NONE, ALL DONE
CALL GTWRD ;GET ONE
SOJG D,.-1 ;DO ALL
JRST DOCAT ;NO. GET NEXT CATEGORY
;ERROR OCCURRED IN READING THE FILE. SAVE ERROR CODE IN AC Q1 AND GO
;CLEAN UP
DRBAD: MOVEI Q1,GETX1 ;Say invalid file format
JRST DIREO1 ; . .
DIREO3: SKIPA Q1,[GETX3] ;SAY HAD OVERLAY ERROR
DIRERR: MOVE Q1,LSTERR ;GET LAST ERROR
;AN ERROR OCCURRED DURING READING OF THE FILE. AC Q1 CONTAINS THE ERROR CODE.
;CLEAN UP AND TAKE ERROR RETURN
DIREO1: MOVE A,WRKPAG ;FREE WORK PAGE
NOINT ;PROTECT STRUCTURES
CALL RELPGS
MOVE A,DIRPAG ;FREE DIR PAGE
CALL RELPGS ;FREE THIS ONE TOO
OKINT ;ALLOW INTS
JRST GETE2 ;AND GO ERROR OUT
;SETPDV handles a PDV block encountered in the file. The PDVAs are
;added to the process's PSB.
SETPDV: HRRZ T2,Q2 ;ISOLATE LENGTH OF BLOCK
SOJ T2, ;GET NUMBER OF PDVAS AVAILABLE
HRRZM T2,NGPDVS ;REMEMBER HOW MANY
HRRZM T2,.POCT2+PDVARG ;STORE FOR PDVOP% JSYS
AOJ T2, ;LEAVE ROOM FOR HEADER
NOINT ;DON'T ALLOW INTERRUPTS WHILE FREE SPACE TIED UP
CALL ASGJFR ;GET SOME FREE SPACE FOR STORING PDVAS
CALL [ MOVEI Q1,MONX02 ;FAILED, PRESUMABLY BECAUSE JSB FULL
JRST GETE2]
MOVEM T1,PDVBLK ;REMEMBER ADDRESS OF BLOCK
MOVEM T1,PDVPTR ;REMEMBER POINTER TO WHERE NEXT PDVA GOES
AOJ T1, ;STEP TO WHERE FIRST PDVA WILL BE PUT
MOVEM T1,.PODAT+PDVARG ;TELL PDVOP% WHERE DATA BLOCK IS
SETPD1: SOSGE NGPDVS ;ANY MORE PDVAS TO BE READ IN?
JRST SETPD2 ;NO
CALL GTWRD ;YES, GET NEXT ONE
AOS A,PDVPTR ;STEP POINTER TO WHERE IT GOES
MOVEM B,(A) ;STORE THIS PDVA
LOAD A,VSECNO,B ;GET SECTION NUMBER
CALL FIXSEC ;CHANGE IT IN CASE NEEDED
STOR A,VSECNO,@PDVPTR ;STORE UPDATED SECTION NUMBER
JRST SETPD1 ;LOOP TO READ IN ALL OF THEM
SETPD2: MOVEI T1,.PODAT+1 ;GET LENGTH OF ARGUMENT BLOCK
MOVEM T1,.POCT1+PDVARG
HLRZ T1,GHNJFN ;GET FORK WHOSE PDVAS ARE BEING SET
MOVEM T1,.POPHD+PDVARG
MOVEI T1,.POADD ;TELL PDVOP% TO ADD THESE PDVAS
MOVEI T2,PDVARG ;TELL IT WHERE ARG BLOCK IS
PDVOP% ;SET THE PDVAS
ERJMP [MOVE T2,PDVBLK ;FAILED, GET ADDRESS OF FREE SPACE BLOCK
MOVEI T1,JSBFRE ;SAY WHICH POOL
CALL RELFRE ;RELEASE THE FREE SPACE
MOVE Q1,LSTERR ;GIVE WHATEVER ERROR PDVOP% DID
JRST GETE2]
MOVE T2,PDVBLK ;RELEASE FREE SPACE STORAGE
MOVEI T1,JSBFRE
CALL RELFRE
OKINT ;ALLOW INTERRUPTS AGAIN
JRST DOCAT ;GET TO NEXT PART OF EXE FILE
;ROUTINE TO SET THE ENTRY VECTOR FROM AN EXE VECTOR BLOCK
SETVEC: TXOE Q1,EXVEC ;SEEN ONE YET?
JRST GETE1 ;YES. BOMB HIM THEN
HRRZ B,Q2 ;GET COUNT
CAIGE B,3 ;PROPER TYPE?
JRST SKPBLK ;NO. FORGET IT THEN
PUSH P,B ;SAVE THE COUNT
CALL GTWRD ;GET NUMBER OF WORDS IN ENTRY VECTOR
MOVE Q2,B ;THE COUNT
CALL GTWRD ;GET ADDRESS OF ENTRY VECTOR
MOVE A,Q2 ;GET LENGTH AND ADDRESS IN A AND B
DMOVEM A,ENTVCW ;SAVE ENTRY VECTOR
LOAD A,VSECNO,1+ENTVCW ;GET SECTION NUMBER FROM FILE'S ENTRY VECTOR
CALL FIXSEC ;GET SECTION WHERE THIS EXE FILE IS BEING PUT
STOR A,VSECNO,1+ENTVCW ;MAKE REAL ENTRY VECTOR
DMOVE A,ENTVCW ;GET VECTOR BEING STORED
CALL VECSET ;SET IT IN THE PROCESS
POP P,Q2 ;RESTORE THE COUNT
MOVEI Q2,-2(Q2) ;GET COUNT MINUS TWO
JRST SKPBLK ;SKIP THE REST
;ENCOUNTERED CODE FOR SHARED SAVE. EACH PAGE TO BE PUT IN THE
;FORK IS INDICATED BY ONE WORD WHERE:
; B0-8: ACCESS BITS, B0=WRITE COPY
; B9-17: FORK PAGE NUMBER TO RECEIVE PAGE
; B18-35: FILE PAGE NUMBER OF SOURCE PAGE
;IN ORDER TO USE THE MULTI-PAGE PMAP AND SAVE TIME, THIS
;ROUTINE SCANS THE INPUT FOR SUCCESSIVE FORK/FILE PAGES AND
;DOES AS MANY AS POSSIBLE WITH EACH PMAP
SGET: CAIE 2,1000 ;CORRECT TYPE NUMBER?
JRST GETE1 ;NO, STRANGE FILE
MOVEI Q3,0(Q2) ;SAVE COUNT
CALL CHECKG ;MAKE SURE IS DISK
JRST [MOVEI Q1,SSAVX1 ;MUST BE DISK
JRST GETE2] ;RETURN ERROR
HRRZ 1,P1 ;JFN
SGT5: BIN ;GET FIRST WORD
ERJMP GETE3 ;FAILED. GO CLEAN UP AND TAKE ERROR RETURN
SGT4: CALL SGCHKL ;CHECK LIMITS
JRST [ SOJG Q3,SGT5 ;NOT WITHIN LIMITS, SKIP PAGE
JRST GET2] ;COUNT DONE
PUSH P,2 ;SAVE FIRST WORD OF THIS GROUP
PUSH P,2 ;SAVE COPY OF IT FOR INCREMENTING
JRST SGT2 ;ENTER LOOP TO SCAN FOR SEQUENTIAL PAGES
;GET NEXT INPUT WORD, SEE IF BOTH FORK AND FILE PAGE ARE 1
;BEYOND LAST INPUT WORD
SGT1: CALL CYGLCK ;CYCLE FORK LOCK TO ALLOW INTS
BIN
ERJMP GETE3 ;FAILED. GO CLEAN UP AND TAKE ERROR RETURN
CAMN 2,0(P) ;THIS PAGE SAME AS EXPECTED ONE?
CALL SGCHKL ;AND WITHIN LIMITS?
JRST SGT3 ;NO, MUST GO DO PREVIOUS INPUT
SGT2: MOVE 2,[1,,1] ;BUMP FORK AND FILE PAGE NUMBERS
ADDM 2,0(P)
SOJG Q3,SGT1 ;COUNT TOTAL PAGES
POP P,4 ;COUNT DONE, ALL INPUT NOW READ
POP P,2 ;RECOVER FIRST WORD OF GROUP
SUBI 4,0(2) ;COMPUTE COUNT OF PAGES IN GROUP
CALL SGTDO ;DO PMAP
JRST GETE0 ;CLEAN UP AND GIVE ERROR IN AC T1
JRST GET2 ;CONTINUE WITH FILE
SGT3: POP P,4 ;RECOVER INCREMENTED PAGE NUMBERS
EXCH 2,0(P) ;RECOVER FIRST WORD OF GROUP, SAVE NEXT
SUBI 4,0(2) ;COMPUTE COUNT OF PAGES IN GROUP
CALL SGTDO ;DO PMAP
JRST GETE0 ;CLEAN UP AND GIVE ERROR IN AC T1
POP P,2 ;RECOVER LAST INPUT
HRRZ 1,P1 ;RESTORE JFN
JRST SGT4 ;GO START SCAN OF NEXT GROUP
;ROUTINE USED BY ABOVE TO SETUP AND DO PMAP
SGTDO: MOVEI 1,0(2) ;FILE PAGE NUMBER
LDB 3,[POINT 9,2,8] ;ACCESS
LDB 2,[POINT 9,2,17] ;MEMORY PAGE
ROT 3,-^D9
TLZE 3,(1B0) ;WRITE COPY REQUEST?
TLO 3,(PM%CPY) ;YES, SET APPROPRIATE BITS
;ENTRY FOR EXE FILES
MAPIT: CALL SAVPMP ;SAVE PMAP ARGS
LOAD A,VSECNO_-9,B ;GET SECTION NUMBER
CALL SETP5 ;UPDATE CORRECT INDEX FOR MSCANP IN CHKLOD
RETBAD ;FAILED, RETURN ERROR
CALL RESPMP ;CHKLOD NEEDS PMAP ARGS
CALL CHKLOD ;SEE IF OVERLAY CHECKS WANTED
RETBAD (GETX3) ;YES. AND IT DID
CALL RESPMP ;RESTORE PMAP ARGS
SKIPL T1 ;DOING DELETE?
HRL 1,P1 ;NO, JFN TO LH
HLL 2,P1 ;FORK HANDLE TO LH
HRRI 3,0(4) ;COUNT OF SUCCESSIVE PAGES TO DO
TXO 3,PM%CNT!PM%EPN ;SAY DO MULTIPLE PAGES, GLOBAL PAGE NUMBER
TXNE F,GT%PRL ;WANT PRELOADING?
TXO T3,PM%PLD ;YES. TURN ON BIT FOR PMAP
; TXNE F,GT%CSH ;DOING SPECIAL GET?
; TXO T3,PM%IND ;YES. REQUEST INDIRECT POINTERS THEN
PMAP
ERJMPR R ;IF PMAP GENERATES ITRAP, RETURN NICELY
RETSKP
;SAVPMP and RESPMP are for saving and restoring the PMAP args
SAVPMP: DMOVEM A,PSAVEM
DMOVEM C,2+PSAVEM
RET
RESPMP: DMOVE A,PSAVEM
DMOVE C,2+PSAVEM
RET
;LOCAL ROUTINE TO CHECK PAGE AGAINST LIMITS
SGCHKL: LDB 3,[POINT 9,2,17] ;GET PAGE NUMBER
CAMG 3,P3 ;TOO HIGH?
CAMGE 3,P2 ;OR TOO LOW?
SOS 0(P) ;YES, CAUSE FAIL RETURN
RETSKP
;LOCAL ROUTINE TO VERIFY FILE IS FROM DISK
CHECKG: HRRZ 1,P1 ;JFN
DVCHR
TLNE 2,777 ;DISK FILE?
RET ;NO
RETSKP ;YES
;LOCAL ROUTINE TO CHECK FOR OVERLAYS
;
;Accepts: T2 rh/ page number
; T4 rh/ number of pages
;
;Returns+1: some conflicts exist
; +2: no conflicts (all pages in range are nonexistent) or don't care
CHKLOD: TXNN F,GT%NOV ;WANT TO PREVENT OVERLAYS?
RETSKP ;NO. RETURN GOOD AND ALLOW MAP
MOVEM T2,CHKPN ;REMEMBER ARGS
MOVEM T4,CHKQAN
MOVE T1,CHKPN ;STARTING PAGE IN PROCESS
ANDX T1,LPGNO_-9 ;ONLY LOCAL PAGE NUMBER HERE
HLL T1,P5 ;PTN OF THE PROCESS
HRRZ T2,CHKQAN ;GET NUMBER OF PAGES
CALL MSCANP ;SEE IF ANY EXIST IN THIS RANGE
JUMPN 2,R ;YES. ERROR THEN
RETSKP ;NO. ALLOW MAP
REPEAT 0,< ;OLD FAST GET CODE
;TEST IF A FAST GET CAN BE DONE
;LOCAL DEFINITIONS FOR DATA STRUCTURE
DEFSTR (FGOFN,,35,12) ;THE OFN
DEFSTR (FGSPT,,23,12) ;THE PROTOTYPE MAP
DEFSTR (FGCNT,,11,11) ;THE SHARE COUNT
DEFSTR (FGVLD,,0,1) ;VALID BIT
FGEVEC==1 ;THE ENTRY VECTOR LENGTH
; ;1+FGEVEC==2 ;ENTRY VECTOR ADDRESS
FGLLCK==3 ;LOCK WORD
TSTFST: SKIPE FSTTBL ;ANY ENTRIES IN THE CACHE?
SKIPE P2 ;YES. DOING ENTIRE ADDRESS SPACE?
RET ;NO. CAN'T DO IT THEN
TXNN F,GT%NOV ;CHECKING FOR OVERLAYS?
CAIE P3,PGSIZ-1 ;YES. UP TO THE END?
RET ;NO. CAN'T DO IT
CALL CHECKG ;ON DISK?
RET ;NO. CAN'T DO IT THEN
TSTFSN: CSKED ;CRITICAL SECTION WHILE TABLE LOCKED
LOCK FGLOCK ;LOCK UP THE TABLE
CALL FNDOFN ;GET OFN FROM THE JFN
RETBAD (,<UNLOCK FGLOCK
ECSKED>)
MOVEI T4,FSTTBL+1 ;START OF ENTRIES
MOVE T3,FSTTBL ;COUNT
TSTFS0: JE FGVLD,(T4),TSTFSX ;VALID?
LOAD T2,FGOFN,(T4) ;GET OFN FROM TABLE
CAIN T1,0(T2) ;SAME AS THE ONE IN THE JFN?
JRST FSTGT1 ;YES. GOT ONE
TSTFSX: ADDI T4,FSN ;NEXT ENTRY
SOJG T3,TSTFS0 ;NO. DO THEM ALL
RETBAD (,<UNLOCK FGLOCK
ECSKED>) ;NOT FOUND
;FOUND A MATCHING ENTRY
FSTGT1: AOS FGLLCK(T4) ;INCREMENT USE COUNT
UNLOCK FGLOCK ;UNLOCK STRUCTURE LOCK
NOINT ;DON'T GO NOINT BECAUSE USE COUNT IS UP
ECSKED ;NOT CRITICAL WHEN TABLE UNLOCKED
MOVE T1,T4 ;COPY ENTRY
CALLRET FSTGET ;DO FAST GET
;ROUTINE TO DO A FAST GET. AT THIS POINT
;FAST TABLE ENTRY IS LOCKED
; T1/ ENTRY IN FAST GET TABLE
; P1/ THE JFN
;RETURNS: +1 SOME SORT OF FAILURE. MUST DO IT THE LONG WAY
; +2 SUCCESS
;ONLY DOES A GET ON THE ENTIRE PROCESS SPACE.
FSTGET: ACVAR <W1,W2,W3> ;WORK REGS
STKVAR <WRKPG1,WRKPG2,SAVENT,<STRADR,2>,PSPTN,FSTOFN,FSTSPN,FSTSPP> ;SOME WORK LOCATIONS
MOVEM T1,SAVENT ;SAVE TABLE INDEX
LOAD T1,FGSPT,(T1) ;GET SPTN
MOVEM T1,PSPTN ;SAVE SPTN OF PROTOTYPE MAP
HLLZ T1,P1 ;GET FORK HANDLE,,0
MOVEI T2,0 ;CONVERT PAGE NUMBER TO PC SECTION
CALL FKHPTX ;GET PTN OF PROCESS
JRST [ MOVE T1,SAVENT
SOS FGLLCK(T1) ;REDUCE USE COUNT
OKINT
RET] ;SO FAIL
HLLZ P5,T1 ;SAVE SPTN
CALL ASGPAG ;GET A PAGE FOR MAPPING FORKS' PT
JRST [ MOVE T1,SAVENT
SOS FGLLCK(T1) ;FREE LOCK
OKINT
RET]
MOVEM T1,WRKPG1 ;SAVE PAGE
CALL ASGPAG ;GET A PAGE TO MAP PROTOTYPE MAP
JRST [ MOVE T1,WRKPG1
CALL RELPAG ;FAILED. RELEASE THIS
MOVE T1,SAVENT
SOS FGLLCK(T1)
OKINT
RET]
MOVEM T1,WRKPG2 ;SAVE THIS AS WELL
;NOW MAP THE FORK'S PT AND THE PROTOTYPE MAP
MOVE T2,T1 ;COPY PAGE
MOVE T1,PSPTN ;GET PROTOTYPE MAP PAGE
TXO T2,<PM%RD> ;ONLY NEED TO READ IT
CALL SETMPG
HLRZ T1,P5 ;SPTN OF FORK'S PT
MOVE T2,WRKPG1
TXO T2,<PM%RD!PM%WT>
CALL SETMPG ;MAP THIS AS WELL
; ..
;PAGES ARE NOW MAPPED AND PROCESS VERIFIED. SCAN TABLE AND
;SET UP MAP
MOVE T3,SAVENT ;GET FAST-GET ENTRY
LOAD T1,FGOFN,(T3) ;GET THE OFN
LOAD T2,FGCNT,(T3) ;GET THE COUNT
MOVEM T1,FSTOFN ;SAVE OFN FOR LATER
HRRZ T1,P1 ;GET THE JFN
CALL MJFCNT ;AND UPDATE THE JFN COUNT AS WELL
NOP
MOVE W1,WRKPG2 ;GET PROTOTYPE PT
MOVE W2,WRKPG1 ;GET FORK'S PAGE TABLE
MOVE W3,IMMPTR ;GET IMMEDIATE PAGE POINTER
TXO W3,UAAB ; TO CHECK FOR PLACE HOLDER
FSTSCN: CALL FLOCK ;LOCK THE PROCESS STRUCTURE
FSTSC5: SKIPE T1,0(W1) ;ANYTHING HERE?
JRST FSTSC0 ;YES. GO PROCESS IT
FSTS22: ADDI W1,1 ;NO. NEXT PAGE
ADDI W2,1 ;SAME HERE
FSTSC2: TRNE W1,PGSIZ-1 ;ALL DONE YET?
JRST FSTSC5 ;NO. GO DO NEXT ONE
JRST FSTDON ;YES.
;FOUND A PAGE IN THE PROTOTYPE PAGE TABLE
FSTSC0: SKIPE 0(W2) ;PROCESS HAVE A PAGE HERE?
JRST FSTSC1 ;YES. MUST DELETE FIRST
CAMN T1,W3 ;NO. IS THIS A PLACE-HOLDER?
JRST FSTS22 ;DONE.
MOVEI T4,1 ;INIT MAP COUNTER
LOAD T2,IPPGN,0(W1) ;GET STARTING PAGE NUMBER
MOVEM T2,FSTSPN ;AND SAVE IT
MOVEM W2,FSTSPP ;SAVE STARTING PROCESS PAGE
LOOP: ADDI W1,1 ;NEXT PAGE
ADDI W2,1 ;AND SAME HERE
TRNN W1,PGSIZ-1 ;AT THE END YET?
JRST LOPMAP ;YES. DO MAPPING THEN
SKIPE 0(W2) ;SOMETHING HERE IN THE PROCESS?
JRST LOPMAP ;YES. DO MAPPING THEN
LOAD T3,IPPGN,0(W1) ;NO. GET PAGE # THEN
CAIE T3,1(T2) ;THE EXPECTED ONE?
JRST LOPMAP ;NO. DO MAP NOW
MOVE T2,T3 ;YES. SAVE PAGE #
ADDI T4,1 ;ANOTHER PAGE IN THE COLLECTION
JRST LOOP ;AND EXAMINE MEXT PAGE
;READY TO DO MAP
LOPMAP: CALL GPAC ;GET USER ACCESS BITS FROM PAGE POINTER
MOVE T3,T1 ;COPY ACCESS BITS TO PROPER REG
MOVE T1,FSTSPN ;GET STARTING PAGE # IN FILE
HRL T1,FSTOFN ;FORM SOURCE ADDRESS
MOVE T2,FSTSPP ;GET PROCESS PAGE ADDRESS
SUB T2,WRKPG1 ;COMPUTE PROCESS PAGE NUMBER
HLL T2,P5 ;GET PROCESS PAGE NUMBER
CALL MSETPT ;MAP IT
JRST FSTSC2 ;AND PROCEED
;PROCESS HAS A PAGE IN THE SLOT.
FSTSC1: DMOVEM W1,STRADR ;SAVE START OF SCAN
FSTSC4: ADDI W2,1 ;NEXT PAGE
ADDI W1,1
TRNN W2,PGSIZ-1 ;AT THE END?
JRST FSTSC3 ;YES.
SKIPE 0(W1) ;ANYTHING HERE?
SKIPN 0(W2) ;YES. ANYTHING IN PROCESS?
SKIPA ;NO. DO DELETER NOW
JRST FSTSC4 ;YES TO BOTH. CONTINUE SCAN
FSTSC3: CALL FUNLK ;RELEASE PROCESS LOCK
SUB W2,1+STRADR ;COMPUTE PAGES SCANNED
SETOM T1
MOVE T2,1+STRADR ;GET START OF RANGE
SUB T2,WRKPG1 ;GET STARTING PAGE NUMBER
HLL T2,P1 ;PROCESS HANDLE
MOVE T3,W2 ;COUNT
TXO T3,PM%CNT ;SET REPEAT COUNT
PMAP ;DELETE PAGES
DMOVE W1,STRADR ;RESTORE START OF RANGE
JRST FSTSCN ;AND GO AGAIN
;MAP ALL DONE. ADJUST COUNTS AND CLEAN UP
;INCREASE SHARE COUNT HERE
;
FSTDON: CALL FUNLK ;RELEASE PROCESS LOCK
MOVE T1,WRKPG1
CALL RELPAG ;CLEAN UP
MOVE T1,WRKPG2
CALL RELPAG ;""
HLLZ T1,P5 ;GET IDENT
MOVEI T2,PGSIZ
CALL PREPG ;PRELOAD THE PAGES
NOP
MOVE T2,SAVENT
MOVE A,FGEVEC(T2) ;GET POSSIBLE ENTRY VECTOR LENGTH
SKIPE B,1+FGEVEC(T2) ;HAVE A VECTOR TO SET?
CALL VECSET ;YES. SET IT THEN
MOVE T1,SAVENT
SOS FGLLCK(T1) ;FREE LOCK
OKINT ;MATCH NOINT DONE EARLIER
RETSKP ;AND DONE
ENDSV. ;END STKVAR
ENDAV. ;END ACVAR
> ;END OF OLD FAST GET CODE
;ROUTINE TO MAKE AN ENTRY IN THE FAST GET CACHE
FSTENT: SAVEAC <P2> ;GET A WORK REG
LOCK FGLOCK ;LOCK UP THE TABLE
MOVE P2,[-FSMAX,,FSTTBL]
SKIPE 0(P2) ;ANYTHING HERE?
JRST [ AOBJN P2,.-1 ;NO. ANY MORE TO DO?
UNLOCK FGLOCK ;DONE WITH TABLE
RET] ;NO. DONE THEN
CALL FNDOFN ;FIND OFN PLEASE
RET ;OOPS. GIVE UP THEN
MOVEM T1,0(P2) ;STASH OFN FOR LATER USE
UNLOCK FGLOCK ;DONE WITH TABLE
CALLRET UPSHR ;UP THE SHARE COUNT
REPEAT 0,< ;OLD CODE
FSTENT: STKVAR <SVX,FSTPAG> ;SAVE ENTRY INDEX HERE
CALL ASGPAG ;GET A WORK PAGE
RET ;COULDN'T
MOVEM T1,FSTPAG ;SAVE IT
NOINT
LOCK FGLOCK ;GET LOCK
MOVEI T4,FSTTBL+1 ;START OF THE TABLE
HRLI T4,-FSMAX ;THE TABLE SIZE
FSTEN0: JN FGVLD,(T4),FSTEN1 ;IF VALID, CAN'T USE IT
MOVEM T4,SVX ;FOUND ONE. SAVE IT
HLLZ T1,P1 ;GET FORK HANDLE,,0
MOVEI T2,0 ;USE PC SECTION
CALL FKHPTN ;GET HANDLE
JRST FSTENX ;BOO HIS
HLLZ P5,T1 ;SAVE SPTN OF PROCESS PAGE TABLE
NOSKED
CALL ASSPTL ;GET AN SPT ENTRY
OKSKED
MOVE T4,SVX
STOR T1,FGSPT,(T4) ;SAVE SPTN
DMOVE T2,ENTVCW ;GET ENTRY VECTOR
DMOVEM T2,FGEVEC(T4) ;SAVE IT
CALL SWPIN4 ;ASSIGN PAGE TO SPTN
CALL FNDOFN ;GET OFN FOR THE GET FILE
JRST [ MOVE T4,SVX
LOAD T1,FGSPT,(T4) ;GET SPTN
CALL DESPT ;RELEASE IT
JRST FSTENX] ;AND GO ERROR OUT
MOVE T4,SVX ;GET BACK INDEX
STOR T1,FGOFN,(T4)
MOVEI T2,1 ;INCREMENT OFN COUNT
CALL MUPSHR ;DO IT NOW
HLRE T2,T4 ;GET THIS OFFSET
ADDI T2,FSMAX+1
CAMLE T2,FSTTBL ;THIS NEW HIGHEST ENTRY?
MOVEM T2,FSTTBL ;YES. STORE IT
MOVE T2,SPCCNT
STOR T2,FGCNT,(T4) ;SAVE THE SHARE COUNT
; ..
;FSTENT CONTINUED
;NOW COPY THE PT
LOAD T1,FGSPT,(T4) ;GET BACK PT
MOVE T2,[PTRW+FPG0A]
CALL SETMPG ;MAP SPTN
MOVE T2,FSTPAG ;GET PAGE
HLRZ T1,P5 ;GET SPT OF FORKS' UPT
TXO T2,PTRW
CALL SETMPG ;MAP THIS AS WELL
HRL T1,FSTPAG ;SOURCE ADDRESS
HRRI T1,FPG0A ;DESTINATION ADDRESS
BLT T1,FPG0A+PGSIZ-1 ;COPY MAP
MOVE T1,FSTPAG ;GET WORK PAGE
CALL RELPAG ;GET RID OF IT
SETZM T1
MOVEI T2,FPG0A
CALL SETMPG ;UNMAP SPTN
MOVE T4,SVX
SETONE FGVLD,(T4) ;SAY ENTRY NOW VALID
FSTENX: UNLOCK FGLOCK ;DONE WITH LOCK
OKINT
RET ;AND DONE WITH ROUTINE
;STEP TO NEXT ENTRY
FSTEN1: ADDI T4,FSN-1
AOBJN T4,FSTEN0 ;DO THEM ALL
JRST FSTENX ;NONE FOUEN
ENDSV. ;END STKVAR
> ;END OF OLD FAST GET CODE
;SPECIAL ROUTINE USED BY GET WHEN BUILDING A PROTOTYPE
;GET ADDRESS SPACE. WILL CREATE PRIVATE POINTERS TO UNASSIGNED
;ADDRESSES TO USE AS PLACE HOLDERS.
MAKPGS: ASUBR<COUNT,ID>
HLLZ T1,ID ;GET FORK HANDLE
MOVEI T2,0 ;USE PC SECTION
CALL FKHPTX ;GET SPTN OF PROCESS PAGE TABLE
RETBAD ()
HLRZS T1 ;GET UPT INDEX
NOINT
MOVE T2,[PTRW+FPG0A]
CALL SETMPG ;MAP PAGE TABLE
HRRZ T3,ID ;GET FIRST PAGE
MOVN T4,COUNT ;GET NUMBER TO DO
HRL T3,T4
MOVE T4,IMMPTR
TXO T4,UAAB ;MAKE THEM ALL UNASSIGNED
MAKPG0: MOVEM T4,FPG0A(T3) ;STORE ONE
AOBJN T3,MAKPG0 ;DO THEM ALL
SETZM T1
CALL SETMPG ;UNDO MAPPING
OKINT
RET ;AND DONE
;ROUTINE TO FIND THE OFN IN A JFN.
; P1/ THE JFN
;RETURNS: +1 ALWAYS. T1/ THE OFN
FNDOFN: SAVEAC <F> ;SAVE FLAGS
SETZM F
HRLZ T1,P1 ;GET JFN
CALL JFNOFN ;GET OFN FOR PAGE 0
RET ;JFN WENT AWAY
HLRZS T1 ;YES. GET PT0 THEN
RETSKP ;DONE
;USER REQUEST TO FLUSH THE CACHE
FLSCSH: MOVX T4,SC%OPR!SC%WHL ;CHECK PRIVILEGES
TDNN T4,CAPENB ;HAVE ENOUGH?
ITERR (CAPX1) ;NO. DON'T DO IT THEN
FLSCS0: LOCK FGLOCK ;LOCK THE CACHE
REPEAT 0,< ;OLD CODE
FLSSC2: SETZM P2
SKIPN FSTTBL ;ANY ENTRIES?
JRST FLSDON ;NO. ALL DONE THEN
MOVN P1,FSTTBL ;YES. GET NUMBER
HRLZS P1
HRRI P1,FSTTBL+1 ;SCAN TABLE
FLSCSL: JE FGVLD,(P1),FLSX ;THIS ONE VALID?
SKIPE FGLLCK(P1) ;YES. ANY USERS?
AOJA P2,FLSX
;FOUND ONE TO DO
LOAD T1,FGOFN,(P1) ;GET THE OFN
CALL RELOFN ;RELEASE IT
LOAD T1,FGSPT,(P1) ;GET SPTN
CALL DESPT ;RELEASE IT
SETZRO FGVLD,(P1) ;SAY ENTRY IS NOW FREE
FLSX: ADDI P1,FSN-1 ;NEXT ENTRY
AOBJN P1,FLSCSL ;DO THEN ALL
JUMPN P2,[UNLOCK FGLOCK
MOVEI T1,^D500 ;WAIT A WHILE
DISMS
JRST FLSCS0] ;AND TRY AGAIN
FLSDON: SETZM FSTTBL ;NO ENTRIES NOW
> ;END OF OLD CODE
MOVE P2,[-FSMAX,,FSTTBL] ;SCAN WHOLE TABLE
FLSLOP: SKIPN T1,0(P2) ;ANYTHING HERE?
JRST FLSX ;NO.
CALL RELOFN ;YES. NOT USING OFN ANYMORE
SETZM 0(P2) ;AND NOT USING ENTRY
FLSX: AOBJN P2,FLSLOP ;DO THEM ALL
UNLOCK FGLOCK ;YES. UNLOCK THE LOCK
MRETNG ;AND DONE
;SAVE, GIVEN LIST OF BLOCK DESCRIPTORS OR ONE BLOCK DESCRIPTOR
;AC USAGE:
; P5 - PTN OF UPT,,0
; P1 - DESCRIPTOR LIST
; Q3 - CURRENT DESCRIPTOR
.SAVE:: MCENT
TRVAR <SHNJFN>
MOVE P1,2 ;SAVE DESCRIPTOR
CALL GTSVI
MOVEM T4,SHNJFN ;SAVE HANDLE AND JFN
CALL GTSVDV ;SEE IF THE DEVICE IS LEGAL (DISK, MAGTAPE OR DECTAPE)
ITERR (SAVX1) ;ILLEGAL DEVICE TO SAVE ONTO; ABORT THE JSYS
HRRI 2,1B20 ;WRITE FILE
OPENF
ITERR ;OPENF FAILED. ABORT THE JSYS
TLNE P1,-1 ;SOMETHING IN LH?
JRST SAVE3 ;YES, IT'S ONE DESCRIPTOR
SAVE2: UMOVE Q3,0(P1) ;GET NEXT DESCRIPTOR
JUMPE Q3,SAVE1 ;CHECK FOR END OF LIST OF DESCRIPTORS
CALL SAVEB ;WRITE BLOCK
AOJA P1,SAVE2
SAVE3: MOVE Q3,P1
CALL SAVEB
SAVE1: HLRZ 1,SHNJFN ;FORK HANDLE
CALL FLOCK ;LOCK THE FORK STRUCTURE
CALL SETLFK
PUSH P,EVLNTH(A) ;GET ENTRY VECTOR LENGTH
PUSH P,EVADDR(A) ;GET ADDRESS
CALL CLRLFK ;CLEAR PSB MAPPING
CALL FUNLK ;UNLOCK FORKS
POP P,B ;RECOVER ENTRY VECTOR ADDRESS
POP P,C ;RECOVER ENTRY VECTOR LENGTH
HRL B,C ;PUT THEM TOGETHER (THEY MIGHT NOT FIT THOUGH!)
HRRZ 1,SHNJFN ;JFN
BOUT ;WRITE ENTRY VECTOR POINTER
CLOSF
JFCL
JRST MRETN
;SAVE, PROCESS ONE BLOCK
SAVEB: HLRZ Q2,Q3 ;MAKE LH COUNT NEGATIVE
TRZE Q2,400000 ;LARGER THAN 377777?
PUSH P,[MSEC1,,SAVEBL] ;YES, DO IN TWO PARTS
MOVNI Q2,0(Q2)
HRLI Q3,0(Q2)
SETO 4, ;SAY NO PAGE NOW MAPPED
NOINT ;BE NOINT WHILE PAGE MAPPED
SAVEB1: JUMPGE Q3,SAVUMP ;DONE, CLEAN UP
MOVE Q2,Q3 ;SETUP TO SCAN FOR NON-0'S
LDB 1,[POINT 9,Q2,26] ;GET PAGE NUMBER
CAIN 1,0(4) ;DIFFERENT FROM CURRENT MAPPING?
JRST SAVE3A ;NO, SAME
MOVEI 4,0(1)
HLL 1,P5 ;FORK HANDLE
PUSH P,1
SETZ 1,
MOVEI 2,FPG0A
CALL SETMPG ;REMOVE EXISTING CONTENTS OF WINDOW
OKINT
MOVE 1,0(P)
CALL MRPACS ;SEE IF PAGE EXISTS
POP P,2
NOINT ;BE NOINT WHILE PAGE MAPPED
TLNN 1,(PA%RD) ;CAN IT BE READ?
JRST SAVE3B ;NO, FORGET IT
MOVE 1,2
MOVE 2,[PTRW+FPG0A]
CALL SETMPG ;MAP PAGE
SKIP FPG0A ;MAKE SURE IT IS READABLE
ERJMP SAVE3B ;WE LOST, NEXT PAGE
SAVE3A: HRRZ Q1,Q2 ;SETUP RELATIVE ADDRESS IN WINDOW
ANDI Q1,PGSIZ-1
ADDI Q1,FPG0A
JRST SAVE8
SAVE3B: ANDI Q2,777000
ADDI Q2,1000 ;TO NEXT PAGE
SUBI Q2,0(Q3)
HRLI Q2,0(Q2) ;COUNT OF WORDS SKIPPED IN BOTH HALVES
ADD Q3,Q2 ;UPDATE COUNT AND ADDRESS
JRST SAVEB1
SAVEBL: HRLI Q3,400000 ;DID N-400000 BEFORE, DO LAST 400000 NOW
NOINT
JRST SAVEB1
SAVE12: TRNN Q2,777 ;NEW PAGE?
JRST SAVE5 ;YES
SAVE8: SKIPN 0(Q1) ;NON-0 WORD?
JRST SAVE6 ;NO, GO CHECK FOR MORE
SAVE7: ADDI Q1,1
AOBJN Q2,SAVE12
MOVE Q2,Q3 ;END OF BLOCK
CALL SAVED
JRST SAVEB1
;WRITE ALL OR PART OF ONE PAGE.
SAVED: HLRE 2,Q2 ;COUNT OF WORDS JUST SCANNED
ADD Q1,2 ;RESET WINDOW POINTER
HRRZ 1,SHNJFN ;JFN
MOVE 2,6
SUBI 2,1 ;OUTPUT IOWD CNT,ADR
BOUT
ERJMP SAVERR ;FAILED
HLRE 3,Q2 ;GET (NEG) COUNT
PUSH P,3 ;SAVE IT
HRRZ 2,Q1 ;GET STARTING ADR
HRLI 2,(<POINT 36,0>) ;CONSTRUCT BYTE PTR TO IT
SOUT ;OUTPUT THE BLOCK
ERJMP SAVERR ;FAILED
POP P,2 ;RECOVER STARTING COUNT
SUB 3,2 ;COMPUTE NO. WDS MOVED
ADDM 3,Q1 ;UPDATE WINDOW PTR
HRL 3,3 ;PUT COUNT IN BOTH HALVES
ADDM 3,Q3 ;UPDATE AOBJN PTR
RET
SAVERR: CALL SAVUMP ;UNMAP ANY PAGE AND GO OKINT
MOVE T1,LSTERR
ITERR () ;DO ERROR
SAVUMP: SETZ T1, ;REMOVE MAPPING
MOVEI T2,FPG0A ;THAT WE HAD DONE
CALL SETMPG ;DO IT
OKINT ;CAN INTERRUPT NOW
RET ;DONE
;FOUND 0 WORD, CHECK FOR MORE
SAVE6: MOVEI 2,0(Q2)
CAIN 2,0(Q3) ;FIRST WORD OF BLOCK OR PAGE?
JRST SAVE9 ;YES
HLRZ 2,6
SETCMI 3,0(Q2)
CAIE 2,-1 ;END OF BLOCK, OR
TRNN 3,777 ;END OF PAGE?
JRST SAVE5 ;YES, FINISH BLOCK
SKIPE 1(Q1) ;SUCCESSIVE 0?
JRST SAVE7 ;NO, CONTINUE SCAN
SAVE5: MOVNI Q2,0(Q2) ;COMPUTE NUMBER OF WORD TO DUMP
ADDI Q2,0(Q3) ;(-CURRENT)+OLD = -DIFFERENCE
MOVSI Q2,0(Q2)
HRRI Q2,0(Q3) ;FIRST ADDRESS
CALL SAVED ;WRITE BLOCK
JRST SAVEB1
;SCAN OVER BLOCK OF 0'S
SAVE10: TRNE Q2,777 ;END OF PAGE?
SKIPE 0(Q1) ;OR NON-0 WORD?
JRST SAVE11 ;YES
SAVE9: ADDI Q1,1
AOBJN Q2,SAVE10
SAVE11: MOVE Q3,Q2 ;UPDATE POINTER
JRST SAVEB1 ;RECHECK PAGE, ETC.
;GTSVDV - ROUTINE TO CHECK FOR LEGAL DEVICE FOR SAVE AND SSAVE
;ACCEPTS IN T3: DEVICE CHARACTERISTICS AS RETURNED IN T2 BY DVCHR
;RETURNS +1: ILLEGAL DEVICE
; +2: LEGAL DEVICE
;ALLOWS DISK, NUL, MAGTAPE AND DECTAPE
;CLOBBERS T4
GTSVDV:
LDB T4,[POINTR (T3,DV%TYP)] ;GET THE DEVICE TYPE
CAIE T4,.DVDSK ;IS IT A DISK?
CAIN T4,.DVNUL ;OR NUL DEVICE?
RETSKP ;YES. GOOD
CAIE T4,.DVMTA ;NO. IS IT A MAGTAPE?
CAIN T4,.DVDTA ;NO. IS IT A DECTAPE?
RETSKP ;GOOD CHOICE. TAKE THE SKIP RETURN
RET ;NOT DISK, MAGTAPE OR DECTAPE. NONSKIP RETURN.
;SSAVE - CREATES EXE FILES
;ACCEPTS FROM USER:
; 1/ (FORK HANDLE,,JFN)
; 2/ EITHER (0,,ADDRESS OF TABLE) IF TABLE IS MORE THAN 1 WORD OR
; TABLE WORD
; 3/ FLAGS - NOT IMPLEMENTED
; A TABLE OF WORDS OF THE FORM
; (- NUMBER OF PAGES IN GROUP,,ACCESS+1ST CORE PAGE)
; EACH OF WHICH REPRESENTS A GROUP OF CONTIGUOUS PAGES
; CALL: SSAVE
;RETURN + 1:ALWAYS
; ITERR HANDLES ERRORS
;SAVES USER'S CORE IMAGE (LH T1) INTO FILE (RH T1)
;HEADER GOES INTO PAGES 0, 1, AND 2 (IF NEEDED)
;AC USAGE:
; ALL REGISTERS EXCEPT Q3 ARE USED. SEE INDIVIDUAL ROUTINES FOR
; COMMENTS
; STRINGS IN DIRECTORY WORDS. IF COMMENT, DEFINED IN GET
DEFSTR(EXFLG,,8,9) ;ACCESS BITS 1ST WORD
; DEFSTR(EXPAG,,35,27) ;FILE PAGE NUMBER 1 ST WORD
; DEFSTR(EXCNT,,8,9) ;REPEAT COUNT 2ND WORD
; DEFSTR(EXADR,,35,27) ;CORE PAGE NUMBER 2ND WORD
; ACCESS BITS INPUT AND SHIFTED TO LH
SSCPY==1B0 ;COPY ON WRITE
SSACC==1B1 ;TAKE ACCESS FROM PAGE
SSWRT==1B3 ;ALLOW WRITE
; ACCESS FOR EXE FILE
EXEWRB==1B2 ;WRITABLE
EXESHR==1B1 ;SHARABLE
; BLOCK TYPES (DEFINED IN GET)
; EXEEND=1777 ;END
; EXEFIL=1776 ;DIRECTORY
; EXEVEC=1775 ;ENTRY VECTOR
; EXEPDV=1774 ;PROGRAM DATA VECTORS
;NOTE: THE EXE FILE FORMAT ALLOWS UP TO THREE PAGES OF DIRECTORY.
;HOWEVER, SSAVE IS CURRENTLY LIMITED TO ONE PAGE.
SSDATA==1 ;FIRST DATA PAGE IN OUTPUT FILE
.SSAVE::MCENT
CALL SSAVA ;CALL ROUTINE TO DO THE SSAVE
ITERR ;ERROR RETURN FROM SSAVA
JRST MRETN ;RETURN FROM SSAVE
;SSAVA - DOES THE WORK FOR SSAVE
;ACCEPTS:
; SAME AS FOR .SSAVE ABOVE
;CALL: CALL SSAVA
;RETURN + 1:ERROR CODE IN T1
; + 2:SUCCESS
;FUNCTION:
; 1) READS THE USER'S INPUT
; 2) SETS UP TO PROCESS EACH GROUP OF PAGES AND CALLS SSAVB
; 3) WRITES THE FILE HEADER INFO
;CALLED BY SSAVE
;AC USAGE:
; P1/ LOCATION OF CURRENT ENTRY IN DIRECTORY
; P3/ NEXT FILE PAGE
; P4/ CURRENT TABLE WORD
; T1-T4/ TEMPORARY STORAGE
;TEMPORARY STORAGE:
; SAVVEC - Saved entry vector (2 words)
; HANJFN - FORK HANDLE,,JFN (AC1 ARG AFTER CHECKING, ETC)
; PDVADR - ADDRESS OF SAVED PDV BLOCK FORMAT IS
; -PDVN,,PDVBLK+1
; PDVN WORDS OF PDVAS
; SAVENT - Entry vector
; SSDIR - ADDRESS OF START OF SCRATCH PAGE IN WHICH DIRECTORY IS BUILT
; SSAC2 - AC2 AS SPECIFIED BY THE USER'S CALLING ROUTINE
; SSDEV - INDICATES TYPE OF OUTPUT DEVICE AND STATE OF PROCESSING
; TADR - PROCESS PAGE NUMBER
; WSEC - LAST SECTION SEEN
SSAVA: TRVAR <<SAVVEC,2>,HANJFN,PDVSPC,PDVADR,SAVENT,SSDIR,SSAC2,SSCORE,SSDEV,TADR,WSEC>
SETOM SSDEV ;INITIALIZE TO INDICATE DISK
SETOM WSEC ;SAY NO SECTION SEEN YET
CALL GTSVI ;INPUT: USER'S T1/ (FORK HANDLE,,JFN)
; OUTPUT: T1/JFN, T2/^D36B5,
; T3/ DEVICE CHARACTERISTICS,
; P5/PTN FOR PAGE 0 OF FORK,T4/FORK HANDLE,,JFN
MOVEM T4,HANJFN ;REMEMBER HANDLE AND JFN
CALL GTSVDV ;SEE IF THIS IS A LEGAL DEVICE
ITERR (SSAVX1) ;NO. RETURN AN ERROR AND ABORT THE JSYS
TLNE T3,777 ;LEGAL. DISK?
AOS SSDEV ;NO. INDICATE FIRST PASS ON SEQUENTIAL
HRRI T2,OF%WR ;WRITE ACCESS - LEFT HALF SET UP FOR
; 36-BIT BYTES IN GTSVI
OPENF ;OPEN OUTPUT FILE FOR WRITE
ITERR ;ERROR ON OPEN - CODE IN T1
SKIPGE SSDEV ;WORKING ON DISK?
JRST [ HRRZ T1,HANJFN ;YES. T1/JFN
MOVEI T2,SSDATA*1000 ;T2/POINTER TO START OF 1ST DATA PAGE
SFPTR ;SET FILE POINTER
ITERR ;FAILED. ERROR IN T1
JRST .+1]
NOINT
CALL ASGPGS ;GET SCRATCH PAGE TO BUILD DIRECTORY IN
JRST [ OKINT
ITERR(SSAVX3)] ;FAILED
MOVEM T1,SSDIR ;SAVE ADDRESS OF FREE PAGE
CALL ASGPGS ;GET A PAGE TO MAP USER'S PAGE INTO
JRST [ MOVEI P4,SSAVX3 ;FAILED. SET ERROR CODE
JRST SSAV6]
MOVEM T1,SSCORE ;SAVE ADDRESS OF THE PAGE
OKINT ;NOW THA HANDLES ARE STORED, ALLOW ^C
CALL GETOFF ;MAP IN THE FORK
DMOVE T2,EVLNTH(T1) ;GET THIS FORK'S ENTRY VECTOR
DMOVEM T2,SAVVEC ;SAVE ENTRY VECTOR WORD
SETZM PDVADR ;ASSUME NO PDVS
SETZM PDVSPC
; NOTE: THE FOLLOWING CODE BUILDS A BLOCK OF PDVAS IN FREE SPACE THE FORMAT OF
; THIS BLOCK IS DEPENDANT ON THE FREE SPACE MANAGERS DESIRE TO USE THE FIRST
; WORD OF THE RETURNED FREE SPACE. THIS CODE WOULD BE SOMEWHAT MORE CLEAR
; IF THAT WAS NOT TRUE SINCE IT IN NO WAY DEPENDS ON THE FREE SPACE HEADER
; AND CURRENTLY INDEXES OFFSET BY 1 TO AVOID TOUCHING THE HEADER
SKIPN T2,PDVS(T1) ;ANY PDVS?
IFSKP.
HRRZ T2,0(T2) ;GET SIZE OF PDV BLOCK
AOS T2 ;+1 FOR FREE HEADER
MOVE P4,T1 ;REMEMBER MAPPED FORK OFFSET
CALL ASGJFS ;GET FREE SPACE FOR BLOCK *GETOFF IS NOINT
JRST [CALL GEM ;UNLOCK
MOVEI T1,SSAVX3 ;ERROR CODE
JRST SSAV5]
MOVEM T1,PDVADR ;SAVE BLOCK ADDRESS
MOVEI T3,1(T1) ;DEST IS PAST FREE HEADER
MOVE T2,PDVS(P4) ;SOURCE
HRRZ T1,0(T2) ;COUNT SHOULD NOT CHANGE WHILE GETOFF (FLOCK)
XBLT. T1 ;SAVE PDV BLOCK LOCALLY
MOVE T1,PDVADR ;GET ADDRESS AGAIN
HRRZ T2,1(T1) ;GET COUNT OF BLOCK
ADDI T1,2 ;GET PDV STG +2 (FIRST PDVA)
MOVNI T2,-1(T2) ;MAKE AOBJN WORD OF -<COUNT-1>
HRL T1,T2 ; ,,PDVSTG+2 (FIRST PDVA)
MOVEM T1,-1(T1) ;SAVE AOBJN WORD IN WORD BEFORE FIRST PDVA
ENDIF.
CALL GEM ;UNLOCK THINGS
MOVEI P3,SSDATA ;P3/START OF DATA AREA IN FILE
;..
;HERE BEGINS A LOOP THAT IS PROCESSED ONCE FOR DISK AND TWICE FOR SEQUENTIAL
;DEVICES. IN THE CASE OF DISK, SSAVB IS CALLED ONCE FOR EACH ENTRY IN THE
;CALLER'S TABLE. SSAVB COPIES THE CORE PAGES ONTO DISK (IF NON-ZERO) AND
;BUILDS THE DIRECTORY. WHEN ALL THE GROUPS HAVE BEEN DONE, THIS ROUTINE WRITES
;THE HEADER PAGES. FOR A SEQUENTIAL DEVICE, THE FIRST PASS SIMPLY CREATES THE
;DIRECTORY AND WRITES THE HEADER PAGES, SINCE THEY PRECEDE ALL DATA. SSAVB IS
;CALLED AGAIN TO WRITE THE DATA PAGES.
;..
SSAV7: MOVE P1,SSDIR ;P1/START OF DIRECTORY AREA.
UMOVE T1,2 ;T1 / INPUT AC2 - TABLE WORD OR ADDRESS OF TABLE
MOVEM T1,SSAC2 ;SAVE INPUT AC2 IN TEMPORARY STORAGE
JUMPL T1,SSAV3 ;NEGATIVE IF SINGLE DESCRIPTOR
;TABLE HAS MORE THAN ONE WORD. T1 POINTS TO CURRENT WORD
SSAV2: CALL GETENT ;GET NEXT TABLE ENTRY
MOVEM T1,SSAC2 ;REMEMBER ADDRESS OF NEXT ENTRY
JUMPE P4,SSAV1 ;0 INDICATES END OF TABLE
CALL SSAV0 ;DO THIS SET OF PAGES
MOVE T1,SSAC2 ;GET ADDRESS OF NEXT ENTRY
JRST SSAV2 ;GO GET THE NEXT TABLE WORD
;TABLE HAS ONE WORD. T1 CONTAINS IT.
SSAV3: MOVEI T1,T2 ;SAY TABLE WORD IS IN T2
CALL GETENT ;GET ENTRY
CALL SSAV0 ;DO THIS SET OF PAGES
;ALL GROUPS HAVE BEEN PROCESSED. SSDEV INDICATES STATE:
; -1: WORKING ON DISK. DIRECTORY HAS BEEN BUILT IN SCRATCH PAGE,
; AND DATA PAGES HAVE BEEN WRITTEN. WRITE DIRECTORY AND QUIT.
; 0: FIRST PASS ON A SEQUENTIAL DEVICE. DIRECTORY HAS BEEN BUILT
; IN SCRATCH PAGE. WRITE IT AND GO START OVER TO WRITE THE
; DATA PAGES
; 1: SECOND PASS ON A SEQUENTIAL DEVICE. DIRECTORY WAS WRITTEN ON
; FIRST PASS, DATA PAGES ON SECOND. QUIT.
;NOTE:WHEN SSAVE SUPPORTS MULTIPLE-PAGE DIRECTORIES, THIS CODE
;SHOULD, WHEN SSDEV=0, DETERMINE THE NUMBER OF PAGES IN THE
;DIRECTORY. IF IT IS LESS THAN 3, IT SHOULD REDUCE ALL THE FILE
;PAGE NUMBERS IN THE DIRECTORY APPROPRIATELY AND SET P3 TO POINT
;TO THE FIRST PAGE AFTER THE DIRECTORY (I.E,. 1 OR 2)
;..
SSAV1: SKIPLE SSDEV ;SECOND PASS FOR SEQUENTIAL?
JRST SSAV8 ;YES. ALL DONE. FILE POINTER IS AT END
SKIPE SSDEV ;NO. PROCESSING DISK?
JRST [ HRRZ T1,HANJFN ;YES. T1/JFN
RFPTR ;GET PRESENT FILE POINTER
JRST SSAV5 ;FAILED
MOVEM T2,P4 ;SAVE FILE POINTER
SETZ T2, ;POINT TO BEGINNING OF FILE
SFPTR ;SET FILE POINTER TO START DIRECTORY
JRST SSAV5 ;FAILED
JRST .+1]
;WRITE THE DIRECTORY BLOCK
SUB P1,SSDIR ;SUBTRACT START OF SCRATCH PAGE FROM CURRENT LOC
MOVE T2,P1 ;NUMBER OF SUBGROUPS DONE *2
JUMPE T2,SSAV4 ;DON'T WRITE DIRECTORY IF NO SUBGROUPS
ADDI T2,1 ;NUMBER OF WORDS IN DIRECTORY (INCLUDES TITLE)
HRLI T2,EXEFIL ;T2/ (TYPE NO.,,NUMBER WORDS)
HRRZ T1,HANJFN ;T1/ JFN FOR FILE
BOUT ;WRITE FIRST WORD OF DIRECTORY
HRRZ T3,P1 ;T3/ (-NUMBER SUBGROUPS IN DIRECTORY)
MOVNS T3
MOVX T2,<POINT 36,0> ;T2/POINTER FOR 36-BIT BYTES
HRR T2,SSDIR ; IN SCRATCH PAGE
SOUT ;WRITE DIRECTORY
;..
;ENTRY VECTOR BLOCK
;..
HRRI T2,3 ;WORD COUNT FOR ENTRY VECTOR BLOCK
HRLI T2,EXEVEC ;T2/(TYPE NO,,NUMBER WORDS)
BOUT ;WRITE FIRST WORD OF ENTRY VECTOR BLOCK
MOVE T2,SAVVEC ;T2/ ENTRY VECTOR LENGTH
HRRZ T1,HANJFN ;JFN FOR OUTPUT FILE
BOUT ;WRITE ENTRY VECTOR COUNT
MOVE T2,1+SAVVEC ;ADDRESS OF ENTRY VECTOR FOR OUTPUT
BOUT ;WRITE ENTRY VECTOR ADDRESS
;PDV BLOCK
SKIPN T2,PDVSPC ;PDVS TO DO?
JRST NOPDVS
AOS T2 ;COUNT HEADER TOO
HRLI T2,EXEPDV ;BLOCK TYPE IS PDV
BOUT ;WRITE BLOCK HEADER
MOVE T3,PDVADR ;GET AOBJN WORD TO PDVAS
MOVE T3,1(T3)
SETZ T4, ;COUNT FOR SANITY
DO.
SKIPGE T2,0(T3) ;GET PDVA
AOS T4 ;COUNT IT WRITTEN PDVAS
TXZE T2,1B0 ;WAS IT MARKED GOOD (UNMARK IT)
BOUT ;WRITE GOOD PDVS
AOBJN T3,TOP. ;CHECK ALL OF THEM
ENDDO.
CAME T4,PDVSPC ;SAME NUMBER
ITERR (SSAVX5) ;NO!!!
;END BLOCK
NOPDVS: HRRZ T1,HANJFN ;GET JFN
HRLI T2,EXEEND
HRRI T2,1 ;T2/ (TYPE NUMBER,,NUMBER WORDS)
BOUT ;WRITE END BLOCK
;HEADER WRITTEN (DIRECTORY, ENTRY VECTOR, ETC.). EITHER WORKING
;ON DISK (SSDEV=-1) OR FIRST PASS FOR SEQUENTIAL DEVICE (SSDEV=0)
SSAV4: SKIPGE SSDEV ;WORKING ON DISK?
JRST [ HRRZ T1,HANJFN ;YES. T1/JFN
MOVE T2,P4 ;T2/ORIGINAL FILE POINTER (AFTER DATA)
SFPTR ;SET FILE POINTER AFTER ALL EXISTING PAGES
JRST SSAV5 ;ERROR FROM SFPTR - CODE IN T1
JRST SSAV8] ;DONE. GO CLOSE THE FILE
;FIRST PASS FOR SEQUENTIAL DEVICE. WRITE THE REST OF THE PAGE AND
;GO REPEAT THE BUILDING PROCESS TO WRITE THE DATA
HRRZ T1,HANJFN ;T1/JFN FOR FILE
RFPTR% ;How far have we gone?
MOVEI T2,5 ;If it fails, assume 5 words
MOVEI T4,-1000 ;Get count for a full page
ADDI T4,(T2) ;Halfword add words already written
SETZM T2 ;T2/DATA TO BE WRITTEN
HRLZ T4,T4 ;TO LEFT HALF FOR COUNTING
JUMPGE T4,SSAV10 ;DON'T WRITE IF PAGE IS FULL
SSAV9: BOUT ;WRITE A WORD
AOBJN T4,SSAV9 ;CONTINUE UNTIL PAGE COMPLETED
SSAV10: MOVEI P3,SSDATA ;YES. P3/ADDRESS OF 1ST DATA PAGE
AOS SSDEV ;INDICATE SECOND PASS
JRST SSAV7 ;GO WRITE THE DATA PAGES
;GETENT gets the entry for a set of pages
;
;Accepts: T1/ address in user space of table word
;
;Returns+1: P4/ table word except for page number
; TADR/ page number
; T1/ address of next entry (varies wrt SS%EPN
GETENT: UMOVE P4,(T1) ;GET FIRST PART OF TABLE WORD
LOAD T2,SS%FPN,P4 ;FIRST ASSUME NON-EXTENDED ENTRY
TXNE P4,SS%EPN ;IS THIS AN EXTENDED ENTRY?
UMOVE T2,1(T1) ;YES, GET PAGE NUMBER FROM SECOND WORD OF PAIR
MOVEM T2,TADR ;REMEMBER PAGE NUMBER
AOJ T1, ;FIRST ASSUME ONE-WORD ENTRY
TXNE P4,SS%EPN
AOJ T1, ;FIX POINTER FOR DOUBLE-WORD ENTRY
RET
;SSAV0 does a group of pages
SSAV0: MOVE T2,SSDIR ;PASS ADDRESS OF DIRECTORY SCRATCH PAGE
MOVE T3,SSCORE ;PASS ADDRESS OF CORE SCRATCH PAGE
MOVE T4,SSDEV ;PASS DEVICE FLAG
CALL SSAVB ;GO PROCESS THIS GROUP OF PAGES
JRST SSAV5 ;ERROR FROM SSAVB - CODE IN T1
RET
;GETOFF maps in the PSB of the fork being saved.
;
;Returns+1: FLOCK locked
; page mapped
; T1/ offset
GETOFF: CALL FLOCK ;PREVENT FORK STRUCTURE FROM CHANGING
HLRZ T1,HANJFN ;GET FORK HANDLE
CALLRET SETLFK ;MAP IN THE FORK TO SOMEWHERE
;This little GEM is used to unwind mappings and locks.
GEM: CALL CLRLFK ;CLEAR MAPPING
CALLRET FUNLK ;UNLOCK FORK STRUCTURE
;ALL OUTPUT DONE. CLOSE FILE AND RELEASE SCRATCH PAGES
SSAV8: HRRZ T1,HANJFN ;JFN
CLOSF ;CLOSE FILE
JFCL
MOVE T1,SSDIR ;T1/ADDRESS OF DIRECTORY SCRATCH PAGE
NOINT ;NO INTERRUPTS WHILE RELEASING PAGES
CALL RELPGS ;RELEASE THE SCRATCH PAGE
MOVEI T1,JSBFRE ;ADDR OF JSB FREE HEADER
SKIPE T2,PDVADR ;ADDRESS OF PDV STORAGE IF ANY
CALL RELFRS ;RELEASE IT
MOVE T1,SSCORE ;T1/ADDRESS OF CORE SCRATCH PAGE
CALL RELPGS ;RELEASE THE PAGE
OKINT ;ALLOW INTERRUPTS
RETSKP ;SUCCESSFUL RETURN
;ERROR OCCURRED AFTER EITHER OR BOTH PAGES WERE OBTAINED. RELEASE THEM.
;THE FAILING ROUTINE SET THE ERROR CODE IN T1.
SSAV5: MOVEM T1,P4 ;SAVE THE ERROR CODE
NOINT ;NO INTERRUPTS WHILE RELEASING PAGES
MOVEI T1,JSBFRE ;ADDR OF JSB FREE HEADER
SKIPE T2,PDVADR ;ADDRESS OF PDV STORAGE
CALL RELFRS ;RELEASE IT
MOVE T1,SSCORE ;T1/ADDRESS OF CORE SCRATCH PAGE
CALL RELPGS ;RELEASE THE PAGE
SSAV6: MOVE T1,SSDIR ;T1/ADDRESS OF DIRECTORY SCRATCH PAGE
CALL RELPGS ;RELEASE THE PAGE
MOVE T1,P4 ;RESTORE THE ERROR CODE
OKINT
ITERR ;ERROR RETURN
;SSAVB - PROCESSES ONE WORD FROM USER TABLE
;ACCEPTS:
; T2/STARTING ADDRESS OF SCRATCH PAGE TO CONTAIN DIRECTORY
; T3/STARTING ADDRESS OF SCRATCH PAGE TO CONTAIN USER'S CORE PAGE
; T4/-1 OR 1 IF DATA PAGES SHOULD BE WRITTEN. 0 IF BUILD DIRECTORY ONLY
; P1/ADDRESS OF NEXT ENTRY IN THE DIRECTORY
; P3/ NEXT FILE PAGE
; P4/ TABLE WORD AS ENTERED (ACCESS IN 18-26) (SAVED IN SSWORD)
; HANJFN/ FORK HANDLE,,JFN
;CALL: CALL SSAVB
;RETURN + 1:ERROR - CODE IN T1
; + 2:SUCCESS
; SSAVB PROCESSES ONE GROUP OF PAGES AS REQUESTED BY ONE WORD IN
; THE INPUT TABLE. CONTIGUOUS PAGES FORM ONE SUBGROUP (AND
; THUS ONE ENTRY IN THE DIRECTORY) UNTIL A PAGE DIFFERS FROM ITS
; PREDECESSOR IN ONE OF THE FOLLOWING WAYS:
; A. PAGE N EITHER
; 1. IS ALL ZERO
; 2. DOES NOT EXIST, OR
; 3. IS NOT READABLE
; AND N-1 IS NONE OF THE ABOVE
; B. PAGE N-1 IS ANY OF THE ABOVE AND PAGE N IS NONE
; C. PAGES N-1 AND N HAVE DIFFERENT ACCESS
; AT THAT POINT THE DIRECTORY ENTRY FOR N-1 IS COMPLETED AND A
; NEW SUBGROUP BEGINS WITH N.
;EACH DIRECTORY ENTRY IS TWO WORDS AS FOLLOWS:
; - - - - - - - - - - - - - - - - - - - -
; !ACCESS !FILE PAGE NUMBER!
; !REPEAT COUNT !CORE PAGE NUMBER!
; - - - - - - - - - - - - - - - - - - - -
;WHERE THE PAGE NUMBERS EACH OCCUPY 27 BITS AND REPRESENT THE STARTING PAGES
;IN A GROUP. THE REPEAT COUNT IS 1 LESS THAN THE NUMBER OF PAGES
;IN A GROUP
;AC USAGE:
; P1/ADDRESS IN SCRATCH PAGE OF FIRST WORD OF CURRENT DIRECTORY ENTRY
; P2/ NUMBER OF PAGES PROCESSED THIS SUBGROUP
; P4/ ADDRESS OF FIRST WORD OF SCRATCH PAGE FOR DIRECTORY
; P5/ ACCESS TO GO WITH PAGE IN FILE
; Q1/ -NUMBER OF PAGES IN GROUP AS INPUT BY USER
; Q2/ NUMBER OF PAGES IN THIS SECTION PROCESSED THIS SUBGROUP
; T1-T3/ TEMPORARY STORAGE
;TEMPORARY STORAGE:
; SSWORD - TABLE WORD CURRENTLY BEING DONE (SPECIFIED BY USER IN CALL)
; SSFLAG - FIRST TIME FLAG (0 ON FIRST ENTRY TO ROUTINE)
; SSCORE - SCRATCH PAGE FOR MAPPING USER'S CORE PAGE
; SSDEV - CONTENTS OF T4 AS PASSED ON ENTRY
SSAVB: STKVAR <SSFLAG,SSWORD,SSCORE,SSDEV,SSPACC>
MOVEM T3,SSCORE ;SAVE ADDRESS OF CORE SCRATCH PAGE
MOVEM T4,SSDEV ;SAVE DEVICE FLAG
TXNN P4,1B0 ;MAKE SURE COUNT IS NEGATIVE
ITERR(SSAVX2) ;LOSE - RETURN CODE IN T1
MOVEM P4,SSWORD ;SAVE TABLE WORD
MOVEM T2,P4 ;P4/ADDRESS OF DIRECTORY SCRATCH PAGE
SETZB P2,Q2 ;CLEAR COUNT OF PAGES IN SUBGROUP AND SECTION
SETZM SSFLAG ;CLEAR FIRST TIME FLAG
HLRO Q1,SSWORD ;-COUNT OF PAGES
SKIPN T3,PDVADR ;PDVS TO DO?
JRST SSB10 ;NO
MOVE T3,1(T3) ;GET AOBJN WORD TO PDVAS
HRR T1,TADR ;FIRST PAGE IN RANGE
MOVN T2,Q1 ;GET COUNT OF PAGES
ADD T2,T1 ;ADD FIRST PAGE SO T2 = LAST PG + 1
LSH T1,PGSFT ;AS ADDRESS
LSH T2,PGSFT
SOS T2 ;T2 IS LIMIT FOR PDV
MOVX T4,1B0 ;MARKER VALUE FOR GOOD PDVA
PDVLOP: CAMG T1,0(T3) ;IS PDV BIGGER THAN LOWER
CAMGE T2,0(T3) ;YES, IS IT SMALLER THAN UPPER
IFSKP.
TDNN T4,0(T3) ;YES AND YES. ALREADY COUNT THIS PDVA?
AOS PDVSPC ;NO, SO COUNT IT NOW
IORM T4,0(T3) ;MARK IT AS GOOD
ENDIF.
AOBJN T3,PDVLOP ;AND LOOP
HLRO Q1,SSWORD ;RESTORE Q1
;..
;SSB10 BEGINS LOOP THROUGH ALL PAGES IN A GROUP AS DESCRIBED BY ONE
;WORD IN INPUT TABLE. ENDS BEYOND SSAVB5.
;..
SSB10: HLLZ T1,HANJFN ;FORK HANDLE TO LH
HRR T1,TADR ;CORE PAGE TO RH OF T1
MOVX T2,SS%EPN ;CHECK TO SEE IF EXTENDED PAGE NUMBERS WANTED
TDNE T2,SSWORD ;WERE THEY?
TLO T1,FH%EPN ; YES, SPECIFY THAT IN FORK HANDLE
RMAP ;GET STATE OF THIS MEM PAGE INTO AC 2
ERJMP [ MOVE T1,LSTERR ;FAILED, SEE WHY
CAIE T1,ARGX06 ;NO SUCH SECTION?
ITERR ;UNKNOWN ERROR, SO BOMB OUT
ADDI P2,777 ;KEEP COUNT OF PAGES FOR EXE DIRECTORY UP-TO-DATE
ADDI Q1,777 ;SKIP THIS ENTIRE NONEXISTENT SECTION OF 1000 PAGES
SOS Q2 ;DECREMENT SECTION COUNT
MOVEI T1,777
ADDM T1,TADR ;UPDATE NEXT PAGE NUMBER TO BE IN NEXT SECTION
JRST SSB1] ;GO SEE IF DONE
MOVEM T2,SSPACC ;SAVE ACCESS BITS FOR PAGE
MOVX P5,<EXEWRB>_-^D27 ;SET WRITABLE IN CASE ALL-ZERO OR DOESN'T EXIST
; (NINE-BIT FIELD RIGHT-JUSTIFIED)
TXNN T2,PA%PEX ;DOES IT EXIST?
JRST SSAVB6 ;NO. TREAT AS IF ALL-ZERO
TXNN T2,PA%RD ;YES. READABLE?
JRST SSAVB6 ;NO, TREAT AS IF ALL-ZERO
;MAP THE USER'S PAGE INTO CORE SCRATCH PAGE
HLL T1,HANJFN ;USER'S FORK HANDLE
HRR T1,TADR ;CORE PAGE
MOVX T2,SS%EPN ;CHECK TO SEE IF EXTENDED PAGE NUMBERS WANTED
TDNE T2,SSWORD ;WERE THEY?
TLO T1,FH%EPN ; YES, SPECIFY THAT IN FORK HANDLE
MOVEI T2,0
CALL FKHPTN ;INPUT: T1/ (FORK HANDLE,,PAGE)
ITERR () ;ILL FORMED RFH
; OUTPUT: T1/ (PTN,,PAGE)
MOVE T2,SSCORE ;T2/ADDRESS OF CORE SCRATCH PAGE
TXO T2,PM%RD ;READ ACCESS
CALL SETMPG ;INPUT: T1/ (PTN,,PAGE)
; T2/(ACCESS ,,MONITOR ADDRESS)
; SETS UP INDIRECT POINTER TO USER PAGE
SKIP SSCORE ;IS PAGE REALLY THERE?
ERJMP SSAVB6 ;NO
; CHECK PAGE FOR ALL ZEROES. GO TO SSAVB6 IF ZERO, SSAVB2 OTHERWISE
MOVSI T1,-1000 ;SET UP COUNTERS
HRR T1,SSCORE ;POINT TO START OF SCRATCH PAGE
SSAVB9: MOVE T2,(T1) ;GET DATA
ERJMP SSAVB6 ;IF PAGE GOES AWAY, ASSUME IT WAS NEVER THERE
JUMPN T2,SSAVB2 ;PAGE IS NON-0 IF SOMETHING WITHIN IT IS.
AOBJN T1,SSAVB9 ;KEEP LOOKING
TXO P5,<EXEZRO>_-^D27 ;SET ALL-ZERO BIT
;CURRENT PAGE ALL ZERO, NOT READABLE, OR DOESN'T EXIST (NOT MAPPED)
;LOOK AT DIRECTORY FOR CURRENT GROUP. IF SAME AS THIS PAGE, ADD TO
;CURRENT GROUP. OTHERWISE, START NEW GROUP
;..
SSAVB6: SKIPN SSFLAG ;FIRST TIME THROUGH?
JRST [ SETOM SSFLAG ;YES. SET THE FLAG
JRST SSAVB1] ; AND GO SET UP THE DIRECTORY
CALL SCOMPR ;SEE IF NEW SUBGROUP NEEDED
JRST SSAVB1 ;START NEW SUBGROUP
JUMPE T1,SSAVB5 ;T1 ZERO IF WORKING ON GROUP OF ALL ZEROES
CALL SSAVC
; SET UP DIRECTORY FOR ALL-ZERO BLOCK
SSAVB1: SETZM (P1) ;SET FILE PAGE NUMBER IN FIRST WORD TO 0
STOR P5,EXFLG,(P1) ;MOVE ACCESS TO FIRST WORD
MOVE T1,TADR
STOR T1,EXPAG,1(P1) ;MOVE CORE PAGE NO TO 2ND WORD
JRST SSAVB5
;CURRENT PAGE NOT ALL ZERO
;NOTE: THIS BLOCK ASSUMES CERTAIN BIT PATTERNS FOR INPUT TO SSAVE
; AND OUTPUT FROM RPACS. CHANGING EITHER WILL AFFECT THIS CODE.
SSAVB2: MOVE T2,SSPACC ;T2/ACCESS FOR USER'S PAGE
HRL T3,SSWORD ;MOVE ACCESS TO LH OF T3
TXNE T3,SSACC ;ACCESS PER CORE PAGE REQUESTED?
JRST [ TXZ T2,SSCPY ;YES. 'AND' ACCESS REQUESTED (LH T3)
; WITH PAGE ACCESS (LH T2)
TXNE T2,PA%CPY ;MOVE COPY ON WRITE BIT TO BIT 0 IN T2
TXO T2,SSCPY ; TO CORRESPOND TO T3
AND T2,T3 ;AND INTO T2
JRST SSB12] ;T2 CONTAINS ACCESS TO BE GIVEN
MOVE T2,T3 ;NO. SAVE ACCESS REQUEST IN T2
SSB12: SETZ T3,
TXNE T2,SSWRT ;WRITE?
JRST [ TXO T3,EXESHR!EXEWRB ;YES. SET SHARABLE AND WRITABLE
JRST SSB11]
TXNE T2,SSCPY ;NO. COPY ON WRITE?
TXO T3,EXEWRB ;YES. SET WRITABLE
SSB11: LOAD P5,EXFLG,T3 ;SAVE RIGHT-JUSTIFIED IN P5
;LOOK AT DIRECTORY FOR CURRENT GROUP. IF SAME AS THIS PAGE, ADD TO
;CURRENT GROUP. OTHERWISE, START NEW GROUP.
SKIPN SSFLAG ;FIRST TIME THROUGH?
JRST [ SETOM SSFLAG ;YES. SET FIRST TIME FLAG
JRST SSAVB3] ;GO SET UP DIRECTORY
CALL SCOMPR ;DO COMPARISON
JRST SSAVB3 ;NEW SUBGROUP DESIRED
JUMPN T1,SSAVB4 ;T1 NOT ZERO IF WORKING ON GROUP OF
; NON-ZERO
CALL SSAVC
; SET UP DIRECTORY FOR NON-ZERO BLOCK
SSAVB3: STOR P5,EXFLG,(P1) ;MOVE ACCESS TO FIRST WORD
STOR P3,EXADR,(P1) ;MOVE FILE PAGE NO. TO 1ST WORD
MOVE T1,TADR
STOR T1,EXPAG,1(P1) ;MOVE CORE PAGE NO TO 2ND WORD
;..
;COPY NON-ZERO PAGE TO FILE (TADR POINTS TO CORE PAGE, P3 TO FILE PAGE)
;..
SSAVB4: SKIPE SSDEV ;ARE WE WRITING THE DATA PAGES?
JRST [ HRRZ T1,HANJFN ;YES.T1/JFN
MOVE T2,[POINT ^D36,0] ;T2/(36 BIT BYTES,,
HRR T2,SSCORE ;START OF CORE SCRATCH PAGE)
MOVNI T3,1000 ;T3/NEGATIVE BYTE COUNT
SOUT ;WRITE THE PAGE
ERJMP SSAVB0 ;FAILED
JRST .+1]
AOS P3 ;POINT TO NEXT FILE PAGE
;PREPARE FOR NEXT PAGE
SSAVB5: SETZ T1, ;T1/0 FOR UNMAP
MOVE T2,SSCORE ;T2/ADDRESS OF CORE SCRATCH PAGE
CALL SETMPG ;UNMAP THE CORE SCRATCH PAGE
SSB1: AOS P2 ;INCREMENT PAGE COUNT FOR SUBGROUP
AOS Q2 ;INCREMENT PAGES FROM SECTION COUNT
AOS TADR ;INCREMENT CORE PAGE NO.
AOJL Q1,SSB10 ;INCREMENT DECREASING PAGE COUNT.
; DONE IF ZERO
; ALL PAGES FOR ONE ENTRY IN INPUT TABLE ARE DONE
CALL SSAVC ;FINISH LAST DIRECTORY ENTRY AND REINITIALIZE
RETSKP ;SUCCESS
;SCOMPR used to compare consecutive pages of memory and
;tell whether a new subgroup is needed.
;
;Returns+1: new subgroup needed
; +2: no new subgroup needed
SCOMPR: LOAD T1,EXFLG,(P1) ;PUT ACCESS BITS INTO T1 RIGHT-JUSTIFIED
LOAD T2,VSECNO_-9,TADR ;SEE WHICH SECTION WE'RE DEALING WITH
CAME T2,WSEC ;DID WE JUST CROSS A SECTION BOUNDARY?
JRST [ EXCH T2,WSEC ;YES, WORRY. (SEE GETX5 COMMENT FOR WHY!)
JUMPL T2,.+1 ;DON'T WORRY MUCH IF THIS IS FIRST SECTION
CALLRET SSAVC] ;DON'T CROSS SECTION BOUNDARY IN DIRECTORY ENTRY
CAME T1,P5 ;IS ACCESS FOR THIS PAGE SAME AS FOR
; CURRENT GROUP?
CALLRET SSAVC ;START NEW SUBGROUP
LOAD T1,EXADR,(P1) ;YES. LOOK AT FILE PAGE NUMBER IN 1ST WORD
RETSKP ;SKIP TO SAY NEW SUBGROUP NOT NEEDED
;HERE IF SOUT FAILED WRITING THE .EXE FILE
SSAVB0: SETZ T1, ;UNMAPPING
MOVE T2,SSCORE ;ADDRESS OF PAGE TO UNMAP
CALL SETMPG ;UNMAP THE WINDOW
HRRZ T1,LSTERR ;GET ERROR CODE RETURNED BY SOUT
ITERR ;RETURN ERROR TO CALLER
;SSAVC - CLEANS UP THE DIRECTORY WHEN A SUBGROUP ENDS
;ACCEPTS:
; P4/ADDRESS OF SCRATCH PAGE
; P1/ ADDRESS OF CURRENT ENTRY IN DIRECTORY
; P2/ NUMBER OF PAGES IN THIS SUBGROUP
;CALL: CALL SSAVC
;CALLED BY SSAVB
;THIS ROUTINE FILLS IN THE REPEAT COUNT IN THE DIRECTORY ENTRY
;FOR THE CURRENT GROUP. THE OTHER FIELDS HAVE BEEN SET IN SSAVB
;WHEN THE GROUP BEGAN.
SSAVC: JE <EXEZRO,EXADR>,(P1),[
CAIE Q2,1000 ;HAS THE ENTIRE EMPTY SECTION BEEN SEEN?
JRST SSAVC0 ;NO, CLEAR ENTRY
MOVX CX,EXEWRB!EXEZRO ;SET FIRST WORD OF ENTRY
MOVEM CX,(P1)
MOVEI P2,1 ;SET PAGE COUNT
JRST .+1 ;WRITE ENTRY
SSAVC0: SETZM 0(P1) ;IF ALLOCATED BUT ZERO
SETZM 1(P1) ;CLEAR ENTRY
JRST SSAVC1] ;AND WRAP UP
SOS P2 ;DECREMENT PAGE COUNT
STOR P2,EXCNT,1(P1) ;SAVE IN 2ND WORD
ADDI P1,2 ;POINT TO NEXT LOCATION IN DIRECTORY
MOVE T1,P4 ;START OF DIRECTORY SCRATCH PAGE
ADDI T1,772 ;LAST WORD OF SCRATCH PAGE
SUB T1,PDVSPC ;LEAVE ROOM FOR PDV LIST
CAML P1,T1 ;P1 POINTS TO FIRST OF PAIR - IS IT
; BEYOND END?
ITERR(SSAVX4) ;YES. RETURN ERROR
SSAVC1: SETZB P2,Q2 ;CLEAR COUNT OF PAGES IN GROUP AND SECTION
RET
TNXEND
END