;GETPDA/ASM
*TITLE	'GETPDA - GRANULE ADDRESS SYSTEM - 1.0'
;
;	GETPDA CALCULATES A PHYSICAL DISK ADDRESS
;	FOR A RELATIVE FILE RECORD.  THE SYSTEM USES
;	A GRANULE ALLOCATION SCHEME.
;
;	ENT	IX =>	FCB
;
;	EXT	 C =	DEVICE
;		 B =	SECTOR HIGH
;		 E =	SECTOR LOW
;		 D =	CYLINDER
;
GETPDA	LD	C,(IX+16)	;DRIVE
	CALL	LOCDCT		;IY => DCT
	LD	B,(IX+08)
	LD	H,(IX+09)
	LD	L,(IX+10)	;BHL = NRN
	LD	A,(IY+19)	;SEC/GRAN
	CALL	TDIVD		;GET GRAN,SEC
	LD	(SDISP),A	;SECTOR DISPLACEMENT
	PUSH	IX
	EX	(SP),HL 	;HL => FCB
	LD	BC,20
	ADD	HL,BC		;HL => SD LIST
	POP	BC		;BC = REQUIRED GRAN
;
	LD	A,5		;SD COUNT
	LD	DE,0		;INIT GRAN OFFSET
;
ADJ0	PUSH	AF		;SAVE SD COUNT
	LD	A,(HL)		;LSB CSD
	INC	HL		;HL => MSB SD
	INC	A		;END SD LIST?
	JR	Z,ADJ1		;IF YES
	PUSH	HL		;SAVE => SD LIST
	LD	H,D
	LD	L,E		;HL = GRAN OFFSET
	XOR	A
	SBC	HL,BC		;FOUND?
	JR	C,ADJ2		;POSSIBLE
	POP	HL		;GET => SD LIST
	JR	Z,NXTCSD	;FOUND!
;
ADJ1	INC	HL		;HL => NEXT GRAN OFFSET
	POP	AF		;GET SD COUNT
	DEC	A		;NEXT SD
	JR	Z,ADJ3		;IF END SD LIST
	LD	E,(HL)
	INC	HL
	LD	D,(HL)		;DE = NEXT GRAN OFFSET
	INC	HL		;HL => NEXT SD
	JR	ADJ0		;TRY AGAIN
;
ADJ2	INC	H		;REQ GRAN > OFFSET?
	LD	A,L		;A = OFFSET-REQUESTED
	POP	HL		;GET => SD LIST
	JR	NZ,ADJ1 	;NOT FOUND!
	PUSH	DE		;SAVE GRAN OFFSET
	LD	E,A		;E = OFF-REQ
	LD	A,(HL)		;GET SD
	AND	1FH		;GRAN COUNT-1
	ADD	A,E
	LD	A,E		;A = OFFSET+COUNT
	POP	DE		;GET GRAN OFFSET
	JR	NC,ADJ1 	;NOT FOUND!
	NEG			;GRAN DISPLACEMENT
	JR	NXTCSD		;FOUND!
;
;	SAVE INFO AND SET-UP FOR SD FETCH
;
ADJ3	LD	A,(SDISP)	;SECTOR DISP
	LD	(TDISP),A	;TEMP SAVE
	LD	A,(OVLYL)	;SYS OVERLAY
	LD	(TOVLY),A	;TEMP SAVE
;
	LD	A,4-1<4+1	;OVERLAY COMMAND
	CALL	OVRLY0		;LOAD/EXEC SYSTEM
;
	PUSH	AF		;SAVE GRAN OR ERROR
TOVLY	EQU	$+1
	LD	A,0
	CP	2-1<4		;OPEN?
	CALL	NZ,OVRLY0	;IF NOT, RE-LOAD
	POP	AF		;GET GRAN OR ERROR
	RET	NZ		;IF ERROR
	LD	(GRAN),A	;SAVE GRAN DISP
;
TDISP	EQU	$+1
	LD	A,0		;GET SECTOR DISP
	LD	(SDISP),A	;SAVE AGAIN
	JR	C,TOPCSD	;MOVE CSD TO TOP
	JR	CSDPDA		;GET DISK ADDRESS
;
*EJECT
;	SQUEEZE THE FCB'S SD LIST
;
;	ENT	 A =	GRAN DISPLACEMENT
;		DE =	GRAN OFFSET IN SD LIST
;		HL =>	SD LIST
;		SP =>	SD COUNT
;
NXTCSD	LD	(GRAN),A	;SAVE GRAN DISP
	LD	B,(HL)
	DEC	HL
	LD	C,(HL)		;BC = GRAN OFFSET
	INC	HL		;HL => SD
	POP	AF		;GET SD COUNT
	CPL			;-COUNT-1
	ADD	A,4		;COUNT > 3?
	JR	NC,ADJ4 	;IF YES
	INC	A		;CORRECT COUNT
	RLCA			;* 2
	RLCA			;* 4
	PUSH	BC		;SAVE
	PUSH	DE
	EX	DE,HL		;DE => SD LIST
	LD	HL,-4
	ADD	HL,DE		;HL => START SQUEEZE
	LD	B,0
	LD	C,A		;BC = LENGTH
	LDDR			;DO IT!
	EX	DE,HL		;HL => SD LIST
	POP	DE		;RESTORE
	POP	BC
;
;	PLACE THE CSD AT TOP OF SD LIST
;
;	ENT	DE =	GRAN OFFSET FOR SD
;		BC =	SEGMENT DESCRIPTOR
;		HL =>	SD LIST
;
TOPCSD	LD	(HL),B		;MSB SD
	DEC	HL		;BKSP
	LD	(HL),C		;LSB SD
	DEC	HL		;BKSP
	LD	(HL),D		;MSB GRAN
	DEC	HL		;BKSP
	LD	(HL),E		;LSB GRAN
;
ADJ4	LD	H,B
	LD	L,C		;HL = SD
;
*EJECT
;	CONVERT CURRENT SD TO DISK ADDRESS
;
;	ENT	HL =	SD
;		IX =>	FCB
;		IY =>	DCT
;
CSDPDA	LD	A,H		;GRAN INFO
	RLCA
	RLCA
	RLCA
	AND	7		;OFFSET TO AREA
GRAN	EQU	$+1
	ADD	A,0		;+ GRAN DISP
	LD	E,A		;E = GRAN
	LD	A,(IY+20)	;GRANS/CYL
	CALL	SDIVD		;GET CYL,GRAN
	ADD	A,L		;+ CYL DISP
	LD	D,A		;D = CYLINDER
	LD	A,(IY+19)	;SEC/GRAN
	LD	L,E
	LD	H,0		;HL = GRAN
	PUSH	DE		;SAVE CYL
	CALL	DMULT		;GET SECTOR
	POP	DE		;GET CYL
SDISP	EQU	$+1
	ADD	A,0		;SECTOR DISP
	LD	E,A		;E = LSB SECTOR
	LD	A,L		;GET LSB
	ADC	A,0		;+ OVERFLOW
	LD	B,A		;B = MSB SECTOR
	LD	C,(IX+16)	;DEVICE NUMBER
	XOR	A		;NO ERROR
	RET
;
 