;  THIS IS THE CP/M BOOTSTRAP FOR THE SINGLE USER SYSTEM.
; I HAVE WRITTEN IT IN SUCH A WAY THAT IT IS INDEPENDENT
; OF THE PROM CODE, EVEN THOUGH THIS MEANS MORE PROGRAMMING
; OF THE DMA.  OTHERWISE, WE WOULD BE FORCED TO MODIFY THE
; PROM CODE EVERY TIME WE WANTED TO MOVE CP/M AROUND IN
; RAM.  THE BOOTSTRAP IS OTHERWISE STRAIGHTFORWARD AND
; REQUIRES NO SPECIAL EXPLANATION.  IT IS DESIGNED TO BE
; LOADED AND EXECUTED AT 0C100H.
;
; JAN 14, 1983   EDITED BY CHUNG MIN CHOI

	TITLE TS3BOOT.MAC--TELEVIDEO SYSTEM TS-803 BOOTSTRAP--JAN 14, 1983

	.Z80
	CSEG
	.PHASE 0C100H

BOOT:	DI			; DISABLE SYSTEM INTERRUPT
	LD	(WBFLAG),A
	OR	A
	LD	A,1
	OUT	(BANKSP),A	; CHANGE MEMORY BANK TO 1
	LD	SP,BOOT		; INITIALIZE THE STACK POINTER
	JR	NZ,BOOT10	; IF FROM FLOPPY THEN SKIP
;
;	ELSE LOAD CP/M FROM WINCHESTER.
;
;	 PRESET RECNO = 1
;
	LD	(RECNO),A
	LD	DE,CPMBAS
;
LOOP:	EX	DE,HL
	LD	A,(H$TRK)
	OUT	(WSDH),A
	XOR	A
	OUT	(WHICYL),A
	OUT	(WLOCYL),A
	INC	A
	OUT	(WCOUNT),A
	LD	A,(H$SEC)
	OUT	(WSECT),A
	LD	A,WREAD
	OUT	(WCMD),A
;
; 	SET B = TRANSFER COUNT; C = INPUT DATA PORT ADDRESS
;
	LD	BC,WDATA
GETIO: 	IN	A,(WSTAT)
	AND	WDRQ
	JR	Z,GETIO
;
;	TRANSFER DATA FROM CONTROLLER TO MEMORY
;
	INIR
WAITH:	IN	A,(WSTAT)
	AND 	WBUSY
	JR	NZ,WAITH
	DEC	H		; SET HL = LAST DMA ADDRESS
	EX	DE,HL
	IN	A,(WSTAT)	; CHECK FOR ERROR
	AND	WFAULT+WERROR	; 
	JR	NZ,LOOP		; IF ERROR THEN RETRY TRANS. DATAT BLOCK
	INC	D		; ELSE HL = NEXT DMA ADDRESS.
	LD	HL,RECNO
	LD	A,(HL)
	SUB	CPMSEC
;
	JP	Z,CCP
;
	INC	(HL)
	DEC	HL
	INC	(HL)
	LD	A,(HL)
	CP	32
	JR	NZ,LOOP
	XOR	A
	LD	(HL),A
	DEC	HL
	DEC	HL
	INC	(HL)
	JR	LOOP

;
; HOME THE HEAD TO TRACK 0
;
BOOT10:	LD	A,RESCMD	; RESTORE COMMAND
	OUT	(FDCCMD),A
	CALL	WAIT		; WAIT FOR COMPLETION
	AND	SEEMSK
	JR	NZ,BOOT10	; SEEK ERROR, TRY AGAIN
;
; INITIAL VALUES FOR TRACK, SECTOR, AND SECTOR COUNT
;
	LD	HL,TRKNO
	LD	(HL),0
	INC	HL
	LD	(HL),2
	INC	HL
	LD	(HL),CPMSEC
	LD	DE,CPMBAS
;
BOOT20:	
	LD	HL,SECNO
	LD	A,(HL)
	CP	SPCYL+1		; TIME TO MOVE TO NEXT TRACK
	JR	C,BOOT30	; NO.
;
; MOVE TO NEXT TRACK AND SEEK.
;
	LD	(HL),1
	DEC	HL		; BUMP TRACK NO.
	INC	(HL)
	LD	A,(HL)
	OUT	(FDCDAT),A	; WRITE TRACK TO DATA REGISTER
	INC	HL
	LD	A,SEECMD
	OUT	(FDCCMD),A	; SEEK.
	CALL	WAIT		; WAIT FOR COMPLETION
	AND	SEEMSK		; STRIP OFF NON-SIGNIFICANT BITS
	JR	NZ,BOOT10	; BOOT ERROR, TRY AGAIN
