;<FOONEX>DSK.MAC;14 18-Mar-81 18:05:50, Edit by MMCM
; SUMEX ERJMP/ERCAL changes
;<FOONEX>DSK.MAC;13 11-Feb-81 19:51:59, Edit by PETERS
;Fix so NTKUN*NSECTK can be larger than a half word value
;DSK:<FOONEX>DSK.MAC;12 29-Jul-80 16:34:42, Edit by FRENCH
;ADDED REDBTI  ROUTINE
;DSK:<PEFMON>DSK.MAC;11 20-Jun-80 11:37:39, Edit by FRENCH
;ADD COMMENT TO DSKOP JSYS FOR BAT LOGGING BITS
;DSK:<PEFMON>DSK.MAC;19 14-May-80 14:15:53, Edit by FRENCH
;REMOVE DSKABT TO PARAMS
;<PEFMON>DSK.MAC;18     8-May-80 17:35:46    EDIT BY FRENCH
;FIX BUG IN CHKBT - TRIED TO DO TERMINAL IO NOSKED
;DSK:<PEFMON>DSK.MAC;16 29-Apr-80 21:12:42, Edit by FRENCH
;FIX BUG IN CVADSW SWAPPING ADDRESS CALCULATION
;<PEFMON>DSK.MAC;8    18-Apr-80 18:07:39    EDIT BY FRENCH
;NOSKIP RET FOR BAD ADR AT DSKASA EVEN IF FORCING
;DSK:<PEFMON>DSK.MAC;7 15-Apr-80 17:31:31, Edit by FRENCH
;MOVED DSKMSK TO PARAMS
;DSK:<PEFWRK>DSK.MAC;4 11-Apr-80 18:11:03, Edit by FRENCH
;RETURN OF DSKRBS BUT JUST DOES SETBTF
;DSK:<PEFWRK>DSK.MAC;3  9-Apr-80 12:31:15, Edit by FRENCH
;FLUSH DISK INDICATOR BIT IN CVADSW
;DSK:<PEFWRK>DSK.MAC;2  8-Apr-80 14:38:51, Edit by FRENCH
;MAKE DSKABT INTERNAL
;DSK:<PEFWRK>DSK.MAC;4  3-Apr-80 20:03:02, Edit by FRENCH
;MOVED CVDSK AND CDSKVA FROM DSKPAK TO HERE
;MOVE CVSWAD AND CVSWAD TO HERE FROM DSKPAK.F3A
;REMOVED READ BAD SPOTS ROUTINE (DSKRBS), NEW STUFF MAKES IT OBSOLETE
;DSK:<PEFWRK>DSK.MAC;1 26-Mar-80 16:31:36, Edit by FRENCH
;LET DSKASA REUSE ASSIGNED DISK ADRS IF SIGN BIT SAYS FORCE ASSIGNMENT
;<134-TENEX>DSK.MAC;8    18-Feb-80 18:19:07    EDIT BY PETERS
; Added bug fixes from ISI
;<134-TENEX>DSK.MAC;7     2-Jul-79 16:44:26    EDIT BY PETERS
;<134-TENEX>DSK.MAC;6     9-Sep-78 18:55:53    EDIT BY PETERS
;<134-TENEX>DSK.MAC;5    27-NOV-77 19:42:08    EDIT BY PETERS
;<133-TENEX>MDSK.MAC;6    28-APR-75 09:24:33    EDIT BY UNTULIS
;<133-TENEX>MDSK.MAC;3     3-APR-75 11:25:14    EDIT BY UNTULIS
;ADD CODE FOR MULTIPLE DISK SWAPPING
;<133-TENEX>DSK.MAC;3     3-JAN-75 15:50:22    EDIT BY UNTULIS
;ADD BBN 133 DSK CODE TO OUR DSK.MAC
;<133-TENEX>DSK.MAC;39    20-NOV-74 16:20:23    EDIT BY CLEMENTS
;<133-TENEX>DSK.MAC;38    25-OCT-74 10:47:00    EDIT BY TOMLINSON
; SET FDBPRM AND FDBUND IN DSKBTTBL WHEN CREATED
;<132>DSK.MAC;8     5-DEC-74 13:44:28    EDIT BY UNTULIS
;ADD CODE TO INITIALIZE HOME BLOCKS (WRHOM)
;<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-MON>DSK.MAC;2     3-DEC-73 19:03:18	EDIT BY LYNCH
; CHANGED NUMBER OF TIMES TO PRINTOUT BT INCONSISTECIES TO 5
;<SRIMON131>DSK.MAC;5    13-AUG-73  3:43:58	EDIT BY KREMERS
;<SRIMON131>DSK.MAC;4     7-AUG-73  1:58:42	EDIT BY KREMERS
;<SRIMON131>DSK.MAC;3	10 JULY 73	EDIT BY KREMERS

	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,BUGCHK,MENTR,MRETN,TODCLK,MRTNE1

