;
; TARBELL ELECTRONICS
; CP/M COLDSTART LOADER
; VERSION OF 3-22-'79.
;
; THIS PROGRAM IS LOADED AT LOCATION ZERO
; BY THE BOOTSTRAP PROGRAM, AND EXECUTED.
; ITS PURPOSE IS TO LOAD AND EXECUTE THE
; CP/M DISK OPERATING SYSTEM AT THE TOP
; OF THE MEMORY IN USE.
;
FALSE	EQU  0		;DEFINE VALUE OF FALSE.
TRUE	EQU  NOT FALSE	;DEFINE VALUE OF TRUE.
;
;********* THIS IS THE AREA TO MAKE CHANGES IN ***********
;********* FOR DIFFERENT SYSTEM CONFIGURATIONS ***********
;							**
MSIZE	EQU  61		;MEMORY SIZE IN DECIMAL KB.	**
DELTA	EQU  FALSE	;TRUE IF DELTA PRODUCTS CPU	**
PERSCI	EQU  FALSE	;TRUE FOR PERSCI DRIVES.	**
DUBSID	EQU  FALSE	;TRUE FOR DOUBLE SIDED SYSTEMS.	**
SPT	EQU  26		;NUMBER OF SECTORS PER TRACK.	**
DISK	EQU  0F8H	;DISK PORT BASE ADDRESS.	**
;							**
;*********************************************************
;*********************************************************
;
DCOM	EQU  DISK	;COMMAND PORT.
DSTAT	EQU  DISK	;STATUS PORT.
TRACK	EQU  DISK+1	;TRACK PORT.
SECT	EQU  DISK+2	;SECTOR PORT.
DATA	EQU  DISK+3	;DATA PORT.
WAIT	EQU  DISK+4	;WAIT PORT.
DCONT	EQU  DISK+4	;CONTROL PORT.
CBASE	EQU  (MSIZE-20)*1024
CPMB	EQU  CBASE+3400H;START OF CP/M.
BDOS	EQU  CPMB+800H	;START OF BDOS.
BIOS	EQU  CPMB+1600H ;START OF BIOS.
BOOTE	EQU  CPMB+1600H	;COLD BOOT ENTRY POINT.
NSECTS	EQU  51		;SECTORS OF CP/M.
RTCNT	EQU  10		;NUMBER OF RETRYS.

	ORG  0		;START OF LOADER.

BOOT:	MVI  E,RTCNT	;GET RETRY COUNT.

	IF  DELTA	;IF USING DELTA PRODUCTS CPU.
	MVI  A,1	;CODE TO KICK OUT ROM
	OUT  9
	ENDIF

BLOOP:	LXI  SP,100H	;SET STACK POINTER.
	LXI  H,BDOS	;CP/M STARTS HERE.
	MVI  D,NSECTS	;NUMBER OF SECTORS TO READ.
	MVI  C,2	;SECTOR NUMBER.
RNTRK:	MVI  B,4	;FOR HEAD LOAD.
	MOV  A,C	;SECTOR IN A.
RNSEC:	CALL READ	;READ FIRST SECTOR.
	DCR  D		;IF DONE,
	JZ   BOOTE	;GO TO CP/M.
	MVI  B,0	;FOR NO HEAD LOAD.
	INR  C		;INCREMENT TRACK COUNT.
	MOV  A,C	;DONE WITH
	CPI  SPT+1	;THIS TRACK?
	JC   RNSEC	;IF NOT, READ NEXT SECTOR.

	IF   NOT PERSCI AND NOT DUBSID
	MVI  A,53H	;STEP COMMAND.
	OUT  DCOM	;ISSUE IT.
	IN   WAIT	;WAIT UNTIL DONE.
	ENDIF

	IF   PERSCI AND NOT DUBSID
	MVI  A,50H	;INCREMENT TRACK
	OUT  DCOM	;REGISTER.
	IN   WAIT	;WAIT FOR INTRQ.
	MVI  A,1	;STEP
	OUT  DCONT	;PERSCI.
	MVI  A,72H	;SWITCH WAIT FOR
	OUT  DCONT	;SEEK COMPLETE.
	IN   WAIT	;WAIT.
	MVI  A,0F2H	;SWITCH WAIT
	OUT  DCONT	;BACK.
	ENDIF

	IF   DUBSID	;IF DOUBLE SIDED SYSTEM.
	MVI  A,0B2H	;SIDE SELECT COMMAND.
	OUT  DCONT	;ISSUE IT.
	ENDIF

	MVI  C,1	;SECTOR NUMBER.
	JMP  RNTRK	;READ NEXT TRACK.

READ:	OUT  SECT	;SET SECTOR REGISTER.
	CALL CHECK	;CHECK FOR ERROR.
	MVI  A,88H	;COMMAND FOR READ.
	ORA  B		;GET HEAD LOAD BIT.
	OUT  DCOM	;ISSUE COMMAND.
RLOOP:	IN   WAIT	;WAIT FOR DRQ.
	ORA  A		;SET FLAGS.
	JP   CHECK	;JUMP IF DONE.
	IN   DATA	;READ DATA.
	MOV  M,A	;PUT IN MEMORY.
	INX  H		;INCREMENT POINTER.
	JMP  RLOOP	;LOOP UNTIL DONE.

CHECK:	IN   DSTAT	;READ STATUS.
	ANI  9DH	;LOOK AT ERROR BITS.
	RZ		;OK IF ZERO.
	DCR  E		;DECREMENT RETRY COUNT.
	JNZ  BLOOP	;TRY AGAIN IF NOT ZERO.
	STA  EC		;SAVE ERROR CODE.
	CMA		;INVERT AND SEND
	OUT  0FFH	;TO FRONT PANEL.
HERE:	JMP  HERE	;LOOP.

	ORG  7DH	;PUT JUMP HERE.
	RST  0		;JUMP INTO BOOT.
	NOP
	DB   020H	;INDICATE SD/SS 128 BYTE
;			 SECTORS.
EC:	END		;END OF BOOT.
