;							>>B/S<<
;	DIRECTORY FUNCTIONS
;
; 02.07 KRS 04/25/80 BIG DIR - DISK BIT MAP
; 02.10 krs 06/21/80 big/small
; 02.14 KRS ??/??/?? ATRIB BYTE
; 02.20 krs 07/??/80 cp/m 2 et al
; 02.23 krs 09/??/80
; 02.24 krs 12/22/80
; 02.35 dew 10/??/81
; 02.37 KRS 02/??/82 SUBDIRS
; 02.40 sbw 08/05/82 Miscellaneous
; 02.42 sbw 12/13/82 Change jumps to SYABT to ABORT
;
	icl	pdef		;02.39
	icl	df		;02.39
	df.dos			;02.39
	df.cpu			;02.39
	df.sys			;02.39
;
	NAM	DR242						;02.42
;
c3ver	equ	0	; 0 = not c3
;
;	NOTE CRMLBL HANDLING NOT DONE
;
	ENT	LOGDK,CLRDK,SETLOG
	ENT	DIRRD,DIRWR
	ENT	DIRCLR					;02.00
	ENT	GETBK,FREBK
	ENT	DSKVC,LOGVC,rodvc,tstalo,wrtpt,wrtptx	;02.20
	ENT	DIVDE8					;02.07
	ent	cksvec,dskbit,abit			;02.20
	ENT	RXDRV					;02.37
;
	ext	hdradr,cmphl,savaf			;02.20
	ext	abort,syabt					;02.42
	EXT	DIRSIZ,DIRCLS,GTSDT,GTDUCB
	EXT	ASDTE,GETCLS,GDIRST
	EXT	DSKIO,MUL16,DIV16,DIV32,NEGHL
	EXT	FCBDK					;02.35
	EXT	BS1READ,bs1dwrt				;02.00
	EXT	BS1ADR,BS1WRT				;02.00
	EXT	FLSALL,gETFRE				;02.00
	EXT	ERMSG
	EXT	CDKBK,MOVE				;02.01
	EXT	cks00					;02.20
	EXT	FREALL,SDT				;02.37
	ifc	c3ver					;02.37
	EXT	PSWRD,SYC09,SYC10,DSKCHG		;02.36
	endc
;
SPC	EQU	20H
CR	EQU	13
LF	EQU	10
;
LABFLG	EQU	81H	; LABEL FLAG BYTE VALUE
CRMLBL	EQU	83H	; CROMEMCO'S LABEL
LABCSZ	EQU	12	; LABEL.CLUSTER SIZE
;
VECLG	EQU	32	;32 BYTES IN ALLOCATION VECTOR
;			LENGTH FIXED IN DSKVC
DRLEN	EQU	32	;16 BYTES/ENTRY
BIGLEN	EQU	64	;SIZE OF BIG DIR ENTRY
FRECNT	EQU	15	; NUMBER OF RECORDS IN DIR ENTRY
;
    ifc SYSUCB=SINGLE
	EXT	?UDEV
    elsec
	EXT	RDUCB
    endc
	EJECT
;
;	READ DIRECTORY ENTRY
;ENTRY:	A=ENTRY NUMBER (1..255),B=DISK
;	IF B=-1 THEN NO READ ,JUST CALC. DIR ENTRY
;		MUST ASSUME SAME DISK DRIVE
;RETURN:	@HL=DIR ENTRY
;		@BUFFER -> UCB.URSBF1
;
DIRRD:	CALL	ASDTE	; ALWAYS READ
;
	CALL	CALDB	; CALCULATE DIR BLK NUM.
	PUSH	B	; C=RELATIVE ENT NUM
	PUSH	PSW	; SAVE FLAG - 0 SET = 1ST REC	 02.20
;
;REAL READ
	PUSH	B	; B=UNIT
	PUSH	D
	CALL	LOGDK	; LOG ON DISK
	POP	D
	POP	B
	MVI	C,0	; CLEAR BLOCK(HIGH)
	CALL	BS1READ	; READ A BLOCK
	POP	PSW	; RETRIEVE FLAGS		;02.20
	BRNZ	DIRR1	;NOR FIRST, GOON		 02.20	;02.35
	CALL	CKS00	;COMPUTE			 02.20
	LXI	H,CKSVEC				;02.20
	MOV	C,B	;SET B_ FOR ADDITION		 02.20
	MVI	B,0					;02.20
	DAD	B	;ADDRESS BYTE			 02.20
	MOV	B,C	;DISK BACK TO B			 02.20
	CMP	M	; IS IT THE SAME		 02.20
	CNZ	WRTPT	;NO, FLAG WRITE PROTECTED	 02.20