; LINKAGE TO DRUM

EXTERN	DASDRM,DRMASN,DRMINI,DRMIO,DRMSEC

; LINKAGE TO PAGEM

EXTERN	SWPDON,MLKPG,MULKPG


; MISCELLANEOUS

EXTERN	BHC,BITS,CAPENB,PWRDWN

INTERN	NDSKEW,NSECPG,DSKABT,DSKRBS
INTERN DSKASN,DEDSK,DSKASA,DSKBTI,MAPBTF,SETBTF
INTERN .GDSKC,.CADSK,DSKSP,.DSKOP,CHKBT,CVSWAD,CVADSW
INTERN CVDSK,CDSKVA
INTERN REDBTI

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


;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:	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
;1B0 ON MEANS FORCE ASSIGNMENT EVEN IF ALREADY ASSIGNED (REUSE IF NECESSARY)

DSKASA:	PUSH P,1		;SAVE IT
	CALL DSKGX
	JRST [POP P,1		;BAD ADR
		JRST DSKLEV]
	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
	TLNN 1,(1B0)		;FORCE THE ASSIGNMENT?
	 JRST DSKLEV		;NO-RETURN NO SKIP
	JRST DSKLVD		;YES-ITS ASSIGNED, ALLOW FOR REUSE

;DEASSIGN DISK ADDRESS

DEDSK:	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 MRTNE1		;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

;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

;ROUTINE TO CONVERT ABS DISK ADR INTO VIRTUAL ADR.		***SRI-AIC***
;ABS INPUT FORMAT IS AS FOLLOWS;  DRIVE,,TRACK (8 BITS)HEAD(5) ***SRI-AIC***
;SECTOR(5)							***SRI-AIC***
.CADSK:	JSYS MENTR	;SLOW CODE ENTRY			***SRI-AIC***
	CALL CDSKVA	;CONVERT				***SRI-AIC***
	UMOVEM 1,1	;RETURN TO USER				***SRI-AIC***
	JRST MRETN	;RETURN					***SRI-AIC***

;DISK OPERATE JSYS - USER UTILITY DISK HANDLE
;AC2/ 1B0 => LOG BAD SPOTS IN BAT BLOCKS, 1B1 => LOG EVEN ASSIGNED SPOTS IN BAT

.DSKOP:	JSYS MENTR
	MOVE 1,CAPENB
	TRNN 1,WHEEL+OPER
	JRST WHEELX		;MUST BE WHEEL OR OPERATOR
DSKOP2:	NOINT							;***SRI-AIC***
	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 MRTNE1]
	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
DSKOP4:	UMOVEM 1,1		;RETURN ERROR BITS		***SRI-AIC***
	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,[5]		; 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
		CALL DSKLEV	; ALLOW DISMS
		HRROI 1,[ASCIZ /
MORE INCONSISTENCIES
/]
		PSOUT
		JRST CHKB7]
	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
CHKB7:	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 OF FDBCTL
	MOVSI 2,200400
	MOVSI 3,200400
	CHFDB			;SET FDBPRM AND FDBUND BIT IN THE FILE
	POP P,1			;RESTORE JFN
	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:	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
	RET


DSKRBS:	HRROI 1,[ASCIZ/
YOU AIN'T GOT NO BAD SPOTS IF YOU GOTS BAT BLOCKS!
/]
	PSOUT
	MOVEI 1,DSKFCT
	MRPAC			;READ STATUS OF BIT TABLE PAGE
	TLNE 2,(1B10)		;PRIVATE?
	CALL SETBTF		;MAP BIT TABLE INTO FILE
	RET


;CALLABLE BY A PROCESS TO REINIT THE DISK BITTABLE

REDBTI:	CALL DSKLBT		;LOCK IT-GO NOSKED
	CALL DSKBTI		;CLEAN IT UP
	CALL DSKSP		;GET DISK STATS FROM CLEAN BITTABLE
	MOVEM 2,DSKFRC		;NEW FREE COUNT
	SETZM NXTDMP		;GET OUT TO DISK QUICKLY
	CALL DSKLEV		;UNLOCK AND GO OKSKED
	RET

;HERE WE CONVERT A LINEAR SOFTWARE DISK ADDRESS PASSED TO US IN AC A
;TO A PHYSICAL HARDWARE DISK ADDRESS WHICH WE RETURN IN AC A

