Google
 

Trailing-Edge - PDP-10 Archives - bb-bt99q-bb - refstr.x23
There is 1 other file named refstr.x23 in the archive. Click here to see a list.
TITLE REFSTR - ROUTINE TO REFRESH A FILE STRUCTURE - V153
SUBTTL  D BLACK 	11 APR 89

	SEARCH	F,S,DEVPRM
	$RELOC
	$INIT


;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
;  OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION
; 1973,1974,1975,1976,1977,1978,1979,1980,1982,1984,1986,1988.
;ALL RIGHTS RESERVED.

.CPYRT<1973,1988>


XP VREFST,153

ENTRY REFSTR


;INTERNS FOR ONCMOD

XP	RB1UN,^D9	;NO OF BLOCKS REFRESHER CREATES ON 1ST UNIT IN STR
XP	RBLUN,5		;NO OF BLOCKS REFRESHER CREATES ON LAST UNIT IN STR

;QUOTAS FOR UFD'S WE CREATE

QR==0			;RESERVED QUOTA
QF==377777777777	;FIRST COME, FIRST SERVED QUOTA
QO==377777777777	;LOGGED OUT QUOTA


;LOCAL FEATURE TEST TO DOCUMENT CODE WHICH USED TO CREATE MAINT.SYS

XPL	FTMAINT,0	;NOT USED
	SUBTTL	REFRESH A FILE STRUCTURE

;ROUTINE TO REFRESH A FILE STRUCTURE
;ARGS	T1=SIXBIT NAME OF STR
;	P2=ADDR OF STR DATA BLOCK
;	F=ADDR OF DDB

REFSTR::PUSHJ	P,SAVE4##	;SAVE PERMANENT ACS (P1-P4)
	PUSH	P,JBTADR##	;MAY BE NEEDED LATER
	MOVEM	P,SAVEP		;SAVE PDL IN CASE ERROR RETURN
	SKIPE	.UONCE##	;USER-MODE?
	PUSHJ	P,USRDTM##	;YES, SET UP DATE/TIME
	MOVEI	T1,NU0DAC##
	MOVEM	T1,JBTADR##
	MOVEI	T1,RIPNDL##!RIPNFS##	;NO DELETE FILE BIT
	MOVEM	T1,NDNCNF	;PLUS NO FAILSAFE BIT
	ADDI	T1,RIPABC##	;ADD IN ALWAYS BAD CHECKSUM FOR SOME FILES
	MOVEM	T1,NDCFAB	;AND SAVE ALL BITS
	HLRZ	U,STRUNI##(P2)	;U=ADDR OF FIRST UNIT IN STR
	HRRZM	U,FSTUNI	;REMEMBER FIRST UNIT
	SKIPN	T1,@ONCMBF##	;USE MONITOR BUFFER ALREADY ALLOCATED FOR SAT RIB
	STOPCD	REFERR,DEBUG,REFMBM, ;++MONITOR BUFFER MISSING
	MOVEM	T1,SATRBA	;(ALSO SAVES POINTER)
	MOVSI	P1,-CORN+1	;MINUS NUMBER OF EXTRA BUFFERS WE NEED
REF1:	MOVEI	T1,BLKSIZ##	;AMOUNT OF CORE FOR 1 BUFFER
	PUSHJ	P,INICOR##	;GET A MONITOR BUFFER (SIZE OF DISK BLOCK)
	HRLI	T2,-BLKSIZ##	;-SIZE OF A DISK BLOCK
	SUBI	T2,1		;MAKE AN IOWD
	MOVEM	T2,SATRBA+1(P1)	;SAVE IOWD
	AOBJN	P1,REF1		;LOOP FOR ALL BUFFERS NEEDED
	MOVE	T1,HOMRBA	;IOWD FOR HOME BLOCK
	MOVEM	T1,@ONCMBF##	;SAVE IOWD IN MONITOR BUFFER
	PUSHJ	P,GTHOM##	;READ IN A HOME BLOCK FROM 1ST UNIT
	  JRST	ERHMSG		;ERROR READING HOME.SYS
	HRRZ	P2,UNISTR(U)	;RESET P2=ADDR OF STR DATA BLOCK
	MOVE	T1,HOMRBA
	SKIPN	J,HOMBPC##+1(T1) ;BLOCKS PER CLUSTER THIS STR
	JRST	ZBCMSG		;ZERO BLOCKS PER CLUSTER
	SETO	T2,
	LDB	T4,STYCNP##(P2)	;T4=MAX CLUSTERS CAN ALLOCATE IN 1 PTR
	MOVEM	T4,MAXALC	;SAVE FOR LATER
	HRRZI	T1,HOMLEN##+1(T1) ;ADDR OF BEGINNING OF FILE LENGTHS
	HRLI	T1,-LSTLEN	;NUMBER OF LENGTHS
	MOVSI	T2,-ZERLEN-1	;COUNTER FOR THOSE WHICH CAN BE 0
	HRRI	T2,FSTLEN	;BEGINNING OF DESTINATION TABLE
	HRREI	P1,-2(J)	;TRY FOR ONLY 1 CLUSTER
	CAIG	P1,0		;SKIP IF AT LEAST 1 DATA BLOCK
	MOVEI	P1,1		;INSIST ON 1
