	.IF	LISTG
	.LIST
	.PAGE
	.ELSE
	.NOLIST
	.ENDC
;****************************************************************************
;
;	Winchester Disk Driver - part 3
;
;	File:	SAGE.PROMG.TEXT
;	Date:	14-Jul-83
;	Issue:	1A
;
;
;	COPYRIGHT (c) 1983 SAGE Computer Technology
;	All Rights Reserved
;
;****************************************************************************
;
;	History:
;
;	1     23-Mar-83 Initial SAGE IV release
;	1A    14-Jul-83 Installed delay after drive ready.
;			Set Winchester flag in BOOTFLGS.
;	2     21-Nov-83 Added check for seek complete during boot
;****************************************************************************


.PAGE
;****************************************************************************
;
;	Reading & Writing
;
;	Uses D0-D2,A0-A1
;
;****************************************************************************

RDCHAN9
	MOVEA.L (SP)+,A1
	MOVE.L	(SP)+,WT_LENG	;Save length argument
	MOVE.L	(SP)+,WT_MEMA	;Save address argument
	MOVE.L	(SP)+,WT_LBN	;Save block number argument
	MOVE.L	A1,-(SP)	;Restore return address
	BSR	WDSELECT
	TST.B	WG_INIT		;Check if controller is initialized
	BNE.S	$10		;Controller already initialized
	BSR	WCINIT		;Init the controller
$10	
	
WTINIT1
	MOVE.B	#10.,WT_RTRY	;Set up initial retry count
WTINIT2				;Direct entry point
	CLR.B	WS_ERR
	BTST	#WB_READY,WP_1A ;Check if drive ready
	BNE	$80		;Drive is not ready
	TST.B	WG_INIT		;Check if controller is initialized
	BNE.S	$10		;Controller was initialized
	BSR	WCINIT		;Initialize the controller
$10	TST.L	WT_LENG		;See if any more bytes to transfer
	BEQ	WDEXIT		;No bytes left to transfer
	BSR	WDCALC		;Calculate transfer parameters
	BNE	WDIOERR		;Terminate on error
	BSR	WDSEEK		;Set up the seek
	TST.B	WS_ERR		;Check for detected errors
	BNE	WDIOERR		;Found error
	BSR	WDREAD		;Set up the read
	TST.B	WS_ERR		;Check for detected errors
	BNE	WDIOERR		;Found error
	BSR	WDMOVEI		;Move data into memory from buffer
	BNE	WDIOERR		;Found error
	MOVEQ	#0,D0		;Update transfer arguments
	MOVE.W	WT_NUMB,D0	;Set up byte count
	ADD.L	D0,WT_MEMA
	SUB.L	D0,WT_LENG
	DIVU	WI_BPS,D0	;Calculate number of blocks
	EXT.L	D0		;Clear high part
	ADD.L	D0,WT_LBN
	BRA	WTINIT1		;Set up next portion of transfer
	
;	Drive is not ready
$80	MOVE.B	#-4.,WS_ERR

;	Fall into WDIOERR


.PAGE
;****************************************************************************
;
;	Winchester Error Analysis
;
;****************************************************************************

WDIOERR
	SUBQ.B	#1,WT_RTRY	;Check for retries
	BLE	WDEXIT		;No more retries
	
	MOVE.B	WS_ERR,D0
	CMPI.B	#-7,D0
	BEQ.S	$40		;Overrun, retry read/write
	CMPI.B	#-8,D0
	BEQ.S	$40		;CRC, retry read/write
	CMPI.B	#-9,D0
	BEQ.S	$40		;Read after write error, retry write
	
	CMPI.B	#-6,D0
	BEQ.S	$30		;Data timeout, retry seek
	CMPI.B	#-12.,D0
	BNE	WDEXIT		;Must be hard error
	
;	Wrong cylinder
	CMPI.B	#3,WT_RTRY
	BGE.S	$40		;Must recalibrate

;	Retry seek
$30	CLR.B	WS_RCAL		;Set up recalibrate request
	
;	Retry read/write
$40	MOVE.W	#-1,D0
$45	DBF	D0,$45
	ADDQ.B	#1,WT_SOFT	;Count soft errors
	MOVE.B	WT_SOFT,D0
	ANDI.B	#1FH,D0
	BEQ.S	$50		;Do VCO recalibrate every 32 soft errors
	CMPI.B	#5,WT_RTRY
	BNE	WTINIT2		;Set up transfer
