;<134-TENEX>DSK.MAC;6     6-NOV-75 12:02:54    EDIT BY OPERATOR
;EXTERN BUGNTE
;<134-TENEX>DSK.MAC;4    14-MAR-75 14:33:30    EDIT BY CLEMENTS
;NAME CHANGE DO DSK FROM MDSK
;<134-TENEX>MDSK.MAC;3    14-MAR-75 13:45:23    EDIT BY CLEMENTS
; ADD MISSING CLOSE-PAREN IN BUGHLT AT DSKA8+6
;<133-TENEX>MDSK.MAC;2    20-NOV-74 16:23:36    EDIT BY CLEMENTS
;<ALLEN>DSK.MAC;9    21-OCT-74 17:25:36    EDIT BY ALLEN
; CALL SMDS0 AT WRMON SO RLRMON GOES TO CORRECT DRIVE
;<ALLEN>DSK.MAC;8    19-OCT-74 17:15:20    EDIT BY ALLEN
;  BUG FIX IN DEDSK
;<ALLEN>DSK.MAC;7    17-OCT-74 11:23:09    EDIT BY ALLEN
;<ALLEN>DSK.MAC;6    17-OCT-74 10:37:40    EDIT BY ALLEN
;<ALLEN>DSK.MAC;4     6-SEP-74 14:09:54    EDIT BY ALLEN
;<ALLEN>DSK.MAC;3    26-AUG-74 11:45:34    EDIT BY ALLEN
;<TENEX-132>DSK.MAC;37    20-MAY-74 12:34:06    EDIT BY TOMLINSON
; ADDED VERSION AND PROTECTION TO BTNAM
;<TENEX-132>DSK.MAC;36    17-APR-74 21:56:25	EDIT BY ALLEN
;<TENEX-132>DSK.MAC;35     4-APR-74 11:15:00	EDIT BY TOMLINSON
;<TENEX-132>DSK.MAC;34     3-APR-74 21:27:49	EDIT BY TOMLINSON
; ADDED DSKCV JSYS TO CONVERT DISC ADDRESS FROM AND TO VIRTUAL
;<TENEX-132>DSK.MAC;33     9-NOV-73 19:49:20	EDIT BY CLEMENTS
;<TENEX-132>DSK.MAC;32    27-JUN-73 20:11:40	EDIT BY CLEMENTS
;<TENEX-132>DSK.MAC;31    13-JUN-73 21:03:15	EDIT BY CLEMENTS
;<TENEX-132>DSK.MAC;30     6-MAR-73 18:15:34	EDIT BY CLEMENTS
;<TENEX-131>DSK.MAC;29    10-JAN-73 11:11:23	EDIT BY TOMLINSON
; CHANGED GDSKC TO USE DSKFRC, SPED UP DSKSP
;<TENEX-130>DSK.MAC;31    20-DEC-72 13:50:14	EDIT BY TOMLINSON
;<TENEX-130>DSK.MAC;30    20-DEC-72 11:33:21	EDIT BY TOMLINSON
;<TENEX-130>DSK.MAC;29    20-DEC-72 10:28:16	EDIT BY TOMLINSON
;<TENEX-130>DSK.MAC;28    20-DEC-72 10:18:14	EDIT BY TOMLINSON
; ADDED HOME BLOCK ASSIGNER (TEMPORARY IN PREP FOR MOUNT PACKS)
;<TENEX-130>DSK.MAC;27    20-DEC-72 09:48:13	EDIT BY TOMLINSON
; MODIFIED DSKASN TO SPEED SEARCH AND RANDOMIZE FREE CHOICE START
;<TENEX-130>DSK.MAC;26    11-DEC-72 15:13:42	EDIT BY TOMLINSON
;<TENEX-130>DSK.MAC;25     4-DEC-72 23:30:56	EDIT BY TOMLINSON
; ADDED CONSTANTS CONTAINING DSKSMA AND DSKRMA
;<TENEX-130>DSK.MAC;24     4-DEC-72 12:19:04	EDIT BY TOMLINSON
;<TENEX-130>DSK.MAC;23     4-DEC-72 11:15:30	EDIT BY TOMLINSON
; CHANGED NAME OF RLRMON.SAV TO RLRMON.(SYSTEM)
;<TENEX-130>DSK.MAC;22    27-NOV-72 17:38:00	EDIT BY TOMLINSON
;<TENEX-130>DSK.MAC;21    27-NOV-72 17:26:34	EDIT BY TOMLINSON
;<TENEX-130>DSK.MAC;20    20-NOV-72 16:58:52	EDIT BY WALLACE
;<TENEX-130>DSK.MAC;19    20-NOV-72 15:04:29	EDIT BY TOMLINSON
;<TENEX-130>DSK.MAC;18    18-NOV-72 16:13:29	EDIT BY WALLACE
;<TENEX-130>DSK.MAC;17    10-NOV-72 12:49:50	EDIT BY TOMLINSON
; ADDED INTERNS
;<TENEX-130>DSK.MAC;16     9-NOV-72 20:12:55	EDIT BY TOMLINSON
;<TENEX-130>DSK.MAC;15     9-NOV-72 20:07:52	EDIT BY TOMLINSON
; ADDED EXTERNS
;<TENEX-130>DSK.MAC;14     9-NOV-72 19:32:26	EDIT BY TOMLINSON
; ISOLATING INTO SEPARATE ASSEMBLY -- TITLE ADDED
;<TENEXDLM>DSK.MAC;13    22-SEP-72 15:17:13	EDIT BY MURPHY
;<TENEXDLM>DSK.MAC;12    21-SEP-72 11:32:23	EDIT BY MURPHY

	SEARCH	PROLOG
	TITLE	DSK

