; LAST UPDATED:		24 MAY 83
; REASON FOR UPDATE:	The boot ROM will now load all of track 0, head 0,
;		26 single density 128 byte sector format sectors.  This change
;		also permits booting of 5 1/4 inch disks, under a different
;		size and density format as determined by the read command
;		parameters.  The larger boot size permits a more advanced
;		boot loader on the first system track.			    aep
;
; PROGRAM NAME:		xxxFPROM.ASM, where "xxx" identifies the relationship
;		of the revision level to it's corresponding BIOS source.
;
; PURPOSE:	Floppy Disk (either 8 inch or 5 1/4 inch drives) initial
;		program loader (IPL), which consequently will load the
;		remainder of the operating system upon execution entry.
;
;	==========================	Copyright 1983, CompuPro Corporation,
;	||			||	A division of Godbout Electronics.
;	||  FLOPPY DISK PROM	||	Oakland Airport,	Oakland, CA
;	||   POWER UP LOADER	||
;	||			||
;	==========================
;
;	This product is a copyright program product of CompuPro and is
;	supplied for use with the CompuPro Disk controllers.
;
; Disk layout Definition.
;
;  Cylinder 0,  Head 0,  8 inch disk = 26 X 128 byte single density sectors.
;  Cylinder 0,  Head 0,  5 inch disk = ?? X ??? byte ?????? density sectors.
;
;	The code is loaded starting at the address immediately following
; the selected execution segment of this PROM (256 Bytes) and may be
; any type of secondary loader or the runtime operating system itself.
;
;
; LIBRARY CONSTANTS:
	MACLIB	COMPUPRO	;Disk and Serial/Parallel interface constants
	MACLIB	ACTIVE		;Flags directing construction for the various
;
; EQUATED CONSTANTS:
;
XBOOT	EQU	100h	;Base Location of second phase loader in RAM
; Drive specific constants. (Set to handle nearly any drive)
SRT	EQU	16 - 10		;10 millisecond step rate for controller value
HUT	EQU	240 / 16	;Head unload delay time in milliseconds (240)
HDLT	EQU	(35 + 1) / 2	;Head load time in milliseconds (35)
;
    if BOOT5X
FDPORT	EQU	FD5PORT		;Set to boot from minifloppies
NS$128	EQU	18	; 128 byte sectors / track	-- 2.25K
NS$256	EQU	18	; 256 byte sectors / track	-- 4.5K
NS$512	EQU	 8	; 512 byte sectors / track (IBM PC compatible, 4K)
NS1024	EQU	 5	;1024 byte sectors / track	-- 5K bytes total
    else
FDPORT	EQU	FD8PORT		;Default is boot from 8 inch drives
NS$128	EQU	26	; 128 byte sectors / track	-- 3.25K
NS$256	EQU	26	; 256 byte sectors / track	-- 6.5K
NS$512	EQU	15	; 512 byte sectors / track	-- 7.5K
NS1024	EQU	 8	;1024 byte sectors / track	-- 8K bytes total
    endif
;
;	ROM Bootstrap loader.
;
    ASEG
	ORG	0		;Base address of bootstrap PROM
	NOP! NOP! NOP! NOP	;Power up delay opcodes
START:	MVI	A,81h		;Turn on the disk motors, leave PROM active
	OUT	FDPORT+FDON
;
; Loop on total error to this point.
	LXI	SP,2		;Init stack pointer in PROM area
	LXI	B,4000h		;Init delay count
DELAY1:	XTHL!	XTHL		;Harmless time consuming instructions
	DCX B!	MOV A,B! ORA C	;Bump count, test if done
	JNZ	DELAY1		;Loop until the time passes
;
; Load Specify Command.
	LXI	D,SPEC		;Point to specify command sequence
	MVI	B,LSPEC		;Length in "B"
SPEC1:	IN	FDPORT+FDCS	;See if ready to accept next byte
	ORA	A
	JP	SPEC1		;Wait if not ready
	LDAX	D		;Load command byte
	OUT 	FDPORT+FDCD	;to controller command port
	INX	D		;Point to next byte
	DCR	B		;Bump count until all loaded
	JNZ	SPEC1		;Loop if more to do
;
; Recalibrate drive.
	MVI	B,LRECAL	;Length of command in "B"
RCAL1:	IN	FDPORT+FDCS	;See if ready to accept next byte
	ORA	A
	JP	RCAL1		;Wait if not ready
	LDAX	D		;Load command byte
	OUT 	FDPORT+FDCD	;to controller command port
	INX	D		;Point to next byte
	DCR	B		;Bump count until all loaded
	JNZ	RCAL1		;Loop if more to command load
;
RCAL2:	IN	FDPORT+INTS	;See if command execution completed
	ORA	A
	JP	RCAL2		;Wait if not
;
; Verify successful completion of recalibrate command.
	MVI	A,FD$RSTS	;"Read Status" command
	OUT	FDPORT+FDCD	; to controller
	LXI	B,0C000h	;Init delay count
