	.IF	LIST9
	.LIST
	.PAGE
	.ELSE
	.NOLIST
	.ENDC
;****************************************************************************
;
;	Floppy disk driver
;
;	File:	SAGE.BIOS9.TEXT
;	Date:	23-Mar-83
;	Issue:	2
;
;
;	COPYRIGHT (c) 1982, 1983 SAGE Computer Technology
;	All Rights Reserved
;
;****************************************************************************
;
;	History:
;
;	1     13-Jun-82 Initial release.
;	1A     3-Sep-82 Removed init of ADDQ.L in floppy interrupt routine.
;	1B     8-Sep-82 Don't Read ID on format request.  Don't count
;			global retry on first recalibrate failure.
;	1C    13-Sep-82 Recalibrate both drives on controller reset.
;			Modified timeout to give error -98.
;	1D    26-Oct-82 Cleared D0 to insure proper timeout schedule in
;			FDINIT3.
;	1E     9-Dec-82 Revised drive motor control variables.
;	2     23-Mar-83 Initial SAGE IV release.
;
;****************************************************************************


.PAGE
;****************************************************************************
;
;	Seek/Recalibrate Interrupt
;	Read Drive Status Interrupt
;
;****************************************************************************

FDSKINT 
FDRSINT
	MOVE.B	#5,SI8255	;Turn on foreground interrupt
	BSET	#FGFLOP_B,FGTASKS+1 ;Set up floppy foreground flag
	MOVE.B	#4,F8255	;Disable floppy interrupt
	PEA	FDNOINT		;Set up for no floppy interrupts
	MOVE.L	(A7)+,A6_TRAP
	RTE


;****************************************************************************
;
;	Unexpected Floppy Interrupt
;
;****************************************************************************

FDNOINT
	MOVE.B	#4,F8255	;Disable floppy interrupt
	RTE


;****************************************************************************
;
;	Floppy Timeout Task (Foreground)
;
;****************************************************************************

FDTOUT	BTST	#7,FD_MSR	;Check for controller request
	BNE.S	$5		;Controller is ready
	MOVE.B	#-4,FS_ERR	;Set up no diskette (timeout)
	BRA.S	$10
	
$5	MOVE.B	#-98.,FS_ERR	;Set up probable controller detected error
$10	MOVE.B	#2,F8255	;Set up Drive Not Ready signal
	MOVE.B	#1,F8255	;Strobe terminal count
	MOVE.B	#0,F8255
	MOVE.B	#4,F8255	;Disable floppy interrupt
	BSET	#FGFLOP_B,FGTASKS+1 ;Set up floppy foreground flag
	RTS			;Done with this scheduled task


;****************************************************************************
;
;	Floppy routine delay timeout (Foreground)
;
;****************************************************************************

FDDLYTO BSET	#FGFLOP_B,FGTASKS+1 ;Set up foreground floppy flag
	RTS

.PAGE
;****************************************************************************
;
;	Floppy drive initialization
;
;	  Steps to initialize:
;	  1. Program parallel port.
;	  2. Reset 765 controller.
;	  3. Specify parameters to controller.
;	  4. Turn on motor.
;	  5. Turn on drive select.
;	  6. Recalibrate drive.
;	  7. Wait for motor up to speed.
;	  8. Read ID field from track 0.
;	  9. Set up bytes/sector and sectors/track.
;
;	On entry A4 points to drive area.
;
;	Registers modified D0, A0
;
;****************************************************************************

FDINIT
	MOVE.B	#2,FTINIT_P	;Set up error pass counter
	CLR.B	FS_ERR		;Clear error indicator
	PEA	FDDLYTO		;Set up floppy delay task
	LEA	FT_DLY+4,A0
	MOVE.L	(A7)+,(A0)
	PEA	FDTOUT		;Set up floppy timeout task address
	LEA	FT_SCHED+4,A0
	MOVE.L	(A7)+,(A0)
	MOVE.B	#3,F8255	;Set Drive Ready signal on
	MOVE.B	#0,F8255	;Make sure terminal count is off
	LEA	FI_DRV0+FI_DRV,A0 ;Set up drive numbers in drive tables
	CLR.B	(A0)
	LEA	FI_DRV1+FI_DRV,A0
	MOVE.B	#1,(A0)

