Google
 

Trailing-Edge - PDP-10 Archives - bb-m780a-sm - monitor-sources/dskalc.mac
There are 55 other files named dskalc.mac in the archive. Click here to see a list.
; UPD ID= 379, SNARK:<5.MONITOR>DSKALC.MAC.22,   6-Jan-82 10:58:08 by DONAHUE
;More 5.1495 - Save Q registers in SEEADR
; UPD ID= 161, SNARK:<5.MONITOR>DSKALC.MAC.21,   9-Sep-81 16:06:20 by DONAHUE
;TCO 5.1495 - REWRITE BAT BLOCK LOGIC TO ACCOUNT FOR LOST PAGES
; UPD ID= 99, SNARK:<5.MONITOR>DSKALC.MAC.20,  12-Aug-81 13:32:13 by PAETZOLD
;TCO 5.1446 - FIX HOME BLOCK COPYING
; UPD ID= 44, SNARK:<5.MONITOR>DSKALC.MAC.19,  17-Jul-81 16:17:48 by MURPHY
;MORE TCO 5.1398 - SKIP RETURN FROM MSETPT
; UPD ID= 11, SNARK:<5.MONITOR>DSKALC.MAC.18,   9-Jul-81 17:14:14 by MURPHY
;TCO 5.1398 - RETURN ERROR CODES ON DSKASN FAILURES
; UPD ID= 1985, SNARK:<5.MONITOR>DSKALC.MAC.17,  13-May-81 14:34:03 by SCHMITT
;More of TCO 5.1319 ...
; UPD ID= 1964, SNARK:<5.MONITOR>DSKALC.MAC.16,   8-May-81 10:33:59 by SCHMITT
;TCO 5.1319 - Rewrite BAT block allocation in drum bit table.
; UPD ID= 1879, SNARK:<5.MONITOR>DSKALC.MAC.15,  23-Apr-81 17:44:36 by LYONS
;ALLOW LOWER CASE INPUT WHEN LOOKING FOR A STRUCTURE NAME
; UPD ID= 1819, SNARK:<5.MONITOR>DSKALC.MAC.14,  17-Apr-81 09:47:47 by WACHS
;TCO 5.1288 Set UDBVID in all units of a file structure
; UPD ID= 1637, SNARK:<5.MONITOR>DSKALC.MAC.13,   3-Mar-81 05:08:45 by WACHS
;TCO 5.1264 - Don't let FSIASK get into section 0
; UPD ID= 1593, SNARK:<5.MONITOR>DSKALC.MAC.12,  27-Feb-81 04:08:02 by WACHS
;TCO 5.1264 - Stay in section 1 after asking for name of Public Structure
; UPD ID= 899, SNARK:<5.MONITOR>DSKALC.MAC.11,  14-Aug-80 10:54:05 by LYONS
;TCO 5.1062 - Check ERRSWP, and bughlt if non zero
; UPD ID= 658, SNARK:<5.MONITOR>DSKALC.MAC.8,  16-Jun-80 17:23:01 by KONEN
;TCO 5.1063 - 
;Look for home block with the CPU serial number before the name PS
;Add to home blocks the serial number of CPU a structure boots
; UPD ID= 638, SNARK:<5.MONITOR>DSKALC.MAC.7,  13-Jun-80 18:27:23 by DBELL
;CHANGE DSKSIZ TO UDBSIZ AT FSIDE1
; UPD ID= 612, SNARK:<5.MONITOR>DSKALC.MAC.6,   6-Jun-80 15:47:22 by SCHMITT
;TCO 5.1060 - Fix calc of size of BTB for struc during initialization
; UPD ID= 610, SNARK:<5.MONITOR>DSKALC.MAC.5,   6-Jun-80 13:57:26 by DBELL
;CHECK WRITE PROTECTION OF PAGES IN DSKOP PROPERLY
; UPD ID= 573, SNARK:<5.MONITOR>DSKALC.MAC.4,  31-May-80 22:46:09 by DBELL
;TCO 5.1048 - CHANGE DSKOP TO ALLOW MULTIPLE-PAGE TRANSFERS
; UPD ID= 391, SNARK:<4.1.MONITOR>DSKALC.MAC.19,  28-Mar-80 14:52:28 by DBELL
;FIX BUG DESCRIPTIONS FOR NOBAT1 AND NOBAT2 BUGCHKS
; UPD ID= 357, SNARK:<4.1.MONITOR>DSKALC.MAC.18,  26-Mar-80 11:06:21 by DBELL
;TCO 4.1.1119 - ADD SUPPORT FOR RP20 DISKS
; UPD ID= 321, SNARK:<4.1.MONITOR>DSKALC.MAC.17,  12-Mar-80 11:59:48 by KONEN
; UPD ID= 202, SNARK:<4.1.MONITOR>DSKALC.MAC.15,  15-Jan-80 10:50:47 by MILLER
;TCO 4.1.1067. FIX COMPUTATION OF SWAT ADDRESS AT DOBDRM
; UPD ID= 54, SNARK:<4.1.MONITOR>DSKALC.MAC.14,  29-Nov-79 10:41:34 by SCHMITT
;MORE OF TCO 4.2409, RESTORE D AFTER DSKASA
;<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 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
	STKVAR <STRN00,MINFP0>
	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 IOX35		;TAKE THE FAILURE RETURN
	CAIE 2,PSNUM		;IS THIS PS?
	IFSKP.
	  MOVX Q1,SC%WHL!SC%OPR ;YES. SEE IF PRIVILEGED
	  TDNE Q1,CAPENB	; IS IT?
	ANSKP.
	  MOVE 1,2		;NO, GET STRUCTURE #
	  CALL GSTRPG		;GET ALLOCATION
	  CAMG T2,SYSSPC	;ABOVE MIN FREE?
	  RETBAD IOX34		;NO, ERROR DISK FULL
	  MOVE 2,STRN00		;YES. ALLOW IT
	ENDIF.
	MOVE Q1,SDBTYP(Q2)	;GET ADDRESS OF DSKSIZ TABLE
	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?
	AOJA T1,[SETZM MINFP0	;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,STRCOD>,<T3,CYLNDR>>)
	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 IOX35			;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

DSKA1:	MOVE 1,SDBMFP(Q2)	;GET MINIMUM LIMIT
	MOVEM 1,MINFP0
	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
	CAML 4,MINFP0		;GOOD ENOUGH TO QUIT?
	JRST DSKA8		;YES