;
BOOT30:	
	LD	A,(HL) 		; UPDATE SECTOR REGISTER
	EX	DE,HL
	CP	(SPCYL/2)+1	; WHICH SIDE?
	LD	C,11100101B	; MOTOR-ON(B1),SIDE-0(B2),DRIVE-0(B4)
	JR	C,BOOT40	; (PRIMARY)
	LD	C,11100001B	; MOTOR-ON,SIDE-1,DRIVE-0 (SECONDARY)
	SUB	(SPCYL/2)
;
BOOT40:	OUT	(FDCSEC),A
	LD	A,C		; CHOOSE SIDE
	OUT	(FDD),A		; WRITE TO FLOPPY SELECT LATCH
	LD	BC,FDCDAT		; SET 256 BYTES COUNTER
	LD	DE,0FFFFH	; SET TIMER 
	LD	A,RDSCMD	; READ SECTOR COMMAND
	OUT	(FDCCMD),A
;
	LD	A,15		; DELAY 60 US
WAIT0:	DEC	A
	JR	NZ,WAIT0
;
DEVRDY:	IN	A,(FDCCMD)
	BIT	1,A		; DRQ BIT SET?
	JR	NZ,READIN	; YES
	DEC	DE		; COUNT DOWN TIMER
	LD	A,D
	OR	E
	JR	Z,BOOT10	; TIME OUT
	IN	A,(FDCCMD)
	BIT	1,A		; DRQ BIT SET?
	JR	NZ,READIN	; YES
	RRCA
	JR	C,DEVRDY
	JR	BOOT10		; ERROR, RETRY
;
DRQRDY:	IN	A,(FDCCMD)
	AND	02H		; DRQ BIT SET?
	JR	Z,DRQRDY	; NO, WAIT
;
READIN:	INI			; INPUT AN ASSEMBLED BYTE
	JR	NZ,DRQRDY	; ALL BYTE READ-IN?
;
	CALL	WAIT
;
	AND	0CH		; ANY ERROR: CRC, LOST DATA?
	JR	NZ,BOOT10	; YES, RETRY
;
	EX	DE,HL
	LD	HL,SECNO
	INC	(HL)
	INC	HL
	DEC	(HL)
	JR	NZ,BOOT20	; LOOP ON NEXT SECTOR IF MORE TO READ
CCP:	EI			; ENABLE SYSTEM INTERRUPT
	LD	A,(WBFLAG)
	JP	CPMBOO		; JUMP TO CBIOS BOOT ADDRESS

	
; THIS ROUTINE LOOPS UNTIL THE FDC IS
; IN A NON-BUSY STATE, OR UNTIL A NOT-
; READY CONDITION IS DETECTED.

WAIT:	LD	A,15		; WE MUST DELAY ABOUT
WAIT10:	DEC	A		; 60 USECS BEFORE READING 
	JR	NZ,WAIT10	; THE STATUS.

WAIT20:	IN	A,(FDCCMD)	; READ THE FDC STATUS

	BIT	FDCBSY,A	; ARE WE PROCESSING A COMMAND?
	JR	NZ,WAIT20	; YES, LOOP UNTIL NOT BUSY
	AND	ERRMSK		; MASK OFF NON-ERROR BITS
	RET
;
H$TRK:	DEFW	0
H$SEC:	DEFB	1
RECNO:	DEFS	1
TRKNO:	DEFS	1		; STORAGE FOR TRACK NUMBER
SECNO:	DEFS	1		; STORAGE FOR SECTOR NUMBER
SECCNT:	DEFS	1		; STORAGE FOR CPM SECTOR COUNTER
WBFLAG:	DEFS	1		; INDICATOR OF HARD OR FLOPPY DISK BOOT.
	.DEPHASE

; 	DRIVE STATUS
;
WFAULT	EQU	020H		; WRITE FAULT ON DRIVE
;
;	CONTROLLER COMMAND
;
WREAD	EQU	020H		; READ SECTOR
;
;	CONTROLLER STATUS
;
WBUSY	EQU	080H		; CONTROLLER BUSY
WDRQ	EQU	008H		; DATA REQUEST
WERROR	EQU	001H		; ERROR STATUS REPORT
;
;	DRIVE/CONTROLLER I/O
;
CBASE	EQU	0B0H		; BASE ADDRESS OF THE CONTROLLER