;
DIRR1:	POP	H	; L:=REL ENT NUM
	MVI	H,0
	DAD	H
	DAD	H
	DAD	H
	DAD	H
	DAD	H	; REL DIR ENT * 32
	XCHG
	CALL	BS1ADR	; HL:=BUFF ADR			02.00
	DAD	D	;  +BUFFER->A(DIR ENTRY)
	RET
	EJECT
;	CALCULATE DIR BLOCK (IN A)
;RETURNS: C=REL ENT NUM, DE=DISK BLK NUM
; MUST HAVE CALLED ASDTE TO SET UP CSDTE
;   FOR GDIRST
;
CALDB:	DCR	A	;DIR BLKS = 1..64
	PUSH	PSW
	MVI	E,3FH
	RRC
CALDB1:	RRC		;DIV BY 2 OR 4
	ANA	E	;REMOVE JUNK
	MOV	E,A
	MVI	D,0	;DE:= DIR BLOC ON DIR TRK
	POP	PSW
CALDB2:	ANI	3
	MOV	C,A	;C:= RELATIVE BLK (0..3)
	PUSH	H
	CALL	GDIRST	; HL:=START DIR BLK
	DAD	D
	MOV	A,D					;02.20
	ORA	E	; IF ZERO, IS FIRST		 02.20
	XCHG		;DE:=DIR BLOCK REQ.
	POP	H
	RET
;
;	WRITE DIR. BLOCK & FLUSH BUFFER			 02.00
;ENTRY:	USES CURR DIR BLOCK (IN UCB.URSBF1)		 02.00
;
DIRWR:	
;	DEFINITION OF BUFFER HEADER - NEEDED		 02.20
;	TO FIND OUT IF THIS IS THE ONE			 02.20
;
	ORG	0			       ;XXX	;02.20
;						XXX	 02.20
B.FLAG:	DS	2	; FLAG WORD		XXX	M  W
B.FWRD:	DS	2	; FOWARD CHAIN		XXX	U  I
B.BWRD:	DS	2	; BACKWARD CHAIN	XXX	S  T
B.BUF:	DS	2	; BUFFER PTR		XXX	T  H
B.UNIT:	DS	1	; UNIT NUMBER		XXX	 
B.BLK:	DS	3	; BLOCK NUMBER		XXX	A  B
B.ERR:	DS	2	; ERROR BYTE		XXX	G  F
B.WCNT:	DS	2	; WORD COUNT		XXX	R  !
;						XXX	E
HDRLEN	EQU	16	; 16 BYTE HEADERS	XXX	E
;						XXX	 02.20
	ROG				       ;XXX	 02.20
;						XXX	 02.20
	PUSH	D	; SAVE FCB ADDRESS		 02.20
	call	bs1adr	; get buffer address		 02.20
	push	h	; save on stack			 02.20
	call	hdradr	; get header address		 02.20
	lxi	d,b.unit ; address unit id		 02.20
	dad	d					;02.20
	MOV	A,M	; UNIT				 02.37
	ANI	7FH	; PURE				 02.37
	MOV	B,A	; IN B				 02.37
	CALL	ASDTE					 02.37
	mov	c,m	; put unit in c			 02.20
	inx	h	; now blk			 02.20
	mov	e,m	; low of disk addr		 02.20
	inx	h					;02.20
	mov	d,m	; high of disk addr		 02.20
	inx	h					;02.20
	mov	a,m	; hi-hi				 02.20
	ora	a					;02.20
	BRNZ	notw1	; must be 0 to work		 02.20	;02.35
	call	gdirst	; now go get it			 02.20
	call	cmphl	; see if same			 02.20
	BRNZ	notw1					;02.20	;02.35
	pop	h	; retrieve bufer		 02.20
	call	cks00	; compute			 02.20
	lxi	h,cksvec				;02.20
	mvi	b,0	; c is unit(rel 0)		 02.20
	dad	b	; address byte			 02.20
	mov	m,a	; new checksum			 02.20
	push	h	; make stack happy		 02.20
