Trailing-Edge
-
PDP-10 Archives
-
AP-D483B-SB_1978
-
qsrfss.mac
There are 31 other files named qsrfss.mac in the archive. Click here to see a list.
TITLE QSRFSS -- Failsoft System for QUASAR
SUBTTL Larry Samberg 6 Aug 76
;***Copyright (C) 1974, 1975, 1976, Digital Equipment Corp., Maynard, Mass.***
SEARCH QSRMAC ;PARAMETER FILE
PROLOGUE(QSRFSS) ;GENERATE THE NECESSARY SYMBOLS
;
;NOTES:
;
;ALL GLOBAL ROUTINES IN THIS MODULE USE "ONLY" ACS S1 AND S2.
; CALLERS ARE GUARANTEED THAT ALL OTHER ACS WILL BE
; RETURNED INTACT.
;
;THE GLOBAL ROUTINES IN THIS MODULE MAKE ONLY ONE ASSUMPTION
; ABOUT THE CONTENTS OF THE QUEUE REQUESTS THAT THEY
; FAILSOFT, THAT IS THAT THEY CONTAIN A STANDARD MESSAGE
; HEADER.
;
;THIS ROUTINE USES A DATA-STRUCTURE CALLED THE "FILE INDEX" OR JUST
; "INDEX". UNFORTUNATELY, THE TERM "INDEX" IS USED TO DESCRIBE
; A TYPE OF REGISTER (ACCUMULATOR) IN AN INSTRUCTION. WHEN THIS
; USAGE APPEARS, AN ATTEMPT HAS BEEN MADE TO SPECIFICALLY REFER
; TO IT AS AN "INDEX REGISTER". THE TWO USAGES OF THIS WORD ARE
; DIFFERENT AND DISTINCT, AND SHOULD NOT BE CONFUSED.
COMMENT\
STOPCDs found in QSRFSS
BRS BAD REQUEST SIZE
CRF CREATE REJECTED FAILSOFT DATA
CUD CLEARING UNUSED DPA
DTL DPA TOO LARGE
DTS DPA TOO SMALL
FUD FOUND UNUSED DPA
NMF NO MORE FILESPACE
RCN REQUEST COUNT NEGATIVE
RCW REBUILD COUNT WRONG
TMS TOO MANY SECTIONS
WQV WRONG QUEUE VERSION
\
SUBTTL Description of Failsoft Files
COMMENT ?
; !=======================================================!
; ! !
; ! INDEX AND UNUSED BLOCKS FOR THIS SECTION !
; ! !
; ! !
; !-------------------------------------------------------!
; ! !
; ! !
; / DATA BLOCKS FOR THIS SECTION /
; / /
; / /
; ! !
; ! !
; !=======================================================!
; !=======================================================!
; !FORMAT VERSION OF THE QUEUE!NO. OF REQUESTS IN SECTION !
; !-------------------------------------------------------!
; ! UNUSED (CONTAINS 0) !
; !-------------------------------------------------------!
; ! !
; ! INDEX SAT MARKERS !
; ! FOR THIS INDEX BLOCK !
; ! !
; !-------------------------------------------------------!
; ! !
; / /
; / DESCRIPTION OF THE DATA BLOCKS IN THIS SECTION /
; / /
; ! !
; !=======================================================!
?
SUBTTL Storage Cells
INDEX: BLOCK 1 ;ADDRESS OF CURRENT INDEX
INDTAB: BLOCK FSSMNS ;TABLE OF INDEX ADDRESSES
SUBTTL Global Routines
;THE FOLLOWING ARE GLOBAL ENTRY POINTS IN QSRFSS
INTERN F$INIT ;INITIALIZE THE FAILSOFT SYSTEM
INTERN F$WRRQ ;WRITE OUT A REQUEST
INTERN F$RDRQ ;READ IN A REQUEST
INTERN F$RLRQ ;RELEASE A REQUEST
SUBTTL Initialization
;FAILSOFT SYSTEM INITIALIZATION
F$INIT: PUSHJ P,.SAVE1## ;SAVE P1
PUSHJ P,I$OQUE## ;GO OPEN UP THE MASTER QUEUES
PUSHJ P,REDIDX ;AND GO READ THE MASTER
HLRZ S1,@INDTAB ;GET INDEX VERSION NUMBER
CAIE S1,FSSQFV ;IS IT RIGHT?
STOPCD (WQV,FATAL) ;++WRONG QUEUE VERSION
INIT.1: CLEAR P1, ;CLEAR OUT AN INDEX REG
INIT.2: MOVE S1,P1 ;COPY ARGUMENT FOR REBILD
SKIPN INDTAB(S1) ;IS THERE ANOTHER INDEX?
POPJ P, ;NO, RETURN
PUSHJ P,REBILD ;REBUILD THIS SECTION
CAIGE P1,FSSMNS-1 ;GOT THEM ALL?
AOJA P1,INIT.2 ;NO, LOOP
POPJ P, ;YES, RETURN
;REBILD -- LOCAL ROUTINE TO REBUILD THE IN-CORE QUEUES FROM THE
; CURRENT SECTION.
;
;REBILD IS CALLED DURING INITIALIZATION (ONLY) TO READ IN AND "RE-CREATE"
; ALL THE REQUESTS IN THE SECTION WHOSE NUMBER IS IN S1.
REBILD: PUSHJ P,.SAVE4## ;SAVE P1-P4
SETZM G$ERR## ;CLEAR GLOBAL ERROR FLAG
MOVE S2,INDTAB(S1) ;GET ADR OF SECTION INDEX
MOVEM S2,INDEX ;SAVE AS CURRENT SECTION
IMULI S1,FSSBPS ;GET BASE DPA
MOVEM S1,REBI.E ;AND SAVE IT
HRRZ P1,@INDEX ;GET THE NUMBER OF REQUESTS
PJUMPE P1,.POPJ## ;RETURN IF ZERO
MOVEM P1,REBI.B ;AND SAVE IT
MOVE P2,INDEX ;GET ADDRESS OF INDEX
ADDI P2,FSSFDB ;POINT TO FIRST DATA BLOCK
MOVEM P2,REBI.A ;AND SAVE IT
MOVE P3,INDEX ;GET ADDRESS OF INDEX
ADDI P3,777 ;POINT TO LAST WORD
MOVEM P3,REBI.C ;AND STORE IT
REBI.1: SKIPN S1,0(P2) ;GET THE NEXT ENTRY
REBI.2: JRST REBI.3 ;ZERO, GO ON TO NEXT
AOJE S1,REBI.3 ;-1 MEANS CONTINUATION, IGNORE
MOVE S1,P2 ;GET THE ADDRESS
SUB S1,INDEX ;MAKE IT A DPA
ADD S1,REBI.E ;ADD IN THE BASE
MOVE P3,S1 ;SAVE DPA IN P3
PUSHJ P,F$RDRQ ;AND READ THE REQUEST
MOVEM S1,REBI.D ;SAVE THE ADDRESS
MOVE M,S1 ;AND PUT IT IN M
TXO P3,.QIFNC ;SET "INTERNAL FUNCTION" BIT
STORE P3,.MSTYP(M),MS.TYP ;AND STORE IN FUNCTION FIELD
; THE CREATE ROUTINE TREATS THE
; LOW ORDER 17 BITS OF THE MSG
; TYPE AS THE DPA ON AN INTERNAL
; CALL
PUSHJ P,Q$CREATE## ;DO THE CREATE
SKIPE G$ERR## ;DID AN ERROR OCCUR
STOPCD(CRF,FATAL) ;++CREATE REJECTED FAILSOFT DATA
MOVE AP,REBI.D ;GET THE ADDRESS OF THE REQEST
ADR2PG AP ;CONVERT TO A PAGE
PUSHJ P,M$RELP## ;RELEASE THE PAGE
SOSG P1,REBI.B ;DECREMENT AND LOAD REQUEST CNT
POPJ P, ;NO MORE, DONE
REBI.3: AOS P2,REBI.A ;INCREMENT AND LOAD INDEX-REGISTER
CAMG P2,REBI.C ;MORE, IS THERE ROOM?
JRST REBI.1 ;YES, LOOP
STOPCD (RCW,FATAL) ;++REBUILD COUNT WRONG
REBI.A: BLOCK 1 ;LOCAL STORAGE
REBI.B: BLOCK 1 ;LOCAL STORAGE
REBI.C: BLOCK 1 ;LOCAL STORAGE
REBI.D: BLOCK 1 ;LOCAL STORAGE
REBI.E: BLOCK 1 ;LOCAL STORAGE
SUBTTL F$WRRQ -- Write out a Request
;F$WRRQ IS CALLED TO FAILSOFT A REQUEST. CALL WITH S1 CONTAINING
; THE ADDRESS OF A REQUEST, AND RETURN WITH S1 CONTAINING
; A DPA FOR IT.
F$WRRQ: MOVEM S1,WRRQ.A ;SAVE THE ADDRESS
LOAD S1,.MSTYP(S1),MS.CNT ;GET THE SIZE OF THE REQUEST
MOVEM S1,WRRQ.C ;AND SAVE IT
PUSHJ P,GETDPA ;GET SOME FILE SPACE
MOVEM S1,WRRQ.B ;AND SAVE THE DPA
HRLZ S2,WRRQ.C ;GET LENGTH,,0
HRR S2,WRRQ.A ;GET LEN,,ADR
PUSHJ P,I$WRIT## ;AND WRITE IT
PUSHJ P,WRTIDX ;WRITE THE INDEX
MOVE S1,WRRQ.B ;GET THE DPA
POPJ P, ;AND RETURN IT
WRRQ.A: BLOCK 1 ;HOLDS THE ADDRESS
WRRQ.B: BLOCK 1 ;HOLDS THE DPA
WRRQ.C: BLOCK 1 ;HOLDS THE SIZE
SUBTTL F$RDRQ -- Read in a Request
;F$RDRQ IS CALLED TO READ A REQUEST FROM THE FAILSOFT SYSTEM. CALL
; F$FDRQ WITH THE DPA IN S1, AND RETURN WITH S1 CONTAINING
; THE ADDRESS OF A PAGE CONTAINING THE REQUEST.
F$RDRQ: MOVEM S1,RDRQ.B ;SAVE THE DPA
PUSHJ P,FNDDPA ;GET THE REQUEST LENGTH
HRLZM S1,RDRQ.C ;SAVE LEN,,0
MOVEM AP,RDRQ.A ;SAVE AP
PUSHJ P,M$ACQP## ;GET A PAGE
PG2ADR AP ;MAKE AN ADDRESS
EXCH AP,RDRQ.A ;GET AP BACK AND SAVE ADR
MOVE S1,RDRQ.B ;GET THE DPA
MOVE S2,RDRQ.C ;GET LEN,,0
HRR S2,RDRQ.A ;GET LEN,,ADDRESS
PUSHJ P,I$READ## ;READ THE REQUEST
MOVE S1,RDRQ.A ;GET THE ADDRESS
POPJ P, ;AND RETURN IT
RDRQ.A: BLOCK 1 ;HOLDS THE ADDRESS
RDRQ.B: BLOCK 1 ;HOLDS THE DPA
RDRQ.C: BLOCK 1 ;HOLDS LENGTH,,0
SUBTTL F$RLRQ -- Release a Request
;F$RLRQ IS CALLED TO RELEASE THE FAILSOFT SPACE FOR A REQUEST.
; IT SIMPLY WRITES OUT AN UPDATED INDEX BLOCK. CALL WITH
; S1 CONTAINING THE DPA OF THE REQUEST.
F$RLRQ: PUSHJ P,CLRDPA ;CLEAR THE INDEX WORDS OUT
PJRST WRTIDX ;WRITE THE INDEX AND RETURN
SUBTTL Index Handling Routines
; REDIDX -- READ THE INDICES DURING INITIALIZATION
; GETDPA -- ALLOCATE FAILSOFT SPACE FOR A REQUEST
; SRHIDX -- SEARCH THE INDEX FOR "N" FREE BLOCKS
; CLRDPA -- RELEASE FAILSOFT SPACE FOR A REQUEST
; FNDDPA -- FIND A FAILSOFT REQUEST IN INDEX
; WRTIDX -- WRITE OUT THE INDICES
; MRKIDX -- MARK INDEX BLOCKS FOR WRITING
SUBTTL REDIDX -- Read INDICES during initialization
;REDIDX IS CALLED DURING THE FAILSOFT SYSTEM INITIALIZATION (F$INIT)
; TO READ IN ALL THE INDICES FROM THE MASTER QUEUE FILE. IT
; ASSUMES THAT THHE MASTER QUEUE(S) HAVE BEEN OPENED AND THAT
; THE GLOBAL VARIABLE G$NBW CONTAINS THE TOTAL NUMBER OF BLOCKS
; WRITTEN IN THE FILE.
;
;IF THE FILE IS BRAND NEW, IT CREATES THE FIRST INDEX PAGE AND WRITES
; IT OUT, SO WHEN REDIDX RETURNS THERE IS ALWAYS A VALID INDEX PAGE.
REDIDX: PUSHJ P,.SAVET## ;SAVE T REGS
CLEARM INDTAB ;CLEAR THE FIRST WORD
IFG FSSMNS-1,<
MOVE S1,[INDTAB,,INDTAB+1] ;MAKE A BLT POINTER
BLT S1,INDTAB+FSSMNS-1 ;AND BLT THE BLOCK TO ZEROS
> ;END IFG FSSMNS-1
MOVE T1,G$NBW## ;GET NUMBER OF BLOCKS WRITTEN
ADDI T1,FSSBPS-1 ;ROUND UP
IDIVI T1,FSSBPS ;CONVERT TO NUMBER OF SECTIONS
CAILE T1,FSSMNS ;COMPARE AGAINST THE MAX
STOPCD (TMS,FATAL) ;++TOO MANY SECTIONS
JUMPE T1,REDI.2 ;IF BRAND NEW, CREATE IT
CLEAR T2, ;ELSE, CLEAR A COUNTER
REDI.1: PUSH P,AP ;SAVE AP
PUSHJ P,M$ACQP## ;GET A PAGE
PG2ADR AP ;CONVERT TO AN ADDRESS
MOVEM AP,INDTAB(T2) ;AND SAVE THE ADDRESS
MOVEI S1,FSSBPS ;GET BLOCKS/SECTION
IMULI S1,(T2) ;*<SECTION-1>
ADDI S1,FSSFIB ;+FIRST BLOCK = DPA
MOVSI S2,FSSWPI ;WORDS/INDEX,,0
HRR S2,AP ;WORDS/INDEX,,ADDRESS
PUSHJ P,I$READ## ;AND READ IT
POP P,AP ;RESTORE AP
SOJLE T1,.POPJ## ;RETURN IF DONE
AOJA T2,REDI.1 ;ELSE LOOP
;HERE ON A BRAND NEW FILE
;
REDI.2: PUSHJ P,GETIPG ;GET AN INDEX PAGE
MOVEM S1,INDTAB ;AND STORE IT'S ADDRESS
MOVEI S1,FSSQFV ;GET A VERSION NUMBER
HRLM S1,@INDTAB ;AND SAVE IT
MOVEI S1,FSSFIB ;DPA OF FIRST INDEX BLOCK
HRRZ S2,INDTAB ;GET ADDRESS OF INDEX PAGE
PJRST I$CRIP## ;CREATE IT AND RETURN
SUBTTL GETDPA -- Routine to allocate space in INDEX
;CALL GETDPA WITH THE SIZE OF THE REQUEST IN S1, AND RETURN WITH
; A DPA IN S1. IT PERFORMS THE FOLLOWING FUNCTIONS:
; 1)FIND FAILSOFT SPACE AND MARK IT IN USE
; 2)MARK INDEX BLOCKS FOR WRITING
; 3)INCREMENT REQUEST COUNT
GETDPA: PUSHJ P,.SAVE2## ;SAVE P1
CLEAR P1, ;AND CLEAR IT
MOVEM S1,GETD.A ;SAVE NUMBER OF WORDS NEEDED
SKIPLE S1 ;MAKE SURE IT'S REASONABLE
CAILE S1,1000 ;AS BEING NOT TOO SMALL OR TOO LARGE
STOPCD (BRS,FATAL) ;++BAD REQUEST SIZE
ADDI S1,FSSBKS-1 ;ROUND UP FIRST
IDIVI S1,FSSBKS ;AND FIND OUT HOW MANY BLOCKS
MOVEM S1,GETD.B ;AND SAVE THAT
GETD.1: MOVE S1,INDTAB(P1) ;GET NEXT INDEX
MOVEM S1,INDEX ;AND SAVE AS CURRENT INDEX
JUMPN S1,GETD.2 ;JUMP IF IT EXISTS
PUSHJ P,GETIPG ;GET AN INDEX PAGE
MOVEM S1,INDTAB(P1) ;SAVE IN INDTAB
MOVEM S1,INDEX ;AND ALSO AS CURRENT INDEX
MOVE S2,S1 ;GET ADR IN S2
MOVE S1,P1 ;GET SECTION NUMBER
IMULI S1,FSSBPS ;CONVERT TO DPA OF INDEX
PUSHJ P,I$CRIP## ;AND CREATE THE PAGE IN THE FILE
GETD.2: MOVE S1,GETD.B ;GET NUMBER OF BLOCKS NEEDED
PUSHJ P,SRHIDX ;SEARCH THIS INDEX FOR THEM
JUMPN S1,GETD.3 ;GOT THEM!!
CAIGE P1,FSSMNS-1 ;NO, ANY MORE INDICES?
AOJA P1,GETD.1 ;YUP, LOOP
STOPCD (NMF,FATAL) ;++NO MORE FILESPACE
;"GETDPA" IS CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
GETD.3: AOS @INDEX ;INCREMENT REQUEST COUNT
MOVE P2,S1 ;SAVE OFFSET OF 1ST AVAIL BLOCK
IMULI P1,FSSBPS ;GET BASE DPA FOR THIS SECTION
ADDB P1,S1 ;GET ABSOLUTE DPA OF NEW ENTRY
MOVEM P1,GETD.C ;AND SAVE IT
PUSHJ P,MRKIDX ;MARK IT AS WRITTEN
MOVEI S1,-1(P1) ;GET FIRST BLOCK - 1
ADD S1,GETD.B ;ADD # BLKS TO GET #LAST BLK
PUSHJ P,MRKIDX ;AND MARK IT
ADD P2,INDEX ;GET ADDRESS OF INDEX WORD
HRLZ S1,GETD.B ;GET #BLKS,,0
HRR S1,GETD.A ;GET #BLKS,,#WORDS
MOVEM S1,0(P2) ;SAVE IN INDEX
MOVE S2,GETD.B ;GET NUMBER OF BLOCKS
MOVE S1,GETD.C ;GET RETURN ARGUMENT
GETD.4: SOJLE S2,.POPJ## ;RETURN IF DONE
AOS P2 ;POINT TO NEXT WORD
SETOM (P2) ;MARK IT
JRST GETD.4 ;AND LOOP
GETD.A: BLOCK 1 ;LOCAL STORAGE
GETD.B: BLOCK 1 ;LOCAL STORAGE
GETD.C: BLOCK 1 ;LOCAL STORAGE
SUBTTL SRHIDX -- Routine to search INDEX for space
;CALL SRHIDX WITH S1 CONTAINING THE NUMBER OF FREE CONTIGUOUS BLOCKS
; NEEDED IN THE CURRENT INDEX. RETURNS WITH S1 CONTAINING THE
; OFFSET OF THE FIRST WORD OF THE GROUP FOUND, OR ZERO IF NO
; SPACE IS FOUND.
SRHIDX: PUSHJ P,.SAVET## ;SAVE THE T ACS
MOVE T1,INDEX ;GET ADDRESS OF THE INDEX
ADDI T1,FSSFDB ;MAKE IT ADR OF FIRST DATA BLOCK
MOVE T2,INDEX ;GET ADDRESS OF INDEX
ADDI T2,FSSWPI-1 ;GET ADR OF LAST WORD IN IT
MOVE S2,S1 ;GET NUMBER OF BLOCKS INTO S2
MOVE T4,S2 ;AND INTO T4
MOVE S1,T1 ;GET "FIRST ZERO" INTO S1
;
;HERE TO LOOP FOR THE NECESSARY NUMBER OF FREE ENTRIES
;
SRHI.1: SKIPE (T1) ;GOT A ZERO?
JRST SRHI.2 ;NO, GO SEARCH FOR ONE
SOJE T4,SRHI.4 ;YES, ALL WE NEED?
CAMGE T1,T2 ;NO, ANYTHING ELSE TO SEARCH?
AOJA T1,SRHI.1 ;YES, LOOP
JRST SRHI.3 ;NO, RETURN ZERO
;
;HERE IF WE FIND A NON-ZERO WORD
;
SRHI.2: CAMGE T1,T2 ;REACHED THE END?
AOSA T1 ;NO, BUMP THE POINTER AND SKIP
JRST SRHI.3 ;YES, RETURN FAILURE
MOVE T4,S2 ;RELOAD #BLKS NEEDED
MOVE S1,T1 ;RELOAD "FIRST ZERO"
JRST SRHI.1 ;AND GO BACK TO THE LOOP
;
;HERE TO RETURN A ZERO
;
SRHI.3: CLEAR S1, ;CLEAR THE AC
POPJ P, ;AND RETURN
;
;HERE WHEN WE FIND "N" CONSECUTIVE ZEROS. S1 CONTAINS THE "FIRST ZERO".
;SUBTRACT THE BASE ADDRESS AND RETURN THE OFFSET.
;
SRHI.4: SUB S1,INDEX ;SUBTRACT THE ADR OF THE INDEX
POPJ P, ;AND RETURN
SUBTTL CLRDPA -- Release Failsoft Space for a request
;CLRDPA IS CALLED WITH A DPA IN S1. IT PERFORMS THE FOLLOWING FUNCTIONS:
; 1) CLEAR SPECIFIED FAILSOFT ENTRIES
; 2) DECREMENT REQUEST COUNT
; 3) MARK INDEX BLOCK FOR WRITING
CLRDPA: MOVEM S1,CLRD.A ;SAVE DPA
PUSHJ P,VALDPA ;INSURE A CORRECT DPA
MOVE S1,INDTAB(S1) ;GET ADR OF THE SECTION INDEX
MOVEM S1,INDEX ;AND SAVE AS CURRENT INDEX
ADD S2,S1 ;GET ADDRESS OF ENTRY INTO S2
HLRZ S1,(S2) ;GET NUMBER OF BLOCKS IN ENTRY
MOVEM S1,CLRD.B ;AND SAVE IT
CLRD.1: SKIPN (S2) ;MAKE SURE IT WAS IN USE
STOPCD (CUD,FATAL) ;++CLEARING UNUSED DPA
CLEARM (S2) ;CLEAR A WORD
SOJLE S1,CLRD.2 ;DONE?
AOJA S2,CLRD.1 ;NO, LOOP FOR ALL BLOCKS
CLRD.2: SOS S1,@INDEX ;DECREMENT REQUEST COUNT
TRNE S1,400000 ;DID WE GO PAST 0?
STOPCD (RCN,FATAL) ;++REQUEST COUNT NEGATIVE
MOVE S1,CLRD.A ;GET DPA OF FIRST BLOCK
PUSHJ P,MRKIDX ;MAKE IT
MOVE S1,CLRD.A ;GET DPA OF FIRST BLOCK
ADD S1,CLRD.B ;ADD NUMBER OF BLOCKS
SUBI S1,1 ;AND BACK OFF BY ONE
PJRST MRKIDX ;MARK THE INDEX AND RETURN
CLRD.A: BLOCK 1 ;LOCAL STORAGE
CLRD.B: BLOCK 1 ;LOCAL STORAGE
SUBTTL FNDDPA -- Find a failsoft entry in the INDEX
;FNDDPA IS CALLED WITH S1 CONTAING A DPA AND RETURNS WITH S1
; CONTAINING THE INDEX ENTRY FOR THAT DPA, I.E.
; XWD #BLOCKS,,#WORDS.
FNDDPA: PUSHJ P,VALDPA ;INSURE A CORRECT DPA
MOVE S1,INDTAB(S1) ;GET ADR OF SECTION INDEX
ADD S1,S2 ;NO, ADD IT IN
MOVE S1,0(S1) ;AND GET THE ENTRY
JUMPN S1,.POPJ## ;RETURN IF GOOD
STOPCD (FUD,FATAL) ;++FOUND UNUSED DPA
SUBTTL WRTIDX -- Routine to write out the INDEX
;WRTIDX LOOPS THRU THE INDEX-SAT TABLE LOOKING FOR INDEX BLOCKS WHICH
; HAVE BEEN CHANGED, AND CAUSES EACH CHANGED INDEX BLOCK TO BE
; RE-WRITTEN.
WRTIDX: PUSHJ P,.SAVET## ;SAVE THE T REGS
CLEAR T3, ;CLEAR THE SECTION INDEX REG
WRTI.1: MOVE T1,INDTAB(T3) ;GET ADR OF SECTION INDEX
MOVEM T1,INDEX ;AND SAVE AS CURRENT
JUMPE T1,.POPJ## ;IF ZERO, WE ARE DONE
MOVEI T2,FSSFIB ;GET NUMBER OF FIRST INDEX BLOCK
ADD T2,INDEX ;GET ADR OF ITS SAT-WORD
CLEAR T1, ;CLEAR AN INDEX REG
WRTI.2: SKIPE S2,(T2) ;WAS THIS BLOCK CHANGED?
CLEARM (T2) ;YES, CLEAR THE FLAG
JUMPE S2,WRTI.3 ;IF NOT, KEEP LOOPING
MOVEI S2,FSSBKS ;GET WORDS/BLOCK
IMUL S2,T1 ;MAKE OFFSET INTO INDEX
ADD S2,INDEX ;MAKE ABSOLUTE ADDRESS
HRLI S2,FSSBKS ;MAKE S2, AND IO-POINTER
MOVEI S1,FSSFIB(T1) ;GET THE DPA FOR THE BLOCK
MOVEI T4,FSSBPS ;GET NUMBER OF BLOCKS/SECTION
IMUL T4,T3 ;GET BASE BLOCK # FOR THIS SEC
ADD S1,T4 ;ADD IT IN
PUSHJ P,I$WRIT## ;WRITE THEM OUT
WRTI.3: AOS T2 ;AOS A POINTER
CAIGE T1,FSSNIB-1 ;GOT ALL THE BLOCKS?
AOJA T1,WRTI.2 ;NO, LOOP
CAIGE T3,FSSMNS-1 ;GOT ALL THE SECTIONS?
AOJA T3,WRTI.1 ;NO, LOOP
POPJ P, ;YES, RETURN
SUBTTL MRKIDX -- Routine to mark INDEX blocks to write
;MRKIDX IS CALLED TO MARK AN INDEX BLOCK AS HAVING BEEN CHANGED.
; CALL WITH THE DPA WHICH HAS CHANGED.
;
;MRKIDX ALWAYS MARKS THE FIRST INDEX BLOCK IN THE SECTION AS HAVING
; BEEN CHANGED, SINCE THE REQUEST COUNT IS THERE.
MRKIDX: PUSH P,T1 ;SAVE T1
PUSHJ P,VALDPA ;INSURE A CORRECT DPA
MOVE T1,INDTAB(S1) ;AND GET ADR OF IT'S INDEX
MOVE S1,S2 ;COPY OFFSET INTO S1
IDIVI S1,FSSBKS ;CONVERT IT TO A BLOCK
SETOM FSSFIB(T1) ;MARK THE FIRST BLOCK
ADD T1,S1 ;ADD THE BLOCK NUMBER IN
SETOM FSSFIB(T1) ;AND MARK THE BLOCK
POP P,T1 ;RESTORE T1
POPJ P, ;AND RETURN
SUBTTL Utility Routines
; GETIPG -- GET A ZEROED PAGE FOR AN INDEX
; VALDPA -- VALIDATE A DPA GIVEN AS AN ARGUMENT TO THE FAILSOFT ROUTINES
SUBTTL GETIPG -- Get a zeroed page for an index
;GETIPG CALLS M$ACQP TO GET A FREE PAGE, ZEROES IT OUT AND RETURNS
; THE ADDRESS OF THE FIRST WORD OF THE PAGE IN S1.
GETIPG: SAVE AP ;SAVE AP
PUSHJ P,M$ACQP## ;GET A PAGE
PG2ADR AP ;MAKE IT AN ADDRESS
MOVE S1,AP ;GET ARG IN S1
PUSHJ P,.ZPAGA## ;ZERO IT
MOVE S1,AP ;RETURN ADDRESS IN S1
POPJ P, ;AND RETURN
SUBTTL VALDPA -- Validate a DPA
;VALDPA IS CALLED WITH S1 AS A DPA GIVEN AS AN ARGUMENT TO THE FAILSOFT
; SYSTEM ROUTINES. IF THE DPA IS INVALID, A STOPCD RESULTS,
; OTHERWISE, S1 IS RETURNED AS THE CORRECT SECTION NUMBER FOR THAT
; DPA AND S2 IS THE OFFSET INTO THAT SECTION.
VALDPA: MOVEM S1,VALD.A ;SAVE IN CASE OF STOPCD
IDIVI S1,FSSBPS ;S1 = SECTION NUMBER, S2 = OFFSET
CAIL S1,FSSMNS ;SECTION TOO LARGE
STOPCD(DTL,FATAL) ;++DPA TOO LARGE
CAIGE S2,FSSFDB ;BELOW THE FIRST DATA BLOCK
STOPCD(DTS,FATAL) ;++DPA TOO SMALL
POPJ P, ;RETURN WITH S1 AND S2 SET
VALD.A: BLOCK 1 ;LOOK HERE IF A STOPCD RESULTED
END