	.IF	LIST8
	.LIST
	.PAGE
	.ELSE
	.NOLIST
	.ENDC
;****************************************************************************
;
;	Floppy disk driver
;
;	File:	SAGE.PROM8.TEXT
;	Date:	23-Mar-83
;	Issue:	3
;
;	COPYRIGHT (c) 1982, 1983 SAGE Computer Technology
;	All Rights Reserved
;
;****************************************************************************
;
;	Release History:
;
;	1     13-Jun-82 Initial release.
;	2     10-Dec-82 Set up init for 8, 9, 10, and 16 SPT.  Put in test
;			mode.  Added common motor on control.
;	3     23-Mar-83 Initial SAGE IV release.
;
;****************************************************************************


.PAGE
;****************************************************************************
;
;	Floppy drive initialization
;
;	  Steps to initialize:
;	  1. Program parallel port.
;	  2. Reset 765 controller.
;	  3. Specify parameters to controller.
;	  4. Turn on drive select.
;	  5. Recalibrate drive.
;	  6. Wait 250 milliseconds for motor.
;	  7. Read ID field from track 0.
;	  8. Set up bytes/sector and sectors/track.
;
;	Registers modified: D0, D1, D2, A1
;
;	Stack depth: 42 bytes (including call).
;
;****************************************************************************

FDINIT
	CLR.B	FS_ERR		;Clear error code
	TST.B	FI_SIDE(A4)	;Check if drive equipped
	BEQ	$120		;Drive not equipped
	MOVE.W	D7,-(A7)	;Save working register
	MOVEQ	#2-1,D7		;Set up error pass counter
$10	MOVE.B	#0FH,F8255	;Strobe controller reset
	MOVE.B	#0,F8255	;Clear terminal count signal
	MOVE.B	#3,F8255	;Set up Drive Ready signal
	LEA	FC_SPEC,A1	;Specify parameters to controller
	MOVE.B	#0EH,F8255	;Turn off controller reset strobe
	BSR	FDCMD
	BNE.S	$35		;Unsuccessful command application

	MOVEQ	#6,D0		;Set up drive select for drive 0
	TST.B	FI_DRV(A4)
	BEQ.S	$30		;Was drive 0
	ADDQ.B	#2,D0		;Make 8 to select drive 1
$30	MOVE.B	D0,F8255	;Apply drive select 
	MOVE.B	#0AH,F8255	;Turn on motors

	MOVEQ	#-1,D0		;Delay
$32	DBF	D0,$32
	BTST	#0,C8255+2	;Check for interrupt
	BEQ.S	$33		;Not interrupt
	BSR	FDISTAT		;Get status but ignore it
	CLR.B	FS_ERR
	
$33	BSR	FDRECAL		;Recalibrate drive
	BEQ.S	$50		;Successful recalibrate
	CMPI.B	#3,FS_ERR
	BEQ.S	$40		;Exit if recalibrate failure
$35	DBF	D7,$10		;Retry once
$40	MOVE.W	(A7)+,D7	;Restore working register
	MOVEQ	#1,D0		;Set up NE condition
	RTS

	MOVEQ	#8,D0		;Default sectors per track
	BTST	#0,FT_TEST
	BNE.S	$95		;Test mode bypasses Read ID, forces 8 SPT
$50	MOVEQ	#DLY5,D0	;Set up 250 Millisecond delay
	SWAP	D0		;  for motor on.
$60	SUBQ.L	#1,D0
	BNE.S	$60		;Loop back for delay
	MOVE.B	#-1,FI_SPT(A4)	;Init to illegal value

$65	LEA	FC_RDID,A1	;Set up to read ID field
	BSR	FDCMD
	BNE.S	$35		;Unsuccessful command application

	MOVE.W	#DLY6-1,D2	;Set up 294 millisecond loop delay
$70	MOVE.B	FD_MSR,D0	;Get master status register from controller
	BTST	#7,D0		;Check for controller service request
	DBNE	D2,$70
	BNE.S	$80		;No timeout on read ID command
	MOVE.B	#2,F8255	;Set up Drive Not Ready
	MOVE.B	#4,FS_ERR	;Set up error code for no diskette
	BRA.S	$40		;Immediate exit

$80	BSR	FDNSTAT		;Read normal read completion status
	BNE.S	$35		;Retry once

	MOVE.B	FS_SECT,D0
	CMP.B	FI_SPT(A4),D0
	BEQ.S	$85		;Found match, done
	BLT	$65		;Back for more
	MOVE.B	D0,FI_SPT(A4)	;Update new max count
	BRA	$65		;Back for more
	
