Google
 

Trailing-Edge - PDP-10 Archives - de-10-omona-v-mc9 - refstr.mac
There are 11 other files named refstr.mac in the archive. Click here to see a list.
TITLE REFSTR - ROUTINE TO REFRESH A FILE STRUCTURE - V4100
SUBTTL  D BLACK  19 SEP 78
	SEARCH	F,S
	$RELOC
	$LOW



;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1973,1974,1975,1976,1977,1978 BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
XP VREFST,4100

ENTRY REFSTR

;EXTERNALS IN COMMOD.MAC

EXTERN	BAFCNT,BAFFIR,BAFNBR,BAYNBB,BLKSIZ,CODBAT,CODHOM,CODRIB,DEVMBF,DSKDDB
EXTERN	FBOOTB,FSFPPN,HOMBPC,HOMLEN,HOMPPN,HOMPT1,HOMREF,HOMTAB,HOMUN1,LBOBAT
EXTERN	LBOISW,MBLKSZ,MFDPPN,MFDPRV,MNBOOT,MRIBLN,NBOOTB,PNTPPN,RIBALC,RIBCOD
EXTERN	RIBENT,RIBEXT,RIBFIR,RIBNAM,RIBPPN,RIBPRV,RIBQTF,RIBQTO,RIBQTR,RIBSIZ
EXTERN	RIBSLF,RIBSTS,RIBUFD,RIBUSD,RIBVER,RIPABC,RIPDIR,RIPNDL,RIPNFS
EXTERN	RIPNUB,SABRNG,SAVE1,SAVE4,SPYCLA,SPYTAL,STNPRT,STRBPU,STRBSC,STRREF
EXTERN	STRSCU,STRUNI,STYCKP,STYCLP,STYCNP,SYNRPR,SYRDPR,SYSPPN,SYSPRV,UNIBPU
EXTERN	UNIHOM,UNISAB,UNISLB,UNISPT,UNISTR,UNYBPC,UNYK4S,UNYKTP,UNYLUN,UNYSIC
EXTERN	UNYSPU,TYPDP,CRUPPN,UFDPRT,DEVBLK

;EXTERNALS IN FILSER

EXTERN	ADJALC,CHKST1,NEWUNI,ONCWAT,PWAIT1,RSPWTC,SATRED,SAVT,TAKBLK,WTUSAT
EXTERN	SATCN,SCNPTR

;OTHERS

EXTERN	CORGRB,GTHOM,HICORE,OMNWRT,REDRUN,WRTRUN,SVOSET,SCONMS,SOPOUT,SPUNAM
EXTERN	BLKSPK,CPOPJ,CPOPJ1,REFLAG,TIME,THSDAT,DAREQ,TICMIN

;INTERNS WHICH MUST AGREE WITH COMMOD

INTERN	BASNBR,BANNBR

BASNBR==^D9
BANNBR==^D17

;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

;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
	MOVEI	R,NU0DAC##
	MOVEM	R,JBTADR##
	MOVEI	T1,RIPNDL	;NO DELETE FILE BIT
	ADDI	T1,RIPNFS	;PLUS NO FAILSAFE BIT
	MOVEM	T1,NDNCNF	;SINCE MACRO CANT ADD GLOBALS IN SAME HALF WORD
	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
	MOVE	T1,DEVMBF(F)	;USE MONITOR BUFFER ALREADY ALLOCATED FOR SAT RIB
	MOVEM	T1,SATRBA	;(ALSO SAVES POINTER)
	MOVE	T1,HICORE	;SAVE ORIGINAL HICORE
	MOVEM	T1,HICSAV	;SO WE CAN RETURN CORE WE USE
	MOVSI	P1,-CORN+1	;MINUS NUMBER OF EXTRA BUFFERS WE NEED