REF1A:	MOVE	T3,(T1)		;T3=VALUE FROM HOME BLOCK
	AOBJN	T2,REF1B	;JUMP IF 0 IS OK
	CAIN	T3,0		;SKIP IF NOT 0
	MOVE	T3,P1		;SET TO MINIMUM VALUE (PROBABLY UFD'S)
REF1B:	MOVEM	T3,-1(T2)
	AOBJN	T1,REF1A	;LOOP FOR ALL LENGTHS
	SETZM	FSTBK		;CLEAR UNIT TABLE
	MOVE	T1,[XWD FSTBK,FSTBK+1]
	BLT	T1,FSTUNW+LSTUNW-1
	SUBTTL	PRESERVE FE.SYS

;FIND FE.SYS, IF IT EXISTS

	HRRZ	U,FSTUNI	;START AT FIRST UNIT
	JRST	REF1D		; (HOME BLOCKS FOR THIS UNIT ALREADY IN CORE)
REF1C:	PUSHJ	P,GTHOM##	;READ HOME BLOCKS
	  JRST	CRHMSG		;CAN'T READ HOME BLOCKS
	LDB	J,UNYBPC##
	HRRZ	P2,UNISTR(U)
REF1D:	MOVE	T1,HOMRBA	;IOWD FOR HOME BLOCKS
	SKIPE	T2,HOMFEB##+1(T1) ;UNIT CONTAIN FE.SYS?
	TLZN	T2,FEVALID##	;YES, IS IT VALID?
	JRST	REF1F		;NO
	HLRZ	T3,T2		;CHANGE PDP-11 SPLIT
	LSH	T3,^D16		;WORD FORMAT
	ANDI	T2,177777	;INTO 10 FORMAT
	IOR	T2,T3
	SUBI	T2,1		;YES, POINT AT RIB ADDRESS
	MOVE	T3,T2		;COPY BLOCK #
	HLRZ	T4,STRBSC##(P2)	;BLOCKS/SCLUST
	IDIV	T3,T4		;IS IT STILL ON A SCLUST BOUNDARY?
	JUMPE	T4,FERIB	;YES
FELOSE:	PUSHJ	P,OTSET##	;NO, TELL HIM BAD NEWS
	MOVEI	T1,[ASCIZ/
%Cannot preserve FE.SYS
/]
	PUSHJ	P,ICONM##	;START MESSAGE
	PUSHJ	P,OPOUT##	;AND OUTPUT IT
	JRST	REF1E		;FLAG NOT VALID
FERIB:	MOVEM	T2,FERBD	;BLOCK IS OK, SAVE IT
	MOVEM	U,FEUN
	MOVE	T1,FERBA
	MOVEM	T1,@ONCMBF##	;POINT TO ONCE AREA
	PUSHJ	P,OMNRED##	;GO READ WHAT PURPORTS TO BE FE.SYS
	  TLO	S,-1		;IO ERROR
	LDB	J,UNYBPC##	;RESET J
	HRRZ	P2,UNISTR(U)	; AND P2
	TLZE	S,-1		;IO ERROR?
	JRST	REF1E		;LOSE, TRY ANOTHER UNIT
	MOVE	T1,FERBA	;WON, POINT AT RIB
	MOVE	T2,RIBPPN##+1(T1) ;MAKE SURE IT REALLY IS A RIB
	MOVE	T3,RIBNAM##+1(T1) ; FOR FE.SYS[1,4]
	CAMN	T2,SYSPPN##
	CAME	T3,[SIXBIT .FE.]
	JRST	REF1E		;NO IT ISN'T
	HLRZ	T2,RIBEXT##+1(T1)
	CAIE	T2,'SYS'
	JRST	REF1E
	MOVE	T2,RIBALC##+1(T1) ;YES IT IS.  CHECK LENGTH
	IDIVI	T2,(J)		;INTEGRAL # OF CLUSTERS?
	JUMPN	T3,FELOSE	;..
	MOVEM	T2,FELEN	;SAVE IF SO
	MOVE	T4,1(T1)	;GET FIRST RIB WORD
	ADDI	T4,(T1)		;RELOCATE TO BUFFER
	LDB	T2,UNYLUN##	;GET UNIT POINTER
	TRO	T2,RIPNUB##	;MAKE CHANGE-UNIT-PTR
	PUSH	T4,T2		;PUT IN
	MOVE	T2,FERBD	;GET DATA BLOCK OF RIB
	IDIVI	T2,(J)		;T2=CLUSTER ADDR OF FE.SYS'S RIB
	MOVE	T3,FELEN	;LENGTH
	PUSH	P,T4		;SAVE T4
	IDIV	T3,MAXALC	;T3=#GROUPS IN FE.SYS
	JUMPN	T4,FERB00
	EXCH	T4,(P)
	JRST	FERB01
FERB00:	DPB	T4,STYCNP##(P2)	;BUILD IN T2
	MOVE	T4,(P)		;RESTORE T4
	MOVEM	T2,(P)		;AND SAVE T2
FERB01:	MOVE	T1,MAXALC	;GET MAX POINTER
	DPB	T1,STYCNP##(P2)	;AND BUILD IT IN T2
FERB0:	JUMPN	T3,FERB1	;MORE FULL POINTERS TO DO IF T3 NON-ZERO
	POP	P,1(T4)		;NONE, PUT LAST CLUSTER IN
	SOJA	T3,FERB2	;FLAG NOT TO DO THIS AGAIN
FERB1:	SETZM	1(T4)		;DEFAULT NO POINTER
	SOJL	T3,FERB2	;WHICH IS CORRECT
	MOVEM	T2,1(T4)	;ELSE SET FULL POINTER
	ADD	T2,T1		;AND POINT TO NEXT CLUSTER
	ADDM	T1,(P)		;AND LAST NEXT CLUSTER
FERB2:	AOBJN	T4,FERB0	;LOOP OVER ALL RIB POINTER SLOTS
	JUMPGE	T3,FELOSE	;IF TOO MANY TO FIT, LOSE
	JRST	REF1G		;DONE
REF1E:	SETZM	FEUN		;NOT FE.SYS, CLEAR FLAG
	SETZM	FERBD		;CLEAR RIB BLOCK NUMBER TOO
REF1F:	HLRZ	U,UNISTR(U)	;TRY NEXT UNIT
	JUMPN	U,REF1C
	SUBTTL	SET UP HOME.SYS AND SAT.SYS

REF1G:	HRRZ	U,FSTUNI	;RESET U TO 1ST UNIT IN STR
	SETZB	T1,UFDBKS	;CLEAR TOTAL BLOCKS ALLOCATED IN CURRENT UFD
	PUSHJ	P,CHEKS1	;COMPUTE CHECKSUM FOR A WORD OF 0
	MOVEM	T1,CHECK0	;AND SAVE THAT SINCE WE NEED IT A LOT
	MOVSI	T1,SYRDPR##	;STANDARD ACCESS CODE FOR SYSTEM FILES
	MOVEM	T1,CURPRT	;SAVE FOR RIBSET

;HERE TO SET UP RIB IN CORE FOR HOME.SYS

	MOVE	T4,HOMRBA	;POINTER TO HOME.SYS RIB IN CORE
	MOVE	T1,HOMFNM	;NAME OF HOME.SYS FILE
	MOVSI	T2,(SIXBIT .SYS.)
	MOVE	T3,SYSPPN##	;IN SYS UFD
	MOVE	P4,NDCFAB	;NO DELETE, NO CHANGE NAME, NO FAILSAFE BITS
	PUSHJ	P,RIBSET	;SET UP RIB FOR HOME.SYS
	MOVEM	T4,HOMRBP	;T4 IS POINTER TO RETRIEVAL POINTERS

;HERE TO SET UP RIB IN CORE FOR SAT.SYS

	MOVE	T4,SATRBA	;POINTER TO SAT.SYS RIB IN CORE
	MOVE	T1,SATFNM	;NAME OF SAT.SYS FILE
	MOVSI	T2,(SIXBIT .SYS.)
	MOVE	T3,SYSPPN##	;IN SYS UFD
	MOVE	P4,NDCFAB	;ALL STATUS BITS
	PUSHJ	P,RIBSET	;SET UP RIB FOR SAT.SYS
	MOVEM	T4,SATRBP	;POINTER TO RETRIEVAL POINTERS FOR SAT.SYS

;HERE FOR NEXT UNIT IN STR

REF2:	MOVE	T1,UNIHOM(U)	;LOGICAL BLOCK NUMS FOR HOME BLOCKS
	MOVEM	T1,LBNLST
	MOVE	T2,[XWD LBOBAT##,LBOBAT##]	;OFFSET FOR BAT BLOCKS
	ADD	T2,T1
	MOVEM	T2,LBNLST+1
	MOVE	T2,[XWD LBOISW##,LBOISW##]	;OFFSET FOR ISW BLOCKS
	ADD	T2,T1
	MOVEM	T2,LBNLST+2
	PUSHJ	P,REDBAT	;READ BAT BLOCK
	PUSHJ	P,STNWUN	;STORE NEW UNIT POINTER IN SAT.SYS RIB
	PUSHJ	P,HOMRBS	;STORE IN HOME.SYS RIB
	LDB	T1,UNYLUN##
	JUMPN	T1,SETSAT	;JUMP IF NOT FIRST UNIT
	MOVE	T1,SATRBP
	MOVEM	T1,SATUN	;SAVE INITIAL POINTER TO RETRIEVAL PTRS
	PUSHJ	P,SATRBS	;AND SAVE A SPACE FOR 1ST RIB PTR (CLS CNT=0)
	MOVE	T1,HOMRBP	;SAME THING FOR HOME.SYS
	MOVEM	T1,HOMUN
	PUSHJ	P,HOMRBS
SETSAT:	MOVE	T1,UNIBPU(U)	;BLOCKS ON THIS UNIT
	IDIV	T1,J		;THEORETICALLY, ((BLOCKS-1)/BPC)+1=CLUSTERS
	SUBI	T1,1		;-1
	LDB	T2,UNYSPU##	;T2=SATS ON THIS UNIT
	JUMPE	T2,FEWSAT	;JUMP IF NO SAT BLOCKS ON UNIT
	IDIV	T1,T2		;THEORETICALLY, (CLUSTERS-1/SATS)+1=CLUSTERS/SAT
	MOVEM	T1,LCLSAT	;-1=LAST CLUSTER IN FIRST SAT
	ADDI	T1,1		;+1 FOR ALL BUT LAST SAT, WHICH IS ADJUSTED
				;TO MAKE THE TOTAL CORRECT
	MOVEM	T1,SVSBTL	;SAVE CLUSTERS PER SAT
	IDIVI	T1,^D36*^D118
	JUMPG	T1,FEWSAT
	SETZM	BEGSAT		;BEGSAT=1ST CLUSTER THIS SAT
	SETOM	DAREQ##		;MAKE SURE DA RESOURCE AVAILABLE
	SETOM	SATIND		;USE SWPUN AS TEMP SAT INDEX, SET TO -1

;HERE TO CREATE NEXT SAT BLOCK FOR THIS UNIT

MRKSAT:	HRRZ	T1,SATBKA	;ADDR OF SAT BLOCK IN CORE
	MOVE	T2,SVSBTL	;ACTUAL CLUSTERS THIS SAT
	PUSHJ	P,MRKEND	;CLEAR BLOCK AND SET BITS IN LAST WORD

;HERE TO SCAN BAT BLOCK AND MARK CLUSTERS CONTAINING BAD BLOCKS

	HRRZ	T1,BATBKA
	MOVE	T2,[PUSHJ P,SETBAD]	;INSTRUCTION TO EXECUTE FOR BAD BLOCKS
	PUSHJ	P,SCNBAT	;SCAN BAT BLOCK AND EXECUTE T2 FOR EACH BAD BLOCK

;HERE TO SET UP FE.SYS, IF THERE USED TO BE ONE
	SKIPE	P3,FERBD	;WAS THERE AN FE.SYS?
	CAME	U,FEUN		;YES, ON THIS UNIT?
	JRST	MRKBD1		;NO
	MOVE	P4,FELEN	;YES, MARK ITS BLOCKS TAKEN IN SAT
MRKFE:	MOVE	T1,P3
	PUSHJ	P,SETSWP	; NOTE THAT WE LEAVE THE RIB ALONE,
	ADD	P3,J		; AS A VALID RIB EXISTS ON DSK. WE ARE JUST POINTING
	SOJG	P4,MRKFE	; THE UFD AT IT AND MARKING ITS BITS IN SAT
;HERE TO MARK BITS FOR SWAPPING REGION

MRKBD1:	LDB	P3,UNYK4S##	;P3=J FOR SWAP ON THIS UNIT
	JUMPE	P3,MRKSW1	;SKIP THIS IF NONE
	LSH	P3,BLKSPK
	SKIPA	P4,UNISLB(U)	;P4=1ST LOGICAL BLOCK
MRKSW2:	ADDI	P4,1		;P4=NEXT LOGICAL BLOCK
	MOVE	T1,P4		;T1=CURRENT LOGICAL BLOCK
	PUSHJ	P,SETSWP	;SET BIT IN SAT BLOCK
	SOJG	P3,MRKSW2	;LOOP FOR ALL SWAP BLOCKS
MRKSW1:	SKIPE	T1,BEGSAT	;SKIP IF THIS IS 1ST SAT ON THIS UNIT
	JRST	ENDSAT

;HERE TO ALLOCATE BLOCKS IN HOME.SYS FILE

	PUSHJ	P,GETHMC	;ALLOCATE BLOCK 0
	  JRST	BADHOM		;CAN'T GET 1ST HOME BLOCK
	PUSHJ	P,HOMRBS	;STORE RETRIEVAL POINTER
	LDB	P3,STYCLP##(P2)	;REMEMBER LAST CLUSTER ALOCATED (FROM T2)
	MOVSI	T3,-LBNLEN
	HLRZ	T1,LBNLST(T3)
	PUSHJ	P,GETHMB	;GET NEXT BLOCK IN THE GROUP
	AOBJN	T3,.-2		;LOOP FOR ALL OF 1ST GROUP
	MOVE	T3,[XWD MNBOOT##,FBOOTB##]	;T3=-# BLOCKS FOR BOOTS, 1ST BLOCK
	HRRZ	T1,T3		;NEXT BLOCK TO ALLOCATE
	PUSHJ	P,GETHMB	;ALLOCATE THE BLOCK
	AOBJN	T3,.-2		;LOOP FOR ALL BLOCKS TO ALLOCATE FOR BOOTS
	MOVSI	T3,-LBNLEN
	HRRZ	T1,LBNLST(T3)	;AND NOW 2ND GROUP
	PUSHJ	P,GETHMB
	AOBJN	T3,.-2		;LOOP FOR ALL THE GROUP
	MOVE	P1,UNISAB(U)	;ADDR OF FIRST SAB BLOCK IN CORE
ENDSAT:	SETZ	T1,		;DONT CARE WHERE SAT GOES IN REGION
	PUSHJ	P,RTAKBK	;GET A BLOCK FOR THE SAT BLOCK
	  STOPCD REFERR,DEBUG,NSS,DIEUNI##, ;++NO SPACE FOR SAT
	PUSHJ	P,SATRBS	;STORE RETRIEVAL POINTER IN SAT.SYS RIB
	LDB	T4,STYCLP##(P2)	;CLUSTER FOR SAT BLOCK
	IMUL	T4,J		;T4=LOGICAL BLOCK NUMBER OF BEGINNING OF CLUSTER
	MOVE	T1,SATBKA	;IOWD FOR SAT BLOCK
	ADDI	T1,1		;MAKE AOBJN PTR
	PUSH	P,R		;SAVE POINTER TO MON BUFFER
	SETZ	R,		;NO RELOCATION
	PUSHJ	P,SATCN##	;COUNT 0 BITS IN T2
	POP	P,R		;RESTORE R
	MOVE	T3,T4		;T3=BEGINNING OF CLUSTER
	EXCH	T2,T3		;T2=BEGINNING OF CLUSTER, T3=FREE CLUSTERS
	AOS	T4,SATIND	;GET INDEX OF THIS SAT
	MOVE	P4,T4		;SAVE IN P4 FOR LATER
	ADD	T4,UNISPT(U)	;POINTER TO SPT ENTRY FOR THIS SAT
IFN FTXMON,<XJRST [MCSEC1+.+1]>	;MUST BE IN SECTION 1 TO REFERENCE THE SAB RING
	EXCH	P1,P2		;P2=ADDR OF THIS SAT
	DPB	T3,SPYTAL##	;STORE COUNT OF FREE CLUSTERS
	PUSH	P,T2		;SAVE LOG BLOCK OF THIS SAT
	IDIV	T2,J		;CLUSTER ADDR OF THIS SAT
	DPB	T2,SPYCLA##	;STORE IN SPT ENTRY
	MOVE	T1,SATBKA	;IOWD
	MOVE	T2,(P)		;LOG BLOCK NUM
	S0PSHJ	BLKWRT		;WRITE OUT THE SAT BLOCK
	LDB	T1,UNYSIC##	;SAT'S IN CORE
	CAMLE	T1,P4		;SKIP IF INDEX IS GT LAST IN CORE
	PUSHJ	P,SATIN		;ELSE READ INTO MONITOR CORE
	MOVE	P2,SABRNG##(P2)	;ADDR OF NEXT SAT IN RING
IFN FTXMON,<XJRST [MCSEC0+.+1]>	;BACK TO SECTION 0 FOR I/O
	EXCH	P1,P2
	MOVE	T1,SATBKA
	SETOM	1(T1)		;SET 1ST WORD TO ONES
	PUSHJ	P,CORONZ	;SET WHOLE BUFFER TO ONES
	POP	P,T2		;RESTORE LOGICAL BLOCK OF BEGINNING OF CLUSTER
	PUSHJ	P,FINCLS	;WRITE OUT ONES IN ALL UNUSED BLOCKS THIS CLUSTER
	MOVE	T1,UNIBPU(U)	;T1=BLOCKS ON THIS UNIT
	IDIV	T1,J		;CONVERT TO FULL CLUSTERS ON UNIT
	MOVE	T2,SVSBTL	;CLUSTERS IN THIS SAT
	ADDB	T2,BEGSAT	;LAST CLUSTER IN THIS SAT+1
	CAML	T2,T1		;SKIP IF NOT PAST END OF UNIT
	JRST	ALSAUN		;NO MORE SATS THIS UNIT
	ADD	T2,SVSBTL	;COMPUTE END OF NEXT SAT+1
	SUBI	T2,1
	MOVEM	T2,LCLSAT	;REMEMBER LAST CLUSTER THIS SAT
	ADDI	T2,1		;BUT WE NEED MORE
	CAMG	T2,T1		;SKIP IF GR THAN LAST BLOCK+1
	JRST	MRKSAT		;NO, KEEP GOING
	SUB	T2,T1		;FIND OUT HOW MUCH OVER
	SUBM	T2,SVSBTL	;AND SUBTRACT THAT FROM SIZE OF LAST SAT
	SUBM	T2,LCLSAT	;AND FROM LAST CLUSTER THIS SAT
	MOVNS	SVSBTL		;EXCEPT IT COMES OUT NEGATIVE THAT WAY
	MOVNS	LCLSAT
	JRST	MRKSAT		;LOOP FOR ALL SATS THIS UNIT
ALSAUN:	MOVE	T1,U		;REMEMBER CURRENT UNIT IN CASE IT'S THE LAST
	HLRZ	U,UNISTR(U)	;NEXT UNIT IN STR
	JUMPN	U,REF2		;LOOP FOR ALL UNITS IN STR
;HERE AFTER ALL SATS ON ALL UNITS ARE WRITTEN

	HRLM	T1,LSTUNI	;REMEMBER LAST UNIT IN STR
	HRRZ	U,FSTUNI	;RESET TO FIRST UNIT IN STR

;HERE TO ALLOCATE SPACE FOR SYS UFD (NEED THIS TO STORE BLOCK NUMBER OF
; UFD IN RIB OF EACH FILE WE CREATE)

	MOVE	T2,SYUFSZ	;NUMBER OF DATA BLOCKS FOR SYS UFD
	PUSHJ	P,HIALCU	;ALLOCATE SPACE FOR SYS UFD
	MOVEM	T1,SYSRBD	;REMEMBER FOR HOME BLOCK
	MOVEM	U,SYSUN

;HERE TO WRITE RIBS FOR SAT.SYS AND HOME.SYS ON LAST UNIT
;ALLOCATE 1ST RIB FOR SAT.SYS

	PUSHJ	P,CATKB		;GET A BLOCK FOR 1ST SAT.SYS RIB
	LDB	T1,STYCLP##(P2)	;CLUSTER ADDR
	IMUL	T1,J		;T1=LOGICAL BLOCK NUMBER OF RIB
	MOVEM	T1,SATRBD	;REMEMBER LOGICAL BLOCK NUMBER OF SAT.SYS RIB
	MOVE	T3,SATUN	;INITIAL PTR TO RETRIEVAL PTRS
	EXCH	T3,SATRBP	;REMEMBER PRESENT, RESET INITIAL
	PUSHJ	P,SATRBS	;STORE RETRIEVAL POINTER FOR SAT.SYS RIB
	MOVEM	T3,SATRBP	;RESTORE PRESENT POSITION
	PUSHJ	P,CMPSIZ	;COMPUTE NUMBER OF WORDS WRITTEN, SETS T4=PTR TO RIB
	MOVE	T1,MFDRBD
	MOVEM	T1,RIBUFD##+1(T4)
	MOVEM	U,SATUN
	MOVE	T2,SATRBD	;LOGICAL BLOCK NUM OF 1ST RIB
	PUSHJ	P,FINCLS	;WRITE ONES IN REST OF CLUSTER
	HLRZ	U,LSTUNI	;RESET TO LAST UNIT
	HRRZ	T4,FSTUNI	;ADDR OF UNIT FOR 1ST RIB
	MOVE	T3,SATRBD	;LOGICAL BLOCK NUM OF 1ST RIB FOR SAT.SYS
	PUSHJ	P,FIL2RB	;ALLOCATE 2ND RIB AND WRITE OUT RIBS
;HERE WHEN SAT.SYS HAS BEEN CREATED
;ALLOCATE 1ST RIB FOR HOME.SYS

	HRRZ	U,FSTUNI	;RESET TO FIRST UNIT
	PUSHJ	P,CATKB		;ALLOCATE A BLOCK FOR 1ST HOME.SYS RIB
	MOVE	T1,CHECK0	;CHECKSUM OF 0
	DPB	T1,STYCKP##(P2)	;ALWAYS 0 OR 1ST WORD OF BLOCK 0
	MOVE	T3,HOMUN	;INITIAL POINTER TO RETRIEVAL PTRS
	EXCH	T3,HOMRBP	;RESTORE INITIAL POINTER TO POINTERS
	PUSHJ	P,HOMRBS	;STORE POINTER TO RIB
	MOVEM	T3,HOMRBP	;BACK TO PRESENT POSITION
	MOVEM	U,HOMUN
	LDB	T1,STYCLP##(P2)	;CLUSTER OF RIB
	IMUL	T1,J		;REMEMBER LOGICAL BLOCK NUMBER OF RIB FOR HOME.SYS
	MOVEM	T1,HOMRBD
	MOVE	T4,HOMRBA
	PUSHJ	P,COMSIZ	;COMPUTE WORDS WRITTEN AND SET T4=PTR TO RIB
	MOVE	T1,MFDRBD
	MOVEM	T1,RIBUFD##+1(T4)

;HERE TO ALLOCATE 2ND RIB FOR HOME.SYS

	HLRZ	U,LSTUNI
	PUSHJ	P,C1TKB		;TAKE 1 BLOCK FOR 2ND RIB FOR HOME.SYS
	MOVE	T1,HOMRBA	;CHECKSUM ON 1ST WORD OF GROUP
	PUSHJ	P,CHEKSM
	PUSHJ	P,HOMRBS	;STORE RETRIEVAL POINTER
	LDB	P3,STYCLP##(P2)	;CLUSTER OF 2ND HOME.SYS RIB
	IMUL	P3,J
	MOVEM	P3,HOMSR2	;SAVE BLOCK NUM OF 2ND HOME.SYS RIB IN TEMP
	MOVE	P1,HOMRBA	;ADDR OF HOME.SYS RIB IN CORE -1
	MOVE	T2,J		;BLOCKS PER CLUSTER
	IMULB	T2,RIBALC##+1(P1)	;CONVERT CLUSTERS ALLOCATED TO BLOCKS
	ADDM	T2,UFDBKS	;KEEP COUNT OF BLOCKS ALLOCATED IN THIS UFD
	MOVE	T2,HOMRBD	;LOGICAL BLOCK NUM OF 1ST RIB FOR HOME.SYS
	MOVEM	T2,RIBSLF##+1(P1)
	MOVE	T1,HOMRBA	;IOWD FOR 1ST HOM.SYS RIB
	HRRZ	U,FSTUNI	;RESET TO FIRST UNIT
	PUSHJ	P,BLKWRT
	HLRZ	U,LSTUNI	;RESET TO LAST UNIT
	MOVEM	P3,RIBSLF##+1(P1)	;LOGICAL BLOCK NUM OF 2ND RIB
	MOVE	T2,P3		;LOGICAL BLOCK NUM OF 2ND RIB
	PUSHJ	P,BLKWRT	;WRITE IT OUT
	MOVE	T1,SATBKA	;ADDRESS OF A SPARE BLOCK OF CORE (SAT BLOCK)
	PUSHJ	P,CORZER	;CLEAR THE BUFFER
;HOME.SYS HAS NOW BEEN CREATED
;HERE TO WRITE ZEROS IN UNUSED BLOCKS IN HOME.SYS

	HRRZI	P1,1(P1)	;ADDR OF HOME.SYS RIB IN CORE
	ADD	P1,RIBFIR##(P1)	;MAKE POINTER TO 1ST RETRIEVAL POINTER
	MOVE	T1,SYSPPN##
	MOVEM	T1,DEVPPN(F)	;MAKE DDB LOOK LIKE HOME.SYS IN SYS
	MOVE	T1,HOMFNM
	MOVEM	T1,DEVFIL(F)	;TO ALLOW WRITING BLOCK 0
HOMZR2:	MOVE	T2,(P1)		;T2=NEXT RETRIEVAL POINTER
	LDB	T1,STYCNP##(P2)	;T1=CLUSTER COUNT
	JUMPN	T1,HOMZR1	;JUMP IF NOT NEW UNIT POINTER
	JUMPE	T2,MNTCRE	;JUMP IF FINISHED
	TRZ	T2,RIPNUB##	;CLEAR BIT SET TO MAKE SURE NON-ZERO
	PUSHJ	P,NEWUNI##	;SET UP U,DEVUNI(F) TO NEW UNIT
	  STOPCD REFERR,DEBUG,NMU,DIESTR##, ;++NO MORE UNITS
	LDB	J,UNYBPC##	;NEWUNI CLOBBERS J
	JRST	HOMZR5		;GO TO NEXT POINTER
HOMZR1:	IMUL	T1,J		;T1=BLOCKS IN THIS GROUP
	LDB	P3,STYCLP##(P2)	;P3=1ST CLUSTER THIS GROUP
	IMUL	P3,J		;=1ST LOGICAL BLOCK
	MOVEI	P4,-1(T1)
	ADD	P4,P3		;P4=LAST BLOCK OF GROUP
	MOVE	T1,SATBKA	;SET T1=IOWD FOR BLOCK OF ZEROS
	CAMN	P3,HOMRBD	;SKIP IF NOT 1ST RIB
	JRST	HOMZR4		;LEAVE IT ALONE
HOMZR3:	CAMN	P3,HOMSR2	;SKIP IF NOT 2ND RIB
	JRST	MNTCRE		;ALL DONE
	JUMPE	P3,HOMZR4	;DON'T WIPE OUT BLOCK 0
	PUSHJ	P,HUSD		;SEE IF THIS BLOCK HAS VALID DATA
	  SKIPA	T2,P3		;NO, SET T2=NEXT LOGICAL BLOCK TO CLEAR
	JRST	HOMZR4		;YES, LEAVE IT ALONE
	PUSHJ	P,BLKWRT	;WRITE OUT BLOCK OF ZEROS
HOMZR4:	CAME	P3,P4		;SKIP IF JUST DID LAST BLOCK THIS GROUP
	AOJA	P3,HOMZR3	;DO IT FOR NEXT BLOCK
HOMZR5:	AOBJN	P1,HOMZR2	;LOOP FOR ALL RETRIEVAL POINTERS
	SUBTTL	CREATE SYSTEM FILES

;HERE TO CREATE FILE MAINT.SYS - ALLOCATING BLOCKS FOR MAINTENANCE

MNTCRE:
IFN FTMAINT,<
	HRRZ	U,FSTUNI	;U=1ST UNIT IN STR
	MOVE	T1,MNTFNM	;NAME OF FILE OF MAINTENANCE TRACKS
	MOVSI	T2,(SIXBIT .SYS.)
	MOVE	T3,SYSPPN##
	MOVEI	T4,1
	MOVE	P4,NDCFAB	;ALL STATUS BITS
	PUSHJ	P,FIL1RB	;ALLOCATE 1ST RIB AND SET UP RIB IN CORE
	MOVEM	T1,MNTRBD	;REMEMBER LOGICAL BLOCK NUM OF 1ST RIB FOR MAINT.SYS
	MOVEM	U,MNTUN
	MOVE	T2,T1		;T2=1ST LOG BLOCK IN CLUSTER
	MOVE	T1,[JRST ONCWAT##]	;SET UP WAIT ROUTINE IN CASE TAKBLK CHANGES SATS
	MOVEM	T1,PWAIT1##
	PUSHJ	P,FINCLS
	JRST	MNTCR4		;DONT NEED NEW UNIT POINTER
MNTCR3:	PUSHJ	P,STNWUN	;STORE NEW UNIT POINTER IN SAT.SYS RIB
MNTCR4:	LDB	T1,UNYKTP##	;GET KONTROLLER TYPE
	MOVE	P1,MNTLST(T1)	;P1=POINTER FOR THIS KONTROLLER TYPE
	LDB	T1,UNYUTP	;T1=UNIT TYPE
	CAIE	T1,0		;SKIP IF 0 (USE RH OF POINTER)
	MOVSS	P1		;(USE LH OF POINTER)
MNTCR1:	LDB	P4,MNYCNT	;GET NEXT COUNT FILED
	JUMPE	P4,MNTCR2	;JUMP IF FINISHED
	LDB	P3,MNYBLA	;GET 1ST BLOCK TO ALLOCATE
	MOVE	T1,P3		;PUT IN T1
MNTCR5:	CAML	T1,UNIBPU(U)
	JRST	MNTCR6		;DONT BOTHER IF GR THAN BLOCKS ON UNIT
	HRROI	T2,1
	PUSHJ	P,TAKBLK##	;ALLOCATE NEXT BLOCK IN GROUP (SET BIT IN SAT TABLE)
	  JFCL			;DONT CARE IF NOT AVAILABLE
	AOS	T1,P3
	SOJG	P4,MNTCR5	;LOOP FOR WHOLE GROUP
MNTCR6:	LDB	T2,MNYCNT	;GET THIS COUNT FIELD AGAIN
	LDB	T1,MNYBLA	;GET 1ST BLOCK OF GROUP
	PUSHJ	P,ZEXBLK	;SET UP PTRS AND 0 BLOCKS IN CLUSTERS OUTSIDE REGION
	AOJA	P1,MNTCR1	;LOOP FOR ALL SECTIONS TO ALLOCATE
MNTCR2:	HLRZ	U,UNISTR(U)	;NEXT UNIT IN STR
	JUMPN	U,MNTCR3	;LOOP FOR ALL UNITS
	HLRZ	U,LSTUNI	;LAST UNIT
	PUSHJ	P,CMPSIZ	;COMPUTE WORDS WRITTEN
	MOVE	T3,MNTRBD	;LOGICAL BLOCK NUM OF 1ST RIB
	HRRZ	T4,FSTUNI	;T4=ADDR OF 1ST UNIT
	PUSHJ	P,FIL2RB	;ALLOCATE 2ND RIB AND WRITE OUT RIBS
>; END IFN FTMAINT
;HERE TO ALLOCATE SPACE FOR CRASH.EXE - SPACE TO WRITE OUT A CRASH FILE

	MOVSI	T1,SYNRPR##	;PROTECTION TO PREVENT READING EXCEPT R 1
	MOVEM	T1,CURPRT
	HLRZ	U,LSTUNI	;TRY TO PUT IT ON LAST UNIT
	SKIPN	T4,CRSBKN	;SKIP IF ALLOCATE CRASH.EXE
	JRST	NOCRS		;NO CRASH.EXE
	MOVE	T1,CRSFNM	;NAME OF CRASH.EXE FILE
	MOVSI	T2,(SIXBIT .EXE.)

	MOVE	P4,NDCFAB	;NO DELETE, FAILSAFE, BAD CHECKSUM
	TRO	P4,RIPDMP##	;SHOW THAT FILE NEED NOT BE CONTIGUOUS
	PUSHJ	P,FILDO		;CREATE FILE
	MOVEM	P1,CRSRBD	;REMEMBER LBN OF 1ST RIB
	MOVEM	U,CRSUN

;HERE TO ALLOCATE SPACE FOR SNAP.SYS - SPACE TO PERIODICALLY DUMP SYSTEM

NOCRS:	SKIPN	T4,SNPBKN	;SKIP OF ALLOCATE CRASH.EXE
	JRST	NOSNP		;NO SNAP.SYS
	MOVE	T1,SNPFNM	;NAME OF SNAP.SYS FILE
	MOVSI	T2,(SIXBIT .SYS.)
	MOVE	P4,NDNCNF	;NO DELETE, NO FAILSAFE
	PUSHJ	P,FILDO		;CREATE FILE
	MOVEM	P1,SNPRBD
	MOVEM	U,SNPUN

;HERE TO ALLOCATE SPACE FOR RECOV.SYS - SCRATCH SPACE FOR RECOVERY PROGRAM

NOSNP:	SKIPN	T4,RCVBKN	;SKIP OF ALLCATE RECOV.SYS
	JRST	NORCV		;NO RECOVERYS
	MOVE	T1,RCVFNM	;NAME OF RECOV.SYS FILE
	MOVSI	T2,(SIXBIT .SYS.)
	MOVE	P4,NDNCNF	;NO DELETE, NO FAILSAFE
	PUSHJ	P,FILDO		;CREATE FILE
	MOVEM	P1,RCVRBD	;REMEMBER LOGICAL BLOCK NUM OF 1ST RIB
	MOVEM	U,RCVUN
;HERE TO CREATE FILE SWAP.SYS FROM SWAPPING SPACE ON THIS STR

NORCV:	HRRZ	U,FSTUNI	;1ST UNIT IN STR
SWPCR4:	LDB	T1,UNYK4S##	;K FOR SWAPPING ON THIS UNIT
	JUMPN	T1,SWPCR5	;YES, CREATE SWAP.SYS
	HLRZ	U,UNISTR(U)	;NEXT UNIT IN STR
	JUMPN	U,SWPCR4	;LOOP FOR ALL UNITS IN STR
	JRST	NOSWAP		;NO SWAPPING SPACE - NO SWAP.SYS
SWPCR5:	HRRZ	U,FSTUNI	;U=ADDR OF FIRST UNIT IN STR
	MOVE	T1,SWPFNM	;NAME OF FILE OF SWAPPING SPACE
	MOVSI	T2,(SIXBIT .SYS.)
	MOVE	T3,SYSPPN##
	MOVEI	T4,1		;NUMBER OF BLOCKS TO ALLOCATE
	MOVE	P4,NDCFAB	;ALL STATUS BITS
	PUSHJ	P,FIL1RB
	MOVEM	T3,SWPRBD
	MOVEM	U,SWPUN
	MOVE	T2,T3		;T2=1ST LOGICAL BLOCK OF CLUSTER
	PUSHJ	P,FINCLS
	LDB	T2,UNYK4S##	;GET K FOR SWAPPING FOR 1ST UNIT
	JUMPE	T2,SWPCR1	;JUMP IF NO SPACE ON 1ST UNIT
	JRST	SWPCR3		;ALREADY HAVE 1ST NEW UNIT POINTER
SWPCR2:	LDB	T2,UNYK4S##	;GET K FOR SWAPPING ON THIS UNIT
	JUMPE	T2,SWPCR1	;JUMP IF NO SPACE ON THIS UNIT
	PUSHJ	P,STNWUN	;STORE NEW UNIT POINTER IN SWAP.SYS RIB
SWPCR3:	MOVE	T1,UNISLB(U)	;FIRST LOGICAL BLOCK FOR SWAPPING
	IDIV	T1,J		;CONVERT TO CLUSTER
	MOVE	T4,T1		;T1=1ST CLUSTER OF AREA
	MOVE	T1,UNISLB(U)	;FIRST LBN
	LDB	T2,UNYK4S##	;GET K FOR SWAPPING
	LSH	T2,BLKSPK	;K FOR SWAPPING TIMES BLOCKS PER K = BLOCKS
	PUSHJ	P,ZEXBLK	;SET UP PTR AND CLEAR BLOCKS OUTSIDE REGION
SWPCR1:	HLRZ	U,UNISTR(U)	;NEXT UNIT IN THIS STR
	JUMPN	U,SWPCR2	;LOOP FOR ALL UNITS THIS STR
	HLRZ	U,LSTUNI	;LAST UNIT
	SKIPN	T2		;T1 NON-ZERO IF SWAPPING SPACE ON LAST UNIT
	PUSHJ	P,STNWUN	;ELSE STORE NEW UNIT PTR FOR LAST UNIT
	PUSHJ	P,CMPSIZ	;COMPUTE SIZE OF FILE
	MOVE	T3,SWPRBD
	HRRZ	T4,FSTUNI	;T4=ADDR OF UNIT FOR 1ST RIB
	PUSHJ	P,FIL2RB
;HERE TO CREATE FILE BADBLK.SYS FROM BAD REGIONS ON THIS STR

NOSWAP:	HRRZ	U,FSTUNI	;ADDR OF FIRST UNIT IN THIS STR
	MOVE	T1,BADFNM	;NAME OF FILE OF BAD REGIONS
	MOVSI	T2,(SIXBIT .SYS.)
	MOVE	T3,SYSPPN##
	MOVEI	T4,1
	MOVE	P4,NDCFAB	;ALL STATUS BITS
	PUSHJ	P,FIL1RB
	MOVEM	T3,BADRBD
	MOVEM	U,BADUN
	MOVE	T2,T3		;T2=1ST LOGICAL BLOCK IN CLUSTER
	PUSHJ	P,FINCLS
	JRST	BADCR2		;ALREADY HAVE NEW UNIT POINTER FOR 1ST UNIT
BADCR3:	PUSHJ	P,STNWUN	;STORE NEW UNIT POINTER FOR THIS UNIT
BADCR2:	PUSHJ	P,REDBAT	;READ IN BAT BLOCK FOR THIS UNIT
	HRRZ	P4,BATBKA
	AOS	T4,P4
	ADD	P4,BAFFIR##(P4)
	LDB	T1,BAYNBR##	;NUMBER OF BAD REGIONS FOUND BY MAP
	ADD	T1,BAFCNT##(T4)	;+ THOSE FOUND BY MONITOR
	JUMPE	T1,BADCR7	;JUMP IF NONE
	MOVNS	T1		;NEGATE
	HRL	P4,T1
BADCR1:	MOVE	T1,BAFELB##(P4)	;1ST BAD BLOCK OF REGION
	TLZ	T1,BATMSK##
	MOVEI	T2,BAPNTP##
	TDNN	T2,BAFAPN##(P4)	;IF OLD-STYLE BAT BLOCK
	HRRZS	T1		; ONLY 18 BITS COUNT
	MOVE	T2,P4		;T2=ADDR OF THIS ENTRY
	LDB	T2,BAYNBB##	;NUMBER OF BAD BLOCKS THIS REGION - 1
	PUSHJ	P,CKOVLP	;CHECK OVER LAP WITH EXISTING PNTRS
	SKIPLE	T2		;IGNORE ENTRY IF IT OVERLAPS WITH A PREVIOUS
	PUSHJ	P,BADREG	;ADD REGION TO RIB
	ADDI	P4,1
	AOBJN	P4,BADCR1	;LOOP FOR ALL BAD REGIONS THIS UNIT
BADCR7:	HLRZ	U,UNISTR(U)	;NEXT UNIT IN STR
	JUMPN	U,BADCR3	;LOOP FOR ALL UNITS THIS STR
	HLRZ	U,LSTUNI	;RESET TO LAST UNIT
	PUSHJ	P,CMPSIZ
	MOVE	T3,BADRBD
	HRRZ	T4,FSTUNI	;T4=ADDR OF UNIT FOR 1ST RIB
	PUSHJ	P,FIL2RB
;HERE TO CREATE SYS UFD
	MOVSI	T1,SYSPRV##	;SET ACCESS CODE FOR SYS UFD
	MOVEM	T1,CURPRT
	HRRZ	U,FSTUNI	;FIRST UNIT ON STR
	MOVE	T1,FSTFL
	PUSHJ	P,FILCHK	;CHECKSUM ON 1ST FILE NAME AND RETURN PTR IN P3
	MOVE	T2,MFDSIZ	;NUMBER OF DATA BLOCKS TO ALLOCATE FOR MFD
	PUSHJ	P,HIALCU	;ALLOCATE SPACE FOR MFD
	MOVEM	U,MFDUN
	MOVE	T2,MFDRBD	;IN CASE OF ACCIDENTAL REFRESHING
	ADDI	T2,2
	MOVE	T1,SATBKA	;COPY THE 2 MFD BLOCKS WE ARE GOING TO WIPE
	MOVEM	T1,@ONCMBF##	; ELSEWHERE ON THE PACK SO A RECOVERY PROGRAM
	PUSHJ	P,OMNRED##	; HAS SOMEWHERE TO START FROM
	  JFCL
	MOVE	T2,UNIBPU(U)
	SUBI	T2,2
	PUSHJ	P,OMNWRT##	;1ST MFD DATA ON HIGHEST BLOCK - 2
	  JFCL
	MOVE	T2,MFDRBD
	ADDI	T2,1
	PUSHJ	P,OMNRED##
	  JFCL
	MOVE	T2,UNIBPU(U)
	SUBI	T2,1
	PUSHJ	P,OMNWRT##	;2ND MFD DATA ON HIGHEST -1
	  JFCL
	LDB	J,UNYBPC##	;RESET J
	MOVE	T1,SATBKA	;ZERO BLOCK AGAIN
	PUSHJ	P,CORZER
	SETZ	P1,		;CLEAR COUNT OF WORDS WRITTEN IN UFD
	MOVSI	T1,-LSTFL
	SKIPE	FSTUNW(T1)	;SKIP IF NO FILE CREATED
	ADDI	P1,2		;COUNT 2 WORDS WRITTEN FOR EACH FILE CREATED
	AOBJN	T1,.-2
	MOVE	T1,SYSPPN##
	MOVEM	T1,SYSUFD	;SAVE IN NAME BLOCK
	PUSHJ	P,UFALST	;SET UP A UFD AND WRITE ZEROS FOR DATA
	MOVE	P4,SYUFSZ	;NUMBER OF DATA BLOCKS
	ADD	P4,P1		;PLUS FIRST BLOCK-1=LAST DATA BLOCK
	MOVE	T1,SATBKA
	MOVEM	T1,UFDSTP
	MOVSI	P3,-LSTFL
	PUSHJ	P,UFDSTO	;CREATE AND STORE ENTRY FOR NEXT FILE
	AOBJN	P3,.-1		;LOOP FOR ALL FILES IN SYS UFD
	PUSHJ	P,NWBKUF	;OUTPUT LAST BLOCK OF DATA

;HERE TO CREATE PRINT UFD
	MOVSI	T1,777000	;INFINITLY WRITEABLE PRIVILEGES
	MOVEM	T1,CURPRT
	MOVE	T1,SPLPPN##	;PRINT UFD
	MOVEM	T1,PRTUFD
	PUSHJ	P,UFDSET
	MOVEM	P1,PRTRBD	;SAVE LOGICAL BLOCK NUM OF 1ST RIB
	MOVEM	U,PRTUN
;HERE TO CREATE CRASH UFD ON DISK PACK STR'S

	LDB	T1,UNYKTP##	;CONTROLLER TYPE
	CAIGE	T1,TYPDP	;SKIP IF BIG ENOUGH TO GET CRASH ON DISK
	JRST	NOXPN		;DON'T BOTHER WITH THIS UFD
	MOVSI	T1,750000	;DON'T WANT PEOPLE READING
	MOVEM	T1,CURPRT
	SKIPN	T1,XPNPPN##	;CRASH PPN
	JRST	NOXPN		;NO CRASH UFD DESIRED
	MOVEM	T1,XPNUFD
	PUSHJ	P,UFDSET
	MOVEM	P1,XPNRBD
	MOVEM	U,XPNUN		;HERE TO CREATE MFD

NOXPN:	MOVE	T1,UFDPRT##
	MOVEM	T1,CURPRT
	MOVE	T1,FFAPPN##	;ALL PRIVILEGES PPN  (1,2)
	MOVEM	T1,ALPUFD
	PUSHJ	P,UFDSET	;CREATE UFD
	MOVEM	P1,ALPRBD
	MOVEM	U,ALPUN
	MOVE	T1,NEWPPN##
	MOVEM	T1,XSYUFD
	MOVSI	T2,SYSPRV##	;GET RIGHT PROTECTION
	MOVEM	T2,CURPRT
	PUSHJ	P,UFDSET	;EXPERIMENTAL SYS
	MOVEM	P1,XSYRBD
	MOVEM	U,XSYUN
	MOVE	T1,OLDPPN##
	MOVEM	T1,OLDUFD
	PUSHJ	P,UFDSET
	MOVEM	P1,OLDRBD
	MOVEM	U,OLDUN

	MOVSI	T1,MFDPRV##	;SET ACCESS CODE FOR MFD
	MOVEM	T1,CURPRT
	MOVE	T1,MFDSIZ	;BLOCKS TO ALLOCATE FOR MFD
	ADDI	T1,2		;+2 FOR RIBS
	PUSHJ	P,LBNCLS	;CONVERT TO CLUSTERS
	IMUL	T1,J		;AND TO BLOCKS
	ADDM	T1,UFDBKS
	MOVEI	P1,2*LSTUF	;NUMBER OF DATA WORDS TO WRITE
	MOVE	T1,MFDPPN##	;NAME OF MFD
	MOVEM	T1,MFDUFD	;SAVE IN NAME BLOCK
	PUSHJ	P,FILCHK	;CHECKSUM ON 1ST NAME AND RETURN PTR IN P3
	MOVE	T1,MFDUFD	;RESET NAME OF MFD
	PUSHJ	P,UFALST
	MOVE	P4,MFDSIZ	;NUMBER OF DATA BLOCKS FOR MFD
	ADD	P4,P1		;P4=LAST DATA BLOCK
	MOVEI	P3,MFDUFD-FSTFL	;PUT MFD IN ITSELF FIRST
	PUSHJ	P,UFDSTO
	MOVE	P3,[XWD -LSTUF,LSTFL]	;NOW DO UFD'S IN MFD
MFDCRE:	MOVE	T1,FSTFL(P3)	;GET NAME OF THIS UFD
	CAME	T1,MFDUFD	;SKIP IF MFD (ALREADY DONE)
	PUSHJ	P,UFDSTO
	AOBJN	P3,MFDCRE	;LOOP FOR ALL UFD'S TO CREATE
	PUSHJ	P,NWBKUF	;OUTPUT LAST BLOCK OF DATA
	MOVE	T2,P1		;1ST BLOCK AFTER REDUNDENT RIB
	ADDI	T2,2		;(REMEMBERING TO USE 36-BIT ARITHMETIC)
	ADDI	P4,1		;LAST "REAL" BLOCK
MFDCR1:	CAMLE	T2,P4		;PAST REGION?
	SOJA	P4,FEFIX	;YES, DONE
	MOVE	T1,SATBKA	;NO, ZERO THIS MFD DATA BLOCK
	PUSHJ	P,BLKWRT	;DO IT TO IT
	AOJA	T2,MFDCR1	;AND TRY NEXT BLOCK
;HERE TO SET UFD POINTER IN FE.SYS RIB AND WRITE IT
FEFIX:	SKIPN	FERBD		;WAS THERE AN FE.SYS?
	JRST	MFDCRD		;NO
	MOVE	U,FEUN		;GET UDB ADDR
	MOVE	T1,FERBA	;GET BUFFER ADDR
	MOVEM	T1,@ONCMBF##	;POINT TO IT
	MOVE	T2,SYSRBD
	MOVEM	T2,RIBUFD+1(T1)	;POINT TO SYS UFD
	MOVE	T2,FERBD	;POINT TO BLOCK TO WRITE
	PUSHJ	P,OMNWRT##	;WRITE IT
	  JFCL
	MOVE	T1,FERBA	;GET BUFFER ADDR AGAIN
	ADD	T2,RIBALC+1(T1)	;AND POINT TO LAST BLOCK
	SOJ	T2,
	PUSHJ	P,OMNWRT##	;..
	  JFCL
;HERE TO SET LOGICAL BLOCK IN STR OF 1ST RIB OF OUR FILES

MFDCRD:	MOVSI	P3,-LSTUNW
FLBKUP:	MOVE	U,FSTUNW(P3)	;SET UNIT OF 1ST RIB OF CURRENT FILE
	LDB	T1,UNYLUN##	;LOGICAL UNIT NUMBER
	IMUL	T1,STRBPU##(P2)	;TIMES BLOCKS PER UNIT
	ADDM	T1,FSTBK(P3)	;PLUS LOG BLOCK ON THIS UNIT=BLK IN STR
	AOBJN	P3,FLBKUP
	SUBTTL	UPDATE HOME BLOCKS

	MOVE	T1,HOMRBA
	MOVEM	T1,@ONCMBF##	;STORE IOWD FOR HOME BLOCK
	HRRZ	U,FSTUNI	;RESET TO 1ST UNIT

;HERE TO UPDATE HOME BLOCKS

HOMUPD:	PUSHJ	P,GTHOM##	;READ HOME BLOCKS
	  JRST	HBEMSG		;ERROR READING HOME BLOCKS
	MOVE	T2,HOMRBA	;IOWD FOR HOME BLOCK
	SETZM	HOMPPN##+1(T2)	;PUT 0 IN PPN WHO LAST REFRESHED
	SETZM	HOMREF##+1(T2)	;CLEAR NEEDS REFRESHING FLAG
	EXCH	U,MFDUN		;U=UNIT MFD IS ON 1ST
	LDB	T4,UNYLUN##	;T4= BIG AMT OF UNIT FOR MFD
	EXCH	U,MFDUN		;RATE=U
	MOVEM	T4,HOMUN1##+1(T2) ;STORE IN HOME BLOCK
	SKIPE	T1,FEUN		;WAS THERE A SAVED FE.SYS?
	CAME	T1,U		;ON THIS UNIT?
	  SKIPA			;NO, BE SURE TO ZAP HOM BLOCK WORDS
	JRST	FEOK
	SETZM	HOMFEB##+1(T2)	;BE SURE FILE IS REALLY GONE
	SETZM	HOMFEL##+1(T2)	;..

FEOK:	MOVEI	T2,HOMTAB##(T2)
	PUSH	T2,SATRBD
	PUSH	T2,HOMRBD
	PUSH	T2,SWPRBD
	PUSH	T2,[0]
	PUSH	T2,BADRBD
	PUSH	T2,CRSRBD
	PUSH	T2,SNPRBD
	PUSH	T2,RCVRBD
	PUSH	T2,SYSRBD
	PUSH	T2,PRTRBD
	PUSH	T2,MFDRBD
	PUSH	T2,MFDPTR
	HRRZ	P1,HOMRBA	;ADDR-1 OF BUFFER IN CORE
	ADDI	P1,1
	PUSHJ	P,WRTRUN##
	  JRST	EWHMSG		;ERROR WRITING HOME BLOCKS
	MOVE	T1,[JRST ONCWAT##]
	MOVEM	T1,PWAIT1##
	PUSHJ	P,WTUSAT##	;WRITE OUT SATS THAT HAVE CHANGED ON THIS UNIT
	HLRZ	U,UNISTR(U)
	JUMPN	U,HOMUPD	;LOOP FOR ALL UNITS IN STR
	SUBTTL	FINISH UP

;HERE WHEN ALL DONE

	TDZA	T1,T1		;INDICATE NO ERRORS
REFERR:	SETO	T1,		;INDICATE ERROR
	MOVEM	T1,ERRRET	;SAVE ERROR FLAG
	PUSHJ	P,RSPWTC##	;RESTORE WAIT ROUTINE
	MOVE	T1,FFAPPN##	;FULL-FILE-ACCESS PPN
	MOVEM	T1,REFLAG##	;SET REFLAG NON-ZERO
	HRRZ	U,FSTUNI	;RESET U TO FIRST UNIT
	HRRZ	P2,UNISTR(U)	;TO RESET P2 WHICH WAS CLOBBERED FIXING HOME BLOCKS
	SKIPN	ERRRET		;SKIP IF AN ERROR OCCURRED
	HRRZS	STRREF##(P2)	;CLEAR NEEDS REFRESHING FLAG IN CORE
	MOVE	T1,SATRBA	;IOWD FOR ORINGINAL MONITOR BUFFER
	MOVEM	T1,@ONCMBF##
	SKIPE	.UONCE##	;ARE WE IN USER MODE?
	JRST	REFXI2		;YES, THEN DON'T BOTHER TO RETURN THE CORE
	MOVSI	P1,-CORN+1	;MINUS NUMBER OF EXTRA BUFFERS WE OBTAINED
REFXI1:	HRRZ	T2,SATRBA+1(P1)	;GET ADDRESS -1
	ADDI	T2,1
	MOVEI	T1,BLKSIZ##	;NUMBER OF WORDS OBTAINED
	PUSHJ	P,GIVWDS##	;RETURN THEM
	SETZM	SATRBA+1(P1)	;ZERO OUT POINTER
	AOBJN	P1,REFXI1	;LOOP FOR REMAINDER
REFXI2:	MOVE	P,SAVEP		;GET SAVED PDL POINTER BACK
	SKIPN	ERRRET		;DID AN ERROR OCCUR?
	AOS	-1(P)		;NO, SET FOR SKIP RETURN
	POP	P,JBTADR##	;RESTORE JBTADR (MAY BE IN INTTAB)
	POPJ	P,		;RETURN
	SUBTTL	ERROR HANDLING

CRHMSG:!
HBEMSG:!
ERHMSG:	MOVEI	T1,[ASCIZ /% Error reading HOME blocks for unit /]
	PUSHJ	P,ICONM##	;SAY WHAT OUR PROBLEM IS
	MOVE	T2,UDBNAM(U)	;GET UNIT NAME
	PUSHJ	P,PRNAME##	;SAY WHICH UNIT
	PUSHJ	P,CRLFOP##	;FLUSH LINE
	JRST	REFERR		;PUNT

EWHMSG:	MOVEI	T1,[ASCIZ /% Error writing HOME blocks for unit /]
	PUSHJ	P,ICONM##	;SAY WHAT OUR PROBLEM IS
	MOVE	T2,UDBNAM(U)	;GET UNIT NAME
	PUSHJ	P,PRNAME##	;SAY WHICH UNIT
	PUSHJ	P,CRLFOP##	;FLUSH LINE
	JRST	REFERR		;PUNT

ZBCMSG:	MOVE	T1,STRNAM##(P2)	;GET STRUCTURE NAME
	MOVEI	T2,[ASCIZ /has zero blocks per cluster/]
	PUSHJ	P,SWARN##	;COMPLAIN ABOUT THE CONDITION
	JRST	REFERR		;PUNT
	SUBTTL	SUBROUTINES

;SUBROUTINE TO READ IN A SAT BLOCK INTO MONITOR CORE
;ARGS	P2=ADDR OF IN-CORE BUFFER
;	P4=INDEX OF SAT

SATIN:	SE1ENT			;MUST BE IN A NON-ZERO SECTION TO READ SATS
	MOVE	T1,[JRST ONCWAT##]
	MOVEM	T1,PWAIT1##	;SET UP WAIT ROUTINE
	PUSH	P,R		;SAVE R
	MOVE	R,P2		;SAT BUFFER ADDRESS
	PUSHJ	P,SATRED##
	POP	P,R		;RESTORE R
	LDB	J,UNYBPC##
	PJRST	RSPWTC##	;RESTORE WAIT ROUTINE
;SUBROUTINE TO READ IN BAT BLOCKS AND TO RETURN NEW UNIT POINTER
;ARG	U=ADDR OF CURRENT UNIT

REDBAT:	MOVE	T1,BATBKA	;IOWD FOR BAT BLOCK
	MOVEM	T1,@ONCMBF##	;STORE IN MONITOR BUFFER
	MOVSI	P2,(SIXBIT .BAT.)
	MOVE	P3,[EXP CODBAT##]
	MOVE	P4,LBNLST+1	;BLOCK NUMBERS FOR BAT BLOCKS
	PUSHJ	P,REDRUN##	;READ BAT BLOCKS AND CHECK FOR ERRORS
	  STOPCD .+1,INFO,ERB,DIEUNI##, ;++ERROR READING BAT BLOCK
	LDB	J,UNYBPC##	;RESET BLOCKS PER CLUSTER
	HRRZ	P2,UNISTR(U)	;AND ADDR OF STR DATA BLOCK
	POPJ	P,

;SUBROUTINE TO SCAN BAT BLOCK AND EXECUTE AN INSTRUCTION FOR EACH BAD BLOCK
;ARGS	T1=ADDR OF BAT BLOCK IN CORE - 1
;	T2=INSTRUCTION TO EXECUTE


SCNBAT::PUSHJ	P,SAVE4##	;SAVE P1-P4
	MOVE	P4,T1		;P4=ADDR OF BAT BLOCK-1
	MOVE	P2,T2		;P2=INSTRUCTION TO EXECUTE
	AOS	T4,P4		;ADDR OF CORE BLOCK FOR BAT BLOCK, SAVED IN T4
	MOVE	T3,T4		;AND BAYNBR NEEDS IT IN T3
	ADD	P4,BAFFIR##(P4)	;P4=ADDR OF FIRST WORD FOR BAD REGION ENTRIES
	LDB	T1,BAYNBR##	;NUMBER OF BAD REGIONS FOUND BY MAP
	ADD	T1,BAFCNT##(T4)	;PLUS THOSE BY MONITOR
	JUMPE	T1,CPOPJ##	;JUMP IF NO BAD REGIONS
	MOVNS	T1		;NEGATE
	HRL	P4,T1		;MAKES P4=-NUM OF ENTRIES,ADDR OF 1ST
MRKBAD:	MOVE	T2,P4		;ADDR OF BAD REGION PTR
	LDB	P3,BAYNBB##	;NUMBER BAD BLOCKS-1
	MOVE	P1,BAFELB##(P4)	;P1=1ST BAD BLOCK
	TLZ	P1,BATMSK##	;JUST LOGICAL BLOCK NUMBER
	MOVEI	T3,BAPNTP##	;IF OLD-STYLE
	TDNN	T3,BAFAPN##(P4)
	HRRZS	P1		; ONLY 18 BITS COUNT
	SUBI	P1,1
MRKBD2:	AOS	T1,P1		;P1=NEXT BAD BLOCK
	XCT	P2		;MARK THIS BLOCK IN SAT
	SOJGE	P3,MRKBD2	;LOOP FOR ALL BAD BLOCKS THIS REGION
	ADDI	P4,1		;COMPENSATE FOR 2 WORD ENTRIES
	AOBJN	P4,MRKBAD	;LOOP FOR ALL ENTRIES
	POPJ	P,
;SUBROUTINE TO SET BITS IN CURRENT SAT BLOCK
;ARGS T1=BLOCK NUMBER
;ENTER AT SETBAD TO MARK BAD BLOCKS
;ENTER AT SETSWP TO MARK SWAPPING SPACE

SETBAD:
SETSWP:	MOVE	T2,T1
	IDIV	T2,J		;T2=CLUSTER NUMBER
	CAML	T2,BEGSAT	;SKIP IF BEFORE BEGINNING OF CURRENT SAT
	CAMLE	T2,LCLSAT	;SKIP IF WITHIN CURRENT SAT (NOT PAST END)
	POPJ	P,		;BLOCK NOT IN CURRENT SAT
	PUSHJ	P,SAVE4##	;SAVE P1-P4
	MOVE	P1,J		;P1=BLOCKS PER CLUSTER
	MOVE	P2,BEGSAT	;P2=1 REPRESENTED BY 1ST BIT
	MOVE	P3,LCLSAT	;P3=GROUP REPRESENTED BY LAST BIT
	MOVE	P4,SATBKA	;P4=IOWD PTR TO CORE BLOCK
	PUSHJ	P,CHKBIT##	;SEE IF BIT ALREADY SET
	  ORM	T4,(T1)		;NO, SET IT
	POPJ	P,		;YES, EXIT

;SUBROUTINE TO CHECK FOR POSSIBLE OVERLAPS IN BADBLK.SYS
;ARGS	T1=1ST BLOCK OF NEW REGION
;	T2=NO OF BLOCKS IN REGION -1
;VALUES	T1=1ST BLOCK IN REGION
;	T2=NO OF BLOCKS IN REGION
CKOVLP:	PUSHJ	P,SAVE1##
	ADD	T2,T1
	MOVE	P1,T1		;1ST BAD BLOCK IN NEW REGION
	MOVE	T3,T2		;LAST BAD BLOCK IN NEW REGION
	MOVE	T4,SATRBA
	ADDI	T4,1
	ADD	T4,RIBFIR##(T4)	;AOBJN WORD FOR CURRENT POINTERS
CKOVL1:	SKIPN	T2,(T4)		;GET A RETRIEVAL POINTER
	JRST	CKOVL3		;DONE
	TLNN	T2,-1
	JRST	CKOVL2		;UNIT-CHANGE
	LDB	T1,STYCLP##(P2)	;1ST CLUSTER IN THIS PNTR
	LDB	T2,STYCNP##(P2)	;NO OF CLUSTERS
	IMULI	T1,(J)
	IMULI	T2,(J)		;CONVERT TO BLOCKS
	SUBI	T2,1
	ADD	T2,T1		;T2=LAST BLOCK IN CURRENT POINTER
	CAML	T2,P1
	CAMLE	T1,T3		;OVERLAP?
	JRST	CKOVL2		;NO
	CAMGE	P1,T2		;YES. AT FRONT?
	AOS	P1,T2		;YES, ADJUST FRONT
	CAMLE	T3,T1		;OVERLAP AT END?
	SOS	T3,T1		;YES, ADJUST END
CKOVL2:	AOBJN	T4,CKOVL1	;CHECK NEXT POINTER
CKOVL3:	MOVE	T1,P1		;(NEW) START OF REGION
	AOS	T2,T3
	SUB	T2,T1		;(NEW) LENGTH OF REGION
	POPJ	P,
;SUBROUTINE TO SET NON ACTUAL DATA BITS IN LAST ACTUAL
;DATA WORD OF A BLOCK
;ARGS	T1=ADDR OF CORE BLOCK -1
;	T2=ACTUAL NUMBER OF GROUPS=NUMBER ACTUAL DATA BITS
MRKEND:	MOVE	T3,T2		;T3=NUMBER GROUPS
	PUSHJ	P,CORZER	;CLEAR THE WHOLE BUFFER
	IDIVI	T3,^D36		;T3=INDEX IN BLOCK
	PUSH	P,T3		;SAVE INDEX
	ADDI	T2,-BLKSIZ##(T3) ;T2=ADDR OF WORD CONTIANING BITS
	JUMPE	T4,MRKEN1	;EXIT IF NO EXTRA BITS
	AOJ	T2,		;ACCOUNT FOR REMAINDER
	MOVNI	T3,-1(T4)	;T3=NUMBER CONTAINING BITS
	MOVSI	T1,400000	;LEFT MOST BIT
	ASH	T1,(T3)		;SET ACTUAL DATA BIT IN T1
	SETCAM	T1,(T2)		;SET THE OTHERS IN THE BLOCK
MRKEN1:	POP	P,T3		;LAST WORD OF BLOCK
	SUBI	T3,BLKSIZ##-1
MRKEN2:	JUMPE	T3,CPOPJ##	;EXIT IF DONE
	SETOM	1(T2)		;SET NEXT SAT WORD =-1
	AOS	T2
	AOJA	T3,MRKEN2	;LOOP TILL END OF BUFFER
;SUBROUTINE TO GET A BLOCK FOR HOME.SYS
;ARG	T1=LOGICAL BLOCK WITHIN UNIT
;	P3=LAST CLUSTER ALLOCATED
;PRESERVES T3, USES P1,T4

GETHMB:	PUSH	P,T3
	PUSHJ	P,GETHMC	;TRY TO GET THE BLOCK
	  JRST	NOBLK		;COULDNT GET IT
	POP	P,T3
	LDB	T1,STYCLP##(P2)	;GET CLUSTER JUST ALLOCATED
	EXCH	T1,P3		;UPDATE LAST CLUSTER ALLOCATED, SAVE PREVIOUS
	ADDI	T1,1
	CAME	T1,P3		;SKIP IF LAST FOLLOWS PREVIOUS
	PJRST	HOMRBS		;NO, STORE NEW RETRIEVAL POINTER AND EXIT
	MOVE	T4,HOMRBP
	MOVE	T2,(T4)		;LAST RETRIEVAL POINTER STORED
	LDB	T1,STYCNP##(P2)	;YES, NEED ONLY INCREMENT COUNT
	ADDI	T1,1
	DPB	T1,STYCNP##(P2)
	MOVEM	T2,(T4)		;STORE NEW PTR
	MOVE	T1,HOMRBA
	AOS	RIBALC##+1(T1)	;BUMP COUNT OF CLUSTERS ALLOCATED
	POPJ	P,

NOBLK:	MOVE	T1,T2
	POP	P,T3
	CAMN	T1,P3		;IF ALREADY ALLOCATED TO US OK
	POPJ	P,
;	POP	P,(P)		;REMOVE CALLER FROM STACK
	PJRST	BADHOM		;TYPE AND HALT

;SUBROUTINE TO GET A BLOCK FOR HOME.SYS AND COMPUTE CHECKSUM
;ARG	T1=LOGICAL BLOCK WITHIN UNIT
;PRESERVES T3, USES P1,T1,T2,T4

GETHMC:	MOVE	P1,T1
	IDIV	T1,J		;SEE IF BLOCK NEEDED STARTS A CLUSTER
	EXCH	P1,T2		;SAVE REMAINDER IN P1 AND REMEMBER BLOCK NEEDED
	SKIPN	T1,T2		;SKIP IF NOT BLOCK 0
	ADDI	P1,1		;MAKE SURE CHECKSUM = 0 FOR BLOCK 0
	PUSHJ	P,RTAKBK	;TRY TO GET THE BLOCK
	  POPJ	P,		;COULDNT
	MOVSI	T1,(SIXBIT .HOM.)
	CAIE	P1,0
	SETZ	T1,		;ZERO IF NOT BEGINNING OF CLUSTER
	PUSHJ	P,CHEKS1	;IF NOT BEGINNING OF CLUSTER, 1ST BLOCK ALL 0
	JRST	CPOPJ1##
;SUBROUTINE TO ALLOCATE 1 BLOCK IN CURRENT SAT WHILE CREATING SATS
;ARG	T1=LOGICAL BLOCK NUMBER TO ALLOCATE, OR 0 IF DONT CARE
;VALUE	NON-SKIP RETURN IF CANT HAVE BLOCK, T2=CLUSTER NEEDED IF WAS NON-0
;	SKIP RETURN IF GOT BLOCK, T2=RETRIEVAL POINTER
;USES T1, PRESERVES T3
RTAKBK:	PUSHJ	P,SAVE1##	;SAVE P1
	JUMPN	T1,RSPBK	;JUMP IF NEED SPECIFIC BLOCK
	MOVE	T1,SATBKA	;SEARCH WHOLE BLOCK
	MOVSI	P1,400000	;LEFT MOST BIT
	MOVE	T2,BEGSAT	;STARTING AT BEGINNING OF THIS SAT
RTAKB1:	TDNN	P1,1(T1)	;SKIP IF CLUSTER NOT AVAILABLE
	JRST	ROK		;GOT ONE
	ROT	P1,-1		;WILL TRY NEXT CLUSTER
	ADDI	T2,1		;KEEP UP CLUSTER NUMBER
	JUMPGE	P1,RTAKB1	;JUMP IF STILL SAME WORD
	AOBJN	T1,RTAKB1	;BUMP INDEX AND KEEP ON IF MORE
	POPJ	P,		;NO CLUSTERS AVAILABLE
RSPBK:	IDIV	T1,J		;CONVERT LOGICAL BLOCK TO CLUSTER
	PUSH	P,T1		;SAVE CLUSTER NEEDED
	IDIVI	T1,^D36
	ADD	T1,SATBKA	;ADDR-1 OF WORD CONTAINING BIT WE WANT
	MOVEI	P1,^D36
	SUBM	P1,T2		;T2=36-REMAINDER
	MOVSI	P1,400000
	ROT	P1,(T2)		;SHIFT BIT INTO POSITION
	POP	P,T2		;T2=CLUSTER DESIRED
	TDNE	P1,1(T1)	;SKIP IF AVAILABLE
	POPJ	P,		;NO
ROK:	ORM	P1,1(T1)	;SET BIT, TAKING CLUSTER
	MOVEI	T1,1
	DPB	T1,STYCNP##(P2)	;SET CLUSTER COUNT TO 1
	JRST	CPOPJ1##

;SUBROUTINE TO CHECK IF A GIVEN BLOCK CONTAINS VALID DATA IN HOME.SYS
;ARG	P3=BLOCK NUMBER TO CHECK
;RETURNS CPOPJ IF DOES NOT CONTAIN DATA
;	CPOPJ1 IF IT DOES
;USES T3,T4
HUSD:	MOVSI	T4,-LBNLEN
	HLRZ	T3,LBNLST(T4)	;T3=NEXT VALID DATA BLOCK TO CHECK FOR
	CAIE	P3,(T3)		;SKIP IF THIS BLOCK HAS VALID DATA
	AOBJN	T4,.-2		;THIS BLOCK IS NOT THERE
	JUMPL	T4,CPOPJ1##	;JUMP IF THIS BLOCKS CONTAINS DATA
	MOVSI	T4,-LBNLEN	;NO, CHECK SECOND GROUP
	HRRZ	T3,LBNLST(T4)
	CAIE	P3,(T3)
	AOBJN	T4,.-2
	JUMPL	T4,CPOPJ1##
	CAIGE	P3,FBOOTB##	;SKIP IF BLOCK PAST BEGINNING OF BOOTS
	POPJ	P,		;CANT BE PART OF BOOTS
	MOVEI	T4,FBOOTB##
	ADDI	T4,NBOOTB##	;LAST BLOCK+1 OF BOOTS
	CAIGE	P3,(T4)		;SKIP IF PAST END OF BOOTS
	JRST	CPOPJ1##	;NO, PART OF BOOTS IS CONSIDERED VALID DATA
	POPJ	P,
;SUBROUTINE TO STORE AN RTP IN THE RIB OF SWAP.SYS
;ARGS	T1=1ST LOGICAL BLOCK OF REGION
;	T2=NUMBER OF BLOCKS IN REGION

ZEXBLK:	PUSHJ	P,SAVE4##
	MOVE	P1,T1		;P1=1ST BLOCK OF REGION
	MOVE	P3,T2		;P3=NUMBER BLOCKS IN REGION
	MOVE	T1,UNIBPU(U)	;BLOCKS ON THIS UNIT
	IDIV	T1,J		;CLUSTERS ON THIS UNIT
	MOVE	T1,UNIBPU(U)	;T2=BLOCKS PAST LAST EVEN MULTIPLE OF CLUSTER SIZE
	SUBI	T1,1(T2)	;T1=LAST BLOCK OF LAST REAL CLUSTER
	CAMLE	P1,T1		;SKIP IF FIRST BLOCK IS WITHIN REAL CLUSTERS
	POPJ	P,		;NO, FORGET THE WHOLE THING
	MOVE	T2,P1		;YES, T2=FIRST BLOCK IN REGION
	ADD	T2,P3		;+NUMBER OF BLOCKS=LAST BLOCK+1
	SUBI	T2,1		;T2=LAST BLOCK OF REGION
	SUB	T2,T1		;-LAST BLOCK OF UNIT=NUMBER OF BLOCKS OVER
	SKIPLE	T2		;SKIP IF ALL WITHIN REAL CLUSTERS
	SUB	P3,T2		;NO, PRETEND REGION GOES TO END OF LAST REAL CLUSTER
	ADD	P3,P1		;P3=1ST BLOCK BEYOND REGION
	SUBI	P3,1		;P3=LAST BLOCK IN REGION
	IDIV	P3,J		;P3=LAST CLUSTER IN REGION
	ADDI	P3,1		;P3=1ST CLUSTER BEYOND REGION
	MOVE	T1,P1		;T1=1ST BLOCK IN REGION
	IDIV	T1,J		;T1=1ST CLUSTER IN REGION
	MOVE	P4,T1		;P4=1ST CLUSTER IN REGION
	SUB	P3,P4		;P3=NUMBER OF CLUSTERS IN REGION
	MOVE	T3,MAXALC	;MAX CLUSTERS CAN ALLOCATE IN 1 PTR
ZEXBL5:	SETZ	T2,
	DPB	P4,STYCLP##(P2)	;STORE 1ST CLUSTER THIS PTR
	CAMG	P3,T3		;SKIP IF MORE IN REGION THAN IN 1 PTR
	JRST	ZEXBL6		;ALL SET
	DPB	T3,STYCNP##(P2)	;STORE MAX
	PUSHJ	P,SATRBS	;STORE PTR
	SUB	P3,T3		;P3=TOTAL LEFT
	ADD	P4,T3		;P4=1ST OF WHATS LEFT
	JRST	ZEXBL5		;LOOP TILL PTRS FOR WHOLE REGION
ZEXBL6:	DPB	P3,STYCNP##(P2)	;STORE LAST COUNT
	PJRST	SATRBS		;STORE LAST PTR AND EXIT
;SUBROUTINE TO ADD A BAD REGION TO THE RIB OF BADBLK.SYS
;T1 PASSES 1ST BLOCK OF REGION
;T2 PASSES NUMBER OF BLOCKS IN REGION
BADREG:	PUSHJ	P,SAVE3##	;SAVE P1-P3
	MOVE	P3,T1		;1ST BLOCK
	MOVE	P1,T2		;NUMBER OF BLOCKS
BADRG1:	PUSHJ	P,BDREG		;PROCESS ONE BLOCK
	ADDI	P3,1		;ON TO THE NEXT BLOCK
	SOJG	P1,BADRG1	;LOOP FOR EACH BLOCK
	POPJ	P,

;SUBROUTINE TO ADD A BAD BLOCK TO THE RIB OF BADBLK.SYS
;P3 PASSES THE BLOCK NUMBER
BDREG:	PUSHJ	P,SAVE4##	;SAVE P1-P4
	MOVE	T1,UNIBPU(U)	;BLOCKS ON THIS UNIT
	IDIV	T1,J		;T2=BLOCKS LEFT AFTER LAST FULL CLUSTER
	MOVE	T1,UNIBPU(U)	;BLOCKS ON THIS UNIT
	SUBI	T1,1(T2)	;LAST BLOCK OF LAST REAL CLUSTER
	CAMLE	P3,T1		;IS IT IN THE MAINT CYL?
	POPJ	P,		;YES, DON'T PUT IN BADBLK
	IDIV	P3,J		;CONVERT BLOCK TO CLUSTER
	LDB	T3,UNYK4S##	;K FOR SWAPPING
	JUMPE	T3,BDREG1	;EASY IF NONE
	LSH	T3,BLKSPK	;BLOCKS OF SWAPPING
	MOVE	T1,UNISLB(U)	;1ST BLOCK FOR SWAPPING
	ADD	T3,T1		;1ST BLOCK BEYOND SWAPPING
	SUBI	T3,1		;LAST BLOCK OF SWAPPING
	IDIV	T3,J		;LAST CLUSTER OF SWAPPING
	IDIV	T1,J		;1ST CLUSTER FOR SWAPPING
	CAML	P3,T1		;IN SWAP.SYS?
	CAMLE	P3,T3
BDREG1:	SKIPA	P4,SATRBA	;NO, GET ADDR-1 OF RIB
	POPJ	P,		;YES, DON'T PUT IN BADBLK TOO

;HERE TO SCAN THE RTP'S THAT ALREADY EXIST
	MOVEI	P4,1(P4)	;ADDR OF RIB
	ADD	P4,RIBFIR##(P4) ;AOBJN PNTR TO RTP'S
BDREG2:	SKIPN	T2,(P4)		;PICK UP AN RTP
	JRST	BDREG3		;EOF, HAVE TO ADD NEW RTP
	LDB	T1,STYCNP##(P2)	;CLUSTER COUNT
	JUMPN	T1,BDREG4	;GO IF GROUP POINTER
	HRRZ	P1,T2		;ZERO MEANS CHANGE UNIT
	TRZ	P1,RIPNUB##	;REMEMBER UNIT NUMBER
	JRST	BDREG5		;AND GET NEXT RTP
BDREG4:	LDB	T4,UNYLUN##	;GET THIS UNIT'S NUMBER
	CAME	T4,P1		;IS THIS RTP FOR THIS UNIT?
	JRST	BDREG5		;NO, GET NEXT RTP
	LDB	T4,STYCLP##(P2)	;CLUSTER ADDRESS
	ADD	T1,T4		;1ST CLUSTER BEYOND GROUP
	CAML	P3,T4		;IS OUR CLUSTER IN THIS GROUP?
	CAML	P3,T1
	SOSA	T4		;NO, GET 1ST CLUSTER BEFORE GROUP
	POPJ	P,		;YES, OUR CLUSTER IS ALREADY IN THE RIB
	LDB	T3,STYCNP##(P2)	;CLUSTER COUNT
	CAML	T3,MAXALC	;CAN IT BE EXPANDED?
	JRST	BDREG5		;NO, TEST NEXT RTP
	MOVEI	T3,RIPNUB##	;1ST RTP
	CAME	T3,-1(P4)	;IS THIS THE 2ND RTP? (THE RIB)
	CAME	P3,T4		;IS OUR CLUSTER JUST BEFORE THE GROUP?
	JRST	BDREG6		;NO

;HERE TO ADD A CLUSTER TO THE BEGINNING OF THE GROUP
	DPB	P3,STYCLP##(P2)	;STORE NEW 1ST CLUSTER

;HERE TO ADD A CLUSTER TO THE (END OF THE) GROUP
BDREG7:	LDB	T1,STYCNP##(P2)	;OLD CLUSTER COUNT
	ADDI	T1,1		;ADD ONE
	DPB	T1,STYCNP##(P2)	;NEW CLUSTER COUNT
	MOVEM	T2,(P4)		;STORE NEW RTP
	HRRZ	T1,SATRBA	;ADDR-1 OF RIB
	AOS	RIBALC##+1(T1)	;ONE MORE CLUSTER ALLOCATED
	POPJ	P,

;HERE IF CLUSTER CAN'T BE ADDED TO FRONT OF GROUP
BDREG6:	CAMN	P3,T1		;CAN IT BE ADDED TO THE END?
	JRST	BDREG7		;YES

;HERE TO TEST NEXT RTP
BDREG5:	AOBJN	P4,BDREG2	;SHOULD ALWAYS JUMP

;HERE TO ADD A NEW RTP
BDREG3:	MOVEI	T2,1		;ONE CLUSTER
	DPB	T2,STYCNP##(P2)	;STORE CLUSTER COUNT
	DPB	P3,STYCLP##(P2)	;STORE CLUSTER ADDRESS
	PJRST	SATRBS		;PUT RTP IN RIB
;SUBROUTINE TO CONVERT NUMBER OF LOGICAL BLOCKS TO NUMBER OF CLUSTERS
;ARG	T1=NUMBER OF LOGICAL BLOCKS
;VALUE	T1=NUMBER OF CLUSTERS

LBNCLS:	SUBI	T1,1
	IDIV	T1,J
	AOJA	T1,CPOPJ##

;SUBROUTINE TO ALLOCATE SPACE FOR A UFD NEAR THE CENTER OF A PACK
;ARGS/VALUES SAME AS FOR UFDALC
HIALCU:	PUSH	P,T2
	SETO	T2,		;ASK FOR MAX POSSIBLE
	MOVE	T1,[JRST ONCWAT##] ;SET UP WAIT ROUTINE
	MOVEM	T1,PWAIT1##	; IN CASE TAKBLK CHANGES SATS
	MOVE	T1,UNIBPU(U)
	LSH	T1,-1		;START AT MIDDLE OF PACK
	PUSHJ	P,TAKBLK##	;(IT WILL FAIL, BUT RIGHT SAT BLOCK WILL
	  JFCL			; BE SET FOR FOLLOWING ALLOCATION)
	POP	P,T2		;RESTORE REAL AMOUNT TO GET
	LDB	J,UNYBPC##	;RESET J
	PUSHJ	P,UFDALC	;ALLOCATE BLOCKS IN MIDDLE OF PACK
	PUSH	P,T1		;SAVE BLOCK NUMBER
	MOVEI	T1,1
	MOVEI	T2,1		;RESET TO ALLOCATE AT START OF PACK
	PUSHJ	P,TAKBLK##	;(THIS WILL FAIL TOO)
	  JFCL
	LDB	J,UNYBPC##
	JRST	TPOPJ##

;SUBROUTINE TO ALLOCATE SPACE FOR A UFD
;ARG	T2=NUMBER OF BLOCKS TO ALLOCATE
;VALUE	T1=LOGICAL BLOCK NUM OF 1ST RIB

UFDALC:	ADDI	T2,2		;2 BLOCKS FOR RIBS
	HRLI	T2,-1		;EXACTLY THIS MANY BLOCKS
	PUSHJ	P,CATKBA	;TRY TO ALLOCATE SPACE
	MOVEM	T2,MFDPTR	;REMEMBER RETRIEVAL PTR
	LDB	T1,STYCLP##(P2)	;1ST CLUSTER
	IMUL	T1,J		;LOGICAL BLOCK OF 1ST RIB
	MOVEM	T1,MFDRBD
	POPJ	P,
;SUBROUTINE TO SET UP A UFD WHICH HAS ALREADY BEEN ALLOCATED
;ARGS	T1=UFD NAME
;	P1=NUMBER OF DATA WORDS TO BE WRITTEN
;	P3=1ST RETRIEVAL POINTER

UFALST:	MOVSI	T2,(SIXBIT .UFD.)
	MOVE	T3,MFDPPN##
	MOVE	T4,SATRBA
	MOVEI	P4,RIPDIR##	;SET DIRECTORY BIT IN STATUS
	ADD	P4,NDNCNF	;NO DELETE, NO FAILSAFE BITS
	PUSHJ	P,RIBSET	;SET UP RIB IN CORE
	MOVEM	T4,SATRBP	;SAVE POINTER TO RETRIEVAL PTRS
	MOVE	T2,UFDBKS	;NUMBER OF BLOCKS ALLOCATED IN CURRENT UFD
	MOVE	T4,SATRBA	;POINTER TO RIB
	MOVEM	T2,RIBUSD##+1(T4)	;STORE BLOCKS ALLOCATED IN RIB
	SETZM	UFDBKS		;AND CLEAR FOR NEXT UFD
	PUSHJ	P,STNWUN
	MOVE	T2,P3		;FIRST RETRIEVAL POINTER
	PUSH	P,SATRBP	;PTR TO RETRIEVAL PTRS
	PUSHJ	P,SATRBS	;STORE RETRIEVAL PTR
	POP	P,T1
	LDB	T3,STYCLP##(P2)	;1ST CLUSTER
	IMUL	T3,J		;T3=LOG BLOCK OF 1ST RIB
	PJRST	FILST1
;SUBROUTINE TO CREATE A FILE OF CONTIGUOUS DISK SPACE AND WRITE ZEROS IN DATA BLOCKS
;ARGS	T1=FILE NAME
;	T2=EXT
;	T3=PPN
;	T4=NUMBER OF DATA BLOCKS TO ALLOCATE
;	P1=NUMBER OF WORDS WHICH WILL BE WRITTEN
;	P4=BITS TO SET IN RIB STATUS WORD
;VALUES	P1=LOGICAL BLOCK NUMBER OF 1ST RIB
;	P3=LOGICAL BLOCK NUMBER OF 2ND RIB
;ENTER AT UFDSET FOR UFD'S, AT FILDO FOR STANDARD SYS FILES

FILDO:	MOVE	T3,SYSPPN##
	MOVEI	P1,BLKSIZ##
	IMUL	P1,T4
	PJRST	FILSET

UFDSET:	MOVSI	T2,(SIXBIT .UFD.)	;EXT
	MOVE	T3,MFDPPN##	;PPN - FALL INTO FILSET
	MOVEI	T4,1		;ALLOCATE 1 DATA BLOCK
	SETZ	P1,		;NUMBER OF WORDS TO WRITE
	MOVEI	P4,RIPDIR##	;DIRECTORY BIT FOR STATUS
	ADD	P4,NDNCNF	;NO DELETE, NO FAILSAFE BITS
FILSET:	ADDI	T4,2		;+2 BLOCKS FOR RIBS
	PUSHJ	P,FIL1RB	;ALLOCATE SPACE AND SET UP RIB IN CORE
FILST1:	SETZ	T2,		;T2=FIRST RELATIVE BLOCK IN GROUP=0 FOR RIB
	EXCH	P1,T3		;P1=LOG BLOCK OF 1ST RIB,T3=DATA WORDS
	MOVE	T4,SATRBA
	MOVEM	T3,RIBSIZ##+1(T4)	;STORE SIZE IN WORDS IN RIB
	ADDI	T3,BLKSIZ##-1
	IDIVI	T3,BLKSIZ##	;CONVERT OT BLOCKS
	ADDI	T3,1		;+1 FOR 2ND RIB
	PUSHJ	P,SCNPTR##	;FIND BLOCK NUM FOR 2ND RIB
	  STOPCD .,STOP,NSR,DIEUNI##, ;++NO SECOND RIB
	LDB	J,UNYBPC##	;J CLOBBERED IN SCNPTR - RESET
	MOVE	P3,DEVBLK##(F)	;DEVBLK=LOG BLOCK OF 2ND RIB
	MOVE	T4,SATRBA	;PTR TO RIB
	MOVE	T1,RIBSTS##+1(T4)	;GET STATUS WORD
	TRNE	T1,RIPDIR##	;SKIP IF NOT DIRECTORY FILE
	PUSHJ	P,QUOSET	;SET UP QUOTAS FOR DIRECTORIES
	MOVE	T4,U
	PJRST	WRTRIB		;WRITE OUT BOTH RIBS
;SUBROUTINE TO COMPUTE SIZE OF FILE IN WORDS=BLOCKS WRITTEN*BLOCK SIZE
;(BEFORE 2ND RIB HAS BEEN ALLOCATED)
;ARGS	T4=ADDR-1 OF RIB

CMPSIZ:	MOVE	T4,SATRBA	;ADDR-1 OF SAT RIB - FALL INTO COMSIZ
COMSIZ:	MOVE	T1,RIBALC##+1(T4)	;NUMBER OF CLUSTERS ALLOCATED
	IMUL	T1,J		;CONVERT TO BLOCKS
	SUBI	T1,1		;-1 FOR FIRST RIB
	IMULI	T1,BLKSIZ##	;TIMES WORDS PER BLOCK
	MOVEM	T1,RIBSIZ##+1(T4)
	POPJ	P,

;SUBROUTINE TO SET UP QUOTAS FOR UFDS
;ARG	T4=ADDR OF RIB IN CORE -1

QUOSET:	MOVE	T1,QUOTAR	;RESERVED QUOTA
	MOVEM	T1,RIBQTR##+1(T4)
	MOVE	T1,QUOTAF	;FIRST COME, FIRST SERVED QUOTA
	MOVEM	T1,RIBQTF##+1(T4)
	MOVE	T1,QUOTAO	;LOGGED OUT QUOTA
	MOVEM	T1,RIBQTO##+1(T4)
	POPJ	P,

;SUBROUTINE TO COMPUTE CHECKSUM FOR 1ST DATA BLOCK OF FILE
;ARGS	T1=1ST WORD OF 1ST DATA BLOCK OF FILE
;	MFDPTR=1ST RETRIEVAL POINTER FOR FILE
;VALUES	P3=MFDPTR=1ST RETRIEVAL POINTER FOR FILE WITH CHECKSUM STORED

FILCHK:	MOVE	T2,MFDPTR	;T2=PTR
	PUSHJ	P,CHEKS1	;DO THE CHECKSUM
	MOVE	P3,T2		;P3=PTR WITH CHECKSUM
	MOVEM	P3,MFDPTR	;AND BACK INTO MFDPTR
	POPJ	P,
;SUBROUTINE TO SET UP A FILE, SET UP RIB, ALLOCATE 1ST RIB
;ARGS	T1=FILE NAME
;	T2=EXT
;	T3=PPN
;	T4=NUMBER OF BLOCKS TO ALLOCATE
;	P4=BITS TO SET IN STATUS WORD
;VALUES	T1=AOBIN PTR TO RETRIEVAL POINTERS
;	T2=LAST RETRIEVAL POINTER
;	T3=LOGICAL BLOCK NUMBER OF FIRST RIB

FIL1RB:	MOVEM	T4,BLKNED	;SAVE NUMBER OF BLOCKS TO ALLOCATE
	MOVE	T4,SATRBA	;ADDR OF RIB IN CORE
	PUSH	P,P4		;SAVE FLAGS FOR .RBSTS
	TRZ	P4,RIPDMP##	;TURN OFF POSSIBLE "NON-CONTIGUOUS" FLAG
	PUSHJ	P,RIBSET
	POP	P,P4		;RESTORE FLAGS
	MOVEM	T4,SATRBP	;POINTER TO RETRIEVAL POINTERS
	PUSHJ	P,STNWUN
	PUSH	P,SATRBP	;SAVE PTR TO RETRIEVAL PTRS
FIL1R1:	HRRO	T2,BLKNED	;BLOCKS NEEDED
	TRNE	P4,RIPDMP##	;SKIP IF WE MUST FIND EXACT FIT IN ONE PASS
	TLZ	T2,-1		;TURN OFF "FIND EXACTLY" FLAG FOR TAKBLK
	MOVEI	T3,ADJALC##	;DEFAULT FOR "FIND SUPERCLUSTERS"
	MOVE	T1,SATRBP	;GET POINTER TO WHERE RETRIEVAL POINTERS GO
	CAME	T1,(P)		;SKIP IF FIRST TRIP THROUGH ALLOCATION LOOP
	MOVEI	T3,TAKBLK##	;ALLOW "REGULAR CLUSTERS" IF NOT FIRST TRIP
	PUSHJ	P,CATKBB	;ALLOCATE MORE SPACE (OR FIRST) TO THE FILE
	MOVE	T1,CHECK0	;0 CHECKSUM
	DPB	T1,STYCKP##(P2)
	PUSHJ	P,SATRBS	;STORE RETRIEVAL POINTER
	LDB	T1,STYCNP##(P2)	;CLUSTERS ACTUALLY ALLOCATED
	IMUL	T1,J		;BLOCKS ALLOCATED
	SUB	T1,BLKNED	;MINUS NEEDED
	JUMPGE	T1,FIL1R2	;JUMP IF HAVE ENOUGH
	MOVNM	T1,BLKNED	;RESET AMOUNT STILL NEEDED
	JRST	FIL1R1		;AND LOOP FOR THOSE
FIL1R2:	POP	P,T1		;AOBJN PTR TO RETRIEVAL PTRS

	MOVE	T2,1(T1)	;1ST PTR
	LDB	T3,STYCLP##(P2)	;1ST CLUSTER ALLOCATED
	IMUL	T3,J		;1ST BLOCK
	POPJ	P,

;SUBROUTINE ALLOCATE 2ND RIB AND WRITE BOTH RIBS
;ARGS	T3=LOGICAL BLOCK NUMBER OF 1ST RIB
;	T4=ADDR OF UNIT FOR 1ST RIB

FIL2RB:	MOVE	P1,T3		;P1=LOG BLOCK NUM OF 1ST RIB
	MOVE	P3,T4		;P3=ADDR OF UNIT FOR 1ST RIB
	PUSHJ	P,C1TKB		;GET A BLOCK FOR 2ND RIB
	MOVE	T1,SATRBA	;CHECKSUM
	PUSHJ	P,CHEKSM
	PUSHJ	P,SATRBS	;STORE RETRIEVAL POINTER
	LDB	T4,STYCLP##(P2)	;1ST CLUSTER
	IMUL	T4,J		;T4=LOGICAL BLOCK NUM OF 2ND RIB
	EXCH	T4,P3		;P3=LOG BLK NUM OF 1ST RIB - FALL INTO WRTRIB
;SUBROUTINE TO WRITE RIBS
;ARGS	P1=LOGICAL BLOCK NUM OF 1ST RIB
;	P3=LOGICAL BLOCK NUM OF 2ND RIB
;	T4=ADDR OF UNIT FOR 1ST RIB

WRTRIB:	EXCH	T4,U		;SET U FOR 1ST UNIT
	PUSH	P,T4
	MOVE	T1,SATRBA	;IOWD FOR RIB
	MOVE	T2,J		;T2=BLOCKS PER CLUSTER
	IMULB	T2,RIBALC##+1(T1)	;CONVERT CLUSTERS ALLOCATED TO BLOCKS
	ADDM	T2,UFDBKS	;KEEP COUNT OF BLOCKS ALLOCATED IN CURRENT UFD
	MOVE	T2,P1		;LOGICAL BLOCK NUM FOR 1ST RIB
	MOVEM	T2,RIBSLF##+1(T1)	;LOGICAL BLOCK OF THIS RIB
	PUSHJ	P,BLKWRT	;WRITE IT OUT
	POP	P,U		;RESTORE U TO CALLING VALUE FOR 2ND RIB
	MOVE	T2,P3		;LOGICAL BLOCK NUM FOR 2ND RIB
	MOVEM	T2,RIBSLF##+1(T1)	;LOGICAL BLOCK OF 2ND RIB
	PJRST	BLKWRT		;WRITE OUT SECOND RIB AND EXIT

;SUBROUTINE TO COMPUTE CHECKSUM ON T1 AND SAVE T2
;ARG	T1=ADDR-1 OF WORD TO BE CHECKSUMMED
;VALUES	T1=CHECKSUM, STORED IN CHECKSUM FIELD OF T2
;USES T4

CHEKSM:	MOVE	T1,1(T1)	;T1=WORD TO CHECKSUM
CHEKS1:	PUSH	P,T2		;SAVE T2
	MOVE	T2,T1		;T2=WORD TO CHEKSUM
	PUSHJ	P,CHKST1##	;CALL FILSER TO COMPUTE IT
	POP	P,T2		;RESTORE T2
	DPB	T1,STYCKP##(P2)	;STORE IN T2 CHECKSUM FIELD
	POPJ	P,

;SUBROUTINE TO ALLOCATE 1 BLOCK BY CALLING TAKBLK
;VALUE	T2=RETRIEVAL POINTER FOR BLOCK ALLOCATED

C1TKB:	MOVEI	T3,TAKBLK##	;CALL TAKBLK
	HRROI	T2,1		;GET THE BLOCK ANYWHERE
	JRST	CATKBB

;SUBROUTINE TO TAKE 1 BLOCK AT BEGINNING OF SUPER CLUSTER FOR 1ST RIB
;ENTER	CATKB TO TAKE EXACTLY 1 BLOCK
;ENTER	CATKBA TO TAKE NUM BLOCKS IN RH(T2)  LH(T2)=-1 FOR EXACT NUM BLOCKS
;VALUE	T2=RETRIEVAL POINTER FOR BLOCKS ALLOCATED

CATKB:	HRROI	T2,1		;EXACTLY 1 BLOCK
CATKBA:	MOVEI	T3,ADJALC##	;GET BLOCKS AT BEGINNING OF SUPER CLUSTER
CATKBB:	MOVE	T1,[JRST ONCWAT##]
	MOVEM	T1,PWAIT1##	;SET UP WAIT IN CASE HAVE TO SWITCH SATS
	SETZ	T1,		;TAKE BLOCKS ANYWHERE
	PUSH	P,J		;IN CASE FILIO DOES IO
	PUSHJ	P,(T3)		;DO IT
	  JRST	NOROOM		;COULDNT GET ANY BLOCKS
	JRST	JPOPJ##		;RESTORE J AND RETURN
BADHOM:	SKIPA	T1,[[ASCIZ / bad block in HOME.SYS space/]]
FEWSAT:	MOVEI	T1,[ASCIZ / not enough SAT blocks/]
	PUSH	P,T1		;SAVE ADDR OF MESSAGE
	MOVEI	T1,[ASCIZ /% Unit /]
	PUSHJ	P,ICONM##	;START MESSAGE
	MOVE	T2,UDBNAM(U)	;GET UNIT NAME
	PUSHJ	P,PRNAME##	;PRINT IT
	POP	P,T1		;RESTORE ADDR OF MESSAGE
	JRST	PMSHLT		;TYPE MESSAGE AND HALT

NOROOM:	;POP	P,J		;CLEANING STACK NOT NECESSARY
NOROO1:	PUSHJ	P,OTSET##	;INITIALIZE CTY BUFFER
	MOVEI	T1,[ASCIZ /% Structure /]
	PUSHJ	P,ICONM##	;START MESSAGE
	MOVE	T2,STRNAM##(P2)	;GET STRUCTURE NAME
	PUSHJ	P,PRNAME##	;PRINT IT
	MOVEI	T1,[ASCIZ / is full, suggest reducing swapping space/]
	;PJRST	PMSHLT		;FALL INTO PMSHLT

;SUBROUTINE TO TYPE A MESSAGE ON CTY AND HALT
;ARGS	T1=ADDR OF MESSAGE
;OTSET MUST ALREADY HAVE BEEN CALLED

PMSHLT:	PUSHJ	P,CONMES##	;PUT CHARS IN CTY BUFFER
	PUSHJ	P,CRLFOP##	;APPEND CRLF AND OUTPUT CTY BUFFER
	JRST	REFERR		;TAKE ERROR RETURN FROM REFSTR
;SUBROUTINE TO COMPUTE AND STORE NEW UNIT POINTER FOR SAT.SYS

STNWUN:	LDB	T2,UNYLUN##	;LOGICAL UNIT NUMBER IN STR
	TRO	T2,RIPNUB##	;SET BIT TO MAKE SURE NON-0, FALL INTO SATRBS

;SUBROUTINE TO STORE RETRIEVAL POINTER IN SAT.SYS RIB
;ARG	T2=RETRIEVAL POINTER
;PRESERVES T2,T3,T4, USES T1

SATRBS:	MOVE	T1,SATRBP
	AOBJN	T1,SATRS1
	STOPCD	.,STOP,TMR,DIEUNI##, ;++TOO MANY RETIREVAL POINTERS
SATRS1:	MOVEM	T1,SATRBP
	PUSHJ	P,SAVT##	;SAVE T2,T3,T4
	MOVE	T3,SATRBA
	JRST	HOMRS2

;SUBROUTINE TO STORE A RETRIEVAL POINTER IN HOME.SYS RIB
;ARG	T2=RETRIEVAL POINTER
;PRESERVES T2,T3,T4, USES T1

HOMRBS:	MOVE	T1,HOMRBP
	AOBJN	T1,HOMRS1
	STOPCD	.,STOP,ERP,DIEUNI##, ;++TOO MANY RETRIEVAL POINTERS
HOMRS1:	MOVEM	T1,HOMRBP
	PUSHJ	P,SAVT##
	MOVE	T3,HOMRBA
HOMRS2:	MOVEM	T2,(T1)
	LDB	T1,STYCNP##(P2)	;NUMBER OF CLUSTERS
	ADDM	T1,RIBALC##+1(T3)	;COUNT TOTAL CLUSTER ALLOCATED FOR THIS FILE
	POPJ	P,

;SUBROUTINE TO WRITE OUT DATA IN ALL BUT 1ST BLOCK OF A CLUSTER
;ARG	T2=1ST BLOCK OF CLUSTER
;	DATA IN SAT BLOCK (SATBKA=IOWD)

FINCLS:	PUSHJ	P,SAVE1##	;SAVE P1
	MOVE	P1,J		;P1=BLOCKS PER CLUSTER
	SOJE	P1,CPOPJ##
	MOVE	T1,SATBKA
FINCL1:	ADDI	T2,1
	PUSHJ	P,BLKWRT
	SOJG	P1,FINCL1
	POPJ	P,
;SUBROUTINE TO SET UP RIB IN CORE
;ARGS	T1=NAME OF FILE
;	T2=EXT
;	T3=PPN
;	T4=ADDR OF BUFFER IN CORE-1
;	P4=BITS TO SET IN STATUS WORD
;	MFDFDB=1ST DATA BLOCK OF UFD IN WHICH FILE IS BEING WRITTEN
;VALUES	T4=POINTER FOR RETRIEVAL POINTERS TO BE STORED IN RIB

RIBSET:	MOVEI	T4,1(T4)	;T4=ADDR OF BUFFER
	MOVEM	T1,RIBNAM##(T4)
	MOVEM	T3,RIBPPN##(T4)	;STORE PPN
	HRR	T2,THSDAT##	;SET ACCESS DATE
	MOVEM	T2,RIBEXT##(T4)	;STORE EXT AND ACCESS DATE
	SUB	T1,CRSFNM	;SEE IF THIS FILE IS CRASH.EXE
	JUMPE	T1,RIBST1	;IF YOU DON'T STORE CREATION TIMES OR DATE
				;SO FILEX CAN STORE THE DATE OF A CRASH
	MOVE	T1,TIME##
	IDIV	T1,TICMIN##	;CONVERT TO TIME IN MINUTES
	LSH	T1,^D12		;SHIFT TIME
	LDB	T2,[POINT 12,THSDAT##,35]	;GET LOW ORDER 12 BITS OF DATE
	ADD	T1,T2		;PUT INTO FUTURE RIBPRV
	LDB	T2,[POINT 3,THSDAT##,23]	;GET HIGH ORDER 3 BITS OF DATE
	DPB	T2,[POINT 3,RIBEXT##(T4),20]	;STORE IN PROPER PLACE
RIBST1:	ADD	T1,CURPRT	;CURRENT ACCESS CODE
	MOVEM	T1,RIBPRV##(T4)	;STORE PRIVS WORD
	MOVE	T1,[XWD MRIBLN##,RIBENT##+1] ;GET AOBJN WORD TO FIRST RET PTR
	MOVEM	T1,RIBFIR##(T4)	;SALT AWAY IN RIB
	SETZM	RIBPRV##+1(T4)	;CLEAR REMAINDER OF RIB
	HRLZI	T1,RIBPRV##+1(T4)
	HRRI	T1,RIBPRV##+2(T4)
	BLT	T1,RIBCOD##-1(T4) ; UP THROUGH RIBCOD
	MOVE	T1,[EXP CODRIB##]
	MOVEM	T1,RIBCOD##(T4)	;UNLIKELY CODE FOR RIB
	MOVE	T1,CNFDVN##	;GET MONITOR VERSION
	MOVEM	T1,RIBVER##(T4)	;STORE VERSION NUMBER OF FILE
	MOVE	T1,[MACTSL##,,RIBACS##]
	MOVEM	T1,RIBACT##(T4)	;POINTER TO NULL ACCT STRING
	MOVE	T1,MFDRBD
	MOVEM	T1,RIBUFD##(T4)	;UFD BLOCK THIS WILL BE FOUND IN
	IORM	P4,RIBSTS##(T4)	;SET ANY STATUS BITS DESIRED
	ADD	T4,RIBFIR##(T4)	;MAKE T4 POINTER TO RETRIEVAL POINTERS
	SOJA	T4,CPOPJ##	;-1 TO ALLOW FOR INCREMENTING AND STORING PTRS
;SUBROUTINE TO SET UP AND STORE AN ENTRY IN A UFD
;	P3=INDEX OF FILE IN OUR TABLES
;	P4=LAST DATA BLOCK TO WRITE

UFDSTO:	SKIPN	T1,FSTUNW(P3)	;SET UP UNIT OF 1ST RIB
	POPJ	P,
	MOVE	T2,FSTBK(P3)	;LOGICAL BLOCK NUM OF 1ST RIB
	PUSHJ	P,COMCFP	;COMPUTE CFP
	MOVE	T1,FSTFL(P3)	;FILE NAME
	HRLI	T2,(SIXBIT .SYS.)	;MOST EXTENSIONS ARE SYS
	CAMN	T1,CRSFNM	;CRASH.EXE HAS A STRANGE EXTENSTION
	HRLI	T2,(SIXBIT .EXE.)

	CAIL	T1,0		;SKIP IF ASCII NAME, NOT OCTAL NUMBER
	HRLI	T2,(SIXBIT .UFD.)	;OCTAL NUMBERS ARE UFDS
	SKIPL	T4,UFDSTP	;SKIP IF STILL ROOM IN THIS BLOCK
	PUSHJ	P,NWBKUF	;WRITE OUT THIS BLOCK AND SET UP FOR NEXT
	MOVEM	T1,1(T4)	;STORE FILE NAME
	MOVEM	T2,2(T4)	;AND EXT AND CFP
	ADD	T4,[XWD 2,2]	;BUMP POINTER
	MOVEM	T4,UFDSTP	;RESTORE POINTER
	POPJ	P,

;SUBROUTINE TO WRITE OUT A UFD BLOCK AND SET UP FOR NEXT
;ARGS	P1=LOGICAL BLOCK NUM-1 TO WRITE OUT
;	P4=LAST LOGICAL BLOCK TO WRITE
;VALUES	T4=POINTER TO NEW BUFFER, UFDSTP SET UP
;PRESERVES T1,T2

NWBKUF:	PUSH	P,T2
	PUSH	P,T1
	AOS	T2,P1		;T2=LOGICAL BLOCK NUM TO WRITE
	MOVE	T1,SATBKA	;IOWD FOR DATA
	CAMLE	P1,P4		;NO SKIP IF NO MORE BLOCKS
	JRST	NOROO1
	PUSHJ	P,BLKWRT	;WRITE OUT THE BLOCK
	MOVE	T4,T1		;SAVE IT IN T4
	EXCH	T1,UFDSTP	;RESET POINTER
	HLRES	T1
	ADDI	T1,BLKSIZ##	;LENGTH OF MONITOR BUFFER
	ADDM	T1,UFDWRD
	MOVE	T1,T4
	PUSHJ	P,CORZER	;CLEAR THE BUFFER
	POP	P,T1
	JRST	T2POPJ##
;SUBROUTINE TO ZERO OUT A BLOCK OF CORE
;ARGS	T1=ADDR-1 OF CORE BLOCK
;ENTER AT CORONZ IF VALUE TO STORE ALREADY SET IN FIRST LOCATION

CORZER:	SETZM	1(T1)		;CLEAR FIRST WORD OF BLOCK
CORONZ:	HRLI	T1,1(T1)	;LH=ADDR
	ADDI	T1,2		;RH=ADDR+1, FORMING BLT POINTER
	MOVEI	T2,BLKSIZ##-2(T1)	;ADDR OF LAST WORD IN BUFFER
	BLT	T1,(T2)		;DO THE WHOLE BUFFER
	POPJ	P,

;SUBROUTINE TO COMPUTE A CFP
;ARG	T1-ADDR OF UNIT ON WHICH 1ST RIB IS WRITTEN
;	T2=LOGICAL BLOCK NUMBER
;	P3=INDEX OF FILE IN OUR TABLES
;VALUE	T2=CFP

COMCFP:	EXCH	T1,U		;T1 WAS UNIT WE WANTED
	LDB	T3,UNYLUN##	;LOGICAL UNIT NUMBER
	HRRZ	T4,UNISTR(U)	;ADDR OF STR DB
	MOVE	U,T1		;RESTORE U
	HRRZ	T1,STRSCU##(T4)	;NUM SUPER CLUSTERS PER UNIT
	IMUL	T1,T3		;SUPER CLUSTER NUM OF BLOCK 0 THIS UNIT
	HLRZ	T4,STRBSC##(T4)	;BLOCKS PER SUPER CLUSTER
	IDIV	T2,T4
	SKIPE	T3		;MUST COME OUT EVEN
	STOPCD	.+1,DEBUG,CIO,	;++CFP IS ODD
	ADD	T2,T1		;COMPLETE COMPUTATION OF SUPER CLUSTER
	POPJ	P,

;SUBROUTINE TO WRITE OUT A BLOCK
;ARGS	T1=IOWD
;	T2=LOGICAL BLOCK NUM
;	U=ADDR OF UNIT
;PRESERVES T1,T2

BLKWRT:	MOVEM	T1,@ONCMBF##	;OMNWRT TAKES IOWD FROM .UPMBF
	PUSHJ	P,OMNWRT##	;CALL ROUTINE IN ONCE.MOD TO WRITE OUT BLOCK
	  STOPCD .+1,DEBUG,EWB,DIEUNI##, ;++ERROR WRITING BLOCK
	LDB	J,UNYBPC##	;RESET BLOCKS PER CLUSTER
	MOVE	T1,@ONCMBF##	;AND IOWD
	POPJ	P,
	SUBTTL	DATA STORAGE

REPEAT	0,<
MNSBLA==^D21	;SIZE OF BLOCK ADDRESS FIELD
MNNBLA==^D35	;RIGHTMOST BIT OF BLOCK ADDRESS FIELD
MNSCNT==^D10	;SIZE OF BLOCK COUNT FIELD
MNNCNT==^D14	;RIGHTMOST BIT OF BLOCK COUNT FIELD
MNLEFT==^D36-MNSCNT-MNSBLA	;NUMBER OF BITS LEFT IN WORD (UNUSED)

MNYCNT:	POINT	MNSCNT,(P1),MNNCNT
MNYBLA:	POINT	MNSBLA,(P1),MNNBLA

MNTLST:	XWD	UTYP01,UTYP00	;KONTROLLER TYPE 0
	XWD	UTYP11,UTYP10	;KONTROLLER TYPE 1 - FIXED HEAD DISK
	XWD	UTYP21,UTYP20	;KONTROLLER TYPE 2 - DISK PACK
	XWD	UTYP31,UTYP30	;KONTROLLER TYPE 3 - MASS FILE

UTYP20:		;RP02
UTYP21:		;RP01
UTYP01:		;DRUM UNIT TYPE 1
UTYP00:		;DRUM UNIT TYPE 0
UTYP11:		;FIXED HEAD DISK UNIT TYPE 1
UTYP10:		;FIXED HEAD DISK UNIT TYPE 0
UTYP31:		;MASS FILE UNIT TYPE 1
UTYP30:	0	;MASS FILE UNIT TYPE 0

>
QUOTAR:	EXP	QR
QUOTAF:	EXP	QF
QUOTAO:	EXP	QO
;NAMES OF FILES WE CREATE
FSTFL:!
SATFNM:	SIXBIT	.SAT.		;SAT FILE
HOMFNM:	SIXBIT	.HOME.		;HOME BLOCK FILE
SWPFNM:	SIXBIT	.SWAP.		;FILE OF SWAPPING SPACE ON STR
IFN FTMAINT,<
MNTFNM:	SIXBIT	.MAINT.		;FILE OF MAINTENANCE TRACKS
>; END IFN FTMAINT
BADFNM:	SIXBIT	.BADBLK.	;FILE OF BAD REGIONS ON STR
CRSFNM:	SIXBIT	.CRASH.		;FILE FOR SAVING MONITOR CRASHES
SNPFNM:	SIXBIT	.SNAP.		;FILE FOR PERIODIC SNAPSHOTS OF MONITOR
RCVFNM:	SIXBIT	.RECOV.		;FILE FOR SCRATCH SPACE FOR RECOVERY PROGRAMS
	SIXBIT	.FE.		;FRONT-END FILE SYSTEM
LSTFL==.-FSTFL

SYSUFD:	BLOCK	1
PRTUFD:	BLOCK	1
XPNUFD:	BLOCK	1
ALPUFD:	BLOCK	1
XSYUFD:	BLOCK	1
OLDUFD:	BLOCK	1
MFDUFD:	BLOCK	1
LSTUF==.-LSTFL-FSTFL

;*** THIS LIST MUST BE IN THE SAME ORDER AS FILE NAMES

FSTBK:!
SATRBD:	BLOCK	1		;LOGICAL BLOCK NUMBER OF 1ST RIB FOR SAT.SYS
HOMRBD:	BLOCK	1		;LOGICAL BLOCK NUMBER OF 1ST RIB FOR HOME.SYS
SWPRBD:	BLOCK	1		;LOGICAL BLOCK NUMBER OF 1ST RIB FOR SWAP.SYS
IFN FTMAINT,<
MNTRBD:	BLOCK	1		;LOGICAL BLOCK NUMBER OF 1ST RIB FOR MAINT.SYS
>; END IFN FTMAINT
BADRBD:	BLOCK	1		;LOGICAL BLOCK NUMBER OF 1ST RIB FOR BADBLK.SYS
CRSRBD:	BLOCK	1		;LOGICAL BLOCK NUMBER OF 1ST RIB FOR CRASH.EXE
SNPRBD:	BLOCK	1		;LOGICAL BLOCK NUMBER OF 1ST RIB FOR SNAP.SYS
RCVRBD:	BLOCK	1		;LOGICAL BLOCK NUMBER OF 1ST RIB FOR RECOV.SYS
FERBD:	BLOCK	1		;LOGICAL BLOCK NUMBER OF 1ST RIB FOR FE.SYS
SYSRBD:	BLOCK	1		;LOGICAL BLOCK NUMBER OF 1ST RIB FOR SYS UFD
PRTRBD:	BLOCK	1		;LOGICAL BLOCK NUMBER OF 1ST RIB FOR PRINT UFD
XPNRBD:	BLOCK	1
ALPRBD:	BLOCK	1		;LOGICAL BLOCK NUMBER OF 1ST RIB FOR 1,2
XSYRBD:	BLOCK	1
OLDRBD:	BLOCK	1
MFDRBD:	BLOCK	1		;LOGICAL BLOCK NUMBER OF 1ST RIB FOR MFD (=1,1 UFD)
MFDPTR:	BLOCK	1		;FIRST RETRIEVAL POINTER FOR MFD
;*** THIS LIST MUST BE IN THE SAME ORDER AS FILE NAMES

FSTUNW:!
SATUN:	BLOCK	1		;LOGICAL UNIT OF 1ST RIB FOR SAT.SYS
HOMUN:	BLOCK	1		;LOGICAL UNIT OF 1ST RIB FOR HOME.SYS
SWPUN:	BLOCK	1		;LOGICAL UNIT OF 1ST RIB FOR SWAP.SYS
IFN FTMAINT,<
MNTUN:	BLOCK	1		;LOGICAL UNIT OF 1ST RIB FOR MAINT.SYS
>; END IFN FTMAINT
BADUN:	BLOCK	1		;LOGICAL UNIT OF 1ST RIB FOR BADBLK.SYS
CRSUN:	BLOCK	1		;LOGICAL UNIT OF 1ST RIB FOR CRASH.EXE
SNPUN:	BLOCK	1		;LOGICAL UNIT OF 1ST RIB FOR SNAP.SYS
RCVUN:	BLOCK	1		;LOGICAL UNIT OF 1ST RIB FOR RECOV.SYS
FEUN:	BLOCK	1		;LOGICAL UNIT OF 1ST RIB FOR FE.SYS
SYSUN:	BLOCK	1		;LOGICAL UNIT OF 1ST RIB FOR SYS UFD
PRTUN:	BLOCK	1		;LOGICAL UNIT OF 1ST RIB FOR PRT UFD
XPNUN:	BLOCK	1
ALPUN:	BLOCK	1		;LOGICAL UNIT OF 1ST RIB FOR 1,2
XSYUN:	BLOCK	1
OLDUN:	BLOCK	1
MFDUN:	BLOCK	1		;LOGICAL UNIT OF 1ST RIB FOR MFD
LSTUNW==.-FSTUNW
SATRBA:	BLOCK	1		;ADDRESS OF 1ST RIB IN CORE FOR SAT.SYS
HOMRBA:	BLOCK	1		;ADDRESS OF RIB IN CORE FOR HOME.SYS
BATBKA:	BLOCK	1		;ADDRESS OF PLACE IN CORE TO READ BAT BLOCKS
SATBKA:	BLOCK	1		;ADDRESS OF PLACE IN CORE TO CREATE SAT BLOCKS
FERBA:	BLOCK	1
CORN==.-SATRBA			;NUMBER OF CORE BLOCKS NEEDED

LBNLST:	BLOCK	3
LBNLEN=.-LBNLST

FSTLEN:!			;THIS TABLE CONTAINS NUMBER OF DATA BLOCKS TO ALLOCATE
CRSBKN:	BLOCK	1
SNPBKN:	BLOCK	1
RCVBKN:	BLOCK	1
ZERLEN==.-FSTLEN		;FILES ABOVE MAY HAVE 0 LENGTH, BELOW MAY NOT
SYUFSZ:	BLOCK	1
	BLOCK	1
MFDSIZ:	BLOCK	1
LSTLEN==.-FSTLEN
FELEN:	BLOCK	1		;NO OF BLOCKS IN FE.SYS

SATRBP:	BLOCK	1		;POINTER TO SPACE IN SAT.SYS RIB FOR RETRIEVAL PTRS
HOMRBP:	BLOCK	1		;POINTER TO SPACE IN HOME.SYS RIB FOR POINTERS
UFDSTP:	BLOCK	1		;POINTER TO SPACE IN UFD RIB FOR POINTERS
UFDWRD:	BLOCK	1		;WORDS WRITTEN IN THIS UFD
BEGSAT:	BLOCK	1
SVSBTL:	BLOCK	1
FSTUNI:	BLOCK	1		;RH=ADDR OF FIRST UNIT IN STR
LSTUNI==FSTUNI			;LH=ADDR OF LAST UNIT IN STR
LCLSAT:	BLOCK	1		;LAST CLUSTER IN CURRENT SAT
NDNCNF:	BLOCK	1		;NO DELETE, CHANGE NAME, FAILSAFE BITS IN UFD RIB
NDCFAB:	BLOCK	1		;ABOVE + ALWAYS BAD CHECKSUM
CHECK0:	BLOCK	1		;CHECKSUM OF WORD OF 0
UFDBKS:	BLOCK	1		;NUMBER OF BLOCKS ALLOCATED IN CURRENT UFD
MAXALC:	BLOCK	1		;MAXIMUM NUMBER OF CLUSTERS CAN ALLOCATE IN 1 PTR
CURPRT:	BLOCK	1		;CURRENT ACCESS CODE
SATIND==BADUN			;USED AS A TEMPORARY
HOMSR2==BADUN			;USED AS A TEMPORARY
BLKNED:	BLOCK	1		;TEMP

SAVEP:	BLOCK	1		;SAVED PDL ON ENTRY (FOR ERRORS)
ERRRET:	BLOCK	1		;FLAG NON-ZERO IF ERROR OCCURRED
				; (STRUCTURE NOT REFRESHED SUCCESSFULLY)
REFEND::END