;WARM START LOADER FOR DOUBLE DENSITY 
;VERSION M4.1
;INTERRUPTS ARE NOT IMPLEMENTED
;THIS IS STORED IN TRACK 0 SECTOR 2
;AND IS LOADED INTO THE 80 BYTES BELOW THE OP SYSTEM ON A 
;COLD OR WARM BOOT
;
;
;THIS VERSION CONTAINS DISK DRIVERS FOR THE DIGITAL SYSTEMS
;FDC-3 CONTROLLER BOARD.  THIS BOARD CAN HANDLE DOUBLE DENSITY
;
;	NOTE :  MSIZE DETERMINES WHERE THIS CBIOS IS LOCATED
MSIZE	EQU	64	;CP/M VERSION MEMORY SIZE IN KILOBYTES
;
;
ram$top	equ	msize*1024
BIOS	EQU	ram$top-6*256	;START OF THE CBIOS PATCH
BDOS	EQU	bios-0e00h	;BASE OF RESIDENT PORTION OF CP/M
ccp  	EQU	bdos-0800h	;LENGTH OF THE CP/M SYSTEM IN BYTES
warmboot equ	ccp-0080h
NSECTS	EQU	(bios-ccp)/128		;NUMBER OF SECTORS TO LOAD ON WARM START
;
	ORG	warm$boot 	;ORIGIN OF THIS PROGRAM
WBOTE	EQU	BIOS+3
SETSEC	EQU	BIOS+21H
SETTRK	EQU	BIOS+1EH
SETDMA	EQU	BIOS+24H
READ	EQU	BIOS+27H
CONOUT	EQU	BIOS+0CH
SIGNON	EQU	BIOS+33h
;
PORT	EQU	04AH
DENSITY	EQU	04CH
;
;	JUMP VECTOR FOR INDIVIDUAL SUBROUTINES
	JMP	INITIO		;COLD START
;
;
WBOOT:	;SIMPLEST CASE IS TO READ THE DISK UNTIL ALL SECTORS LOADED
;
;
	MVI	B,NSECTS	;B COUNTS THE NUMBER OF SECTORS TO LOAD
	MVI	C,0		;C HAS THE CURRENT TRACK NUMBER
	MVI	D,3		;D HAS THE NEXT SECTOR TO READ
;	NOTE THAT WE BEGIN BY READING TRACK 0, SECTOR 3 SINCE SECTOR 1
;	CONTAINS THE COLD START LOADER, WHICH IS SKIPPED IN A WARM START
;	AND SECTOR 2 IS THE WARM START LOADER
	LXI	H,CCP		;BASE OF CP/M (INITIAL LOAD POINT)
LOAD1:	;LOAD ONE MORE SECTOR
	PUSH	B	;SAVE SECTOR COUNT, CURRENT TRACK
	PUSH	D	;SAVE NEXT SECTOR TO READ
	PUSH	H	;SAVE DMA ADDRESS
	MOV	C,D	;GET SECTOR ADDRESS TO REGISTER C
	CALL	SETSEC	;SET SECTOR ADDRESS FROM REGISTER C
	POP	B	;RECALL DMA ADDRESS TO B,C
	PUSH	B	;REPLACE ON STACK FOR LATER RECALL
	CALL	SETDMA	;SET DMA ADDRESS FROM B,C
;
;	DRIVE SET TO 0, TRACK SET, SECTOR SET, DMA ADDRESS SET
	CALL	READ
	ORA	A	;ANY ERRORS?
	JNZ	WBOOT	;RETRY THE ENTIRE BOOT IF AN ERROR OCCURS
;
;	NO ERROR, MOVE TO NEXT SECTOR
	POP	H	;RECALL DMA ADDRESS
	LXI	D,128	;DMA=DMA+128
	DAD	D	;NEW DMA ADDRESS IS IN H,L
	POP	D	;RECALL SECTOR ADDRESS
	POP	B	;RECALL NUMBER OF SECTORS REMAINING, AND CURRENT TRK
	DCR	B	;SECTORS=SECTORS-1
	JZ	GOCPM	;TRANSFER TO CP/M IF ALL HAVE BEEN LOADED
;
;	MORE SECTORS REMAIN TO LOAD, CHECK FOR TRACK CHANGE
	INR	D
	MOV	A,D	;SECTOR=27?, IF SO, CHANGE TRACKS
	CPI	27
	JC	LOAD1	;CARRY GENERATED IF SECTOR<27
;
;	END OF CURRENT TRACK, GO TO NEXT TRACK
;CHECK FOR DENSITY CHANGE
;THE DENSITY TO BE USED IS THE DENSITY OF DRIVE A
	LDA	DENSITY
	RRC
	JNC	LOAD2
;CHANGE TO DOUBLE DENSITY
	MVI	A,8
	STA	PORT
LOAD2:
	MVI	D,1	;BEGIN WITH FIRST SECTOR OF NEXT TRACK
	INR	C	;TRACK=TRACK+1
;
;	SAVE REGISTER STATE, AND CHANGE TRACKS
	PUSH	B
	PUSH	D
	PUSH	H
	CALL	SETTRK	;TRACK ADDRESS SET FROM REGISTER C
	POP	H
	POP	D
	POP	B
	JMP	LOAD1	;FOR ANOTHER SECTOR
;
INITIO:
;
;GIVE LOG-ON MESSAGE ON COLD START ONLY
	LXI	SP,80H
	LXI	H,SIGNON
PRTMESS:
	MOV	A,M
	ORA	A	;ZERO?
	JZ	GOCPM
	PUSH	H
	MOV	C,A
	CALL	CONOUT
	POP	H
	INX	H
	JMP	PRTMESS
GOCPM:
;COME HERE ON EITHER WARM OR COLD BOOT
;INITIALIZE POINTERS IN LOW MEMORY
	MVI	A,0C3H	;C3 IS A JMP INSTRUCTION
	STA	0	;FOR JMP TO WBOOT
	LXI	H,WBOTE	;WBOOT ENTRY POINT
	SHLD	1	;SET ADDRESS FIELD FOR JMP AT 0
;
	STA	5	;FOR JMP TO BDOS
	LXI	H,BDOS+6 ;BDOS ENTRY POINT
	SHLD	6	;ADDRESS FIELD OF JUMP AT 5 TO BDOS
;
	LXI	B,80H	;DEFAULT DMA ADDRESS IS 80H
	CALL	SETDMA
;
;PUT ACTIVE DISK NUMBER (STORED IN LOCATION 4) IN C
	LDA	04H
	MOV	C,A
	DI
	ORG	ccp	;GO TO CPM FOR FURTHUR PROCESSING
 	END