REF1:	MOVEI	T2,BLKSIZ	;AMOUNT OF CORE FOR 1 BUFFER
	PUSHJ	P,CORGRB	;GET A MONITOR BUFFER (SIZE OF DISK BLOCK)
	HRLI	T1,MBLKSZ
	SUBI	T1,1
	MOVEM	T1,SATRBA+1(P1)	;SAVE IOWD
	AOBJN	P1,REF1		;LOOP FOR ALL BUFFERS NEEDED
	MOVE	T1,HOMRBA	;IOWD FOR HOME BLOCK
	MOVEM	T1,DEVMBF(F)	;SAVE IOWD IN MONITOR BUFFER
	PUSHJ	P,GTHOM		;READ IN A HOME BLOCK FROM 1ST UNIT
	  STOPCD .+1,DEBUG,ERH,	;ERROR READIN 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
	STOPCD	CPOPJ,DEBUG,ZBC, ;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
	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
	SETZM	FSTBK		;CLEAR UNIT TABLE
	MOVE	T1,[XWD FSTBK,FSTBK+1]
	BLT	T1,FSTUNW+LSTUNW-1

;NOW 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
	  STOPCD .+1,DEBUG,CRH, ;++CAN'T READ HOME BLOCKS
	LDB	J,UNYBPC##
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
	SUBI	T2,1		;YES, POINT AT RIB ADDRESS
	MOVEM	T2,FERBD	;AND SAVE
	MOVE	T3,HOMFEL##+1(T1) ;GET LENGTH OF FE.SYS
	IDIVI	T3,(J)		;CONVERT TO CLUSTERS
	SKIPE	T4
	ADDI	T3,1
	MOVEM	T3,FELEN	;SAVE
	MOVEM	U,FEUN		;SAVE UNIT OS FE.SYS
	MOVE	T1,SATRBA	;USE SAT.SYS SPACE TEMPORARILY
	MOVEM	T1,DEVMBF##(F)
	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,SATRBA	;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 AGAINST WHAT WAS
	IDIVI	T2,(J)		; IN THE HOME BLOCK
	CAMN	T2,FELEN
	JRST	REF1G		;OK, IT REALLY IS FE.SYS
