;****************************************************************************
;
;  HDFBL - High Density Floppy Boot Loader
;    This code is returned by the FDC+ whenever a sector read is performed
;    by original Altair disk code. When an Altair boot ROM attempts to
;    read the disk to boot, it will think the disk read worked and jump
;    to this code at location zero. This code, in turn, reads track 0
;    from the HD Floppy and jumps to that code to continue the boot
;    process.
;
;    Since this code reads an entire 10240 byte track into RAM to retrieve
;    the second stage loader, the track is placed in RAM at 4000h to avoid
;    overwriting programs in the first 16K of the CP/M program area.
;
;    For use in the FDC+, the output of this assembly must must be put into
;    a 137 byte Altair sector as follows:
;
;      Byte 	Value		Notes
;         0	80h		Sync bit and track number (zero)
;         1	80h		Low byte of max load address (0080h)
;         2	00h		High byte of max load address
;     3-130			Code below with fill bytes of zero
;       131	FFh		Marker byte
;       132	xx		Checksum of bytes 3-130
;   133-136	00h		Fill out Altair sector
;
;    Version History
;
;    Ver     Date	  Description
;    ---   --------	---------------------
;    1.0   06/20/20	Original, Mike Douglas  
;    1.1   07/06/20     Update for 10240 byte track vs 9984 bytes. De-select
;			drive before jumping to loaded code in case loaded
;			code is not good.   
;
;****************************************************************************
HDFLDR	equ	4000h		;location to place HD floppy loader
STACK	equ	HDFLDR-100h	;stack location
TRKLEN	equ	10240		;track length to read

; Altair FDC+ Equates

DRVSLCT	equ	08h		;drive select register (out)
cDSLCT	equ	80h		;deselect drive

DRVSTAT	equ	08h		;drive status register (in)
sENWD	equ	01h		;enter new write data flag
sMOVEOK	equ	02h		;OK to move head
sHDSTAT	equ	04h		;head status flag
sDSKEN	equ	08h		;disk is selected and enabled
sINTEN	equ	20h		;processor interrupts enabled
sTRACK0	equ	40h		;on track zero flag
sNRDA	equ	80h		;new read data available

DRVCMD	equ	09h		;drive command register (out)
cSTEPI	equ	01h		;step in
cSTEPO	equ	02h		;step out
cHDLOAD	equ	04h		;head load
cRESTMR	equ	04h		;restart motor-off timer (MINIDSK)
cHDUNLD	equ	08h		;head unload
cREADEN	equ	10h		;read request enable
cHCSON	equ	40h		;reduce head current switch
cWRTEN	equ	80h		;write request enable

DRVSEC	equ	09h		;drive sector position (in)
sNEWSEC	equ	01h		;new sector flag (sector true)

DRVDATA	equ	0Ah		;drive read/write data (in/out)

DRVTRK	equ	0Bh		;OUT to provide cylinder to FDC+

DRVIOS	equ	0Bh		;IN for I/O operation status
sCRCERR	equ	01h		;1=checksum error
sTRKERR	equ	02h		;1=track number error
sEOSERR	equ	04h		;1=unexpected end of sector
sDONE	equ	80h		;1=disk transfer complete
sERRMSK	equ	(NOT sDONE) AND 0FFh

;--------------------------------------------------------------
; bootDsk - Load track zero into RAM at location HDFLDR.
;--------------------------------------------------------------
	org	0

bootDsk	di			;ensure interrupts disabled
	lxi	sp,STACK	;init stack pointer

	mvi	a,cDSLCT	;deselect current drive
	out	DRVSLCT	
	xra	a		;select drive 0
	out	DRVSLCT
	out	DRVTRK		;give track 0 to FDC+
	mvi	a,cHDLOAD	;load the head
	out	DRVCMD
	
; Restore to track zero

seek0	in	DRVSTAT		;loop until OK to move the head 
	ani	sMOVEOK
	jnz	seek0

	in	DRVSTAT		;see if we are at track 0
	ani	sTRACK0		;at track zero?
	jz	waitSec		;yes, start the load process

	mvi	a,cSTEPO	;issue step out
	out	DRVCMD
	jmp	seek0

; Load track zero into RAM
	
waitSec	in	DRVSEC		;read sector position register
	rar			;wait for sector true (0=true)
	jc	waitSec	

	lxi	h,HDFLDR	;HL->where to put HD Floppy loader
	lxi	b,TRKLEN/2	;BC=transfer counter
	mvi	a,cREADEN	;issue read request
	out	DRVCMD

wtData	in	DRVSTAT		;wait for data to be ready
	ora	a		;test for NRDA flag true (zero)
	jm	wtData

	in	DRVDATA		;do dummy read to start transfer

; rdFifo - Read data without handshake. Data should be read slower than
;    the physical transfer rate of 16us/byte. This loop averages 17us/byte.

rdFifo	in	DRVDATA		;(10) get and store a byte
	mov	m,a		;(7)
	inx	h		;(5)

	in	DRVDATA		;(10) get and store abyte
	mov	m,a		;(7)
	inx	h		;(5)

	dcx	b		;(5) decrement transfer counter
	mov	a,b		;(5)
	ora	c		;(4)
	jnz	rdFifo		;(10)

	in	DRVIOS		;get the I/O status
	sta	HDFLDR-1	;save for diagnosis
	ani	sERRMSK		;test the error bits
	jnz	bootDsk		;error, start over
	
	mvi	a,cDSLCT	;deselect the drive
	out	DRVSLCT	

	jmp	HDFLDR		;enter the HD Floppy loader

	end