;DEVICE INDEPENDENT DISK RELATED STUFF - D. MURPHY

; LINKAGE TO LDINIT (VERSION NUMBER STUFF)

EXTERN	SVNUM

; LINKAGE TO SWPMON

EXTERN	GETSMF,SWCEND,WHEELX

; LINKAGE TO PISRV

EXTERN	BUGHLT,BUGNTE,BUGCHK,MENTR,MRETN,TODCLK

; LINKAGE TO DRUM

EXTERN	ASDRMS,DASDRM,DRMASN,DRMINI,DRMIO,DRMSEC,DRUMP

; LINKAGE TO PAGEM

EXTERN	SWPDON,MLKPG,MULKPG

; MISCELLANEOUS

EXTERN	BHC,BITS,CAPENB,PWRDWN

INTERN	WRSWM,NDSKEW,DSKSMA,NSECPG,DSKRML,DSKSML
	INTERN SMDSKA,RLRMON,WRMON
	INTERN DSKASN,DEDSK,DSKASA,DSKBTI,MAPBTF,SETBTF,DSKRBS
	INTERN .GDSKC,DSKSP,.DSKOP,CHKBT
	EXTERN SWPCOR

; STORAGE

GS DSKFRC,1		; DISK FREE SPACE COUNTER
IFG NPACKS-1,<GS ASNDRV,1>	; NEXT DRIVE TO USE FOR FREE CHOICE

MXASCH==30		; MAX WIDTH OF DSKASN SEARCH FOR MINFP TRACKS
DSKABT==1B14		;BITS IOR'D TO LH OF DISK ADDRESS
DSKMSK==777774		;BITS NOT USED IN LH OF DISK ADDRESS


;ROUTINES TO SAVE AND GET MON ON DISK

;WRITE RES MON ON DISK

WRMON:	CALL SMDS0		;BUILD TABLE OF ADDRESSES FOR RLRMON

	MOVN 10,SWPCOR
	MOVSI 10,1(10)
	MOVEI 11,RLRCA		;FIRST CORE LOC
WRMN1:	CAIGE 11,RLRMA+1000	;SKIP OVER PLACE WHERE RELOAD CODE LIVES
	CAIGE 11,RLRMA
	CAIA
	ADDI 11,1000
	MOVEI 1,0(10)
	IMULI 1,NSECPG
	ADD 1,DSKRML		;COMPUTE ADDRESS FOR THIS PAGE
	CALL CVDSK		;CONVERT TO HARDWARE FORMAT
	MOVE 2,[1B14+1000]	;WRITE ONE PAGE
	MOVEI 3,0(11)
	MOVEI 4,0(3)
	ANDI 4,777
	SUBI 2,0(4)		;ADJUST WORD COUNT FOR PARTIAL PAGE
	DSKOP
	ANDCMI 11,777		;BUMP CORE ADDRESS TO NEXT PAGE
	ADDI 11,1000
	AOBJN 10,WRMN1
	RET

;BUILD TABLE OF HARDWARE FORMAT ADDRESSES - CALLED FROM POSTLD

SMDSKA:	PUSHJ P,SMDS0
	MOVE 1,[XWD RLMX0,RLRMA]
	BLT 1,RLRMA+777		;MOVE RELOAD ROUTINE TO RUN LOCATION
	MOVEI 1,400000
	MOVE 2,[JRST MNBOOT]
	SEVEC			;ENTRY VECTOR FOR RELOAD ROUTINE
	MOVE 1,SVNUM
	HRLI 1,(1B0+1B17)	; FOR OUTPUT AND SHORT FORM STRING
	HRROI 2,[SYSNAM(<ASCIZ \RLRMON.>,<\>)]
	GTJFN
	0
	HRLI 1,400000
	MOVE 2,[XWD RLRMSZ,RLRMA] ;TENDMP WON'T LOAD 1 BLOCK FILE
	SAVE			;MAKE SAVE FILE OF RELOAD ROUTINE
	RET

; BUILD TABLE OF DISC ADDRESSES (CALLED FROM WRMON AND AT POSTLD)