REF1E:	SETZM	FEUN		;NOT FE.SYS, CLEAR FLAG
REF1F:	HLRZ	U,UNISTR##(U)	;TRY NEXT UNIT
	JUMPN	U,REF1C
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		;((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		;(CLUSTERS-1/SATS)+1=CLUSTERS/SAT
	MOVEM	T1,LCLSAT	;-1=LAST CLUSTER IN FIRST SAT
	ADDI	T1,1		;+1 FOR ALL BUT LAST SAT
	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
	HLRZ	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 CPOPJ,DEBUG,NSS, ;++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
	PUSHJ	P,SATCN		;COUNT 0 BITS IN T2
	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
	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
	PUSHJ	P,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
	HLRZ	P2,SABRNG(P2)	;ADDR OF NEXT SAT IN RING
	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
ENSACL:	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,UFDALC	;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 CPOPJ,DEBUG,NMU, ;++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
	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
;HERE TO CREATE FILE MAINT.SYS - ALLOCATING BLOCKS FOR MAINTENANCE

MNTCRE:
REPEAT	0,<
	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
>
;HERE TO ALLOCATE SPACE FOR CRASH.SAV - 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.SAV
	JRST	NOCRS		;NO CRASH.SAV
	MOVE	T1,CRSFNM	;NAME OF CRASH.SAV FILE
IFE FTEXE,<
	MOVSI	T2,(SIXBIT .SAV.)
>
IFN FTEXE,<
	MOVSI	T2,(SIXBIT .EXE.)
>
	MOVE	P4,NDCFAB	;NO DELETE, FAILSAFE, BAD CHECKSUM
	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.SAV
	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	;J 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 J 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 J 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 J FOR SWAPPING
	LSH	T2,BLKSPK	;J FOR SWAPPING TIMES BLOCKS PER J = 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 THIS REGION
	TLZ	T1,BATMSK##
	MOVEI	T2,BAPNTP##
	TDNN	T2,BAFAPN##(P4)	;IF OLD-STYLE BAT
	HRRZS	T1		; ONLY 18 BITS COUNT
	MOVE	T2,P4		;T2=ADDR OF THIS ENTRY
	LDB	T2,BAYNBB	;NUMBER OF BAD BLOCKS THIS REGION - 1
	ADDI	T2,1
	PUSHJ	P,ZEXBLK	;SET PTR AND 0 BLOCKS OUTSIDE REGION
	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

SYSCRE:	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,UFDALC	;ALLOCATE SPACE FOR MFD
	MOVEM	U,MFDUN
	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,PNTPPN	;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	NOCRU		;DON'T BOTHER WITH THIS UFD
	MOVSI	T1,750000	;DON'T WANT PEOPLE READING
	MOVEM	T1,CURPRT
	SKIPN	T1,CRUPPN	;CRASH PPN
	JRST	NOCRU		;NO CRASH UFD DESIRED
	MOVEM	T1,CRUUFD
	PUSHJ	P,UFDSET
	MOVEM	P1,CRURBD
	MOVEM	U,CRUUN		;HERE TO CREATE MFD

NOCRU:	MOVE	T1,UFDPRT
	MOVEM	T1,CURPRT
	MOVE	T1,FSFPPN	;ALL PRIVILEGES PPN  (1,2)
	MOVEM	T1,ALPUFD
	PUSHJ	P,UFDSET	;CREATE UFD
	MOVEM	P1,ALPRBD
	MOVEM	U,ALPUN
	MOVE	T1,XSYPPN##
	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
	MOVEI	T2,2(P1)	;1ST BLOCK AFTER REDUNDENT RIB
	ADDI	P4,1		;LAST "REAL" BLOCK
MFDCR1:	CAMLE	T2,P4		;PAST REGION?
	SOJA	P4,MFDCRD	;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 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
	MOVE	T1,HOMRBA
	MOVEM	T1,DEVMBF(F)	;STORE IOWD FOR HOME BLOCK
	HRRZ	U,FSTUNI	;RESET TO 1ST UNIT

;HERE TO UPDATE HOME BLOCKS

HOMUPD:	PUSHJ	P,GTHOM		;READ HOME BLOCKS
	  STOPCD .+1,DEBUG,HBE, ;++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
	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
	  STOPCD .+1,DEBUG,EWH,	;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
;HERE WHEN ALL DONE

	PUSHJ	P,RSPWTC	;RESTORE WAIT ROUTINE
	MOVE	T1,FSFPPN	;FAILSAFE PROJ-R
	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
	HRRZS	STRREF(P2)	;CLEAR NEEDS REFRESHING FLAG IN CORE
	MOVE	T1,SATRBA	;IOWD FOR ORINGINAL MONITOR BUFFER
	MOVEM	T1,DEVMBF(F)
	MOVE	T1,HICSAV	;ORIGINAL VALUE OF HICORE
	MOVEM	T1,HICORE
	POP	P,JBTADR	;RESTORE JBTADR (MAY BE IN INTTAB)
	JRST	CPOPJ1		;SKIP RETURN
;SUBROUTINE TO READ IN A SAT BLOCK INTO MONITOR CORE
;ARGS	P2=ADDR OF IN-CORE BUFFER
;	P4=INDEX OF SAT

SATIN:	MOVE	T1,[JRST ONCWAT]
	MOVEM	T1,PWAIT1	;SET UP WAIT ROUTINE
	PUSHJ	P,SATRED
	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,DEVMBF(F)	;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,DEBUG,ERB,	;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
	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	T4,BAPNTP##	;IF OLD-STYLE
	TDNN	T4,BAFAPN##(P4)
	HRRZS	P1		; ONLY 18 BITS COUNT
	JRST	.+2
MRKBD2:	ADDI	P1,1		;P1=NEXT BAD BLOCK
	MOVE	T1,P1
	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 IF A BIT IS SET IN A BLOCK IN WHICH EACH BIT REPRESENTS A GROUP OF BLOCKS
;ARGS	P1=# OF BLOCKS REPRESENTED BY 1 BIT
;	P2=GROUP NUMBER REPRESENTED BY FIRST BIT
;	P3=GROUP NUMBER REPRESENTED BY BEST ACTUAL DATA BIT
;	P4=IOWD PTR TO BLOCK
;	T1=BLOCK NUMBER
;RETURN POPJ IF NOT SET
;SKIP IF SET

	INTERN	CHKBIT

CHKBIT:	IDIV	T1,P1		;T1=GROUP #
	SUB	T1,P2		;T1=RELATIVE GROUP # IN THIS BLOCK
	IDIVI	T1,^D36		;T1=INDEX IN BLOCK OF WORD CONTAINING LIST
	MOVNS	T2		;T2=BITS TO SHIFT RIGHT
	MOVSI	T4,400000	;SET LEFTMOST BIT
	LSH	T4,(T2)		;POSITION BIT
	ADDI	T1,1(P4)	;T1=ADDR OF WORD CONTAINING BIT
	TDNN	T4,(T1)		;SKIP IF BIT SET
	POPJ	P,		;NO, POPJ. RETURN
	JRST	CPOPJ1		;YES SKIP RETURN

;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
	JUMPE	T4,MRKEN1	;EXIT IF NO EXTRA BITS
	ADDI	T2,MBLKSZ+1(T3)	;T2=ADDR OF WORD CONTAINING BITS
	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,
BADHOM:	MOVEI	T1,[ASCIZ\
BAD BLOCK IN HOME.SYS SPACE\]
	PJRST	PMSHLT		;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 WRITE 0'S IN BLOCKS IN CLUSTERS CONTAINING THE REGION BUT
; NOT IN THE REGION, AND TO STORE RETRIEVAL POINTERS FOR THE REGION
;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
	MOVE	T1,P1		;T1=FIRST BLOCK IN REGION
	IDIV	T1,J		;T1=1ST CLUSTER IN REGION
	MOVE	P4,T1		;P4=1ST CLUSTER IN REGION
	IMUL	T1,J		;T1=1ST BLOCK IN 1ST CLUSTER
	MOVE	T2,T1		;SAVE IN T2
	MOVE	T1,SATBKA	;IOWD FOR BLOCK OF 0'S
	PUSHJ	P,ZEXBLA	;WRITE 0'S UP TO BEGINNING OF REGION
	ADD	P1,P3		;1ST BLOCK IN REGION+NUM BLOCKS IN REGION
	MOVE	T1,P1		;P1=1ST BLOCK PAST REGION
	SUBI	T1,1		;-1=LAST BLOCK IN REGION
	IDIV	T1,J		;T1=LAST CLUSTER
	AOS	T2,T1		;T2=1ST CLUSTER PAST REGION
	IMUL	T2,J		;T2=1ST BLOCK PAST LAST CLUSTER OF REGION
	EXCH	T2,P1		;T2=1ST BLOCK PAST REGION, P1=1ST PAST LAST CLUSTER
	MOVE	P3,SATBKA	;IOWD FOR BLOCK OF 0'S
	EXCH	T1,P3		;P3=LAST CLUSTER+1, T1=IOWD
	PUSHJ	P,ZEXBLA	;WRITE 0'S PAST REGION IN LAST CLUSTER
	SUB	P3,P4		;P3=NUM CLUSTERS, P4=1ST CLUSTER
	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 WRITE BLOCKS OF 0'S IN UNUSED PARTS OF A CLUSTER
;ARGS	T2=1ST BLOCK TO 0
;	P1=1ST BLOCK PAST END OF REGION TO 0

ZEXBLA:	CAMN	T2,P1		;NO SKIP WHEN REACH BEGINNING OF REGION
	POPJ	P,
	PUSHJ	P,BLKWRT	;WRITE 0'S IN BLOCK
	AOJA	T2,ZEXBLA
;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
;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	.,HALT,NSR,	;++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
	PUSHJ	P,RIBSET
	MOVEM	T4,SATRBP	;POINTER TO RETRIEVAL POINTERS
	PUSHJ	P,STNWUN
	PUSH	P,SATRBP	;SAVE PTR TO RETRIEVAL PTRS
FIL1R1:	HRRO	T2,BLKNED	;BLOCKS NEEDED
	PUSHJ	P,CATKBA	;TRY TO ALLOCATE BLOCKS
	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
	PUSHJ	P,(T3)		;DO IT
	  JRST	NOROOM		;COULDNT GET ANY BLOCKS
	POPJ	P,
FEWSAT:	MOVEI	T1,[ASCIZ . NOT ENOUGH SAT BLOCKS
.]
PMUHLT:	PUSH	P,T1		;SAVE ADDR OF MESSAGE
	PUSHJ	P,SVOSET	;INITIALIZE CTY BUFFER
	PUSHJ	P,SPUNAM	;TYPE UNIT NAME
	POP	P,T1		;RESTORE ADDR OF MESSAGE
	JRST	PMSHL1		;TYPE MESSAGE AND HALT
NOROOM:
	MOVEI	T1,[ASCIZ .
FILE STRUCTURE FULL, SUGGEST REDUCING SWAPPING SPACE
.]

;SUBROUTINE TO TYPE A MESSAGE ON CTY AND HALT
;ARGS	T1=ADDR OF MESSAGE

PMSHLT:	PUSHJ	P,SVOSET	;INITIALIZE CTY BUFFER
PMSHL1:	PUSHJ	P,SCONMS	;PUT CHARS IN CTY BUFFER
	PUSHJ	P,SOPOUT	;OUTPUT CTY BUFFER
	STOPCD	.,HALT,CAS,	;COULDNT ALLOCATE SPACE
;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	.,HALT,TMR,	;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	.,HALT,ERP,	;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.SAV
	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)
	MOVE	T1,[XWD MRIBLN,RIBENT+1]
	MOVEM	T1,RIBFIR(T4)
	MOVE	T1,STNVER	;STANDARD VERSION NUMBER
	MOVEM	T1,RIBVER(T4)
	SETZM	RIBPRV+1(T4)
	HRLZI	T1,RIBPRV+1(T4)
	HRRI	T1,RIBPRV+2(T4)
	BLT	T1,RIBCOD-1(T4)
	MOVE	T1,[EXP CODRIB]
	MOVEM	T1,RIBCOD(T4)	;UNLIKELY CODE FOR RIB
	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
	ORM	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.SAV HAS A STRANGE EXTENSTION
IFE FTEXE,<
	HRLI	T2,(SIXBIT .SAV.)
>
IFN FTEXE,<
	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	NOROOM
	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
	POP	P,T2
	POPJ	P,
;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,DEVMBF(F)	;OMNWRT TAKES IOWD FROM DEVMBF(F)
	PUSHJ	P,OMNWRT	;CALL ROUTINE IN ONCE.MOD TO WRITE OUT BLOCK
	  STOPCD .+1,DEBUG,EWB,	;++ERROR WRITING BLOCK
	LDB	J,UNYBPC	;RESET BLOCKS PER CLUSTER
	MOVE	T1,DEVMBF(F)	;AND IOWD
	POPJ	P,
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

>
STNVER:	XWD	0,1		;STANDARD VERSION NUMBER

QUOTAR:	EXP	QR
QUOTAF:	EXP	QF
QUOTAO:	EXP	QO

BAYNBR:	POINT	BASNBR,BAFNBR(T4),BANNBR

;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
;;MNTFNM:	SIXBIT	.MAINT.		;FILE OF MAINTENANCE TRACKS
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
FEFNM:	SIXBIT	.FE.		;FRONT-END FILE SYSTEM
LSTFL=.-FSTFL

SYSUFD:	BLOCK	1
PRTUFD:	BLOCK	1
CRUUFD:	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
;;MNTRBD:	BLOCK	1		;LOGICAL BLOCK NUMBER OF 1ST RIB FOR MAINT.SYS
BADRBD:	BLOCK	1		;LOGICAL BLOCK NUMBER OF 1ST RIB FOR BADBLK.SYS
CRSRBD:	BLOCK	1		;LOGICAL BLOCK NUMBER OF 1ST RIB FOR CRASH.SAV
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
CRURBD:	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
LSTBKL=.-FSTBK

;*** 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
;;MNTUN:	BLOCK	1		;LOGICAL UNIT OF 1ST RIB FOR MAINT.SYS
BADUN:	BLOCK	1		;LOGICAL UNIT OF 1ST RIB FOR BADBLK.SYS
CRSUN:	BLOCK	1		;LOGICAL UNIT OF 1ST RIB FOR CRASH.SAV
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
CRUUN:	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
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
PRUFSZ:	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
HICSAV:	BLOCK	1		;SAVE ORIGINAL HICORE (IN ONCE.MOD)
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
REFEND:	END