DELAY2:	XTHL!	XTHL		;Let command settle
	DCX B!	MOV A,B! ORA C	;Bump count, test if done
	JNZ	DELAY2		;Loop until the time passes
;
RCAL3:	IN	FDPORT+FDCS	;See if command accepted
	ORA	A
	JP	RCAL3		;Loop until ready
	IN	FDPORT+FDCD	;Get first resulting "Status Byte"
	XRI	20h		;Flip "drive ready" status bit
	MOV	C,A		;Put result in "C"
RCAL4:	IN	FDPORT+FDCS	;Get command execution status again
	ORA	A
	JP	RCAL4		;See if seek complete
	IN	FDPORT+FDCD	;Get second "execution" result byte
	ORA	C		;Combine the two result status bytes
	JNZ	START		;Loop to retry if error
;
; Execute read operation sequence until loaded successfully.
	LXI	H,DATA		;DMA data pointer
	MVI	B,LDMA		;Length of DMA data
;
; Output beginning DMA address.
ADDR:	LDAX	D		;Get byte of extended address
	OUT	FDPORT+FDMA	;Send to DMA port of DISK 1
	INX	D		;Next byte to xfer
	DCR	B		;Bump count
	JNZ	ADDR		;Loop until all 3 bytes loaded
;
; Read all the data on track 0 in to get the cold boot loader.
	MVI	B,LREAD		;Load "B" with command lenght
READ1:	IN	FDPORT+FDCS	;Get controller status
	ORA	A
	JP	READ1		;Wait until controller ready for another byte
	LDAX	D		;load command byte
	OUT 	FDPORT+FDCD	; to controller
	INX	D		;Point to next byte to load
	DCR	B		;Bump command load count
	JNZ	READ1		;Loop if more bytes to load
;
READ2:	IN	FDPORT+INTS	;See if interrupt active (command complete)
	ORA	A
	JP	READ2		;Loop until so
;
READ3:	IN	FDPORT+FDCS	;See if ready to read status
	ORA	A
	JP	READ3		;Wait if not
	IN	FDPORT+FDCD	;Get resulting status of read operation
	SUI	40h		;Remove "abnormal ending" status bit
	MOV	H,A		;Put result in "E"
READ4:	IN	FDPORT+FDCS	;Get second status byte
	ORA	A
	JP	READ4		;Loop until ready
	IN	FDPORT+FDCD	;Second status byte in "A"
	XRI	FD$EOC		;Remove "End of Cylinder" bit
	MOV	L,A		;Put result in "D"
;
	MVI	B,7-2		;Count of remaining status bytes (ignored)
READ5:	IN	FDPORT+FDCS	;See if controller ready
	ORA	A
	JP	READ5		;Loop if not
	IN	FDPORT+FDCD	;Read status byte, ignore it
	DCR	B		;Bump remaining count
	JNZ	READ5		;Wait until all done
; If "Abnormal Ending" caused by "End of Cylinder" error, then read is valid.
	MOV A,L!  ORA	H	;Combine the two significant status bytes
	JNZ	START		;Loop to try next read if error
	JMP	BOOTVEC		;Exit from boot PROM if successful
;
	PAGE
;************************************************
;*	FIXED STORAGE FOR DISK PARAMETERS	*
;************************************************
	ORG	($ and 0FFF0h) + 16	;Next Segment boundary
;
SPEC:	DB	FD$SPEC		;Floppy disk specification command
	DB	SRT SHL 4 + HUT
	DB	HDLT SHL 1
LSPEC	EQU	$-SPEC		;Length of specification sequence
;
RECAL:	DB	FD$RECA,0	;Recalibrate command (home to track 0)
LRECAL	EQU	$-RECAL		;Command length
;
; Function data for controller to boot
DATA:	DB	0		;Extended Address
	DB	high XBOOT	;Base address of BOOT loader
	DB	low XBOOT
LDMA	EQU	$-DATA		;Length of DMA to load
;
; Try to read disk as single density 128 byte sectors.
READ:	DB	FD$RDAT		;Read sector(s) command for 8272 controller
	DB	0		;Head select, Drive select = 0
	DB	0		;Cylinder #0
	DB	0		;Head #0
	DB	1		;Starting Record (sector)
	DB	0		;"N" parameter (128 byte sectors)
	DB	NS$128		;Read to end of track = 3.25K bytes
	DB	07h		;GPL (Gap length)
	DB	128		;DTL (Data length)
LREAD	EQU	$-READ		;Length of parameter block to xmit
;
;************************************************
;*	EXIT ON SUCCESSFUL READ OPERATION	*
;************************************************
	ORG	XBOOT-6		;6 bytes perform exit sequence
;
; Successful read operation enables exit from PROM by falling thru to adjacent
; RAM immediately after disabling its own "phantom" control line.  This must
; be the last instruction in the 256 byte segment allotted to each of 8
; possible boot routines.
;
BOOTVEC:MVI	C,0		;Boot switch value passed to loader
	MVI	A,80h		;Turn drive motor on, bootstrap ROM off
	OUT	FDPORT+FDON	;Enter BOOT routine directly
;	org	xboot		;Cold boot code starts in RAM here
;
	END