DSKA4:	SKIPN MINFP0		;DOING FREE CHOICE?
	AOSA T1			;NO, LOOK ON NEXT TRACK
	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
		RETBAD IOX34]	;DISK FULL
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,STRCOD>,<T2,SECTOR>>)
		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,STRCOD>,<T2,SECTOR>>)
	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,STRCOD>,<T2,SECTOR>>)
		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,STRCOD>,<T2,SECTOR>>)
	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 CKU VALUE (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 CKU NUMBERS
	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

SEEADR::SAVEPQ
	SE1CAL
	MOVE P2,B		;SAVE CORE ADDRESS
	TLZ C,-1		;CLEAR JUNK IN LEFT HALF
	MOVE P4,UDBSIZ(C)	;GET POINTER TO DSKSIZ ENTRY
	PUSH P,A		;SAVE DISK ADDRESS
	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
	MOVE P2,SECPAG(P4)	;GET SECTORS PER PAGE
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
	PUSH P,D		;SAVE NUMBER
	MOVEM C,D		;STORE ADDRESS
	MOVE A,SECCYL(P4)	;GET NUMBER OF SECTORS
	ADD A,LPPCYL(P4)	;  IN ONE CYLINDER
	IDIV D,A		;GET NUMBER OF CYLINDERS IN PHYSICAL ADDRESS
	IMUL D,LPPCYL(P4)	;GET NUMBER OF LOST SECTORS
	SUB C,D			;TRANSLATE TO LOGICAL
	POP P,D			;RESTORE NUMBER OF BLOCKS
	ADD D,C			;GET LAST ONE
	TRZ C,-1(P2)		;TRUNCATE TO PAGE BOUNDARY
	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
	OKSKED
	RETSKP			;RETURN WITH IT LOCKED
CANT:	HRLI A,0(A)		;UNIT NUMBER TO LH
	HRRI A,BATTST		;TEST ADDRESS
	RDISMS			;AND GO INTO SCHEDULER WAIT
	RETSKP

;SCHEDULER TEST FOR BAT BLCOK AVAILABLE

	RESCD

BATTST:	MOVX B,US.BLK		;THE BIT
	TDNE B,UDBSTS(A)	;FREE NOW?
	JRST 0(4)		;NO. BLOCK AGAIN
	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
	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 CKU VALUE
	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
		MOVE D,STRTPT	;GET SIZE DATA
		MOVE B,SECCYL(D);GET NUMBER OF SECTORS
		ADD B,LPPCYL(D)	;  IN A CYLINDER
		IDIV A,B	;NUMBER OF CYLINDERS
		IMUL A,LPPCYL(D);NUMBER OF LOST SECTORS
		MOVE D,SVADR2	;GET BACK ADDRESS
		SUBM D,A	;TRANSLATE TO LOGICAL
		MOVE B,STRN04	;2/STRUCTURE NUMBER
		CALL DSKASA	; ASSIGN IT
		 AOS INIER2	;COUNT NUMBER OF FAILURES FOR BAD PAGES
		MOVE D,STRN04	; GET BACK STRUCTURE NUMBER
		HRRZ D,STRTAB(D) ; AND THEN GET START OF SDB 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,STRCOD>,<T2,AMOUNT>>)
		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
	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
	 NOP
	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,STRCOD>>)
		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,STRCOD>>)

;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,SPTIDX>>)
	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
	TXNE T1,DA%INI!DA%WRT	;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
	TXNE T1,DA%WRT		;NOW, WHAT WERE WE DOING?
	JRST DSKUA5		;WRITING 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
	
	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
	MOVE T1,STRN07		;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
	CALL UPDOFN		;AND MAKE IT APPEAR ON THE DISK
	OKSKED			;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 SET AND BITS 2-6 ARE -1, DEVICE DESIGNATOR FOR STRUCTURE
;		IF 1B1 SET AND DOP%NF ALSO, THE CHAN, CONTROLLER, AND
;		UNIT NUMBERS TO BE USED (CKU VALUE)
;		OTHERWISE, IGNORED
;
;RETURNS +1: ALWAYS,
;	T1/ 0 ON SUCCESS, NON-ZERO ON FAILURE
;
;FLAGS IN T2:
;	1B10 (DOP%NF) USE NEW FORMAT FOR CHANNEL AND UNIT NUMBERS (CKU NUMBER)
;	1B11 (DOP%IL) INHIBIT ERROR LOGGING
;	1B12 (DOP%IR) INHIBIT ERROR RECOVERY
;	1B14 (DOP%WR) WRITE ACCESS
;
;CURRENTLY, IF THE TRANSFER CROSSES A PAGE BOUNDARY, THEN ERROR CORRECTION
;AND LOGGING ARE INHIBITED SINCE PHYSIO DOESN'T YET KNOW HOW TO HANDLE
;MULTIPLE CCW WORDS IN ERROR RECOVERY.
.DSKOP::MCENT
	STKVAR <STRNXX,UAC2,UAC3,SAVLCK>	;ALLOCATE STORAGE
	SETOM STRNXX		;NO STRUCTURE TO UNLOCK YET
	MOVEM T1,Q1		;REMEMBER AC FOR LATER
	MOVEM T2,UAC2		;PRESERVE USER'S FLAGS AND COUNT
	MOVEM T3,UAC3		;PRESERVE ADDRESS ALSO
	MOVE T4,CAPENB		;GET USER'S CAPABILITIES
	TXNN T4,SC%WHL!SC%OPR!SC%MNT ;HAVE PROPER PRIVILEGES?
	ITERR (WHELX1)		;NO. COMPLAIN
	TXNE T2,-1-<DOP%NF!DOP%IL!DOP%IR!DOP%WR!DOP%CT>	;ANY UNUSED FLAGS USED?
	ITERR (DECRSV)		;YES, COMPLAIN
	LOAD Q2,DOP%AT,Q1	;GET ADDRESS TYPE
	CAIN Q2,.DOPSR		;STRUCTURE RELATIVE?
	JRST [	LOAD T1,DOP%SN,Q1 ;YES. GET SN
		JUMPE T1,[MOVEI T1,PSNUM ;USE PS IF ZERO
			 SKIPN STRTAB(A) ;MAKE SURE ITS HERE
			 ITERR (DSKOX3)
			 JRST DSKOP3]  ;CONTINUE (NO STR TO LOCK)
		CAIE T1,<.RTJST (DOP%SN,DOP%SN)> ;IS FIELD ALL ONES?
		ITERR (DSKOX3)
		UMOVE T1,4	;GET DEVICE DESIGNATOR
		CALL CHKSTR	;CONVERT TO STR #
		 ITERR (DSKOX3)	;NONE
		MOVEM T1,STRNXX	;REMEMBER STRUCTURE TO UNLOCK
		JRST DSKOP3]	;PROCEED
	CAIE Q2,.DOPPU		;PHYSICAL?
	ITERR (DSKOX4)		;NO, THEN ILLEGAL MODE WAS REQUESTED
	UMOVE P4,4		;GET POSSIBLE CHANNEL, CONTROLLER, UNIT NUMBERS
	MOVE T1,UAC2		;ALSO GET USER'S FLAGS
	TXNE T1,DOP%NF		;ALREADY SETUP IN NEW FORMAT?
	JRST DSKOPN		;YES, GO ON
	MOVX P4,DOP%K2		;OLD FORMAT, GET VALUE FOR NO CONTROLLER
	LOAD T1,DOP%CN,Q1	;GET CHANNEL FROM OLD FORMAT LOCATION
	STOR T1,DOP%C2,P4	;STORE AWAY IN NEW FORMAT
	LOAD T1,DOP%UN,Q1	;GET UNIT NUMBER FROM OLD STYLE LOCATION
	STOR T1,DOP%U2,P4	;STORE AWAY IN NEW FORMAT TOO
DSKOPN:	MOVE T1,P4		;GET CKU NUMBER
	CALL CKUNPK		;UNPACK THEM
	CALL CHKCKU		;SEE IF THEY ARE LEGAL
	 ITERR ()		;NO, GIVE AN ERROR
	MOVE P3,T1		;REMEMBER THE UDB
DSKOP3:	MOVE T4,CAPENB		;GET CAPS AGAIN
	TXNE T4,SC%WHL!SC%OPR	;WHEEL OR OPERATOR?
	JRST DSKOP2		;WHEELS AND OPERATORS CAN DO IT ALL
	MOVE T2,UAC2		;GET USER FLAGS
	TXNN T2,DOP%WR		;WANT TO WRITE IT?
	JRST DSKOP2		;NO. ALLOW MAINT TO READ ANYTHING
	CAIN Q2,.DOPPU		;WANT TO WRITE PHYSICAL?
	SKIPL UDBSTR(P3)	;AND UNIT NOT PART OF A STRUCTURE?
	 ITERR (WHELX1,<SKIPL T1,STRNXX	;NO, GET STRUCTURE NUMBER
			CALL ULKSTR>)	;UNLOCK IT AND RETURN ERROR