$50	BSR	WVCOINIT	;Recalibrate VCO
	BRA	WTINIT2		;Set up transfer again


.PAGE
;****************************************************************************
;
;	Done with Winchester Transfer
;
;****************************************************************************

WDEXIT
	MOVE.B	WP_1B,D0	;Deselect the drive
	ANDI.B	#0F0H,D0
	MOVE.B	D0,WP_1B
	MOVE.B	WS_ERR,D0	;Set up error reply code
	RTS
	

.PAGE
;****************************************************************************
;
;	Setup Winchester Drive Parameters
;
;****************************************************************************

WSELECT
	MOVEA.L (SP)+,A1
	MOVE.L	(SP)+,D3	;Save pointer to name or partition number
	MOVE.W	(SP)+,D1	;Set up drive select bit
	MOVEQ	#0,D0
	BSET	D1,D0
	MOVE.B	D0,WI_SELCT
	LSL.B	#4,D1		;Save drive in subdevice number
	MOVE.B	D1,WDRIVE
	MOVE.L	A1,-(SP)	;Restore return address
	CLR.B	WG_INIT		;Force re-initialization
	MOVE.B	#1,WI_HEADS	;Default disk parameters
	MOVE.B	#19.,WI_SPT
	MOVE.W	#512.,WI_BPS
	MOVE.W	#64.,WI_LOWC
	MOVE.W	#72.,WI_HIGHC
	MOVE.W	#6000.,WI_STPCT
	CLR.W	WI_BTTBL	;No bad blocks
	CLR.W	WI_BASE		;Make partition 0
	CLR.W	WI_TOP

;	Check if Drive is ready
	BSR	WDSELECT	;Select the drive
	MOVEQ	#47.,D1		;Set up 1 minute delay
	SWAP	D1
	BTST	#WB_READY,WP_1A
	BEQ.S	$5		;Drive is ready
$1	LEA	MSG33,A0	;Printout "Waiting for Drive Ready"
	BSR	TERMTEXT
	BSR	TERMCRLF
	BRA.S	$0
	
$2	BTST	#WB_READY,WP_1A
	BEQ.S	$5		;Drive is ready
	
$0	BSR	KEYCHK		;Check keyboard
	BEQ.S	$3		;No character
	BSR	KEYBCH		;Get character
	CMPI.B	#"Q",D0
	BEQ.S	$4		;Get out of routine
$3	SUBQ.L	#1,D1
	BNE	$2		;Back for another test
$4	MOVE.B	#-4,WS_ERR	;Set up Not Ready error
	BRA	WDEXIT

;	Check that drive ready is valid for 200 milliseconds
$5	MOVEQ	#-1,D0
$6	BTST	#WB_READY,WP_1A
	DBNE	D0,$6
	BEQ	$7		;Drive is ready
	SWAP	D1
	CMPI.W	#47.,D1
	SEQ	D0
	SWAP	D1
	TST.B	D0
	BNE	$1		;Need "Waiting message"
	BRA	$2

;	Check for seek complete

$7	MOVE.L	#0,D1		;Reset D1 to get correct delay
	MOVEQ	#47.,D1		;Set up 1 minute delay
	SWAP	D1
$8	BTST	#WB_SKCMP,WP_1A ;See if seek complete
	BEQ.S	$15		;Seek is complete
	BSR	KEYCHK		;Check keyboard
	BEQ.S	$9		;No character
	BSR	KEYBCH		;Get character
	CMPI.B	#"Q",D0
	BEQ	$4		;Get out of routine
$9	SUBQ.L	#1,D1
	BNE	$8		;Back for another test

;	Read in partition map & bad track table & other info

$15	CLR.L	-(SP)		;Located at block zero
	LEA	400H,A0		;Set up destination address
	MOVE.L	A0,-(SP)
	MOVE.L	#1024.,D0	;Set up length
	MOVE.L	D0,-(SP)
	BSR	RDCHAN9		;Read Winchester
	BNE	WDEXIT		;Failure
	
	MOVEQ	#16.,D0
	CMP.L	D0,D3		;Check if pointer or partition number
	BLT.S	$30		;D3 is partition number
	MOVEA.L D3,A0		;Set up test address
	LEA	600H,A1		;Set up address of partition names
	MOVEQ	#0,D3