CVDSK:	TLZ A,DSKMSK		;FLUSH EXTRA BITS
	IDIV A,[NTKUN*NSECTK]	;ISOLATE UNIT IN AC A
	IDIVI B,NSECTK		;ISOLATE CYLINDER IN AC B
	IDIVI C,NSECS		;ISOLATE SURFACE IN AC C AND SECTOR IN AC D
	LSH A,NCYLBT+NSRFBT+NSECBT	;SHIFT AC A TO HARDWARE UNIT FIELD
	LSH B,NSRFBT+NSECBT	;SHIFT AC B TO HARDWARE CYLINDER FIELD
	LSH C,NSECBT		;SHIFT AC C TO HARDWARE SURFACE FILED
	IOR A,B			;MERGE CYLINDER WITH UNIT FIELDS
	IOR A,C			;MERGE SURFACE FIELD
	IOR A,D			;MERGE SECTOR FIELD
	RET


;HERE WE CONVERT A HARDWARE DISK ADDRESS PASSED TO US IN AC A
;TO A LINEAR SOFTWARE DISK ADDRESS WHICH WE RETURN IN AC A

CDSKVA:	LSHC A,-<NCYLBT+NSRFBT+NSECBT>	;ISOLATE UNIT IN AC A
	LSHC B,-<^D36-NCYLBT>	;ISOLATE CYLINDER IN AC B
	LSHC C,-<^D36-NSRFBT>	;ISOLATE SURVACE IN AC C
	LSH D,-<^D36-NSECBT>	;ISOLATE SECTOR IN AC D
	IMUL A,[NTKUN*NSECTK]	;UNIT TIMES NUMBER OF SECTORS PER UNIT
	IMULI B,NSECTK		;CYLINDER TIMES NUMBER OF SECTORS PER CYLINDER
	IMULI C,NSECS		;SURFACE TIMES NUMBER OF SECTORS PER SURFACE
	ADD A,B			;MERGE UNIT AND CYLINDER COMPONENTS
	ADD A,C			;MERGE SURFACE COMPONENT
	ADD A,D			;MERGE SECTOR COMPONENT
	RET			;ALL OF WHICH EQUALS LINEAR SECTOR ADDRESS!!


;HERE WE CONVERT A SWAP ADDRESS PASSED TO US IN AC A
;TO A LINEAR DISK ADDRESS WHICH WE RETURN IN AC A

CVSWAD:	HRRZS A			;FLUSH NON-ADDRESS BITS
	IDIVI A,100		;ISOLATE "TRACK" IN AC A, "SECTOR" IN AC B
	IMULI A,DRMSEC		;GET "TRACK" COMPONENT OF SWAP PAGE NUMBER
	ADD A,B			;MERGE "SECTOR" COMPONENT OF SWAP PAGE NUMBER
	IDIVI A,NPACKS		;UNIT SWAP PAGE TO A, UNIT TO B
	IMULI A,NSECPG		;CONVERT UNIT SWAP PAGE TO UNIT SWAP SECTOR
	IMUL B,[NTKUN*NSECTK]	;COMPUTE SECTORS COMPONENT PER UNIT
	ADDI B,SWPTK*NSECTK	;PLUS SECTORS OF SWAP AREA OFFSET
	ADDB A,B		;MERGE COMPONENTS, PREPARE RANGE CHECK
	IDIVI B,NSECTK		;EXTRACT LINEAR CYLINDER FROM COMPUTED ADDRESS
	IDIVI B,NTKUN		;NOW EXTRACT PHYSICAL CYLINDER
	CAIL C,SWPTK		;MAKE SURE THIS CYLINDER IS NOT IN THE
	CAIL C,SWPTKH		;FILES AREA, ELSE DIE...
	BUG(HLT,<SWAP ADDRESS IN FILES AREA>)
	RET

;HERE WE CONVERT A LINEAR DISK ADR TO A DRUM SWAPPING ADR
;ACCEPTS LINEAR ADR IN 1
;RETURNS DRUM ADR IN 1

CVADSW:	TLZ 1,DSKMSK		;FLUSH EXTRA BITS
	MOVE 2,1		;DON'T CLOBBER 1
	IDIVI 2,NSECTK		;2/ TRACK, 3/ SECTOR ON TRACK
	IDIVI 2,NTKUN		;2/ UNIT, 3/ TRACK ON UNIT
	CAIL 3,SWPTK		;MAKE SURE IT IS IN SWAPPING AREA
	CAIL 3,SWPTKH
	 BUG (HLT,<CVADSW: TRIED TO CONVERT NON-SWAP DISK ADR TO DRUM ADR>)
	IDIV 1,[NTKUN*NSECTK]	;1/ UNIT, 2/ SEC ON UNIT
	SUBI 2,SWPTK*NSECTK	;2/ SWAP SEC ON UNIT
	IMULI 2,NPACKS		;OBVIOUS
	ADD 1,2			;1/ SWAP SECTOR
	IDIVI 1,NSECPG		;CONVERT TO LINEAR PAGE
	IDIVI 1,DRMSEC		;CONVERT TO BAND AND SECTOR
	LSH 1,6
	IORI 1,0(2)
	RET




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