DSKOP2:	NOINT			;NO INTERRUPTIONS NOW
	MOVE T1,UAC3		;GET USER ADDRESS
	HRRZ T2,UAC2		;AND WORD COUNT
	MOVX T3,DOP%WR		;GET WRITE FLAG READY
	ANDCM T3,UAC2		;MAKE VALUE INDICATING IF CORE IS TO BE WRITTEN
	CALL IOLOCK		;LOCK DOWN NECESSARY USER PAGES
	 ITERR(,<EXCH T1,STRNXX	;FAILED, SAVE ERROR CODE AND GET STR INDEX
		SKIPL T1	;WAS ONE SAVED?
		CALL ULKSTR	;YES, UNLOCK THE STRUCTURE
		OKINT		;INTERRUPTS OK AGAIN
		MOVE T1,STRNXX>)	;RESTORE ERROR CODE
	MOVEM T1,SAVLCK		;REMEMBER ADDRESS OF PAGE LIST
	MOVE T2,UAC3		;GET USER ADDRESS AGAIN
	HRRZ T3,UAC2		;AND WORD COUNT AGAIN
	HRRZ P1,STRTAB+PSNUM	;** TEMPORARY CROCK TO GET CDB ADDRESS **
	HRRZ P1,SDBUDB(P1)	;GET A UDB
	HRRZ P1,UDBCDB(P1)	;THEN GET A CDB ADDRESS
	CALL IOLCCW		;TURN LIST OF PAGES INTO LIST OF CCW WORDS
	MOVE T1,SAVLCK		;GET ADDRESS OF CCW LIST
	MOVE T1,(T1)		;THEN GET AOBJN POINTER TO LIST
	TLC T1,-1		;CHECK FOR ONLY ONE ELEMENT IN LIST
	TLCE T1,-1		;IS THERE ONLY ONE?
	JRST DSKOP4		;NO, SKIP ON
	MOVE T1,(T1)		;YES, GET THE CCW WORD
	HRRZ T2,CDBDSP(P1)	;GET DISPATCH ADDRESS
	CALL CDSCCA(T2)		;EXTRACT THE PHYSICAL ADDRESS FROM THE CCW
	SKIPA P3,T1		;THEN SAVE IT
DSKOP4:	SETZM P3		;OR ZERO AC AS A FLAG
	LOAD T1,DOP%RA,Q1	;GET DISK ADDRESS
	CAIE Q2,.DOPSR		;STRUCTURE RELATIVE?
	LOAD T1,DOP%UA,Q1	;NO. GET UNIT RELATIVE ADDRESS
	MOVE T2,UAC2		;GET FLAGS AND COUNT
	TXO T2,DOP%EO		;GENERATE ERRORS ON OFF-LINE
	SKIPN T3,P3		;GET PHYSICAL ADDRESS IF ONLY ONE CCW
	MOVE T3,SAVLCK		;OR POINTER TO CCW LIST IF MULTIPLE ONES
	SKIPGE T4,STRNXX	;GET STRUCTURE NUMBER
	MOVEI T4,PSNUM		;USE PS IF -1
	CAIN Q2,.DOPPU		;PHYSICAL ADDRESSES?
	JRST [	TXO T2,1B0	;YES. TELL UDSKIO WE HAVE THE NUMBERS
		MOVE T4,P4	;GET CKU VALUE TO USE
		JRST .+1]	;AND GO DO IT
	SKIPN P3		;DOING MULTIPLE PAGE TRANSFER?
	CALL MDSKIO		;YES, CALL MULTIPLE-PAGE ROUTINE
	SKIPE P3		;DOING A SINGLE PAGE TRANSFER INSTEAD?
	CALL UDSKIO		;YES, CALL OLD ROUTINE
	UMOVEM T1,1		;RETURN ERROR BITS
	MOVE T1,SAVLCK		;GET POINTER TO LIST OF CCW WORDS
	MOVX T2,DOP%WR		;GET WRITE FLAG READY
	ANDCM T2,UAC2		;CREATE FLAG INDICATING IF CORE WAS WRITTEN
	CALL IOCNLK		;UNLOCK ALL PAGES THAT WERE LOCKED
	OKINT			;ALLOW INTS AGAIN
	SKIPL T1,STRNXX		;SAVED STR #
	CALL ULKSTR		;YES - UNLOCK IT
	JRST MRETN		;AND RETURN
;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
	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,STRCOD>>)
		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
	MOVE T3,P1		;GET UDB
	CALL FNDCH1		;RETURN THE CKU NUMBERS NEEDED
	MOVE D,T1		;PUT INTO RIGHT AC
	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 THE CKU VALUE (CHAN, CTRL, UNIT NUMBERS)
	MOVEM A,Q1		;SAVE IT
	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/ CKU NUMBERS
	MOVE C,Q3		;C/ VIRTUAL ADDRESS OF WORK PAGE
	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
	SKIPE 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
	JUMPN 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 T3,0(Q1)		;GET ADDRESS OF UDB FOR THIS LOGICAL UNIT
	CALL FNDCH1		;GET THE CKU NUMBER FOR THE 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/ CKU NUMBERS
	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
	 JRST BATQE		;FAILED. MUST BE DONE THEN
	MOVEI C,0(P4)		;UDB INDEX
	CALL FNDCH1		;GO GET CKU NUMBERS
	MOVE P2,A		;SAVE THEM
	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=CKU NUMBER


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
	LOAD B,DOP%U2,P2	;UNIT NUMBER OF THIS DRIVE
				;** NOTE: THIS IS POSSIBLY WORTHLESS FOR THE
				;** RP20, SINCE IT HAS A CONTROLLER, AND ITS
				;** UNIT NUMBER CAN BE LARGER THAN 35 ANYWAY
	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 CHAN, CTRL, AND UNIT NUMBERS
	MOVE B,P5		;GET VIRTUAL ADDRESS
	MOVE C,P1		;AND 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
	SKIPE ERRSWP		;WAS THERE A SWAP ERROR?
	JRST [			;YES THERE WAS, TAKE CARE OF IT
		SOSN ERRSWP	;DEC THE COUNT, SKIP IF DONE
		BUG (SWPXXX)	;CATCH ALL ERROR		
		JRST .+1]	;IF WE KEEP GOING, OK BY ME
	OKINT			;AND ALLOW INTS NOW
	RET
   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)
HOMSER==:164			;SERIAL NUMBER OF CPU WHICH IS BOOTED BY THIS
				; STRUCTURE
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,FSICTL,FSIUNT,FSIUDB,FSINAM,FSIFLG,FSINPK,FSIUSZ,FSISWP,FSITYP,FSISER,FSICUR>
	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:	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 [SKIPN T1,LPSNAM	;NO PUBLIC STR FOUND, CHECK NAMES
		MOVE T1,PSNAM	;LOGICAL PS NAME NOT SET UP, USE PS NAME
		MOVEM T1,FSINAM
		SETZM FSICUR	;CLEAR NAME OF CURRENT STR NAME
		CALL CHKHOM	;GO READ HOME BLOCKS AND CHECK THEM
		 JRST FSIIN1	;NO PUBLIC STRUCTURE FOUND, GO COMPLAIN
		JRST .+1]
	;..
	;..
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
	MOVEM P1,FSINAM		;STORE FOR POSSIBLE LATER USE
	MOVE T1,P1		;PRINT ITS NAME
	CALL FSI6TY
	HRROI T1,[ASCIZ/ mounted/] ;SAY IT IS MOUNTED
	CALL FSIPSO
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/	CURRENT CDB
;  P2/	CURRENT KDB IF ANY
;  P3/	CURRENT UDB
;  P4/	AOBJN POINTER OVER ALL CHANNELS



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 P4,MAXCHN		;SET UP TO READ EVERY HOME BLOCK
	HRLZS P4		;GET AOBJN COUNTER OF CHANNELS

CHKHO1:	SKIPN P1,CHNTAB(P4)	;THIS CHANNEL EXIST?
	JRST CHKHO2		;NO, TRY NEXT ONE
	CALL DGUMAP		;YES, LOOP OVER ALL UNITS ON THIS CHANNEL
	 CALL CKHOMU		;EXAMINE EACH UNIT ON THE CHANNEL