;							 02.20
notw1:	pop	h	; adjust stack			 02.20
	POP	D	; RESTORE FCB			 02.20
;							 02.20
	JMP	BS1WRT					;02.20
;
;	CLEAR DIR FROM USE				 02.00
;	ENTRY:  B=UNIT					 02.00
;
DIRCLR:	PUSH	B					;02.00
	CALL	FLSALL					;02.00
	POP	B					;02.00
	RET						;02.00
;
;	FREE CURRENT DIR BLOCK				 02.00
;ENTRY: USES BLOCK IN UCB.URSBF1			 02.00
	EJECT
;	ALLOCATE A DISK CLUSTER
;ENTRY:  B=DISK
;RETURN: DE=CLUSTER, A=0,OKAY -1,NO SPACE
;	BLOCK WILL BE 0..DSKSZ-1
GETBK:	PUSH	B	;MUST ASSUME DISK LOG-IN UPON OPEN
	call	logdk	;02.34
	CALL	DSKVC	;@HL=ALLOCATION VECTOR OF DISK (B)
	PUSH	H	; SAVE @VECTOR
	MVI	L,SDTNCL	;GET NUMBER OF CLUSTERS
	CALL	GTSDT
	MOV	C,M	;IN BC
	INX	H
	MOV	B,M
	LXI	H,7	;FIX BUG - DIVIDE		;02.07
	DAD	B	;CLUSTERS BY 8 FOR		;02.07
	XCHG		;DONE CHECK ON THE		;02.07
	CALL	DIVDE8					;02.07
	MOV	C,E	;NUMBER OF CLUSTERS		;02.07
	MOV	B,D	;(BIT MAP IS 8'S)		;02.07
	LXI	D,0	;STARTING BLOCK NO.
	POP	H	;RESTORE HL=@VECTOR
	PUSH	H
GETB1:	MOV	A,M
	CPI	-1
	BRNZ	GETB2	;FREE BIT FOUND			;02.35
	INX	H
	INX	D	;8 CLUSTERS USED
	DCX	B	;COUNT CLUSTERS
	MOV	A,B
	ORA	C
	BRNZ	GETB1	;KEEP LOOKING			;02.35
	POP	H
	POP	B
OUTOFX:	MVI	A,-1	; OUT OF SPACE (A=-1)
	RET
GETB2:	XCHG		;8 BITS PER BYTE
	DAD	H
	DAD	H
	DAD	H
	XCHG
GETB3:	RLC		;FIND ACTUAL BIT
	INX	D	;INC BLOCK NO.
	BRC	GETB3					;02.35
	DCX	D	;MAKE ORG ZERO
	POP	H
	POP	B	; DISK
;	DE = BLOCK TO ALLOCATE
	PUSH	H	;PUT BACK			;02.07
	CALL	CHKBK	; WILL CHECK VALIDITY		;02.07
	POP	H	;RESTORE			;02.07
	BRNC	OUTOFX					;02.07	;02.35
	CALL	SBIT	;SET BIT IN MAP
	XRA	A
	RET
	EJECT
;
;	FREE A DISK CLUSTER
;ENTRY: B=DISK, DE=CLUSTER
;
FREBK:	CALL	CHKBK					;02.07
	RNC		;SKIP ILLEGAL REQUESTS
	CALL	DSKVC	;HL=A(ALLOCATION VECTOR)
	BR	CBIT	;CLEAR BIT (E) FROM @HL		;02.35
;
CHKBK:	MVI	L,SDTNCL	;GET MAX CLUSTE		 02.07
	CALL	GTSDT
	MOV	A,E	;REQUEST < MAX ?
	SUB	M
	INX	H
	MOV	A,D
	SBB	M
	RET
;
;	GET A(DISKVECTOR)  FROM SDT
;ENTRY:	B=DISK, RETURN:   H VECTOR @HL
;
DSKVC:	PUSH	PSW
	CALL	ASDTE
	MVI	L,SDTMAP
	CALL	GTSDT
	MOV	A,M	; @HL=A(VECTOR)
	INX	H
	MOV	H,M
	MOV	L,A
	POP	PSW
	RET
;
;	BIT ADDRESSING
;	NUMBERED FROM 7 TO BIT 0 (0..7)
;ENTRY: HL=VECTOR, DE=BIT(0..65535)
;RETURNS: HL=BYTE, A=MASK
ABIT:	PUSH	D
	CALL	DIVDE8	;MAKE BIT BYTE
	DAD	D	;HL=A (BYTE)
	POP	D
	MOV	A,E
MBITX:	ANI	7	;DEVELOP MASK FOR BIT
	PUSH	H
	PUSH	D
	LXI	H,BTAB
	MOV	E,A
	MVI	D,0
	DAD	D
	MOV	A,M
	POP	D
	POP	H
	RET
BTAB:	DB	80H,40H,20H,10H,8,4,2,1
;
SBIT:	CALL	ABIT	;SET BIT
	ORA	M	;OR IN BIT
	MOV	M,A
	RET
;
CBIT:	CALL	ABIT	;CLEAR BIT
	CMA
	ANA	M	;MASK OUT BIT
	MOV	M,A
	RET
;	BUILD NORMAL BIT MASK (BIT=E) BIT0=0...BIT7=7
;ENTRY:	E=BIT NUM, RETURN: A=MASK
MBIT:	MVI	A,7
	SUB	E
	BR	MBITX					;02.35
;
DSKBIT:	MOV	A,B	;	; low of disk addr		 02.20
	inx	h					;02.20
	mov	d,m	; high of disk addr		 02.20
	inx	h					;02.20
	mov	a,m	; hi-hi				 02D	; SAVE INPUT
	MOV	D,E	; SET GROUP			02.37
	MVI	C,2	; LOOP CONTROL			02.37
	MVI	B,0	; 'A' DRIVE			02.37
;	
RXDR0:  LXI	H,8008H	; MASK AND LOOP CONTROL		02.37
RXDR1:	MOV	A,H
	RLC
	MOV	H,A	; UPDATED MASH FOR NEXT ONE	02.37
	ANA	D	; TEST THIS BIT
	BRZ	RXDR2 	; NO				02.37
	PUSH	H	;				02.37
	PUSH	D	;				02.37
	PUSH	B	;				02.37
	CALL	CLRDK	; YES				02.37
	POP	B	;				02.37
	POP	D	;				02.37
	POP	H	;				02.37
;
RXDR2:	INR	B					;02.37
	LDA	SDT					;02.37
	CMP	B					;02.37
	BREQ	RXDR3					;02.37
	DCR	L	; EIGHT BITS TO TEST		02.37
	BRNZ	RXDR1	;				02.37
	DCR	C	; TWO BYTES TO TEST		02.37
RXDR3:	POP	D	; RETRIEVE SECOND GROUP		02.37
	push	d	; Preserve stack level			;02.40
	BRNZ	RXDR0	;				02.37
	pop	d	; Clean up stack			;02.40
	XRA	A	;				02.37
	JMP	SAVAF	; RETURN 00 TO USER		02.37
;
;	CLEAR DISK  (B=DISK 0...)
;
CLRDK:	
	CALL	DSKBIT	; DE:=DISK, HL:=VOGVC
	BR	CBIT	;CLEAR BIT			;02.35
;
tstalo:	
;	test cluster allocated - de = @fcb		 02.20
;		(next record to be read/written)	 02.20
	call	cdkbk	;this routine really does it!	 02.20
	BRC	notalo	;carry set = no			 02.20	;02.35
	xra	A					;02.20
	jmp	savaf	;give result to indians!	;02.20
;
notalo:	xra	a					;02.20
	dcr	a	;-1, carry set			 02.20
	jmp	savaf	;go home, kid			 02.20
;
	EJECT
;
;  DO LOGIN IF REQUIRED (FOR SYSCALS)
;					(*01.02*)
SETLOG:	PUSH	D
	PUSH	B
	CALL	FCBDK	; B:=DISK CODE
	CALL	LOGDK	; DO IT
	POP	B
	POP	D
;  ** SPECIAL RETURN IN A
	XRA	A	; A:=0 FOR NMTCH
	RET		; WHICH USUALLY FOLLOWS
;
;	LOGIN DISK (B=DISK NUM 0..7)
;	USES NEW BUFFER FROM FREE POOL
LOGDK:
	CALL	ASDTE	; SET CURR SDT ENTRY
	CALL	DSKBIT	; DE:=DISK, HL:=LOGVC
	CALL	ABIT	; HL:=DISK'S BYTE, A:=BIT
;			xchg removed			 02.20
	MOV	C,A	; C:=BIT
	mov	a,m					;02.20
	ANA	C
	RNZ		; DONE, DISK ALREADY LOGGED IN
;
;
	PUSH	H	; SAVE POINTER			 02.37
	PUSH	B	; SAVE BIT			 02.37
;
;	CODE MOVED 02.37
;
	MVI	L,SDTCSZ
	CALL	GTSDT
	MVI	M,8	; CLUSTERING:=8
	INX	H
	INX	H
	INX	H	; SKIP DUCB (NOT CHGED)
	INX	H	; (HOME CAN SET START BLK)
	INX	H	; SKIP START DIR BLK
	MVI	M,64	; DIR ENTRIES
	INX	H
	MVI	M,2	; AND 2 DIR CLUSTERS
	INX	H
	mov	a,m					;02.20
	ani	subdir+bigonly				;02.23
	mov	m,a					;02.20
	MVI	C,8
LOGDK1:	INX	H
	MVI	M,SPC	; BLANK OUT VOLUME NAME
	DCR	C
	BRNZ	LOGDK1					;02.35
; NOW HOME DISK UNIT (HOME CAN SET SDT VALUES)
	PUSH	B
	MVI	A,11	; FREE				 02.37
	CALL	DSKIO					;02.37
	POP	B					;02.37
	PUSH	B					;02.37
	MVI	A,10	;R1.05 SIZE THE DISK
	CALL	DSKIO	;*  (WILL SET CSDTE)
	POP	B	;* GET DISK
;
	MVI	A,0	;* HOME THE DISK
	CALL	DSKIO	;*  (WILL SET CSDTE)
;
LOGS01:	POP	B					;02.37
	POP	H					;02.37
	mov	a,m					;02.20
	ORA	C
	mov	m,a	; FLAG AS LOGGED		 02.20
	call	dskbit					;02.20
	inx	h	; ro vec right after		 02.20
	inx	h	; login vec			 02.20
	call	cbit	; clear the bit			;02.20
;
	ifc	c3ver					;02.37
;----------02.36 DSKCHG VECTOR ---------------
	CALL	DSKBIT	; CONVERT DISK BIT
	LXI	H,DSKCHG
	CALL	CBIT
;-----------END 02.36 ------------------------
	endc						;02.37
	CALL	GETFRE
;
	LXI	D,0	;DE=DIRECTORY BLOCK
LOG2:	PUSH	H
	PUSH	D
	PUSH	B
	PUSH	H
	CALL	GDIRST	; HL:=START OF DIR BLK
	DAD	D
	SHLD	BADBLK	; SAVE FOR ERR MSG
	XCHG
	POP	H	; DE:=DIR BLK NUM.+DIR BLK 1 ADR
	MVI	C,0	; CLEAR BLOCK(HIGH)
	MVI	A,5	; READ INTERLEAVED
	CALL	DSKIO
	ORA	A
	LXI	H,LGERM
	CNZ	ERMSG	; BAD DIR READ ON LOGIN
	POP	B
	POP	D
	POP	H
	EJECT						;02.01
;
	PUSH	B
	PUSH	D
	PUSH	H	;HL=BUFFER
;
;	CAN'T GET DIRECTORY TYPE UNTIL WE KNOW IT	02.07
;	OR SET ANYTHING IN DISK CLUSTER AREA EITHER	02.07
;	IF NOT FIRST DIR BLOCK GO PROCESS (IS SMALL)	02.07
;							02.07
	MOV	A,E				;	02.07
	ORA	D				;	02.07
	JNZ	LOG3A				;	02.07
;
;	compute the checksum				 02.20
;	of this record for later r/o check!		 02.20
	PUSH	H					;02.20
	PUSH	B					;02.20
	CALL	cks00	; COMPUTE CHECKSUM		 02.20
	LXI	H,CKSVEC				;02.20
	MOV	C,B	; DISK				 02.20
	MVI	B,0					;02.20
	DAD	B	; ADDRESS BYTE			 02.20
	MOV	M,A	; SAVE CHECKSUM			 02.20
	POP	B					;02.20
	MVI	L,SDTDTY ; get dir type byte		 02.23
	CALL	GTSDT					;02.23
	xthl		; exchange stack top		 02.23
;
	MOV 	A,M
; IF LABEL THEN SETUP CSDTE (##00.31)
	CPI	BIGLBL
	xthl		; dir type back in hl		 02.23
	BRNE	LOGNB					;02.37
	MVI	A,'A'					;02.37
	ADD	B					;02.37
	STA	BLBAD					;02.37
	LXI	H,BLBADM				;02.37
	BR	SNDERR					;02.37
;							;02.37
BLBADM:	DB	13,10,'>>Error - NO BIG DISK SUPPORT'	;02.37
	DB	' IN SYSTEM - unit '			;02.37
BLBAD:	DB	0,13,10,0				.02,37
;
lognb:	pop	h					;02.23
	mov	a,m					;02.23
	CPI	LABFLG
	BRZ	LOG3D	;STANDARD LABEL			;02.35
	CPI	CRMLBL					;02.37
	JNZ	LOG3X					;02.37
	MVI	A,'A'					;02.37
	ADD	B					;02.37
	STA	CRMDK					;02.37
	LXI	H,CRMMSG				;02.37
SNDERR:	call	ermsg	; Show error message			;02.42
	call	abort	; Test ^C trapping			;02.42
	jmp	syabt	; If ^C inactive, hard exit		;02.42
;							;02.37
CRMMSG:	DB	13,10,'>>Error - CROMEMCO label found'	;02.37
	DB	' on unit '				;02.37
CRMDK:	DB	0,13,10,0				;02.37
;
LOG3D:
	PUSH	H	;ENTRY
	mvi	l,sdtdty				;02.20
	call	gtsdt	;address dir type		 02.20
	mov	a,m					;02.20
	ori	lbldir	;flag as labeled		 02.20
	mov	m,a	;put back			 02.20
	pop	h					;02.20
	push	h	;restore sdt entry		 02.20
	PUSH	B	;DISK
	XCHG
	LXI	H,LABCSZ  ; LABEL CLUSTER SIZE
	DAD	D
	MOV	A,M
	PUSH	H
	MVI	L,SDTCSZ  ; SDT.CLUSTER:=
	CALL	GTSDT
	MOV	M,A
	MOV	C,A	; SAVE CLUSTERSIZE
	POP	H
	INX	H
	MOV	A,M	; A:=DIR TYPE
	PUSH	H
	MVI	L,SDTDTY
	CALL	GTSDT
	ORA	M
	MOV	M,A
	POP	H
	INX	H	; ONE BYTE UN-USED
	INX	H
	MOV	A,M	; GET RECORD COUNT
LOG3E:	ADD	A					;02.07
LOG3F:	ADD	A	; DIR ENTRIES:=BLOCKS*2 OR 4
	BRNC	LOG3FX					;02.37
	MVI	A,0FEH					;02.37
log3fx:	PUSH	H					;02.13
	MVI	L,SDTMLN
	CALL	GTSDT
	MOV	M,A
	XTHL
	PUSH	D	;SAVE LABEL
	MOV	L,M	;GET RECORD COUNT
	MVI	H,0
	MOV	E,C	;GET CLUSTERSIZE
	MOV	D,H
	DAD	D	;ROUND
	DCX	H	; UP...
	CALL	DIV16	;GET CLUSTERS
	MOV	C,L	;HOLD IT
	POP	D
	POP	H
	INX	H
	MOV	M,C	; SDT.MASTER DIR CLUSTERS
	INX	H
	INX	H
	INX	D	; SKIP DISK BYTE
; MOVE IN LABEL NAME
	MVI	B,8
LOG3C:	LDAX	D
	MOV	M,A
	INX	D	; SDT.LABEL:=DISK LABEL
	INX	H
	DCR	B
	BRNZ	LOG3C					;02.35
	ifc	c3ver					;02.37
;-------PASSWORD TEST 02.36----------------------
	PUSH	D	;SAVE DISK BLOCK PTR
	MVI	B,3	; TEST FOR NON-BLANK PASSWORD
     .DO
	LDAX	D
	ORA	A
	BRNZ	.BREAK
	DBNZ	.DO	; ALL NULS MEANS NO PASSWORD ON DISK
	POP	D	; CLEAR STACK
	BR	..NOPSW
     .UNTIL
	POP	D	;GET DISK PSWRD PTR
	POP	B
	PUSH	B	;GET BC=DISK NUMBER
	MOV	A,B	;PUT DISK NUMBER IN MSG
	ADI	'A'
	STA	..DSK
	MOV	C,B
	MVI	B,0
	LXI	H,PSWRD
	DAD	B
	DAD	B
	DAD	B	;HL=DISK PASSWORD IN MEMORY (3 BYTES EACH)
;NOW CHECK FOR USER ENTERED PASSWORD
    .DO
	PUSH	D	; DE=DISK PASSWORD
	PUSH	H	; HL=MEMORY TABLE
	MVI	B,3
      .DO
	LDAX	D
	CMP	M
	BRNE	.BREAK	; FAILS - NO MATCH
	INX	H
	INX	D
	DBNZ	.DO
	POP	H	; CLEAR STACK
	POP	D
	BR	..NOPSW	; MATCHED - ALL OK
      .UNTIL
;FAILED - ASK USER FOR A NEW PASSWORD
	LXI	D,..ASK
	CALL	SYC09		; GIVE PROMPT
	LXI	D,..BUF
	CALL	SYC10		; READ ANSWER
	LXI	H,..BUFA
	POP	D
	PUSH	D
	LXI	B,3
	LDIR		; MOVE ANSWER TO MEMORY
	POP	H
	POP	D	; RESTORE PTRS
	BR	.DO	; TRY AGAIN
    .UNTIL
..ASK:	DB	CR,LF,'Enter Disk 
..DSK:	DB	'X Password: $'
..BUF:	DB	4,0
..BUFA:	DB	'...',0
;
..NOPSW:
;-------END PASSWORD TEST 02.36 --------------------
	endc						;02.37
	CALL	SETNCL
;
	POP	B	;DISK
	POP	H	;ENTRY	
	BR	log3y					;02.10	;02.35
	EJECT	
;
LOG3X:	MVI	A,0C0H	; DEFAULT			;02.07
	BR	LOG3Z					;02.07	;02.35
LOG3Y:	MVI	A,80H
LOG3Z:	PUSH	B	;* SAVE DISK
	PUSH	H	;* SAVE BUFFER
	CALL	DSKVC					:02.07
	MOV	M,A	; FLAG AS NEEDED		;02.07
;
	CALL	SETNCL
;
;****	ADDED 02.40:	******************************************
;
; If a type 2S system, or a small directory in a type 2 system, then
; abort if the number of clusters is >255.  Return with the disk marked
; as logged, so that processing may continue.  This will allow a large
; floppy disk to be labelled with a larger clustersize to prevent this
; problem from occuring again.
;
;
	mov	a,d	; Small directory:
	ora	a	; >255 clusters?
	brz	okclus	; No: Number of clusters OK.
;
	pop	b	; Too many clusters: Clean up stack
	pop	b	; b := Disk number
;
	mvi	a,'A'
	add	b	; Fill in the unit in the error
	sta	clbad	; message.
	lxi	h,clbadm
	call	ermsg	; Report the error.
;
; Enter here to release the buffer and return.
;
prlsrt:
	pop	h	; Buffer address
	pop	d
	pop	b	; Disk
	ret
;
okclus:
;
;****	END OF 02.40 addition	***********************************
;
	LXI	H,7	;ROUND UP
	DAD	D
	XCHG
	CALL	DIVDE8	;MAKE BITS BYTES
	POP	H
	POP	B
	PUSH	B
	PUSH	H
	CALL	DSKVC
;	DO NOT INITIALIZE FIRST BYTE - ALREADY DONE ;02.07K
  .do								;02.40
	inx	h						;02.40
	dcx	d						;02.40
	mov	a,d						;02.40
	ora	e						;02.40
	brz	.break		; Handle <8 clusters		;02.40
	mvi	m,0		; Zero allocation vector	;02.40
	br	.do						;02.40
  .until							;02.40
	POP	H	;BUFFER				 02.07
	POP	B	; DISK				 02.07
; LOGIN DISK MAP (DM) ENTRIES
;
LOG3A:	MVI	C,4					;02.07
LOG3Q:	MOV	A,M					;02.07
	CPI	0E5H					;02.07
	BRZ	LOG4	;DELETED FILE			 02.07	;02.35
	XCHG
	LXI	H,FRECNT
	DAD	D
	XCHG
	PUSH	H	;@DIR ENTRY
	PUSH	B	;B=DISK/C=ENTRY CNT
	CALL	DSKVC	; @HL=ALLOCATION VECTOR
	PUSH	H	;TOP=@ALLOCATION VECTOR
	XCHG		;HL=@ENTRY BLK CNT
	INX	H	;UP TO DM
	MVI	C,16	;CLUSTERS TO LOG
LOG5:	MOV	E,M	;DE=DM CLUSTER
	MOV	A,E
	ORA	A	:USED?
	BRZ	LOG5C	;NO...				;02.35
	MVI	D,0
	XTHL
	PUSH	H	;TOP,HL=ALLOCATION VECTOR
	CALL	SBIT	;SET BIT
	POP	H
	XTHL
LOG5C:	INX	H
	DCR	C	;COUNT LOGGED CLUSTERS
	BRNZ	LOG5					;02.35
	POP	D	; @ALLOCATION VEC.
	POP	B	;B=DISK/C=ENTRY CNTR
	POP	H	;@DIR ENTRY
;
;	NEXT DIRECTORY ENTRY
LOG4:	LXI	D,DRLEN
	DAD	D	;NEXT ENTRY
	DCR	C
	BRNZ	LOG3Q					;02.35
;
	POP	H	;@BUFFER
	POP	D	;BLOCK NUM
	INX	D
	CALL	DIRSIZ
	MVI	C,3FH
	RRC
	RRC
	ANA	C
	POP	B	;B:=DISK
	CMP	E	;NEXT BLOCK OF
	JNZ	LOG2	; FOUR ENRIES
;
	RET
;
; Error message for 2.40 addition.
;
clbadm:	db	13,10,'>>Error - More than 255 clusters on '
	db	'small directory - unit '
clbad:	db	' :',13,10,0
;
;	WRITE PROTECT DISK (28 CALL)			 02.20
;
WRTPTX:
	LHLUCB	DEV	; CURRENT DEVICE TO L	;02.20	;02.35
	MOV	B,L	; TO B				 02.20
;
WRTPT:	CALL	ASDTE					;02.20
	CALL	DSKBIT					;02.20
	INX	H	;INCREMENT TO R/O		 02.20
	INX	H	;VECTOR (AFTER THE		 02.20
	CALL	ABIT	;LOGIN VECTOR)			 02.20
	ORA	M	;SET IT				 02.20
	MOV	M,A	;PUT IT BACK			 02.20
	RET						;02.20
	EJECT
;
;  SET NUMBER OF CLUSTERS IN SDT by calculating:		;02.40
;								;02.40
;	# clusters = (# blocks) / (blocks/cluster)		;02.40
;
SETNCL:	MVI	L,SDTCSZ
	CALL	GTSDT
	MOV	C,M
	MVI	B,0
	MVI	L,DUBSIZ
	CALL	GTDUCB
	MOV	E,M
	INX	H
	MOV	D,M
	INX	H
	MOV	L,M
	MOV	H,B
	PUSH	H	; HI
	PUSH	D	; LO
	CALL	GDIRST
	CALL	NEGHL
	POP	D	; LO
	DAD	D	;  INTO HL
	POP	D	; HI
	BRC	SETNC1	; NO BORROW			;02.35
	DCX	D
SETNC1:	CALL	DIV32
	MVI	L,SDTNCL
	CALL	GTSDT
	MOV	M,E
	INX	H
	MOV	M,D
	RET
;
;
;  DIVIDE DE BY 8
;
DIVDE8:	PUSH	B
	MOV	A,D
	RRC
	RRC
	RRC
	MOV	B,A
	ANI	1FH
	MOV	D,A
	MOV	A,B
	ANI	0E0H
	MOV	B,A
	MOV	A,E
	RRC
	RRC
	RRC
	ANI	1FH
	ORA	B
	MOV	E,A
	POP	B
	RET
;
;
LGERM:	DB	'Bad Directory Block: 00',80H
BADBLK:	DW	0
	DB	'I',13,10,0
;
;  ALLOCATION STORAGE
;
LOGVC:	DB	0,0	;16 DISK LOG BITS
;
rodvc:	db	0,0	;16 disk r/o bits		 02.20
;
cksvec: db	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0		;02.20
;
	END