;	Set up fixed part of floppy interrupt routine in RAM
	LEA	FDIOINT+12.,A0	;Set up address of floppy routine code
	MOVE.W	#5378H,(A0)+	;Set up SUBQW	#1,xxx.W
	MOVE.W	#FT_CTRB,(A0)+	;  with its address FT_CTRB
	MOVE.W	#6702H,(A0)+	;Set up BEQ  $10
	MOVE.W	#4E73H,(A0)+	;Set up RTE
	MOVE.W	#4EF9H,(A0)+	;Set up $10  JMP  xxx.L
	PEA	FDINTC
	MOVE.L	(A7)+,(A0)	;Set up target of JMP
	
	TST.B	FS_INIT		;Check if controller to be initialized
	BNE	$10		;Don't reinitialize
	LEA	FI_DRVMT,A0	;Disable possible schedules
	CLR.B	FI_MOTOR(A0)
	BSR	CSCHED
	MOVE.B	#4,F8255	;Disable floppy interrupt
	MOVE.B	#7,F8255	;Deselect drive 0
	MOVE.B	#9,F8255	;Deselect drive 1
	MOVE.B	#0BH,F8255	;Turn off 'Both Motors On' signal
	MOVE.B	#0FH,F8255	;Strobe controller reset
	LEA	FI_DRV0,A0	;Clear tables
	CLR.B	FI_SEL(A0)
	CLR.B	FI_RCAL(A0)	;Request recalibrate
	MOVE.W	FI_STEP(A0),D0	;Get drive parameters
	LEA	FI_DRV1,A0
	CLR.B	FI_SEL(A0)
	CLR.B	FI_RCAL(A0)	;Request recalibrate
	LEA	FC_GCMD,A0	;Specify parameters to controller
	MOVE.W	#303H,(A0)
	MOVE.W	D0,2(A0)
	MOVE.B	#0EH,F8255	;Turn off controller reset strobe
	BSR	FDCMD
	BNE	FDINIT5		;Unsuccessful command application
	MOVE.B	#1,FS_INIT	;Indicate initialized
	MOVEQ	#-1,D0		;Set up delay
$5	DBF	D0,$5
	BTST	#0,C8255+2	;Check for interrupt
	BEQ.S	$10		;No interrupt
	BSR	FDISTAT		;Get interrupt status
	CLR.B	FS_ERR		;Ignore interrupt status

$10	BSR	SELECT		;Turn on drive Select
	TST.B	FI_RCAL(A4)	;Check for recalibrate request
	BNE	FDINIT6		;Don't recalibrate
	LEA	FDINIT2,A0	;Set up return from recalibrate
	MOVE.L	A0,FTRCAL_A
	BRA	FDRECAL		;Now recalibrate the drive

;	Return from recalibrate
FDINIT2 TST.B	FI_IGNOR(A4)
	BNE.S	$10		;Ignore errors
	TST.B	FS_ERR		;Check for error from recalibrate
	BNE	FDINIT5		;Unsuccessful recalibrate
$10	MOVE.B	#1,FI_RCAL(A4)	;Set up recalibrated flag

;	Now check if motor is up to speed
	LEA	FI_DRVMT,A0	;Address motor control
	CMPI.B	#2,FI_MOTOR(A0) ;Check if motor is active
	BEQ.S	FDINIT3		;Motor is up to speed
	BSET	#0,FI_STREQ(A0) ;Set flag to continue with active motor
	LEA	FDINIT3,A0	;Set up Motor active transfer completion
	MOVE.L	A0,FT_CONT
	BRA	FDEXIT		;Exit the Floppy Foreground process
	