$85	CMPI.B	#8,D0
	BEQ.S	$95		;Was 8 sectors per track
	CMPI.B	#9,D0
	BEQ.S	$90		;Was 9 sectors per track
	CMPI.B	#16.,D0
	BEQ.S	$130		;Was 16 sectors per track
	CMPI.B	#10.,D0
	BNE.S	$110		;Was not 10 sectors per track
	
;	Process 10 sectors per track
	MOVEQ	#24.,D2		;Gap 3 for 10 SPT
	BRA.S	$100
	
;	Process 9 sectors per track
$90	MOVEQ	#32,D2		;Gap 3 for 9 SPT
	BRA.S	$100
	
;	Process 8 sectors per track
$95	MOVEQ	#42.,D2		;Gap 3 for 8 SPT
	
$100	CMPI.B	#2,FS_BPS
	BNE.S	$110		;Illegal bytes per sector
	MOVE.W	#512.,FI_BPS(A4)
$105	MOVE.B	D0,FI_SPT(A4)
	MOVE.B	D2,FI_GAP3(A4)	;Store Gap 3 value
	MOVE.W	(A7)+,D7	;Restore working register
	CLR.B	D0		;EQ indicates successful
	RTS

;	Set up illegal BPS error
$110	MOVE.B	#9,FS_ERR
	BRA	$40

;	Drive not equipped, set up bad address error
$120	MOVE.B	#11.,FS_ERR
	RTS

;	Process 16 sectors per track
$130	CMPI.B	#1,FS_BPS
	BNE	$110		;Illegal bytes per sector
	MOVE.W	#256.,FI_BPS(A4)
	MOVEQ	#32.,D2		;Gap 3 value
	BRA	$105

.PAGE
;****************************************************************************
;
;	Calculate current floppy parameters.
;
;	  Cylinder address.
;	  Head address.
;	  Starting sector address.
;	  Last sector address.
;	  Transfer byte count.
;
;	Routine uses registers: D0, D1, & D2.
;
;	Stack depth: 4 bytes (including call).
;
;****************************************************************************

FDCALC
	TST.B	FI_SIDE(A4)	;See if drive is equipped
	BEQ.S	$30		;Drive not equipped
	CLR.L	D1		;Find sectors per block
	MOVE.W	#512.,D1
	DIVU	FI_BPS(A4),D1	;D1 = Sectors per block

	CLR.L	D2		;Find logical sector number on total disk
	MOVE.W	FT_LBN,D2
	MULU	D1,D2		;D2 = logical sector number

	CLR.L	D1		;Set up default head number
	MOVE.B	FI_SPT(A4),D1
	DIVU	D1,D2		;Form logical track number
	CLR.W	D1
	BTST	#0,FI_SIDE(A4)	;Check how many sides
	BNE.S	$10		;Single sided drive, Cylinder = Track
	LSR.W	#1,D2		;Form cylinder number
	ROXL.B	#1,D1		;Form head number
$10	MOVE.B	D1,FT_HEAD	;Save head address
	MOVE.B	D2,FT_CYL	;Save cylinder address
	CMP.B	FI_NCYL(A4),D2	;Check cylinder limit
	BGE.S	$30		;Address to big
	
	SWAP	D2		;Access sector number
	MOVE.B	FI_SPT(A4),D1
	SUB.B	D2,D1		;Number of sectors left in track
	MULU	FI_BPS(A4),D1	;Number of bytes left in track
	CMP.L	FT_LENG,D1	;Check how many bytes needed
	BLE.S	$20		;Use whole remainder of track
	MOVE.L	FT_LENG,D1	;Only need part of track
$20
	ADDQ.B	#1,D2
	MOVE.B	D2,FT_SSEC	;Save first sector number (one based)
	MOVE.W	D1,FT_TCTR	;Save byte count for this transfer
	CLR.B	D0		;EQ means success
	RTS

;	Address is out of range
$30	MOVE.B	#11.,FS_ERR	;Indicate error (NE)
	RTS