WDATA 	EQU	CBASE		; DATA PORT (I/O)
WPCYL	EQU	CBASE+1		; WRITE PRECOMP CYLINDER NUMBER (O)
WERRS	EQU	CBASE+1		; ERROR DEFINITION (I)
WCOUNT	EQU	CBASE+2		; SECTOR COUNT (I/O)
WSECT	EQU	CBASE+3		; SECTOR NUMBER (I/O)
WLOCYL	EQU	CBASE+4		; CYLINDER NUMBER, LOW ORDER BITS(I-O)
WHICYL	EQU	CBASE+5		; CYLINDER NUMBER, HIGH ORDER BITS(I-O)
WSDH	EQU	CBASE+6		; SECTOR SIZE, DRIVE SELECT, HEAD SELECT (I/O)
WCMD	EQU	CBASE+7		; COMMAND PORT (O)
WSTAT	EQU	CBASE+7		; STATUS PORT (I)
;
; FDC EQUATES

FDCCMD	EQU	80H		; FDC STATUS AND COMMAND PORT
FDCTRK	EQU	81H		; FDC TRACK PORT
FDCSEC	EQU	82H		; FDC SECTOR PORT
FDCDAT	EQU	83H		; FDC DATA PORT

FDD	EQU	90H		; FLOPPY SELECT LATCH
BANKSP	EQU	13H		; MEMORY SELECTION PORT

; FDC STATUS BITS

FDCBSY	EQU	0		; FDC BUSY IS BIT 0
FDCIND	EQU	1		; FDC INDEX HOLE DETECTED
FDCTR0	EQU	2		; FDC TRACK 0 DETECTED
FDCCRC	EQU	3		; FDC CRC ERROR ENCOUNTERED
FDCSEE	EQU	4		; FDC SEEK ERROR ENCOUNTERED
FDCHLD	EQU	5		; FDC HEAD LOAD ACK.
FDCPRT	EQU	6		; FDC DISK IS WRITE PROTECTED
FDCRDY	EQU	7		; FDC DISK NOT READY BIT

; FDC STATUS BYTE MASKS

ERRMSK	EQU	01011100B	; MASK OFF INSIGNIFICANT BITS
SEEMSK	EQU	00011000B	; CHECK THE NOT READY BIT
DNRMSK	EQU	00000000B	; DRIVE NOT READY MASK

; FDC COMMAND BYTES

RESCMD	EQU	00000111B	; HOME HEAD COMMAND
SEECMD	EQU	00010111B	; SEEK TRACK COMMAND
HDSCMD	EQU	00110111B	; HEAD STEP, PREVIOUS DIRECTION
HSICMD	EQU	01010111B	; HEAD STEP IN, TOWARD HUB.
HSOCMD	EQU	01110111B	; HEAD STEP OUT, TOWARD EDGE.
RDSCMD	EQU	10000000B	; READ SECTOR
WTSCMD	EQU	10100000B	; WRITE SECTOR
RDACMD	EQU	11000000B	; READ SECTOR ADDRESS
RDTCMD	EQU	11100000B	; READ TRACK
WTTCMD	EQU	11110000B	; WRITE TRACK
FRCCMD	EQU	11010000B	; FORCE TERMINATION

; DISK CONFIGURATION EQUATES

NUMTRK	EQU	40		; NUMBER OF TRACKS ON DISKETTES
MAXTRK	EQU	NUMTRK-1	; NUMBER STARTS AT 0
MINTRK	EQU	0		; WHERE TO BEGIN SEEK TEST
SPT	EQU	18		; SECTORS PER TRACK
SPCYL	EQU	SPT*2		; SECTORS PER CYLINDER
BPSEC	EQU	100H		; BYTE PER SECTOR

;	*********************************************
;	* FOLLOWING CPMBAS(CCP ENTRY POINT ADDRESS) * 
;	* HAS TO BE CONSULTED WITH 802FBIOS.MAC FOR * 
;	* FUTURE MOVCPM GENERATION.                 *
;	*********************************************

CPMBAS	EQU	0D400H		; CCP ADDRESS FOR 59K SYSTEM
CPMLN	EQU	1600H		; CP/M SIZE = CCP + BDOS = 1600H
CPMSEC	EQU	(0FFFFH-CPMBAS)/256+1	; NUMBER OF SECTORS FOR TVI CP/M
CPMBOO	EQU	CPMBAS+CPMLN		; CBIOS COLD START ENTRY POINT

	END