;	May be entered from above or via motor up to speed completion.
;	Set up Read ID process
FDINIT3 CMPI.B	#2,FT_DIR
	BEQ	FDINIT5		;Dont read ID if Formatting
	LEA	FDINIT4,A0	;Set up Read ID completion address
	MOVE.L	A0,FT_CONT
	LEA	FDRSINT,A0	;Set up interrupt to read drive status
	MOVE.L	A0,A6_TRAP
	LEA	FC_GCMD,A0	;Set up to read ID field
	MOVE.B	#2,(A0)
	MOVE.B	FI_MFM(A4),D0
	ADD.B	#0AH,D0
	MOVE.B	D0,1(A0)
	MOVE.B	FI_DRV(A4),2(A0)
	BSR	FDCMD
	BNE	FDINIT5		;Unsuccessful command application
	MOVE.B	#5,F8255	;Enable floppy controller interrupt
	LEA	FT_SCHED,A0	;Set up transfer timeout
	MOVEQ	#0,D0
	MOVE.W	#26240.,D0	;Allow 410 milliseconds
	MOVE.L	D0,8(A0)
	BSR	ESCHED		;Enter the schedule
	BRA	FDEXIT		;Get out of the floppy foreground


;	Entered from Read ID completion or Timeout on Read ID.
FDINIT4
	LEA	FT_SCHED,A0	;Cancel timeout routine
	BSR	CSCHED
	BSR	FDNSTAT		;Check status
	TST.B	FI_IGNOR(A4)
	BNE.S	FDINIT5		;Ignore errors
	MOVE.B	FS_ERR,D0
	BEQ.S	FDINIT5		;No error
	
;	Process read error, only local retry -5 to -8 errors
	CMPI.B	#-4,D0		;Check for No Diskette timeout
	BEQ.S	FDINIT5		;Found 'No Diskette' error

	CMPI.B	#-5,D0
	BHI.S	FDINIT5		;Just exit
	CMPI.B	#-9,D0
	BLS.S	FDINIT5		;Just exit
	SUBQ.B	#1,FTINIT_P
	BEQ.S	FDINIT5		;No local retries
	SUBQ.B	#1,FT_RTRY
	BEQ.S	FDINIT5		;No global retries
	CLR.B	FS_ERR		;Clear error indicator
	ADDQ.B	#1,FI_SOFTE(A4) ;Advance soft error count
	BRA	FDINIT3		;Set up another Read Drive Status


;	Return from FDINIT
FDINIT5 MOVEA.L FTINIT_A,A0
	JMP	(A0)

;	No recalibrate, just check if motor is up to speed
FDINIT6 LEA	FI_DRVMT,A0	;Address motor control
	CMPI.B	#2,FI_MOTOR(A0) ;Check if motor is active
	BEQ.S	FDINIT5		;Motor is up to speed
	BSET	#0,FI_STREQ(A0) ;Set flag to continue with active motor
	LEA	FDINIT5,A0	;Set up Motor active transfer completion
	MOVE.L	A0,FT_CONT
	BRA	FDEXIT		;Exit the Floppy Foreground process
	


.PAGE
;****************************************************************************
;
;	Recalibrate floppy drive
;
;	Registers modified: D0, A0
;
;****************************************************************************

FDRECAL
	MOVE.B	#2,FTRCAL_P	;Retry counter for recalibrate
	CLR.B	FI_CCYL(A4)	;Indicate current cylinder at 0