SMDS0:
	MOVSI 10,-PPRMPG
	MOVE 11,DSKRML	;LINEAR ADDRESS OF MON STORAGE AREA
SMDS1:	MOVE 1,11
	CALL CVDSK		;CONVERT TO HARDWARE FORMAT
	MOVEM 1,RLMX0(10)	;BUILD TABLE
	ADDI 11,NSECPG
	AOBJN 10,SMDS1
	RET

;PUT SWP MON ON DISK

WRSWM:	MOVEI 7,SWPMP0
	MOVE 10,DSKSML
DSWM1:	NOSKED
	MOVE 1,10		;DISK ADDRESS
	TLO 1,(1B0)		;FLAG LINEAR ADDRESS
	MOVE 2,[1B14+1000]	;WRITE A PAGE
	MOVEI 3,0(7)		;MMAP PAGE NUMBER
	LSH 3,^D9
	DSKOP
	ADDI 10,NSECPG		;NEXT DISK ADDRESS
	OKSKED
	CAMGE 7,SWCEND
	AOJA 7,DSWM1
	RET

;ASSIGN PAGE ON DISK
;IF AC1=0, ASSIGN FROM TRACK WITH .GE. NMINFP FREE PAGES
;OTHERWISE, TAKE AC1 AS DISK ADDRESS AND ASSIGN FROM SAME TRACK
;  IF NOT FULL, OR FROM NEAREST TRACK WITH .GE. NMINFP FREE PAGES
;IN EITHER CASE, IF NO TRACK HAS .GE. NMINFP FREE PAGES, THE TRACK
;  WITH THE MAX NUMBER OF FREE PAGES WILL BE USED

DSKASN:	SKIPN DISKP		;DISK ON SYSTEM?
	JRST [	CALL DRMASN	;NO, GET A DRUM ADDRESS
		RET		;WASN'T ONE
		TLO 1,(DSKABT)	;MAKE IT LOOK LIKE A DISK ADDRESS
		AOS 0(P)
		RET]
	CALL DSKLBT		;LOCK BIT TABLE AND WRITE-ENABLE IT
	JUMPE 1,DSKA1		;FREE CHOICE
	TLZ 1,DSKMSK		;FLUSH GARBAGE BITS
	IDIVI 1,NSECTK		;SEPARATE INTO TRACK AND SECTOR
	CAIGE 1,HITRK		;REASONABLE TRACK?
	CAIGE 1,LOTRK
	JRST DSKA1		;NO, USE FREE CHOICE ALGORITHM
	MOVE 3,1		;MAKE SURE REQUESTED TRACK
	IDIVI 3,NTKUN		;NOT IN PSEUDO DRUM AREA
	CAIL 4,SWPTK
	CAIL 4,SWPTKH
	CAIA			;TRACK IS OKAY
	 JRST DSKLEV		;NO GOOD, RETURN
	MOVEI 6,1		;IN CASE REQUESTED TRACK FULL
	SKIPN DSKFCT(1)		;ANY PAGES FREE ON REQUESTED TRACK?
	JRST DSKB1		;SORRY
DSKA9:	SOS DSKFCT(1)		;ASSIGN PAGE THIS TRACK, REDUCE COUNT
	SOS DSKFRC		; REDUCE TOTAL
	PUSH P,1		;SAVE TRACK NUMBER
	IMULI 1,NBWTK		;COMPUTE ADDRESS OF START OF BITS
	SETZ 2,