CHKHO2:	AOBJN P4,CHKHO1		;LOOP OVER ALL CHANNELS



;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.
	SKIPE FSINAM		;HAVE WE TRIED PS: YET?
	JRST CHKHO9		;YES
	SKIPN T1,LPSNAM		;IS THERE A LOGICAL PS NAME?
	MOVE T1,PSNAM		;NO, THE DEFAULT NAME IS PS
	MOVEM T1,FSINAM		;STORE FOR NEXT LOOK
	SETZM FSICUR		;ZERO ANY CURRENT STR LOOKING AT
	JRST CHKH20		;AND GO LOOK AGAIN
CHKHO9:	HRROI T1,[ASCIZ/ System structure not found.  What is its name? /]
	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 the name of the system 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 one 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
;SUBROUTINE CALLED BY CHKHOM TO EXAMINE THE STATE OF A PARTICULAR UNIT.
;CALLED WITH:
;  P1/	CDB
;  P2/	KDB IF ANY
;  P3/	UDB
;RETURNS:  +1 ALWAYS
;USES Q1-Q3

CKHOMU:	MOVE T1,UDBSTS(P3)	;GET UNIT STATUS
	TXNN T1,US.DSK		;IS THIS A DISK UNIT?
	RET			;NO, DON'T EXAMINE IT
	MOVE T3,P3		;COPY UDB FOR CALL
	CALL FNDCH1		;CALCULATE THE CKU NUMBERS
	MOVEM T1,Q2		;REMEMBER FOR LATER USE
	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
	 RET			;ERROR OR OFF-LINE
	MOVEI T1,HOMPGA		;NOW CHECK THE FIRST HOME BLOCK
	MOVEI T2,HM1BLK		;...
	CALL HBCCHK		;CHECK THE CONSISTENCY CHECKS
	 TXZA Q1,HB%1OK		;HOME BLOCKS BAD
	TXO Q1,HB%1OK		;HOME BLOCK IS GOOD
	MOVEI T1,HOMPGA+HBLEN	;NOW CHECK THE BACKUP HOME BLOCK
	MOVEI T2,HM2BLK
	CALL HBCCHK
	 TXZA Q1,HB%2OK		;BACKUP HOME BLOCK IS BAD
	TXO Q1,HB%2OK		;BACKUP HOME BLOCK IS GOOD
	TXNE Q1,HB%2OK		;ARE THERE ANY GOOD HOME BLOCKS
	HRRI Q1,HOMPGA+HBLEN	;YES, GET ADR OF HOME BLOCK
	TXNE Q1,HB%1OK		;SEE IF PRIMARY IS GOOD
	HRRI Q1,HOMPGA		;YES, USE IT
	TRNN Q1,-1		;ANY HOME BLOCKS GOOD?
	RET			;NO, RETURN
	MOVX T1,US.WLK		;SEE IF THIS UNIT IS WRITE LOCKED
	TDNE T1,UDBSTS(P3)	;...
	TXO Q1,HB%WLK		;YES, SET WRITE LOCKED FLAG
	HRRZ T1,Q1		;GET ADDRESS OF HOME BLOCK
	MOVE T2,HOMSER(T1)	;GET THE CPU SERIAL # OUT OF THE HOME BLOCK
	CAME T2,APRSER		;IS IT THE ONE FOR THE PUBLIC STRUCTURE?
	JRST [SKIPE T2,HOMSNM(T1) ;SERIAL # DOES NOT MATCH. CHECKING FOR PS?
		CAME T2,FSINAM	;YES, CORRECT NAME?
		RET		;NO, DON'T BUILD AN SDB, THEN
		JRST .+1]
	MOVE T2,HOMSNM(T1)	;GET STRUCTURE NAME
	SKIPN FSICUR		;FIRST TIME THRU?
	MOVEM T2,FSICUR		;YES, STORE CURRENT NAME
	CAME T2,FSICUR		;ARE THEY THE SAME?
	RET			;NO, DON'T BUILD AN SDB, THEN
	SETZ T4,		;INDICATE NO COPYING REQUIRED
	TXNN Q1,HB%1OK		;WAS FIRST HOME BLOCK OK?
	MOVEI T4,CPYH2		;NO. SET UP TO COPY THE SECONDARY
	TXNN Q1,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
	MOVE T3,Q2		;GET CKU NUMBERS
	CALL @T4		;COPY THE GOOD ONE INTO THE BAD ONE
	 JRST CHKHO8		;FAILED. LEAVE ERROR BITS SET
	TXO Q1,HB%1OK!HB%2OK	;OK, CLEAR ERROR BITS
CHKHO8:	MOVE T1,Q1		;T1/(FLAGS,,ADR OF HOME BLOCK)
	MOVE T2,P3		;T2/ADDRESS OF UDB FOR THIS UNIT
	CALL BLDSTR		;GO BUILD STRTAB AND SDB
				; RETURNS ADDRESS OF SDB IN T1
	 RET			;RAN OUT OF STR'S

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

	MOVE T2,P3		;GET ADDRESS OF UDB
	HLL T2,Q1		;SAVE FLAGS FOR THIS UNIT
	HRRZ T3,HOMLUN(Q1)	;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
	RET			;DONE WITH THIS UNIT