.PAGE
;****************************************************************************
;
;	Transfer Floppy data.
;
;	Routine parameters on stack:
;	  (last in - on top of stack)
;	  Drive number (0 or 1) (word)
;	  Number of bytes to transfer. (long word)
;	  Base memory address for transfer. (long word)
;	  Base logical diskette block number for transfer. (word)
;
;	Floppy error number is returned in D0 and condition flag is set
;	to NE if an error exists.
;
;	Registers modified: D0, D1, D2, D3, D4, D5, D7, A1.
;
;	Stack depth:  46 bytes (including call).
;
;****************************************************************************

FDREAD	CLR.B	FT_DIR		;Set up data direction for read
	BRA.S	FDTRAN

FDWRITE MOVE.B	#1,FT_DIR	;Set up data direction for write

FDTRAN	MOVEA.L (A7)+,A1	;Save return address for now
	LEA	FI_DRV0,A4	;Set up default drive pointer
	MOVE.W	(A7)+,D0	;Get drive number
	BEQ.S	$3		;Was drive 0
	LEA	FI_DRV1,A4	;Set up pointer for drive 1
$3	MOVE.L	(A7)+,FT_LENG	;Set up transfer length
	MOVE.L	(A7)+,FT_MEMA	;Set up memory buffer address
	MOVE.W	(A7)+,FT_LBN	;Set up logical block number
	MOVE.L	A1,-(A7)	;Put return address back on stack
	MOVEQ	#3,D7		;Set up retry count
	TST.W	FI_BPS(A4)	;See if already initialized
	BNE	$60		;Just turn on select
$5	BSR	FDINIT		;Initialize drive
	BNE	$40		;Trouble initializing
$10	TST.L	FT_LENG		;See if any bytes to transfer
	BEQ	$40		;Done with total read
	MOVE.B	#3,F8255	;Set up Drive Ready signal
	TST.B	FT_DIR		;Check which direction
	BEQ.S	$15		;Was read
	BTST	#1,C8255+2	;Check for write protect
	BEQ.S	$12		;No write protect
	MOVE.B	#12.,FS_ERR	;Signal write protect error
	BRA	$40		;Immediate exit

$12	MOVE.B	FI_NCYL(A4),D0	;Check if half way through cylinders
	LSR.B	#1,D0
	CMP.B	FT_CYL,D0
	BLE.S	$13		;Precompensation is required
	MOVE.B	#0DH,F8255	;Set up for no precompensation
	BRA.S	$15

$13	MOVE.B	#0CH,F8255	;Apply precompensation control

$15	BSR	FDCALC		;Calculate parameters
	BNE	$40		;Transfer is out of range
	BSR	FDSEEK		;Now seek the cylinder
	BNE.S	$20		;Had trouble seeking
	LEA	FC_GCMD,A1	;Set up command buffer
	MOVE.W	#945H,D0	;Set up write command
	TST.B	FT_DIR
	BNE.S	$17		;Was write command
	ADDQ.W	#1,D0		;Change to read command
$17	MOVE.W	D0,(A1)+	;Set up command
	MOVE.B	FT_HEAD,D0
	LSL.B	#2,D0
	MOVE.B	D0,(A1)+	;Set up head parameter
	MOVE.B	FT_CYL,(A1)+	;Cylinder
	MOVE.B	FT_HEAD,(A1)+	;Head
	MOVE.B	FT_SSEC,(A1)+	;Starting sector
	MOVE.W	FI_BPS(A4),D0	;Form code for BPS
	LSR.W	#8,D0
	MOVE.B	D0,(A1)+
	MOVE.B	FI_SPT(A4),(A1)+  ;EOT
	MOVE.B	FI_GAP3(A4),(A1)+ ;Gap 3
	MOVE.B	#0FFH,(A1)+	  ;DTL (unused here)
	LEA	FC_GCMD,A1	;Re-establish command address
	BSR	FDCMD		;Apply command
	BNE.S	$20		;Trouble applying command
	MOVEA.L FT_MEMA,A1	;Set up transfer address
	CLR.L	D1
	MOVE.W	FT_TCTR,D1	;Set up byte count
	MOVE.B	FT_DIR,D2	;Set up direction parameter
	BSR	FDLOAD		;Transfer floppy data
	BNE.S	$20		;Bad data transfer
	MOVE.W	#800.,D0
$18	DBF	D0,$18		;One millisecond delay before after write
				;  to prevent premature step pulse
	ADD.L	D1,FT_MEMA	;Update address
	SUB.L	D1,FT_LENG	;Update length
	DIVU	#512.,D1	;Calculate number of blocks
	ADD.W	D1,FT_LBN	;Update logical block number
	BRA	$10		;Back for more