DSKA2:	SKIPE 3,DSKBTB(1)	;ANY FREE BLOCKS THIS WORD?
	JRST DSKA3		;YES
	ADDI 2,^D36		;THAT'S 36 PAGES
	CAIL 2,NPGTK		;LOOKED AT BITS FOR ALL PAGES?
	BUG(HLT,<DSK BIT TABLE FOULED, CAN'T FIND FREE PAGE ON TRACK WITH NON-0 COUNT>)
	AOJA 1,DSKA2		;THERE MUST BE ONE THERE

;DSKASN...

DSKA3:	JFFO 3,.+1		;FIND FIRST FREE BLOCK
	MOVE 3,BITS(4)		;MAKE IT NO LONGER FREE
	ANDCAM 3,DSKBTB(1)
	ADDI 2,0(4)		;PAGE NUMBER WITHIN THIS TRACK
	IMULI 2,NSECPG		;CONVERT TO SECTOR NUMBER
	POP P,1			;RECOVER TRACK NUMBER
	IMULI 1,NSECTK		;COMPUTE LINEAR ADDRESS
	ADD 1,2
	TLO 1,(DSKABT)		;INDICATE DISK ADDRESS, NEWLY ASSIGNED
DSKLVD:	SETZM NXTDMP		;REQUEST SWAP TO DISK
DSKLV1:	AOS 0(P)		;SKIP RETURN
DSKLEV:	PUSH P,1
	PUSH P,2
	PUSH P,7
	MOVSI 1,WRITEB		;CLEAR WRITE BIT ON BITTBL PAGES
	MOVEI 7,DSKFCT
DSKUB1:	MOVEI 2,0(7)
	LSH 2,-^D9		;PAGE NUMBER
	ANDCAM 1,MMAP(2)	;CLEAR WRITE BIT IN MON MAP
	ADDI 7,1000		;NEXT PAGE
	CAIGE 7,DSKBTB+NTRACK*NBWTK
	JRST DSKUB1
	POP P,7
	POP P,2
	POP P,1
	SETOM DSKBLK
	OKSKED
	RET

;THE SEARCH FOR THE BEST TRACK

DSKA1:	IFG NPACKS-1,<		; IF MORE THAN ONE POSITIONER
	AOS 1,ASNDRV		; CYCLE THRU THEM
	IDIVI 1,NPACKS
	IMULI 2,NTKUN		; TRACK 0 OF THE DESIRED POSITIONER
	MOVEI 1,NTKUN/2(2)	; MIDDLE TRACK
>
	IFLE NPACKS-1,<
	MOVEI 1,<HITRK-LOTRK>/2+LOTRK	;START IN MIDDLE FOR FREE CHOICE
>	MOVEI 6,NMINFP		;MIN FREE
DSKB1:	SETZB 3,5
	PUSH P,1		;SAVE ORIGINAL TRACK
DSKA6:	CAML 5,DSKFCT(1)	;THIS TRACK HAVE MORE FREE THAN CURRENT?
	JRST DSKA4		;NO
	MOVE 5,DSKFCT(1)	;GET NEW MAX
	MOVEI 4,0(1)		;REMEMBER WHAT TRACK HAD IT
	CAIL 5,0(6)		;LARGE ENOUGH TO STOP?
	JRST DSKA8		;YES
DSKA4:	MOVE 1,0(P)		;KEEP LOOKING, GET ORIGINAL TRACK NO.
	MOVN 3,3		;MAKE INCREMENT IN OPPOSITE DIRECTION
	JUMPGE 3,DSKA5		;FORWARD AGAIN?
DSKA7:	ADD 1,3			;COMPUTE NEXT TRACK TO LOOK AT
	CAIGE 1,HITRK		;WITHIN USABLE RANGE?
	CAIGE 1,LOTRK
	JRST DSKA4		;NO, RECOMPUTE
	JRST DSKA6		;GO LOOK

DSKA5:	CAIL 3,MXASCH		; SEARCHED FAR ENOUGH?
	 JUMPG 5,DSKA8		; YES, IF WE HAVE ANYTHING, KEEP IT
	CAIGE 3,NTRACK		; OR LOOKED AT ALL TRACKS?
	AOJA 3,DSKA7		;NO, GO LOOK AT NEXT PAIR
	JUMPE 5,DSKAA1		;DISK ENTIRELY FULL!!
DSKA8:	POP P,1			;CLEAR STACK
	MOVEI 1,0(4)		;BEST TRACK FOUND
	IDIVI 4,NTKUN		;MAKE SURE SELECTED TRACK NOT IN
	CAIL 5,SWPTK		;PSEUDO DRUM AREA
	CAIL 5,SWPTKH
	JRST DSKA9		;GO ASSIGN FROM IT
	BUG (HLT,<ATTEMPT TO ASSIGN FILE PAGE IN PSEUDO-DRUM AREA>)

;LOCK AND WRITE-ENABLE BIT TABLE
;INVOKED ON ENTRY TO ANY ASSIGNMENT OR DEASSIGNMENT ROUTINE

DSKLBT:	NOSKED
	AOSE DSKBLK		;TRY TO LOCK TABLE
	BUG(CHK,<DISK BIT TABLE ALREADY LOCKED AT DSKLBT>)
	PUSH P,1
	PUSH P,2
	PUSH P,7
	MOVSI 1,WRITEB
	MOVEI 7,DSKFCT
DSKLB1:	MOVEI 2,0(7)
	LSH 2,-^D9
	IORM 1,MMAP(2)		;PUT ON WRITE BIT IN MON MAP
	ADDI 7,1000
	CAIGE 7,DSKBTB+NTRACK*NBWTK
	JRST DSKLB1
	POP P,7
	POP P,2
	POP P,1
	RET

;ASSIGN SPECIFIC DISK ADDRESS

DSKASA:	PUSH P,1		;SAVE IT
	CALL DSKGX		;GET INDICES, ETC.
	JRST DSKAA1		;BAD ADDRESS
	TDNN 3,DSKBTB(1)	;PAGE FREE?
	JRST DSKAA1		;SORRY
	SOS DSKFCT(2)
	SOS DSKFRC
	ANDCAM 3,DSKBTB(1)	;ASSIGN IT
	POP P,1
	JRST DSKLVD		;RETURN GOOD

DSKAA1:	POP P,1
	JRST DSKLEV		;RETURN NO-SKIP

;DEASSIGN DISK ADDRESS

DEDSK:	SKIPN DISKP		;DISK ON SYSTEM?
	JRST DASDRM		;NO, MUST BE DRUM
	CALL DSKLBT		;LOCK AND WRITE ENABLE BIT TABLE
	TLZ 1,DSKMSK		;GET RID OF RANDOM BITS
	IDIVI 1,NSECTK		;CONVERT TO LINEAR TRACK
	PUSH P,4		;SAVE AC4
	MOVE 3,1
	IDIVI 3,NTKUN		;PACK-RELATIVE TRACK IN AC4
	MOVE 3,4		;GET IT TO AC3
	POP P,4			;AND RESTORE AC4
	CAIL 3,SWPTK		;WITHIN PSEUDO DRUM AREA?
	CAIL 3,SWPTKH
	 CAIA			;NO
	JRST DEDSK1		;YES, DON'T DO IT.
	CALL DSKGX2		;GET INDICES, ETC.
	JRST DEDSK1		;BAD ADDRESS
	TDNE 3,DSKBTB(1)	;PAGE ASSIGNED?
	JRST DEDSK1		;NO
	IORM 3,DSKBTB(1)	;UNASSIGN IT
	AOS DSKFCT(2)
	AOS DSKFRC
	SETZM NXTDMP
	JRST DSKLEV		;RETURN

DEDSK1:	BUG(CHK,<ATTEMPT TO DEASSIGN BAD OR UNASSIGNED DISK ADDRESS>)
	JRST DSKLEV

;COMPUTE INDEX INTO BIT TABLE

DSKGX:	CALL DSKLBT		;LOCK AND WRITE-ENABLE BIT TABLE
	TLZ 1,DSKMSK		;FLUSH RANDOM BITS
	IDIVI 1,NSECTK		;SEPARATE INTO TRACK AND SECTOR
DSKGX2:	CAIGE 1,HITRK		;LEGAL TRACK NUMBER?
	CAIGE 1,LOTRK
	RET			;NO, RETURN NO-SKIP
	CAIL 2,NPGTK*NSECPG	;WITHIN ASSIGNABLE PORTION OF TRACK?
	RET			;NO
	PUSH P,1		;SAVE TRACK NUMBER
	IMULI 1,NBWTK		;INDEX TO FIRST WORD OF BITS
	IDIVI 2,NSECPG		;CONVERT TO PAGE NUMBER
	IDIVI 2,^D36		;GET INDEX TO BIT WORD WITHIN TRACK
	ADDI 1,0(2)
	POP P,2			;RECOVER TRACK NUMBER
	MOVE 3,BITS(3)		;GET BIT FOR THIS PAGE
	AOS 0(P)
	RET

;DISK ASSIGNMENT CONTROL JSYS

	INTERN .DSKAS

; ADR = ASSIGN
; ADR+1B0 = DEASSIGN
; ADR+1B1 = ASSIGN FREE

SWAPCD

.DSKAS:	JSYS MENTR
	MOVE 4,CAPENB		;REQUIRES WHEEL OR OPERATOR
	TRNN 4,WHEEL+OPER
	JRST WHEELX
	TLZE 1,(1B0)		;DEASSIGN?
	JRST [	CALL DEDSK	;YES
		JRST MRETN]
	MOVEI 2,DSKASA		;DO SPECIFIC ASSIGNMENT
	TLZE 1,(1B1)		;UNLESS BIT 1,
	MOVEI 2,DSKASN		;IN WHICH CASE TO FREE ASSMT
	CALL 0(2)		;DO WHICHEVER
	JRST MRETN		;BAD RETURN, NO INFORMATION
	UMOVEM 1,1		;GOOD RETURN, AND VALUE OF AC1
	AOS 0(P)
	JRST MRETN

; CONVERT DISC FROM AND TO VIRTUAL TO AND FROM HARDWARE
; ACCEPTS
;	1	; DISC ADDRESS A LA DSKOP (SIGN BIT SET FOR VIRTUAL)
;	DSKCV
;RETURNS +1	; ALWAYS. DISC ADDRESS OF OPPOSIT TYPE IN AC1

.DSKCV::JSYS MENTR
	TLZN 1,(1B0)		; HARDWARE ADDRESS?
	 JRST DSKCVH		; YES
	CALL CVDSK		; NO. CONVERT TO HARDWARE ADDRESS
	UMOVEM 1,1		; RETURN RESULT TO USER
	JRST MRETN

DSKCVH:	CALL CDSKVA		; CONVERT TO LINEAR ADDRESS
	TLO 1,(1B0)		; MARK IT AS A LINEAR ADDRESS
	UMOVEM 1,1		; RETURN RESULT TO USER
	JRST MRETN

RESCD

;READ BADSPOTS FROM FILE

DSKRBS:	MOVEI 1,101
	HRROI 2,[ASCIZ /
READ BADSPOTS FROM FILE: /]
	SETZ 3,
	SOUT
	MOVSI 1,120003
	MOVE 2,[XWD 100,101]
	GTJFN
	JRST DSKRBS
	MOVE 2,[XWD 070000,200000]
	OPENF
	JRST DSKRBS
	MOVE 16,1		;SAVE JFN
DSKRB1:	MOVEI 1,0(16)		;RECOVER JFN
	MOVEI 3,^D8
	NIN			;READ OCTAL BADSPOT H'WARE FORMAT
	JRST DSKRB3		;DIDNT GET A NUMBER
	MOVE 7,2		;SAVE THE NUMBER
DSKRB4:	BKJFN
	JRST DSKRB2		;CAN'T SEE TERMINATOR, ASSUME VALID
	BIN
	CAIN 2,"Z"-100		;CONTROL-Z?
	JRST DSKRB6		;FOR TTY MEANS MAKE LIKE EOF
	CAIN 2,15
	BIN
	CAIE 2,EOL
	CAIN 2,12
	JRST DSKRB2		;OK IF TERM WITH CR OR EOL
	MOVEI 1,EOL
	PBOUT
	JRST DSKRB1		;ANYTHING ELSE ABORTS

DSKRB2:	JUMPE 7,DSKRB1		;IF NOT NUMBER
	MOVE 1,7
	CALL CDSKVA		;CONVERT TO INTERNAL ADDRESS
	PUSH P,1
	IDIVI 1,NTKUN		;AC1=UNIT, AC2=TRACK ON UNIT
	CAIL 2,SWPTK		;IN SWAP AREA?
	CAIL 2,SWPTKH
	 CAIA			;NO
	JRST DSKRB7		;YES
	POP P,1
	CALL DSKASA		;ASSIGN IT
	JRST DSKRB5		;ALREADY ASSIGNED
	JRST DSKRB1

DSKRB3:	GTSTS
	SETZ 7,
	TLNN 2,(1B8)		;EOF?
	JRST DSKRB4		;NO
DSKRB6:	CLOSF
	JFCL
	MOVEI 1,DSKFCT
	MRPAC			;READ STATUS OF BIT TABLE PAGE
	TLNE 2,(1B10)		;PRIVATE?
	CALL SETBTF		;MAP BIT TABLE INTO FILE
	RET

DSKRB5:	MOVEI 1,101
	MOVE 2,7		;ADDRESS
	MOVEI 3,10		;IN OCTAL
	NOUT			;IS PRINTED
	BUG(CHK,<DSKRBS - BAD RETURN FROM NOUT>)
	HRROI 2,[ASCIZ / ALREADY MARKED
/]
	SETZ 3,
	SOUT
	JRST DSKRB1

DSKRB7:	SUB P,BHC+1		;ADJUST STACK POINTER
	SKIPE DRUMP		;SWAPPING ON DISK
	JRST DSKRB1		;NO, IGNORE
	IMULI 1,SWPSEC		;NUMBER OF SWAP SECTORS ON PRIOR UNITS
	SUBI 2,SWPTK		;GET TRACK RELATIVE TO THIS UNIT'S SWAP AREA
	IMULI 2,NSECTK		;CONVERT TO SECTORS
	ADD 1,2			;GET LINEAR SECTOR NUMBER IN SWAP SPACE
	IDIVI 1,NSECPG		;CONVERT TO LINEAR PAGE
	IDIVI 1,DRMSEC		;CONVERT TO BAND AND SECTOR
	LSH 1,6
	IORI 1,0(2)
	CALL ASDRMS		;ASSIGN IN DRUM BIT TABLE
	JRST DSKRB5		;ALREADY ASSIGNED
	JRST DSKRB1

;DISK USEAGE STATISTICS

DSKSP:	MOVE 3,[XWD LOTRK-HITRK,LOTRK]
	SETZ 2,			;SETUP TO EXAMINE ALL TRACKS
DSKSP1:	ADD 2,DSKFCT(3)		;FREE COUNT THIS TRACK
	AOBJN 3,DSKSP1
	MOVE 1,[NPGTK*<HITRK-LOTRK-DSKNST>]
	SUB 1,2
	RET

.GDSKC:	MOVE 2,DSKFRC		; FREE PAGES
	MOVE 1,[NPGTK*<HITRK-LOTRK-DSKNST>]
	SUB 1,2
	XCT MJRSTF

;DISK OPERATE JSYS - USER UTILITY DISK HANDLE

.DSKOP:	JSYS MENTR
	MOVE 1,CAPENB
	TRNN 1,WHEEL+OPER
	JRST WHEELX		;MUST BE WHEEL OR OPER
	NOINT
	ANDI 2,3777		;CHECK FOR CROSS OF PAGE BOUNDARY
	ADDI 2,-1(3)			;CORE ADR + WORD COUNT
	XOR 2,3
	TRNE 2,777000		;SAME PAGE?
	JRST [	MOVEI 1,4000	;NO, GIVE IPO ERROR
		UMOVEM 1,1
		JRST MRETN]
	HRRZS 1,3		;ADDRESS
	UMOVE 2,0(1)		;REF THE PAGE TO ASSIGN IT
	MOVE 2,0(P)		;GET PC WORD AT CALL
	TLNE 2,UMODF		;CHECK USER MODE BIT AT CALL
	HRLI 1,(1B0)		;CALLED FROM USER, INDICATE IN ADDRESS
	CAIGE 3,PPRMA		;RESIDENT MONITOR ADDRESS?
	JUMPGE 1,[PUSH P,[0]	;YES, FLAG NO PAGE TO UNLOCK
		LSH 1,-^D9	;PAGE NUMBER
		JRST DSKOP1]
	CALL FPTA		;GET PTN.PN
	PUSH P,1
	CALL MLKPG		;LOCK THE PAGE
DSKOP1:	MOVSI 3,(CORMB)		;CORE MODIFIED BIT
	UMOVE 2,2
	TLNN 2,(1B14)		;READ?
	IORM 3,CST0(1)		;YES, NOTE CORE CHANGED
	PUSH P,1
	UMOVE 1,1		;GET USERS ADDRESS
	TLZE 1,(1B0)		;HARDWARE ADDRESS?
	CALL CVDSK		;NO, CONVERT IT
	POP P,3
	LSH 3,^D9		;CONVERT PAGE NUMBER TO ADDRESS
	UMOVE 4,3		;USERS ADDRESS
	ANDI 4,777
	IORI 3,0(4)		;FOR STARTING NOT AT BEGNG OF PAGE
	UMOVE 2,2		;OTHER ARGS
	CALL UDSKIO
	UMOVEM 1,1		;RETURN ERROR BITS
	POP P,1			;RECOVER PTN.PN OF LOCKED PAGE
	JUMPE 1,MRETN		;RES MON IF 0
	CALL MULKPG		;UNLOCK IT
	JRST MRETN

;CHECK CONSISTENCY OF BIT TABLE

CHKBT:	CALL DSKLBT
	CALL CHKB0		; DO THE CHECK
	CALL DSKSP		; COUNT FREE TRACKS
	MOVEM 2,DSKFRC		; SAVE FOR OPENF CHECKS
	RET

CHKB0:	PUSH P,[43]		; MAX ERRORS TO PRINT
	MOVE 7,[XWD LOTRK-HITRK,LOTRK]
CHKB5:	MOVEI 6,0(7)		;TRACK
	IMULI 6,NBWTK		;COMPUTE OFFSET INTO TABLE
	MOVEI 4,NPGTK		;NUMBER PAGES PER TRACK
	SETZ 5,			;WILL COUNT FREE PAGES FOUND
CHKB2:	MOVE 1,DSKBTB(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:	CAME 5,DSKFCT(7)	;COUNT CORRECT AS REMEMBERED?
	JRST CHKB4		;NO
CHKB6:	AOBJN 7,CHKB5		;YES, LOOP OVER TRACKS
	SUB P,BHC+1		; FLUSH COUNTER
	JRST DSKLEV		;UNLOCK BIT TABLE AND RETURN

;REPORT INCONSISTENCY

CHKB4:	EXCH 5,DSKFCT(7)	;STORE NEW COUNT, GET OLD ONE
	SOSG 6,0(P)		; COUNT ERROR
	 JRST [	JUMPL 6,CHKB6	; IF NOT FIRST TIME, CONTINUE
		HRROI 1,[ASCIZ /
MORE INCONSISTENCIES
/]
		PSOUT
		JRST CHKB6]
	CALL DSKLEV		;UNLOCK BIT TABLE, ETC.
	HRROI 1,[ASCIZ /
BT INCONSISTENCY
 TRK CNT BITS
/]
	PSOUT
	MOVEI 1,101
	MOVE 3,[1B2+4B17+10]	;OCTAL NUMBERS IF 4 CHAR FIELD
	MOVEI 2,0(7)
	NOUT			;TRACK
	BUG(HLT,<CHKBT - BAD RETURN FROM NOUT>)
	MOVE 2,5
	ANDI 2,777		;IN CASE REALLY FOULED UP
	NOUT			;OLD COUNT
	BUG(HLT,<CHKBT - BAD RETURN FROM NOUT>)
	MOVE 2,DSKFCT(7)
	NOUT			;NEW COUNT
	BUG(HLT,<CHKBT - BAD RETURN FROM NOUT>)
	HRROI 1,[ASCIZ / - CORRECTED
/]
	PSOUT
	CALL DSKLBT		;RE-LOCK BIT TABLE
	JRST CHKB6		;CONTINUE SCAN

;BIT TABLE FILE LOGIC

;PUT BIT TABLE PAGES IN FILE

SETBTF:	MOVSI 1,(1B17)	;SHORT FORM
	CALL OPNBTF		;OPEN (CREATE) FILE
	PUSH P,1		;SAVE JFN
	HRLI 1,1		;INDEX FOR FDBCTL
	MOVSI 2,200400		;SET FDBPRM AND FDBUND IN BITTBL FILE
	MOVSI 3,200400		; ..
	CHFDB
	POP P,1
	MOVEI 7,DSKFCT		;ADDRESS OF FIRST PAGE
	SETZ 6,			;MAP INDEX
SETBF1:	CAIL 7,DSKBTB+NTRACK*NBWTK	;END OF BIT TABLE?
	JRST SETBF2		;YES, DONE
	MOVS 1,DBTJFN
	HRRI 1,0(6)
	CALL JFNOFN		;CONVERT TO OFN
	BUG(HLT,<SETBTF - JFNOFN ON BIT TABLE FILE FAILED>)
	MOVE 2,1
	MOVEI 1,0(7)
	CALL FPTA		;CONVERT MON ADDRESS TO PTN.PN
	MOVSI 3,RWX
	CALL SETPT		;PUT PAGE IN FILE
	ADDI 7,1000
	AOJA 6,SETBF1

SETBF2:	MOVE 1,DBTJFN
	CLOSF			;CLOSE DER FILE
	JFCL
	RET

;MAP BIT TABLE FILE INTO MON SPACE

MAPBTF:	MOVSI 1,(1B2+1B17)	;OLD FILE, SHORT FORM
	CALL OPNBTF		;OPEN THE FILE
	MOVEI 7,DSKFCT
	SETZ 6,
MAPBF1:	CAIL 7,DSKBTB+NTRACK*NBWTK
	JRST SETBF2
	MOVEI 1,0(6)		;FILE PAGE NUMBER
	HRL 1,DBTJFN
	CALL JFNOFN
	BUG(HLT,<MAPBTF - JFNOFN ON BIT TABLE FILE FAILED>)
	MOVEI 2,0(7)
	HRLI 2,READB
	CALL SETMPG
	ADDI 7,1000
	AOJA 6,MAPBF1

;OPEN BIT TABLE FILE

OPNBTF:	HRRI 1,1		;VERSION 1 ALWAYS
	HRROI 2,BTNAM
	GTJFN
	BUG(HLT,<FAILED TO GTJFN DSKBTTBL>)
	MOVEM 1,DBTJFN
	MOVEI 2,1B19+1B20+1B25	;THAWED READ AND WRITE
	OPENF
	BUG(HLT,<FAILED TO OPEN DSK BIT TABLE FILE>)
	RET

BTNAM:	ASCIZ /DSK:<SYSTEM>DSKBTTBL;1;P400000/

;INITIALIZE BIT TABLE

DSKBTI:	SKIPN DISKP		;DISK ON SYSTEM?
	RET			;NO
	MOVSI 2,-NTRACK
	MOVEI 1,NPGTK
DSKBT2:	MOVEI 3,0(2)		;GET CURRENT TRACK
	SETZM DSKFCT(2)
	IDIVI 3,NTKUN
	CAIL 4,SWPTK		;WITHIN PSEUDO DRUM AREA?
	CAIL 4,SWPTKH
	MOVEM 1,DSKFCT(2)	;NO, STORE FULL COUNT
	AOBJN 2,DSKBT2
	SETZ 2,
DSKAI1:	SETOM DSKBTB(2)		;INIT ONE TRACK OF BITS
	SUBI 1,^D36
	CAILE 1,^D36		;LAST WORD?
	AOJA 2,DSKAI1
	MOVN 1,BITS-1(1)	;LAST WORD PARTIALLY FULL
	MOVEM 1,DSKBTB+1(2)
	MOVE 1,[XWD DSKBTB,DSKBTB+NBWTK]
	BLT 1,DSKBTB+NTRACK*NBWTK-1	;REPLICATE FOR ALL TRACKS

;MARK PSEUDO DRUM TRACKS AS FULLY ASSIGNED
	MOVSI 2,-NTRACK
DSKPSE:	SKIPE DSKFCT(2)		;THIS TRACK IN PSEUDO DRUM?
	 JRST DSKNTK		;NO
	MOVEI 3,0(2)
	IMULI 3,NBWTK
	HRLI 3,-NBWTK
	SETZM DSKBTB(3)
	AOBJN 3,.-1
DSKNTK:	AOBJN 2,DSKPSE

	MOVSI 7,-NHOME
HOMASN:	PUSH P,7
	MOVE 1,HOME(7)		; GET HARDWARE ADDRESS OF HOME BLOCK
	CALL CDSKVA		; CONVERT TO LINEAR ADDRESS
	ANDCMI 1,NSECPG-1	; MASK TO PAGE BOUNDARY
	CALL DSKASA		; ASSIGN IT
	 BUG(HLT,<DSKBTI: FAILED TO ASSIGN HOME BLOCK>)
	POP P,7
	AOBJN 7,HOMASN
	RET

; THIS ASSEMBLY CONTINUES WITH DEVICE DEPENDENT DSKPAK OR DSKBRY ETC.