;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	;NOT YET, GET ADDRESS OF UDB
		HRRZ T3,T4	;ALSO GET STRUCTURE NUMBER
		CALL CRTSTR	;CREATE THE SDB
		 MOVE T1,T3	;FAILED, GET ADDRESS OF SDB
		RETSKP]		;SLOT CREATED, TAKE SUCCESS RETURN
	CAMN T2,SDBNAM(T3)	;IS THIS THE STRUCTURE WE WANT?
	JRST [	MOVE T2,UDBLOC	;YES, GET ADDRESS OF UDB
		CALL ADDSTR	;ADD THE UNIT TO THE STRUCTURE
		 MOVE T1,T3	;FAILED, 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 T4,ADSUDB		;SET T4=ADDRESS OF UDB
	CALL FIXVID		;FIX UDBVID
	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
;	T3/ 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,CRTSSN,CRTSER>	;SAVE CALLING ARGUMENTS
	SETZM CRTSER		;INDICATE NO ERRORS YET
	TRNN T3,-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 T4,CRTUDB		;SET T4=ADDRESS OF UDB
	CALL FIXVID		;FIX UP UDBVID IF A MULTI-PACK STRUCTURE
	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 FIX UP UDBVID FOR A UNIT IN A MULTI-PACK STRUCTURE
;ACCEPTS
;	T1/ADDRESS OF HOME BLOCK
;	T3/ADDRESS OF SDB
;	T4/ADDRESS OF UDB
;
;	CALL FIXVID
;RETURNS +1 WITH UDBVID FIXED TO BE XXXN, WHERE XXX=STR NAME, N=UNIT IN STR
FIXVID:	HLRZ T2,HOMLUN(T1)	;GET NO OF PACKS IN STRUCTURE
	SOJLE T2,R		;NOTHING TO DO IF A SINGLE-PACK STRUCTURE
	HRRZ T2,HOMLUN(T1)	;MULTI-PACK - GET UNIT WITHIN STRUCTURE
	MOVE T1,SDBNAM(T3)	;GET NAME OF STRUCTURE
	TRNE T1,77		;6-CHARACTER NAME?
	RET			;YES, NOTHING WE CAN DO ABOUT IT
	ADDI T2,'0'		;NO, GET SIXBIT UNIT NUMBER
	MOVEI T1,7700		;SET FOR TEST ON NAME
FIXVI1:	TDNE T1,SDBNAM(T3)	;THIS CHARACTER IN NAME?
	JRST FIXVI2		;YES, HERE IS WHERE TO APPEND UNIT NO
	LSHC T1,6		;NO, SHIFT MASK, ENDING CHARACTER
	JRST FIXVI1		;AND TEST NEXT CHARACTER OF NAME
FIXVI2:	IOR T2,SDBNAM(T3)	;MANUFACTURE XXXX+N
	MOVEM T2,UDBVID(T4)	;SAVE NAME IN UDB
	RET			;AND WE ARE DONE
;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 SBD
;BLDSDB - ROUTINE CALLED FROM THE MSTR JSYS TO ADD A UNIT TO A STRUCTURE
;
;ACCEPTS IN T1/ CKU NUMBER OF UNIT
;	    T2/	ADDRESS OF HOME BLOCK PAGE
;	    T3/ FOR BLDNEW: STRUCTURE NUMBER
;		FOR BLDSDB: SDB ADDRESS
;
;RETURNS: +1	 FAILURE, ERROR CODE IN T1
;	  +2	SUCCESS, T1/ ADDRESS OF SDB


BLDNEW::SKIPA T4,[IFIW CRTSTR]	;GET ONE ROUTINE TO CALL
BLDSDB::MOVE T4,[IFIW ADDSTR]	;OR OTHER ROUTINE TO CALL
	ASUBR <BLSCKU,BLSADR,BLSSDB,BLSROU>
	CALL CKUNPK		;UNPACK THE CKU NUMBERS
	CALL CHKCKU		;VERIFY THEY ARE GOOD AND RETURN THE UDB
	 RETBAD ()		;FAILED
	MOVE T2,T1		;PUT UDB IN RIGHT AC
	MOVE T1,BLSADR		;GET ADDRESS OF PAGE CONTAINING HOME BLOCKS
	MOVE T3,BLSSDB		;GET SDB ADDRESS OR STRUCTURE NUMBER
	CALL @BLSROU		;CREATE AN SDB OR ADD THIS UNIT TO IT
	 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::STKVAR <UNIBVA>		;ALLOCATE STORAGE
	MOVEM T4,UNIBVA		;REMEMBER ADDRESS AND PAGE
	CALL CHKCKU		;CONVERT THE CKU NUMBERS INTO UDB ADDRESS
	 RETBAD ()		;CAN'T DO IT
	MOVE T4,T1		;MOVE UDB TO RIGHT AC
	HLRZ T1,UNIBVA		;GET VIRTUAL ADDRESS OF BAT BLOCK PAGE
	HRRZ T2,UNIBVA		;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/ CKU VALUE (CHANNEL, CONTROLLER, AND UNIT NUMBERS)
;	     T4/ NUMBER OF UNITS IN STRUCTURE,,UNIT NUMBER WITHIN STRUCTURE
;	     P1/ # OF PAGES FOR SWAPPING ON THIS STRUCTURE
;	     P2/ MEDIA IDENTIFICATION (PACK UNIQUE CODE)
;	     P3/ SERIAL NUMBER OF CPU BOOTED FROM THIS STRUCTURE
;		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,CRHCKU,CRHNUM>
	STKVAR <CRHVIR,CRHP4S,CRHMID,CRHUDB,CRHSER>
	MOVEM P1,CRHP4S		;SAVE # OF PAGES FOR SWAPPING
	MOVEM P2,CRHMID		;SAVE MEDIA ID
	MOVEM P3,CRHSER		;SAVE SERIAL NUMBER

; VALIDATE AMOUNT OF SWAPPING SPACE REQUESTED

	MOVE T1,CRHCKU		;GET CKU VALUE
	CALL CKUNPK		;EXPAND INTO THE SEPARATE NUMBERS
	CALL CHKCKU		;RETURN THE UDB IN T1
	 RETBAD ()		;CAN'T FIND IT
	MOVEM T1,CRHUDB		;REMEMBER THE UDB
	HLRZ T2,CRHNUM		;GET NUMBER OF UNITS IN STRUCTURE
	MOVE T3,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

	MOVE P1,CRHUDB		;GET BACK UDB ADDRESS
	MOVE P1,UDBSIZ(P1)	;THEN GET POINTER TO 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
	MOVE P2,CRHSER		;GET CPU SERIAL NUMBER
	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,CRHCKU		;GET CKU 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,CRHCKU		;GET CKU 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/ CKU NUMBERS OF 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)
;
;NOTICE:  SINCE AN RP20 HAS SECTORS OF 1000 WORDS, AND WE HAVE READ ONLY
;200 WORDS, A CERTAIN KIND OF OVERRUN IS EXPECTED TO OCCUR BY PHYH2, AND
;THEREFORE IS IGNORED.  IF THE HOME BLOCKS READ BAD OCCASIONALLY, THEN
;THE PROBLEM MIGHT BE THAT THESE IGNORED OVERRUNS ARE "REAL".


REDHOM::STKVAR <REDCKU,REDHOB,REDBLK,REDVIR>
	MOVEM T1,REDCKU		;SAVE CHANNEL, CONTROLLER, AND UNIT NUMBER
	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,REDCKU		;GET CKU NUMBER
	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,REDCKU		;GET CKU NUMBER AGAIN
	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
	TLC T1,-1		;CHECK FOR DRIVE OFFLINE KIND OF ERROR
	TLCN 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/	CKU 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,CPHCKU> ;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)	;SAVE THIS,,OTHER BLOCK NUMBERS
	HRRZM T3,HOMSLF(T4)	;SAVE THIS BLOCK NUMBER


; NOW WRITE OUT THE CORRECTED HOME BLOCK

	HRRZ T1,CPHVIR		;GET VIRTUAL ADDRESS OF HOME BLOCKS
	SKIPN CPHDIR		;WRITING OUT FIRST HOME BLOCK?
	CALL SWPHOM		;NO, SWAP THEM SO PAGE STARTS WITH SECOND ONE
	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
	MOVE T4,CPHCKU		;GET CKU VALUE FOR UNIT
	CALL UDSKIO		;WRITE THE CORRECTED HOME BLOCK
	MOVE T4,T1		;SAVE RESULT
	HRRZ T1,CPHVIR		;GET BACK VIRTUAL ADDRESS OF HOME BLOCKS
	SKIPN CPHDIR		;DID WE SWAP THEM?
	CALL SWPHOM		;YES, SWAP THEM BACK
	JUMPN T4,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
;THE CHANNEL, CONTROLLER, AND UNIT NUMBERS OF THE UNIT (CKU VALUE)

;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
	MOVE P2,FSISER		;GET CPU SERIAL NUMBER
	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 CKU NUMBER
	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 CKU NUMBER
	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/ CKU NUMBER
;	    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 SWAP THE HOME OR BAT BLOCKS IN A PAGE.  NECESSARY BECAUSE
;THE DISK WRITE HAS TO BEGIN AT THE FIRST WORD OF A PAGE FOR RP20'S.
;CALL:
;  T1/	VIRTUAL ADDRESS OF THE PAGE HOLDING THE HOME OR BAT BLOCKS
;RETURNS:
;  +1:	ALWAYS, WITH THE TWO HOME OR BAT BLOCKS SWAPPED.
;THIS ROUTINE TRASHES THE REMAINDER OF THE PAGE AFTER THE TWO BLOCKS.


SWPHOM:	MOVSI T2,0(T1)		;COPY FROM FIRST BLOCK
	IORI T2,HBLEN*2(T1)	;TO SECOND HALF OF PAGE
	BLT T2,HBLEN*3-1(T1)	;SAVE FIRST HOME BLOCK AWAY
	MOVSI T2,HBLEN(T1)	;NOW POINT AT SECOND HOME BLOCK
	IORI T2,0(T1)		;AND TOP OF PAGE
	BLT T2,HBLEN-1(T1)	;COPY SECOND HOME BLOCK UP ONTO FIRST ONE
	MOVSI T2,HBLEN*2(T1)	;NOW WANT TO COPY BACK FIRST HOME BLOCK
	IORI T2,HBLEN(T1)	;ON TOP OF OLD SECOND HOME BLOCK
	BLT T2,HBLEN*2-1(T1)	;DO IT
	RET			;DONE
