Google
 

Trailing-Edge - PDP-10 Archives - BB-Y393E-SM - monitor-sources/dskalc.mac
There are 55 other files named dskalc.mac in the archive. Click here to see a list.
;Edit 3181 to DSKALC.MAC by LOMARTIRE on Wed 7-Nov-84 - Prevent OKSKBG BUGHLTs.
;Edit 3092 to DSKALC.MAC by LOMARTIRE on Wed 18-Apr-84, for SPR #19331
;		Prevent J0NRUN by being NOSKED when BAT block lock obtained
;Edit 2960 to DSKALC.MAC by WEETON on Tue 10-May-83, for SPR #18539
;		Allow abortions of DA%INI without doing DA%WRTs
; UPD ID= 215, FARK:<4-1-WORKING-SOURCES.MONITOR>DSKALC.MAC.2,  28-Oct-82 11:05:43 by DONAHUE
;Edit 2851 - Rwrite disk allocation algorithm to be fairer
;<4-1-FIELD-IMAGE.MONITOR>DSKALC.MAC.2, 25-Feb-82 20:18:45, EDIT BY DONAHUE
;UPDATE COPYRIGHT DATE
; UPD ID= 992, FARK:<4-WORKING-SOURCES.MONITOR>DSKALC.MAC.8,  21-Feb-82 18:34:27 by ZIMA
;Edit 1986 - Fix structure rebuilding to initialize for BOOTSTRAP.BIN properly.
; UPD ID= 938, FARK:<4-WORKING-SOURCES.MONITOR>DSKALC.MAC.7,   7-Jan-82 13:04:13 by DONAHUE
;Edit 1972 - Save Q registers in SEEADR for previous edit
; UPD ID= 783, FARK:<4-WORKING-SOURCES.MONITOR>DSKALC.MAC.6,   8-Sep-81 10:37:42 by DONAHUE
;Edit 1939 - Rewrite Bat block logic to convert all addresses to logical
; UPD ID= 717, FARK:<4-WORKING-SOURCES.MONITOR>DSKALC.MAC.5,  19-Aug-81 10:17:37 by ZIMA
;Edit 1925 - put edit 1826 in standard form.  No code changes.
; UPD ID= 534, FARK:<4-WORKING-SOURCES.MONITOR>DSKALC.MAC.4,  13-May-81 14:38:36 by SCHMITT
;Edit 1874 - Restore DSKSIZ index at DSECT1
; UPD ID= 517, FARK:<4-WORKING-SOURCES.MONITOR>DSKALC.MAC.3,   6-May-81 14:07:41 by SCHMITT
;Edit 1867 - Rewrite Bad swapping address allocation routine at GTADR
; UPD ID= 370, FARK:<4-WORKING-SOURCES.MONITOR>DSKALC.MAC.2,  19-Jan-81 16:05:54 by DONAHUE
;Edit 1826 - set bit AR%EXM in some <R-D> files when creating a structure
; UPD ID= 164, FARK:<4-WORKING-SOURCES.MONITOR>DSKALC.MAC.4,  28-Aug-80 14:24:18 by ZIMA
;Edit 1772 - put 1732 into standard form.
; UPD ID= 50, FARK:<4-WORKING-SOURCES.MONITOR>DSKALC.MAC.3,   7-Jun-80 10:47:52 by SCHMITT
; Edit 1732 - Restore SDB ADR for structure after assigning Swap ADR
; UPD ID= 47, FARK:<4-WORKING-SOURCES.MONITOR>DSKALC.MAC.2,   6-Jun-80 15:40:55 by SCHMITT
; TCO 5.1060 - EDIT 1731 - Fix calc of BTB size at FSIDI2+52
; UPD ID= 201, SNARK:<4.MONITOR>DSKALC.MAC.15,  12-Jan-80 15:58:17 by DBELL
;TCO 4.2596 - MAKE DSKOP GIVE ERROR IF UNUSED FLAGS ARE SPECIFIED
;<4.MONITOR>DSKALC.MAC.14,  3-Jan-80 08:08:34, EDIT BY R.ACE
;UPDATE COPYRIGHT DATE
;<OSMAN.MON>DSKALC.MAC.1, 10-Sep-79 15:27:16, EDIT BY OSMAN
;TCO 4.2412 - Move definition of BUGHLTs, BUGCHKs, and BUGINFs to BUGS.MAC
;<4.MONITOR>DSKALC.MAC.12,  7-Sep-79 10:37:47, EDIT BY SCHMITT
;JUST CLEANING UP PREVIOUS EDIT
;<4.MONITOR>DSKALC.MAC.11, 17-Aug-79 10:39:46, EDIT BY SCHMITT
;TCO 4.2409-EDIT TO CURE ASAASG & ASGBPG BUGCHECK DURING BIT TABLE INIT
;<4.MONITOR>DSKALC.MAC.10,  2-May-79 08:13:11, Edit by KONEN
;CHANGE JOB TO FORK IN SDBSTS FOR INITING A STRUCTURE
;<4.MONITOR>DSKALC.MAC.9, 17-Apr-79 15:47:50, EDIT BY DBELL
;TCO 4.2251 - ROUND BAT BLOCK ENTRIES DOWN TO PAGE BOUNDARIES.
;<4.MONITOR>DSKALC.MAC.8, 19-Mar-79 13:51:01, EDIT BY HALL
;GETBTB - BE NOINT WHEN WE HAVE JSB FREE SPACE
;<4.MONITOR>DSKALC.MAC.7,  4-Mar-79 15:27:50, EDIT BY KONEN
;UPDATE COPYRIGHT FOR RELEASE 4
;<4.MONITOR>DSKALC.MAC.5,  8-Jan-79 06:42:59, EDIT BY GILBERT
;TCO 4.2155 - Implement hidden symbol tables:
;	Change PSECT bounds symbols.
;	Change BUTPGA to HOMPGA.
;FIX REDHOM ROUTINE SO ADDRESSES LESS THAN 400000 DON'T CAUSE SECG37
;<4.MONITOR>DSKALC.MAC.4, 15-Oct-78 00:07:18, EDIT BY ZIMA
;TCO 4.2044 FIX CPYH1/CPYH2 TO WRITE CORRECT HOMHOM WORD
;<4.MONITOR>DSKALC.MAC.3, 12-Oct-78 01:11:04, EDIT BY ZIMA
;TCO 4.2041 FIX ADDPR TO USE THE LAST BAT BLOCK ENTRY
;<3A.MONITOR>DSKALC.MAC.11, 24-Jul-78 22:56:16, Edit by MCLEAN
;FIX DSKASG NOT TO LOOSE Q1
;<4.MONITOR>DSKALC.MAC.8,  6-May-78 21:26:06, Edit by MCLEAN
;ADD RP07

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1976,1977,1978,1979,1980,1981,1982 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.

	SEARCH PROLOG,PHYPAR
	TTITLE DSKALC

;NO SPECIAL AC'S USED HEREIN

	SWAPCD

;DEVICE INDEPENDENT DISK RELATED STUFF - D. MURPHY

;STORAGE

;RS LSTTKA,1			;LAST TRACK ASSIGNED
;RS DSKFRC,1			;TOTAL FREE PAGES ON DISK
;RS DSKALK,1			;LOCK AGAINST DISK ASSIGNMENTS
;DSKASN - ASSIGN PAGE ON DISK
;IF AC1 .NE 0, AC1 IS DISK ADDRESS - ASSIGN FROM SAME TRACK
;OTHERWISE, ASSIGN FROM A TRACK WITH .GE MINFPG FREE PAGES.  START
;SEARCHING AT SDBLCA, EXAMINE TRACK N ON ALL DRIVES, THEN TRACK
;N+1 ON ALL DRIVES, ETC.

;ACCEPTS:
;	T1/SECTOR NUMBER ON DISK RELATIVE TO START OF STRUCTURE OR ZERO
;	T2/STRUCTURE NUMBER

;RETURNS +1: FAILURE
;	 +2: SUCCESS
;		T1/DISK ADDRESS ASSIGNED

;USE OF Q REGISTERS:
;	Q1/ADDRESS OF SIZE DATA FOR THIS DISK TYPE
;	Q2/ADDRESS OF SDB FOR THIS STRUCTURE
;	Q3/CURRENT CYLINDER NUMBER

DSKASN::SAVEQ
	SE1CAL			;FORCE SECTION 1
;**;[2851] Change 1 line at DSKASN:+2L	PED	28-OCT-82
	STKVAR <STRN00>		;[2851]
	MOVEM 2,STRN00		;SAVE STRUCTURE NUMBER
	MOVEM 1,Q3		;SAVE DISK ADDRESS
	MOVE Q2,STRTAB(2)	;GET ADDRESS OF SDB FOR THIS STRUCTURE
	MOVX T4,MI%ASG		;IF ASSIGNMENTS ARE PROHIBITED BECAUSE BIT
	TDNE T4,SDBSTS(Q2)	; TABLE IS BAD OR DOESN'T EXIST,
	RETBAD			;TAKE THE FAILURE RETURN
	CAIN 2,PSNUM		;IS THIS PS?
	JRST [	MOVX Q1,SC%WHL!SC%OPR ;YES. SEE IF PRIVILEGED
		TDNE Q1,CAPENB	; IS IT?
		JRST .+1	;YES. ALLOW CREATE THEN
		MOVE 1,2	;GET STRUCTURE #
		CALL GSTRPG	;GET ALLOCATION
		CAMG T2,SYSSPC	;ABOVE MIN FREE?
		RETBAD (,<MOVE 1,Q3>) ;NO. ERROR THEN
		MOVE 2,STRN00	;YES. ALLOW IT
		JRST .+1]
	MOVE Q1,SDBTYP(Q2)	;GET ADDRESS OF DSKSIZ TABLE FOR THIS TYPE OF DISK
	MOVE 1,2		;1/STRUCTURE NUMBER
	CALL MAPBTB		;MAP INDEX BLOCK INTO BTBBAS, LOCK INTO CORE,
				; LOCK BTBLCK, GO NOSKED
	MOVE 1,Q3		;RESTORE DISK ADDRESS
	MOVE 4,BTBORA		;ADDRESS OF START OF BIT TABLE
	JUMPE 1,DSKA1		;FREE CHOICE

;USER REQUESTED A SPECIFIC ADDRESS.  TRY TO GET A PAGE ON THE SAME
;CYLINDER. IF NO PAGE IS FREE, SCAN INCREASING TRACK NUMBES

	TLZ 1,DSKMSK		;FLUSH GARBAGE BITS
	IDIV 1,SECCYL(Q1)	;1/CYLINDER, 2/SECTOR WITHIN CYLINDER
	CAMG 1,SDBCYL(Q2)	;WITHIN CYLINDER LIMIT FOR STRUCTURE?
	CAIGE 1,LOTRK		;NON-NEGATIVE CYLINDER NUMBER?
	JRST DSKA1		;NO, USE FREE CHOICE ALGORITHM
	ADD 4,1			;POINT TO BIT TABLE WORD FOR THIS TRACK
	SKIPN 0(T4)		;ANY PAGES FREE ON THIS TRACK?
;**;[2851] Change 1 line at DSKA9:-7L	PED	28-OCT-82
	JRST [ADD T1,CYLUNT(Q1)	;[2851] NO, GO GET A PAGE FROM THE NEXT TRACK
		JRST DSKSQ]
	; ..
;A CYLINDER HAS BEEN SELECTED
;	T1/CYLINDER NUMBER
;	T4/ADDRESS OF WORD IN BIT TABLE CONTAINING THE NUMBER OF FREE PAGES

DSKA9:	MOVEM 1,Q3		;SAVE TRACK NUMBER
	SOS 0(4)		;REDUCE FREE COUNT THIS TRACK
	SOS SDBFRC(Q2)		;REDUCE FREE COUNT FOR STRUCTURE
	IMUL 1,BTWCYL(Q1)	;COMPUTE OFFSET OF START OF BITS FOR THIS TRACK
	ADD 1,BTBORA		;COMPUTE ADDRESS IN BIT TABLE
	ADD 1,SDBBT0(Q2)	;ADD SIZE OF TOP HALF
	SETZ 2,			;INITIALIZE COUNT OF BITS

;LOOP THROUGH BIT WORDS FOR THIS CYLINDER, FINDING THE FIRST WORD
;WITH AT LEAST ONE 'ON' BIT, INDICATING A FREE PAGE

DSKA2:	SKIPE 3,0(1)		;ANY FREE PAGES THIS WORD?
	JRST DSKA3		;YES
	ADDI 2,^D36		;NO. NOTE 36 BITS HAVE BEEN CHECKED
	CAML 2,PAGCYL(Q1)	;LOOKED AT BITS FOR ALL PAGES?
	 SKIPA			;YES. COULDN'T FIND A FREE PAGE
	AOJA 1,DSKA2		;NO. GO LOOK AT THE NEXT WORD OF BITS

;FOUND A CYLINDER WHOSE FREE COUNT IS NON-ZERO, AND ITS BITS INDICATE NO
;FREE PAGES. WARN THE OPERATOR AND PROHIBIT ASSIGNMENTS AND DEASSIGNMENTS

	MOVE T1,STRN00		;T1/ STRUCTURE NUMBER
	MOVE T2,STRTAB(T1)	;POINT TO SDB FOR THIS STRUCTURE
	LOAD T2,STRUC,(T2)	;GET UNIQUE CODE FOR THIS STRUCTURE
	MOVE T3,Q3		;GET CYLINDER NUMBER
	BUG(DSKBT1,<<T2,D>,<T3,D>>)
	MOVX T3,MI%ASG		;SET BIT IN STRUCTURE STATUS WORD
	IORM T3,SDBSTS(Q2)	; TO PROHIBIT ASSIGNMENTS AND DEASSIGNMENTS
	CALL UMPBTB		;UNMAP INDEX BLOCK FROM BTBBAS, UNLOCK CORE PAGE,
				; UNLOCK BTBLCK, GO OKSKED
	RETBAD			;TAKE FAILURE RETURN
;HERE WHEN FREE PAGE HAS BEEN FOUND. MARK IF OFF IN THE BIT TABLE
;CONVERT IT TO A SECTOR NUMBER TO RETURN TO THE CALLER

;	T1/ADDRESS OF WORD IN BIT HALF OF BIT TABLE
;	T2/PAGE NUMBER WITHIN CYLINDER FOR BIT 0 OF CURRENT BIT WORD
;	T3/CONTENTS OF WORD
;	Q2/ADDRESS OF SDB
;	Q1/ADDRESS OF SIZE DATA FOR THIS DISK TYPE

DSKA3:	JFFO 3,.+1		;FIND FIRST FREE BLOCK
	MOVE 3,BITS(4)		;MAKE IT NO LONGER FREE
	ANDCAM 3,0(1)		;CLEAR BIT
	ADDI 2,0(4)		;PAGE NUMBER WITHIN THIS TRACK
	IMUL 2,SECPAG(Q1)	;CONVERT TO SECTOR NUMBER
	MOVE 1,Q3		;RECOVER CYLINDER NUMBER
	IMUL 1,SECCYL(Q1)	;COMPUTE LINEAR ADDRESS
	ADD 1,2
	TLO 1,(DSKAB)		;INDICATE DISK ADDRESS, NEWLY ASSIGNED
	MOVEM 1,Q3		;SAVE DISK ADDRESS
	MOVE 1,STRN00		;1/STRUCTURE NUMBER
	CALL UMPBTB		;UNMAP INDEX BLOCK FROM BTBBAS, UNLOCK CORE PAGE,
				; UNLOCK BTBLCK, GO OKSKED
	MOVE 1,Q3		;RESTORE DISK ADDRESS
	RETSKP
;THE SEARCH FOR THE BEST TRACK (DSKASN)

;	Q2/ADDRESS OF SDB
;	Q1/ADDRESS OF SIZE DATA FOR THIS DISK TYPE

;**;[2851] Delete 2 lines at DSKA1:	PED	28-OCT-82
DSKA1:	MOVE 1,SDBLCA(Q2)	;START WITH LAST TRACK ASSIGNED
DSKSQ:	SETZ 4,			;TO RECORD MAX FREE FOUND
	MOVE 3,SDBCYL(Q2)	;NUMBER CYLINDERS TO LOOK AT
DSKA6:	CAIGE 1,LOTRK		;LOOKING AT NON-NEGATIVE TRACK?
	JRST [	ADD 1,CYLUNT(Q1);NO, LOOK AT NEXT PACK
		JRST DSKA6]
	CAML 1,SDBCYL(Q2)	;LOOKING WITHIN KNOWN CYLINDERS?
	JRST [	IDIV 1,CYLUNT(Q1) ;NO, LOOK ON PACK 0...
		MOVEI 1,1(2)	;NEXT CYLINDER
		JRST DSKA6]
	MOVE 2,BTBORA		;POINT TO START OF BIT TABLE
	ADD 2,1			;POINT TO WORD FOR THIS TRACK
	CAML 4,0(2)		;THIS TRACK HAVE .G THAN BEST SO FAR?
	JRST DSKA4		;NO
	MOVE 4,0(2)		;YES, REMEMBER COUNT
	MOVEM 1,SDBLCA(Q2)	;REMEMBER WHAT TRACK HAD IT
;**;[2851] Change 1 line at DSKA4:-2L	PED	28-OCT-82
	CAML 4,SDBMFP(Q2)	;[2851] GOOD ENOUGH TO QUIT?
	JRST DSKA8		;YES
;**;[2851] Delete 2 lines at DSKA4:	PED	28-OCT-82
DSKA4:	ADD 1,CYLUNT(Q1)	;LOOK ON NEXT DRIVE
	SOJG 3,DSKA6		;COUNT TRACKS EXAMINED
	MOVEM 4,SDBMFP(Q2)	;REMEMBER NEW LOW VALUE
	JUMPE 4,[MOVE 1,STRN00	;IF ZERO, FOUND NO TRACK WITH FREE PAGE
		CALL UMPBTB	;UNMAP INDEX BLOCK FROM BTBBAS, UNLOCK CORE PAGE,
				; UNLOCK BTBLCK, GO OKSKED
		MOVE 1,Q3	;RETURN ADDRESS REQUESTED
		RET]		;TAKE ERROR RETURN
DSKA8:	MOVE 1,SDBLCA(Q2)	;GET TRACK
	MOVE 4,BTBORA		;POINT TO START OF BIT TABLE
	ADD 4,1			;POINT TO WORD OF FREE PAGES FOR THIS TRACK
	JRST DSKA9		;GO SELECT PAGE ON THIS TRACK
;DSKASA - ASSIGN SPECIFIC DISK ADDRESS
;CYLASA - ASSIGN SPECIFIC CYLINDER (1 CYL OF DISK ADDRESSES)

;ACCEPTS:
;	T1/SECTOR NUMBER ON DISK RELATIVE TO START OF STRUCTURE
;	T2/STRUCTURE NUMBER

;RETURNS +1: FAILURE
;		T1/ERROR CODE
;	 +2: SUCCESS
;		T1/ DISK ADDRESS ASSIGNED

;THIS ROUTINE IS CALLED BY MONITOR CODE. IT BUGCHKS IF THE PAGE
;WAS ALREADY ASSIGNED

CYLASA::TDZA T3,T3		;SAY CYLINDER
DSKASA::SETO T3,0		;SAY SINGLE ADDRESS
	ASUBR<DSKAD1,STRN20>
	SE1CAL			;FORCE SECTION 1
	CALL DSKASG		;GO DO THE ASSIGNMENT
	 JRST [	CAIE T1,DSKX08	;FAILED. WAS IT ALREADY ASSIGNED?
		RETBAD		;NO. SOME OTHER ERROR. DON'T BUGCHK
		EXCH T1,STRN20	;YES. GET STRUCTURE NUMBER AND SAVE ERROR
		HRRZ T1,STRTAB(T1) ;POINT TO ITS SDB
		LOAD T1,STRUC,(T1) ;GET ITS UNIQUE CODE
		MOVE T2,DSKAD1	;GET REQUESTED DISK ADDRESS
		BUG(ASAASG,<<T1,D>,<T2,D>>)
		MOVE T1,STRN20	;RETRIEVE ERROR CODE
		RETBAD]		;TAKE ERROR RETURN
	RETSKP			;SUCCESS

;DSKASG - ASSIGN SPECIFIC DISK ADDRESS OR CYLINDER

;ACCEPTS:
;	T1/SECTOR NUMBER ON DISK RELATIVE TO START OF STRUCTURE
;	T2/STRUCTURE NUMBER
;	T3/ -1 IF SINGLE DISK ADDRESS, 0 IF CYLINDER

;RETURNS +1: FAILURE
;		T1/ERROR CODE
;	 +2: SUCCESS
;		T1/ DISK ADDRESS ASSIGNED

;THIS ROUTINE IS CALLED DIRECTLY BY THE DSKAS JSYS. IT DOES NOT BUGCHK
;WHEN AN ADDRESS IS PASSED FOR A PAGE THAT IS ALREADY ASSIGNED. THIS
;IS BECAUSE CHECKD DELIBERATELY DOES THE DSKAS JSYS FOR PAGES THAT ARE
;ASSIGNED. IT DOES BUGCHK ON ILLEGAL DISK ADDRESS.

DSKASG:	STKVAR <STRN01,DSKADR,ASGTYP>
	MOVEM T1,DSKADR		;SAVE DISK ADDRESS
	MOVEM T2,STRN01		;SAVE STRUCTURE NUMBER
	MOVEM T3,ASGTYP		;SAVE TYPE OF ASSIGN
	MOVE T3,STRTAB(T2)	;POINT TO SDB FOR THIS STRUCTURE
	MOVX T4,MI%ASG		;IF ASSIGNMENTS ARE PROHIBITED BECAUSE BIT
	TDNE T4,SDBSTS(T3)	; TABLE IS BAD OR DOESN'T EXIST,
	RETBAD (DSKX05)		; TAKE THE FAILURE RETURN
	MOVE T1,T2		;T1/STRUCTURE NUMBER
	CALL MAPBTB		;MAP INDEX BLOCK INTO BTBBAS, LOCK INTO CORE,
				; LOCK BTBLCK, GO NOSKED
	MOVE T1,DSKADR		;T1/DISK ADDRESS
	MOVE T2,STRN01		;T2/STRUCTURE NUMBER
	CALL DSKGX		;COMPUTE LOCATION IN BIT TABLE
				; T1/OFFSET IN BIT PART OF BITTABLE, T2/TRACK
				; NUMBER, T3/WORD CONTAINING BIT FOR THIS PAGE	
	 JRST DSKAA2		;BAD ADDRESS
	EXCH Q1,ASGTYP		;GET TYPE
	MOVE T4,STRN01		;GET STRUCTURE NUMBER
	MOVE T4,STRTAB(T4)	;POINT TO START OF SDB FOR THIS STRUCTURE
	ADD T1,SDBBT0(T4)	;COMPUTE OFFSET IN BIT TABLE FOR BIT WORD
	ADD T1,BTBORA		;COMPUTE ADDRESS OF BIT WORD
	ADD T2,BTBORA		;POINT TO WORD CONTAINING FREE PAGE COUNT
	JUMPN  Q1,DSKAA3	;ONLY SINGLE PAGE
	MOVE Q1,SDBTYP(T4)	;FIND DISK TYPE
	MOVE Q1,PAGCYL(Q1)	;GET PAGES PER CYL
DSKAA3:	TDNN 3,0(T1)		;PAGE FREE?
	JRST DSKAA1		;NO. RETURN BAD
	ANDCAM T3,0(T1)		;YES. ASSIGN IT
	SOS 0(T2)		;REDUCE FREE COUNT FOR TRACK
	SOS SDBFRC(T4)		;REDUCE FREE PAGE COUNT FOR STRUCTURE
	SOJLE Q1,DSKATX		;DONE IF Q1 <0
	ROT T3,-1		;SHIFT 1 BIT
	JUMPG T3,DSKAA3		;DO NEXT BIT
	AOJA T1,DSKAA3		;NEXT WORD

DSKATX:	EXCH Q1,ASGTYP		;RESTORE Q1
	MOVE T1,STRN01		;T1/STRUCTURE NUMBER
	CALL UMPBTB		;UNMAP INDEX BLOCK FROM BTBBAS, UNLOCK CORE PAGE,
				; UNLOCK BTBLCK, GO OKSKED
	MOVE T1,DSKADR		;RESTORE SECTOR NUMBER
	RETSKP			;TAKE SUCCESSFUL RETURN

;PAGE WAS ALREADY ASSIGNED

DSKAA1:	EXCH Q1,ASGTYP		;RESTORE Q1
	MOVE T1,STRN01		;T1/STRUCTURE NUMBER
	CALL UMPBTB		;UNMAP INDEX BLOCK FROM BTBBAS, UNLOCK CORE PAGE,
				; UNLOCK BTBLCK, GO OKSKED
	RETBAD (DSKX08)		;INDICATE PAGE ALREADY ASSIGNED

;ILLEGAL ADDRESS WAS SPECIFIED. GIVE BUGCHK AND TAKE FAILURE RETURN

DSKAA2:	MOVE T1,STRN01		;T1/STRUCTURE NUMBER
	HRRZ T3,STRTAB(T1)	;POINT TO THE SDB FOR THIS STRUCTURE
	LOAD T3,STRUC,(T3)	;GET ITS UNIQUE CODE
	MOVE T2,DSKADR		;GET REQUESTED ADDRESS
	BUG(ASGBAD,<<T3,D>,<T2,D>>)
	CALL UMPBTB		;UNMAP INDEX BLOCK FROM BTBBAS, UNLOCK CORE PAGE,
				; UNLOCK BTBLCK, GO OKSKED
	RETBAD(DSKX06)		;INDICATE INVALID DISK ADDRESS
;DEDSKC - DEASSIGN DISK ADDRESS

;ACCEPTS:
;	1/LINEAR DISK ADDRESS (SECTOR NUMBER)
;	2/ SPTH VALUE FOR THE OFN
;	3/STRUCTURE NUMBER

;	CALL DEDSKC

;RETURNS +1: ALWAYS

;THIS ROUTINE DEASSIGNS A DISK ADDRESS ONLY IF IT IS NOT BAD.  IT CHECKS
;THE BAT BLOCKS TO SEE IF THE PAGE IS BAD.

DEDSKC::STKVAR<STRNO>
	SE1CAL
	MOVEM T3,STRNO		;SAVE STRUCTURE NUMBER
	TXNE T2,OFNBAT		;DOES THIS OFN DESCRIBE A BAD PAGE?
	JRST [	CALL CHKBAD	;YES. GO SEE IF THIS PAGE IS BAD
		 RET		;PAGE IS MARKED IN BAT BLOCKS. DON'T DEASSIGN
		JRST .+1]

;THIS PAGE IS GOOD. RELEASE IT.  T1 CONTAINS THE SECTOR NUMBER

	MOVE T2,STRNO		;RESTORE STRUCTURE NUMBER
				; AND FALL INTO DEDSK


;DEDSK - DEASSIGN A SPECIFIC ADDRESS, IGNORING BAT BLOCKS

;ACCEPTS:
;	T1/SECTOR NUMBER RELATIVE TO START OF STRUCTURE
;	T2/STRUCTURE NUMBER

;	CALL DEDSK

;RETURNS +1:ALWAYS

;CALLED BY MONITOR ROUTINES (NOT DSKAS JSYS)
;BUGCHKS IF PAGE WAS NOT ASSIGNED

DEDSK::	ASUBR<DEDADR,DEDSTN>
	SE1CAL
	CALL DSKDEA		;DO IT
	 JRST [	CAIE T1,DSKX07	;FAILED. WAS PAGE NOT ASSIGNED?
		JRST .+1	;NO. SOMETHING ELSE. DON'T BUGCHK
		MOVE T1,DEDSTN	;YES. GET STRUCTURE NUMBER
		HRRZ T1,STRTAB(T1) ;POINT TO ITS SDB
		LOAD T1,STRUC,(T1) ;GET ITS UNIQUE CODE
		MOVE T2,DEDADR	;GET REQUESTED DISK ADDRESS
		BUG(DEAUNA,<<T1,D>,<T2,D>>)
		JRST .+1]
	RET			;RETURN +1 REGARDLESS OF RESULT
;DSKDEA - DEASSIGN A SPECIFID ADDRESS, IGNORING BAD BLOCKS

;ACCEPTS:
;	T1/ SECTOR NUMBER RELATIVE TO START OF STRUCTURE
;	T2/ STRUCTURE NUMBER (STRTAB INDEX)

;RETURNS +1: BAD ADDRESS OR IT WASN'T ASSIGNED OR BIT TABLE IS BAD
;		T1/ERROR CODE
;	 +2: SUCCESS

;CALLED FROM DSKAS JSYS AS WELL AS FROM ABOVE - BUGCHKS ONLY ON ILLEGAL ADDRESS

DSKDEA:	STKVAR<STRN02,DSKADR>
	MOVEM T1,DSKADR		;SAVE SECTOR NUMBER
	MOVEM T2,STRN02		;SAVE STRUCTURE NUMBER
	MOVE T3,STRTAB(T2)	;POINT TO START OF SDB FOR THIS STRUCTURE
	MOVX T4,MI%ASG		;IF DEASSIGNMENTS ARE PROHIBITED BECAUSE BIT
	TDNE T4,SDBSTS(T3)	; TABLE IS BAD OR DOESN'T EXIST,
	RETBAD(DSKX05)		;TAKE THE FAILURE RETURN
	MOVE T1,T2		;T1/STRUCTURE NUMBER
	CALL MAPBTB		;MAP INDEX BLOCK INTO BTBBAS, LOCK INTO CORE,
				; LOCK BTBLCK, GO NOSKED
	MOVE T1,DSKADR		;RESTORE SECTOR NUMBER
	MOVE T2,STRN02		;RESTORE STRUCTURE NUMBER
	CALL DSKGX		;COMPUTE LOCATION IN BIT TABLE
				; T1/OFFSET IN BIT PART OF BITTABLE, T2/TRACK
				; NUMBER, T3/WORD CONTAINING BIT FOR THIS PAGE	
	 JRST DSKDE2		;BAD ADDRESS
	MOVE T4,STRN01		;GET STRUCTURE NUMBER
	MOVE T4,STRTAB(T4)	;POINT TO START OF SDB FOR THIS STRUCTURE
	ADD T1,SDBBT0(T4)	;OFFSET IN BIT TABLE FOR BIT WORD
	ADD T1,BTBORA		;ADDRESS OF BIT WORD
	TDNE 3,0(T1)		;PAGE ASSIGNED?
	 JRST DSKDE1		;NO, RETURN BAD
	IORM 3,0(T1)		;YES. UNASSIGN IT
	ADD T2,BTBORA		;POINT TO WORD IN BIT TABLE FOR THIS TRACK
	AOS 0(T2)		;INCREMENT COUNT OF FREE PAGES FOR THIS TRACK
	AOS T1,SDBFRC(T4)	;INCREMENT FREE COUNT FOR THIS STRUCTURE
	MOVE T2,SDBOMF(T4)	;GET ORIGINAL MINIMUM FREE PAGE VALUE
	CAMLE T1,SDBMXF(T4)	;HAS THE FREE COUNT GONE ABOVE MINIMUM
	MOVEM T2,SDBMFP(T4)	;YES, SET THE MINIMUM VALUE UP AGAIN
	MOVE T1,STRN02		;T1/STRUCTURE NUMBER
	CALL UMPBTB		;UNMAP INDEX BLOCK FROM BTBBAS, UNLOCK CORE PAGE,
				; UNLOCK BTBLCK, GO OKSKED
	RETSKP			;TAKE SUCCESSFUL RETURN

;PAGE WAS NOT ASSIGNED

DSKDE1:	MOVE T1,STRN02		;T1/STRUCTURE NUMBER
	CALL UMPBTB		;UNMAP INDEX BLOCK FROM BTBBAS, UNLOCK CORE PAGE,
				; UNLOCK BTBLCK, GO OKSKED
	RETBAD(DSKX07)		;INDICATE PAGE NOT ASSIGNED

;ILLEGAL ADDRESS WAS SPECIFIED. GIVE BUGCHK AND TAKE FAILURE RETURN

DSKDE2:	MOVE T1,STRN02		;T1/STRUCTURE NUMBER
	HRRZ T3,STRTAB(T1)	;POINT TO ITS SDB
	LOAD T3,STRUC,(T3)	;GET ITS UNIQUE CODE
	MOVE T2,DSKADR		;GET THE REQUESTED ADDRESS
	BUG(DEABAD,<<T3,D>,<T2,D>>)
	CALL UMPBTB		;UNMAP THE BIT TABLE
	RETBAD(DSKX06)		;INDICATE INVALID DISK ADDRESS
;CHKBAD - ROUTINE TO SEE IF DISK ADDRESS IS MARKED IN BAT BLOCKS

;ACCEPTS:
;	T1/SECTOR NUMBER RELATIVE TO START OF STRUCTURE
;	T3/STRUCTURE NUMBER

;CALL CHKBAD

;RETURNS +1: ADDRESS IS MARKED IN BAT BLOCKS
;	 +2: ADDRESS IS NOT MARKED IN BAT BLOCKS
;		T1/SECTOR NUMBER

;USES FPG3A AS A WORK PAGE. LOCKS AND READS THE BAT BLOCK FOR THE
;APPROPRIATE DRIVE, AND LOOKS FOR THE GIVEN ADDRESS IN THE BAT BLOCKS

CHKBAD:SAVEP
	MOVE P1,A		;SAVE ADDRESS
	MOVE P5,C		;MOVE STRUCTURE NUMBER TO PERMANENT PLACE
	TXZ A,DSKAB		;TURN OFF TYPE BIT
	HRRZ B,STRTAB(P5)	;GET SDB FOR THIS STRUCTURE
	IDIV A,SDBSIZ(B)	;COMPUTE UNIT AND ADDRESS
	MOVE P2,A		;SAVE LOGICAL UNIT
	MOVE P3,B		;SAVE LOCAL ADDRESS
	HRRZ P4,STRTAB(P5)	;GET POINTER TO PS
	MOVEI P4,SDBUDB(P4)	;GET FIRST SDBUDB INDEX
	ADDI P4,0(A)		;POINTER TO THIS SDBUDB
	HRRZ A,0(P4)		;GET UDB INDEX
	CALL LKBAT		;LOCK THIS BAT BLOCK
	 JRST [	MOVE A,P1	;NO. MUST BE GOOD THEN
		RETSKP]		;SO GO DELETE IT
	NOINT			;PREVENT LOCAL INTERRUPTS
	MOVEI A,FPG3A		;GET A PAGE
	CALL MLKMA		;LOCK IT DOWN
	MOVE P2,A		;SAVE CORE PAGE NUMBER
	LSH A,PGSFT		;MAKE IT A CORE ADDRESS
	PUSH P,A		;SAVE VIRTUAL ADDRESS
	CALL FNDCHN		;GET CHANNEL,,UNIT (ARGUMENT IN P4)
	POP P,B			;PHYSICAL PAGE
	MOVEI C,FPG3A		;VIRTUAL ADDRESS
	CALL GETBAT		;GET THE BAT BLOCKS
	HRRZ C,0(P4)		;UDB POINTER
	MOVEI B,FPG3A		;VIRTUAL PAGE
	CALL VERBAT		;MAKE SURE THEY ARE GOOD
	 JRST ISGOOD		;NONE THERE. ASSUME PAGE IS GOOD
	MOVE A,P3		;ADDRESS
	MOVEI B,FPG3A		;BAT BLOCK
	MOVE C,P5		;GET THE STRUCTURE NUMBER
	HRRZ C,STRTAB(P5)	;GET POINTER TO STRUCTURE TABLE
	MOVE C,SDBUDB(C)	;GET A UDB POINTER
	CALL SEEADR		;SEE IF IN THERE
	 JRST ISGOOD
	MOVE A,P2		;CORE ADDRESS
	CALL MULKCR		;RELEASE IT
	OKINT			;ALLOW INTS AGAIN
	HRRZ A,0(P4)		;UDB INDEX
	CALL ULKBAT		;FREE THE BAT BLOCK
	RETBAD			;LEAVE PAGE ASSIGNED
ISGOOD:	MOVE A,P2		;CORE PAGE
	CALL MULKCR		;FREE IT
	OKINT			;ALLOW INTS AGAIN
	HRRZ A,0(P4)		;UDB INDEX
	CALL ULKBAT		;FREE THE BAT BLOCK
	MOVE A,P1
	RETSKP			;GO RELEASE THEPAGE
;SPECIAL ROUTINE CALLED FROM PAGEM TO READ IN BAT BLOCKS FOR
;A GIVEN UNIT. ACCEPTS:
;	1/ UNIT
;	2/ CORE ADDRESS
;	3/ MEMORY ADDRESS
;	4/ STRUCTURE NUMBER
;RETURNS:
;	+1/ NO BAT BLOCKS
;	+2/ BAT BLOCKS READ IN BUT NOT LOCKED

RDBAT::	STKVAR <SAVUNT,SAVCOR,SAVMEM,SAVUDB>
	SE1CAL
	MOVEM A,SAVUNT
	MOVEM B,SAVCOR
	MOVEM C,SAVMEM
	HRRZ A,STRTAB(D)	;PS
	HRRI A,SDBUDB(A)	;THE UDB
	ADD A,SAVUNT		;ADD IN UNIT
	HRRZ A,0(A)		;GET UDB ADDRESS
	MOVEM A,SAVUDB		;SAVE IT
	CALL LKBAT		;LOCK IT
	 RET			;FAILED
	MOVE C,SAVUDB		;GET UDB
	CALL FNDCH1		;GET CHANNEL,,UNIT
	MOVE B,SAVCOR
	MOVE C,SAVMEM		;ARGS
	CALL GETBAT		;GET BAT BLOCKS
	MOVE C,SAVUDB		;GET UDB
	MOVE B,SAVMEM		;THE MEMORY ADDRESS
	CALL VERBAT		;VERIFY EM
	 SKIPA
	AOS (P)
	MOVE A,SAVUDB		;GET UDB
	CALL ULKBAT		;FREE BAT LOCKS
	RET			;DONE
;ROUTINE TO SEE IF LOCAL DISK ADDRESS IN A IS CONTAINED IN
;BAT BLOCK POINTED TO BY B
;ACCEPTS: 1/LOCAL DISK ADDRESS
;	  2/BAT BLOCK VIRTUAL ADDRESS
;	   3/UDB ADDRESS OF ONE DISK ON THIS STRUCTURE
;RETURNS:
;	+1/ NOT IN BLOCK
;	 +2/ IN BLOCK , B= WORD ADDRESS OF PAIR A= REAL DISK ADDRESS
;	  (DISK ADDRESS UPDATED TO INCLUDE  LOST SECTORS PER CYLINDER

;**;[1972] Change 1 line at SEEADR:+0L	PED	6-JAN-82
SEEADR::SAVEPQ			;[1939]
	SE1CAL
	MOVE P2,B		;SAVE CORE ADDRESS
	HRRZ P3,C		;GET UDB ADDRESS FOR LOAD
	LDB P3,USYTYP		;GET DEVIP3E TYEP
	MOVEI C,DSKSZ0		;ASSUME RP04 DISK SIZE
	CAIN P3,.UTRP7		;RP07?
	MOVEI C,DSKSZ2		;YES SET UP SIZE POINTERS
	CAIN P3,.UTRM3		;RM03?
	MOVEI C,DSKSZ3		;SET UP RM03 SIZE
	CAIN P3,.UTRP6		;CHECK FOR RP06 SIZE
	MOVEI C,DSKSZ1		;RP06 SIZE
;**;[1939] Change 1 line at SEEADR:+12.L	PED	8-SEP-81
	MOVE P4,C		;[1939] POINT TO SIZE DATA
	PUSH P,A		;SAVE DISK ADDRESS
;**;[1939] Delete 3 lines at SEEADR+15.L	PED	8-SEP-81
	MOVE P1,A		;SET CORRECT DISK SIZE
	MOVEI A,0(P2)		;POINTER TO BAT BLOCK
	CALL BATSPC		;GET SPACE REMAINING
	CAIN A,-MAXBFR		;ANY THERE?
	JRST [	POP P,A		;NO. NOT IN BLOCK THEN
		RET]
	ADDI A,MAXBFR		;DO SUBTRACT
	MOVNI A,0(A)		;GET NEGATIVE OF DIFFERENCE
	ASH A,-1		;DIVIDE BY TWO
	HRLI B,0(A)		;GET NEG NUMBER OF PAIRS
	HRRI B,BAT1P(P2)	;FIRST BAD PAIR
DOABAD:	LOAD C,BADT,(B)		;GET TYPE OF THIS BAD PAIR
	SKIPE C			;OLD OR NEW
	JRST [	LOAD C,ADD27,(B) ;NEW GET LONG ADDRESS
		JRST DOABA1]
	LOAD C,ADD18,(B)	;OLD, GET SHORT ADDRESS
DOABA1:	LOAD D,BATNB,(B)	;GET NUMBER IN THIS REGION
;**;[1939] Add 8. lines at DOABA1:+1L	PED	8-SEP-81
	PUSH P,D		;[1939] SAVE NUMBER OF BLOCKS
	MOVEM C,D		;[1939] STORE ADDRESS
	MOVE A,SECCYL(P4)	;[1939] GET NUMBER OF USED SECTORS
	ADD A,LPPCYL(P4)	;[1939] PLUS NUMBER OF UNUSED
	IDIV D,A		;[1939] GET NUMBER OF CYLINDERS
	IMUL D,LPPCYL(P4)	;[1939] FIND NUMBER OF UNUSED SECTORS
	SUB C,D			;[1939] CONVERT TO LOGICAL ADDRESS
	POP P,D			;[1939] GET BACK NUMBER OF BLOCKS
	ADD D,C			;GET LAST ONE
	TRZ C,3			;TRUNCATE TO PAGE BOUNDARY.  **  NOTE:
				;THIS ASSUMES FOUR SECTORS PER PAGE **
	CAML P1,C		;WITHIN THE RANGE?
	CAMLE P1,D		;" ?
	SKIPA			;NO
	JRST [	POP P,T1
		RETSKP]
	AOS B			;TWO WORDS PER PAIR
	AOBJN B,DOABAD	;DO ALL REGIONS
	CALLRET PA1		;NOT THERE

;ROUTINE TO CALCULATE SPACE LEFT IN BAT BLOCK. ACCEPTS:
;	A/ ADDRESS OF BAT BLOCK
;RETURNS:	+1 WITH A/SPACE LEFT

	RESCD(INIT)			;MUST BE RESIDENT
BATSPC:	LOAD B,BTHCT,(A)	;GET ENTRIES USED BY MAPPER
	LOAD C,BTMCT,(A)	;PAIRS ADDED BY MONITOR
	ADDI B,0(C)		;TOTAL PAIRS USED
	LSH B,1			;2 WORDS PER PAIR
	MOVEI A,-MAXBFR(B)	;GET NEG OF SPACE
	TRNN A,1B18		;OVERFLOW?
	SETZ A,			;YES. SAY NO ROOM LEFT
	RET			;AND DONE
;THESE ROUTINES LOCK AND UNLOCK BAT BLOCKS.
;ACCEPTS: 1/UDB POINTER
;RETURNS: +1/ UNIT HAS NO BAT BLOCKS
;	   +2/BAT BLOCKS LOCKED

	SWAPCD			;IS SWAPPABLE
LKBAT::	MOVX B,US.BAT		;FIRST SEE IF IT HAS BAT BLOCKS
	SE1CAL
	TDNE B,UDBSTS(A)	;DOES IT?
	RET			;NO
	MOVX B,US.BLK		;GET THE BIT
	NOSKED			;PROTECT IT
	TDNE B,UDBSTS(A)	;IS IT ALREADY LOCKED?
	JRST CANT		;YES. ARRANGE FOR A BLOCK
	IORM B,UDBSTS(A)	;NO. LOCK IT THEN
;**;[3092]  Replace 2 lines with 1 at LKBAT:+9		DML	17-APR-84
;[3092]	OKSKED
	RETSKP			;[3092] RETURN WITH IT LOCKED AND NOSKED
CANT:	HRLI A,0(A)		;UNIT NUMBER TO LH
	HRRI A,BATTST		;TEST ADDRESS
	RDISMS			;AND GO INTO SCHEDULER WAIT
	RETSKP

;[3092] SCHEDULER TEST FOR BAT BLOCK AVAILABLE

	RESCD

BATTST:	MOVX B,US.BLK		;THE BIT
	TDNE B,UDBSTS(A)	;FREE NOW?
	JRST 0(4)		;NO. BLOCK AGAIN
;**;[3092]  Add 1 line after BATTST:+2			DML	17-APR-84
	NOSKED			;[3092] BE NOSKED WHILE WE HAVE LOCK
	IORM B,UDBSTS(A)	;YES. LOCK IT
	JRST 1(4)		;AND WAKE UP
	SWAPCD

;ROUTINE TO UNLOCK A BAT BLOCK
;ACCEPTS 1/UDB POINTER

ULKBAT::MOVX B,US.BLK		;THE BIT
	SE1CAL
	ANDCAM B,UDBSTS(A)	;CLEAR LOCK
;**;[3092]  Add 1 line after ULKBAT:+2			DML	17-APR-84
	OKSKED			;[3092] BECOME OKSKED AGAIN AFTER LOCK RELEASE
	RET			;AND RETURN
;COMPUTE INDEX INTO BIT TABLE

;ACCEPTS:
;	T1/SECTOR NUMBER RELATIVE TO START OF STRUCTURE
;	T2/STRUCTURE NUMBER

;RETURNS +1: INVALID ADDRESS
;	 +2: VALID ADDRESS
;		T1/OFFSET IN BIT PART OF BIT TABLE FOR DESIRED TRACK
;		T2/TRACK NUMBER
;		T3/WORD WITH BIT CORRESPONDING TO THIS PAGE SET

;CALLED AFTER A CALL TO MAPBTB, WHICH MAPS THE BIT TABLE FOR THIS STRUCTURE
;AND GOES NOSKED

	SWAPCD

DSKGX:	MOVE T3,STRTAB(T2)	;POINT TO SDB FOR THIS STRUCTURE
	MOVE T4,SDBTYP(T3)	;POINT TO DSKSIZ TABLE FOR THIS DISK TYPE
	TLZ T1,DSKMSK		;FLUSH RANDOM BITS
	IDIV T1,SECCYL(T4)	;1/CYLINDER, 2/SECTOR WITHIN CYLINDER
	CAML T1,SDBCYL(T3)	;WITHIN KNOWN CYLINDERS FOR THIS STRUCTURE?
	RET			;NO.
	CAML T1,SDBBT0(T3)	;WITHIN TOP HALF OF BIT TABLE?
	RET			;NO, RETURN NO-SKIP
	CAIGE T1,LOTRK		;NON-NEGATIVE CYLINDER NUMBER?
	RET			;NO
	MOVE T3,PAGCYL(T4)	;GET PAGES PER CYLINDER
	IMUL T3,SECPAG(T4)	;COMPUTE NUMBER SECTORS IN COMPLETE PAGES
	CAML T2,T3		;IS THIS SECTOR WITHIN A FULL PAGE (POSSIBLE
				; EXTRA SECTORS AT END OF CYLINDER)?
	RET			;NO
	PUSH P,T1		;SAVE TRACK NUMBER
	IMUL T1,BTWCYL(T4)	;INDEX TO FIRST WORD OF BITS
	IDIV T2,SECPAG(T4)	;CONVERT SECTOR TO PAGE WITHIN CYLINDER
	IDIVI T2,^D36		;GET INDEX TO BIT WORD WITHIN CYLINDER
	ADDI T1,0(T2)		;T1/OFFSET OF BIT WORD FOR THIS PAGE
	POP P,T2		;T2/CYLINDER NUMBER
	MOVE T3,BITS(T3)	;T3/BIT FOR THIS PAGE
	RETSKP
;CREATE THE BIT TABLE

;ACCEPTS:
;	T1/STRUCTURE NUMBER

;RETURNS +1: FAILURE (FATAL ERROR FROM CRTBTB)
;	 +2: SUCCESS

;CALLED WHEN A STRUCTURE IS BEING CREATED OR ITS BIT TABLE
;IS BEING RECREATED.  INITIALIZES THE BIT TABLE
;IN CORE, LEAVING THE SDB POINTING TO THE IN-CORE PAGE TABLE
;ASSIGNS SPACE FOR HOME BLOCKS AND SWAPPING SPACE
;EXITS OKSKED WITH BIT TABLE UNLOCKED AND SPT(BTBBAS) CLEARED.

CRTBTB::STKVAR<STRN03,BTBMAP,CRTBER>
	SE1CAL
	MOVEM T1,STRN03		;SAVE STRUCTURE NUMBER
	NOSKED			;NOSKED WHILE INITING THE BIT TABLE
	CALL ASSPTL		;ASSIGN SPT SLOT; INIT TO USHR AND UAAB; PUT
				; FORK INDEX IN SPTH; RETURN OFFSET IN AC1
	MOVEM T1,BTBMAP		;SAVE SPT SLOT FOR TEMPORARY PAGE TABLE
	MOVE T2,STRN03		;GET STRUCTURE NUMBER
	MOVE T2,STRTAB(T2)	;POINT TO START OF SDB FOR THIS STRUCTURE
	MOVEM T1,SDBBTB(T2)	;SAVE SPT INDEX FOR PAGE TABLE IN SDB
	HLL T1,SHRPTR		;MAKE SHARE POINTER
	MOVEM T1,MSECTB+BTSEC	;SET IN SECTION POINTER
	CALL MONCLR		;CLEAR PAGER
	MOVE T1,BTBMAP		;FIND SPT
	CALL SWPIN1		;GET A CORE PAGE, MAKE SPT POINTED TO BY T1 POINT
				; TO THE PAGE, LOCK IT IN CORE
	MOVE T1,BTBMAP		;T1/SPT INDEX FOR PAGE TABLE FOR BIT TABLE
	CALL LCKBTB		;LOCK THE LOCK AND MAKE BTBBAS POINT TO PAGE TABLE
	SETZM CRTBER		;INDICATE NO ERRORS INITIALLY
	MOVE T1,STRN03		;T1/STRUCTURE NUMBER
	CALL INIBTB		;SET INITIAL VALUES IN BIT TABLE
	 SETOM CRTBER		;INDICATE ERROR
	MOVE T1,STRN03		;T1/STRUCTURE NUMBER
	CALL UMPBTB		;UNMAP INDEX BLOCK FROM BTBBAS, UNLOCK CORE PAGE,
				; UNLOCK BTBLCK, GO OKSKED
	SKIPE CRTBER		;DID WE ENCOUNTER ANY ERRORS?
	RETBAD			;YES. TAKE FAILURE RETURN
	RETSKP			;NO. TAKE SUCCESS RETURN
;INITIALIZE BIT TABLE

;ACCEPTS:
;	T1/STRUCTURE NUMBER

;RETURNS +1: FATAL ERROR (FAILED TO ASSIGN HOME BLOCK OR SWAPPING SPACE)
;	 +2: SUCCESS

;THIS ROUTINE INITIALIZES THE BIT TABLE THAT IS CURRENTLY POINTED TO
;BY THE STRUCTURE'S SDB. NORMALLY IT IS CALLED BY CRTBTB, WHICH HAS
;OBTAINED A PAGE IN CORE TO SERVE AS A PAGE TABLE TO AN ADDRESS SPACE.
;IT CAUSES ALL PAGES TO BE AVAILABLE AND THEN ASSIGNS THOSE PAGES THAT
;BELONG TO THE HOME BLOCKS AND SWAPPING SPACE.  IT ALSO ASSIGNS PAGES THAT
;ARE POINTED TO BY THE BAT BLOCKS.

;CALLED NOSKED WITH SPT(BTBBAS) SET UP AND BTBLCK LOCKED

INIBTB::SAVEPQ
	SE1CAL
	STKVAR<STRN04,SVPAIR,SVADR1,SVADR2,STRTPT,LSTPAG,INIER1,INIER2>
	SETZM INIER1		;INDICATE NO FATAL ERRORS YET
	SETZM INIER2		;INDICATE NO BAT BLOCK FAILURES YET
	MOVEM T1,STRN04		;SAVE STRUCTURE NUMBER
	MOVE T4,STRTAB(T1)	;POINT TO START OF SDB FOR THIS STRUCTURE
	MOVE T1,SDBTYP(T4)	;POINT TO SIZE DATA FOR THIS DISK TYPE
	MOVEM T1,STRTPT		;SAVE POINTER

;INITIALIZE TOP HALF OF BIT TABLE (CONTAINS COUNT OF FREE PAGES PER CYLINDER).
;SET EACH WORD TO INDICATE ALL PAGES AVAILABLE.

	MOVE T1,PAGCYL(T1)	;GET NUMBER OF PAGES PER CYLINDER
	MOVN T2,SDBBT0(T4)	;GET SIZE OF TOP HALF OF BIT TABLE
	HRLZS T2		;T2/(-COUNT,,OFFSET IN TOP HALF)
INIBT2:	MOVEI T3,0(T2)		;GET OFFSET
	ADD T3,BTBORA		;ADDRESS OF CURRENT WORD
	MOVEM T1,0(T3)		;STORE FULL COUNT FOR EACH TRACK
	AOBJN T2,INIBT2		;GO TO NEXT WORD
;INITIALIZE BOTTOM OF BIT TABLE.  CONTAINS 1 BIT PER PAGE, WITH EACH NEW
;CYLINDER STARTING A NEW WORD.  CURRENTLY EACH CYLINDER HAS 3 WORDS WITH
;THE THIRD ONLY PARTIALLY USED.  THIS CODE INITIALIZES THE FIRST 3 TO
;INDICATE ALL PAGES FREE (THEIR CORRESPONDING BITS SET) AND BLTS TO THE
;REST OF THE TABLE

	MOVE T2,SDBBT0(T4)	;START AT BEGINNING OF BIT PART OF BIT TABLE
	ADD T2,BTBORA		;COMPUTE ADDRESS OF FIRST BIT WORD
INIBT1:	SETOM 0(T2)		;INIT ONE TRACK OF BITS
	SUBI 1,^D36		;REDUCE COUNT OF PAGES (1 BIT PER PAGE)
	CAILE 1,^D36		;LAST WORD?
	AOJA 2,INIBT1		;NO. GO INITIALIZE IT
	MOVN 1,BITS-1(1)	;LAST WORD PARTIALLY FULL. SET ONLY VALID BITS
	MOVEM T1,1(T2)		;STORE LAST WORD FOR FIRST TRACK
	MOVE T2,BTBORA		;CONSTRUCT STARTING LOCATIONS FOR BLT
	ADD T2,SDBBT0(T4)	;GET SIZE OF TOP HALF OF BIT TABLE
	MOVE T3,T2		;MAKE DESTINATION POINTER
	MOVE T1,STRTPT		;POINT TO SIZE DATA FOR THIS DISK TYPE
	ADD T3,BTWCYL(T1)	;2ND GROUP OF WORDS
	MOVN T1,BTWCYL(T1)	;FIND OFFSET INTO SECOND GROUP
	ADD T1,SDBBT1(T4)	;FIND LENGTH OF TRANSFER
	CALL XBLTA		;COPY GROUPS OF BIT WORDS TO REST OF TABLE
	SETOM BTBLCK		;CLEAR LOCK BECAUSE DSKASA WILL SET IT.
				; WE ARE STILL NOSKED
;ASSIGN SPACE FOR THE HOME BLOCKS

	MOVE Q1,STRN04		;GET STRUCTURE NUMBER
	MOVE Q1,STRTAB(Q1)	;POINT TO START OF SDB FOR STRUCTURE
	MOVE P2,SDBTYP(Q1)	;POINT TO SIZE DATA FOR THIS DISK TYPE
	MOVSI Q3,-NHOME		;Q3/(-COUNT,,OFFSET TO HOME TABLE)
	SETOM LSTPAG		;INITIALIZE LAST PAGE ASSIGNED

;LOOP OVER SPECIAL SECTORS IN HOME BLOCK TABLE

HOMAS1:	MOVE T1,HOME(Q3)	;GET SECTOR NUMBER WITHIN UNIT
	IDIV T1,SECPAG(P2)	;CONVERT TO PAGE
	CAMN T1,LSTPAG		;SAME AS LAST PAGE ASSIGNED?
	JRST HOMAS3		;YES. DON'T ASSIGN IT AGAIN

;ASSIGN THIS PAGE FOR ALL UNITS

	MOVEM T1,LSTPAG		;SAVE LAST PAGE ASSIGNED
	MOVN Q2,SDBNUM(Q1)	;NO. GET NUMBER OF UNITS IN STRUCTURE
	HRLZS Q2		;Q2/(-COUNT,,UNIT NUMBER)
HOMAS2:	MOVEI T1,0(Q2)		;GET UNIT NUMBER
	IMUL T1,SECUNT(P2)	;COMPUTE FIRST SECTOR IN THIS UNIT
	ADD T1,HOME(Q3)		;T1/SECTOR TO ASSIGN
	MOVE T2,STRN04		;T2/STRUCTURE NUMBER
	CALL DSKASA		;ASSIGN THE PAGE
	 SETOM INIER1		;INDICATE A FATAL ERROR
	AOBJN Q2,HOMAS2		;LOOP TO NEXT UNIT IN STRUCTURE
HOMAS3:	AOBJN Q3,HOMAS1		;LOOP TO NEXT SPECIAL SECTOR


;ASSIGN PAGES FOR SWAPPING.  SDB INDICATES HOW MANY PAGES
;IF NONE, SWPASN RETURNS NORMALLY

	MOVE T1,STRN04		;T1/ STRUCTURE NUMBER
	CALL SWPASN		;ALLOCATE PAGES FOR SWAPPING SPACE
	 SETOM INIER1		;INDICATE FATAL ERROR
	; ..
	; ..
; NOW READ IN ALL OF THE BAT BLOCKS AND MARK EACH RECORDED
;BAT BLOCK IN THE NEW BIT TABLE
;	SETZ P2,
	MOVEI A,FPG3A		; GET A PAGE TO WORK WITH
	CALL MLKMA		;LOCK IT
	LSH A,PGSFT		;MAKE IT A CORE ADDRESS
	MOVE P1,A		;SAVE IT
	MOVE A,STRN04		;GET STRUCTURE NUMBER
	HRRZ A,STRTAB(A)	;GET SDB FOR THIS STRUCTURE
	MOVN P4,SDBNUM(A)	;NUMBER OF PACKS
	MOVSI P4,0(P4)		;TO THE LEFT HALF
	HRRI P4,SDBUDB(A)	;FIRST UDB POINTER
PACKS:	HRRZ A,0(P4)		;GET UDB POINTER
	CALL LKBAT		;LOCK UP THE BAT BLOCKS
	 JRST CYCLE		;NONE THERE
	CALL FNDCHN		;GET CHANNEL,,UNIT
	MOVE P2,T1		;SAVE IT
	MOVE B,P1		;PAGE ADDRESS
	MOVEI C,FPG3A		;THE VIRTUAL ADDRESS
	CALL GETBAT		;GET AND VERIFY BAT BLOCKS
	MOVEI B,FPG3A		; CORE ADDRESS
	HRRZ C,0(P4)		;UDB ADDRESS
	CALL VERBAT		; GO VERIFY THE BATS
	 JRST [	HRRZ A,0(P4)	;UDB ADDRESS
		CALL ULKBAT	;FREE THE BAT BLOCK
		JRST CYCLE]	;AND DONE
	MOVEI A,FPG3A		;BAT BLOCK ADDRESS
	CALL BATSPC		;GET SPACE USED
	MOVEI P3,MAXBFR(A)	;SPACE USED
	JUMPE P3,CYCLE0		; NONE HERE IF A ZERO
	LSH P3,-1		;CALCULATE NUMBER OF PAIRS
	MOVEI C,BAT1P+FPG3A	;FIRST BAD BLOCK PAIR
DOBAD:	LOAD A,BADT,(C)		; GET TYPE OF THIS BLOCK
	SKIPN A
	JRST [	LOAD A,ADD18,(C) ;GET 18 BIT ADDRESS
		JRST GOTADR]	;AND GO IN LINE
	LOAD A,ADD27,(C)	;GET 27 BIT ADDRESS
GOTADR:	LOAD B,BATNB,(C)	;GET NUMBER OF BAD ONES
	ADD B,A			;
	MOVEM C,SVPAIR		;SAVE BAD PAIR INDEX
	MOVE D,STRN04		;GET STRUCTURE NUMBER
	HRRZ D,STRTAB(D)	;POINT TO START OF SDB FOR THIS STRUCTURE
	MOVEI C,0(P4)		;THIS ONE
	SUBI C,SDBUDB(D)
	IMUL C,SDBSIZ(D)
	ADD A,C			; MAKE THIS LINEAR
	ADD B,C			; AND THIS TOO
	MOVEM B,SVADR1		;SAVE LAST ADDRESS
TOPASG:	MOVEM A,SVADR2		; SAVE ADDRESS
	TRZ A,3
	SUB A,SDBFSS(D)		; SUB XDR OF START OF SWAPPING SECTRS
	SKIPL A			; IF <0 THEN XDR IS NOT IN SWAPPING AREA
	CAML A,SDBNSS(D)	; IF 0 <= A < # SWPPNG SCTRS ==> IN SWPING AREA
	JRST [	MOVE A,SVADR2	; NOT IN SWPNG AREA, GET BAD SECTOR ADDRESS
;**;[1939] Add 7 lines at TOPASG:+6L	PED	8-SEP-81
		MOVE D,STRTPT	;[1939] GET SIZE DATA FOR THIS TYPE
		MOVE B,SECCYL(D) ;[1939] GET # OF USED SECTORS PER CYL
		ADD B,LPPCYL(D) ;[1939] PLUS NUMBER OF UNUSED
		IDIV A,B	;[1939] FIND NUMBER OF PHYSICAL CYLINDERS
		IMUL A,LPPCYL(D) ;[1939] NUMBER OF UNUSED SECTORS
		MOVE D,SVADR2	;[1939] GET ORIGINAL (PHYSICAL) ADDRESS
		SUBM D,A	;[1939] CONVERT TO A LOGICAL ADDRESS
		MOVE B,STRN04	;2/STRUCTURE NUMBER
		CALL DSKASA	; ASSIGN IT
		 AOS INIER2	;COUNT NUMBER OF FAILURES FOR BAD PAGES
;**;[1772] Change 3 [1732] lines at TOPASG: +9L	JGZ	28-AUG-80
;**;[1732] Add 2 lines at TOPASG: +9L	   RAS   7-JUN-80
		MOVE D,STRN04	;[1732] Get back structure number
		HRRZ D,STRTAB(D) ;[1732] Get SDB ADR for structure
		JRST .+1]
	MOVE A,SVADR2		; GET BACK BAD SECTOR ADDRESS
	MOVE B,STRTPT		;POINT TO SIZE DATA FOR THIS DISK TYPE
	ADD A,SECPAG(B)		; MOVE TO NEXT PAGE
	CAMG A,SVADR1		; OVER THE END?
	JRST TOPASG		; NO
	MOVE C,SVPAIR		; RESTORE BAD PAIR INDEX
	ADDI C,2		; TO NEXT PAIR
	SOJG P3,DOBAD
CYCLE0:	HRRZ A,0(P4)		;UDB ADDRESS
	CALL ULKBAT		;FREE THE BAT BLOCK
CYCLE:	AOBJN P4,PACKS		;DO ALL PACKS
	MOVE A,P1		; GET CORE ADDRESS
	LSH A,-PGSFT		;MAKE IT A PAGE NUMBER
	CALL MULKCR		;UNLOCK IT
	MOVE A,STRN04
	CALL DSKSP		;GET NEW FREE COUNT
	MOVE 1,STRN04		;GET STRUCTURE NUMBER
	MOVE 1,STRTAB(1)	;POINT TO START OF SDB FOR THIS STRUCTURE
	MOVEM 2,SDBFRC(1)	;UPDATE COUNT OF FREE PAGES FOR STRUCTURE
	SKIPE INIER1		;WERE THERE ANY FATAL ERRORS?
	RETBAD(MSTX28)		;YES. RETURN 'FAILED TO INIT BIT TABLE'
	SKIPE T2,INIER2		;NO. WERE ANY BAD PAGES NOT ASSIGNED?
	 JRST [	MOVE T1,STRN04	;YES. GET THE STRUCTURE NUMBER
		MOVE T1,STRTAB(T1) ;POINT TO START OF SDB FOR THIS STRUCTURE
		LOAD T1,STRUC,(T1) ;GET UNIQUE CODE FOR THIS STRUCTURE
		 BUG(ASGBPG,<<T1,D>,<T2,D>>)
		JRST .+1]
	RETSKP			; AND DONE
;WRTBTB - WRITE THE BIT TABLE

;ACCEPTS:
;	T1/STRUCTURE NUMBER

;RETURNS +1: FAILED
;	 +2: SUCCEEDED

;WHEN THIS IS CALLED, SDBBTB POINTS TO TEMPORARY PAGE TABLE, WHICH
;CONTAINS POINTERS TO THE IN-CORE COPY OF THE BIT TABLE.  THIS ROUTINE
;MAPS THE BIT TABLE INTO A FILE, WHICH IT CREATES, AND DESTROYS THE
;IN-CORE COPY.  IT MAKES SDBBTB CONTAIN THE OFN FOR THE NEW FILE

WRTBTB::SAVEQ
	SE1CAL
	STKVAR<STRN05,BTJFN3,BTBFIL,BTBPT>
	MOVEM T1,STRN05		;SAVE THE STRUCTURE NUMBER

;CONSTRUCT A FILE SPEC FOR THE NEW BIT TABLE FILE CONTAINING THE STRUCTURE
;NAME AND GET A JFN

	MOVX T2,GJ%FOU!GJ%PHY!GJ%SHT ;NEXT GENERATION,PHYSICAL,SHORT
	CALL GETBTB		;BUILD THE FILE SPEC AND GET A JFN
	 RETBAD			;FAILED
	MOVEM T1,BTJFN3		;SAVE THE JFN

;OPEN THE FILE AND SET THE NO-DUMP BIT IN THE FDB FOR DUMPER WON'T DUMP FILE

	MOVX T2,OF%RD!OF%WR!OF%THW ;T2/READ, WRITE, THAWED ACCESS
	OPENF			;OPEN THE BIT TABLE FILE
	 JRST WRTBT2		;FAILED
;**;[1925] Change 1826 lines at WRTBTB: +10L	JGZ	19-AUG-81
;**;[1826] Add 4 lines at WRTBTB:+10L	PED	19-JAN-81
	MOVEI T2,.AREXM		;[1826] BIT TO SET
	MOVEI T3,.ARSET		;[1826] SET IT
	ARCF			;[1826] WITH AN ARCF
	 ERJMP WRTBT5		;[1826] HANDLE FAILURES
	MOVEI T2,.FBCTL		;OFFSET OF FLAG WORD IN FDB
	MOVE T1,BTJFN3		;T1/JFN IN RH
	STOR T2,CF%DSP,T1	;T1/OFFSET IN FDB IN LH
	MOVX T2,FB%NOD		;T2/MASK OF BITS TO BE AFFECTED
	MOVX T3,FB%NOD		;T3/NEW VALUE - SET NO DUMP
	CHFDB			;CHANGE THE FDB TO REFLECT NO DUMP
	 ERJMP WRTBT5		;FAILED - GO CLOSE THE FILE

;GET SOME INFORMATION ABOUT THE FILE

	MOVE T1,BTJFN3		;T1/JFN
	MOVE T2,[3,,.FBCTL]	;T2/(COUNT,,FIRST WORD)
	MOVEI T3,Q1		;T3/DESTINATION
	GTFDB			;GET SOME INFO ON THE FILE
	 ERJMP WRTBT5		;FAILED. GO CLOSE THE FILE
	TXNE Q1,FB%LNG		;IS IT A LONG FILE?
	BUG(WRTLNG)
	MOVE T1,Q3		;T1/ADDRESS OF INDEX BLOCK
	TXO T1,THAWB+FILWB	;OPEN THAWED WITH WRITE ACCESS
	;..
;GET AN OFN FOR THE FILE TO UPDATE THE SHARE COUNT SO THAT CLOSING
;IT WON'T GET RID OF THE OFN

	;..

	MOVE T2,STRN05		;T2/STRUCTURE NUMBER
	CALL ASROFN		;ASSIGN OFN
	 JRST WRTBT3		;FAILED. THIS SHOULD NOT HAPPEN IF OPENF SUCCEEDED
	MOVEM T1,BTBFIL		;SAVE THE OFN FOR THE FILE	
	MOVE T1,BTJFN3		;T1/JFN
	CLOSF			;CLOSE THE FILE TO GET RID OF THE JFN (OFN REMAINS)
	 JFCL

;GET THE SPT INDEX FOR THE TEMPORARY PAGE TABLE

	MOVE T1,STRN05		;GET STRUCTURE NUMBER
	MOVE T1,STRTAB(T1)	;POINT TO START OF SDB FOR THIS STRUCTURE
	MOVE T2,SDBBTB(T1)	;GET SPT INDEX FOR PAGE TABLE
	MOVEM T2,BTBPT		;SAVE IT

;COPY THE IN-CORE BIT TABLE TO THE NEW FILE

	MOVE Q2,SDBBT0(T1)	;GET SIZE OF TOP HALF OF BIT TABLE
	MOVEM Q2,Q3		;SAVE IT FOR LATER
	ADD Q2,SDBBT1(T1)	;ADD SIZE OF BOTTOM HALF
	ADDI Q2,<PGSIZ-1>	;ROUND TO END OF PAGE
	IDIVI Q2,PGSIZ		;CONVERT TO NUMBER OF PAGES
	MOVN Q1,Q2		;-NUMBER OF PAGES IN BIT TABLE FILE
	HRLZS Q1		;Q1/(-PAGE COUNT,,0)

;LOOP THROUGH ALL PAGES IN THE FILE,MAPPING THE CORE PAGE INTO THE FILE.
;MAP IT BACK BECAUSE THE IN-CORE COPY IS BEING USED WHEN SETPT CALLS DSKASN, 
;AND THE CORE-TO-FILE MAP DESTROYS THE CORE CONTENTS.

WRTBT1:	NOSKED
	HRLZ T1,BTBPT		;T1/(PTN,,PN)
	HRR T1,Q1
	HRLZ T2,BTBFIL		;T2/(OFN,,PN)
	HRR T2,Q1
	MOVX T3,PTRW		;T3/READ, WRITE ACCESS
	CALL SETPT		;MAP PAGE TO FILE
	EXCH T1,T2
	CALL SETPT		;MAP FILE TO PAGE
	OKSKED
	AOBJN Q1,WRTBT1		;AT END OF TABLE YET?
	;..
;ALL PAGES MAPPED. MAKE THE SDB POINT TO THE FILE AND GET RID OF THE
;IN-CORE PAGES, INCLUDING THE PAGE TABLE

	;..

	MOVE T1,BTBFIL		;YES. GET OFN FOR FILE
	MOVE T2,STRN05		;GET STRUCTURE NUMBER
	MOVE T2,STRTAB(T2)	;POINT TO START OF SDB FOR THIS STRUCTURE
	MOVEM T1,SDBBTB(T2)	;SAVE THE OFN IN THE SDB
	SETZM T1		;T1/ TO INDICATE CLEAR THE PAGE TABLE
	HRLZ T2,BTBPT		;T2/ (OFN,,PN)
	MOVE T4,Q2		;T4/NUMBER OF PAGES
	CALL MSETPT		;CLEAR THE TEMPORARY PAGE TABLE
	MOVE T1,BTBPT		;T1/SPT ENTRY FOR PAGE TABLE
	CALL DESPT		;RELEASE THE SPT SLOT
	MOVE T1,STRN05		;T1/STRUCTURE NUMBER
	CALL CPYBAK		;UPDATE BACKUP OF ROOT-DIRECTORY TO SHOW
				; THE NEW BIT TABLE FILE
	 JRST [	MOVE T1,STRN05	;GET STRUCTURE NUMBER
		MOVE T1,STRTAB(T1) ;POINT TO SDB FOR THIS STRUCTURE
		LOAD T1,STRUC,(T1) ;GET UNIQUE CODE
		BUG(WRTCPB,<<T1,D>>)
		JRST .+1]
	MOVE T1,STRN05		;T1/STRUCTURE NUMBER
	MOVEI T2,HOMBTB		;T2/OFFSET IN HOME BLOCK FOR WORD TO CHANGE
	MOVE T3,STRN05		;GET STRUCTURE NUMBER
	MOVE T3,STRTAB(T3)	;POINT TO SDB FOR THIS STRUCTURE
	MOVE T3,SDBBT0(T3)	;T3/SIZE OF TOP HALF OF BIT TABLE
	HRROI T4,-1		;CHANGE ENTIRE WORD
	CALL MODHOM		;REWRITE THE HOME BLOCK TO INDICATE THE
				; NEW SIZE OF THE BIT TABLE
	 RETBAD(MSTRX6)		;INDICATE HOME BLOCKS ARE BAD
	HRLZ T1,BTBFIL		;OFN,,0
	MOVEI T2,1000
	CALL UPDPGS		;UPDATE FILE PAGES
	MOVE T1,BTBFIL
	CALL UPDOFN		;UPDATE OFN ALSO
	RETSKP

;ERROR AFTER GTJFN BUT BEFORE OPENF.  RELEASE THE JFN

WRTBT2:	MOVEM T1,STRN05		;SAVE ERROR CODE IN TEMPORARY LOCATION
	MOVE T1,BTJFN3		;T1/JFN OF BIT TABLE FILE
	RLJFN			;RELEASE THE JFN
	 JFCL			;IGNORE FAILURE
	MOVE T1,STRN05		;RESTORE ERROR CODE
	RETBAD			;TAKE NON-SKIP RETURN


;ASOFN FAILED WHEN OPENF SUCCEEDED.  SOMETHING IS REALLY WRONG...

WRTBT3:	MOVE T2,STRN05		;GET STRUCTURE NUMBER
	HRRZ T2,STRTAB(T2)	;POINT TO ITS SDB
	LOAD T2,STRUC,(T2)	;GET ITS UNIQUE CODE
	BUG(WRTBT4,<<T2,D>>)

;ERROR OCCURRED AFTER OPENF AND BEFORE CLOSF.  CLOSE THE FILE

WRTBT5:	MOVEM T1,STRN05		;SAVE ERROR CODE IN TEMPORARY LOCATION
	MOVE T1,BTJFN3		;T1/JFN FOR BIT TABLE FILE
	CLOSF			;CLOSE THE FILE
	 JFCL			;IGNORE FAILURE
	MOVE T1,STRN05		;RESTORE ERROR CODE
	RETBAD			;TAKE NON-SKIP RETURN
;MNTBTB - MOUNT THE BIT TABLE

;ACCEPTS:
;	T1/STRUCTURE NUMBER

;RETURNS +1: FAILED TO FIND BIT TABLE
;	 +2: SUCCEEDED

;CALLED WHEN STRUCTURE IS BEING MOUNTED AND BY JOB 0 FOR ALL STRUCTURES MOUNTED AT
;SYSTEM STARTUP.  GETS AN OFN FOR THE BIT TABLE FILE AND STORES IT IN THE SDB

MNTBTB::SAVEQ
	SE1CAL
	STKVAR<STRN06,BTJFN2>
	MOVEM T1,STRN06		;SAVE STRUCTURE NUMBER
	MOVX T2,GJ%OLD!GJ%PHY!GJ%DEL!GJ%SHT ;T2/BITS FOR GTJFN
	CALL GETBTB		;GET JFN FOR BIT TABLE FILE
	 RETBAD			;FAILED
	MOVEM T1,BTJFN2		;SAVE THE JFN
	MOVE T2,[3,,.FBCTL]	;T2/(COUNT,,FIRST WORD)
	MOVEI T3,Q1		;T3/DESTINATION
	GTFDB			;GET SOME INFO ON THE FILE
	 ERJMP MNTBT1		;FAILED. RELEASE THE JFN
	TXNE Q1,FB%LNG		;IS IT A LONG FILE?
	BUG(MNTLNG)
	MOVE T1,Q3		;T1/ADDRESS OF INDEX BLOCK
	TXO T1,THAWB+FILWB	;THAWED SO IT IS UPDATED INSTANTLY
	MOVE T2,STRN06		;T2/STRUCTURE NUMBER
	CALL ASROFN		;GET AN OFN FOR THE FILE
	 JRST MNTBT1		;FAILED. GO RELEASE THE JFN
	MOVE T2,STRN06		;GET STRUCTURE NUMBER
	MOVE T2,STRTAB(T2)	;POINT TO START OF SDB FOR THIS STRUCTURE
	MOVEM T1,SDBBTB(T2)	;SAVE OFN FOR THIS STRUCTURE
	MOVE T1,BTJFN2		;T1/JFN FOR BIT TABLE
	RLJFN			;RELEASE THE JFN
	 JFCL			;IGNORE FAILURE
	RETSKP

;ERROR AFTER GTJFN.  RELEASE THE JFN

MNTBT1:	MOVEM T1,STRN06		;SAVE ERROR CODE IN TEMPORARY LOCATION
	MOVE T1,BTJFN2		;T1/JFN FOR BIT TABLE FILE
	RLJFN			;RELEASE THE JFN
	 JFCL			;IGNORE FAILURE
	MOVE T1,STRN06		;RESTORE ERROR CODE
	RETBAD			;TAKE NON-SKIP RETURN
;MAPBTB - MAP THE BIT TABLE

;ACCEPTS:
;	T1/STRUCTURE NUMBER

;RETURNS +1: ALWAYS, NOSKED

;FOR A GIVEN STRUCTURE, GETS OFN FOR ITS BIT TABLE FROM ITS SDB, SWAPS ITS
;INDEX BLOCK INTO CORE.  CALLS LCKBTB TO LOCK BTBLCK AND MAKE THE SPECIAL
;SPT SLOT, BTBBAS, POINT TO THE INDEX BLOCK

MAPBTB::STKVAR<BTBMAP>
	SE1CAL
	MOVE T1,STRTAB(T1)	;POINT TO START OF SDB FOR THIS STRUCTURE
	SKIPN T1,SDBBTB(T1)	;IS THERE AN OFN FOR THE BIT TABLE?
	 BUG(MAPBT1)
	MOVEM T1,BTBMAP		;YES. SAVE SPT INDEX
	NOSKED			;NOSKED WHILE BTBBAS POINTS TO THIS BIT TABLE
	HLL T1,SHRPTR		;SET UP SHARE POINTER TO BTB SECTION
	MOVEM T1,MSECTB+BTSEC	;SET UP SECTION POINTER
	CALL MONCLR		;RESET PAGER MAP
	MOVE T1,BTBMAP		;RECOVER MAP
	CALL SWPIN1		;SWAP IT INTO CORE AND LOCK DOWN THE PAGE
	MOVE T1,BTBMAP		;GET SPT INDEX
	CALL LCKBTB		;LOCK THE LOCK AND SET BTBBAS TO POINT TO THIS INDEX BLOCK
	RET
;UMPBTB - UNMAP THE BIT TABLE

;ACCPETS:
;	T1/STRUCTURE NUMBER

;RETURNS +1: ALWAYS

;CALLED NOSKED, WITH BIT TABLE MAPPED. RETURNS OKSKED WITH BIT TABLE UNMAPPED
;AND BTBLCK UNLOCKED

UMPBTB::MOVEM T1,T4		;SAVE STRUCTURE NUMBER
	SE1CAL
	MOVE T1,BTBBAS		;GET OFFSET OF SPECIAL SPT SLOT FOR BIT TABLE
	MOVX T3,UAAB		;SET UP FOR SPT SLOT UNUSED
	MOVEM T3,SPT(T1)	;INDICATE THIS IN BTBBAS SLOT
	CALL UPSHR		;SET SHARE COUNT
	SETZM SPTH(T1)		;NO ONE OWNS THIS SLOT FOR NOW
	MOVE T2,T4		;GET STRUCTURE NUMBER
	MOVE T2,STRTAB(T2)	;POINT TO START OF SDB FOR THIS STRUCTURE
	SETZM MSECTB+BTSEC	;CLEAR SECTION POINTER
	MOVE T1,SDBBTB(T2)	;GET OFN CURRENTLY MAPPED
	LOAD T1,STGADR,SPT(T1)	;GET CORE ADDRESS THAT INDEX BLOCK IS MAPPED INTO
	CALL UNLBTB		;UNLOCK THE CORE PAGE (LOCKED BY MAPBTB)
	SETOM BTBLCK		;CLEAR THE BIT TABLE LOCK
	OKSKED
	RET
;LCKBTB - LOCK BIT TABLE - CALLED ON ENTRY TO ANY ASSIGNMENT OR DEASSIGNMENT
;ROUTINE

;ACCEPTS:
;	T1/OFFSET IN SPT FOR ENTRY TO COPY INTO BTBBAS

;RETURNS +1: ALWAYS

;CALLED NOSKED

;COPIES AN SPT ENTRY INTO THE SPECIAL BIT TABLE SLOT, BTBBAS.  STORES THE OFFSET
;INTO SPTH(BTBBAS).  THE SPT SLOT MUST POINT TO A PAGE TABLE FOR A BIT TABLE.
;IT MAY BE IN EITHER PART OF THE SPT.  THIS ROUTINE ALSO LOCKS THE BIT TABLE
;LOCK.

LCKBTB:	AOSE BTBLCK		;TRY TO LOCK SPT SLOT
	BUG(DSKBT3,<<T1,D>>)
	MOVE T2,BTBBAS		;GET SPECIAL SPT INDEX FOR BIT TABLE
	MOVE T3,SPT(T1)		;GET CONTENTS OF SPT ENTRY FOR STRUCTURE TO BE MAPPED
	MOVEM T3,SPT(T2)	;COPY INTO BTBBAS ENTRY (MMAP POINTS TO BTBBAS)
	MOVEM T1,SPTH(T2)	;SHOW SPT SLOT AS OWNER IN BTBBAS
	RET
;GETBTB - GET A JFN ON THE BIT TABLE FILE

;ACCEPTS:
;	T1/STRUCTURE NUMBER
;	T2/BITS FOR GTJFN AS PASSED IN T1

;	CALL GETBTB

;RETURNS +1: FAILED
;	 +2: SUCCEEDED
;		T1/JFN FOR BIT TABLE FILE

GETBTB:
	STKVAR <STRN16,NAMBLK,FLAGS,BTJFN0>
	MOVEM T1,STRN16		;SAVE THE STRUCTURE NUMBER
	MOVEM T2,FLAGS		;SAVE BITS FOR GTJFN
	MOVEI T2,10		;GET 8 WORDS OF FREE SPACE FROM THE
	NOINT			;NOINT WHILE WE HAVE JSB FREE SPACE
	CALL ASGJFR		; JSB TO HOLD THE FILE SPEC
	 RETBAD	(,<OKINT>)	;FAILED TO GET THE SPACE
	MOVEM T1,NAMBLK		;SAVE LOCATION OF START OF STRING AREA
	HRROI T1,1(T1)		;POINT TO WORD AFTER THE HEADER
	MOVE T2,STRN16		;T2/STRUCTURE NUMBER
	HRROI T3,BTBNAM		;T3/POINTER TO FILE NAME
	CALL STRST		;BUILD A STRING CONTAINING STRUCTURE NAME
				; AND FILE SPEC
	 JRST GETBT1		;FAILED
	MOVE T1,FLAGS		;T1/BITS FOR GTJFN
	HRRO T2,NAMBLK		;USE FILE NAME JUST CREATED
	ADDI T2,1		;POINT TO WORD AFTER HEADER
	GTJFN			;GET A JFN FOR THE BIT TABLE FILE
	 JRST GETBT1		;FAILED
	MOVEM T1,BTJFN0		;SAVE THE JFN
	MOVEI T1,JSBFRE		;T1/RETURNING SPACE IN JSB
	MOVE T2,NAMBLK		;T2/START OF BLOCK
	CALL RELFRE		;RELEASE THE STRING SPACE WE GOT BEFORE
	OKINT			;OKINT NOW THAT FREE SPACE RETURNED
	MOVE T1,BTJFN0		;RETURN THE JFN IN T1
	RETSKP

;GOT AN ERROR AFTER THE CALL TO ASGJFR AND BEFORE THE CALL TO RELFRE.
;RELEASE THE SPACE AND TAKE ERROR RETURN

GETBT1:	MOVEM T1,STRN16		;SAVE ERROR CODE IN TEMPORARY LOCATION
	MOVEI T1,JSBFRE		;T1/RETURNING SPACE IN THE JSB
	MOVE T2,NAMBLK		;T2/START OF BLOCK
	CALL RELFRE		;RELEASE THE SPACE WE GOT BEFORE
	OKINT			;OKINT NOW THAT FREE SPACE RETURNED
	MOVE T1,STRN16		;RESTORE THE ERROR CODE
	RETBAD

BTBNAM:	ASCIZ /<ROOT-DIRECTORY>DSKBTTBL/
;DSKAS - DISK ASSIGNMENT CONTROL JSYS

;ACCEPTS:
;T1/ DATA PLUS BITS (SEE BELOW)
;T2/ DEVICE DESIGNATOR

;NO BITS: DATA IS SECTOR NUMBER FROM BEGINNING OF STRUCTURE. ASSIGN THIS PAGE
;B0 (DA%DEA): DATA IS SECTOR NUMBER FROM BEGINNING OF STRUCTURE. DEASSIGN THIS PAGE
;B1 (DA%ASF): DATA IS SECTOR NUMBER FROM BEGINNING OF STRUCTURE.  ASSIGN NEAR THIS SECTOR
;B2 (DA%CNV): CONVERT THE ADDRESS IN THE REST OF THE WORD
;B3 (DA%HWA): ADDRESS IS HARDWARE.  CONVERT TO SOFTWARE
;IF B3 IS NOT SET, DATA IS SOFTWARE ADDRESS. CONVERT TO HARDWARE
;B4 (DA%INI): NO DATA. INITIALIZE THE BIT TABLE FOR STRUCTURE IN T2
;B5 (DA%WRT): NO DATA. WRITE THE BIT TABLE FILE FOR THE STRUCTURE IN T2
; 1B0+1B1+SIXBIT / CLEAR/ = CLEAR WHOLE BIT TABLE (NO LONGER SUPPORTED)

;RETURNS +1: FAILED
;	 +2: SUCCEEDED

.DSKAS::MCENT
	CALL DSKASO		;CALL ROUTINE TO DO THE WORK
	 RETERR			;FAILED. NON-SKIP RETURN
	SMRETN			;SUCCEEDED. SKIP RETURN

DSKASO:	TRVAR <STRN07,BTJFN1>
	TXNE A,DA%CNV		;CONVERSION WANTED?
	JRST DSKUA2		;YES
	MOVE 4,CAPENB		;NO. EVERYTHING ELSE REQUIRES WHEEL OR OPERATOR
	TXNN 4,SC%WHL+SC%OPR
	RETBAD(WHELX1)		;CALLER DOESN'T HAVE ENOUGH PRIVILEGES
	UMOVE T1,2		;GET DEVICE DESIGNATOR
	CALL CHKSTR
	 RETBAD (DSKX01)	;NO SUCH STR
	MOVEM T1,STRN07		;SAVE STR NUMBER
	UMOVE T1,1		;RESTORE USER FLAGS
	MOVE T2,STRN07		;SET THIS UP
;**;[2960]Change 1 lines at DSKASO: +12L	RWW	9-May-83
	TXNE T1,DA%INI!DA%WRT!DA%AIN	;WORKING ON THE BIT TABLE?
	JRST [	MOVEI T4,DSKUA4	;YES
		JRST DSKUAD]
	TXZE 1,DA%DEA		;NO.DEASSIGN?
	JRST [	MOVEI T4,DSKUA1	;YES - GO DO IT
		JRST DSKUAD]

;SOME SORT OF ASSIGNMENT TO BE DONE

	MOVEI T4,DSKUAA		;DO SPECIFIC ASSIGNMENT
	TXZE 1,DA%ASF		;UNLESS BIT 1,
	MOVEI T4,DSKUAN		;IN WHICH CASE ASSIGN AS CLOSE
				; AS POSSIBLE
	; ..
	; ..
DSKUAD:	CALL 0(T4)		;DO WHICHEVER
	 JRST [	EXCH T1,STRN07	;SAVE ERROR CODE - GET STR #
		CALL ULKSTR	;UNLOCK STR
		MOVE T1,STRN07	;GET ERROR CODE BACK
		RET]		;FAIL RETURN
	MOVE T1,STRN07		;UPDATE BIT TABLE
	CALL UPDBTB		;...
	MOVE T1,STRN07		;RELEASE STRUCTURE LOCK
	CALL ULKSTR		;...
	RETSKP			;GIVE GOOD RETURN

;HERE IF DA%DEA IS SET. IF DA%ASF IS SET TOO, THIS IS THE BIT TABLE
;CLEAR FUNCTION. OTHERWISE, IT IS THE DEASSIGN FUNCTION

DSKUA1:	TXZN 1,DA%ASF		;BIT 1 ALSO?
	JRST [	CALL DSKDEA	;NO, DEASSIGN SPECIFIC ADDRESS
		 RETBAD		;FAILED
		RETSKP]

;USER HAS REQUESTED THE BIT TABLE CLEAR FUNCTION.  THIS HAS BEEN
;REPLACED BY THE INI/WRT COMBINATION

	RETBAD (ARGX02)		;RETURN 'INVALID FUNCTION'
REPEAT 0,<
	CAME 1,[SIXBIT / CLEAR/] ;SEE IF 'PASSWORD' OK
	RETBAD			;LOSE - HE DIDN'T 'REALLY' WANT TO...
	MOVE T1,STRN07		;T1/STRUCTURE NUMBER
	CALL MAPBTB		;MAP INDEX BLOCK INTO BTBBAS, LOCK INTO CORE,
				; LOCK BTBLCK, GO NOSKED
	MOVE T1,STRN07		;T1/STRUCTURE NUMBER
	CALL INIBTB		;INITIALIZE THE BIT TABLE
	MOVE T1,STRN07		;T1/STRUCTURE NUMBER
	CALL UMPBTB		;UNMAP INDEX BLOCK FROM BTBBAS, UNLOCK CORE PAGE,
				; UNLOCK BTBLCK, GO OKSKED
	RETSKP
>

;USER WANTS ADDRESS CONVERSION

DSKUA2:	MOVE D,CAPENB		;CHECK CAPABILITIES
	TXNN D,SC%WHL+SC%OPR+SC%MNT
	RETBAD(WHELX1)		;INSUFFICIENT
	TXZN A,DA%HWA		;HARDWARE OR SOFTWARE ADDRESS?
	JRST [	ANDX A,STGADR	;SOFTWARE, GET ONLY VALID BITS
		JRST DSKUA3]
DSKUA3:	UMOVEM A,A
	RETSKP
;USER WANTS TO MODIFY THE BIT TABLE. DO SOME COMMON THINGS BEFORE DECIDING
;WHICH FUNCTION TO DO

DSKUA4:	MOVE T3,STRTAB(T2)	;GET SDB PNTR FOR STRUCTURE
	ADDI T2,DVXST0		;POINT TO DEVXXX TABLES FOR THIS STRUCTURE
	MOVX T4,D1%INI		;SET UP BIT FOR STRUCTURE BEING INITED
	NOSKED			;DON'T LET ANYONE STOP US WHILE WE'RE MESSING
				; WITH THE BIT TABLE
;**;[2960]Change 2 lines at	DSKUA4: +5L	RWW	9-May-83
	TXNE T1,DA%WRT!DA%AIN	;[2960]NOW, WHAT WERE WE DOING?
	JRST DSKUA5		;[2960]WRITING(OR ABORTING) THE FILE. GO DO IT

;USER WANTS TO INITIALIZE THE BIT TABLE.  CREATE AN IN-CORE COPY AND
;GIVE THIS FORK EXCLUSIVE ACCESS UNTIL THE WRITE FUNCTION IS DONE.

	TDNE T4,DEVCH1(T2)	;IS BIT ALREADY ON?
	JRST DSKU40		;YES - DON'T CHANGE JOB #
	IORM T4,DEVCH1(T2)	;SAY THAT WE ARE DOING IT
	HRRZS DEVUNT(T2)	;MAKE STRUCTURE APPEAR TO BE ASSIGNED TO JOB 0
				;SO EXEC WON'T SAY IT IS AVAILABLE
	MOVE T4,FORKX		;GET THIS FORK'S NUMBER
	STOR T4,STRJB,(T3)	;SAVE IT AS THE INITING FORK
DSKU40:	SETZRO MI%ASG,SDBSTS(T3) ;ALLOW ASSIGNMENTS AGAIN SINCE WE ARE
				; CREATING A NEW BIT TABLE
	SETZM SDBLCA(T3)	;RESET LAST CYLINDER ASSIGNED FOR THIS
				;STRUCTURE (USED BY DSKASN)
	SKIPE T1,SDBBTB(T3)	;GET CURRENT OFN FOR BIT TABLE
	JRST [	CAIL T1,NOFN	;IS IT A REAL OFN FOR A FILE?
		JRST DSKUA6	;NO. BIT TABLE WAS JUST CREATED
		CALL RELOFN	;YES. RELEASE IT
		JRST .+1]
	MOVE T1,STRN07		;T1/STRUCTURE NUMBER
	CALL CRTBTB		;GO INITIALIZE THE IN-CORE COPY OF THE 
				; BIT TABLE
	 RETBAD (,<OKSKED>)	;FAILED
DSKUA6:	OKSKED			;ALLOW SCHEDULING
	RETSKP

;NOTE ON THE CALL TO RELOFN:
;IT IS POSSIBLE TO DO THE CREATE FUNCTION TWICE IN A ROW, THUS
;ENTERING THIS CODE WHEN A PRIVATE COPY OF THE BIT TABLE EXISTS.
;ONLY THE JOB THAT SET THE D1%INI BIT IN DEVCH1 (AND THUS HAS
;EXCLUSIVE ACCESS) CAN DO THIS FUNCTION AS WELL AS THE 'WRITE'
;FUNCTION. IF A PRIVATE COPY EXISTS, SDBBTB FOR THE STRUCTURE WILL
;CONTAIN A NUMBER LARGER THAN NOFN. IN THAT CASE, RELOFN AND CRTBTB
;ARE NOT CALLED. THIS IS BECAUSE (1) RELOFN WILL FAIL AND (2)
;CRTBTB WOULD CREATE A SECOND PRIVATE PAGE TABLE, LOSING TRACK OF
;THE EXISTING PAGE TABLE. 
;USER WANTS TO WRITE THE BIT TABLE FILE. IF AN IN-CORE COPY EXISTS, SDBBTB
;CONTAINS A NUMBER >= NOFN. IF NOT, THIS CODE RETURNS AN ERROR

DSKUA5:	TDNN T4,DEVCH1(T2)	;IS THE BIT TABLE BEING INITED?
	RETBAD(DSKX03,<OKSKED>)	;NO. IT SHOULD BE
	MOVE T1,SDBBTB(T3)	;GET CURRENT OFN FOR BIT TABLE
	SKIPE T1
	CAIGE T1,NOFN		;REAL FILE OFN?
	RETBAD(DSKX03,<OKSKED>)	;DON'T HAVE SPT INDEX FOR BITTABLE

;GET A JFN ON THE FILE AND GET RID OF IT IN THE DIRECTORY
	
;**;[2960]Add 23 lines at DSKUA5: + 9L	RWW	9-May-83
	UMOVE T2,T1		;[2960]get user's flags back
	TXNE T2,DA%AIN		;[2960]aborting initialization?
	JRST [  HRLZ T2,T1	;[2960]yes, T2/ (OFN,,PN)
		MOVE T1,STRN07	;[2960]get stucture number back.
		MOVE T1,STRTAB(T1) ;[2960]get address of SDB
		MOVE Q1,T1	;[2960]save address for later use
		MOVE T3,SDBBT0(T1) ;[2960]get size of top half of BIT table
		ADD T3,SDBBT1(T1) ;[2960]add size of bottom half
		ADDI T3,<PGSIZ-1> ;[2960]round to end of page
		IDIVI T3,PGSIZ	;[2960]convert to number of pages
		MOVE T4,T3	;[2960]T4/number of pages
		MOVX T3,PM%RD+PM%WR ;[2960]make page available
		SETZM T1	;[2960]T1/ to indicate clear the page table
		CALL MSETPT	;[2960]CLEAR THE TEMPORARY PAGE TABLE
		 NOP		;[2960]don't care
		MOVE T1,SDBBTB(Q1) ;[2960]OFN of bit table
		CALL DESPT	;[2960]RELEASE THE SPT SLOT
		SETZM SDBBTB(Q1) ;[2960]clear OFN of BTB
		MOVE T1,STRN07	;[2960]structure number
		CALL MNTBTB	;[2960]mount bittable
		 JFCL		;[2960]don't care about errors
		JRST DSKUA7]	;[2960]don't write data onto the disk
	MOVE T1,STRN07		;T1/STRUCTURE NUMBER
	MOVX T2,GJ%OLD!GJ%PHY!GJ%DEL!GJ%SHT
	CALL GETBTB		;GET A JFN FOR THE FILE
	 RETSKP			;IGNORE FAILURE
	MOVEM T1,BTJFN1		;SAVE JFN
	TXO T1,DF%FGT!DF%EXP	;GET RID OF POINTER TO INDEX BLOCK
				; AND RELEASE FDB (SEE DSKDEL)
	DELF			; IN THE DIRECTORY
	 JFCL			;IGNORE FAILURE. PRIVATE COPY HAS BEEN
				; CREATED ANYWAY
	MOVE T1,BTJFN1		;T1/JFN
	RLJFN			;RELEASE THE JFN
	 JFCL			;IGNORE FAILURE
	MOVE T1,STRN07		;T1/STRUCTURE NUMBER
	CALL WRTBTB		;WRITE THE BIT TABLE FILE
	 RETBAD (,<OKSKED>)	;FAILED
;**;[2960]Change 1 line at DSKUA5: + 29L	RWW	9-May-83
DSKUA7:	MOVE T1,STRN07		;[2960]T1/STRUCTURE NUMBER
	MOVE T2,STRTAB(T1)	;T2/ADDRESS OF START OF SDB FOR THIS STRUCTURE
	CALL FRESTR		;INDICATE STRUCTURE IS AVAILABLE
	MOVE T1,STRN07		;GET STRUCTURE AGAIN
	MOVE T1,STRTAB(T1)	;GET SDB FOR THIS STRUCTURE
	HRRZ T1,SDBBTB(T1)	;GET OFN OF THE NEW BIT TABLE
;**;[2960]Add 2 lines at DSKUA7: + 6L	RWW	9-May-83
	UMOVE T4,T1		;[2960]get user's flags back
	TXNE T4,DA%AIN		;[2960]aborting initialization?
	CALL UPDOFN		;AND MAKE IT APPEAR ON THE DISK
;**;[2960]Change 1 line at 		RWW	9-May-83
DSKUA8:	OKSKED			;[2960]ALLOW SCHEDULING
	RETSKP

;JACKET ROUTINES FOR DSKASN AND DSKASA

DSKUAA:	TDZA T4,T4		;OFFSET 0
DSKUAN: MOVEI T4,1		;OFFSET 1
	SETO T3,0		;SAY SINGLE ASSIGN
	CALL @[	IFIW!DSKASG
		IFIW!DSKASN](T4)	;CALL CORRECT ROUTINE
	 RETBAD ()		;FAILURE
	UMOVEM T1,1		;RETURN ADDRESS ASSIGNED
	RETSKP			;GOOD RETURN
;DISK USAGE STATISTICS

;ACCEPTS:
;	T1/STRUCTURE NUMBER

;	CALL DSKSP

;RETURNS +1: ALWAYS
;		T1/NUMBER OF USED PAGES
;		T2/NUMBER OF FREE PAGES

DSKSP::	STKVAR <STRN10,FRECNT>
	SE1CAL
	MOVEM T1,STRN10		;SAVE THE STRUCTURE NUMBER
	CALL MAPBTB		;MAP INDEX BLOCK INTO BTBBAS, LOCK INTO CORE,
				; LOCK BTBLCK, GO NOSKED
	MOVE T3,STRN10		;GET STRUCTURE NUMBER
	MOVE T3,STRTAB(T3)	;POINT TO START OF SDB FOR THIS STRUCTURE
	MOVN T4,SDBCYL(T3)	;(-TOTAL CYLINDERS IN STRUCTURE)
	MOVEI T3,LOTRK
	ADD T3,BTBORA		;POINT TO WORD IN TOP OF BIT TABLE
	SETZ T2,			;SETUP TO EXAMINE ALL TRACKS
DSKSP1:	ADD T2,0(T3)		;ADD FREE COUNT OF THIS TRACK
	AOS T3			;NEXT WORD
	AOJL T4,DSKSP1		;DO ALL TRACKS
	MOVEM T2,FRECNT		;SAVE COUNT OF FREE PAGES
	MOVE T1,STRN10		;T1/STRUCTURE NUMBER
	CALL UMPBTB		;UNMAP INDEX BLOCK FROM BTBBAS, UNLOCK CORE PAGE,
				; UNLOCK BTBLCK, GO OKSKED
	MOVE T3,STRN10		;GET STRUCTURE NUMBER
	MOVE T3,STRTAB(T3)	;POINT TO START OF SDB FOR THIS STRUCTURE
	MOVE T1,SDBCYL(T3)	;GET TOTAL CYLINDERS ON STRUCTURE
	MOVE T3,SDBTYP(T3)	;POINT TO SIZE DATA FOR THIS DISK TYPE
	IMUL T1,PAGCYL(T3)	;CONVERT CYLINDERS TO PAGES ON STRUCTURE
	MOVE T2,FRECNT		;RESTORE FREE COUNT
	SUB T1,T2		;USED = TOTAL - FREE
	RET
;GDSKC - JSYS TO GET COUNT OF FREE PAGES ON A STRUCTURE

;ACCEPTS:
;	T1/DEVICE DESIGNATOR (MUST BE DISK)

;RETURNS +1: ALWAYS
;		T1/NUMBER OF PAGES USED
;		T2/NUMBER OF PAGES FREE

;NOTE: IF THE BIT TABLE IS IN THE PROCESS OF BEING INITIALIZED,
;D1%INI WILL BE SET IN DEVCH1.  IF THE FORK DOING THIS JSYS IS DOING THE
;INIT, THE JSYS WILL SUCCEED.  HOWEVER, IT IS POSSIBLE THE SDBFRC WILL
;NOT BE SET UP CORRECTLY.

.GDSKC::MCENT			;JSYS ENTRY
	STKVAR <STRN17>
	UMOVE T1,T1		;GET DEVICE DESIGNATOR
	CALL CHKSTR		;SEE IF VALID STRUCTURE, RETURN NO. IN AC1
	 ITERR(DEVX1)		;STRUCTURE DOES NOT EXIST
	MOVEM T1,STRN17		;SAVE STR #
	CALL GSTRPG		;GET COUNTS. RETURNS USED IN T1, FREE IN T2
	UMOVEM T1,1		;PAGES USED
	UMOVEM T2,2		;PAGES FREE
	MOVE T1,STRN17		;UNLOCK STR
	CALL ULKSTR		;...
	JRST MRETN

;CHKSTR - CONVERT DEVICE DESIGNATOR TO STRUCTURE NUMBER

;ACCEPTS: 
;	T1/DEVICE DESIGNATOR

;RETURNS +1: STRUCTURE DOES NOT EXIST OR IS BEING INITIALIZED
;	 +2: STRUCTURE EXISTS
;		T1/STRUCTURE NUMBER

CHKSTR:	HLRZ T2,T1		;GET DEVICE TYPE
	CAIE T2,.DVDES+.DVDSK	;IS IT A DISK
	RET			;NO - RETURN
	HRRZS T1		;USE UNIQUE CODE
	CAIN T1,-1		;DSK?
	LOAD T1,JSUC		;YES, GET CURRENT CONNECTED STR
	CALL CNVSTR		;CONVERT TO STR #
	 RET			;NO - SUCH STR
	MOVE T4,STRTAB(T1)	;GET SDB
	MOVEI T2,DVXST0(T1)	;POINT TO THIS STR IN DEVXXX TABLE
	MOVX T3,D1%INI		;TEST FOR STRUCTURE BEING INITIALIZED
	TDNE T3,DEVCH1(T2)	;IF SO, DSKFRC MAY NOT BE SET UP
	JRST [	LOAD T3,STRJB,(T4) ;BEING INITED. SEE WHAT FORK IS DOING IT
		CAME T3,FORKX	;IS IT THIS FORK?
		CALLRET ULKSTR	;NO - UNLOCK STR AND RETURN
		JRST .+1]	;YES. CAN REFERENCE BIT TABLE INFO
	RETSKP			;GOOD STRUCTURE, NOT BEING INITIALIZED
				; OR BEING INITED BY THIS FORK

;GSTRPG - GET PAGE COUNTS FOR A STRUCTURE

;ACCEPTS:
;	T1/STRUCTURE NUMBER

;RETURNS +1: ALWAYS
;	T1/COUNT OF USED PAGES ON THE STRUCTURE
;	T2/COUNT OF FREE PAGES ON THE STRUCTURE

;THIS ROUTINE DOES NOT MAKE A CONSISTENCY CHECK.  IT MERELY USES THE SDB VALUES

GSTRPG::MOVE T3,STRTAB(T1)	;POINT TO SDB FOR THIS STRUCTURE
	MOVE T2,SDBFRC(T3)	;GET NUMBER FREE PAGES FOR STRUCTURE
	MOVE T1,SDBCYL(T3)	;GET TOTAL CYLINDERS IN STRUCTURE
	MOVE T3,SDBTYP(T3)	;POINT TO SIZE DATA FOR THIS DISK TYPE
	IMUL T1,PAGCYL(T3)	;CONVERT CYLINDERS TO TOTAL PAGES
	SUB T1,T2		;USED = TOTAL - FREE
	RET
;DISK OPERATE JSYS - USER UTILITY DISK HANDLE

;ACCEPTS:
;	T1/ 1B1+CHANNEL NUMBER (BITS 2-6) + UNIT NUMBER (BITS 7-12)
;		+ SECTOR NUMBER WITHIN UNIT (BITS 13-35)
;				OR
;	    1B0 + 0 (BITS 2-6) + SECTOR NUMBER WITHIN STRUCTURE (BITS 7-35)
;				OR
;	    1B0 + -1 (BITS 2-6) +SECTOR NUMBER WITHIN STRUCTURE (BITS 7-35)
;	T2/FLAGS + NUMBER OF WORDS
;	T3/ STARTING ADDRESS IN USER'S ADDRESS SPACE
;	T4/ DEPENDS ON T1 AS FOLLOWS:
;		IF 1B0 IS SET AND BITS 2-6 ARE -1, DEVICE DESIGNATOR FOR STRUCTURE
;		OTHERWISE, IGNORED

;	DSKOP

;RETURNS +1: ALWAYS,
;	T1/ 0 ON SUCCESS, NON-ZERO ON FAILURE

;NOTES ON ARGUMENTS:
;IN T1, IF BITS 2-6 ARE 0, STRUCTURE 0 (PS) IS USED

;FLAGS IN T2:
;	1B11 (DOP%IL) INHIBIT ERROR LOGGING
;	1B12 (DOP%IR) INHIBIT ERROR RECOVERY
;	1B14 (DOP%WR) WRITE ACCESS


;1/	EITHER BYTE (2).DOPSR(34)LINEAR ADDRESS WITHIN STR
;	OR     BYTE (2).DOPPU(5)CHANNEL NUMBER(6)UNIT NUMBER(23)LINEAR ADDRESS WITHIN UNIT
; 2/ DOP%WR (1B14) - WRITE
;	18-35 - COUNT
; 3/ VIRTUAL ADDRESS
; 4/ DEVICE DESIGNATOR IF DOP%SN := -1

.DSKOP::MCENT
	STKVAR <STRNXX,SAVPAG,SAVPTN>
	MOVE D,CAPENB		;GET USER'S CAPABILITIES
	TXNN D,SC%WHL!SC%OPR!SC%MNT ;HAVE PROPER PRIVILEGES?
	ITERR (WHELX1)		;NO. COMPLAIN
	TXNE B,-1-<DOP%IL!DOP%IR!DOP%WR!DOP%CT>	;SPECIFYING UNUSED FLAGS?
	ITERR (DECRSV)		;YES, COMPLAIN
	UMOVE P2,1		;GET USER ADDRESS
	LOAD A,DOP%AT,P2	;GET ADDRESS TYPE
	CAIN A,.DOPSR		;STRUCTURE RELATIVE?
	JRST [	LOAD A,DOP%SN,P2 ;YES. GET SN
		JUMPE A,[MOVEI A,PSNUM ;USE PS IF ZERO
			 SKIPN STRTAB(A) ;MAKE SURE ITS HERE
			 ITERR (DSKOX3)
			 JRST DSKOP3]  ;CONTINUE (NO STR TO LOCK)
		CAIE A,<.RTJST (DOP%SN,DOP%SN)> ;IS FIELD ALL ONES?
		ITERR (DSKOX3)
		UMOVE A,4	;GET DEVICE DESIGNATOR
		CALL CHKSTR	;CONVERT TO STR #
		 ITERR (DSKOX3)	;NONE
		JRST DKOP3A]	;SAVE # TO UNLOCK WHEN DONE
	CAIN A,.DOPPU		;PHYSICAL?
	JRST [	LOAD A,DOP%CN,P2 ;YES. GET CHANNEL
		CAIL A,CHNN	;VALID?
		ITERR (DSKOX1)	;NO. ERROR
		LOAD A,DOP%UN,P2 ;GET UNIT
		CAIL A,MAXRH	;VALID?
		ITERR (DSKOX2)	;NO
		JRST DSKOP3]	;ALL VERIFIED
	ITERR (DSKOX4)		;ILLEGAL MODE REQUESTED
DSKOP3:	SETO A,			;NO STR # TO REMEMBER
DKOP3A:	MOVEM A,STRNXX		;SAVE STR # OR -1
	MOVE D,CAPENB		;GET CAPS AGAIN
	TXNE D,SC%WHL!SC%OPR	;WHEEL OR OPERATOR?
	JRST DSKOP2		;WHEELS AND OPERATORS CAN DO IT ALL
	UMOVE B,2		;GET USER FLAGS
	TXNN B,DOP%WR		;WANT TO WRITE IT?
	JRST DSKOP2		;NO. ALLOW MAINT TO READ ANYTHING
	LOAD C,DOP%AT,P2	;GET ADDRESS TYPE
	CAIE C,.DOPPU		;WANT TO WRITE PHYSICAL?
	JRST DSKOPE		;NO - CAN'T WRITE STR
	LOAD C,DOP%CN,P2	;GET CHANNEL OF DISK
	SKIPN C,CHNTAB(C)	;DOES THIS CHANNEL EXIST?
	JRST DSKOP2		;NO. LET UDSKIO COMPLAIN THEN
	LOAD D,DOP%UN,P2	;GET UNIT NUMBER
	ADDI D,CDBUDB(C)	;GET POINTER TO UDB IN CDB
	SKIPN D,0(D)		;DOES THIS UNIT EXIST
	JRST DSKOP2		;NO. LET UDSKIO COMPLAIN
	SKIPL UDBSTR(D)		;YES. DOES IT BELONG TO A STRUCTURE?
	JRST DSKOPE		;YES - CAN'T DO IT
DSKOP2:	UMOVE B,2		;GET COUNT
	UMOVE C,3		;GET USER ADDRS
	ANDI B,3777		;CHECK FOR CROSS OF PAGE BOUNDARY
	ADDI B,-1(C)		;CORE ADR + WORD COUNT
	XOR B,C
	TRNE B,777000		;SAME PAGE?
	JRST [	MOVEI A,4000	;NO, GIVE IPO ERROR
		UMOVEM A,1
		JRST DSKOPZ]
	HRRZS A,C		;ADDRESS
	UMOVE B,2		;GET USERS FLAGS
	TXNE B,DOP%WR		;WRITE?
	XCTU [SKIPA 0(A)]	;YES, REF CORE PAGE TO ENSURE EXISTS
	XCTU [MOVES 0(A)]	;NO, BE SURE CAN MODIFY CORE PAGE
	NOINT			;NO INTERRUPTS AFTER TESTING WRITE CAPS
	MOVE B,MPP		;GET RETURN PC FLAGS
	MOVE B,0(B)		;...
	TLNE B,(UMODF)		;CALLED FROM USER?
	HRLI A,(1B0)		;CALLED FROM USER, INDICATE IN ADDRESS
	CALL FPTA		;GET PTN.PN
	MOVEM A,SAVPTN		;SAVE IT
	CALL MLKPG		;LOCK THE PAGE
DSKOP1:	MOVEM A,SAVPAG		;SAVE PAGE NUMBER
	LOAD P1,DOP%AT,P2	;GET ADDRESS TYPE
	LOAD D,DOP%RA,P2	;GET DISK ADDRESS
	CAIE P1,.DOPSR		;STRUCTURE RELATIVE?
	LOAD D,DOP%UA,P2	;NO. GET UNIT RELATIVE ADDRESS
	MOVE A,D		;MOVE ADDRESS TO PROPER PLACE
	MOVE C,SAVPAG		;RECOVER PHYS PAGE NUMBER
	LSH C,^D9		;CONVERT PAGE NUMBER TO ADDRESS
	UMOVE D,3		;USERS ADDRESS
	ANDI D,777
	IORI C,0(D)		;FOR STARTING NOT AT BEGNG OF PAGE
	UMOVE B,2		;OTHER ARGS
	SKIPGE D,STRNXX		;GET STRUCTURE NUMBER
	MOVEI D,PSNUM		;USE PS IF -1
	CAIN P1,.DOPPU		;PHYSICAL ADDRESSES?
	JRST [	TXO B,1B0	;YES. TELL UDSKIO WE HAVE CHANNEL,,UNIT
		LOAD D,DOP%UN,P2 ;GET UNIT NUMBER
		LOAD P1,DOP%CN,P2 ;GET CHANNEL
		HRL D,P1	;FORM CHANNEL,,UNIT
		JRST .+1]	;AND GO DO IT
	CALL UDSKIO
	UMOVEM A,1		;RETURN ERROR BITS
	MOVE A,SAVPAG		;GET PAGE # BACK
	MOVX C,CORMB		;CORE MODIFIED BIT
	UMOVE B,2
	TLNN B,(1B14)		;READ?
	IORM C,CST0(A)		;YES, NOTE CORE CHANGED
	MOVE A,SAVPTN		;RECOVER PTN.PN OF LOCKED PAGE
	CALL MULKPG		;UNLOCK IT
	OKINT			;ALLOW INTS AGAIN
DSKOPZ:	SKIPGE A,STRNXX		;SAVED STR #
	JRST MRETN		;NO - RETURN
	CALL ULKSTR		;YES - UNLOCK IT
	JRST MRETN		;AND RETURN

DSKOPE:	SKIPGE A,STRNXX		;SAVED STR #?
	ITERR (WHELX1)		;NO
	CALL ULKSTR		;YES - UNLOCK IT
	ITERR (WHELX1)		;AND RETURN ERROR
;CHKBT - CHECK CONSISTENCY OF BIT TABLE

;ACCEPTS:
;	T1/ STRUCTURE NUMBER
;	T2/ FLAGS

;	CALL CHKBT

;RETURNS +1: CHKB0 FOUND ERRORS
;		T1/ COUNT OF USED PAGES
;		T2/ COUNT OF FREE PAGES
;		T3/ ERROR COUNT
;	 +2: NO ERRORS,
;		T1/ COUNT OF USED PAGES
;		T2/ COUNT OF FREE PAGES
;		T3/ ERROR COUNT (ZERO)

;COMPARES COUNT OF FREE PAGES PER TRACK WITH BITS FOR EACH PAGE IN THE TRACK.
;IF THEY DISAGREE, FIXES THE COUNT AND PRINTS MESSAGE IF REQUESTED IN T2
;ALSO FIXES THE FREE COUNT FOR THE ENTIRE STRUCTURE

CHKBT::	STKVAR <STRN11,CHKBTE>
	SE1CAL
	MOVEM T1,STRN11		;SAVE STRUCTURE NUMBER
	CALL CHKB0		;CHECK CONSISTENCY
	MOVEM T1,CHKBTE		;SAVE COUNT OF ERRORS
	MOVE T1,STRN11		;NO. T1/STRUCTURE NUMBER
	CALL DSKSP		;CALCULATE FREE COUNT
				;T1/USED PAGES, T2/FREE PAGES
	MOVE T3,STRN11		;GET STRUCTURE NUMBER
	MOVE T3,STRTAB(T3)	;POINT TO START OF SDB FOR THIS STRUCTURE
	MOVEM T2,SDBFRC(T3)	;STORE NEW COUNT OF FREE PAGES IN SDB
	SKIPE T3,CHKBTE		;WERE THERE ANY ERRORS?
	RETBAD			;YES. TAKE ERROR RETURN
	RETSKP			;NO. TAKE SUCCESS RETURN
;CHKB0 - CHECK FREE PAGE COUNT AGAINST BITS FOR INDIVIDUAL PAGES

;ACCEPTS:
;	T1/ STRUCTURE NUMBER
;	T2/ FLAGS

;RETURNS +1: ALWAYS
;		T1/COUNT OF ERRORS

;USE OF P REGISTERS:
;	P1/ADDRESS OF SDB FOR THIS STRUCTURE
;	P2/ADDRESS OF SIZE DATA FOR THIS DISK TYPE

CHKB0:	SAVEPQ
	STKVAR<STRN12,ERRCNT,GOODCT,BADCNT,CKBTFL>
	MOVEM T1,STRN12		;SAVE THE STRUCTURE NUMBER
	MOVEM T2,CKBTFL		;SAVE FLAGS
	MOVE P1,STRTAB(T1)	;P1/ADDRESS OF SDB FOR THIS STRUCTURE
	MOVE P2,SDBTYP(P1)	;P2/ADDRESS OF SIZE DATA FOR THIS DISK TYPE
	CALL MAPBTB		;MAP INDEX BLOCK INTO BTBBAS, LOCK INTO CORE,
				; LOCK BTBLCK, GO NOSKED
	SETZM ERRCNT		;INITIALIZE COUNT OF ERRORS
	MOVN 7,SDBCYL(P1)	;7/(-TOTAL CYLINDERS IN STRUCTURE,,LOWEST CYL)
	HRLZ 7,7
	HRRI 7,LOTRK
CHKB5:	MOVEI 6,0(7)		;GET NEXT CYLINDER NUMBER
	IMUL 6,BTWCYL(P2)	;COMPUTE OFFSET IN BIT PART OF TABLE
	ADD 6,BTBORA		;POINT TO ACTUAL WORD IN BIT PART OF TABLE
	ADD 6,SDBBT0(P1)
	MOVE 4,PAGCYL(P2)	;COUNT BACKWARDS FROM NO. PAGES PER CYLINDER
	SETZ 5,			;WILL COUNT FREE PAGES FOUND
CHKB2:	MOVE 1,0(6)		;GET WORD OF BITS
	MOVNI 2,^D36		;36 OF THEM...
CHKB1:	TDNE 1,BITS+^D36(2)	;THIS PAGE FREE?
	AOJ 5,			;YES, COUNT IT
	SOJLE 4,CHKB3		;STOP IF CHECKED ALL PAGES THIS TRACK
	AOJL 2,CHKB1		;LOOP OVER BITS IN WORD
	AOJA 6,CHKB2		;LOOP OVER WORDS

CHKB3:	MOVE 1,BTBORA		;POINT TO BEGINNING OF BIT TABLE
	ADDI 1,0(7)		;POINT TO WORD FOR THIS TRACK
	CAME 5,0(1)		;COUNT CORRECT AS REMEMBERED?
	JRST CHKB4		;NO
CHKB6:	AOBJN 7,CHKB5		;YES, LOOP OVER TRACKS
	MOVE 1,STRN12		;1/STRUCTURE NUMBER
	CALL UMPBTB		;UNMAP INDEX BLOCK FROM BTBBAS, UNLOCK CORE PAGE,
				; UNLOCK BTBLCK, GO OKSKED
	MOVE 1,ERRCNT		;RESTORE COUNT OF ERRORS
	RET
;INCONSISTENCY BETWEEN COUNT OF FREE PAGES FOR A TRACK AND THE BITS FOR
;EACH PAGE. REPORT THE INCONSISTENCY AND CONTINUE THE SEARCH.  

;T1/ ADDRESS OF WORD IN FIRST PART OF BIT TABLE CONTAINING FREE PAGE COUNT
;5/ COUNT AS OBTAINED FROM ADDING BITS
;7/CYLINDER NUMBER

CHKB4:	MOVEM 5,GOODCT		;SAVE THE COUNT OF BITS
	EXCH 5,0(1)		;STORE NEW COUNT, GET OLD ONE
	MOVEM 5,BADCNT		;SAVE OLD COUNT OF FREE PAGES
	AOS 6,ERRCNT		;COUNT ERRORS
	MOVE A,CKBTFL		;GET FLAGS
	TXNN A,MI%MSG		;MESSAGES DESIRED ?
	JRST CHKB6		;NO, GO ON
	CAIL 6,^D20		;YES, REPORTED ENOUGH?
	JRST [	CAIE 6,^D20	;YES, NOTED OTHERS ALREADY?
		JRST CHKB6	;YES, CONTINUE QUIETLY
		MOVE 1,STRN12	;T1/STRUCTURE NUMBER
		CALL UMPBTB	;UNMAP INDEX BLOCK FROM BTBBAS, UNLOCK CORE PAGE,
				; UNLOCK BTBLCK, GO OKSKED
		HRROI 1,[ASCIZ /
AND OTHERS...
/]
		PSOUT		;NOTE ADDITIONAL ERRORS AFTER CUTOFF
		MOVE 1,STRN12	;T1/STRUCTURE NUMBER
		CALL MAPBTB	;MAP INDEX BLOCK INTO BTBBAS, LOCK INTO CORE,
				; LOCK BTBLCK, GO NOSKED
		JRST CHKB6]	;CONTINUE WITH SCAN
	MOVE 1,STRN12		;T1/STRUCTURE NUMBER
	CALL UMPBTB		;UNMAP INDEX BLOCK FROM BTBBAS, UNLOCK CORE PAGE,
				; UNLOCK BTBLCK, GO OKSKED
	HRROI 1,[ASCIZ /
BT INCONSISTENCY (COUNTS WILL BE CORRECTED)
 TRK CNT BITS
/]
	CAIG 6,1		;FIRST ERROR?
	PSOUT			;YES, PRINT HEADING
	MOVEI 1,101
	MOVX T3,<NO%LFL+FLD(4,NO%COL)+FLD(10,NO%RDX)> ;LEADING FILLER, 
				;4 COLUMNS, OCTAL NUMBER
	MOVEI 2,0(7)		;GET CYLINDER NUMBER
	NOUT			;PRINT TRACK NUMBER
	 MOVX T3,<NO%LFL+FLD(4,NO%COL)+FLD(10,NO%RDX)> ;FAILED. RESTORE FLAGS
	MOVE 2,BADCNT		;RESTORE FREE PAGE COUNT FROM TOP OF BIT TABLE
	NOUT			;PRINT FREE PAGE COUNT
	 MOVX T3,<NO%LFL+FLD(4,NO%COL)+FLD(10,NO%RDX)> ;FAILED. RESTORE FLAGS
	MOVE 2,GOODCT		;GET COUNT FROM BITS
	ANDI 2,777		;IN CASE REALLY FOULED UP
	NOUT			;PRINT COUNT FROM BITS
	 JFCL
	HRROI 1,[ASCIZ /
/]
	PSOUT
	MOVE 1,STRN12		;T1/ STRUCTURE NUMBER
	CALL MAPBTB		;MAP INDEX BLOCK INTO BTBBAS, LOCK INTO CORE,
				; LOCK BTBLCK, GO NOSKED
	JRST CHKB6		;CONTINUE SCAN
;UPDATE BIT TABLE--CAUSE CHANGED PAGES TO BE WRITTEN TO DISK

;ACCEPTS:
;	T1/STRUCTURE NUMBER

;	CALL UPDBTB

;RETURNS +1: ALWAYS

;NOTE: IF THE BIT TABLE IS IN PRIVATE PAGES RATHER THAN A FILE,
;ITS OFN IS >= NOFN. UPDPGS CANNOT BE CALLED IN THIS CASE BECAUSE
;IT CALLS UPDOFN, WHICH WANTS THE PAGES TO BE IN A FILE

UPDBTB::MOVE T4,T1		;GET UNIT NUMBER
	SE1CAL
REPEAT 0,<
	ADDI T4,DVXST0		;POINT TO THIS STRUCTURE IN DEVXXX TABLES
	MOVX T3,D1%INI		;SET UP BIT FOR INITING STRUCTURE
	TDNE T3,DEVCH1(T4)	;IF SO, DON'T TRY TO DO THIS BECAUSE
				; UPDPGS CALLS OPDOFN, WHICH WANTS BIT TABLE
				; TO BE A FILE.
	RET
>
	MOVE T3,STRTAB(T1)	;POINT TO START OF SDB FOR THIS STRUCTURE
	SKIPE T1,SDBBTB(T3)	;GET OFN FOR BIT TABLE
	CAIL T1,NOFN		;IS IT A REAL OFN?
	RET			;NO OFN FOR BIT TABLE. DON'T TRY TO UPDATE
	HRLZS T1		;T1/(OFN,,PAGE 0)
	MOVE T2,SDBBT0(T3)	;GET SIZE OF TOP HALF OF BIT TABLE
	ADD T2,SDBBT1(T3)	;ADD SIZE OF BOTTOM
	ADDI T2,<PGSIZ-1>	;ROUND UP TO END OF PAGE
	IDIVI T2,PGSIZ		;T2/ PAGE COUNT
	SKIPE T1		;DO NOTHING IF NO OFN ASSIGNED
	CALL UPDPGS		;UPDATE PAGES
	RET
;THIS ROUTINE WILL ALLOCATE THE FE FILE SYSTEM ON THE DUAL-PORTED
;DISK DRIVE AND THE BOOTSTRAP.BIN FILE.
; IT IS EXECUTED ONLY AT SYSTEM REFRESH TIME AND
;IS DONE AS PART OF THE BIT TABLE INITIALIZATION LOGIC.

;ACCEPTS:
;	T1/STRUCTURE NUMBER
;	T2/NUMBER OF PAGES TO ALLOCATE
;		CALL FEFSYS
;RETURNS: +1	 FAILURE
;	  +2	SUCCESS

; LOCAL VARIABLES --

;STRN13		;STRUCTURE NUMBER
;OFNPTT		;OFN OF PTT
;OFNPT		;OFN OF PT
;FEFNAM		;GTJFN STRING PLACED HERE
;FEFPAG		;NUMBER OF PAGES SPECIFIED FOR FE FILE SYSTEM
;FEFCYL		;NUMBER OF CYLINDERS FOR FE FILE SYSTEM

BOTSYS::TDZA C,C		;SET BOOT FLAG
FEFSYS::SETO C,			;SET FE FLAG
	JUMPE T2,RSKP		;RETURN SUCCESS IF NOTHING TO ALLOCATE
	SKIPG T2		;NEGATIVE # OF PAGES SPECIFIED ?
	RET			;YES, RETURN FAILURE
	SE1CAL
	SAVEPQ
	JSBVAR <STRTY1,STRN13,OFNPTT,OFNPT,<FEFNAM,^D12>,FEFPAG,FEFCYL,FILTYP>,R
	MOVEM C,FILTYP		;SAVE TYPE OF ENTRY
	DMOVEM A,P1		;SAVE STRUCTURE # AND # OF PAGES FOR FE FILE SYS
	MOVEM P1,STRN13		;SAVE STRUCTURE NUMBER
	MOVEM P2,FEFPAG		;SAVE NUMBER OF PAGES INITIALLY SPECIFIED
	HRRZ Q1,STRTAB(P1)	;Q1/ADDRESS OF SDB FOR THIS STRUCTURE
	MOVN Q2,SDBNUM(Q1)	;NUMBER OF UNITS IN STRUCTURE
	MOVSI Q2,0(Q2)		;FORM AOBJN POINTER
	HRRI Q2,SDBUDB(Q1)	;FIRST UDB
	MOVE Q3,Q2		;COPY AOBJN POINTER
FEFSY0:	HRRZ A,0(Q3)		;GET UDB
	CALL WRBOOT		;WRITE BOOT BLOCK
	AOBJN Q3,FEFSY0		;LOOP FO ALL UNITS
	MOVE A,Q1		;COPY SDB
	MOVE B,Q2		;COPY AOBJN POINTER AGAIN

;LOOP THROUGH LOGICAL UNITS LOOKING FOR DUAL-PORTED DRIVE

FESYS2:	MOVE D,0(B)		;UDB ADDRESS
	MOVX C,US.PGM		;FLAG FOR THE DUAL-PORTED DRIVE
	TDNE C,UDBSTS(D)	;IS THIS IT?
	JRST FEFSY1		;YES
	AOBJN B,FESYS2		;NO. LOOK AT NEXT
;	SKIPN FILTYP		;IF BOOTSTRAP NO BUGCHECK
;	BUG(NO2PRT)
	MOVEI B,SDBUDB(Q1)	;POINTER TO LOGICAL 0
FEFSY1:	MOVE P4,B		;SAVE UDB INDEX
	MOVEI P1,0(B)		;ADDRESS OF UDB POINTER
	SUBI P1,SDBUDB(Q1)	;CALCULATE RELATIVE PCAK NUMBER
	MOVE Q2,SDBTYP(Q1)	;Q2/ADDRESS OF SIZE DATA FOR THIS DISK TYPE
	MOVEM Q2,STRTY1		;SAVE IT FOR FEWRTH
	MOVE A,FEFPAG		;GET DESIRED # OF PAGES IN FE FILE SYSTEM
	IDIV A,PAGCYL(Q2)	;COMPUTE # OF CYLINDERS
	SKIPE B			;ROUND UP TO THE NEXT FULL CYLINDER
	ADDI A,1		; IF A PARTIAL CYLINDER REQUESTED
	MOVEM A,FEFCYL		;SAVE # OF CYLINDERS TO ALLOCATE
	IMUL A,PAGCYL(Q2)	;COMPUTE ACTUAL # OF PAGES TO ALLOCATE
	SKIPE FILTYP		;SKIP IF BOOTSTRAP.BIN SINCE IT REALLY
				;DOESN'T NEED A FULL CYL OF SPACE
	MOVEM A,FEFPAG		;SAVE ACTUAL # OF PAGES TO ALLOCATE
	IMUL P1,CYLUNT(Q2)	;NOW GET FIRST CYLINDER ON PACK
	MOVE P2,P1		;MOVE TRACK NUMBER
	ADD P1,CYLUNT(Q2)	;LAST TRACK ON THE PACK
	SOS P1			; ...
	MOVE A,STRN13		;1/STRUCTURE NUMBER
	CALL MAPBTB		;MAP INDEX BLOCK INTO BTBBAS, LOCK INTO CORE,
				; LOCK BTBLCK, GO NOSKED

;A DUAL-PORTED DRIVE HAS BEEN FOUND. FIND A BLOCK OF CONTIGUOUS 
;CYLINDERS LARGE ENOUGH TO HOLD THE FRONT END FILE SYSTEM.
;EACH CYLINDER IN THE BLOCK MUST HAVE ALL ITS PAGES FREE

;P2/CYLINDER NUMBER RELATIVE TO START OF STRUCTURE FOR FIRST CYLINDER
;   ON THIS UNIT
;P1/CYLINDER NUMBER RELATIVE TO START OF STRUCTURE FOR LAST CYLINDER
;   ON THIS UNIT

FEFSY3:	MOVE C,FEFCYL		;GET # OF CYLINDERS TO ALLOCATE
	ADD C,P2		;COMPUTE LAST CYLINDER # TO ALLOCATE
	CAML C,P1		;ENOUGH SPACE LEFT ON THIS PACK ?
	JRST [	MOVE A,STRN13	 ;NO, GET STRUCTURE NUMBER
		CALL UMPBTB	;GO UNMAP THE BIT TABLE AND RETURN FAILURE
		JRST FEFER0]	;GO RELEASE LOCAL VARIABLE BLOCK AND RETURN
	MOVE D,P2		;GET NUMBER OF FIRST CYLINDER TO USE
	MOVN P2,FEFCYL		;GET -<# OF CYLINDERS TO ALLOCATE>
	ADD D,BTBORA		;COMPUTE ADDRESS IN BIT TABLE
	MOVE C,PAGCYL(Q2)	;GET # OF PAGES ON EACH CYLINDER FOR THIS PACK
FEFSY4:	CAME C,0(D)		;THIS ONE GOOD?
	JRST FEFSY5		;NO
	AOS D
	AOJL P2,FEFSY4		;YES. DO ALL OF THEM
	MOVE P2,D		;GET SIZE
	SUB P2,BTBORA		;SUBTRACT BIT MAP START
	SUB P2,FEFCYL		;BACK UP TO BEGINNING
	JRST FEFSY6		;FOUND A REGION

FEFSY5:	XMOVEI P2,1(D)		;SKIP THIS BAD TRACK AND GO ON
	SUB P2,BTBORA		;RESTORE TRACK NUMBER
	JRST FEFSY3		;AND TRY AGAIN
;FOUND A REGION TO ALLOCATE. 
;	P2/ LOWEST TRACK NUMBER IN REGION

FEFSY6:	MOVE A,STRN13		;1/STRUCTURE NUMBER
	CALL UMPBTB		;UNMAP INDEX BLOCK FROM BTBBAS, UNLOCK CORE PAGE,
				; UNLOCK BTBLCK, GO OKSKED
	MOVEI P1,0(P2)		;GET FIRST TRACK NUMBER
	IMUL P1,SECCYL(Q2)	;CONVERT TO SECTOR NUMBER
	MOVE P3,FEFPAG		;GET # OF PAGES TO ALLOCATE
	MOVE P2,P1		;SAVE STARTING SECTOR

;WRITE THE HOME BLOCK SAYING THIS PACK HAS THE FE FILE SYSTEM

	CALL ASGPAG		;GET A PAGE
	 JRST FEFER0		;FAILED, RELEASE LOCAL VARIABLE BLOCK AND RETURN
	MOVE Q3,A		;SAVE PAGE
	MOVE B,P4		;GET SDBUDB POINTER
	MOVE C,P1		;START SECTOR
	MOVE D,P3		;# OF PAGES
	SKIPN FILTYP		;CHECK FILE TYPE
	JRST [CALL BOWRTH	;WRITE BOOT FILE
		JRST FEFER1	;RELEASE ASSIGNED PAGE AND RETURN ERROR
		JRST .+3]	;SKIP OVER FE WRITE
	CALL FEWRTH		;GO WRITE THE HOME BLOCK
	 JRST FEFER1		;RELEASE ASSIGNED PAGE AND RETURN ERROR
	; ..
;ASSIGN ALL PAGES IN THE BLOCK.
;	P1/FIRST SECTOR
;	P2/FIRST SECTOR
;	Q2/ADDRESS OF SIZE DATA FOR THIS DISK TYPE

FEFSY7:	MOVE A,P1		;1/SECTOR NUMBER
	MOVE B,STRN13		;2/STRUCTURE NUMBER
	CALL DSKASA		;ASSIGN IT
	 JRST FEFER1		;FAILED, RELEASE SPACE AND RETURN ERROR
	ADD P1,SECPAG(Q2)	;NEXT PAGE
	SOJG P3,FEFSY7		;ASSIGN ALL RELEVANT PAGES

;NOW THAT THE REGION IS ALLOCATED, A FILE MUST BE CREATED WHICH
;DEFINES THE SELECTED TRACKS.
;	P2/ STARTING SECTOR IN REGION

	HRROI A,FEFNAM		;T1/ ADDRS OF BLOCK FOR NAME
	MOVE B,STRN13		;T2/STRUCTURE NUMBER
	HRROI C,[ASCIZ/<ROOT-DIRECTORY>FRONT-END-FILE-SYSTEM.BIN;P770000/]
	SKIPN FILTYP		;CHECK FOR BOOT FILE
	HRROI C,[ASCIZ/<ROOT-DIRECTORY>BOOTSTRAP.BIN;P770000/]
				;C/ NAME OF FILE WITHOUT STRUCTURE
	CALL STRST		;CREATE FILE SPEC INCLUDING THE STRUCTURE NAME
				; IN FREE SPACE POINTED TO BY FEFNAM
 	 JRST FEFERR		;FAILED. GO RELEASE FREE SPACE
	MOVX A,GJ%NEW!GJ%SHT	;GTJFN ARGS
	HRROI B,FEFNAM		;B/ ADDRS OF FILE NAME
	GTJFN			;GET A JFN FOR IT
	 JRST FEFERR		;NOT THERE. CANT FIX HOME BLOCK THEN
	MOVE P3,A		;SAVE THE JFN
	IMULI A,MLJFN		;MAKE IT AN INTERNAL INDEX
	CALL GETFDT		;GET FDB FOR THIS JFN
	 JRST FEFER1		;FAILED, RELEASE LOCAL VARIABLE BLOCK AND RETURN
	MOVE P4,A		;SAVE FDB LOC
	MOVE B,.FBCTL(P4)	;GET CONTROL WORD
	TXZ B,FB%NXF		;MAKE IT EXISTANT
	TXO B,FB%LNG!FB%NOD	;AND MAKE IT LONG AND NO DUMP AS WELL
	MOVEM B,.FBCTL(P4)	;BACK INTO THE FDB
;**;[1925] Change 1826 lines at FEFSY8: -23L	JGZ	19-AUG-81
;**;[1826] Add 2 lines at FEFSY8: -23L	PED	19-JAN-81
	MOVX B,AR%EXM		;[1826] GET THE BIT TO SET
	IORM B,.FBBBT(P4)	;[1826] SET IT IN THE FDB
	CALL ASGPAG		;NOW GET ONE FOR THE SUB PAGE TABLES
	 JRST FEFER1		;FAILED, RELEASE SPACE AND RETURN ERROR
	MOVE P5,A		;AND SAVE THIS AS WELL
	SETZ A,			;A/0 FOR FREE CHOICE OF SECTOR NUMBER
	MOVE B,STRN13		;B/STRUCTURE NUMBER
	CALL DSKASN		;GET A DISK PAGE
	 JRST FEFER2		;RELEASE ASSIGNED PAGES AND RETURN ERROR
	MOVEM A,.FBADR(P4)	;SAVE THIS IN THE FDB
	MOVE B,STRN13		;2/STRUCTURE NUMBER
	TXO A,FILNB		;SAY IS A NEW INDEX BLOCK
	CALL ASROFN		;GET THE OFN
	 JRST FEFER2		;FAILED, RELEASE ASSIGNED PAGES AND RETURN ERROR
	MOVEM A,OFNPTT		;SAVE THE OFN OF THE PTT
	CALL UPDOFN		;UPDATE IT
	MOVE C,FEFPAG		;GET # OF PAGES TO ALLOCATE
	HRRM C,.FBBYV(P4)	;STORE FILE SIZE
	CALL USTDIR		;DONE WITH THE FDB AND THE DIRECTORY
	MOVE P4,FEFPAG		;GET # OF PAGES TO ALLOCATE
	TXO P2,DSKAB		;SAY THIS IS A DISK ADDRESS
	MOVE A,OFNPTT		;GET OFN OF PTT
	MOVEI B,0(Q3)		;PAGE TO HOLD IT
	HRLI B,(PTRW)		;GET FULL ACCESS
	CALL SETMPG		;GET THE PAGE
	;..
FEFSY8:	SETZ A,			;1/FREE CHOICE OF PAGE
	MOVE B,STRN13		;2/STRUCTURE NUMBER
	CALL DSKASN		;GET A DISK PAGE
	 JRST FEFER3		;FAILED; RELEASE PAGES AND OFN, RETURN ERROR
	TXO A,DSKAB		;SAY IS A DISK ADDRESS
	MOVEM A,0(Q3)		;TO THE PTT
	MOVX B,OFNWRB		;THE OFN WRITE BIT
	MOVE C,OFNPTT		;OFN OF PTT
	IORM B,SPTH(C)		;SAY IT IS WRITTEN
	MOVEI B,IMMCOD		;AND THAT THE POINTER IS IMMEDIATE
	STOR B,PTRCOD,(Q3)	;""
	AOS Q3			;NEXT SLOT
	TXO A,FILNB		;SAY IS A NEW INDEX BLOCK
	MOVE B,STRN13		;2/STRUCTURE NUMBER
	CALL ASROFN		;GET AN OFN
	 JRST FEFER3		;FAILED, RELEASE PAGES AND OFN; RETURN ERROR
	MOVEM A,OFNPT		;SAVE IT
	CALL UPDOFN		;INITIALIZE IT
	MOVE A,OFNPT		;GET THE OFN
	MOVEI B,0(P5)		;GET PAGE FOR THIS PT
	HRLI B,(PTRW)		;FULL ACCESS
	CALL SETMPG		;GET THE PAGE
	MOVEI D,1000		;SIZE OF A PT
	CAIGE P4,1000		;ROOM FOR ALL OF IT?
	MOVEI D,0(P4)		;NO
	SUBI P4,1000		;NUMBER LEFT TO DO
	MOVEI B,IMMCOD		;ALL POINTERS ARE IMMEDIATE

;WRITE A PAGE TABLE

FEFSY9:	MOVEM P2,0(P5)		;STORE SECTOR NUMBER
	STOR B,PTRCOD,(P5)	;MAKE IT IMMEDIATE
	ADD P2,SECPAG(Q2)	;GO TO NEXT PAGE
	SOJLE D,FEFS11		;MORE TO DO?
	ADDI P5,1
	JRST FEFSY9		;OFF TO STORE THEM ALL

FEFS11:	TRZ P5,777		;RESOTRE PAGE ADDRESS
	MOVEI B,0(P5)
	MOVE A,OFNPT		;GET OFN OF PT
	MOVX C,OFNWRB		;THE WRITE BIT
	IORM C,SPTH(A)		;SAY THE XB IS WRITTEN
	SETZ A,			;UNMAP THE PAGE
	CALL SETMPG		;DO IT
	MOVE A,OFNPT		;RESTORE OFN OF PT
	CALL RELOFN		;FREE IT
	JUMPG P4,FEFSY8		;DO THEM ALL
;HERE THE FILE IS CREATED. NOW RELEASE ALL SPACE AND RETURN

	TXZ Q3,777		;ADDRESS OF PTT IN CORE
	SETZ A,			;UNMAP THE PAGE
	MOVEI B,0(Q3)		;TO DO THE UNMAP
	CALL SETMPG		;DO IT
	MOVE A,OFNPTT		;OFN OF THE PTT
	CALL RELOFN		;DO IT
	MOVE A,Q3
	CALL RELPAG		;RELEASE ALL JSB SPACE
	MOVE A,P5
	CALL RELPAG		;THIS ONE TOO
	MOVE A,P3		;THE JFN
	RLJFN			;FREE THE JFN
	 JFCL
	MOVE A,STRN13		;A/STRUCTURE NUMBER
	CALL CPYBAK		;REMAKE BACKUP OF ROOT-DIRECTORY TO
				; POINT TO FRONT END FILE SYSTEM
	JRST [	MOVE A,STRN13	 ;GET STRUCTURE NUMBER
		HRRZ A,STRTAB(A) ;POINT TO ITS SDB
		LOAD A,STRUC,(A) ;GET ITS UNIQUE CODE
		BUG(FEOCPB,<<T1,D>>)
		JRST .+1]
	RETSKP			;AND DONE

FEFER3:	MOVE A,OFNPTT		;GET OFN
	CALL RELOFN		;RELEASE THE OFN
				;FALL INTO FEFER2

FEFER2:	MOVE A,P5		;GET ADDRESS OF ASSIGNED PAGE
	CALL RELPAG		;RELEASE THE PAGE
				;FALL INTO FEFER1

FEFERR:
FEFER1:	MOVE A,Q3		;GET ADDRESS OF ASSIGNED PAGE
	CALL RELPAG		;RELEASE THE PAGE

	SE1CAL			;FIXUP FOR SECTION 1 RETURNS TO 0
FEFER0:	RET
;ROUTINE TO WRITE FE BOOT BLOCK ON PACK WITH FE FILE SYSTEM.
;ACCEPTS:	A/ UDB
;RETURNS	+1 ALWAYS

WRBOOT:	SAVEP			;PRESERVE REGS
	MOVE P1,A		;SAVE UDB
	CALL ASGPAG		;GET A WORK PAGE
	 RET			;DON'T DO IT THEN
	MOVE P2,A		;SAVE PAGE ADDRESS
	HRLI A,BOOTST		;MOVE FE BOOT BLOCK
	BLT A,BOOTLN-1(P2)	;MOVE BOOT DATA
	MOVE A,P2		;THE ADDRESS AGAIN
	CALL MLKMA		;LOCK IT DOWN
	LSH A,PGSFT		;MAKE IT A CORE ADDRESS
	MOVE P3,A		;SAVE IT
	HRRZ A,UDBCDB(P1)	;GET CDB
	HRLZ D,CDBADR(A)	;GET CHANNEL ADDRESS
	HRR D,UDBADR(P1)	;GET UNIT ADDRESS
	SETZ A,			;DO BLOCK 0
	MOVE B,[1B0+1B14+HBLEN]	;WRITE ONE BLOCK
	MOVE C,P3		;THE PHYSICAL ADDRESS
	CALL UDSKIO		;WRITE IT OUT
	MOVE A,P3		;THE PHYSICAL ADDRESS
	LSH A,-PGSFT		;GET PAGE ADDRESS
	CALL MULKCR		;UNLOCK IT
	MOVE A,P2		;THE WORK PAGE
	CALLRET RELPAG		;GET RID OF IT

;THE BOOT DATA FOR THE FE
;THIS CODE IS POSITION INDEPENDENT AND IT CAN BE LOCATED ANYWHERE
;IN MEMORY (THAT IS THE CODE FROM BOOT11 DOWN.).



BOOTST:
BOOTBK:
BOOT11:	5,,12706		;RESET,MOVE #1000,SP
	1000,,10700		;MOV PC,R0
	62700,,36		;ADD #BOTMSG-.,R0
	112001,,1403		;MOVB (R0)+,R1,BEQ 20$
	4767,,4
	773,,0			;BR 10$,HALT
	110137,,177566		;MOVB R1,@#TPB
	105737,,177564
	100375,,207		;BPL 10$,RET
BTMSG:	5015,,20012
	20040,,25052
	52052,,44510
	20123,,47526
	52514,,42515
	42040,,42517
	20123,,47516
	20124,,47503
	52116,,44501
	20116,,20101
	40510,,42122
	40527,,42522
	41040,,47517
	40524,,46102
	20105,,54523
	52123,,46505
	25040,,25052
	5015,,12
BOOTLN==.-BOOTBK		;LENGTH OF THIS DATA BLOCK
;FEWRTH - SUBROUTINE TO WRITE THE HOME BLOCKS FOR THE FRONT END FILE
;BOWRTH - SUBROUTINE TO WRITE THE HOME BLOCKS FOR THE BOOTSTRAP FILE
;SYSTEM.

;ACCEPTS:
;	A/ VIRTUAL ADDRESS OF WORK PAGE
;	B/ ADDRESS OF SDBUDB FOR THE UNIT
;	C/ SECTOR NUMBER OF START OF FRONT END FILE SYSTEM
;	D/# OF PAGES IN FRONT END FILE SYSTEM

;	CALL FEWRTH
;	CALL BOWRTH

;RETURNS +1: FAILURE
;	 +2: SUCCESS

;THE CALLER HAS ESTABLISHED WHICH UNIT IS TO CONTAIN THE FRONT END OR BOOTSTRAP
;FILE SYSTEM.  THIS ROUTINE WRITES INTO THAT PACK'S HOME BLOCKS THE
;STARTING SECTOR AND LENGTH OF THE FRONT END FILE SYSTEM.

BOWRTH: SAVEPQ			;SAVE WORK CELLS
	SETZ Q2,0		;SET BOOT FLAG
	JRST FEWCOM		;GO TO COMMON PART
FEWRTH:	SAVEPQ			;SAVE WORK CELLS
	SETO Q2,0		;SET FE FLAG
FEWCOM:	SETZM P2		;INITIALIZE ERROR REGISTER
	MOVE Q3,A		;SAVE VIRTUAL ADDRESS OF WORK PAGE
	MOVE P4,B		;SDBUDB ADDRESS
	MOVE P1,C		;START SECTOR OF FRONT END FILE SYSTEM
	MOVE P3,D		;# OF PAGES IN FRONT END FILE SYSTEM
	CALL MLKMA		;LOCK IT DOWN FOR THE I/O
	LSH A,PGSFT		;MAKE PHYSICAL ADDRESS
	MOVE P5,A		;SAVE PHYSICAL ADDRESS OF WORK PAGE
	CALL FNDCHN		;GET CHANNEL,,UNIT 
	MOVEM A,Q1		;SAVE CHANNEL,,UNIT
	MOVE B,P5		;PHYSICAL ADDRESS OF WORK PAGE
	MOVEI C,HM1BLK		;HOME BLOCK SECTOR NUMBER
	MOVE D,Q3		;VIRTUAL ADDRESS OF WORK PAGE
	CALL REDHOM		;READ THE HOME BLOCKS
	 JRST [	SETOM P2	;NOTE FAILURE
		JRST FWRT10 ]	;GO UNLOCK THE PAGE
	MOVE A,P1		;SECTOR NUMBER OF START OF FEFS
	TLO A,(1B4)		;EXISTANT BIT
	SKIPN Q2		;CHECK FOR BOOT FLAG
	ADDI Q3,HOMFE2-HOMFE0	;CHEAT A LITTLE HERE TO POINT TO BOOT AREA IN HOME BLOCK
	DPB A,[POINT ^D16,HOMFE0(Q3),35] ;STORE IN FIRST HOME BLOCK
	DPB A,[POINT ^D16,HOMFE0+HBLEN(Q3),35] ;STORE IN 2ND HOME BLOCK
	LSH A,-^D16		;GET UPPER 16 BITS
	DPB A,[POINT ^D16,HOMFE0(Q3),17]
	DPB A,[POINT ^D16,HOMFE0+HBLEN(Q3),17]
	MOVE A,P3		;GET NUMBER OF PAGES
	MOVE B,STRTY1		;GET ADDRESS OF SIZE DATA FOR THIS DISK TYPE
	IMUL A,SECPAG(B)	;CONVERT PAGES TO SECTORS
	DPB A,[POINT ^D16,HOMFE1(Q3),35]
	DPB A,[POINT ^D16,HOMFE1+HBLEN(Q3),35]
	LSH A,-^D16
	DPB A,[POINT ^D16,HOMFE1(Q3),17]
	DPB A,[POINT ^D16,HOMFE1+HBLEN(Q3),17]
	MOVE A,P5		;A/ PHYSICAL ADDRESS FOR WORK PAGE
	MOVE B,Q1		;B/ CHANNEL,,UNIT
	CALL UPDHOM		;WRITE BOTH HOME BLOCKS TO THE DISK
	 SETOM P2		;NOTE OCCURRENCE OF ERROR
FWRT10:	MOVE A,P5		;GET CORE ADDRESS
	LSH A,-PGSFT		;MAKE IT A CORE PAGE NUMBER
	CALL MULKCR		;UNLOCK IT
	SKIPE P2		;ANY ERRORS FOUND ?
	RET			;AND DONE
	RETSKP			;NO, GIVE SUCCESS RETURN
;ROUTINE CALLED FROM FILINI AND MSTR TO PUT THE FRONT END FILE SYSTEM
;OR THE BOOTSTRAP.BIN FILE
;POINTERS INTO THE HOME BLOCK ON THE RELEVANT PACK. THIS IS
;CALLED WHENEVER THE MONITOR HAS BEEN REQUESTED TO REWRITE
;THE HOME BLOCKS, BUT NOT DO A FILE SYSTEM REFRESH.

;ACCEPTS:
;	A/STRUCTURE NUMBER

;RETURNS +1:  FAILURE
;	 +2: SUCCESS

FIXBOT::TDZA B,B		;SET BOOT FLAG
FIXFES::SETO B,			;SET FE FLAG
	SE1CAL
	TRVAR <STRTY1>		;ADDRESS OF SIZE DATA FOR THIS DISK TYPE
	STKVAR <STRN14,SVPAGE,SVSIZE,SVDISK,SVPHYS,NAMBLK,TYPBLK>
	MOVEM B,TYPBLK		;SAVE ENTRY FLAG
	MOVEM A,STRN14		;SAVE STRUCTURE NUMBER
	MOVEI B,^D12		;GET SOME FREE SPACE TO BUILD THE FILE
	CALL ASGJFR		; SPEC IN (INCLUDING STRUCTURE NAME)
	 RET			;FAILED TO GET IT
	MOVEM A,NAMBLK		;SAVE ADDRESS OF HEADER FOR STRING SPACE
	HRROI A,1(A)		;T1/ADDRESS OF FREE SPACE (AFTER HEADER)
	MOVE B,STRN14		;T2/STRUCTURE NUMBER
	HRROI C,[ASCIZ/<ROOT-DIRECTORY>FRONT-END-FILE-SYSTEM.BIN.1/]
	SKIPN TYPBLK		;CHECK FOR BOOTSTRAP FILE
	HRROI C,[ASCIZ/<ROOT-DIRECTORY>BOOTSTRAP.BIN.1/]
				;C/ NAME OF FILE WITHOUT STRUCTURE
	CALL STRST		;CREATE FILE SPEC INCLUDING THE STRUCTURE NAME
				; IN FREE SPACE POINTED TO BY NAMBLK
	 JRST FIXFE2		;FAILED. RELEASE SPACE AND RETURN
	MOVX A,GJ%OLD!GJ%SHT	;GTJFN ARGS
	HRRO B,NAMBLK		;B/ADDRESS OF FILE NAME
	ADDI B,1		;POINT BEYOND HEADER
	GTJFN			;GET A JFN FOR IT
	 JRST FIXFE2		;FAILED. RELEASE SPACE AND RETURN
	MOVEM A,SVPAGE		;STASH AWAY JFN
	MOVEI A,JSBFRE		;A/RETURNING SPACE IN JSB
	MOVE B,NAMBLK		;B/ADDRESS OF BLOCK
	CALL RELFRE		;RETURN THE FREE SPACE
	SETZM NAMBLK		;INITIALIZE ERROR FLAG
	MOVE A,SVPAGE		;RESTORE JFN
	IMULI A,MLJFN		;MAKE IT AN INTERNAL INDEX
	CALL GETFDT		;GO FIND FILE'S FDB
	 JRST [	MOVE A,SVPAGE	;GET JFN BACK AGAIN
		RLJFN		;RELEASE THE JFN
		 JFCL		;IGNORE FAILURE
		RET ]		;GIVE FAIL RETURN
	HRRZ B,.FBBYV(A)	;GET SIZE OF FILE
	MOVEM B,SVSIZE		;SAVE IT
	MOVE B,.FBADR(A)	;GET DISK ADDRESS
	MOVEM B,SVDISK		;REMEMBER IT
	CALL USTDIR		;DONE WITH THE DIRECTORY
	MOVE A,SVPAGE		;THE JFN
	RLJFN			;CLEAN IT UP
	 JFCL
	CALL ASGPAG		;GO GET A PAGE
	 RET			;FAILED, GIVE FAIL RETURN
	MOVEM A,SVPAGE		;REMEMBER IT
	CALL MLKMA		;LOCK IT DOWN
	LSH A,PGSFT		;MAKE IT  A CORE ADDRESS
	MOVEM A,SVPHYS		;REMEMBER IT
	MOVE C,A
	MOVE A,SVDISK		;THE ADDRESS
	MOVEI B,1000		;COUNT
	MOVE D,STRN14		;D/STRUCTURE NUMBER
	CALL UDSKIO		;READ IN INDEX
	SKIPGE A		;GOT IT?
FIXFE1:	JRST [	MOVE A,SVPHYS	;NO, GET PHYS ADR
		LSH A,-PGSFT	;CONVERT TO PAGE
		CALL MULKCR	;UNLOCK PAGE
		MOVE A,SVPAGE	;GET PAGE #
		CALLRET RELPAG]	;RELEASE THE PAGE AND RETURN FAILURE
	HRRZ A,SVPAGE		;GET ADDRESS OF FIRST INDEX BLOCK
	MOVE A,0(A)
	MOVEI B,1000
	MOVE C,SVPHYS		;THE PHYSICAL ADDRESS
	MOVE D,STRN14		;D/STRUCTURE NUMBER
	CALL UDSKIO
	JUMPL A,FIXFE1		;IF FAILED GO COMPLAIN
	MOVE A,SVPAGE		;GET ADDRESS OF FIRST PAGE
	MOVE A,0(A)
	TLZ A,DSKMSK		;ONLY USE GOOD BITS
	EXCH A,SVPHYS		;GET PHYSICAL ADDRESS
	LSH A,-PGSFT		;MAKE IT A PAGE ADDRESS
	CALL MULKCR		;FREE IT
	MOVE B,STRN14		;GET STRUCTURE NUMBER
	HRRZ D,STRTAB(B)	;FIND START OF SDB'S
	MOVE C,SDBTYP(D)	;POINT TO SIZE DATA FOR THIS DISK TYPE
	MOVEM C,STRTY1		;SAVE FOR FEWRTH
	MOVE A,SVPHYS		;GET DISK ADDRESS
	IDIV A,SECUNT(C)	;GET UNIT NUMBER
	MOVEI B,SDBUDB(D)	;THE FIRST ONE
	ADDI B,0(A)		;ADDRESS OF SDBUDB
	MOVE A,SVPAGE		;THE WORK ADDRESS
	MOVE C,SVPHYS		;FIRST SECTOR
	MOVE D,SVSIZE		;# OF PAGES
	SKIPN TYPBLK		;CHECK WHICH TO WRITE
	JRST [	CALL BOWRTH	;WRITE BOOT
		SETOM NAMBLK	;FAILED, NOTE ERROR
		JRST .+3]
	CALL FEWRTH		;GO FIX HOME BLOCK
	 SETOM NAMBLK		;FAILED, NOTE ERROR
	MOVE A,SVPAGE		;THE PAGE
	CALL RELPAG		;AND DONE
	SKIPE NAMBLK		;ANY ERRORS ?
	RET			;YES, RETURN FAILURE
	RETSKP			;NO, RETURN SUCCESS

;GOT AN ERROR AFTER THE CALL TO ASGJFR AND BEFORE THE CALL TO RELFRE
;RELEASE THE SPACE

FIXFE2:	MOVEI T1,JSBFRE		;T1/RETURNING SPACE IN THE JSB
	MOVE T2,NAMBLK		;T2/START OF BLOCK
	CALL RELFRE		;RELEASE THE SPACE WE GOT BEFORE
	RET
;GTFESZ - GET THE SIZE OF THE FRONT END FILE SYSTEM
;GTBTSZ - GET THE SIZE OF THE BOOTSTRAP FILE

;ACCEPTS:
;	T1/STRUCTURE NUMBER

;	CALL GTFESZ
;	CALL GTBTSZ

;RETURNS +1: INTERNAL ERROR
;	 +2: NO ERROR,
;		T1/NUMBER OF PAGES (0 IS POSSIBLE)

;THIS ROUTINE IS CALLED WHEN THE FILE SYSTEM IS BEING REFRESHED AND THE
;HOME BLOCKS ARE NOT BEING REWRITTEN. IT OBTAINS THE SIZE OF THE FRONT END
;FILE SYSTEM FROM THE HOME BLOCKS OF THE UNIT THAT CONTAINS THE FILE.
;THIS NUMBER WILL BE PASSED TO FEFSYS, WHICH CREATES THE FILE
;<ROOT-DIRECTORY>FRONT-END-FILE-SYSTEM.BIN.
;SINCE FEFSYS LOOKS FOR A DUAL-PORTED DRIVE, AND SINCE THE PACK THAT
;PRESENTLY CONTAINS THE FILE MAY NOT BE DUAL-PORTED, THE WORDS IN THE
;HOME BLOCK THAT POINT TO THE FRONT END FILE SYSTEM ARE ZEROED BY THIS
;ROUTINE. FEFSYS WILL REWRITE THE HOME BLOCKS FOR THE UNIT THAT IT PICKS.

GTBTSZ::TDZA T2,T2		;FLAG ENTRY TYPE
GTFESZ::SETO T2,0
	SE1CAL
	SAVEQ
	STKVAR <GTFEST,GTFEVA,GTFEPA,GTFECU,GTTYPE>
	MOVEM T2,GTTYPE		;SAVE ENTRY TYPE
	MOVEM T1,GTFEST		;SAVE STRUCTURE NUMBER
	NOINT			;NO INTERRUPTS WHILE FREE PAGE IS ASSIGNTED
	CALL ASGPAG		;GET A PAGE TO READ HOME BLOCKS INTO
	 RETBAD(,<OKINT>)	;FAILED. NO SPACE AVAILABLE
	MOVEM T1,GTFEVA		;SAVE VIRTUAL ADDRESS OF START OF PAGE
	CALL MLKMA		;LOCK DOWN THE PAGE INTO CORE
	LSH T1,PGSFT		;CONVERT PAGE NUMBER TO PHYSICAL ADDRESS
	MOVEM T1,GTFEPA		;SAVE PHYSICAL ADDRESS OF WORK PAGE
	MOVE T2,GTFEST		;GET STRUCTURE NUMBER
	MOVE T2,STRTAB(T2)	;POINT TO SDB FOR THIS STRUCTURE
	LOAD Q1,STRNUM,(T2)	;GET NUMBER OF UNITS IN THIS STRUCTURE
	MOVNS Q1		;GET NEGATIVE NUMBER
	HRLZS Q1		;SET UP AOBJN POINTER TO UNITS
	HRRI Q1,SDBUDB(T2)	;Q1/(-COUNT,,SDBUDB ADDRESS)
GTFES1:	MOVE T2,0(Q1)		;GET ADDRESS OF UDB FOR THIS LOGICAL UNIT
	HRRZ T1,UDBADR(T2)	;GET PHYSICAL UNIT NUMBER
	HRRZ T2,UDBCDB(T2)	;POINT TO CDB FOR THIS UNIT
	HRL T1,CDBADR(T2)	;T1/(CHANNEL,,UNIT)
	MOVEM T1,GTFECU		;SAVE FOR LATER
	MOVE T2,GTFEPA		;T2/PHYSICAL ADDRESS OF WORK PAGE
	MOVEI T3,HM1BLK		;T3/SECTOR NUMBER OF FIRST HOME BLOCK
	MOVE T4,GTFEVA		;T4/VIRTUAL ADDRESS OF WORK PAGE
	CALL REDHOM		;READ THE FIRST HOME BLOCK
	 JRST GTFES2		;DRIVE IS OFF-LINE. IGNORE IT
	MOVE T3,GTFEVA		;POINT TO START OF WORK PAGE
	SKIPN GTTYPE		;CHECK TYPE SO CORRECT WORD IS FOUND
	ADDI T3,HOMFE2-HOMFE0
	MOVE T2,HOMFE0(T3)	;GET NUMBER OF SECTORS IN FEFS
	TXNE T2,1B2		;DOES THIS PACK HAVE THE FRONT END FILE SYSTEM?
	JRST GTFES3		;YES. GO GET THE INFORMATION
GTFES2:	AOBJN Q1,GTFES1		;NO. GO TO NEXT UNIT
	SETZ Q3,		;INDICATE NO FRONT END FILE SYSTEM IN STRUCTURE
	JRST GTFES4		;GO CLEAN UP AND EXIT
;THIS UNIT HAS THE FRONT END FILE SYSTEM.  GET ITS SIZE IN SECTORS
;THEN CLEAR THIS FIELD IN THE HOME BLOCKS SO THAT FEFSYS CAN PUT THE
;FRONT END FILE SYSTEM IN WHATEVER PACK IT CHOOSES

GTFES3:	LDB Q3,[POINT ^D16,HOMFE1(T3),17]
	LSH Q3,^D16		;SHIFT LEFT HALF LEFT 16 BITS
	LDB T2,[POINT ^D16,HOMFE1(T3),35]
	IORM T2,Q3		;STORE RIGHT HALF IN RIGHT 16 BITS
	SETZM HOMFE0(T3)	;CLEAR THE STARTING SECTOR IN THE FIRST HOME BLOCK
	SETZM HOMFE0+HBLEN(T3)	;CLEAR IT IN THE SECOND HOME BLOCK
	SETZM HOMFE1(T3)	;CLEAR THE COUNT IN THE FIRST HOME BLOCK
	SETZM HOMFE1+HBLEN(T3)	;CLEAR IT IN THE SECOND HOME BLOCK
	MOVE T1,GTFEPA		;T1/PHYSICAL ADDRESS OF PAGE CONTAINING HOME BLOCKS
	MOVE T2,GTFECU		;T2/(CHANNEL,,UNIT)
	CALL UPDHOM		;REWRITE THE HOME BLOCKS
	 JFCL			;IGNORE FAILURE

;RELEASE THE PAGE AND EXIT

GTFES4:	MOVE T1,GTFEPA		;GET PHYSICAL ADDRESS OF START OF PAGE
	LSH T1,-PGSFT		;T1/PAGE NUMBER OF LOCKED PAGE
	CALL MULKCR		;UNLOCK THE CORE PAGE
	MOVE T1,GTFEVA		;T1/VIRTUAL ADDRESS OF WORK PAGE
	CALL RELPAG		;RELEASE THE PAGE IN JSB FREE SPACE
	OKINT			;ALLOW INTERRUPTS
	MOVE T2,GTFEST		;GET STRUCTURE NUMBER
	MOVE T2,STRTAB(T2)	;POINT TO SDB FOR THIS STRUCTURE
	MOVE T2,SDBTYP(T2)	;POINT TO SIZE DATA FOR THIS TYPE OF DISK
	MOVE T1,Q3		;GET SIZE IN SECTORS
	IDIV T1,SECPAG(T2)	;CONVERT TO NUMBER OF PAGES (FEWRTH MADE
				; IT AN INTEGRAL NUMBER)
	RETSKP			;TAKE SUCCESS RETURN

;THIS ROUTINE VERIFIES THE BAT BLOCKS.
;ACEPTS A/MASK RETURNED BY GETBAT
;	    B/CORE ADDRESS
;	    C/UDB POINTER
;
;RETURNS +1 NO GOOD BLOCKS
;	 +2 B POINTS TO A GOOD BAT BLOCK

VERBAT::SAVEP
	MOVE P2,C		; SAVE DRIVE
	MOVE P1,B		; SAVE ADDRESS
	MOVE P3,A		; SAVE MASK
	TLNN P3,(1B0)		; 1 OK?
	JRST NO1		; NO
	TLNE P3,(1B1)		; 2 OK?
	RETSKP			; ALL WELL
	MOVEI A,HBLEN(P1)	;CORE ADDRESS
	HRLI A,(P1)		; CORE ADDRESS OF PRIMARY
	BLT A,<2*HBLEN-2>(P1)	;COPY TO THE SECONDARY
	MOVEI A,BATBL1+HM2BLK-HM1BLK ;ADDRESS OF SECONDARY
	MOVEM A,BATBLK+HBLEN(P1) ;STORE BLOCK NUMBER
	RETSKP
NO1:	TLNN P3,(1B1)		; 2 GOOD?
	JRST [	MOVX A,US.BAT	;SAY NO BATS ON THIS GUY
		IORM A,UDBSTS(P2) ;MARK BIT
		BUG(BADBAT)
		RET]		;AND GIVE UP
	MOVEI A,(P1)
	HRLI A,HBLEN(P1)	;TO THE SECONDARY
	BLT A,<HBLEN-2>(P1)	;MOVE SECONDARY TO THE PRIMARY
	MOVEI A,BATBL1		;ADDRESS OF BAT BLOCK
	MOVEM A,BATBLK(P1)	;STORE BLOCK NUMBER
	RETSKP			;AND RETURN

;ROUTINE CALLED BY SYSERR POSTING ROUTINE TO MARK A DISK BAT
;BLOCK ON A "HARD" DISK ERROR. ACCEPTS:
;	1/ UDB POINTER
;	2/LOCAL LINEAR DISK ADDRESS
;
;RETURNS: +1 ALWAYS WITH BAT BLOCK UPDATED

BATQ::	SAVEP			;YES. SAVE SOME REGISTERS
	NOINT			; NO INTS WHILST PAGE IS LOCKED
	MOVEI P5,FPG3A		;ADDRESS OF BAT BLOCK
	MOVE P4,A		;SAVE UDB INDEX
	MOVE P3,B		;SAVE LOCAL DISK ADDRESS
	MOVEI A,FPG3A		;USE ALTERNATE XB PAGE
	CALL MLKMA		;LOCK IT DOWN
	LSH A,PGSFT		;MAKE IT A CORE ADDRESS
	MOVE P1,A		;SAVE IT
	MOVEI A,0(P4)		;UDB POINTER
	CALL LKBAT		;LOCK DOWN THE BAT BLOCK
;**;[3181]  Change 1 line at BATQ:+11			DML	7-Nov-84
	 JRST BATQE1		;[3181] FAILED. MUST BE DONE THEN
	MOVEI C,0(P4)		;UDB INDEX
	CALL FNDCH1		;GO GET CHANNEL,,UNIT
	MOVE P2,A		;SAVE CHANNEL,,UNIT
	MOVE B,P1		;PHYSICAL CORE ADDRESS
	MOVEI C,FPG3A		;VIRTUAL ADDRESS
	CALL GETBAT		;GET THE BAT BLOCKS
	MOVEI B,FPG3A		;VIRTUAL ADDRESS
	MOVEI C,0(P4)		;UDB INDEX
	CALL VERBAT		;GO VERIFY BAT BLOCKS
	 JRST BATQE		;ALL DONE
	; ..
	; ..

;HERE WHEN CORRECT BAT BLOCKS ARE IN FPG3A. P3=LOCAL DISK ADDRESS
;P4= UDB INDEX  P1=PHYSCIAL CORE ADDRESS P2=CHANNEL,,UNIT


GOTDRV:	MOVE A,P3		;GET LOCAL ADDRESS
	MOVEI B,FPG3A		;AND WHERE THE BAT BLOCK IS
	MOVE C,P4		;GET UDB ADDRESS
	CALL SEEADR		;SEE IF IN THE PAGE YET
	 JRST GTDRV1		;NO. MUST ADD IT THEN
	MOVE P3,A		;SAVE DISK ADDRESS
	MOVEI C,HBLEN(B)	;SET UP POINTER TO PAIR
	JRST UPDBLK		;GO SET VALUES

;MUST INSERT THE ADDRESS IN THE BAT BLOCK

GTDRV1:	MOVE P3,A		;SAVE DISK ADDRESS
	LOAD B,BTMCT,(P5)	;GET NUMBER OF PAIRS ADDED BY MONITOR
	JUMPE B,ADDPR		;NONE. MUST ADD A PAIR THEN
	MOVNI B,(B)		;GET NEG
	LOAD C,BTHCT,(P5)	;GET PAIRS ADDED BY MAPPER
	LSH C,1			;MAKE IT A WORD COUNT
	ADDI C,FPG3A+BAT1P	;GET START OF MONITOR PAIRS
	HRLI C,0(B)		;FORM AOBJN WORD

DOPAIR:	LOAD A,BATNB,(C)	;GET NUMBER OF BAD SPOTS IN THIS REGION
	CAILE A,MAXBAD-4	;ROOM FOR ANOTHER PAGE?
	JRST NXTPR		;NO. GO ON
	LOAD A,BADT,(C)		;GET TYPE OF THIS ENTRY
	SKIPE A			;OLD OR NEW?
	JRST [	LOAD A,ADD27,(C) ;NEW
		JRST DOPA1]	;GO INLINE
	LOAD A,ADD18,(C)	;OLD. GET SHORT ADDRESS
DOPA1:	LOAD D,BATNB,(C)	;GET NUMBER
	ADD D,A			;GET END ADDRESS
	ADDI D,1		;ONE MORE PLEASE
	SUBI A,4		;GET PREVIOUS PAGE
	CAMN A,P3		;IS THIS IMMEDIATELY PRECEEDING PAGE?
	JRST [	STOR P3,ADD27,(C) ;MAKE THIS THW NEW START
		MOVEI D,HBLEN(C) ;POINT TO THE SECONDARY
		STOR P3,ADD27,(D) ;UPDATE THE SECONDARY
		JRST CMNPAR]	;GO DO COMMON STUFF
	CAME D,P3		;AT THE END?
	JRST NXTPR		;NO. GO TO NEXT PAIR
CMNPAR:	LOAD B,BATNB,(C)	;GET COUNT
	ADDI B,4		;NEW COUNT
	STOR B,BATNB,(C)
	MOVEI D,1		;JUTS IN CASE
	STOR D,BADT,(C)		;MAKE IT A NEW TYPE
	ADDI C,HBLEN		;POINT TO THE SECONDARY
	STOR B,BATNB,(C)	;UPDATE THIS NODE COUNT
	STOR D,BADT,(C)		;AND SET TYPE
	JRST UPDBLK		;GO PUT IN COMMON STUFF
NXTPR:	AOS C
	AOBJN C,DOPAIR
	; ..

	; ..
;HERE IF MUST ADD A NEW PAIR
; TCO 4.2041  CALL BATSPC BEFORE BUMPING MONITOR-ADDED COUNT
; AND ADJUST ADDRESS CALCULATION SO LAST BAT ENTRY IS USED.

ADDPR:	MOVEI A,0(P5)		;ADDRESS OF BAT BLOCK
	CALL BATSPC		;CALCULATE SPACE LEFT FOR US
	LOAD B,BTMCT,(P5)	;GET COUNT ADDED BY MONITOR
	AOS B
	STOR B,BTMCT,(P5)	;UPDATE THIS
	STOR B,BTMC2,(P5)	;AND UPDATE THE SECONDARY
	SKIPN A			;ANY PAIRS LEFT?
	JRST RLSNOD		;NO. GO GIVE IT UP THEN
	MOVEI C,MAXBFR(A)	;ROOM USED
	ADDI C,BAT1P+FPG3A	;GET REAL ADDRESS OF PAIR(TCO 4.2041 ADJUSTMENT)
	MOVEI B,3		;NUMBER IN REGION
	MOVEI A,1		;FOR TYPE
	STOR B,BATNB,(C)
	STOR P3,ADD27,(C)	;STORE ADDRESS
	STOR A,BADT,(C)		;STORE THE TYPE
	ADDI C,HBLEN		;POINT TO SECONDARY
	STOR B,BATNB,(C)	;INTO SECONDARY AS WELL
	STOR P3,ADD27,(C)
	STOR A,BADT,(C)
UPDBLK:	MOVEI D,-HBLEN(C)	;POINT TO PRIMARY
	MOVEI A,1		;A BIT TO SHIFT
	MOVEI B,0(P2)		;UNIT NUMBER OF THIS DRIVE
	LSH A,PUBCNT(B)		;POSITION THE BIT
	IORM A,0(C)		;MERGE IT INTO THE BLOCK
	IORM A,0(D)		;AND THE PRIMARY AS WELL
	CALL GAPRID		;GET APR SERIAL NUMBER
	STOR A,APRNM,(C)	;AND STASH IT IN THE ENTRY
	STOR A,APRNM,(D)	;AND IN THE PRIMARY AS WELL
	MOVE A,UDBCDB(P4)	;GET ADDRESS OF CDB
	MOVE A,CDBADR(A)	;GET MASSBUS CONTROLLER #
	STOR A,BTKNM,(C)	;TO THE BAT BLOCK
	STOR A,BTKNM,(D)	;AND THE OTHER AS WELL

;NOW WRITE THE BAT BLOCK OUT

RLSNOD:	MOVE A,P2		;GET CHANNEL,,UNIT
	MOVE C,P1		;PHYSICAL CORE ADDRESS
	CALL BATOUT		;WRITE THEM
	 JFCL			;CAN'T DO MUCH ABOUT IT

BATQE:	MOVE A,P1
	LSH A,-PGSFT		;GET CORE PAGE NUMBER
	CALL MULKCR		;RELEASE IT
	MOVEI T1,0(P4)		;THE UDB INDEX
	CALL ULKBAT		;FREE THE BAT BLOCKS
	OKINT			;AND ALLOW INTS NOW
	RET

;**;[3181]  Add 5 lines after BATQE:+6			DML	7-Nov-84
BATQE1:	MOVE A,P1		;[3181] 
	LSH A,-PGSFT		;[3181] GET CORE PAGE NUMBER
	CALL MULKCR		;[3181] RELEASE IT
	OKINT			;[3181] AND ALLOW INTS NOW
	RET			;[3181] 
   REPEAT 0,<
;ROUTINE TO WRITE OUT THE IN CORE BAT BLOCK IF IT HAS BEEN CHANGED

CLRPAG:	JUMPL P2,R		;IF NO BAT BLOCKS, RETURN
	TLNN P2,(1B1)		;HAS IT BEEN WRITTEN?
	JRST CLRPG1		;NO. JUTS UNLOCK IT
	MOVEI A,0(P2)		;YES. GET UNIT
	MOVE C,P1		;AND CORE ADDRESS
	CALL BATOUT		;AND WRITE THEM OUT
	 JFCL			;DONT CARE HERE
CLRPG1:	HRRZ A,DRIVTB(P2)	;GET UNIT ID
	CALL ULKBAT		;RELEASE THE BAT BLOCKS
	SETO P2,		;SAY NO CURRENT UNIT
	RET			;AND DONE
   >				;END OF REPEAT 0
;ROUTINE TO ASSIGN THE SWAPPING BLOCKS
;ACCEPTS:
;	T1/STRUCTURE NUMBER
;	CALL SWPASN
;RETURNS +1: FAILED TO ASSIGN ONE OR MORE SWAPPING PAGES
;	 +2: SUCCESS

SWPASN:	SAVEQ
	STKVAR <STRN15,STRTP,STRPTR,SWPAER>
	SETZM SWPAER		;INITIALLY NO ERRORS
	MOVEM T1,STRN15		;SAVE STRUCTURE NUMBER
	MOVE T1,STRTAB(T1)	;POINT TO SDB FOR THIS STRUCTURE
	MOVEM T1,STRPTR		;SAVE POINTER
	SKIPN SDBNSS(T1)	;ANY SWAPPING ON THIS STRUCTURE ?
	RETSKP			;NO, RETURN
	MOVE T2,SDBTYP(T1)	;POINT TO SIZE DATA FOR THIS DISK TYPE
	MOVEM T2,STRTP		;SAVE POINTER
	MOVN Q1,SDBNUM(T1)	;Q1/(-NO. PACKS IN STRUCTURE,,PACK NO.)
	HRLZS Q1		;FOR ALL PACKS

;LOOP THROUGH UNITS, ASSIGNING SWAPPING PAGES

SWPAS1:	MOVE Q2,SECUNT(T2)	;GET # OF SECTORS PER UNIT
	IMULI Q2,0(Q1)		;GET LOGICAL ADR OF START OF THIS PACK
	ADD Q2,SDBFSS(T1)	;GET START OF SWAPPING SPACE ON UNIT
	MOVE Q3,SDBNSS(T1)	;GET # OF SWAPPING SECTORS PER UNIT
	ADD Q3,SECPAG(T2)	;MAKE SURE TO EVEN UP TO FULL PAGE
	SUBI Q3,1
	MOVE T1,Q3		;GET # OF SECTORS FOR SWAPPING
	IDIV T1,SECCYL(T2)	;GET # OF PAGES FOR SWAPPING
	MOVE Q3,T1		;COULD NOT DO A IDIV TO Q3

;FOR A UNIT, ASSIGN EACH SWAPPING PAGE

SWPAS2:	MOVE T1,Q2		;GET NEXT PAGE TO BE ASSIGNED
	MOVE T2,STRN15		;T2/STRUCTURE NUMBER
	CALL CYLASA		;ASSIGN THE PAGE
	 SETOM SWPAER		;INDICATE FAILURE
	MOVE T1,STRPTR		;RESTORE POINTER TO SDB FOR STRUCTURE
	MOVE T2,STRTP		;RESTORE POINTER TO SIZE DATA
	ADD Q2,SECCYL(T2)	;STEP TO THE NEXT PAGE
	SOJG Q3,SWPAS2		;LOOP BACK FOR ALL PAGES ON UNIT

	AOBJN Q1,SWPAS1		;LOOP BACK FOR ALL UNITS
	SKIPE SWPAER		;WERE THERE ANY ERRORS?
	RETBAD			;YES. TAKE FAILURE RETURN
	RETSKP			;NO. TAKE SUCCESS RETURN
;VARIABLES USED BY FSIINI ROUTINE

CTYFIL==6			;FILLER CHARACTERS NEEDED FOR CTY

;HOME BLOCK DEFINITIONS

CODHOM==:707070			;HOME BLOCK SPECIAL CODE
HBLEN==:200			;LENGTH OF HOME BLOCK
HM1BLK==:1			;BLOCK # OF FIRST HOME BLOCK
HM2BLK==:^D10			;BLOCK # OF SECOND HOME BLOCK

HOMNAM==:0			;SIXBIT /HOM/
HOMID==:1			;SIXBIT /ID/
HOMPHY==:2			;PHYSICAL ADR'S OF HOME BLOCKS
HOMSNM==:3			;SIXBIT /STRUCTURE NAME/
HOMLUN==:4			;XWD TOTAL PACKS, LOGICAL PACK #
HOMHOM==:5			;BLOCK # OF HOME BLK,, BLK # OF OTHER HB
HOMP4S==:6			;# OF PAGES FOR SWAPPING ON EACH UNIT
HOMFST==:7			;FIRST SWAPPING TRACK ON EACH UNIT
HOMRXB==:10			;ADR OF INDEX BLOCK OF ROOT DIRECTORY
HOMBXB==:11			;INDEX BLOCK ADR OF BACKUP FILE
HOMFLG==:12			;FLAGS
HOMSIZ==:13			;SIZE OF A UNIT IN SECTORS (BLOCKS)
HOMBTB==:14			;SIZE OF TOP HALF OF BIT TABLE (NUMBER OF TRACKS)
HOMMID==:15			;MEDIA IDENTIFICATION (PACK UNIQUE CODE)

HOMFE0==:61			;FE FILE SYSTEM WORD ONE (SECTOR #)
HOMFE1==:62			;FE FILE SYSTEM WORD TWO (# OF SECTORS)

;HOME BLOCK LOCATIONS 61-100 ARE RESERVED FOR THE FRONT-END.

HOMFE2==:101			;BOOTSTRAP.BIN WORD ONE (SECTOR #)
HOMFE3==:102			;BOOTSTRAP.BIN WORD TWO (# OF SECTORS)
HOMUID==:165			;UNIT ID
HOMOID==:170			;OWNER ID
HOMFSN==:173			;FILE SYSTEM TYPE
HOMCOD==:176			;0 ,, CODHOM
HOMSLF==:177			;THIS HOME BLOCK #
;ROUTINE TO DO THE FIRST PHASE OF THE FILE SYSTEM INITIALIZATION
;FOR THE PUBLIC STRUCTURE (CALLED ONLY ON SYSTEM STARTUP)
;IF THE FILE SYSTEM IS BEING INITIALIZED (STARTED AT SYSLOD),
;THEN A DIALOGUE IS ENTERED TO REWRITE THE HOME BLOCKS ON THE
;PUBLIC STRUCTURE
;WHEN THE STRUCTURE IS DEFINED, OR IF NORMAL STARTUP IS DONE, THE
;SDB AND STRTAB ENTRY ARE CREATED FOR THE PUBLIC STRUCTURE.  IT IS
;ASSUMED TO BE PS, BUT THE USER MAY SPECIFY AN ALTERNATIVE.

	RESCD(INIT)

;DISC ADDRESS OF INDEX FILE

DIDSC0==:5740			;ROOT-DIR XB IS IN A FIXED PLACE 
DIDSC1==:13700			;BACKUP ROOT-DIR XB IS ALSO FIXED

DIDSCI::DIDSC0+DSKAB
DIDSCJ::DIDSC1+DSKAB		;BACKUP OF ROOT-DIR IS IN FIXED PLACE
;RS DIDSCA,1

;THIS ROUTINE USES "STARTF" TO TELL IF FILE SYSTEM IS BEING INITIALIZED.
;	0 MEANS NOT REFRESHING (STARTED AT SYSGO1),
;	MI%RFS MEANS REFRESHING (STARTED AT SYSLOD)

;	CALL FSIINI

;RETURNS +1:	ALWAYS

FSIINI::SAVEP
	TRVAR <FSIPPG,FSIPPA,FSIDIC,FSICHN,FSIUNT,FSINAM,FSIFLG,FSINPK,FSIUSZ,FSISWP,FSITYP>
	MOVEI T1,HOMPGA		;GET A PAGE LOCKED DOWN TO DO IO INTO
	CALL MLKMA		;LOCK IT INTO PHYSICAL PAGE
	MOVEM T1,FSIPPG		;SAVE PHYSICAL PAGE NUMBER
	LSH T1,PGSFT		;GET PHYSICAL ADDRESS ALSO
	MOVEM T1,FSIPPA		;SAVE PHYSICAL ADR OF IO PAGE
	HRROI T1,[ASCIZ/
/]
	CALL FSIPSO		;START AT THE BEGINNING OF A NEW LINE
FSIIN0:	SKIPN T1,LPSNAM		;IS THERE A LOGICAL PS NAME?
	MOVE T1,PSNAM		;NO, THE PUBLIC STRUCTURE IS ALWAYS PS
	MOVEM T1,FSINAM		; BY DEFAULT (USER MAY CHANGE IT)
	SKIPE STARTF		;IS THE FILE SYSTEM BEING INITIALIZED
	CALL FSIDIA		;YES, DO THE INITIALIZATION DIALOGUE
	CALL CHKHOM		;GO READ HOME BLOCKS AND CHECK THEM
	 JRST FSIIN1		;NO PUBLIC STR FOUND, GO COMPLAIN
	;..
	;..
REPEAT 0,<
	HRROI T1,[ASCIZ/
[/]
	CALL FSIPSO		;START STR MESSAGE
	MOVSI P1,-STRN		;NOW TYPE OUT THE STR'S THAT ARE MOUNTED
	SETZ P2,		;FIRST COUNT THEM
FSINR1:	SKIPE STRTAB(P1)	;IS THERE A STR DEFINED HERE?
	AOS P2			;YES, COUNT IT
	AOBJN P1,FSINR1		;LOOP FOR ALL STRUCTURES
	MOVSI P1,-STRN		;NOW TYPE NAMES
FSINR2:	SKIPN T2,STRTAB(P1)	;GET POINTER TO SDB
	JRST FSINR3		;NO STR HERE
	MOVE T1,SDBNAM(T2)	;GET NAME OF STR
	CALL FSI6TY		;TYPE OUT NAME
	SOJLE P2,FSINR4		;ANY MORE LEFT?
	HRROI T1,[ASCIZ/, /]	;ASSUME MORE THAN ONE LEFT
	CAIN P2,1		;UNLESS THERE IS EXACTLY 1 LEFT
	HRROI T1,[ASCIZ/, AND /]
	CALL FSIPSO		;TYPE OUT COMMA BETWEEN STR NAMES
FSINR3:	AOBJN P1,FSINR2		;LOOP BACK FOR OTHER STR NAMES
FSINR4:	HRROI T1,[ASCIZ/ MOUNTED]
/]
	CALL FSIPSO		;END MESSAGE
>

	HRROI T1,[ASCIZ/
[/]
	CALL FSIPSO		;START WITH A NEW LINE
	MOVE P1,STRTAB+PSNUM	;POINT TO SDB FOR PUBLIC STRUCTURE
	MOVE P1,SDBNAM(P1)	;GET ITS NAME
	MOVE T1,P1		;PRINT ITS NAME
	CALL FSI6TY
	HRROI T1,[ASCIZ/ MOUNTED/] ;SAY IT IS MOUNTED
	CALL FSIPSO
	CAMN P1,PSNAM		;IS ITS NAME 'PS'?
	JRST FSIIN2		;YES. JUST SAY IT IS MOUNTED
	HRROI T1,[ASCIZ/ AS /]	;NO. SAY IT IS MOUNTED AS PS
	CALL FSIPSO
	MOVE T1,PSNAM		;GET 'PS'
	CALL FSI6TY		;PRINT IT
FSIIN2:	HRROI T1,[ASCIZ/]
/]
	CALL FSIPSO		;END THE LINE
	MOVEI T1,HOMPGA		;UNLOCK THE IO PAGE
	CALL MULKMP		;...
	SKIPE STARTF		;IF SYSTEM BEING INIT'ED, 
	JRST [	MOVEI T1,PSNUM	;T1/STRUCTURE 0 (PUBLIC STRUCTURE)
		CALL FSIBAT	; INIT BAT BLOCKS FOR PS
		JRST .+1]
	MOVE T2,CTYLNO		;WAIT FOR MESSAGES TO FINISH
	CALL STADYN		;POINT TO DYNAMIC DATA
	 BUG(TTNAC5)
	CALL TTSOBE		;SEE IF OUTPUT BUFFER IS EMPTY
	JRST .-1		;LOOP UNTIL THEY ARE TYPED
	RET			;ALL DONE

FSIIN1:	HRROI T1,[ASCIZ/
HAVE THE PROBLEMS MENTIONED ABOVE BEEN CORRECTED YET: /]
	HRROI T2,[ASCIZ/
[WHEN ALL OF THE PROBLEMS ARE CORRECTED, TYPE "Y".
 IF STRUCTURES NEED DEFINING, THEN FOLLOW THE FILE SYSTEM 
 INITIALIZATION PROCEDURE.]
/]
	MOVEI T3,FSIYNO		;YES OR NO ANSWER WANTED
	CALL FSIASK		;GO ASK QUESTION
	 JRST FSIIN1		;ERROR, REPEAT QUESTION
	JUMPE T1,FSIIN1		;IF NO, REPEAT QUESTON UNTIL YES
	JRST FSIIN0		;START OVER AGAIN
;ROUTINE TO READ ALL HOME BLOCKS AND CHECK THEIR CONSISTENCY
;THIS ROUTINE BUILDS STRTAB AND THE SDB'S FOR EACH STRUCTURE
;	CALL CHKHOM
;RETURNS +1:	SOMETHING IS AMISS - A MESSAGE WAS TYPED ALREADY
;	 +2:	STRTAB AND SDB'S ARE SET UP

;USE OF NON-TEMPORARY REGISTERS:
;	P1/(-MAXIMUM CHANNEL NUMBER,,CURRENT CHANNEL NUMBER)
;	P2/(-MAXIMUM UNIT WITHIN CHANNEL,,CURRENT UNIT)
;	Q3/ADDRESS OF UDB

CHKHOM:	SAVEPQ			;SAVE PERMANENT ACS
	STKVAR <CHKHOE>
CHKH20:	SETOM CHKHOE		;INITIALIZE ERROR WORD TO "TRUE"
	MOVSI T1,-STRN		;INITIALIZE THE STRTAB TO ZERO
	SETZM STRTAB(T1)	;ZERO STRTAB
	AOBJN T1,.-1		;...
	MOVN P1,MAXCHN		;SET UP TO READ EVERY HOME BLOCK
	HRLZS P1		;GET AOBJN COUNTER OF CHANNELS

;LOOP THROUGH CHANNELS
;	P1/(NEGATIVE COUNT,,CURRENT CHANNEL)

CHKHO2:	MOVSI P2,-MAXRH		;GET COUNTER OF UNITS PER CHANNEL

;LOOP THROUGH UNITS
;	P2/(NEGATIVE COUNT,,CURRENT UNIT)

CHKHO3:	SETZ P3,		;INITIALIZE FLAGS
	SKIPN Q1,CHNTAB(P1)	;NOW FIND UDB FOR THIS UNIT
	JRST CHKHO4		;NO CDB FOR THIS CHANNEL
	MOVEI Q3,CDBUDB(Q1)	;GET ADR OF UDB TABLE IN CDB
	ADDI Q3,0(P2)		;ADD IN THE UNIT NUMBER
	SKIPN Q3,0(Q3)		;IS THERE A UDB?
	JRST CHKHO4		;NO
	LOAD T1,USTYP,(Q3)	;GET DEVICE TYPE
	MOVSI T2,-NDSKUT	;CHECK IF FILE DISK
	CAME T1,DSKUTP(T2)	; ...
	AOBJN T2,.-1
	SKIPL T2		;FOUND?
	JRST CHKHO4		;NO
	HRL T1,P1		;GET CHANNEL NUMBER
	HRR T1,P2		;AND UNIT NUMBER
	MOVE T2,FSIPPA		;GET PAGE FOR IO
	MOVEI T3,HM1BLK		;GET HOME BLOCK NUMBER
	MOVEI T4,HOMPGA		;GET VIRTUAL PAGE ADR TO READ INTO
	CALL REDHOM		;READ IN THE HOME BLOCKS
	 JRST CHKHO4		;ERROR OR OFF-LINE
	MOVEI T1,HOMPGA		;NOW CHECK THE FIRST HOME BLOCK
	MOVEI T2,HM1BLK		;...
	CALL HBCCHK		;CHECK THE CONSISTENCY CHECKS
	 TXZA P3,HB%1OK		;HOME BLOCKS BAD
	TXO P3,HB%1OK		;HOME BLOCK IS GOOD
	MOVEI T1,HOMPGA+HBLEN	;NOW CHECK THE BACKUP HOME BLOCK
	MOVEI T2,HM2BLK
	CALL HBCCHK
	 TXZA P3,HB%2OK		;BACKUP HOME BLOCK IS BAD
	TXO P3,HB%2OK		;BACKUP HOME BLOCK IS GOOD
	TXNE P3,HB%2OK		;ARE THERE ANY GOOD HOME BLOCKS
	HRRI P3,HOMPGA+HBLEN	;YES, GET ADR OF HOME BLOCK
	TXNE P3,HB%1OK		;SEE IF PRIMARY IS GOOD
	HRRI P3,HOMPGA		;YES, USE IT
	TRNN P3,-1		;ANY HOME BLOCKS GOOD?
	JRST CHKHO4		;NO, STEP TO NEXT UNIT
	MOVX T1,US.WLK		;SEE IF THIS UNIT IS WRITE LOCKED
	TDNE T1,UDBSTS(Q3)	;...
	TXO P3,HB%WLK		;YES, SET WRITE LOCKED FLAG
	HRRZ T1,P3		;GET ADDRESS OF HOME BLOCK
	MOVE T1,HOMSNM(T1)	;GET THE NAME OUT OF THE HOME BLOCK
	CAME T1,FSINAM		;IS IT THE ONE WE WANT FOR THE PUBLIC STRUCTURE?
	JRST CHKHO4		;NO. DON'T BUILD AN SDB, THEN
	SETZ T4,		;INDICATE NO COPYING REQUIRED
	TXNN P3,HB%1OK		;WAS FIRST HOME BLOCK OK?
	MOVEI T4,CPYH2		;NO. SET UP TO COPY THE SECONDARY
	TXNN P3,HB%2OK			;WAS SECOND HOME BLOCK OK?
	MOVEI T4,CPYH1		;NO. SET UP TO COPY PRIMARY
	JUMPE T4,CHKHO8		;BOTH OK. DON'T COPY EITHER
	MOVX T1,MI%MSG		;T1/ASK FOR MESSAGE
	HRRI T1,HOMPGA		;T1/VIRTUAL START OF WORK PAGE
	MOVE T2,FSIPPA		;T2/PHYSICAL START OF WORK PAGE
	HRL T3,P1		;T3/(CHANNEL,,UNIT)
	HRR T3,P2
	CALL @T4		;COPY THE GOOD ONE INTO THE BAD ONE
	 JRST CHKHO8		;FAILED. LEAVE ERROR BITS SET
	MOVX T4,HB%1OK!HB%2OK	;OK. CLEAR ERROR BITS
	IORM T4,P3
CHKHO8:	MOVE T1,P3		;T1/(FLAGS,,ADR OF HOME BLOCK)
	MOVE T2,Q3		;T2/ADDRESS OF UDB FOR THIS UNIT
	CALL BLDSTR		;GO BUILD STRTAB AND SDB
				; RETURNS ADDRESS OF SDB IN T1
	 JRST CHKHO4		;RAN OUT OF STR'S

;SDB BUILT AND STRTAB POINTS TO IT.  STORE POINTER TO UDB+FLAGS IN SDBUDB

	MOVE T2,Q3		;GET ADDRESS OF UDB
	HLL T2,P3		;SAVE FLAGS FOR THIS UNIT
	HRRZ T3,HOMLUN(P3)	;GET LOGICAL UNIT # OF THIS UNIT
	ADDI T3,SDBUDB(T1)	;GET INDEX INTO SDB FOR THIS UNIT
	SKIPE 0(T3)		;GET CURRENT UDB ADR
	TXO T2,HB%MUN		;MARK THAT THERE ARE MULTIPLE UNITS
	IORM T2,0(T3)		;STORE UDB ADR AND FLAGS IN SDBUDB
CHKHO4:	AOBJN P2,CHKHO3		;STEP TO NEXT UNIT
	AOBJN P1,CHKHO2		;THEN STEP CHANNEL NUMBER
	;..
;LOOP THROUGH STRUCTURES CHECKING FOR CONSISTENCY AND COMPLETENESS

	;..
	MOVSI P1,-STRN		;SET UP TO LOOK AT STRTAB
CHKHO5:	SKIPN P2,STRTAB(P1)	;IS THIS STR DEFINED?
	JRST CHKHO7		;NO, SKIP IT
	MOVEI T1,540000		;MAKE INTO 5B2+40000+STR NUMBER
	STOR T1,STRUC,(P2)	;STORE UNIQUE CODE IN STRUCTURE DATA BLOCK
	HRRZ T1,P1		;GET STRUCTURE NUMBER
	STOR T1,STRUS,(P2)	;PUT THE STR NUMBER INTO STRUC
	MOVE T1,SDBSTS(P2)	;GET FLAGS
	TXNE T1,HB%HBM		;IS THERE ANY INCONSISTENCY IN HOME B'S
	JRST CHKH16		;YES, GO COMPLAIN
	TXNE T1,MI%MXB		;IS BIT TABLE TOO BIG?
	JRST CHKH40		;YES. GO COMPLAIN
	MOVN P3,SDBNUM(P2)	;GET NUMBER OF PACKS IN THIS STR
	HRLZS P3		;SET UP AOBJN COUNTER
	HRR P3,P2		;GET ADR OF SDB

;LOOP THROUGH LOGICAL UNITS

CHKHO6:	SKIPN T1,SDBUDB(P3)	;IS THERE A UNIT?
	JRST CHKH11		;NO, MISSING UNIT
	TXNE T1,HB%MUN		;MULTIPLE UNIT?
	JRST CHKH12		;YES, GO COMPLAIN
	TXNE T1,HB%WLK		;WRITE LOCKED?
	JRST CHKH17		;YES

;STORE INTO UDBSTR (UNIT WITHIN STRUCTURE,,STRUCTURE NUMBER)

	MOVEM P1,UDBSTR(T1)	;STORE STRUCTURE NUMBER IN RH
	MOVEI T2,0(P3)		;ADDRESS OF SDB FOR THIS STRUCTURE PLUS UNIT NO.
	SUBI T2,0(P2)		;MINUS ADDRESS OF SDB FOR THIS STRUCTURE
	HRLM T2,UDBSTR(T1)	;STORE UNIT NUMBER IN LH

	TXNN T1,HB%1OK		;GOOD PRIMARY HOME BLOCK?
	JRST CHKH13		;NO
	TXNN T1,HB%2OK		;GOOD BACKUP HOME BLOCK?
	JRST CHKH14		;NO
CHKH6A:	AOBJN P3,CHKHO6		;CHECK OTHER UNITS IN STR
CHKHO7:	AOBJN P1,CHKHO5		;LOOP FOR ALL STR'S
	;..
	;..

;ALL PACKS HAVE BEEN READ.  IF THE SPECIFIED STRUCTURE WAS FOUND, THERE
;IS AN SDB FOR IT.  IT MUST HAVE SWAPPING SPACE

	SKIPE T1, STRTAB+PSNUM	;HAVE WE FOUND THE PUBLIC STRUCTURE?
	JRST CHKH10		;YES.
CHKHO9:	MOVE T1,FSINAM		;GET NAME OF STRUCTURE WE WERE LOOKING FOR
	CALL FSI6TY		;TYPE IT OUT
	HRROI T1,[ASCIZ/ NOT FOUND. WHAT IS THE NAME OF THE PUBLIC STRUCTURE? /]
	HRROI T2,[ASCIZ/
TYPE THE NAME OF A STRUCTURE THAT IS ON-LINE AND HAS SWAPPING SPACE
/]
	MOVEI T3,FSIDEV		;GET A SIXBIT DEVICE NAME
	CALL FSIASK		;GET THE NAME OF THE PUBLIC STRUCTURE
	 JRST CHKHO9		;FAILED. TRY AGAIN
	JUMPE T1,CHKHO9		;GAVE NO NAME. TRY AGAIN
	MOVEM T1,FSINAM		;SAVE THE NAME AND GO TRY TO FIND
	JRST CHKH20		; THIS STRUCTURE

;A STRUCTURE IS DEFINED. SEE IF IT HAS SWAPPING SPACE

CHKH10:	SKIPE T2,SDBNSS(T1)	;# OF SWAPPING SECTORS
	JRST CHKH30		;HAS SWAPPING. THIS IS THE PUBLIC STRUCTURE
CHKH21:	MOVE T1,FSINAM		;NO. SWAPPING. COMPLAIN
	CALL FSI6TY
	HRROI T1,[ASCIZ/ DOES NOT HAVE SWAPPING SPACE. WHAT IS NAME OF THE PUBLIC STRUCTURE? /]
	HRROI T2,[ASCIZ/
TYPE THE NAME OF A STRUCTURE THAT IS ON-LINE AND HAS SWAPPING SPACE
/]
	MOVEI T3,FSISIX		;GET A SIXBIT NAME
	CALL FSIASK		;GET THE NAME OF THE PUBLIC STRUCTURE
	 JRST CHKH21		;FAILED. TRY AGAIN
	JUMPE T1,CHKH21		;GAVE NO NAME. TRY AGAIN
	MOVEM T1,FSINAM		;SAVE THE NAME
	JRST CHKH20		;GO TRY TO FIND THIS STRUCTURE

;THIS STRUCTURE IS OK. MAKE IT THE PUBLIC STRUCTURE

CHKH30:	MOVEM T2,NSSUN		; IN THE PUBLIC STRUCTURE
	MOVE T2,SDBFSS(T1)	;FIRST SWAPPING SECTOR
	MOVEM  T2,FSSUN		; IN THE PUBLIC STRUCTURE
	MOVX T2,MS%DOM		;SAY THAT THIS IS A DOMESTIC STRUCTURE
	IORM T2,SDBSTS(T1)
	SKIPN CHKHOE		;WAS THERE AN ERROR DURING CHKHOM?
	RET			;YES
	RETSKP			;NO
REPEAT 0,<

;NOW SEARCH FOR A PUBLIC STR (NEEDED FOR SWAPPING)

	SETZ P3,		;INITIALIZE TO SAY NO PUB BIT YET
	MOVSI P1,-STRN
CHKHO8:	SKIPN P2,STRTAB(P1)	;IS THIS STR DEFINED?
	JRST CHKHO9		;NO
	MOVE T2,SDBNAM(P2)	;GET STRUCTURE NAME
	MOVE T1,SDBSTS(P2)	;GET FLAGS
	TXNE T1,HB%PUB		;IS THIS THE PUBLIC STR?
	JRST CHKH20		;YES!
	came t2,psnam		;no. is it ps?
	JRST CHKHO9		;NO. KEEP LOOKING
	HRROI T1,[ASCIZ/? THERE IS A NON-PUBLIC PS MOUNTED.
/]
	CALL FSIPSO		;YES. PRINT A MESSAGE
	RET

;A STRUCTURE HAD THE PUB BIT SET.  THIS QUALIFIES TO BE PS

CHKH20:	CAMN T2,PSNAM		;IS IT PS?
	JRST [	MOVEM P1,P3	;YES. SAVE ITS LOCATION
		JRST CHKHO9]	;GO TO THE NEXT STRUCTURE
	SKIPN P3		;NO. HAVE WE FOUND A CANDIDATE?
	MOVEM P1,P3		;NO. SAVE THIS ONE
CHKHO9:	AOBJN P1,CHKHO8		;LOOP FOR ALL STR'S
	SKIPE P1,P3		;DID WE FIND A PUB BIT?
	JRST CHKH10		;YES. GO MAKE IT BE STRUCTURE 0

;NO STRUCTURE HAD THE PUB BIT SET

	HRROI T1,[ASCIZ/? NO PUBLIC STRUCTURE MOUNTED.
/]
	CALL FSIPSO		;NO PUBLIC STR IS A FATAL ERROR
	RET

;FOUND A STRUCTURE WITH HB%PUB SET. MAKE IT BE STRUCTURE 0  
;P1 POINTS TO PS IF THERE WAS ONE, FIRST PUBLIC STRUCTURE OTHERWISE

CHKH10:	MOVE T1,STRTAB		;GET STR 0
	EXCH T1,STRTAB(P1)	;MAKE PUBLIC STR BE STR 0
	MOVEM T1,STRTAB		;...
>
;ERROR CONDITIONS

;ERRORS IN A SINGLE UNIT

;MISSING UNIT IN STRUCTURE. MARK THIS AS A FATAL ERROR
;BUT LOOK AT THE REMAINING UNITS

CHKH11:	HRROI T1,[ASCIZ/? LOGICAL UNIT /]
	CALL FSIPSO
	HRRZ T1,P3		;GET UNIT NUMBER
	SUBI T1,0(P2)		;SUBTRACT OFF THE SDB ADR
	CALL FSIDTY		;TYPE OUT UNIT NUMBER
	HRROI T1,[ASCIZ/ MISSING FROM STRUCTURE /]
	HRROI P4,[ASCIZ/.
/]
	JRST CHKH15		;GO TYPE STR NAME

;MULTIPLE UNITS IN STRUCTURE. MARK THIS AS A FATAL ERROR
;BUT LOOK AT THE REMAINING UNITS

CHKH12:	HRROI T1,[ASCIZ/? MORE THAN 1 LOGICAL UNIT /]
	CALL FSIPSO
	HRRZ T1,P3		;GET UNIT NUMBER
	SUBI T1,0(P2)		;SUBTRACT OFF THE SDB ADR
	CALL FSIDTY
	HRROI T1,[ASCIZ/ IN STRUCTURE /]
	HRROI P4,[ASCIZ/.
/]
	JRST CHKH15

;WRITE LOCKED UNIT. MARK THIS AS A FATAL ERROR
;BUT LOOK AT THE REMAINING UNITS

CHKH17:	HRROI T1,[ASCIZ/? LOGICAL UNIT /]
	CALL FSIPSO
	MOVEI T1,0(P3)		;GET UNIT NUMBER
	SUBI T1,0(P2)		;SUBTRACT OFF THE SDB ADR
	CALL FSIDTY		;TYPE OUT UNIT NUMBER
	HRROI T1,[ASCIZ/ OF STRUCTURE /]
	HRROI P4,[ASCIZ/ IS WRITE LOCKED.
/]
	JRST CHKH15

CHKH15:	CALL FSIPSO
	MOVE T1,SDBNAM(P2)	;GET STR NAME
	CALL FSI6TY		;TYPE OUT STR NAME
	MOVE T1,P4
	CALL FSIPSO
	SETZM CHKHOE		;INDICATE FATAL ERROR
	JRST CHKH6A		;GO ON TO NEXT UNIT IN STRUCTURE

;PROBLEM WITH ONE HOME BLOCK. PRINT A WARNING BUT DON'T
;INDICATE A FATAL ERROR

CHKH13:	SKIPA T1,[-1,,[ASCIZ/% Primary Home Block on "/]]
CHKH14:	HRROI T1,[ASCIZ/% Backup Home Block on "/]
	CALL FSIPSO		;TYPE OUT START OF MESSAGE
	MOVE T1,SDBNAM(P2)	;GET STR NAME
	CALL FSI6TY		;TYPE IT OUT
	HRROI T1,[ASCIZ/" Logical Unit /]
	CALL FSIPSO		;...
	MOVEI T1,0(P3)		;GET LOGICAL UNIT NUMBER
	SUBI T1,0(P2)		;SUBTRACT OFF THE SDB ADR
	CALL FSIDTY		;ADD IT TO MESSAGE
	HRROI T1,[ASCIZ/ is incorrect.
/]
	CALL FSIPSO		;END MESSAGE
	JRST CHKH6A		;LOOP BACK FOR ALL UNITS
;PROBLEMS RELATED TO A STRUCTURE

;BIT TABLE FILE IS TOO BIG FOR MONITOR'S ADDRESS SPACE

CHKH40:	HRROI T1,[ASCIZ/? BIT TABLE IS TOO LARGE IN STRUCTURE /]
	JRST CHKH42

;HOME BLOCK INCONSISTENCY. MARK THIS AS A FATAL ERROR
;AND PROCEED TO THE NEXT STRUCTURE

CHKH16:	HRROI T1,[ASCIZ/? INCONSISTENT SET OF PACKS COMPOSING STRUCTURE /]
CHKH42:	CALL FSIPSO
	MOVE T1,SDBNAM(P2)	;GET STR NAME
	CALL FSI6TY		;TYPE OUT STR NAME
	HRROI T1,[ASCIZ/.
/]
	CALL FSIPSO		;END MESSAGE
	SETZM CHKHOE		;MARK THAT A FATAL ERROR HAPPENED
	JRST CHKHO7		;GO BACK AND LOOK AT OTHER STR'S
;BLDSTR - ROUTINE TO SET UP SDB'S AND STRTAB

;ACCEPTS:
;	T1/VIRTUAL ADDRESS OF WORK PAGE HOLDING HOME BLOCK
;	T2/ADDRESS OF UDB FOR THIS UNIT

;	CALL BLDSTR

;RETURNS +1: NO MORE ROOM IN STRTAB
;		T1/ADDRESS OF SDB
;	 +2: SUCCESS,
;		T1/ ADDRESS OF SDB

;THIS ROUTINE IS CALLED BY FSIINI, ONCE FOR EACH PHYSICAL UNIT
;IF AN SDB ENTRY EXISTS FOR A STRUCTURE WITH THE NAME IN THE HOME
;BLOCKS, IT ADDS THIS UNIT TO THAT STRUCTURE. IF NOT, IT CREATES
;A NEW SDB.  IF ERRORS ARE DETECTED, FLAGS ARE SET IN SDBUDB (IF THE
;ERROR APPLIES TO A SINGLE UNIT) OR SDBSTS (IF IT APPLIES TO THE
;STRUCTURE).  ERRORS ARE NOT INDICATED BY A +1 RETURN.

BLDSTR::STKVAR <UDBLOC>
	MOVEM T2,UDBLOC		;SAVE ADDRESS OF UDB
	MOVE T2,HOMSNM(T1)	;GET THE STR NAME
	MOVSI T4,-STRN		;SET UP TO SEARCH FOR THIS STR NAME
BLDST1:	SKIPN T3,STRTAB(T4)	;IS THIS STR DEFINED?
	JRST [	MOVE T2,UDBLOC	;GET ADDRESS OF UDB
		CALL CRTSTR	;NO SDB YET. CREATE ONE
		 MOVE T1,T3	;GET ADDRESS OF SDB
		RETSKP]		;SLOT CREATED. TAKE SUCCESS RETURN
	CAMN T2,SDBNAM(T3)	;IS THIS THE STRUCTURE WE WANT?
	JRST [	MOVE T2,UDBLOC	;GET ADDRESS OF UDB
		CALL ADDSTR	;THIS IS IT. ADD THE UNIT TO THE STRUCTURE
		 MOVE T1,T3	;GET ADDRESS OF SDB
		RETSKP]		;UNIT ADDED. TAKE SUCCESS RETURN
	AOBJN T4,BLDST1		;NO, LOOP THROUGH ALL STR'S
	RETBAD			;NO MORE SLOTS AVAILABLE
;ADDSTR - ADD A UNIT TO AN EXISTING SDB

;ACCEPTS:
;	T1/ VIRTUAL ADDRESS OF START OF HOME BLOCKS
;	T2/ ADDRESS OF UDB FOR THIS UNIT
;	T3/ ADDRESS OF SDB FOR THIS STRUCTURE

;	CALL ADDSTR

;RETURNS +1: PACK DOESN'T AGREE WITH REST OF STRUCTURE
;		T1/ERROR CODE
;		T3/ ADDRESS OF SDB
;	 +2: PACK ADDED TO STRUCTURE
;		T1/ ADDRESS OF SDB

ADDSTR:	STKVAR <ADSUDB>
	MOVEM T2,ADSUDB		;SAVE ADDRESS OF UDB
	HLRZ T2,HOMLUN(T1)	;GET NUMBER OF PACKS IN STR
	CAME T2,SDBNUM(T3)	;SAME AS PREVIOUS HOME BLOCK?
	JRST ADDST5		;NO, MISMATCH
	MOVE T2,HOMRXB(T1)	;GET ADR OF ROOT IB
	CAME T2,SDBRXB(T3)	;CHECK FOR MATCHING ADR'S
	JRST ADDST5		;NO MATCH
	MOVE T2,HOMBXB(T1)	;GET ADR OF BACKUP IB
	CAME T2,SDBBXB(T3)
	JRST ADDST5		;NO MATCH
	MOVE T2,HOMMID(T1)	;GET MEDIA ID
	CAME T2,SDBPUC(T3)	;SAME AS ID OF OTHER PACKS ?
	JRST ADDST5		;NO, FAIL
	MOVE T4,ADSUDB		;GET ADDRESS OF UDB
	CALL GETTYP		;GET DISK SIZE POINTER
	 RETBAD (MSTX17)	;INDICATE 'PACKS MUST BE OF SAME TYPE'
	CAME T4,SDBTYP(T3)	;IS THE NEW DISK THE SAME SIZE
	JRST ADDST5		;NO. NO MATCH
	SKIPN T2,HOMBTB(T1)	;GET SIZE OF TOP HALF OF BIT TABLE
	MOVEI T2,BTBTOP		;ZERO. USE OLD STYLE SIZE
	CAME T2,SDBBT0(T3)	;IS IT THE SAME AS THE REST OF THE STRUCTURE?
	JRST ADDST5		;NO. REPORT HOME BLOCKS MISMATCH
	MOVE T2,HOMFLG(T1)	;GET FLAGS
	IORM T2,SDBSTS(T3)	;SAVE FLAGS
	MOVE T1,T3		;RETURN WITH ADR OF SDB IN T1
	RETSKP

ADDST5:	MOVX T2,HB%HBM		;MARK THAT THE HOME BLOCKS MISMATCH
	IORM T2,SDBSTS(T3)
	RETBAD (MSTX17)		;INDICATE 'PACKS MUST BE OF SAME TYPE'
;CRTSTR - CREATE A NEW SDB

;ACCEPTS:
;	T1/ ADDRESS OF HOME BLOCK
;	T2/ ADDRESS OF UDB FOR THIS UNIT
;	T4/ OFFSET IN STRTAB FOR NEXT AVAILABLE SLOT

;	CALL CRTSTR

;RETURNS +1: FAILURE,	T1/ ERROR CODE
;			T3/ ADDRESS OF SDB
;	 +2: SUCCESS, T1/ ADDRESS OF SDB

CRTSTR::
	ASUBR <CRTSHB,CRTUDB,CRTSER,CRTSSN>
	SETZM CRTSER		;INDICATE NO ERRORS YET
	TRNN T4,-1		;IF STR 0, USE THE PREALLOCATED SDB
	JRST [	MOVE T1,[SDBBL0,,SDBBL0+1]
		SETZM SDBBL0	;GET A ZERO
		BLT T1,SDBBL0+SDBLN-1 ;CLEAR THE SDB
		MOVEI T1,SDBBL0	;GET ADDRESS OF PS SDB
		JRST CRTST1]	;AND PROCEED
	MOVEI T1,SDBLN		;GET SPACE FOR SDB
	HRLI T1,.RESP3		;FROM THE RESIDENT FREE POOL
	MOVEI T2,.RESGP		;GET SPACE FROM GENERAL POOL
	CALL ASGRES		;...
	 RETBAD ()		;COULD NOT GET SPACE
CRTST1:	MOVE T4,CRTSSN		;GET STR NUMBER TO BE USED
	MOVEM T1,STRTAB(T4)	;STORE THE POINTER TO THE SDB
	MOVE T3,T1		;GET ADR OF SDB INTO T3
	MOVE T1,CRTSHB		;SET UP ACS AGAIN
	MOVE T4,CRTUDB		;GET UDB ADDRESS
	MOVE T2,HOMSNM(T1)	;GET STR NAME
	MOVEM T2,SDBNAM(T3)	;SAVE NAME IN SDB
	MOVEM T2,UDBVID(T4)	;STORE STR NAME AS VOLUMN ID IN UDB
	HLRZ T2,HOMLUN(T1)	;GET NPACKS
	MOVEM T2,SDBNUM(T3)	;STORE NUMBER OF UNITS IN SDB
	MOVE T2,HOMRXB(T1)	;ROOT INDEX ADR
	MOVEM T2,SDBRXB(T3)
	MOVE T2,HOMBXB(T1)	;BACKUP OF ROOT DIR
	MOVEM T2,SDBBXB(T3)
	MOVEI T2,NRESDN		;SET UP STARTING DIR # FOR GETNDN
	STOR T2,STRLDN,(T3)	;GETNDN STARTS SCANNING AT DIR # 20
	MOVE T2,HOMMID(T1)	;GET MEDIA ID
	STOR T2,STRMI,(T3)	;STORE MEDIA ID (PACK UNIQUE CODE)
	CALL GETTYP		;GET DISK SIZE POINTER
	 JRST [	MOVEI T2,MSTX27	;INDICATE 'NOT A DISK'
		MOVEM T2,CRTSER
		JRST CRTST5]
	MOVEM T4,SDBTYP(T3)	;SAVE IT IN THE SDB
	MOVE T2,MINFPG(T4)	;GET INITIAL VALUE OF MINIMUM FREE COUNT
	MOVEM T2,SDBOMF(T3)	;REMEMBER THIS IN THE SDB
	MOVEM T2,SDBMFP(T3)	;START WITH THIS AS THE MINIMUM VALUE
	MOVE T2,MAXFPU(T4)	;GET TURNING POINT OF ALLOCATION ALGORITHM
	IMUL T2,SDBNUM(T3)	;GET TURNING POINT FOR STRUCTURE
	MOVEM T2,SDBMXF(T3)	;SAVE IT IN SDB
	MOVE T2,CYLUNT(T4)	;SET THE STARTING TRACK NUMBER
	LSH T2,-1		;  FOR THE FREE CHOICE TO THE MIDDLE
	MOVEM T2,SDBLCA(T3)	;  OF THE FIRST PACK OF THE STRUCTURE
	MOVE T2,SDBNUM(T3)	;GET NUMBER OF UNITS IN STRUCTURE
	IMUL T2,CYLUNT(T4)	;COMPUTE TOTAL CYLINDERS IN STRUCTURE
	MOVEM T2,SDBCYL(T3)	;SAVE IN SDB
	IMUL T2,PAGCYL(T4)	;COMPUTE TOTAL PAGES IN STRUCTURE
	CAMLE T2,[MXPGUN]	;LEGAL # OF PAGES?
	JRST [	MOVEI T2,MSTX35	;NO. STRUCTURE TOO BIG
		MOVEM T2,CRTSER	;SAVE ERROR
		JRST CRTST5]	;AND GIVE UP
	MOVE T2,HOMP4S(T1)	;NUMBER PAGES FOR SWAPPING PER UNIT
	IMUL T2,SECPAG(T4)	;CONVERT TO SECTORS
	MOVEM T2,SDBNSS(T3)	;SAVE IN SDB
	MOVE T2,HOMFST(T1)	;FIRST SWAPPING TRACK
	IMUL T2,SECCYL(T4)	;CONVERT TO SECTOR NUMBER
	MOVEM T2,SDBFSS(T3)	;SAVE IN SDB
	MOVE T2,CRTUDB		;GET ADDRESS OF UDB
	MOVE T2,CYLUNT(T4)	;GET NUMBER OF CYLINDERS PER UNIT
	IMUL T2,SECCYL(T4)	;CONVERT TO SECTORS
	MOVEM T2,SDBSIZ(T3)	;SAVE IN SDB
	SKIPN T2,HOMBTB(T1)	;SEE IF SIZE OF TOP OF BIT TABLE IS DEFINED
	JRST [	MOVEI T2,BTBTOP	;NO. MUST HAVE BEEN BUILT BY OLD MONITOR
		MOVEM T2,SDBBT0(T3) ;SAVE OLD SIZE OF TOP HALF OF BIT TABLE
		MOVEI T2,BTBBOT	; AND OLD SIZE OF BOTTOM HALF
		MOVEM T2,SDBBT1(T3) ; IN THE SDB
		JRST CRTST3]
	MOVEM T2,SDBBT0(T3)	;BUILT BY RELEASE 2 OR LATER. SAVE SIZE
				;  OF TOP HALF OF BIT TABLE
	IMUL T2,BTWCYL(T4)	;COMPUTE NUMBER OF BIT WORDS IN BOTTOM
	MOVEM T2,SDBBT1(T3)	;SAVE IT IN THE SDB
CRTST3:	ADD T2,SDBBT0(T3)	;COMPUTE TOTAL SPACE IN FILE
	CAMLE T2,BTBSIZ		;WILL IT FIT IN ADDRESS SPACE?
	JRST [	HRRZ T2,HOMLUN(T1)	;GET UNIT WITHIN STRUCTURE
		ADDI T2,SDBUDB(T3)	;POINT TO ITS UDB
		MOVX T4,MI%MXB	;NO. INDICATE THIS FOR LATER
		IORM T4,0(T2)
		MOVEI T2,MSTRX6	;INDICATE 'BAD HOME BLOCKS'
		MOVEM T2,CRTSER
		JRST .+1]
CRTST5:	MOVE T2,HOMFLG(T1)	;GET FLAGS
	IORM T2,SDBSTS(T3)	;SAVE FLAGS
	MOVE T1,T3		;RETURN WITH ADR OF SDB IN T1
	SKIPN CRTSER
	RETSKP
	MOVE T1,CRTSSN		;GET STR NUMBER
	CALL CLRSTB		;CLEAR THE STRTAB ENTRY
	MOVE T1,CRTSER		;GET THE ERROR CODE
	RETBAD ()		;GIVE FAILURE RETURN


;ROUTINE TO CLEAR AN ENTRY IN STRTAB
;ACCEPTS IN T1/	STR NUMBER
;	CALL CLRSTB
;RETURNS +1:	ALWAYS

CLRSTB::SKIPN T2,STRTAB(T1)	;IS THERE ANYTHING THERE?
	RET			;NO
	SETZM STRTAB(T1)	;YES, CLEAR IT
	JUMPE T1,R		;DONT TRY TO RELEASE STR 0'S SDB
	MOVE T1,T2		;AND RELEASE THE SDB BLOCK
	CALLRET RELRES		;BACK TO THE RESIDENT POOL
;GETTYP - GET TYPE OF DISK

;ACCEPTS:
;	T1/ ADDRESS OF HOME BLOCK
;	T3/ ADDRESS OF SDB
;	T4/ ADDRESS OF UDB FOR THIS UNIT

;	CALL GETTYP

;RETURNS +1: UNKNOWN DISK TYPE
;	 +2: VALID DISK TYPE,
;		T2/ OFFSET INTO DSKUTP FOR THIS DISK TYPE
;		T4/ ADDRESS OF DISK SIZE TABLE

;PRESERVES T1 AND T3

GETTYP:	LOAD T4,USTYP,(T4)	;GET TYPE OF UNIT
	MOVSI T2,-NDSKUT	;T2/(-COUNT OF TABLE,,CURRENT OFFSET)
	CAME T4,DSKUTP(T2)	;IS THIS A DISK?
	AOBJN T2,.-1		;NO. KEEP LOOKING
	SKIPL T2		;OUT OF LOOP. DID WE FIND ONE?
	 JRST [	HRRZ T2,HOMLUN(T1)
		ADDI T2,SDBUDB(T3)
		MOVX T4,MS%TYP
		IORM T4,0(T2)
		RETBAD]
	MOVE T4,DSKSIZ(T2)	;YES. GET ADDRESS OF SIZE DATA FOR THIS TYPE
	RETSKP
;BLDNEW - ROUTINE CALLED FROM THE MSTR JSYS TO CREATE A NEW SDB
;
;ACCEPTS IN T1/	CHANNEL NUMBER
;	    T2/	UNIT NUMBER
;	    T3/	ADDRESS OF HOME BLOCK PAGE
;	    T4/	STRUCTURE NUMBER (INDEX INTO STRTAB)
;		CALL BLDNEW
;RETURNS: +1	 FAILURE, ERROR CODE IN T1
;	  +2	SUCCESS, T1/ ADDRESS OF SDB

BLDNEW::ASUBR <BNWCHN,BNWUNI,BNWADR,BNWSTR>
	MOVE T1,CHNTAB(T1)	;GET ADDRESS OF CDB
	ADDI T1,CDBUDB(T2)	;FORM POINTER TO ADDRESS OF UDB
	MOVE T2,(T1)		;GET ADDRESS OF UDB FOR THIS UNIT
	MOVE T1,BNWADR		;GET ADDRESS OF PAGE CONTAINING HOME BLOCKS
	MOVE T4,BNWSTR		;GET STRUCTURE NUMBER
	CALL CRTSTR		;GO CREATE THE SDB
	 RETBAD ()		;FAILED, RETURN ERROR
	RETSKP			;RETURN SUCCESS


;BLDSDB - ROUTINE CALLED FROM THE MSTR JSYS TOADD A UNIT TO A STRUCTURE
;
;ACCEPTS IN T1/	CHANNEL NUMBER
;	    T2/	UNIT NUMBER
;	    T3/	ADDRESS OF HOME BLOCK PAGE
;	    T4/ ADDRESS OF SDB FOR THIS STRUCTURE
;		CALL BLDSDB
;RETURNS: +1	 FAILURE, ERROR CODE IN T1
;	  +2	SUCCESS, T1/ ADDRESS OF SDB

BLDSDB::ASUBR <BLSCHN,BLSUNI,BLSADR,BLSSDB>
	MOVE T1,CHNTAB(T1)	;GET ADDRESS OF CDB
	ADDI T1,CDBUDB(T2)	;FORM POINTER TO ADDRESS OF UDB
	MOVE T2,(T1)		;GET ADDRESS OF UDB FOR THIS UNIT
	MOVE T1,BLSADR		;GET ADDRESS OF PAGE CONTAINING HOME BLOCKS
	MOVE T3,BLSSDB		;GET ADDRESS OF SDB
	CALL ADDSTR		;GO ADD THIS UNIT TO THE STRUCTURE
	 RETBAD ()		;FAILED, RETURN ERROR
	RETSKP			;RETURN SUCCESS
; ROUTINE TO CHECK THE BAT BLOCKS ON A SINGLE UNIT, CALLED FROM MSTR JSYS
;
; ACCEPTS IN T1/ CHANNEL NUMBER
;	     T2/ CONTROLLER NUMBER
;	     T3/ UNIT NUMBER
;	     T4/ VIRTUAL ADDRESS,,PHYSICAL PAGE NUMBER OF BAT BLOCK PAGE
;		CALL UNIBAT
; RETURNS: +1	 FAILED, BAT BLOCKS BAD
;	   +2	SUCCESS, BAT BLOCKS OK

	SWAPCD
UNIBAT::MOVE T1,CHNTAB(T1)	;GET CDB ADDRESS
	ADDI T1,CDBUDB(T3)	;GET POINTER TO ADDRESS OF UDB FOR THIS UNIT
	MOVEM T4,T3		;SAVE ADDRESSES OF BAT BLOCK PAGE
	MOVE T4,(T1)		;GET ADDRESS OF UDB FOR THIS UNIT
	HLRZ T1,T3		;GET VIRTUAL ADDRESS OF BAT BLOCK PAGE
	HRRZ T2,T3		;GET PHYSICAL PAGE NUMBER OF BAT BLOCK PAGE
	LSH T2,PGSFT		;CONVERT TO PHYSICAL ADDRESS OF BAT BLOCK PAGE
	MOVX T3,MS%NFB		;DO NOT REPAIR THE BAT BLOCKS IF BAD
	CALLRET DOPACK		;GO CHECK THE BAT BLOCKS ON THIS UNIT
; ROUTINE TO CREATE A PAIR OF NEW HOME BLOCKS ON A UNIT
;
; ACCEPTS IN T1/ FLAGS,,ADDRESS OF ID INFO
;	     T2/ STRUCTURE NAME
;	     T3/ CHANNEL NUMBER,,UNIT NUMBER
;	     T4/ NUMBER OF UNITS IN STRUCTURE,,UNIT NUMBER WITHIN STRUCTURE
;	     P1/ # OF PAGES FOR SWAPPING ON THIS STRUCTURE
;	     P2/ MEDIA IDENTIFICATION (PACK UNIQUE CODE)
;		CALL CRTHOM
; RETURNS: +1	 FAILED, COULD NOT WRITE HOME BLOCKS
;	   +2	SUCCESS, HOME BLOCKS WRITTEN

IDLEN==6		;NUMBER OF WORDS OF UNIT AND OWNER ID INFO

CRTHOM::SAVEP
	ASUBR <CRHINF,CRHSTR,CRHUNI,CRHNUM>
	STKVAR <CRHVIR,CRHP4S,CRHMID>
	MOVEM P1,CRHP4S		;SAVE # OF PAGES FOR SWAPPING
	MOVEM P2,CRHMID		;SAVE MEDIA ID

; VALIDATE AMOUNT OF SWAPPING SPACE REQUESTED

	HLRZ T1,CRHUNI		;GET CHANNEL NUMBER
	HRRZ T2,CRHUNI		;GET UNIT NUMBER
	HLRZ T3,CRHNUM		;GET NUMBER OF UNITS IN STRUCTURE
	MOVE T4,CRHP4S		;GET # OF PAGES FOR SWAPPING ON THIS STR
	CALL CHKSWP		;GO CHECK THE SWAPPING SPACE REQUESTED
	 RETBAD ()		;FAILED, INVALID AMOUNT REQUESTED

; GET UNIT SIZE AND ADDRESS OF SIZE TABLE

	HLRZ P1,CRHUNI		;GET CHANNEL NUMBER
	MOVE P1,CHNTAB(P1)	;GET ADDRESS OF CHANNEL DATA BLOCK
	HRRZ T3,CRHUNI		;GET UNIT NUMBER AGAIN
	ADDI P1,CDBUDB(T3)	;FORM POINTER TO ADDRESS OF UDB FOR THIS UNIT
	MOVE P1,(P1)		;GET ADDRESS OF UNIT DATA BLOCK
	LOAD T1,USTYP,(P1)	;GET UNIT TYPE
	MOVSI T2,-NDSKUT	;SET UP TO LOOK FOR A KNOWN DISK TYPE
	CAME T1,DSKUTP(T2)	;CHECK FOR A KNOWN DISK TYPE
	AOBJN T2,.-1		;CONTINUE LOOKING
	SKIPL T2		;FOUND A KNOWN DISK TYPE ?
	RET			;NO, RETURN
	MOVE P1,DSKSIZ(T2)	;YES, GET ADDRESS OF SIZE TABLE
	HRLZ P3,CYLUNT(P1)	;GET NUMBER OF CYLINDERS PER UNIT
	HLR P3,CRHNUM		;GET NUMBER OF UNITS IN STRUCTURE

; GET A PAGE FOR IN WHICH TO CREATE A HOME BLOCK

	NOINT			;DO NOT PERMIT INTERRUPTS
	CALL ASGPAG		;ASSIGN A PAGE
	 RETBAD (,<OKINT>)	;FAILED, RETURN
	MOVEM T1,CRHVIR		;SAVE ADDRESS OF PAGE
	HRR T4,CRHVIR		;GET ADDRESS OF HOME BLOCK PAGE
	HRL T4,CRHP4S		;GET # OF PAGES FOR SWAPPING ON THIS STR
	MOVE T3,P3		;GET UNIT SIZE AND # OF UNITS
	MOVE T2,CRHSTR		;GET STRUCTURE NAME
	HLLZ T1,CRHINF		;GET FLAGS
	CALL SETHOM		;GO SET UP PRIMARY HOME BLOCK

; ADD REMAINING INFO TO THE HOME BLOCK

	HRRZ T2,CRHVIR		;GET ADDRESS OF HOME BLOCK
	MOVE T1,CRHMID		;GET MEDIA IDENTIFICATION (PACK UNIQUE CODE)
	MOVEM T1,HOMMID(T2)	;SAVE MEDIA ID
	HRRZ T1,CRHNUM		;GET UNIT NUMBER WITHIN STRUCTURE
	HRRM T1,HOMLUN(T2)	;STORE UNIT # WITHIN STRUCTURE
	HRLZ T1,CRHINF		;GET ADDRESS OF ID INFO BLOCK
	HRRI T1,HOMUID(T2)	;GET DESTINATION ADDRESS
	BLT T1,HOMUID+IDLEN-1(T2) ;COPY ID INFO INTO HOME BLOCK
	;..
	;..

; LOCK THE HOME BLOCK PAGE AND WRITE THE HOME BLOCKS

	SETZM P2		;INITIALIZE FAILURE FLAG
	HRRZ T1,CRHVIR		;GET ADDRESS OF HOME BLOCK PAGE
	CALL MLKMA		;LOCK THE PAGE
	MOVEM T1,P1		;SAVE PHYSICAL PAGE NUMBER
	HRRZ T1,CRHVIR		;GET FLAGS,,VIRTUAL ADDRESS OF HOME BLOCK PAGE
	HRRZ T2,P1		;GET PHYSICAL PAGE NUMBER
	LSH T2,PGSFT		;FORM PHYSICAL ADDRESS OF HOME BLOCK PAGE
	MOVE T3,CRHUNI		;GET CHANNEL,,UNIT NUMBERS
	CALL CPYH1		;WRITE OUT SECONDARY HOME BLOCK
	 SETOM P2		;FAILED, FLAG ERROR
	HRRZ T1,CRHVIR		;GET FLAGS,,VIRTUAL ADDRESS OF HOME BLOCK PAGE
	HRRZ T2,P1		;GET PHYSICAL PAGE NUMBER
	LSH T2,PGSFT		;FORM PHYSICAL ADDRESS OF HOME BLOCK PAGE
	MOVE T3,CRHUNI		;GET CHANNEL,,UNIT NUMBERS
	CALL CPYH2		;WRITE OUT PRIMARY HOME BLOCK
	 SETOM P2		;FAILED, FLAG ERROR

; UNLOCK AND RETURN THE HOME BLOCK PAGE, AND RETURN

	HRRZ T1,P1		;GET PHYSICAL PAGE NUMBER
	CALL MULKCR		;UNLOCK THE PAGE
	HRRZ T1,CRHVIR		;GET VIRTUAL ADDRESS OF PAGE
	CALL RELPAG		;RELEASE THE PAGE
	OKINT			;PERMIT INTERRUPTS
	JUMPN P2,R		;IF I/O ERROR, RETURN FAILURE
	RETSKP			;ELSE RETURN SUCCESS
	RESCD(INIT)
;ROUTINE TO READ IN THE PRIMARY AND BACKUP HOME BLOCKS
;OR THE PRIMARY AND BACKUP BAT BLOCKS
;ACCEPTS IN T1/	CHANNEL # ,, DRIVE # TO BE READ
;	    T2/	ADDRESS OF PAGE TO READ INTO
;           T3/ LOCAL BLOCK ADDRESS OF PRIMARY BLOCK
;	    T4/	VIRTUAL CORE ADDRESS
;	CALL REDHOM
;RETURNS +1:	DRIVE OFF-LINE
;	 +2:	BOTH BLOCKS READ IN (BUT NOT NECESSARILY WITHOUT ERRORS)

REDHOM::STKVAR <REDHOA,REDHOB,REDBLK,REDVIR>
	MOVEM T1,REDHOA		;SAVE CHANNEL ,, UNIT
	MOVEM T2,REDHOB		;SAVE ADDRESS OF PAGE TO HOLD HOME BLKS
	MOVEM T4,REDVIR		; SAVE VIRTUAL ADDRESS
	SETZM (T4)		; ZERO WHOLE AREA
	HRLI T4,(T4)		; IN BOTH HALFS
	AOS T4
	HRRZ T2,T4		;GET BASE ADDRESS AGAIN
	BLT T4,<HBLEN*2-1>(T2)	; ZAP ENTIRE AREA
	MOVEM T3,REDBLK		; SAVE LOCAL BLOCK NUMBER
	MOVE T1,REDBLK		;GET UNIT RELATIVE ADR TO BE READ
	MOVEI T2,HBLEN		;READ IN ONLY THE HOME BLOCK
	MOVE T3,REDHOB		;GET ADDRESS TO READ INTO
	MOVE T4,REDHOA		;GET CHANNEL ,, UNIT
	TXO T2,1B0!DOP%EO	;GET AN ERROR ON OFFLINE
	CALL UDSKIO		;READ IN THE HOME BLOCK
	MOVE T4,REDVIR		;RESTORE VIRTUAL ADDRESS
	SKIPE T1		;WAS THERE AN ERROR?
	SETZM HOMNAM(T4)	;YES. CLEAR NAME
	MOVE T1,REDBLK		;GET BACK DISK ADDRESS
	ADDI T1,HM2BLK-HM1BLK	;POINT TO BACKUP HOME BLOCKS
	MOVEI T2,HBLEN		;SET UP LENGTH
	MOVE T3,REDHOB		;GET ADDRESS TO READ INTO
	ADDI T3,HBLEN		;PUT IT JUST AFTER FIRST HOME BLOCK
	MOVE T4,REDHOA		;GET CHANNEL ,, UNIT
	TXO T2,1B0!DOP%EO	;GET AN ERROR ON OFFLINE
	CALL UDSKIO		;READ IN HOME BLOCK
	MOVE T4,REDVIR		;GET VIRTUAL ADDRESS
	SKIPE T1		;DISK ERROR?
	SETZM <HOMNAM+HBLEN>(T4) ;YES. ZAP THIS NAME
	CAMN T1,[-1]		;DRIVE OFF-LINE?
	RET			;YES
	RETSKP			;READ IN BOTH OK
;ROUTINE TO CHECK THE CONSISTENCY OF THE HOME BLOCKS
;ACCEPTS IN T1/	ADDRESS OF HOME BLOCK
;	    T2/	HOME BLOCK #
;	CALL HBCCHK
;RETURNS +1:	NOT CONSISTENT OR MULTIPLE LOGICAL UNITS
;	 +2:	CONSISTENT, LOGICAL UNIT # IN T1

HBCCHK::MOVS T3,HOMNAM(T1)	;GET SIXBIT /HOM/
	CAIE T3,'HOM'		;IS THIS CORRECT?
	RET			;NO, GIVE ERROR RETURN
	MOVE T3,HOMCOD(T1)	;GET HOME BLOCK CODE
	CAIE T3,CODHOM		;MUST BE "707070"
	RET			;INCONSISTENT
	MOVE T3,HOMSLF(T1)	;GET BLOCK NUMBER OF HOME BLOCK
	CAME T2,T3		;IS IT WHAT IS EXPECTED?
	RETBAD			;NO, NOT A CONSISTENT HOME BLOCK
	MOVE T2,HOMFSN(T1)	;GET FILE SYSTEM TYPE
	CAME T2,[BYTE (2)0(8)" "," "(2)0(8)"O","T"]
	RETBAD			;NOT A TOPS-20 PACK
	MOVE T2,HOMFSN+1(T1)	;GET CHARACTERS 5-8 OF TYPE
	MOVE T3,HOMFSN+2(T1)	;GET CHARACTERS 9-12 OF TYPE
	CAMN T2,[BYTE (2)0(8)"S","P"(2)0(8)"2","-"]
	CAME T3,[BYTE (2)0(8)" ","0"(2)0(8)" "," "]
	RETBAD			;NOT A TOPS-20 PACK
	RETSKP			;HOME BLOCK IS OK
;ROUTINES TO CORRECT ONE INCORRECT HOME BLOCK
;AND WRITE THE CORRECTED BLOCK ON THE DISK
;CALLED FROM MSTR JSYS
;
;ACCEPTS: T1/	FLAGS,,VIRTUAL ADDRESS OF PAGE CONTAINING HOME BLOCKS
;	  T2/	PHYSICAL ADDRESS OF PAGE CONTAINING HOME BLOCKS
;	  T3/	CHANNEL,,UNIT NUMBERS FOR THIS PACK
;  IF A MESSAGE IS REQUESTED, ALSO:
;	  P4/	SDBUDB POINTER FOR THIS UNIT
;	  P5/	STRUCTURE NUMBER
;		CALL CPYH1/CPYH2
;RETURNS: +1	 ERROR WRITING THE HOME BLOCK
;	  +2	SUCCESS, GOOD HOME BLOCK COPIED OVER BAD ONE

CPYH1::	TDZA T4,T4		;INDICATE COPYING PRIMARY TO SECONDARY
CPYH2::	SETOM T4		;INDICATE COPYING SECONDARY TO PRIMARY
	ASUBR <CPHVIR,CPHPHY,CPHCHN> ;STORE INPUT ARGUMENTS
	STKVAR <CPHDIR,CPHLOC>		;ALLOCATE SPACE FOR DIRECTION OF TRANSFER FLAG
	MOVEM T4,CPHDIR		;SAVE DIRECTION OF TRANSFER
	TXNN T1,MI%MSG		;MESSAGE DESIRED ?
	JRST CPYH10		;NO, GO COPY THE GOOD HOME BLOCK
	HRRZ T3,CPHVIR		;POINT TO START OF HOME BLOCK 1
	HRROI T1,[ASCIZ/% Copying primary HOME block to secondary on /]
	SKIPE CPHDIR		;REALLY COPYING SECONDARY TO PRIMARY ?
	JRST [	HRROI T1,[ASCIZ/% Copying secondary HOME block to primary on /]
		ADDI T3,HBLEN	;POINT TO START OF HOME BLOCK 2
		JRST .+1]
	MOVEM T3,CPHLOC		;SAVE ADDRESS OF GOOD HOME BLOCK
	CALL FSIPSO		;OUTPUT INITIAL PART OF MESSAGE
	MOVE T3,CPHLOC		;POINT TO CORRECT HOME BLOCK
	MOVE T1,HOMSNM(T3)	;GET NAME OF STRUCTURE
	CALL FSI6TY		;PRINT NAME OF STRUCTURE
	HRROI T1,[ASCIZ/ UNIT /]
	CALL FSIPSO		;PRINT 'UNIT'
	MOVE T3,CPHLOC
	HRRZ T1,HOMLUN(T3)	;GET UNIT NUMBER
	CALL FSIOTY		;PRINT THE UNIT NUMBER
	HRROI T1,[ASCIZ/
/]				;GET END OF LINE
	CALL FSIPSO		;OUTPUT END OF MESSAGE

; HERE TO DO THE ACTUAL COPY

CPYH10:	HRRZ T1,CPHVIR		;GET VIRTUAL ADDRESS OF FIRST HOME BLOCK
	MOVE T3,[HM2BLK,,HM1BLK] ;GET BLOCK NUMBERS OF OTHER,,THIS HOME BLOCK
	MOVEI T4,(T1)		;GET VIRTUAL ADDRESS OF FIRST HOME BLOCK
	HRLI T1,HBLEN(T1)	;GET SOURCE ADDRESS FOR COPY
	SKIPE CPHDIR		;COPYING SECONDARY TO PRIMARY ?
	JRST CPYH20		;YES, GO SET UP TERMINATING ADDRESS
	HRLI T1,(T4)		;NO, GET SOURCE ADDRESS
	HRRI T1,HBLEN(T4)	;GET DESTINATION ADDRESS
	MOVS T3,T3		;SWAP THIS,,OTHER HOME BLOCK NUMBERS
	ADDI T4,HBLEN		;POINT TO SECOND HOME BLOCK
CPYH20:	MOVEI T2,(T1)		;GET BASE FOR TERMINATING ADDRESS
	BLT T1,HBLEN-1(T2)	;COPY GOOD HOME BLOCK
	MOVSM T3,HOMHOM(T4)	;TCO 4.2044 SAVE THIS,,OTHER BLOCK NUMBERS
	HRRZM T3,HOMSLF(T4)	;SAVE THIS BLOCK NUMBER
	;..
	;..

; NOW WRITE OUT THE CORRECTED HOME BLOCK

	HRRZ T1,T3		;GET SECTOR NUMBER
	MOVE T2,[1B0+DOP%WR+HBLEN] ;CHANNEL+UNIT, WRITE, ONE HOME BLOCK
	MOVE T3,CPHPHY		;GET PHYSICAL ADDRESS OF FIRST HOME BLOCK
	SKIPN CPHDIR		;WRITING FIRST HOME BLOCK ?
	ADDI T3,HBLEN		;NO, GET PHYSICAL ADDRESS OF SECOND
	MOVE T4,CPHCHN		;GET CHANNEL AND UNIT NUMBERS
	CALL UDSKIO		;WRITE THE CORRECTED HOME BLOCK
	JUMPN T1,R		;IF ERROR, RETURN FAILURE
	RETSKP			;RETURN SUCCESS
;ROUTINE TO WRITE ALL HOME BLOCKS IN PUBLIC STRUCTURE
;ASSUMES THAT HOMTAB IS SET UP FOR THE PUBLIC STR
;	CALL WRTHOM
;RETURNS +1:	ERROR ON WRITE
;	 +2:	HOME BLOCKS WRITTEN OK

;HOMTAB IS INDEXED BY LOGICAL UNIT WITHIN STRUCTURE, CONTAINS
;	(CHANNEL,,PHYSICAL UNIT)

;FSINPK/NUMBER OF UNITS IN STRUCTURE

WRTHOM:	SAVEP
	MOVE T1,FSIFLG		;GET FLAGS
	MOVE T2,FSINAM		;GET STRUCTURE NAME
	HRR T3,FSINPK		;GET NUMBER OF UNITS IN STRUCTURE
	HRL T3,FSIUSZ		;GET UNIT SIZE
	MOVEI T4,HOMPGA		;GET ADDRESS OF HOME BLOCK PAGE
	HRL T4,FSISWP		;GET # OF PAGES FOR SWAPPING
	MOVE P1,FSITYP		;GET ADDRESS OF DISK SIZE DATA
	CALL SETHOM		;GO SETUP HOME BLOCK PAGE
	CALL GETMID		;GET THE MEDIA ID FOR THIS STR
	MOVEM T1,HOMPGA+HOMMID	;SAVE THE MEDIA ID
	MOVN P1,FSINPK		;SET UP LOOP COUNTER
	HRLZS P1
	SETZ P3,		;INITIALIZE ERROR COUNTER TO 0
	;..
	;..
WRTHO1:	HRRM P1,HOMPGA+HOMLUN	;SET UP LOGICAL UNIT NUMBER
	MOVEI T1,HM1BLK		;WRITE FIRST HOME BLOCK
	MOVE T2,HOMTAB(P1)	;GET CHANNEL ,, UNIT
	CALL WRTHB
	 AOS P3			;COUNT UP ERRORS
	MOVSS HOMPGA+HOMHOM	;SWITCH POINTER TO HOME BLOCKS
	MOVEI T1,HM2BLK		;THEN WRITE SECOND HOME BLOCK
	MOVE T2,HOMTAB(P1)	;GET CHANNEL ,, UNIT
	CALL WRTHB
	 AOS P3			;COUNT UP ERRORS
	MOVSS HOMPGA+HOMHOM	;SWITCH POINTER BACK FOR FIRST HOME BLK
	AOBJN P1,WRTHO1		;LOOP BACK FOR ALL PACKS IN PUBLIC STR
	JUMPG P3,R		;IF ERRORS, GIVE NON-SKIP RETURN
	RETSKP			;OTHERWISE GIVE SKIP RETURN

;ROUTINE TO WRITE A HOME BLOCK
;ASSUMES THAT HOMPG IS SET UP WITH A HOME BLOCK IMAGE
;ACCEPTS IN T1/	BLOCK # OF THIS HOME BLOCK
;	    T2/	CHANNEL # ,, UNIT #
;	    P1/	LOGICAL PACK #
;	CALL WRTHB
;RETURNS +1:	ERROR ON WRITE
;	 +2:	OK

WRTHB:	MOVEM T1,HOMPGA+HOMSLF	;SAVE POINTER TO SELF
	MOVE T4,T2		;SET UP FOR CALL TO UDSKIO
	MOVEI T2,HBLEN		;ONLY WRITE THE HOME BLOCK
	TLO T2,(1B0+1B14)	;MARK THAT A WRITE IS TO BE DONE
	MOVE T3,FSIPPA		;GET PHYSICAL ADDRESS
	CALL UDSKIO		;WRITE OUT THE HOME BLOCK
	JUMPE T1,RSKP		;NO ERRORS IF T1=0
	HRROI T1,[ASCIZ/
? Error writing Home Block on logical unit /]
	CALL FSIPSO
	MOVEI T1,0(P1)		;GET UNIT NUMBER
	CALL FSIOTY		;TYPE IT OUT
	HRROI T1,[ASCIZ/
/]
	CALL FSIPSO		;END WITH A CR-LF
	RET			;AND EXIT
; ROUTINE TO SETUP FIRST HOME BLOCK ON A UNIT
; (EXCEPT FOR LOGICAL UNIT # IN HOMLUN)
;
; ACCEPTS IN T1/ FLAGS
;	     T2/ STRUCTURE NAME
;	     T3/ UNIT SIZE,,NUMBER OF UNITS IN STRUCTURE
;	     T4/ # OF PAGES FOR SWAPPING,,ADDRESS OF HOME BLOCK PAGE
;	     P1/ ADDRESS OF DISK SIZE TABLE
;		CALL SETHOM
; RETURNS: +1 ALWAYS, FIRST HOME BLOCK SET UP

SETHOM::ASUBR <STHFLG,STHSTR,STHUNI,STHADR>
	HRLZ T1,T4		;GET START ADDRESS OF HOME BLOCK PAGE
	HRRI T1,1(T4)		;GET DESTINATION ADDRESS
	HRRZS T4		;GET ADDRESS ONLY
	SETZM (T4)		;ZERO THE PAGE FIRST
	BLT T1,HBLEN-1(T4)	;...
	MOVSI T1,'HOM'		;SET UP THE HOME BLOCK
	MOVEM T1,HOMNAM(T4)	;SIXBIT /HOM/
	MOVE T1,SECUNT(P1)	;GET NUMBER OF SECTORS PER UNIT
	MOVEM T1,HOMSIZ(T4)	;TO THE HOME BLOCK
	MOVE T1,STHSTR		;GET STR NAME
	MOVEM T1,HOMSNM(T4)
	HRLZ T1,STHUNI		;GET TOTAL # OF PACKS IN STR
	MOVEM T1,HOMLUN(T4)	;LOGICAL UNITS GET SET UP LATER
	MOVE T1,[HM1BLK,,HM2BLK]
	MOVEM T1,HOMHOM(T4)	;SET UP POINTERS TO HOME BLOCKS
	MOVE T1,[BYTE (2)0(8)" "," "(2)0(8)"O","T"]
	MOVEM T1,HOMFSN(T4)	;SET UP NAME OF SYSTEM PACKS
	MOVE T1,[BYTE (2)0(8)"S","P"(2)0(8)"2","-"]
	MOVEM T1,HOMFSN+1(T4)
	MOVE T1,[BYTE (2)0(8)" ","0"(2)0(8)" "," "]
	MOVEM T1,HOMFSN+2(T4)
	MOVE T1,STHFLG		;SET UP FLAGS
	MOVEM T1,HOMFLG(T4)
	MOVE T1,DIDSCI		;SET UP POINTER TO INDEX BLOCK
	MOVEM T1,HOMRXB(T4)
	MOVE T1,DIDSCJ		;SET UP POINTER TO BACKUP ROOT-DIR
	MOVEM T1,HOMBXB(T4)
	HLRZ T1,STHADR		;GET # OF PAGES TO ALLOCATE FOR SWAPPING
	MOVE T2,STHUNI		;GET # OF UNITS IN THIS STRUCTURE
	CALL CMPSWP		;COMPUTE # OF PAGES FOR SWAPPING ON THIS UNIT
	MOVEM T1,HOMP4S(T4)	;PUT # OF PAGES FOR SWAPPING IN HOME BLK
	IDIV T1,PAGCYL(P1)	;GET NUMBER OF CYLINDERS OF SWAP SPACE
	HLRZ T2,STHUNI		;GET UNIT SIZE IN CYLINDERS
	SUB T2,T1		;COMPUTE STARTING CYLINDER FOR SWAPPING
	LSH T2,-1		;SO THAT SWAP SPACE STRADDLES THE CENTER
	MOVEM T2,HOMFST(T4)	;PUT ADR OF FIRST SWAPPING TRACK IN HB
	MOVEI T1,CODHOM		;SET UP SPECIAL CODE
	MOVEM T1,HOMCOD(T4)

	MOVE T1,CYLUNT(P1)	;GET TOTAL CYLINDERS PER UNIT
	HRRZ T2,STHUNI		;GET NUMBER OF UNITS IN STRUCTURE
	IMUL T1,T2		;COMPUTE TOTAL FOR STRUCTURE
	MOVEM T1,HOMBTB(T4)	;SAVE AS SIZE OF TOP HALF OF BIT TABLE
	RET			;RETURN
;MODHOM - MODIFY THE HOME BLOCKS

;ACCEPTS:
;	T1/ STRUCTURE NUMBER
;	T2/ OFFSET IN HOME BLOCKS OF WORD TO CHANGE
;	T3/ DATA TO GO INTO THAT WORD
;	T4/ MASK OF BITS TO CHANGE

;	CALL MODHOM

;RETURNS +1: FAILED TO UPDATE THE HOME BLOCK
;	 +2: SUCCEEDED

;THIS ROUTINE READS BOTH HOME BLOCKS, CHANGES ONE WORD IN THEM, AND
;REWRITES THE MODIFIED HOME BLOCKS.  IT DOES NOT CHECK THEM FOR
;CORRECTNESS
	SWAPCD
MODHOM::
	SAVEQ
	STKVAR <MODHOF,MODHDA,MODHVA,MODHPA,MODHST,MODHCU,MODMSK>
	MOVEM T1,MODHST		;SAVE STRUCTURE NUMBER
	MOVEM T2,MODHOF		;SAVE THE OFFSET
	MOVEM T3,MODHDA		;SAVE THE DATA
	MOVEM T4,MODMSK		;SAVE MASK
	NOINT			;NO INTERRUPTS WHILE PAGE IS ASSIGNED
	CALL ASGPAG		;GET A PAGE IN JSB FREE SPACE
	 RETBAD (,<OKINT>)	;COULDN'T GET A PAGE
	MOVEM T1,MODHVA		;SAVE STARTING ADDRESS OF PAGE (VIRTUAL)
	CALL MLKMA		;LOCK DOWN A PHYSICAL PAGE TO CORRESPOND
 				; TO THIS ADDRESS
	LSH T1,PGSFT		;CONVERT ITS PHYSICAL PAGE NO. TO AN ADDRESS
	MOVEM T1,MODHPA		;SAVE STARTING ADDRESS OF PAGE (PHYSICAL)
	MOVE T2,MODHST		;GET STRUCTURE NUMBER
	MOVE T2,STRTAB(T2)	;POINT TO SDB FOR THIS STRUCTURE
	LOAD Q1,STRNUM,(T2)	;GET NUMBER OF UNITS IN STRUCTURE
	MOVNS Q1		;MAKE IT NEGATIVE
	HRLZS Q1		;LEFT HALF OF AOBJN POINTER
	HRRI Q1,SDBUDB(T2)	;Q1/(-COUNT,,SDBUDB ADDRESS)
	SETZM Q2		;INITIALIZE ERROR FLAG TO NO ERRORS
MODHO1:	MOVE T2,0(Q1)		;GET ADDRESS OF UDB FOR THIS LOCICAL UNIT
	HRRZ T1,UDBADR(T2)	;GET PHYSICAL UNIT NUMBER
	HRRZ T2,UDBCDB(T2)	;POINT TO CDB FOR THIS UNIT
	HRL T1,CDBADR(T2)	;T1/(CHANNEL,,UNIT) FOR THIS LOGICAL UNIT
	MOVEM T1,MODHCU		;SAVE CHANNEL AND UNIT
	MOVE T2,MODHPA		;T2/PHYSICAL ADDRESS OF PAGE TO READ INTO
	MOVEI T3,HM1BLK		;T2/SECTOR NUMBER OF FIRST HOME BLOCK
	MOVE T4,MODHVA		;T4/VIRTUAL ADDRESS OF PAGE TO READ INTO
	CALL REDHOM		;READ BOTH HOME BLOCKS INTO PAGE POINTED
				; TO BY T4
	 JRST [	SETOM Q2	;INDICATE ERROR
		JRST MODHO5]	;GO CLEAN UP AND QUIT
	MOVE T1,MODHOF		;GET THE OFFSET TO BE CHANGED
	ADD T1,MODHVA		;POINT TO THE ACTUAL WORD
	MOVE T2,0(T1)		;GET ORIGINAL DATA FROM HOMEBLOCK
	TDZ T2,MODMSK		;CLEAR BITS BEING CHANGED
	MOVE T3,MODHDA		;GET NEW DATA
	AND T3,MODMSK		;KEEP ONLY BITS BEING CHANGED
	IOR T2,T3		;COLLECT NEW VERSION OF DATA WORD FOR HOMEBLOCK
	MOVEM T2,0(T1)		;STORE INTO FIRST HOME BLOCK
	MOVE T2,HBLEN(T1)	;GET ORIGINAL DATA FROM SECOND HOMEBLOCK
	TDZ T2,MODMSK		;CLEAR BITS BEING CHANGED
	IOR T2,T3		;COLLECT NEW VERSION OF DATA WORD FOR HOMEBLOCK
	MOVEM T2,HBLEN(T1)	;STORE INTO SECOND HOME BLOCK
	MOVE T1,MODHPA		;T1/PHYSICAL ADDRESS OF WORK PAGE
	MOVE T2,MODHCU		;T2/(CHANNEL,,UNIT) FOR THIS LOGICAL UNIT
	CALL UPDHOM		;UPDATE HOME BLOCKS ON THIS UNIT
	 JRST [	SETOM Q2	;NOTE FAILURE
		JRST MODHO5]	;GO CLEAN UP AND QUIT
MODHO3:	AOBJN Q1,MODHO1		;LOOP THROUGH ALL UNITS IN STRUCTURE
MODHO5:	MOVE T1,MODHPA		;T1/PHYSICAL ADDRESS OF WORK PAGE
	LSH T1,-PGSFT		;CONVERT TO PAGE NUMBER
	CALL MULKCR		;UNLOCK IT FROM CORE
	MOVE T1,MODHVA		;T1/VIRTUAL ADDRESS OF WORK PAGE
	CALL RELPAG		;RELEASE THE WORK PAGE
	OKINT			;INTERRUPTS ARE OK NOW
	SKIPE Q2		;WERE THERE ANY ERRORS?
	RETBAD			;YES. TAKE ERROR RETURN
	RETSKP			;NO. TAKE SUCCESS RETURN

;UPDHOM - UPDATE THE HOME BLOCKS

;ACCEPTS:
;	T1/ PHYSICAL ADDRESS OF START OF PAGE WHERE HOME BLOCK DATA
;		IS STORED
;	T2/ CHANNEL,,UNIT FOR PACK TO BE WRITTEN

;	CALL UPDHOM

;RETURNS +1: FAILED
;	 +2: SUCCEEDED

;THIS ROUTINE WRITES BOTH HOME BLOCKS FOR A SINGLE UNIT.  THE CALLER 
;MUST HAVE SET UP IN THE PAGE POINTED TO BY T1 THE DATA FOR BOTH HOME
;BLOCKS IN 2 CONTIGUOUS BLOCKS OF LENGTH HBLEN EACH.  CALLING REDHO
;WILL CAUSE THE PAGE TO BE SET UP THIS WAY

UPDHOM:
	SAVEQ
	ASUBR <UPDHPA,UPDHCU>
	DMOVE T3,T1		;MOVE ARGUMENTS TO T3 AND T4 FOR UDSKIO
	MOVEI T1,HM1BLK		;T1/SECTOR NUMBER OF FIRST HOME BLOCK
	MOVE T2,[1B0+1B14+HBLEN] ;T2/WRITE, ADDRESS IS (CHAN,,UNIT), LENGTH
	CALL UDSKIO		;WRITE THE FIRST HOME BLOCK TO THE DISK
	MOVEM T1,Q1		;SAVE ERROR INDICATOR FROM UDSKIO
	MOVEI T1,HM2BLK		;NO. T1/SECTOR NUMBER OF SECOND HOME BLOCK
	MOVE T2,[1B0+1B14+HBLEN] ;T2/WRITE, ADDRESS IS (CHAN,,UNIT), LENGTH
	MOVE T3,UPDHPA		;T3/PHYSICAL ADDRESS OF START OF PAGE
	ADDI T3,HBLEN		;POINT TO SECOND BLOCK OF DATA
	MOVE T4,UPDHCU		;T4/(CHANNEL,,UNIT)
	CALL UDSKIO		;WRITE THE SECOND HOME BLOCK TO THE DISK
	SKIPN T1		;WERE THERE ANY ERRORS?
	SKIPE Q1		;NO. HOW ABOUT WITH BLOCK 1
	RETBAD			;YES. TAKE ERROR RETURN
	RETSKP			;NO ERRORS. TAKE SUCCESS RETURN
	RESCD(INIT)
;ROUTINE TO READ ALL BAT BLOCKS ON A GIVEN STRUCTURE AND
;PERFORM A QUICK CONSISTENCY CHECK FOR THE GIVEN STRUCTURE.
;IF THE PUBLIC STRUCTURE IS GIVEN, IT MARKS OFF IN THE SWAPPING
;SPACE BIT TABLE DISK ADDRESSES IN THE SWAPPING SPACE THAT ARE BAD

;		CALL CHKBAT
;
;ACCEPTS:
;	T1/ STRUCTURE NUMBER
;	T2/ VIRTUAL ADDRESS OF PAGE TO READ BAT BLOCKS INTO
;	T3/ FLAGS
;		CALL CHKBAT
;RETURNS: +1 ALWAYS WITH APPROPRIATE WARNINGS AND MESSAGES OUTPUT
;	     ON THE CTY AND LOGGED IN THE ERROR FILE

;USE OF P REGISTERS:
;	P1/ PHYSICAL ADDRESS OF BAT BLOCK PAGE
;	P4 /(-NUMBER PACKS,,SDBUDB FOR CURRENT PACK)
;	P5 /STRUCTURE NUMBER

CHKBAT::SAVEP			;GET SOME WORK SPACE
;**;[1867] Change one line at CHKBAT: +1L	RAS	6-MAY-81
	STKVAR <CKBADR,CKBPAG,CKBFLG>
	MOVEM T2,CKBADR		;SAVE VIRTUAL ADDRESS OF BAT BLOCK PAGE
	MOVEM T3,CKBFLG		;SAVE FLAGS
	MOVE P5,A
	MOVE T1,CKBADR		;GET VIRTUAL ADDRESS OF BAT BLOCK PAGE
	CALL MLKMA		;LOCK IT DOWN
	MOVEM A,CKBPAG		;SAVE PHYSICAL PAGE NUMBER
	MOVEI P1,(T1)		;GET PHYSICAL PAGE NUMBER
	LSH P1,PGSFT		;SAVE CORE ADDRESS
BATSTR:	SKIPN P4,STRTAB(P5)	;THIS STRUCTURE EXIST?
	JRST NXTUN1		;NO. GO TO NEXT
	MOVN T1,SDBNUM(P4)	;GET -NUMBER OF PACKS
	HRLI P4,0(T1)		;FORM AOBJN POINTER
	HRRI P4,SDBUDB(P4)	;AND POINT TO FIRST UDB

;LOOP THROUGH PACKS
;	P4/(NEGATIVE COUNT,,SDBUDB)

DOUNIT:	MOVE T1,CKBADR		;GET VIRTUAL ADDRESS OF BAT BLOCK PAGE
	MOVE T2,P1		;GET PHYSICAL ADDRESS OF BAT BLOCK PAGE
	MOVE T3,CKBFLG		;GET FLAGS
	HRRZ T4,(P4)		;GET ADDRESS OF UDB
	CALL DOPACK		;GO CHECK THE BAT BLOCKS ON ONE UNIT
	 JRST NXTUN1		;DON'T TRY TO MARK OFF SWAPPING SPACE
	;..
	;..

;ROUTINE TO MARK OFF SWAPPING SPACE WHICH HAS BEEN RECORDED BAD
;AND TO MOVE TO THE NEXT LOGICAL UNIT

NXTUNT:	JUMPN P5,NXTUN1		;IS THIS THE PUBLIC STRUCTURE
	MOVE A,CKBADR		;GET VIRTAUL ADDRESS OF FIRST BAT BLOCK
	CALL BATSPC		;FOUND SPACE IN BLOCK
	MOVEI P3,MAXBFR(A)	;FIND NUMBER USED
	JUMPE P3,NXTUN1		;NONE HERE
	LSH P3,-1		;CALCULATE NUMBER OF PAIRS
	MOVE C,CKBADR		;GET VIRTUAL ADDRESS OF FIRST BAT BLOCK
	ADDI C,BAT1P		;FIRST BAD ONE
DOBADS:	LOAD A,BADT,(C)		;GET TYPE OF THIS PAIR
	SKIPN A			;OLD?
	JRST [	LOAD A,ADD18,(C) ;YES.
		JRST GTADR]	;GO INLINE
	LOAD A,ADD27,(C)	;NO. GET NEW TYPE
GTADR:	LOAD B,BATNB,(C)	;NUMBER OF BAD ONES
	ADD B,A			;CALCULATE LAST SECTOR
;**;[1867] Replace 31 lines with 1 at GTADR: +2L	RAS	6-MAY-81
	CALL DSPAIR		;[1867] MARK BAT SECTORS IN BIT TABLE
	ADDI C,2		;NEXT PAIR
	SOJG P3,DOBADS		;DO ALL PAIRS
NXTUN1:	AOBJN P4,DOUNIT		;DO ALL PACKS
	MOVE A,CKBPAG		;GET PHYSICAL PAGE NUMBER OF BAT BLOCK PAGE
	CALLRET MULKCR		;UNLOCK THE PAGE AND RETURN
;**;[1867] Insert 84 Lines at NXTUN1: +3L		RAS	6-MAY-81
;DSPAIR
;Routine to mark a bat block pair as used in the drum bit table.
;
;Accepts:
;
;	T1/ Physical Disk Address of first bad sector
;	T2/ Physical Disk Address of last bad sector
;	P4/ (Negative Count,,SDBUDB)
;	P5/ Structure Number
;
;		CALL DSPAIR
;
;Returns: +1 	Always.
;	     	All sectors defined by arguments which correspond to
;	     	logical sectors are marked in the drum bit table
;	
;	Destroys T1 and T2
;
;Use of Registers:
;
;	C/  DSKSIZ Table
;	D/  SDB
;	P1/ PHYSICAL ADDRESS OF BAT BLOCK PAGE
;	P4 /(-NUMBER PACKS,,SDBUDB FOR CURRENT PACK)
;	P5 /STRUCTURE NUMBER

DSPAIR:	CAML T1,T2		;[1867] STILL WITHIN THE REGION?
	 RET			;[1867] NO, FINISHED WITH THIS PAIR
	CALL DOSECT		;[1867] MARK THIS SECTOR AS USED
	JRST DSPAIR		;[1867] YES. GO DO IT

DOSECT:	SAVEAC <T2,T3,T4>	;[1867]
	STKVAR <CURBAT,CKBDRA>	;[1867]
	MOVEM T1,CURBAT		;[1867] SAVE PHYS SECT ADDRESS OF FIRST SECTOR
	MOVE T4,STRTAB(P5)	;[1867] GET SDB
	MOVE T3,SDBTYP(T4)	;[1867] POINT TO SIZE DATA FOR THIS DISK TYPE
	CALL CVDADR		;[1867] FIND LOGICAL SECTOR NUMBER
	 RET			;[1867] THIS IS A LOST SECTOR, FORGET IT
	IDIV T1,SECPAG(T3)	;[1867] GET INTEGRAL NUMBER OF PAGES
	IMUL T1,SECPAG(T3)	;[1867] FIND STARTING SECTOR FOR PAGE
	SUB T1,SDBFSS(T4)	;[1867] SEE IF WITHIN SWAPPING BOUNDS
	SKIPL T1		;[1867] IS IT?
	CAML T1,SDBNSS(T4)	;[1867] ?
	 JRST DSECT1		;[1867] NO
	IDIV T1,SECCYL(T3)	;[1867] FIND TRACK AND SECTOR OFFSET IN TRACK
	IMUL T1,SDBNUM(T4)	;[1867] FIND INTERLEAVED TRACK NUMBER
	MOVEI T4,-SDBUDB(P4)	;[1867] GET PACK # + SDB LOCATION
	SUB T4,STRTAB(P5)	;[1867] COMPUTE PACK NUMBER IN STRUCTURE
	ADD T1,T4		;[1867] ADD PACK NUMBER ...
	IMUL T1,SECCYL(T3)	;[1867] FIND STARTING SWAP SECT FOR THIS TRACK
	ADD T1,T2		;[1867] ADD IN SECTOR OFFSET IN TRACK
	TXO T1,DRMOB		;[1867] SAY IS AN OVERFLOW ADDRESS
	MOVEM T1,CKBDRA		;[1867] SAVE ADDRESS TO BE ASSIGNED
	CALL DRMASA		;[1867] ASSIGN DRUM ADDRESS
	 JRST [	MOVE T3,STRTAB+PSNUM ;[1867] POINT TO SDB FOR PS (ONLY CASE
		LOAD T3,STRNAM,(T3) ;[1867]  IN WHICH WE GET HERE)
		SKIPE T1	;[1867] OUT-OF-RANGE?
		BUG(SWPASF,<<T3,T4>,<CKBDRA,T4>>)
		JRST DSECT1]	;[1867]
DSECT1:	MOVE T1,CURBAT		;[1867] GET BACK PHYSICAL SECTOR ADDRESS
;**;[1874] Insert two lines at DSECT1: +1L	RAS	13-MAY-81
	MOVE T4,STRTAB(P5)	;[1874] GET SDB
	MOVE T3,SDBTYP(T4)	;[1874] POINT TO SIZE DATA FOR THIS DISK TYPE
	ADD T1,SECPAG(T3)	;[1867] STEP THE SECTORS BY A PAGE
	RET			;[1867] AND RETURN

;CVDADR - Local routine to DSPAIR to convert a physical unit address to
; a logical linear unit sector address, accounting for lost sectors.
;
;ACCEPTS
;  T1/	Physical Sector Address
;  T3/	DSKSIZ table for structure type
;
;	CALL	CVDADR
;
;RETURNS  +1:	Address is for a lost sector.
;		T1/  Physical sector address just following lost region
;	  +2:	T1/  Logical sector address
;
;Uses T1-T3.  Preserves T4.

CVDADR:	SAVEAC <T4>
	MOVE T4,SECCYL(T3)	;[1867] GET LOGICAL SECTORS/CYLINDER
	ADD T4,LPPCYL(T3)	;[1867] ADD LOST SECT TO GET PHYSICAL SEC/CYL
	IDIV T1,T4		;[1867] GET CYL IN T1, SEC IN T2
	CAML T2,SECCYL(T3)	;[1867] IS THIS A LOST SECTOR?
	JRST [	AOS T1		;[1867] YES, GET CYL FOLLOWING THIS LOST REGION
		IMUL T1,T4	;[1867] FIND PHYS SECT NUMBER OF FIRST SECTOR
		RET]		;[1867] AND RETURN
	IMUL T1,SECCYL(T3)	;[1867] CONVERT CYL TO LOGICAL SECTORS
	ADD T1,T2		;[1867] COMBINE TO GET LOGICAL ADR
	RETSKP			;[1867] AND TAKE SKIP RETURN

; ROUTINE TO CHECK THE BAT BLOCKS ON A SINGLE UNIT
;
; ACCEPTS IN T1/ VIRTUAL ADDRESS OF BAT BLOCK PAGE
;	     T2/ PHYSICAL ADDRESS OF BAT BLOCK PAGE
;	     T3/ FLAGS
;		MI%MSG - TYPE MESSAGES ON CTY IF ON
;		MS%NFB - DO NOT FIX BAD BAT BLOCKS
;	     T4/ ADDRESS OF UDB FOR THIS UNIT
;		CALL DOPACK
; RETURNS: +1	 FAILED, BAT BLOCKS BAD (ONLY TAKEN IF MS%NFB WAS ON)
;	   +2	SUCCESS, BAT BLOCKS GOOD OR REPAIRED IF BAD


DOPACK:	SAVEP
	ASUBR <PAKVIR,PAKPHY,PAKFLG,PAKUDB>
	MOVEI P4,PAKUDB		;SET UP POINTER TO ADDRESS OF UDB
	CALL SETBAT		;SET NO BAT BIT
	CALL FNDCHN		;GO FIND CHANNEL,,UNIT FOR THIS PACK
	MOVE P2,T1		;SAVE THE PHYSICAL ID
	MOVE T3,PAKVIR		;VIRTUAL ADDRESS TO READ INTO
	MOVE T2,PAKPHY		;CORE ADDRESS
	CALL GETBAT		;GET THE BAT BLOCKS INTO CORE
	MOVE T2,T1		;MOVE THE MASK
	TLNN T2,(1B0)		;IS ONE OK?
	JRST ONEBAD		;NO. HOPE 2 IS OK!
	TLNE T2,(1B1)		;IS 2 OK?
	JRST CMPBAT		;YES. GO COMPARE BAT BLOCKS
TWOBAD:	MOVE T1,PAKFLG		;GET FLAGS
	TXNE T1,MS%NFB		;FIX THE BAD BAT BLOCK ?
	RET			;NO, RETURN FAILURE (BAT BLOCK BAD)
	MOVE T2,PAKVIR		;GET VIRTUAL ADDRESS OF FIRST BAT BLOCK
	MOVE T3,PAKPHY		;PHYSICAL CORE ADDRESS
	CALL CPY1		;COPY PRIMARY
	 JRST NOBATS		; ASSUME NONE THERE
	JRST CHKFUL

;PRIMARY BAT BLOCK IS INCORRECT

ONEBAD:	TLNN T2,(1B1)		;IS THE BACKUP OK?
	JRST NOBATS		;NO. WE LOSE
	MOVE T1,PAKFLG		;YES, GET FLAGS
	TXNE T1,MS%NFB		;FIX THE BAD BAT BLOCK ?
	RET			;NO, RETURN FAILURE (BAD BAT BLOCK)
	MOVE T2,PAKVIR		;GET ADDRESS OF BAT BLOCKS
	MOVE T3,PAKPHY		;PHYSICAL CORE ADDRESS
	CALL CPY2		;COPY SECONDARY TO PRIMARY BAT BLOCK
	 JRST NOBATS		; ASSUME NONE THERE
; HERE TO COMPARE THE TWO BAT BLOCKS

CMPBAT:	MOVE T1,PAKVIR		;GET ADDRESS OF FIRST BAT BLOCK
	CALL BATCMP		;COMPARE THE TWO BLOCKS
	 SKIPA			;DIDNT MAKE IT
	JRST CHKFUL		;THEY COMPARE!
NOCMPR:	MOVE T1,PAKFLG		;GET FLAGS
	TXNN T1,MI%MSG		;MESSAGE REQUESTED ?
	JRST TWOBAD		;NO, GO ON
	HRROI T1,[ASCIZ /%BAT blocks do not compare on /]
	CALL FSIPSO
	CALL UNTSTR		;OUTPUT STRUCTURE/UNIT MESSAGE
	HRROI T1,[ASCIZ /
/]
	CALL FSIPSO
	JRST TWOBAD		;SO DO THE COPY
CHKFUL:	CALL CLRBAT		; CLEAR BAT BIT
	MOVE T1,PAKVIR		;GET ADDRESS OF BAT BLOCKS
	CALL BATSPC		;FOUND SPACE LEFT
	JUMPN A,RSKP		;IF ROOM LEFT, GO ON
	MOVE T1,PAKFLG		;GET FLAGS
	TXNN T1,MI%MSG		;MESSAGE REQUESTED ?
	RETSKP			;NO, RETURN SUCCESS
	HRROI T1,[ASCIZ /%BAT block full on /]
	CALL FSIPSO
	CALL UNTSTR		;OUTPUT STRUCTURE/UNIT MESSAGE
	HRROI T1,[ASCIZ /
/]
	CALL FSIPSO		;FINISH IT OFF
	RETSKP			;RETURN SUCCESS

;HERE IF UNIT DOES NOT HAVE CONSISTENT BAT BLOCKS

NOBATS:	MOVE T1,PAKFLG		;GET FLAGS
	TXNN T1,MI%MSG		;MESSAGES REQUESTED ?
	JRST CREBAT		;NO, GO SEE IF NEW BAT BLOCKS ARE WANTED
	MOVEI T1,"?"		;YES, GET FIRST CHARACTER OF ERROR MESSAGE
	CALL FSIPBO		;OUTPUT INITIAL PART OF MESSAGE
	CALL UNTSTR		;STRUCTURE/UNIT MESSAGE
	HRROI T1,[ASCIZ / has no consistent BAT blocks
/]
	CALL FSIPSO		;TELL HIM
CREBAT:	MOVE T1,PAKFLG		;GET FLAGS
	TXNE T1,MS%NFB		;FIX THE BAT BLOCKS ?
	RETSKP			;NO, RETURN
	XMOVEI P4,PAKUDB	;GET POINTER TO ADDRESS OF UDB
	CALL FNDCHN		;GET CHANNEL AND UNIT NUMBERS
	MOVE T2,PAKVIR		;GET VIRTUAL ADDRESS FOR NEW BAT BLOCKS
	MOVE T3,PAKPHY		;GET PHYSICAL ADDRESS FOR NEW BAT BLOCKS
	SETZM T4		;NO FLAGS
	CALL MAKBAT		;MAKE A SET OF NEW BAT BLOCKS
	 RET			;FAILED, RETURN ERROR
	RETSKP			;DONE, RETURN SUCCESS
;ROUTINE TO OUTPUT STANDARD STRUCTURE/UNIT MESSAGE
;	P5/ STRUCTURE NUMBER
;	P4/ SDBUDB POINTER

UNTSTR:	HRRZ T1,STRTAB(P5)	;GET SDB POINTER
	MOVE T1,SDBNAM(T1)	;GET IT'S NAME
	CALL FSI6TY		;OUTPUT SIXBIT NAME
	HRROI T1,[ASCIZ / unit /]
	CALL FSIPSO		;OUTPUT LITERAL STRING
	MOVE T1,(P4)		;GET ADDRESS OF UDB FOR THIS UNIT
	HLRZ T1,UDBSTR(T1)	;GET UNIT NUMBER
	CALLRET FSIOTY		;OUTPUT OCTAL NUMBER
;THIS ROUTINE COMPARES TWO BAT BLOCKS
;ACCEPTS:	T1/ VIRTUAL ADDRESS OF FIRST BAT BLOCK
;
;RETURNS: +1 NO COMPARE
;	  +2 COMPARE

BATCMP:	MOVEI T3,HBLEN-1	;DO 127 WORDS
	MOVE T2,T1		;GET ADDRESS OF FIRST BAT BLOCK
	MOVEI T4,HBLEN(T2)	;GET ADDRESS OF SECOND BAT BLOCK
CMPR:	MOVE T1,(T2)		;GET WORD FROM BLOCK 1
	CAME T1,(T4)		;SAME IN BLOCK 2?
	RET			;NO COMPARE
	ADDI T2,1
	ADDI T4,1		;NEXT WORD
	SOJG T3,CMPR		;DO ALL OF BLOCK
	RETSKP			;EXACT


;ROUTINES TO SET AND CLEAR DSKBAT IN DSKSTS
;ACCEPTS P4/ SDBUDB POINTER
;
;RETURNS +1 ALWAYS

SETBAT:	TDZA T1,T1		; REMEMBER THIS ENTRY
CLRBAT:	MOVEI T1,1		; REMEMBER THIS ENTRY
	MOVX T2,US.BAT		; THE BIT IN QUESTION
	HRRZ T3,0(P4)		;GET UDB POINTER
	XCT [	IORM T2,UDBSTS(T3) ;SET BIT
		ANDCAM T2,UDBSTS(T3)](T1) 
	RET
;THIS ROUTINE WILL READ THE BAT BLOCKS INTO A SPECIFED BUFFER
;ACCEPTS T1/ CHANNEL#,,UNIT#
;	  T2/ CORE ADDRESS
;	  T3/ VIRTUAL CORE ADDRESS
;RETURNS +1 ALWAYS WITH
;	1B0 0F T1 =1 IF PRIMARY IS IN AND GOOD
;	1B1 OF T1 =1 IF SECONDARY IS IN AND GOOD

GETBAT::SAVEP			;GET SOME REGS
	MOVEI P1,(T3)		;SAVE VIRTUAL ADDRESS
	MOVEI T3,BATBL1		;LOCAL ADDRESS OF FIRST BAT BLOCK
	MOVE P2,T1		;SAVE DRIVE
	MOVEI T4,(P1)		;VIRTUAL CORE ADDRESS
	CALL REDHOM		;GET THE BAT BLOCKS IN CORE
	 JFCL			;IGNORE ERROR CONDITIONS
	MOVEI T1,(P1)		;CORE ADDRESS
	MOVEI T2,BATBL1		;BLOCK NUMBER
	SETZ P3,
	CALL BATLOK		;VERIFY BLOCK IS GOOD
	 JRST CHKBT1		;NOT. GO LOOK AT NEXT ONE
	MOVSI P3,(1B0)		; SAY 1 IS GOOD
CHKBT1:	MOVEI T1,(P1)
	ADDI T1,HBLEN		;POIINT TO SECOND ONE
	MOVEI T2,BATBL1+HM2BLK-HM1BLK ;IS AFTER NEXT BLOCK
	CALL BATLOK		;GO CHECK SECOND BAT BLOCK
	TDZA T1,T1		; 2 IS BAD
	MOVSI T1,(1B1)		;SAY 2 IS GOOD
	IOR T1,P3		;MASK THEM TOGETHER
	RET
;ROUTINE TO WRITE OUT THE BAT BLOCKS FOR A GIVEN PHYSICAL DRIVE
;ACCEPTS 1/CHANNEL#,,UNIT#
;	  3/ CORE ADDRESS OF FIRST BLOCK
;RETURNS: +1 WRITE FAILED
;	  +2 OK

BATOUT::STKVAR <SVCOR,SVDRV,TEST1>
	SETZM TEST1		;ASSUME NONE WORKED
	MOVEM T3,SVCOR		;SAVE CORE ADDRESS
	MOVEM T1,SVDRV		;SAVE THIS ADDRESS
	MOVE T2,[1B0+1B14+HBLEN] ;CONTROL WORD
	MOVE T3,SVCOR
	MOVE T4,SVDRV		;GET CHANNEL,,UNIT
	MOVEI T1,BATBL1		;BLOCK NUMBER
	CALL UDSKIO		;OPRATE THE DISK
	JUMPE T1,DO2B		;IF NO ERROR,GO ON
	SETOM TEST1		;MARK FAILURE
	HLRZ T1,SVDRV		;GET CHANNEL
	HRRZ T2,SVDRV		;GET UNIT
	BUG(NOBAT1,<<T1,D>,<T2,D>>)
DO2B:	MOVE T2,[1B0+1B14+HBLEN] ;CONTROL WORD
	MOVE T3,SVCOR
	ADDI T3,HBLEN		;TO NEXT GUY
	MOVEI T1,BATBL1+HM2BLK-HM1BLK ;ADDRESS OF SECONDARY BLOCK
	MOVE T4,SVDRV
	CALL UDSKIO		;OPERATE DISK AGAIN
	SKIPN T1		; GOOD?
	RETSKP			;YES. SAY IT IS GOOD THEN
	HLRZ T1,SVDRV		;GET CHANNEL
	HRRZ T2,SVDRV		;GET UNIT
	BUG(NOBAT2,<<T1,D>,<T2,D>>)
	SKIPE TEST1		;DID IT WRITE THE PRIMARY?
	RET			;NO. NONE GOOD THEN
	RETSKP			;YES. ONE IS GOOD
;ROUTINE TO CHECK THE BAT BLOCK FOR CONSISTENCY
;ACCEPTS IN T1/ CORE ADDRESS OF BAT BLOCK
;	     T2/ BLOCK #
;RETURNS: +1 INCOSISTENT BAT BLOCK
;	  +2 CONSISTENT

BATLOK:	MOVS T3,BATNAM(T1)	;GET THE NAME
	CAIE T3,'BAT'		;IS IT A BAT BLOCK
	RETBAD			;BAD
	MOVE T3,BATCOD(T1)	;GET UNLIKELY CODE
	CAIE T3,CODBAT		;GOOD?
	RETBAD			;NO
	MOVE T3,BATBLK(T1)	;GET BLOCK NUMBER
	CAME T3,T2		;CORRECT ONE?
	RETBAD			;NO
	RETSKP			;IT'S GOOD
;FSIDIA - DIAGLOGUE TO DEFINE THE PUBLIC STRUCTURE

;	CALL FSIDIA

;RETURNS +1: ALWAYS,
;		FLAGS SET IN STARTF INDICATING ANSWERS TO QUESTIONS

;THIS IS ALWAYS CALLED WHEN THE SYSTEM IS STARTED AT SYSLOD. IT ACCEPTS
;INFORMATION FROM THE USER AND WRITES THE HOME BLOCKS (IF REQUESTED)
;ON THE SPECIFIED PACKS, THUS CREATING A STRUCTURE.  IT DOES NOT
;BUILD AN SDB FOR THE STRUCTURE

FSIDIA:	MOVSI T1,-HOMTBL	;CLEAR OUT PHYSICAL DRIVE CORRESPONDENCE
	SETOM HOMTAB(T1)	;FOR DETECTING MULTIPLE REFERENCES
	AOBJN T1,.-1
	HRROI T1,[ASCIZ/
[For additional information type "?" to any of the following questions.]
/]
	CALL FSIPSO

;SEE IF USER WANTS TO REFRESH THE FILE SYSTEM

FSIDI0:	SETOM FSIUSZ		;INDICATE UNIT SIZE UNKNOWN
	HRROI T1,[ASCIZ/
DO YOU WANT TO REPLACE THE FILE SYSTEM ON THE PUBLIC STRUCTURE? /]
	HRROI T2,[ASCIZ/
[THIS PROCEDURE REMOVES ALL EXISTING DIRECTORIES AND FILES AND CREATES
THE MININUM DIRECTORIES NEEDED TO BRING UP THE SYSTEM.]
/]
	MOVEI T3,FSIYNO		;GET YES OR NO
	CALL FSIASK		;GO ASK QUESTION AND GET ANSWER IN T1
	 JRST FSIDI0		;ERROR, GO ASK AGAIN
	SKIPN T1		;WAS THE ANSWER YES?
	JRST [	MOVX T4,MI%RFS	;NO. INDICATE NOT REFRESHING
		ANDCAM T4,STARTF
		MOVX T4,MI%RCN	; BUT RATHER MIGHT BE RECONSTRUCTING
		IORM T4,STARTF	; FOR FILINI TO DETECT LATER
		MOVE T2,DBUGSW	;IF DEBUGGING, ALLOW THEM TO REWRITE THE
		CAIE T2,2	; THE HOME BLOCKS. OTHERWISE, ASSUME
		RET		; THEY COULD DO THEMSELVES IN
		JRST .+1]
	SETOM FEFSIZ		;INDICATE SIZE OF FE FILE SYSTEM UNKNOWN
;**;[1986] Add one line at FSIDI4: -3L	JGZ	21-FEB-82
	SETOM	BOTSIZ		;[1986] INDICATE SIZE OF BOOTSTRAP.BIN UNKNOWN

;SEE IF USER WANTS TO REWRITE THE HOME BLOCKS

FSIDI4:	HRROI T1,[ASCIZ/
DO YOU WANT TO DEFINE THE PUBLIC STRUCTURE? /]
	HRROI T2,[ASCIZ/
[THIS WILL CAUSE THE HOME BLOCKS TO BE REWRITTEN.  IT SHOULD BE DONE
ONLY IF THE ANSWER TO THE PREVIOUS QUESTION WAS YES.]
/]
	MOVEI T3,FSIYNO		;GET YES OR NO
	CALL FSIASK		;ASK THE QUESTION AND GET THE ANSWER
	 JRST FSIDI4		;FAILED. TRY AGAIN
	JUMPE T1,R		;IF NO. DON'T REWRITE HOME BLOCKS

;USER WANTS TO REWRITE HOME BLOCKS. IF NOT ALSO REFRESHING FILE SYSTEM,
;PRINT WARNING BUT CONTINUE

	MOVX T4,MI%HMB		;YES. INDICATE HOME BLOCKS ARE TO BE
	IORM T4,STARTF		; REWRITTEN FOR FILINI TO DETECT LATER
	MOVX T4,MI%RFS		;ARE WE REFRESHING THE FILE SYSTEM?
	TDNE T4,STARTF
	JRST FSIDI1		;YES. OK THEN
	HRROI T1,[ASCIZ/
WARNING: THIS IS A DANGEROUS PROCEDURE.  IT MAY CAUSE INCONSISTENCY
IN THE STRUCTURE.
/]
	CALL FSIPSO		;OUTPUT THE WARNING

;FIND OUT WHAT PACKS ARE IN THE STRUCTURE

FSIDI1:	HRROI T1,[ASCIZ/
How many packs are in thIS Structure: /]
	HRROI T2,[ASCIZ/
[Enter the decimal number of disk packs that compose thIS STRUCTURE]
/]
	MOVEI T3,FSIDEC		;GET DECIMAL NUMBER OF PACKS
	CALL FSIASK		;GO ASK QUESTION AND GET ANSWER
	 JRST FSIDI1		;ERROR, GO ASK QUESTION AGAIN
	JUMPLE T1,[HRROI T1,[ASCIZ/? The answer must be greater than zero!
/]
		CALL FSIPSO	;TYPE OUT COMPLAINT
		JRST FSIDI1]	;GO ASK QUESTION AGAIN
	MOVEM T1,FSINPK		;SAVE COUNT OF PACKS IN PUBLIC STR
	MOVEM T1,FSIDIC		;SAVE THIS COUNT FOR ENSUING QUESTIONS
	CAILE T1,HOMTBL		;IS THIS NUMBER TOO BIG?
	JRST [	HRROI T1,[ASCIZ/? The monitor is not assembled to handle that many units!
/]
		CALL FSIPSO	;TYPE OUT MESSAGE
		JRST FSIDI1]	;ASK QUESTION AGAIN
	;..
	;..
;GET THE CHANNEL AND UNIT FOR EACH LOGICAL UNIT IN THE STRUCTURE.
;STORE IN HOMTAB, INDEXED BY LOGICAL UNIT NUMBER, (CHANNEL,,UNIT)

FSIDI2:	MOVE T1,[POINT 7,FSIBLK] ;SET UP TO BUILD QUESTION STRING
	MOVE T2,[POINT 7,[ASCIZ/
On which "CHANNEL,UNIT" is logical pack # /]]
	CALL FSICPY		;COPY STRING TO TEMP BLOCK
	MOVE T2,FSINPK		;CALCULATE NUMBER OF THIS UNIT
	SUB T2,FSIDIC		;UNITS START AT 0, THEN 1, 2, ...
	MOVEI T3,12		;SET RADIX TO 10
	CALL FSINST		;PUT PACK # IN QUESTION STRING
	MOVE T2,[POINT 7,[ASCIZ/ mounted: /]]
	CALL FSICPY		;FINISH BUILDING QUESTION STRING
	HRROI T1,FSIBLK		;GET POINTER TO QUESTION STRING
	MOVEI T2,FSICFG		;HELP MESSAGE ROUTINE
	MOVEI T3,FSIDEC		;GET PHYSICAL DRIVE #
	CALL FSIASK		;ASK QUESTION AND GET ANSWER
	 JRST FSIDI2		;ERROR, GO ASK QUESTION AGAIN
	MOVEM T1,FSICHN		;SAVE CHANNEL NUMBER
	SKIPE CHNTAB(T1)	;EXIST?
	CAMLE T1,MAXCHN		;IS IT OK?
	JRST [	HRROI T1,[ASCIZ/? ILLEGAL CHANNEL NUMBER.
/]
		CALL FSIPSO
		JRST FSIDI2]
	CALL FSIDEC		;READ IN SECOND NUMBER
	 JRST FSIDI2		;ERROR
	MOVEM T1,FSIUNT		;SAVE UNIT NUMBER
	CAIL T1,MAXRH		;IS MONITOR BUILT FOR THIS HIGH A #?
	JRST [	HRROI T1,[ASCIZ/? UNIT NUMBER TOO HIGH.
/]
		CALL FSIPSO	;NO, TYPE OUT APPROPRIATE MESSAGE
		JRST FSIDI2]	;AND GO ASK QUESTION AGAIN
	MOVE T1,FSICHN		;GET CHANNEL NUMBER
	MOVE T1,CHNTAB(T1)	;GET CDB
	MOVE T2,FSIUNT		;GET UNIT NUMBER
	ADD T2,CDBIUN(T1)	;GET POINTER TO UDB
	SKIPN T1,(T2)		;GET UDB
	JRST [	HRROI T1,[ASCIZ /? NO SUCH UNIT.
/]
		CALL FSIPSO	;ANNOUNCE LOSSAGE
		JRST FSIDI2]	;AND TRY THAT ONE AGAIN.
	LOAD T2,USTYP,(T1)	;GET UNIT TYPE
	MOVSI T3,-NDSKUT	;SETUP LOOP
	CAME T2,DSKUTP(T3)	;SEARCH FOR
	AOBJN T3,.-1		;THIS TYPE
	SKIPL T3		;WAS IT FOUND?
	JRST [	HRROI T1,[ASCIZ /? NOT A SUPPORTED FILE DISK.
/]
		CALL FSIPSO	;PRINT MESSAGE
		JRST FSIDI2]	;AND TRY FOR A GOOD RESPONSE
	MOVE T3,DSKSIZ(T3)	;GET ADDRESS OF SIZE DATA FOR THIS TYPE
	MOVEM T3,FSITYP		;SAVE IT FOR WRTHOM
	MOVE T2,CYLUNT(T3)	;GET NUMBER OF CYLINDERS
	SKIPGE FSIUSZ		;UNIT SIZE SET YET?
	MOVEM T2,FSIUSZ		;NO - SET IT
	CAME T2,FSIUSZ		;CHECK IF SAME AS OTHER UNITS
	JRST [	HRROI T1,[ASCIZ /? ALL DISK UNITS IN A SINGLE STRUCTURE MUST BE THE SAME SIZE.
/]
		CALL FSIPSO	;CHIDE USER
		JRST FSIDI2]	;AND TRY AGAIN
	IMUL T2,FSINPK		;CHECK IF A STRUCTURE THIS LARGE IS OK
;**; [1731] Fix calc of size of resultant BTB  RAS   6-JUN-80

	MOVE T1,BTWCYL(T3)	; Get number of Bit words per cylinder
	AOS T1			; Add one word per cyl for top half of BTB
	IMUL T2,T1		; CYL/STR * BTB words/CYL = size of BTB
	CAMLE T2,BTBSIZ		; I.E,. ITS BIT TABLE ISN'T TOO BIG)
	JRST [	HRROI T1,[ASCIZ /? YOU ARE ATTEMPTING TO DEFINE A STRUCTURE WHICH HAS MORE SPACE THAN IS SUPPORTED.
/]
		CALL FSIPSO
		JRST FSIDI0]	;RESTART THE WHOLE AFFAIR
	MOVE T2,FSINPK		;GET LOGICAL PACK NUMBER AGAIN
	SUB T2,FSIDIC		;...
	HRL T3,FSICHN		;T3/(CHANNEL,,UNIT) SPECIFIED
	HRR T3,FSIUNT
	MOVE T4,T2		;LIMIT SEARCH TO PREVIOUS ENTRY
	SOS T4
	JUMPL T4,FSIDI8		;NO PREVIOUS ENTRIES. NO DUPLICATION
	MOVNS T4		;GET NEGATIVE COUNT
	HRLZS T4		;T4/(-COUNT,,LOGICAL UNIT NUMBER)
FSIDI7:	CAMN T3,HOMTAB(T4)	;HAS THIS PAIR BEEN SPECIFIED BEFORE?
	JRST [	HRROI T1,[ASCIZ/? That drive was already assigned
/]
		CALL FSIPSO	;TYPE OUT COMPLAINT
		JRST FSIDI2]	;ASK QUESTION AGAIN
	AOBJN T4,FSIDI7		;NO. KEEP LOOKING
FSIDI8:	MOVEM T3,HOMTAB(T2)	;STORE (CHANNEL,,UNIT) FOR THIS LOGICAL UNIT
	SOSLE FSIDIC		;ANY MORE PACKS IN THE STR?
	JRST FSIDI2		;YES, ASK ABOUT THEM ALSO
FSIDI3:	HRROI T1,[ASCIZ/
DO YOU WANT THE DEFAULT SWAPPING SPACE? /]
	MOVEI T2,FSIPSW		;T2/ROUTINE TO TYPE HELP TEXT
	MOVEI T3,FSIYNO		;T3/ROUTINE TO GET YES OR NOT
	CALL FSIASK		;ASK THE QUESTION
	 JRST FSIDI3		;ERROR. GO ASK AGAIN
	JUMPN T1,[	MOVE T1,NSWPGS
			JRST FSIDI6]

;USER DOESN'T WANT THE DEFAULT. GET THE USER'S CHOICE

FSIDI5:	HRROI T1,[ASCIZ/
HOW MANY PAGES FOR SWAPPING? /]
	HRROI T2,[ASCIZ/
[ENTER THE DECIMAL NUMBER OF PAGES TO BE ALLOCATED FOR THE ENTIRE
STRUCTURE]
/]
	MOVEI T3,FSIDEC		;READ A DECIMAL NUMBER
	CALL FSIASK		;ASK THE QUESTION AND GET THE ANSWER
	 JRST FSIDI5		;ERROR. ASK AGAIN
FSIDI6:	MOVEM T1,FSISWP		;SAVE THE ANSWER
	CAIGE T1,^D2000		;IS THIS ENOUGH SWAPPING SPACE?
	JRST FSIDI9		;NO. PS MUST HAVE ENOUGH
	HLRZ T1,HOMTAB		;T1/ CHANNEL OF FIRST LOGICAL UNIT
	HRRZ T2,HOMTAB		;T2/ UNIT OF FIRST LOGICAL UNIT
	MOVE T3,FSINPK		;T3/NUMBER OF UNITS IN STRUCTURE
	MOVE T4,FSISWP		;T4/NUMBER OF SWAPPING PAGES SPECIFIED
	CALL CHKSWP		;SEE IF THIS ANSWER IS VALID
	 SKIPA			;INVALID. GO COMPLAIN
	JRST FSID10		;VALID. PROCEED

FSIDI9:	HRROI T1,[ASCIZ/
? INVALID NUMBER OF SWAPPING PAGES FOR THIS TYPE OF DISK.
/]
	CALL FSIPSO		;PRINT THE COMPLAINT
	JRST FSIDI3		;GO ASK AGAIN

;IF USER IS REFRESHING, FIND OUT HOW MUCH ROOM TO ALLOCATE FOR THE
;FRONT END FILE SYSTEM

FSID10:	MOVX T4,MI%RFS		;ARE WE REFRESHING?
	TDNN T4,STARTF
	JRST FSID17		;NO. DON'T ASK ABOUT THE SIZE
	HRROI T1,[ASCIZ/
DO YOU WANT THE DEFAULT SIZE FRONT END FILE SYSTEM? /]
	HRROI T2,[ASCIZ/
[THE DEFAULT IS 950 PAGES]
/]
	MOVEI T3,FSIYNO		;GET YES OR NO
	CALL FSIASK		;ASK QUESTION AND GET THE ANSWER
	 JRST FSID10		;ERROR. ASK AGAIN
	JUMPN T1,[MOVEI T1,NPGSFE
		JRST FSID12]

;USER DOESN'T WANT THE DEFAULT. GET THE USER'S CHOICE

FSID11:	HRROI T1,[ASCIZ/
HOW MANY PAGES FOR THE FRONT END FILE SYSTEM? /]
	HRROI T2,[ASCIZ/
[ENTER THE DECIMAL NUMBER OF PAGES FOR THE FRONT END FILE SYSTEM]
/]
	MOVEI T3,FSIDEC		;GET A DECIMAL NUMBER
	CALL FSIASK		;ASK QUESTION AND GET THE ANSWER
	 JRST FSID10		;ERROR. ASK AGAIN
FSID12:	MOVEM T1,FEFSIZ		;SAVE THE ANSWER
	JRST FSID13		;YES.

	REPEAT 0,<
FSIDI3:	HRROI T1,[ASCIZ/
IS THIS STRUCTURE THE PRIMARY PUBLIC STRUCTURE: /]
	HRROI T2,[ASCIZ/
[THE PRIMARY PUBLIC STRUCTURE IS THE STRUCTURE THAT CONTAINS <SYSTEM>
 AND <SUBSYS> AND TO WHICH EACH USER IS CONNECTED BY LOGIN.
 THE PRIMARY PUBLIC STRUCTURE MUST ALWAYS BE MOUNTED DURING SYSTEM
 OPERATION.]
/]
	MOVEI T3,FSIYNO		;GET A YES OR NO ANSWER
	CALL FSIASK		;ASK THE QUESTION
	 JRST FSIDI3		;GET AN ANSWER
	SKIPE T1		;WAS THE ANSWER YES?
	MOVX T1,HB%PUB		;YES, MARK THAT THIS IS PUBLIC STR
	MOVEM T1,FSIFLG		;SAVE FLAGS
>

;DEFINITION IS COMPLETE. WRITE THE HOME BLOCKS

FSID13:	HRROI T1,[ASCIZ/
DO YOU WANT THE DEFAULT SIZE BOOTSTRAP AREA? /]
	HRROI T2,[ASCIZ/
[THE DEFAULT IS 64 PAGES]
/]
	MOVEI T3,FSIYNO		;GET YES OR NO
	CALL FSIASK		;ASK QUESTION AND GET THE ANSWER
	JRST FSID13		;ERROR. ASK AGAIN
	JUMPN T1,[MOVEI T1,NPGSBT
		JRST FSID15]

;USER DOESN'T WANT THE DEFAULT. GET THE USERS CHOICE

	HRROI T1,[ASCIZ/
HOW MANY PAGES FOR THE BOOTSTRAP FILE? /]
	HRROI T2,[ASCIZ/
[ENTER THE DECIMAL NUMBER OF PAGES FOR THE BOOTSTRAP FILE]
/]
	MOVEI T3,FSIDEC		;GET A DECIMAL NUMBER
	CALL FSIASK		;ASK QUESTION AND GET THE ANSWER
	JRST FSID13		;ERROR. ASK AGAIN
FSID15:	MOVEM T1,BOTSIZ		;SAVE THE ANSWER
	CAIL T1,NPGSBT		;IS THIS ENOUGH SPACE?
	JRST FSID17		;YES
	HRROI T1,[ASCIZ/
? INVALID NUMBER OF PAGES FOR THE BOOTSTRAP FILE
/]
	CALL FSIPSO		;NO. COMPLAIN
	JRST FSID13		;TRY AGAIN
FSID17:	SETZM FSIFLG		;INIT FLAGS
	CALL WRTHOM		;NOW THAT HOMTAB IS OK, GO WRITE HB'S
	 RET			;ERROR ON WRITING OF HOME BLOCKS
	HRROI T1,[ASCIZ/
[STRUCTURE "/]
	CALL FSIPSO		;TELL OPERATOR THAT STR WAS DEFINED OK
	MOVE T1,FSINAM		;GET STR NAME
	CALL FSI6TY
	HRROI T1,[ASCIZ/" SUCCESSFULLY DEFINED]
/]
	CALL FSIPSO		;END MESSAGE AND EXIT
;	JRST FSIDI0		;LOOP BACK UNTIL USER THRU DEFINING
	RET
;ROUTINE TO TYPE OUT CONFIGURATION OF CHANNELS,UNITS
;AC USAGE:
;P1 - CDB
;P2 - STATUS
;P3 - UDB
;P4 - CHANNEL AOBJN POINTER
;P5 - UNIT AOBJN POINTER


FSICFG:	SAVEP
	HRROI T1,FSIMS1		;GET HELP MESSAGE
	CALL FSIPSO		;TYPE OUT FIRST PART OF MESSAGE
	MOVN P4,MAXCHN		;BUILD CHANNEL AOBJN POINTER
	HRLZS P4		; ...
FSICF1:	SKIPN P1,CHNTAB(P4)	;GET CDB
	JRST FSICF4		;NO CDB
	MOVE P5,CDBIUN(P1)	;GET UNIT AOBJN POINTER
FSICF2:	SKIPN P3,(P5)		;UDB PRESENT?
	JRST FSICF3		;NO
	LOAD T1,USTYP,(P3)	;GET UNIT TYPE
	MOVSI T2,-NDSKUT	;CHECK IF FILE DISK TYPE
	CAME T1,DSKUTP(T2)
	AOBJN T2,.-1		;LOOP
	SKIPL T2		;FOUND?
	JRST FSICF3		;NO - TRY NEXT
	HRRZ T1,CDBADR(P1)	;GET CHANNEL ADDRESS
	CALL FSIOTY		;TYPE
	MOVEI T1,","		;PRINT COMMA
	CALL FSIPBO		; ...
	HRRZ T1,UDBADR(P3)	;FINISH CHANNEL,UNIT
	CALL FSIOTY
	HRROI T1,[ASCIZ / ;TYPE=/] ;PREPARE TO PRINT UNIT TYPE
	CALL FSIPSO		; ...
	LOAD T1,USTYP,(P3)	;GET TYPE
	MOVE T1,NAMUTP(T1)	;GET POINTER TO NAME
	CALL FSIPSO		;PRINT NAME
	MOVE P2,UDBSTS(P3)	;COPY STATUS
	TXNE P2,US.OFS		;OFFLINE?
	CALL FSICF5		;YES - PRINT MESSAGE
	TXNE P2,US.PGM		;PROGRAMMABLE DUAL PORT?
	CALL FSICF6		;YES - PRINT MESSAGE
	TXNE P2,US.WLK		;WRITE LOCKED?
	CALL FSICF7		;YES - PRINT MESSAGE
	HRROI T1,[ASCIZ /
/]
	CALL FSIPSO
FSICF3:	AOBJN P5,FSICF2		;LOOP FOR ALL UNITS
FSICF4:	AOBJN P4,FSICF1		;LOOP FOR ALL CHANNELS
	HRROI T1,[ASCIZ/]
/]
	CALLRET FSIPSO		;FINISH OUT MESSAGE

;HERE IF OFFLINE

FSICF5:	HRROI T1,[ASCIZ /,OFFLINE/]
	CALL FSIPSO		;PRINT MESSAGE
	RET

;HERE IF DUAL PORT

FSICF6:	HRROI T1,[ASCIZ /,DUAL PORT/]
	CALL FSIPSO		;PRINT MESSAGE
	RET

;HERE IF WRITE LOCKED

FSICF7:	HRROI T1,[ASCIZ /,WRITE LOCKED/]
	CALL FSIPSO		;PRINT MESSAGE
	RET

FSIMS1:	ASCIZ/
[ENTER A PAIR OF NUMBERS SEPARATED BY A COMMA THAT SPECIFY THE
 CHANNEL AND UNIT UPON WHICH THE APPROPRIATE PACK IS MOUNTED.
 THE FOLLOWING IS A LIST OF VALID CHANNEL,UNIT PAIRS:
/
;ROUTINES TO CORRECT ONE INCORRECT BAT BLOCK
;AND WRITE THE CORRECT PAIR
;BOTH ACCEPT:	T1/ FLAGS
;		T2/ VIRTUAL ADDRESS OF FIRST BAT BLOCK
;		T3/ PHYSICAL CORE ADDRESS
;		P2/ CHANNEL,,UNIT
;		P4/ SDBUDB POINTER
;		P5/ STRTAB POINTER


CPY1:	TDZA T4,T4		;INDICATE COPYING PRIMARY TO SECONDARY
CPY2:	SETOM T4		;INDICATE COPYING SECONDARY TO PRIMARY
	STKVAR <CPBFLG,CPBVIR,CPBPHY,CPBDIR>
	MOVEM T1,CPBFLG		;SAVE FLAGS
	MOVEM T2,CPBVIR		;SAVE VIRTUAL ADDRESS OF FIRST BAT BLOCK
	MOVEM T3,CPBPHY		;SAVE PHYSICAL ADDRESS OF FIRST BAT BLOCK
	MOVEM T4,CPBDIR		;SAVE DIRECTION OF COPY
	TXNN T1,MI%MSG		;MESSAGE DESIRED ?
	JRST CPYB10		;NO, GO SET UP THE BLT INSTRUCTION
	HRROI T1,[ASCIZ/% Copying secondary BAT block to primary on /]
	SKIPN CPBDIR		;COPYING PRIMARY TO SECONDARY ?
	HRROI T1,[ASCIZ/% Copying primary BAT block to secondary on /]
	CALL FSIPSO		;ISSUE MESSAGE
	CALL UNTSTR		;OUTPUT STR NAME AND UNIT NUMBER
	HRROI T1,[ASCIZ/
/]				;GET END OF LINE
	CALL FSIPSO		;TERMINATE LINE

; HERE TO DO THE ACTUAL COPY

CPYB10:	MOVE T1,CPBVIR		;GET VIRTUAL ADDRESS OF FIRST BAT BLOCK
	MOVEI T3,BATBL1		;GET BLOCK NUMBER OF FIRST BAT BLOCK
	MOVEI T4,BATBLK(T1)	;GET ADDRESS OF BLOCK # IN FIRST BAT BLOCK
	SKIPN CPBDIR		;COPYING SECONDARY TO PRIMARY ?
	JRST CPYB20		;NO, GO SET UP TO COPY PRIMARY TO SECONDARY
	HRLI T1,HBLEN(T1)	;YES, GET SOURCE ADDRESS
	JRST CPYB30		;GO SET UP TERMINATING ADDRESS FOR COPY
CPYB20:	HRLI T1,(T1)		;GET SOURCE ADDRESS
	ADDI T1,HBLEN		;GET DESTINATION ADDRESS
	ADDI T3,HM2BLK-HM1BLK	;GET BLOCK NUMBER OF SECOND BAT BLOCK
	ADDI T4,HBLEN		;POINNT TO BLOCK NUMBER IN SECOND BAT BLOCK
CPYB30:	MOVEI T2,(T1)		;SET UP TERMINATING ADDRESS
	BLT T1,HBLEN-2(T2)	;COPY THE GOOD BAT BLOCK
	MOVEM T3,(T4)		;STORE PROPER BLOCK NUMBER IN DESTINATION BLOCK
	MOVE T1,P2		;GET CHANNEL,, UNIT NUMBERS
	MOVE T3,CPBPHY		;GET PHYSICAL ADDRESS OF BAT BLOCKS
	CALL BATOUT		;WRITE THE NOW GOOD BAT BLOCKS
	 RETBAD			;FAILED, RETURN ERROR
	RETSKP			;SUCCESS, RETURN
;FSIBAT - DO ONCE ONLY CODE FOR THE BAT BLOCKS

;ACCEPTS:
;		T1/STRUCTURE NUMBER

;	CALL FSIBAT

;RETURNS +1: ALWAYS

;DOES CONSISTENCY CHECK AND CORRECTS BAT BLOCK BY COPYING THE
;BACKUP LIKE CHKBAT
;IF NONE THERE, ASKS IF A SET SHOULD BE PUT ON AND DOES IT IF THE
;ANSWER IS YES

;CURRENTLY ONLY CALLED FOR STRUCTURE 0 AT SYSTEM STARTUP

FSIBAT:	SAVEP			;SAVE THE PERMANENTS
	MOVEM T1,P5		;SAVE STRUCTURE NUMBER
	MOVEI T1,HOMPGA		;THE WORK PAGE
	CALL MLKMA		;LOCK IT
	LSH T1,PGSFT		;MAKE IT A CORE ADDRESS
	MOVE P1,T1		;SAVE IT
FSIBA1:	SKIPN P4,STRTAB(P5)	;DOES STRUCTURE EXIST?
	JRST GOOD22		;NO. DON'T DO ANYTHING TO IT
	MOVN T1,SDBNUM(P4)	;YES. SET UP UNIT AOBJN WORD
	HRLI P4,0(T1)		;NEGATIVE COUNT
	HRRI P4,SDBUDB(P4)	;THE SDBUBD INDEX

;LOOP THROUGH ALL PACKS IN A STRUCTURE

NEW1:	CALL SETBAT		; SET DSKBAT BIT IN DSKSTS
	CALL FNDCHN		;FIND CHANNEL,,UNIT FOR THIS PACK
	MOVE P2,T1		;SAVE IT
	MOVE T2,P1		;PHYSICAL CORE ADDRESS
	MOVEI T3,HOMPGA		;VIRTUAL ADDRESS
	CALL GETBAT		;GET THE BAT BLOCKS
	MOVE T2,T1		;BITS
	TLNN T2,(1B0)		;PRIMARY OK?
	JRST BAD1		;NO
	TLNE T2,(1B1)		;SECONDARY OK?
	JRST GOOD2
	MOVE T3,P1		;CORE ADDRESS
	MOVX T1,MI%MSG		;NOTE THAT A MESSAGE IS DESIRED
	MOVEI T2,HOMPGA		;GET VIRTUAL ADDRESS OF FIRST BAT BLOCK
	CALL CPY1		;COPY PRIMARY
	 JRST NONB		;BAD
	JRST GOOD2
BAD1:	TLNN T2,(1B1)		; A GOOD SECONDARY?
	JRST NONB		;NO. NO BAT BLOCKS
	MOVX T1,MI%MSG		;NOTE THAT A MESSAGE IS DESIRED
	MOVEI T2,HOMPGA		;GET VIRTUAL ADDRESS OF FIRST BAT BLOCK
	MOVE T3,P1		;GET CORE ADDRESS
	CALL CPY2		;PUT SECONDARY INTO PRIMARY
	 JRST NONB		;BAD I/O
	JRST GOOD2
;HERE WHEN NO GOOD BAT BLOCKS COULD BE FOUND FOR THIS UNIT

NONB:	MOVEI T1,"?"
	CALL FSIPBO		;ERROR PREFIX
	CALL UNTSTR
	HRROI T1,[ASCIZ / HAS NO BAT BLOCKS.
/]
	CALL FSIPSO		;TELL HIM
REASK:	HRROI T1,[ASCIZ /DO YOU WANT TO WRITE A SET OF PROTOTYPE BAT BLOCKS? /]
	HRROI T2,BATASK		; THE QUESTION
	HRROI T3,FSIYNO		; GET A YES OR A NO.
	CALL FSIASK		; GO ASK THE QUESTION
	 JRST REASK		; ASK AGAIN
	JUMPL T1,NEWBAT		; IF YES, GO MAKE THEM
	JRST GOOD21		; NO. SKIP IT THEN
NEWBAT:	MOVE T1,P2		; GET CHANNEL,,UNIT NUMBERS
	MOVEI T2,HOMPGA		; VIRTUAL ADDRESS OF NEW BAT BLOCKS
	MOVE T3,P1		; PHYSICAL CORE ADDRESS OF NEW BAT BLOCKS
	MOVX T4,MI%MSG		; ISSUE A MESSAGE ON A WRITE ERROR
	CALL MAKBAT		; CREATE A PAIR OF NEW BAT BLOCKS
	 JRST GOOD21		; FAILED, GO ON
	; ..
	; ..

;THE PACK HAS TWO GOOD BAT BLOCKS HERE

GOOD2:	CALL CLRBAT		; MARK STATUS WORD
GOOD21:	AOBJN P4,NEW1		;DO ALL PACKS
GOOD22:	MOVEI T1,HOMPGA		;RELEASE PAGE THAT BAT BLOCKS WERE
	CALL MULKMP		; READ INTO
	RET			; AND DONE

;ROUTINE TO FIND CHANNEL,,UNIT FOR A PACK
;ACCEPTS:	P4/SDBUDB INDEX
;RETURNS:	T1/ CHANNEL,,UNIT

FNDCHN:	HRRZ T3,0(P4)		;GET UDB
FNDCH1::HRRZ T1,UDBADR(T3)	;UNIT NUMBER
	HRRZ T3,UDBCDB(T3)	;GET CDB POINTER
	HRL T1,CDBADR(T3)	;GET CHANNEL NUMBER
	RET			;AND DONE

BATASK:	ASCIZ /
[THIS PACK DOES NOT HAVE A VALID SET OF BAT BLOCKS. ANSWERING
YES WILL CAUSE THE MONITOR TO CREATE THE BAT BLOCKS WITHOUT
PERFORMING A FULL MAP FUNCTION.]
/
;MAKBAT - ROUTINE TO CREATE AND WRITE OUT TWO NEW BAT BLOCKS
;
;ACCEPTS IN T1/	PHYSICAL CHANNEL,,UNIT NUMBERS
;	    T2/	VIRTUAL ADDRESS OF WHERE NEW BAT BLOCKS ARE TO GO
;	    T3/	PHYSICAL MEMORY ADDRESS OF NEW BAT BLOCKS
;	    T4/	FLAGS:
;	*   P4/	SDBUDB POINTER FOR THIS UNIT
;	*   P5/	STRUCTURE NUMBER
;			MI%MSG - ISSUE A MESSAGE ON TERMINAL ON WRITE ERROR
;		CALL MAKBAT
;RETURNS: +1	 FAILURE, WRITE ERROR
;	  +2	SUCCESS, BAT BLOCKS CREATED
;
; * P4 AND P5 NEED NOT BE SET UP IF MESSAGES ARE NOT DESIRED ON ERRORS

MAKBAT:	ASUBR <MKBUNI,MKBVIR,MKBPHY,MKBFLG>
	MOVE T1,MKBVIR		;GET START OF BAT BLOCK PAGE
	SETZM (T1)		;CLEAR FIRST WORD OF NEW BAT BLOCK
	ADDI T1,1		;SET UP TO CLEAR THE FIRST BAT BLOCK
	HRL T1,MKBVIR		;THE START
	BLT T1,HBLEN-1(T2)	;CLEAR OUT ONE BLOCK
	MOVSI T1,'BAT'		; THE BLOCK NAME
	MOVEM T1,BATNAM(T2)	; TO THE NEW BLOCK
	MOVE T1,[-MAXBFR,,BAT1P] ;FORM FREE SPACE WORD
	MOVEM T1,BATFRE(T2)	; TO THE BLOCK
	MOVEI T1,CODBAT		; UNLIKELY CODE
	MOVEM T1,BATCOD(T2)	; TO THE BLOCK
	MOVEI T1,BATBL1		; BLOCK NUMBER
	MOVEM T1,BATBLK(T2)	; TO THE BLOCK
	ADDI T1,HM2BLK-HM1BLK	; NUMBER BETWEEN THEM
	MOVEM T1,BATBLK+HBLEN(T2) ;THE BACKUP ADDRESS
	MOVEI T1,HBLEN(T2)
	HRLI T1,(T2)		; FOR THE BLT
	BLT T1,2*HBLEN-2(T2)	; ALL BUT LAST WORD
	MOVE T1,MKBUNI		;CHANNEL,,UNIT
	MOVE T3,MKBPHY		;REAL CORE ADDRESS
	CALL BATOUT		; WRITE IT
	 JRST MKB010		; FAILED, GO ISSUE MESSAGE IF REQUESTED
	RETSKP			; SUCCESS, RETURN

; HERE ON A WRITE ERROR

MKB010:	MOVE T1,MKBFLG		;GET THE FLAGS
	TXNN T1,MI%MSG		;A MESSAGE DESIRED ?
	RET			;NO, JUST GIVE FAIL RETURN
	HRROI T1,[ASCIZ /?FAILED TO WRITE BAT BLOCKS FOR /]
	CALL FSIPSO		;TELL HIM
	CALL UNTSTR
	HRROI T1,[ASCIZ /
/]
	CALLRET FSIPSO		;CLEAN UP THE MESSAGE
;CHKSWP - ROUTINE TO VALIDATE THE # OF PAGES FOR SWAPPING ON A STRUCTURE
;
;ACCEPTS IN T1/	CHANNEL NUMBER
;	    T2/	UNIT NUMBER
;	    T3/ # OF UNITS IN STRUCTURE
;	    T4/	# OF PAGES FOR SWAPPING ON STR
;		CALL CHKSWP
;RETURNS: +1	 FAILED, # OF PAGES SPECIFIED IS INVALID
;	  +2	SUCCESS, VALID # OF PAGES SPECIFIED

CHKSWP::JUMPE T4,RSKP		;RETURN SUCCESS IF NOTHING TO ALLOCATE
	SKIPG T4		;NEGATIVE # OF PAGES SPECIFIED ?
	RETBAD (MSTX25)		;YES, RETURN FAILURE
	SAVEP
	MOVE T1,CHNTAB(T1)	;GET ADDRESS OF CHANNEL DATA BLOCK
	ADDI T1,CDBUDB(T2)	;GET ADDRESS OF POINTER TO UDB FOR THIS UNIT
	MOVE T1,(T1)		;GET ADDRESS OF UNIT DATA BLOCK
	LOAD T1,USTYP,(T1)	;GET DISK TYPE FOR THIS UNIT
	MOVSI T2,-NDSKUT	;SET UP AOBJN POINTER TO LOOK FOR DISK TYPE
CKSW10:	CAMN T1,DSKUTP(T2)	;FOUND THIS TYPE OF DISK ?
	JRST CKSW20		;YES, GO GET ADDRESS OF SIZE TABLE
	AOBJN T2,CKSW10		;NO, GO CHECK NEXT TYPE OF DISK
	RETBAD (MSTX25)		;NO SUCH TYPE, INVALID # OF PAGES FOR THIS UNIT

CKSW20:	MOVE P1,DSKSIZ(T2)	;GET ADDRESS OF DISK SIZE TABLE FOR THIS UNIT
	MOVE T1,T4		;GET # OF PAGES FOR SWAPPING ON THIS STRUCTURE
	MOVE T2,T3		;GET # OF UNITS IN THIS STRUCTURE
	CALL CMPSWP		;COMPUTE # OF PAGES FOR SWAPPING ON THIS UNIT
	MOVE T2,CYLUNT(P1)	;GET # OF CYLINDERS ON THIS UNIT
	IMUL T2,PAGCYL(P1)	;COMPUTE # OF PAGES ON THIS UNIT
	CAMG T2,T1		;MORE PAGES THAN REQUESTED FOR SWAPPING ?
	RETBAD (MSTX25)		;NO, FAIL
	RETSKP			;YES, RETURN SUCCESS


;CMPSWP - ROUTINE TO COMPUTE # OF PAGES FOR SWAPPING ON A UNIT
;
;ACCEPTS IN T1/	DESIRED # OF PAGES FOR SWAPPING ON STRUCTURE
;	    T2/ NUMBER OF UNITS IN STRUCTURE
;	    P1/ ADDRESS OF DISK SIZE TABLE FOR THIS STRUCTURE
;		CALL CMPSWP
;RETURNS: +1 ALWAYS, T1/ # OF PAGES FOR SWAPPING ON THIS UNIT

CMPSWP:	SOS T1			;ONE LESS
	HRRZ T2,STHUNI		;GET NUMBER OF UNITS IN STRUCTURE
	ADD T1,T2		;T1 = NDST+NPACKS-1 (TO AVOID ROUND OFF)
	IDIV T1,T2		;GET # OF PAGES PER UNIT
	ADD T1,PAGCYL(P1)	;ROUND TO EVEN NUMBER OF CYLINDERS
	SUBI T1,1
	IDIV T1,PAGCYL(P1)
	IMUL T1,PAGCYL(P1)
	RET			;RETURN
;ROUTINE TO COPY ONE STRING TO ANOTHER
;ACCEPTS IN T1/	POINTER TO DESTINATION STRING
;	    T2/	POINTER TO SOURCE STRING
;	CALL FSICPY
;RETURNS +1:	ALWAYS, UPDATED STRING POINTER IN T1 AND NULL AFTER END

FSICPY:	ILDB T3,T2		;GET NEXT CHARACTER
	JUMPE T3,FSICP1		;NULL MEANS AT END
	IDPB T3,T1		;STORE CHARACTER
	JRST FSICPY		;LOOP BACK
FSICP1:	MOVE T4,T1		;NOW APPEND NULL
	IDPB T3,T4		;WITHOUT CHANGING BYTE POINTER IN T1
	RET			;ALL DONE


;ROUTINE TO TYPE OUT A OCTAL NUMBER
;ACCEPTS IN T1/	NUMBER
;	CALL FSIOTY
;RETURNS +1:	ALWAYS

FSIDTY:	SKIPA T3,[12]		;SET RADIX TO ^D10
FSIOTY:	MOVEI T3,10		;SET RADIX TO 8
	STKVAR <<FSINBK,3>>
	MOVE T2,T1		;SET UP FOR CALL TO FSINST
	MOVSI T1,(POINT 7,0)	;SET UP BYTE POINTER
	HRRI T1,FSINBK
	CALL FSINST
	MOVEI T2,0		;ADD NULL TO END OF STRING
	IDPB T2,T1		;...
	HRROI T1,FSINBK
	CALLRET FSIPSO		;TYPE NUMBER


;Routine to convert a number to an asciz string
;Accepts in T1/	String pointer to destination string
;	    T2/	OCTAL NUMBER
;	    T3/	RADIX
;	CALL FSINST
;RETURNS +1:	ALWAYS, UPDATED STRING POINTER IN T1

FSINST:	MOVE T4,T3		;SAVE RADIX
FSINS1:	IDIVI T2,0(T4)		;GET LOW ORDER DIGIT
	PUSH P,T3		;SAVE IT
	SKIPE T2		;ALL DONE?
	CALL FSINS1		;NO, GO GET NEXT LOW ORDER DIGIT
	POP P,T2		;GET HIGH ORDER DIGIT
	ADDI T2,"0"		;MAKE IT ASCII
	IDPB T2,T1		;PUT IT IN THE STRING
	RET			;GO GET OTHER DIGITS IF ANY
;ROUTINE TO ASK A QUESTION AND GET AN ANSWER
;  THIS ROUTINE HANDLES "?" AND RUBOUT

;ACCEPTS IN T1/	POINTER TO QUESTION STRING
;	    T2/	POINTER TO HELP STRING OR THE ADR OF THE HELP ROUTINE
;	    T3/	ADDRESS OF ROUTINE TO READ IN ANSWER
;	CALL FSIASK
;RETURNS +1:	ERROR
;	 +2:	SUCCESSFUL, ANSWER IN T1

FSIASK:	STKVAR <FSIASP,FSIASH,FSIASR>
	MOVEM T1,FSIASP		;SAVE POINTER TO QUESTION
	MOVEM T2,FSIASH		;SAVE POINTER TO HELP MESSAGE
	HRRZM T3,FSIASR		;SAVE ADDRESS OF ROUTINE TO BE CALLED
FSIAS1:	MOVE T1,FSIASP		;GET POINTER TO QUESTION STRING
	CALL FSIPSO		;ASK THE QUESTION
	CALL @FSIASR		;GET THE ANSWER
	 JRST [	JUMPE T1,FSIAS2	;"?" TYPED
		JRST FSIAS1]	;CONTROL-R TYPED
	RETSKP			;RETURN WITH ANSWER IN T1

FSIAS2:	MOVE T1,FSIASH		;GET POINTER TO HELP MESSAGE
	TLNN T1,-1		;IS THIS A HELP ROUTINE
	JRST [	CALL 0(T1)	;YES, GO CALL IT
		JRST FSIAS1]	;AND GO REASK THE QUESTION
	CALL FSIPSO		;TYPE OUT HELP MESSAGE
	JRST FSIAS1		;GO ASK QUESTION AGAIN
;ROUTINE TO GET A YES OR NO ANSWER
;	CALL FSIYNO
;RETURNS +1:	T1=0 MEANS "?" TYPED, T1=1 MEANS CONT-R TYPED
;	 +2:	T1=-1 MEANS YES, T1=0 MEANS NO

FSIYNO:	CALL FSIPBI		;GET A CHARACTER FROM TTY
	MOVE T2,T1		;SAVE FIRST CHARACTER
FSIYN1:	CAIN T1,"?"		;IS THIS A HELP REQUEST
	JRST RFALSE		;YES, RETURN WITH T1=0
	CAIN T1,"R"-100		;CONTROL-R?
	JRST [	MOVEI T1,1	;YES, RETURN WITH T1=1
		RET]
	CAIE T1,"U"-100		;CONTROL-U?
	CAIN T1,.CHDEL		;OR RUBOUT?
	JRST [	CALL FSIRUB	;YES, SIMULATE RUBOUT ACTION
		JRST FSIYNO]	;START OVER AGAIN
	CAIN T1,.CHLFD		;END OF LINE?
	JRST FSIYN2		;YES, CHECK ANSWER
	CALL FSIPBI		;GET ANOTHER CHARACTER
	JRST FSIYN1		;GO CHECK IT OUT

FSIYN2:	CAIN T2,"Y"		;FIRST CHAR A Y?
	JRST FSIYN3		;YES, GO RETURN TRUE
	CAIN T2,"N"		;NO?
	JRST FSIYN4		;YES, GO RETURN FALSE
	HRROI T1,[ASCIZ/? Answer "Y" or "N"  /]
	CALL FSIPSO		;TYPE OUT HELP
	JRST FSIYNO		;GO GET ANSWER AGAIN

FSIYN4:	TDZA T1,T1		;NO, RETURN T1=0
FSIYN3:	SETO T1,		;YES, RETURN T1=-1
	RETSKP
;ROUTINE TO READ IN A SIXBIT NAME
;	CALL FSISIX
;RETURNS +1:	T1=0 MEANS "?" TYPED, T1=1 MEANS CONTROL-R TYPED
;	 +2:	SIXBIT NAME IN T1

FSIDEV:	TDZA T4,T4		;ALLOW ":" AS A TERMINATOR
FSISIX:	SETO T4,		;COLON IS NOT ALLOWED
FSISI4:	MOVE T2,[POINT 6,T3]	;SET UP STRING POINTER TO ANSWER
	SETZ T3,		;INITIALIZE ANSWER AC
FSISI1:	CALL FSIPBI		;GET A CHARACTER
	CAIN T1,"?"
	JRST RFALSE		;QUESTION MARK WAS TYPED
	CAIN T1,"R"-100		;CONTROL-R?
	JRST [	MOVEI T1,1	;YES, RETURN WITH T1=1
		RET]
	CAIE T1,"U"-100		;CONTROL-U?
	CAIN T1,.CHDEL		;OR RUBOUT?
	JRST [	CALL FSIRUB	;YES. GO TYPE 'XXX'
		JRST FSISI4]	;START OVER. T4 IS STILL SET UP
	CAIN T1,.CHLFD		;END OF LINE?
	JRST [	MOVE T1,T3	;YES, GET ANSWER
		RETSKP]		;RETURN WITH ANSWER IN T1
	JUMPN T4,FSISI2		;ALLOWING A COLON?
	CAIN T1,":"		;YES, IS IT A COLON
	TLZ T2,7700		;YES, IGNORE ANY OTHER STUFF AFTER IT
FSISI2:	SUBI T1,40		;CONVERT TO SIXBIT
	TRNE T1,777700		;LEGAL SIXBIT CHARACTER?
	JRST FSISI3		;NO, GO COMPLAIN
	IDPB T1,T2		;STORE CHARACTER IN ANSWER
	TLNN T2,770000		;AT END OF 6 CHAR WORD?
	TLZ T2,7700		;YES, SET SIZE FIELD TO 0 FOR REMAINDER
	JRST FSISI1		;LOOP BACK FOR OTHER CHARACTERS

FSISI3:	HRROI T1,[ASCIZ/? Illegal character, retype answer again: /]
	CALL FSIPSO		;TYPE OUT COMPLAINT
	JRST FSISI4		;START OVER. T4 IS STILL SET UP


;ROUTINE TO TYPE OUT A SIXBIT NAME
;ACCEPTS IN T1/	SIXBIT NAME
;	CALL FSI6TY
;RETURNS +1:	ALWAYS

FSI6TY:	MOVE T2,T1		;SAVE SIXBIT NAME
	MOVE T3,[POINT 6,T2]	;SET UP BYTE POINTER
FSI6T1:	ILDB T1,T3		;GET NEXT CHARACTER
	JUMPE T1,R		;IF ZERO, EXIT
	ADDI T1,40		;MAKE IT ASCII
	CALL FSIPBO		;TYPE OUT CHARACTER
	TLNE T3,770000		;LAST CHARACTER?
	JRST FSI6T1		;NO, GO TYPE OUT NEXT CHAR
	RET			;YES, EXIT
;ROUTINES TO GET AN OCTAL OR DECIMAL NUMBER
;	CALL FSIOCT	OR	CALL FSIDEC
;RETURNS +1:	T1=0 MEANS "?" TYPED, T1=1 MEANS CONTROL-R TYPED
;	 +2:	NUMBER IN T1

FSIDEC:	STKVAR <FSIOCN,FSIOCR,FSIOCM,FSIOCC>
	SETZM FSIOCM		;MARK THAT DECIMAL NUMBER REQUESTED
	MOVEI T1,12		;GET RADIX
	MOVEM T1,FSIOCR		;STORE FOR CONVERSION
	JRST FSIOC0		;ENTER COMMON CODE

FSIOCT:	STKVAR <FSIOCN,FSIOCR,FSIOCM,FSIOCC>
	SETOM FSIOCM		;OCTAL NUMBER REQUESTED
	MOVEI T1,10		;GET RADIX
	MOVEM T1,FSIOCR		;SAVE FOR OCTAL CONVERSION
FSIOC0:	SETZM FSIOCN		;INITIALIZE THE ANSWER
	SETZM FSIOCC		;INITIALIZE COUNT OF DIGITS SEEN
FSIOC1:	CALL FSIPBI		;GET A CHARACTER
	CAIN T1,"?"		;QUESTION MARK?
	JRST RFALSE		;YES, RETURN WITH T1=0
	CAIN T1,"R"-100		;CONTROL-R?
	JRST [	MOVEI T1,1	;YES, RETURN WITH T1=1
		RET]
	CAIE T1,"U"-100		;CONTROL-U?
	CAIN T1,.CHDEL		;OR RUBOUT?
	JRST [	CALL FSIRUB	;YES, TYPE OUT RUBOUT STRING
		JRST FSIOC0]	;AND START OVER AGAIN
	CAIE T1," "		;ALLOW SPACE OR COMMA
	CAIN T1,","		; TO DELIMIT A NUMBER
	SKIPA
	CAIN T1,.CHLFD		;END OF LINE?
	JRST [	SKIPG FSIOCC	;ANY DIGITS TYPED
		JRST FSIOC2	;NO, A DIGIT MUST BE TYPED
		MOVE T1,FSIOCN	;YES, GET ANSWER
		RETSKP]		;AND RETURN
	CAIL T1,"0"		;LEGAL DIGIT?
	CAILE T1,"9"		;...
	JRST FSIOCE		;NO, GO TYPE ERROR MESSAGE
	CAILE T1,"7"		;OCTAL NUMBER?
	SKIPN FSIOCM		;NO, IS DECIMAL NUMBER WANTED?
	SKIPA			;YES, THE ALL OK
	JRST FSIOCE		;NO, ILLEGAL OCTAL DIGIT
	SUBI T1,"0"		;TURN IT INTO A DIGIT
	MOVE T2,FSIOCN		;GET ANSWER
	IMUL T2,FSIOCR		;MULTIPLY BY RADIX VALUE
	ADD T2,T1		;ADD IN LOW ORDER DIGIT
	MOVEM T2,FSIOCN		;SAVE UPDATED ANSWER
	AOS FSIOCC		;COUNT UP DIGITS SEEN
	JRST FSIOC1		;AND LOOP BACK FOR MORE
FSIOC2:	HRROI T1,[ASCIZ/? Null answer not allowed, retype answer: /]
	CALL FSIPSO		;TYPE OUT MESSAGE
	JRST FSIOC0		;AND TRY AGAIN

FSIOCE:	HRROI T1,[ASCIZ/
? Illegal character, retype answer: /]
	CALL FSIPSO		;TYPE OUT COMPLAINT
	JRST FSIOC0		;TRY AGAIN
;ROUTINE TO TYPE OUT RUBOUT STRING
;	CALL FSIRUB
;RETURNS +1:	ALWAYS

FSIRUB:	HRROI T1,[ASCIZ/ XXX
/]
	CALL FSIPSO		;TYPE OUT STRING
	RET			;AND RETURN


;ROUTINE TO TYPE OUT A STRING
;ACCEPTS IN T1/	STRING POINTER
;	CALL FSIPSO
;RETURNS +1:	ALWAYS
;		CLOBERS T1 ONLY

FSIPSO:	STKVAR <FSIPSP>
	TLC T1,-1		;SEE IF -1,,ADR
	TLCN T1,-1		;...
	HRLI T1,(POINT 7,0)	;YES, SET UP BYTE POINTER
	MOVEM T1,FSIPSP		;SAVE STRING POINTER
FSIPS1:	ILDB T1,FSIPSP		;GET NEXT CHARACTER
	JUMPE T1,R		;RETURN ON NULL
	CALL FSIPBO		;OUTPUT THIS CHARACTER
	JRST FSIPS1		;LOOP TIL THRU
;ROUTINE TO READ IN A CHARACTER
;	CALL FSIPBI
;RETURNS +1:	ALWAYS, UPPERCASE CHARACTER IN T1
;		SAVES ALL ACS

;NOTE: THIS ROUTINE LOCKS THE TELETYPE DATA EVEN THOUGH IT IS THE
;ONLY PROCESS RUNNING BECAUSE TCI CALLS ULKTTY IF IT GOES INTO INPUT
;WAIT.

FSIPBI:	PUSH P,T2		;SAVE ALL ACS
	PUSH P,T3
	PUSH P,T4
FSIPB1:	MOVE T2,CTYLNO		;GET CTY LINE NUMBER
	CALL LCKTTY		;POINT TO DYNAMIC DATA
	 BUG(TTNAC4)
	CALL TCI		;INPUT A CHAR
	 JRST FSIPB1		;NEEDED TO BLOCK. GO TRY AGAIN
	CALL ULKTTY		;FREE THE TTY
	CAIN T1,.CHCRT		;FLUSH CR
	JRST FSIPB1
	POP P,T4
	POP P,T3
	POP P,T2
	RET

;ROUTINE TO OUTPUT A CHARACTER
;ACCEPTS IN T1/	CHARACTER
;	CALL FSIPBO
;RETURN +1:	ALWAYS, ALL ACS PRESERVED

FSIPBO:	SAVET
	MOVE T2,CTYLNO		;GET CTY LINE NUMBER
	CALL LCKTTY		;POINT TO DYNAMIC DATA
	 BUG(TTNAC3)
	CALL TCO
	CALL ULKTTY		;FREE THE TTY
	RET

;FSIPSW - ROUTINE TO PRINT HELP TEXT FOR SWAPPING SPACE DEFAULT

;USES THE DEFAULT NUMBER OF PAGES FOR THE RUNNING MONITOR AND ROUNDS
;IT UP TO AN INTEGRAL NUMBER OF CYLINDERS. ASSUMES THAT ALL KNOWN
;DISK TYPES HAVE THE SAME NUMBER OF PAGES PER CYLINDER AS AN RP04

FSIPSW:	HRROI T1,[ASCIZ/
[THE DEFAULT IS /]
	CALL FSIPSO
	MOVEI T3,DSKSZ0		;ASSUME RP04 SIZE CHARACTERISTICS
	MOVE T1,NSWPGS		;GET DEFAULT NUMBER OF PAGES
	IDIV T1,PAGCYL(T3)	;CONVERT TO CYLINDERS
	SKIPE T2		;WAS THERE A REMAINDER?
	AOS T1			;YES. INCREMENT CYLINDER COUNT
	IMUL T1,PAGCYL(T3)	;CONVERT BACK TO PAGES
	CALL FSIDTY		;PRINT THE NUMBER
	HRROI T1,[ASCIZ/ PAGES]
/]
	CALL FSIPSO
	RET

	TNXEND
	END