;	Process failures
$20	BTST	#0,FT_TEST
	BNE.S	$55		;Ignore all errors in test mode
	SUBQ.B	#1,D7		;Check retry count
	BEQ.S	$40		;Give up
	MOVE.B	FS_ERR,D0
	CMPI.B	#1,D0
	BEQ	$5		;Try total reinit
	CMPI.B	#3,D0
	BEQ.S	$40		;Don't retry seek
	CMPI.B	#4,D0
	BNE	$10		;Not missing diskette, retry

$40	BTST	#0,FT_TEST
	BNE.S	$55		;Don't deselect in test mode
	MOVEQ	#7,D0		;Set up to deselect drive 0
	TST.B	FI_DRV(A4)
	BEQ.S	$50		;Was drive 0
	ADDQ.B	#2,D0		;Make for drive 1
$50	MOVE.B	D0,F8255	;Disable drive select
	MOVE.B	#0BH,F8255	;Turn off motors
$55	MOVE.B	FS_ERR,D0	;Check for errors
	RTS

;	Already initialized - just select drive
$60	BTST	#1,FT_TEST
	BNE	$10		;Dont need to select in test mode
	MOVEQ	#6,D0		;Set up select for drive 0
	TST.B	FI_DRV(A4)
	BEQ.S	$70		;Was drive 0
	ADDQ.B	#2,D0		;Make 0AH to select drive 1
$70	MOVE.B	D0,F8255	;Apply drive select
	MOVE.B	#0AH,F8255	;Turn on motors
	
	MOVEQ	#DLY5,D0	;Set up delay
	SWAP	D0
$80	SUBQ.L	#1,D0
	BNE.S	$80
	BRA	$10

.PAGE
;****************************************************************************
;
;	Floppy bootstrap
;
;	The drive number (0 or 1) is on the stack before the return address.
;
;	This routine attempts to read 1024 bytes from the selected diskette
;	(A4 pointer) into location 400H.  If the first four bytes are "BOOT"
;	then the routine is started by jumping to 404H.	 If the boot jump
;	is taken, the processor is still in supervisor mode and the return
;	address from FDBOOT is still on the system stack.
;
;	Registers modified:  D0, D1, D2, D3, D4, D5, D7, A0, A1. 
;
;	Stack depth:  50 bytes (including call)
;
;****************************************************************************

FDBOOT
	MOVE.B	4(A7),BOOTFLGS	;Set up bootstrap flags
	CLR.B	4(A7)		;Clear high byte of device number
$5	CLR.W	FI_DRV0+FI_BPS	;Force re-init of drives
	CLR.W	FI_DRV1+FI_BPS
	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	MSG19,A0	;Output "Booting from Floppy"
	BSR	TERMTEXT
	BSR	TERMCRLF
	CLR.W	-(A7)		;Bootstrap is at block 0
	MOVEA.W #400H,A0	;Transfer size and address are 1K
	MOVE.L	A0,-(A7)
	MOVE.L	A0,-(A7)
	MOVE.W	14.(A7),-(A7)	;Get drive number
	BSR	FDREAD		;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
	JMP	(A0)		;Go to boot code

;	Couldn't read boot
$10	BSR	TERMCRLF
	MOVE.B	FS_ERR,D0	;Get error number
	CMPI.B	#4,D0
	BEQ.S	$40		;Probably no diskette
	LEA	MSG10,A0	;Printout Drive ERROR
	BSR	TERMTEXT
	BSR	TERMHEXB
$20	LEA	MSG12,A0	;Printout " on drive "
	BSR	TERMTEXT
	MOVE.B	FI_DRV(A4),D0	;Printout drive number
	BSR	TERMDIGT
	BSR	TERMCRLF	;Printout carriage return & line feed
	MOVEA.L (A7)+,A0	;Get return address
	ADDQ.L	#2,A7		;Get rid of drive number
	JMP	(A0)		;Any return from boot is from failure

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

;	Diskette missing
$40	LEA	MSG20,A0	;Printout "Put in BOOT disk and press a key"
	BSR	TERMTEXT
	BSR	KEYBCH		;Get any character
	BSR	TERMCRLF
	CMPI.B	#"Q",D0
	BNE	$5		;Try again
	LEA	MSG21,A0	;Printout "Boot Aborted"
	BSR	TERMTEXT
	BRA.S	$20

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