; 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
;	     P2/ SERIAL NUMBER OF CPU THIS STRUCTURE BOOTS
;		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
	MOVE T3,P1		;GET POINTER TO DSKSIZ TABLE
	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
	MOVEM P2,HOMSER(T4)	;STORE CPU SERIAL NUMBER
	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 T3,0(Q1)		;GET ADDRESS OF UDB FOR THIS LOCICAL UNIT
	CALL FNDCH1		;CONVERT UDB ADDRESS INTO CKU NUMBER
	MOVEM T1,MODHCU		;SAVE THE CKU VALUE
	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/CKU NUMBERS FOR THIS LOGICAL UNIT
	MOVE T3,MODHVA		;GET VIRTUAL ADDRESS
	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/ CKU NUMBERS FOR THE PACK TO BE WRITTEN
;	T3/ VIRTUAL ADDRESS OF THE PAGE WITH THE HOME BLOCKS
;
;	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 REDHOM
;WILL CAUSE THE PAGE TO BE SET UP THIS WAY



UPDHOM:	SAVEQ
	ASUBR <UPDHPA,UPDHCU,UPDVPA>
	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 CKU NUMBER, LENGTH
	CALL UDSKIO		;WRITE THE FIRST HOME BLOCK TO THE DISK
	MOVEM T1,Q1		;SAVE ERROR INDICATOR FROM UDSKIO
	MOVE T1,UPDVPA		;GET VIRTUAL ADDRESS OF HOME BLOCKS
	CALL SWPHOM		;SWAP THE HOME BLOCKS
	MOVEI T1,HM2BLK		;T1/SECTOR NUMBER OF SECOND HOME BLOCK
	MOVE T2,[1B0+1B14+HBLEN] ;T2/WRITE, ADDRESS IS CKU NUMBER, LENGTH
	MOVE T3,UPDHPA		;T3/PHYSICAL ADDRESS OF START OF PAGE
	MOVE T4,UPDHCU		;T4/ CKU VALUE
	CALL UDSKIO		;WRITE THE SECOND HOME BLOCK TO THE DISK
	IORM T1,Q1		;REMEMBER ERROR IF ANY
	MOVE T1,UPDVPA		;GET BACK VIRTUAL ADDRESS
	CALL SWPHOM		;SWAP BACK THE HOME BLOCKS
	SKIPE Q1		;ANY ERROR FROM EITHER WRITE?
	 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
	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
	CALL DSPAIR		;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
;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		; STILL WITHIN THE REGION?
	 RET			; NO, FINISHED WITH THIS PAIR
	CALL DOSECT		; MARK THIS SECTOR AS USED
	JRST DSPAIR		; YES. GO DO IT

DOSECT:	SAVEAC <T2,T3,T4>	;
	STKVAR <CURBAT,CKBDRA>	;
	MOVEM T1,CURBAT		; SAVE PHYS SECT ADDRESS OF FIRST SECTOR
	MOVE T4,STRTAB(P5)	; GET SDB
	MOVE T3,SDBTYP(T4)	; POINT TO SIZE DATA FOR THIS DISK TYPE
	CALL CVDADR		; FIND LOGICAL SECTOR NUMBER
	 RET			; THIS IS A LOST SECTOR, FORGET IT
	IDIV T1,SECPAG(T3)	; GET INTEGRAL NUMBER OF PAGES
	IMUL T1,SECPAG(T3)	; FIND STARTING SECTOR FOR PAGE
	SUB T1,SDBFSS(T4)	; SEE IF WITHIN SWAPPING BOUNDS
	SKIPL T1		; IS IT?
	CAML T1,SDBNSS(T4)	; ?
	 JRST DSECT1		; NO
	IDIV T1,SECCYL(T3)	; FIND TRACK AND SECTOR OFFSET IN TRACK
	IMUL T1,SDBNUM(T4)	; FIND INTERLEAVED TRACK NUMBER
	MOVEI T4,-SDBUDB(P4)	; GET PACK # + SDB LOCATION
	SUB T4,STRTAB(P5)	; COMPUTE PACK NUMBER IN STRUCTURE
	ADD T1,T4		; ADD PACK NUMBER ...
	IMUL T1,SECCYL(T3)	; FIND STARTING SWAP SECT FOR THIS TRACK
	ADD T1,T2		; ADD IN SECTOR OFFSET IN TRACK
	TXO T1,DRMOB		; SAY IS AN OVERFLOW ADDRESS
	MOVEM T1,CKBDRA		; SAVE ADDRESS TO BE ASSIGNED
	CALL DRMASA		; ASSIGN DRUM ADDRESS
	 JRST [	MOVE T3,STRTAB+PSNUM ; POINT TO SDB FOR PS (ONLY CASE
		LOAD T3,STRNAM,(T3) ;  IN WHICH WE GET HERE)
		SKIPE T1	; OUT-OF-RANGE?
		BUG(SWPASF,<<T3,STRNAM>,<CKBDRA,ADDR>>)
		JRST DSECT1]	;
DSECT1:	MOVE T1,CURBAT		; GET BACK PHYSICAL SECTOR ADDRESS
	MOVE T3,STRTAB(P5)	; GET SDB
	MOVE T3,SDBTYP(T3)	; POINT TO SIZE DATA FOR THIS DISK TYPE
	ADD T1,SECPAG(T3)	; STEP THE SECTORS BY A PAGE
	RET			; 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)	; GET LOGICAL SECTORS/CYLINDER
	ADD T4,LPPCYL(T3)	; ADD LOST SECT TO GET PHYSICAL SEC/CYL
	IDIV T1,T4		; GET CYL IN T1, SEC IN T2
	CAML T2,SECCYL(T3)	; IS THIS A LOST SECTOR?
	JRST [	AOS T1		; YES, GET CYL FOLLOWING THIS LOST REGION
		IMUL T1,T4	; FIND PHYS SECT NUMBER OF FIRST SECTOR
		RET]		; AND RETURN
	IMUL T1,SECCYL(T3)	; CONVERT CYL TO LOGICAL SECTORS
	ADD T1,T2		; COMBINE TO GET LOGICAL ADR
	RETSKP			; 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 THE CKU NUMBERS 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, CONTROLLER, 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/ CKU NUMBER (CHAN, CTRL, AND UNIT NUMBERS)
;	  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: T1/  CKU NUMBER OF UNIT
;	  T2/  VIRTUAL ADDRESS IN MEMORY OF BAT BLOCKS
;	  T3/  PHYSICAL CORE ADDRESS OF BAT BLOCKS
;RETURNS: +1 WRITE FAILED
;	  +2 OK


BATOUT::ASUBR <SVDRV,SVVADR,SVPADR,TEST1>	;SAVE CALLING ARGUMENTS
	SETZM TEST1		;ASSUME NONE WORKED
	MOVE T2,[1B0+1B14+HBLEN] ;CONTROL WORD
	MOVE T3,SVPADR		;GET PHYSICAL ADDRESS
	MOVE T4,SVDRV		;GET CKU NUMBERS
	MOVEI T1,BATBL1		;BLOCK NUMBER
	CALL UDSKIO		;OPERATE THE DISK
	JUMPE T1,DO2B		;IF NO ERROR,GO ON
	SETOM TEST1		;MARK FAILURE
	MOVE T1,SVDRV		;GET CKU NUMBER BACK
	BUG(NOBAT1,<<T1,CKUNUM>>)