;	Retry entry point
FDRCAL1 CLR.B	FS_ERR		;Clear error flag
	LEA	FDRCAL2,A0	;Set up completion address
	MOVE.L	A0,FT_CONT
	LEA	FDSKINT,A0	;Set up seek/recalibrate interrupt
	MOVE.L	A0,A6_TRAP
	LEA	FC_GCMD,A0	;Load command address
	MOVE.W	#207H,(A0)	;Set up recalibrate command
	MOVE.B	FI_DRV(A4),2(A0)
	BSR	FDCMD		;Apply command
	BNE.S	FDRCAL3		;Problem with command, terminate attempt
	MOVE.B	#5,F8255	;Enable floppy controller interrupt
	LEA	FT_SCHED,A0	;Set up recalibrate timeout
	MOVEQ	#1,D0		;Allow 1 second
	SWAP	D0
	MOVE.L	D0,8(A0)
	BSR	ESCHED		;Enter the schedule
	BRA	FDEXIT		;Get out of the floppy foreground

;	Completion of recalibrate
FDRCAL2 LEA	FT_SCHED,A0	;Cancel the timeout schedule
	BSR	CSCHED
	BSR	FDISTAT		;Read interrupt status
	MOVE.B	FS_ERR,D0	;Check for errors
	BEQ.S	FDRCAL3		;Had successful completion
	
;	Had recalibrate error
	CMPI.B	#-3,D0		;Check for equipment check
	BNE.S	FDRCAL3		;Bypass retry for other errors
	SUBQ.B	#1,FTRCAL_P	;Check for retry
	BNE.S	FDRCAL1		;Recalibrate retry

FDRCAL3 MOVEA.L FTRCAL_A,A0	;Transfer to recalibrate completion address
	JMP	(A0)

.PAGE
;****************************************************************************
;
;	Floppy Drive Seek
;
;	Registers modified: none
;
;	Routine retries three times by recalibrating if a seek error occurs.
;
;****************************************************************************

FDSEEK
	CLR.B	FS_ERR		;Clear error indicator
	MOVE.B	FT_CYL,D0	;Get desired cylinder
	CMP.B	FI_CCYL(A4),D0	;See if there already
	BEQ	FDSEEK5		;Already there, nothing to do
	LEA	FDSEEK2,A0	;Set up continuation address
	MOVE.L	A0,FT_CONT
	LEA	FDSKINT,A0	;Set up Seek Interrupt address
	MOVE.L	A0,A6_TRAP
	LEA	FC_GCMD,A0	;Set up command buffer address
	MOVE.W	#30FH,(A0)	;Set up Seek command
	MOVE.B	FT_HEAD,D0
	LSL.B	#2,D0
	ADD.B	FI_DRV(A4),D0
	MOVE.B	D0,2(A0)
	MOVE.B	FT_CYL,D0	;Set up cylinder parameter
	TST.B	FI_DBSTP(A4)	;Check for double stepping
	BEQ.S	$10		;Not double stepping
	ADD.B	FT_CYL,D0	;Double the cylinder number
$10	MOVE.B	D0,3(A0)	;Store cylinder number
	BSR	FDCMD		;Apply command
	BNE.S	FDSEEK5		;Problem with command
	MOVE.B	#5,F8255	;Enable floppy controller interrupt
	LEA	FT_SCHED,A0	;Set up seek timeout
	MOVEQ	#1,D0		;Allow 1 second
	SWAP	D0
	MOVE.L	D0,8(A0)
	BSR	ESCHED		;Enter the schedule
	BRA	FDEXIT		;Get out of the floppy foreground

;	Seek completion entry
FDSEEK2 LEA	FT_SCHED,A0	;Cancel the timeout check
	BSR	CSCHED
	BSR	FDISTAT		;Read interrupt status
	TST.B	FI_IGNOR(A4)
	BNE.S	FDSEEK5		;Ignore errors
	TST.B	FS_ERR		;Check for seek error
	BNE.S	FDSEEK5		;Unsuccessful seek

;	Successful seek
	MOVE.B	FT_CYL,FI_CCYL(A4) ;Set up current cylinder address

FDSEEK5 MOVEA.L FTSEEK_A,A0	;Done with seek, take completion address
	JMP	(A0)

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