$10	MOVE.L	(A1),D1
	CMP.L	(A0),D1
	BNE.S	$20		;No match
	MOVE.L	4(A1),D1
	CMP.L	4(A0),D1
	BEQ.S	$30		;Found match
$20	ADDA.W	#32.,A1
	ADDQ.W	#1,D3
	CMP.W	#16.,D3
	BLT	$10		;Try another name
	MOVE.B	#1,WS_ERR	;Set up failure code
	BRA	WDEXIT

$30	OR.B	D3,WDRIVE	;Put partition into subdevice number
	LSL.W	#2,D3		;Partition * 4
	LEA	400H,A0
	MOVE.W	0(A0,D3.W),WI_BASE ;Base of partition
	MOVE.W	2(A0,D3.W),WI_TOP  ;Top of partition
	
	MOVE.B	502.(A0),WI_SPT
	MOVE.B	503.(A0),WI_HEADS
	MOVE.W	504.(A0),WI_BPS
	MOVE.W	506.(A0),WI_LOWC
	MOVE.W	508.(A0),WI_HIGHC
	MOVE.W	510.(A0),WI_STPCT
	
	ADDA.W	#64.,A0		;Move bad track map into place
	LEA	WI_BTTBL,A1
	MOVEQ	#32.-1,D0
$40	MOVE.L	(A0)+,(A1)+
	DBF	D0,$40
	
	BRA	WDEXIT
	

.PAGE
;****************************************************************************
;
;	Winchester Bootstrap
;
;	Calling sequence:
;	   MOVE.W	DRIVENUM,-(SP)
;	   MOVE.L	PARTNUM,-(SP)	;May be pointer to boot symbol
;
;****************************************************************************

WDBOOT
	MOVEA.L (SP)+,A6	;Save return address
	MOVE.B	4(SP),BOOTFLGS	;Set up bootstrap flags
	BSET	#1,BOOTFLGS	;Set up Winchester flag
	CLR.B	4(SP)		;Clear high byte of device number
	BSR	SETTRAP		;Set up default TRAP vectors
	MOVE	#2700H,SR	;Make sure interrupts are disabled
	MOVE.B	#25H,TERM_C	;Turn on transmit
	CLR.B	BUGBIOS		;Disable BIOS I/O for Debugger
	BSR	TERMCRLF
	LEA	MSG31,A0	;Output "Booting from Hard Drive"
	BSR	TERMTEXT
	BSR	TERMCRLF
	BSR	WSELECT		;Select the drive
	BNE.S	$40		;Found error
	CLR.L	-(SP)		;Bootstrap is at block zero
	MOVEA.W #400H,A0	;Transfer size and address are 1K
	MOVE.L	A0,-(SP)	;Address
	MOVE.L	A0,-(SP)	;Size
	BSR	RDCHAN9		;Read in Bootstrap
	BNE.S	$10		;Read failed
	MOVEA.W #400H,A0
	CMPI.W	#424FH,(A0)+	;Check for special "BOOT" value
	BNE.S	$30		;Not a BOOT routine
	CMPI.W	#4F54H,(A0)+
	BNE.S	$30		;Not a BOOT routine
	MOVEQ	#0,D0		;Pass up the subdevice number
	MOVE.B	WDRIVE,D0
	MOVE.W	D0,-(SP)
	MOVE.L	A6,-(SP)	;Set up return address
	JMP	(A0)		;Go to boot code
	
;	Couldn't read boot
$10	BSR	TERMCRLF
	MOVE.B	WS_ERR,D0	;Get error number
	NEG.B	D0
	LEA	MSG10,A0	;Printout "Drive ERROR "
	BSR	TERMTEXT
	BSR	TERMHEXB
$20	BSR	TERMCRLF
	JMP	(A6)		;Return from WDBOOT

;	Was not boot disk
$30	LEA	MSG11,A0	;Printout "Not a BOOT disk"
	BSR	TERMTEXT
	BRA	$20

;	Error selecting drive
$40	CMPI.B	#1,WS_ERR	;Check if could not find Name
	BNE.S	$10		;Normal drive error
	BSR	TERMCRLF
	LEA	MSG32,A0	;Printout "Could not find "
	BSR	TERMTEXT
	LEA	BOOTNAME,A0
	BSR	TERMTEXT
	BRA	$20
	

                                                                                                                                                                                                                                                                                                                                                                        