DO2B:	MOVE T1,SVVADR		;GET VIRTUAL ADDRESS OF BAT BLOCKS
	CALL SWPHOM		;SWAP THE BAT BLOCKS
	MOVE T2,[1B0+1B14+HBLEN] ;CONTROL WORD
	MOVE T3,SVPADR		;GET PHYSICAL ADDRESS AGAIN
	MOVE T4,SVDRV		;GET CKU NUMBER
	MOVEI T1,BATBL1+HM2BLK-HM1BLK ;ADDRESS OF SECONDARY BLOCK
	CALL UDSKIO		;OPERATE DISK AGAIN
	MOVE T4,T1		;SAVE RESULT
	MOVE T1,SVVADR		;RETRIEVE VIRTUAL ADDRESS OF BAT BLOCKS
	CALL SWPHOM		;SWAP BAT BLOCKS BACK
	SKIPN T4		;NO ERRORS?
	RETSKP			;YES. SAY IT IS GOOD THEN
	MOVE T1,SVDRV		;GET CKU NUMBER
	BUG(NOBAT2,<<T1,CKUNUM>>)
	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 system structure? /]
	HRROI T2,[ASCIZ/
[This procedure removes all existing directories and files and creates
the minimum 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

;SEE IF USER WANTS TO REWRITE THE HOME BLOCKS

FSIDI4:	HRROI T1,[ASCIZ/
Do you want to define the system 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, CONTROLLER, AND UNIT FOR EACH LOGICAL UNIT IN THE STRUCTURE.
;STORE IN HOMTAB, INDEXED BY LOGICAL UNIT NUMBER


FSIDI2:	MOVE T1,[POINT 7,FSIBLK] ;SET UP TO BUILD QUESTION STRING
	MOVE T2,[POINT 7,[ASCIZ/
On which "CHANNEL,CONTROLLER,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,FSIOCT		;GET PHYSICAL DRIVE #
	CALL FSIASK		;ASK QUESTION AND GET ANSWER
	 JRST FSIDI2		;ERROR, GO ASK QUESTION AGAIN
	MOVEM T1,FSICHN		;SAVE CHANNEL NUMBER
	CALL FSIOCT		;READ IN CONTROLLER NUMBER
	 JRST FSIDI2		;ERROR, ASK AGAIN
	MOVEM T1,FSICTL		;SAVE CONTROLLER NUMBER
	CALL FSIOCT		;READ IN UNIT NUMBER
	 JRST FSIDI2		;ERROR
	MOVEM T1,FSIUNT		;SAVE UNIT NUMBER
	MOVE T1,FSICHN		;GET CHANNEL NUMBER
	MOVE T2,FSICTL		;CONTROLLER NUMBER
	MOVE T3,FSIUNT		;AND UNIT NUMBER
	CALL CHKCKU		;LOOK FOR THE SPECIFIED UNIT
	 SKIPA T2,T1		;FAILED, HAVE TO SEE WHY
	JRST FSIDE1		;FOUND IT, PROCEED
	HRROI T1,[ASCIZ/? Can't find specified unit/]	;START WITH CATCH ALL
	CAIN T2,MSTX14		;INVALID CHANNEL?
	HRROI T1,[ASCIZ/? Illegal channel number/]
	CAIN T2,MSTX41		;NO SUCH CHANNEL?
	HRROI T1,[ASCIZ/? No such channel/]
	CAIN T2,MSTX16		;INVALID CONTROLLER?
	HRROI T1,[ASCIZ/? Illegal controller number/]
	CAIN T2,MSTX42		;NO SUCH CONTROLLER?
	HRROI T1,[ASCIZ/? No such controller/]
	CAIN T2,MSTX15		;ILLEGAL UNIT?
	HRROI T1,[ASCIZ/? Illegal unit number/]
	CAIN T2,DIAGX9		;NO SUCH UNIT?
	HRROI T1,[ASCIZ/? No such unit/]
	CAIN T2,MSTX27		;NOT A DISK?
	HRROI T1,[ASCIZ/? Not a disk device/]
	CALL FSIPSO		;GIVE THE MESSAGE
	HRROI T1,[ASCIZ/.
/]				;FINAL CRLF
	CALL FSIPSO		;GIVE THAT TOO
	JRST FSIDI2		;AND TRY AGAIN


FSIDE1:	MOVEM T1,FSIUDB		;REMEMBER UDB OF UNIT
	MOVE T3,UDBSIZ(T1)	;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
	MOVE T1,BTWCYL(T3)	; Get Bit words per cylinder
	AOS T1			; Add one word/cyl for Top 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 T1,FSICHN		;GET CHANNEL
	MOVE T2,FSICTL		;CONTROLLER
	MOVE T3,FSIUNT		;AND UNIT
	CALL CKUPAK		;RETURN THE CKU NUMBER IN T1
	MOVE T2,FSINPK		;GET LOGICAL PACK NUMBER AGAIN
	SUB T2,FSIDIC		;...
	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 T1,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 T1,HOMTAB(T2)	;STORE CKU NUMBER 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
	JUMPLE T1,FSIDI9	;NEGATIVE IS ILLEGAL
	CAIGE T1,^D2000		;IS THIS ENOUGH SWAPPING SPACE?
	JRST FSIDI9		;NO. PS MUST HAVE ENOUGH
	MOVE T1,FSIUDB		;T1/ UDB OF A UNIT
	MOVE T2,FSINPK		;T2/NUMBER OF UNITS IN STRUCTURE
	MOVE T3,FSISWP		;T3/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:	JUMPL T1,FSID10		;ASK AGAIN IF NEGATIVE
	MOVEM T1,FEFSIZ		;SAVE THE ANSWER
	JRST FSID13		;YES.

	REPEAT 0,<
FSIDI3:	HRROI T1,[ASCIZ/
Is this structure the system structure? /]
	HRROI T2,[ASCIZ/
[The system structure is the structure that contains <SYSTEM>
 and <SUBSYS> and to which each user is connected by login.  The
 system 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
>


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:	HRROI T1,[ASCIZ/
What is the name of this structure? /]
	HRROI T2,[ASCIZ/
Enter 6 or fewer characters
/]
	MOVEI T3,FSIDEV		;GET A SIXBIT DEVICE NAME
	CALL FSIASK		;GET THE NAME OF THE STRUCTURE
	 JRST FSID17		;FAILED, TRY AGAIN
	JUMPE T1,FSID17		;GAVE NO NAME, TRY AGAIN
	MOVEM T1,FSINAM		;SAVE THE NAME
	SETZM FSIFLG		;INIT FLAGS
	MOVE T1,APRSER		;GET CPU SERIAL NUMBER
	MOVEM T1,FSISER
	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, CONTROLLERS, AND UNITS


FSICFG:	STKVAR <FSICFC,FSICFK,FSICFU,FSICFA>	;ALLOCATE STORAGE
	HRROI T1,FSIMS1		;GET HELP MESSAGE
	CALL FSIPSO		;TYPE OUT FIRST PART OF MESSAGE
	SETOM FSICFC		;SET CHANNEL TO -1 TO START LOOP

FSICF1:	MOVE T1,FSICFC		;GET CHANNEL NUMBER
	MOVE T2,FSICFK		;AND CONTROLLER NUMBER
	MOVE T3,FSICFU		;AND THE UNIT NUMBER
	CALL ADVCKU		;ADVANCE TO NEXT DISK UNIT IN SYSTEM
	 JRST [	HRROI T1,[ASCIZ/]
/]				;NO MORE UNITS, GET FINAL TEXT
		CALLRET FSIPSO]	;FINISH MESSAGE AND RETURN
	MOVEM T1,FSICFC		;SAVE NEW CHANNEL NUMBER (DMOVEM DOESN'T WORK!!)
	MOVEM T2,FSICFK		;AND NEW CONTROLLER NUMBER
	MOVEM T3,FSICFU		;ALSO SAVE NEW UNIT NUMBER
	MOVEM T4,FSICFA		;FINALLY SAVE UDB ADDRESS
	HRROI T1,[ASCIZ/   /]	;START WITH SOME SPACES
	CALL FSIPSO		;TYPE THEM
	MOVE T1,FSICFC		;GET CHANNEL NUMBER
	CALL FSIOTY		;TYPE IT
	MOVEI T1,","		;PRINT COMMA
	CALL FSIPBO		; ...
	MOVE T1,FSICFK		;GET CONTROLLER NUMBER
	CALL FSIOTY		;PRINT IT
	MOVEI T1,","		;ANOTHER COMMA
	CALL FSIPBO		;TYPE IT
	MOVE T1,FSICFU		;GET UNIT NUMBER
	CALL FSIOTY		;TYPE IT
	HRROI T1,[ASCIZ /   ;Type=/] ;PREPARE TO PRINT UNIT TYPE
	CALL FSIPSO		; ...
	MOVE T4,FSICFA		;GET UDB ADDRESS
	LOAD T1,USTYP,(T4)	;GET TYPE
	MOVE T1,NAMUTP(T1)	;GET POINTER TO NAME
	CALL FSIPSO		;PRINT NAME
	MOVE T4,UDBSTS(T4)	;GET UNIT STATUS
	TXNE T4,US.OFS		;OFFLINE?
	CALL FSICF5		;YES - PRINT MESSAGE
	TXNE T4,US.PGM		;PROGRAMMABLE DUAL PORT?
	CALL FSICF6		;YES - PRINT MESSAGE
	TXNE T4,US.WLK		;WRITE LOCKED?
	CALL FSICF7		;YES - PRINT MESSAGE
	HRROI T1,[ASCIZ /
/]
	CALL FSIPSO
	JRST FSICF1		;LOOP FOR NEXT UNIT


;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 triple of numbers separated by commas that specify the channel,
 controller, and unit upon which the appropriate pack is mounted.  The
 following is a list of valid channel, controller, and unit numbers:
/
;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/ CKU NUMBER
;		P4/ SDBUDB POINTER
;		P5/ STRTAB POINTER


CPY1:	TDZA T4,T4		;INDICATE COPYING PRIMARY TO SECONDARY
CPY2:	SETOM T4		;INDICATE COPYING SECONDARY TO PRIMARY
	ASUBR <CPBFLG,CPBVIR,CPBPHY,CPBDIR>	;SAVE ARGUMENTS
	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 CKU NUMBERS
	MOVE T2,CPBVIR		;GET VIRTUAL ADDRESS OF BAT BLOCKS
	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 CKU NUMBERS 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 CKU 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 THE CKU NUMBERS FOR A PACK (THE CHANNEL, CONTROLLER,
;AND UNIT NUMBERS OF THE PACK).
;ACCEPTS:	P4/ SDBUDB INDEX   (FOR CALL TO FNDCHN)
;OR:		T3/ UDB   (FOR CALL TO FNDCH1)
;RETURNS:	T1/ CKU NUMBERS
;DESTROYS T2-T4

FNDCHN:	HRRZ T3,0(P4)		;GET UDB
FNDCH1::SAVEP			;PROTECT SOME ACS
	HRRZ P1,UDBCDB(T3)	;SET UP POINTERS
	HRRZ P2,UDBKDB(T3)	;AS THEY NORMALLY ARE
	MOVE P3,T3		;FOR CALL
	CALL FNDCKU		;GET THE PROPER NUMBERS
	CALLRET CKUPAK		;PACK THEM INTO ONE AC AND RETURN

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 CKU 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 <MKBCKU,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,MKBCKU		; GET CHAN, CTRL, AND UNIT NUMBERS
	MOVE T2,MKBVIR		;GET VIRTUAL CORE ADDRESS OF BLOCKS
	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/ UDB OF A DISK UNIT OF THE STRUCTURE
;	    T2/ # OF UNITS IN STRUCTURE
;	    T3/	# OF PAGES FOR SWAPPING ON STR
;		CALL CHKSWP
;RETURNS: +1	 FAILED, # OF PAGES SPECIFIED IS INVALID
;	  +2	SUCCESS, VALID # OF PAGES SPECIFIED

CHKSWP::JUMPE T3,RSKP		;RETURN SUCCESS IF NOTHING TO ALLOCATE
	EXCH T1,T3		;SWITCH ARGUMENTS
	MOVX T4,US.DSK		;GET FLAG READY
	SKIPLE T1		;POSITIVE NUMBER OF PAGES FOR SWAPPING?
	TDNN T4,UDBSTS(T3)	;AND THIS IS A DISK?
	 RETBAD (MSTX25)	;NO, ERROR
	MOVE T3,UDBSIZ(T3)	;GET DISK SIZE POINTER
	CALL CMPSWP		;COMPUTE # OF PAGES FOR SWAPPING ON THIS UNIT
	MOVE T2,CYLUNT(T3)	;GET # OF CYLINDERS ON THIS UNIT
	IMUL T2,PAGCYL(T3)	;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
;	    T3/ ADDRESS OF DISK SIZE TABLE FOR THIS STRUCTURE
;		CALL CMPSWP
;RETURNS: +1 ALWAYS, T1/ # OF PAGES FOR SWAPPING ON THIS UNIT
;PRESERVES T3

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(T3)	;ROUND TO EVEN NUMBER OF CYLINDERS
	SUBI T1,1
	IDIV T1,PAGCYL(T3)
	IMUL T1,PAGCYL(T3)
	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:   T1/ STRING POINTER TO STORAGE
;	    T2/	NUMBER TO TYPE
;	    T3/	RADIX
;	CALL FSINST
;RETURNS +1:	ALWAYS, UPDATED STRING POINTER IN T1


FSINST:	MOVE T4,T3		;SAVE RADIX
	JUMPGE T2,FSINS1	;SKIP ON IF NUMBER IS POSITIVE
	MOVEI T3,"-"		;IT'S NEGATIVE, GET MINUS SIGN
	IDPB T3,T1		;STORE IN THE STRING
	MOVM T2,T2		;AND MAKE NUMBER POSITIVE
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
	MOVE T3,FSIASR		;GET ADDRESS OF ROUTINE FOR ANSWER
	CALL (T3)		;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:	CAIL T1,140		;LOWER CASE?
	SUBI T1,40		;YES, UPPERCASE IT BEFORE THE SIXBIT CONVERSION
	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 A SIGNED 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


FSIOCT:	SKIPA T1,[^D8]		;GET OCTAL RADIX
FSIDEC:	MOVEI T1,^D10		;OR DECIMAL RADIX
	STKVAR <FSIOCN,FSIOCR,FSIOCC,FSIOCS>	;ALLOCATE VARIABLES
	MOVEM T1,FSIOCR		;REMEMBER RADIX

FSIOC0:	SETZM FSIOCN		;INITIALIZE THE ANSWER
	SETZM FSIOCC		;INITIALIZE COUNT OF DIGITS SEEN
	SETZM FSIOCS		;INITIALIZE SIGN OF NUMBER TO BE POSITIVE
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, NULL INPUT ISN'T LEGAL
		MOVE T1,FSIOCN	;GET NUMBER TYPED
		SKIPE FSIOCS	;MINUS SIGN USED?
		MOVNS T1	;YES, NEGATE THE NUMBER
		RETSKP]		;AND RETURN
	CAIN T1,"-"		;MINUS SIGN?
	JRST [	SKIPN FSIOCS	;ALREADY TYPED A MINUS SIGN?
		SKIPE FSIOCC	;OR ALREADY TYPED DIGITS?
		JRST FSIOCE	;YES, BAD NUMBER
		SETOM FSIOCS	;REMEMBER TO NEGATE ANSWER
		JRST FSIOC1]	;AND CONTINUE
	SUBI T1,"0"		;SHOULD BE A DIGIT NOW, CONVERT FROM ASCIZ
	SKIPL T1		;TOO SMALL TO BE A DIGIT?
	CAML T1,FSIOCR		;OR TOO LARGE TO BE A DIGIT?
	JRST FSIOCE		;YES, COMPLAIN
	MOVE T2,FSIOCR		;GET RADIX
	IMULM T2,FSIOCN		;MULTIPLY PREVIOUS RESULT BY RADIX
	ADDM T1,FSIOCN		;ADD IN NEW DIGIT
	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 number, 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