	PAGE	*** ICOM FLOPPY DRIVERS ***
	IFUND	NFLOPPIES
NFLOPPIES	EQU	2	THE STANDARD
	FIN	NFLOPPIES
*
*	PHYSICAL DISK DRIVERS STORAGE "DEFS"
*
::	SET	*
	ORG	DSKINFO:SIZE	TACKS ON TO BOTTOM OF DISK INFO TABLE
FDJMPINTAD	RMB	1	FOR JUMP OP CODE
FDINTSTATEAD	RMB	2	JUMP ADDRESS
FDREADWRITE	RMB	1	0 IS READ, <>0 IS WRITE
FDSEEKRETRY	RMB	1	NUMBER OF RE-SEEKS
FDRETRY	RMB	1	READ/WRITE RETRY COUNT
FDTARGETCYL	RMB	2	WHERE WE WANT TO BE
FDDRIVE	RMB	1	DRIVE NUMBER TO USE
FDCYL	RMB	2	CURRENT CYL
FDTRACK	RMB	2	DESIRED TRACK (?HOW DIFFERENT FROM TARGET CYL?)
FDSECTOR	RMB	1	GIMME THIS ONE
FDSKERRCT	RMB	2	SEEK ERROR COUNT
FDLSTSKERR	RMB	2	LAST SEEK STATUS IN ERROR
FDWERRCT	RMB	2	WRITE ERROR COUNT
FDLSTWERR	RMB	2	LAST WRITE ERROR STATUS
FDRERRCT	RMB	2	READ ERROR COUNT
FDLSTRERR	RMB	2	LAST READ STATUS IN ERROR
FDOPERCT3	RMB	1	OPERATION COUNT- BYTE 3
FDOPERCT2	RMB	1	OPERATION COUNT- BYTE 2
FDOPERCT1	RMB	1	OPERATION COUNT- BYTE 1
FDMAPALGORITHM	RMB	2
FDK1MODNSPT	RMB	1	SPIRALING CONSTANT MOD NSPT
FDK2MODNSPT	RMB	1	2*SC MOD NSPT
FDK4MODNSPT	RMB	1	4*SC MOD NSPT
FDK8MODNSPT	RMB	1	8*SC MOD NSPT
FDK16MODNSPT	RMB	1	16*SC MOD NSPT
FDK32MODNSPT	RMB	1	32*SC MOD NSPT
FDMAP	EQU	*	MAP FOR MAPPING
FDSIZE	EQU	*
	ORG	::
	PAGE
*
*	DISK INFO TABLE
*
*
	IF	NFLOPPIES=4
FD3DCB	FCB	1	DCB:DONEFLAG
	FDB	0	DCB:LASTERROR
	FDB	D3STR	DCB:NAME
	FDB	NEXTDISKDCB	DCB:NEXT
	FDB	FDDRIVER	DCB:DRIVER
	FDB	FDNBPS
	FDB	FDNSPT
	FDB	FDNTPC
	FDB	FDNCYL
	RPT	FD3DCB+DSKINFO:SIZE-*
	FCB	0
	JMP	DISKINTUNEXPECTED
	RPT	FD3DCB+FDDRIVE-*
	FCB	0
	FCB	3	FDDRIVE
	RPT	FD3DCB+FDMAP-*
	FCB	0
	RPT	FDNSPT
	FCB	*-(FD3DCB+FDMAP)
NEXTDISKDCB	SET	FD3DCB
NDISKDCBS	SET	NDISKDCBS+1
D3STR	FCC	"D3:"
	FCB	0
	FIN	NFLOPPIES=4
	IF	NFLOPPIES>=3
FD2DCB	FCB	1	DCB:DONEFLAG
	FDB	0	DCB:LASTERROR
	FDB	D2STR	DCB:NAME
	FDB	NEXTDISKDCB	DCB:NEXT
	FDB	FDDRIVER	DCB:DRIVER
	FDB	FDNBPS
	FDB	FDNSPT
	FDB	FDNTPC
	FDB	FDNCYL
	RPT	FD2DCB+DSKINFO:SIZE-*
	FCB	0
	JMP	DISKINTUNEXPECTED
	RPT	FD2DCB+FDDRIVE-*
	FCB	0
	FCB	2	FDDRIVE
	RPT	FD2DCB+FDMAP-*
	FCB	0
	RPT	FDNSPT
	FCB	*-(FD2DCB+FDMAP)
*
D2STR	FCC	"D2:"
	FCB	0
NEXTDISKDCB	SET	FD2DCB
NDISKDCBS	SET	NDISKDCBS+1
	FIN	NFLOPPIES>=3
FD1DCB	FCB	1
	FDB	0
	FDB	D1STR
	FDB	NEXTDISKDCB
	FDB	FDDRIVER
	FDB	FDNBPS	DSKINFO:NBPS
	FDB	FDNSPT	DSKINFO:NSPT
	FDB	FDNTPC	DSKINFO:NTPC
	FDB	FDNCYL	DSKINFO:NCYL
	RPT	FD1DCB+DSKINFO:SIZE-*
	FCB	0
	JMP	DISKINTUNEXPECTED
	RPT	FD1DCB+FDDRIVE-*
	FCB	0
	FCB	1
	RPT	FD1DCB+FDMAP-*
	FCB	0
	RPT	FDNSPT
	FCB	*-(FD1DCB+FDMAP)
NEXTDISKDCB	SET	FD1DCB
NDISKDCBS	SET	NDISKDCBS+1
D1STR	FCC	'D1:'
	FCB	0

FD0DCB	FCB	1	DCB:DONEFLAG
	FDB	0	DCB:LASTERROR
	FDB	D0STR	DCB:NAME
	FDB	NEXTDISKDCB	DCB:NEXT
	FDB	FDDRIVER	DCB:DRIVER
	FDB	FDNBPS	DSKINFO:NBPS
	FDB	FDNSPT	DSKINFO:NSPT
	FDB	FDNTPC	DSKINFO:NTPC
	FDB	FDNCYL	DSKINFO:NCYL
	RPT	FD0DCB+DSKINFO:SIZE-*
	FCB	0
	JMP	DISKINTUNEXPECTED
	RPT	FD0DCB+FDMAP-*
	FCB	0
	RPT	FDNSPT
	FCB	*-(FD0DCB+FDMAP)
NEXTDISKDCB	SET	FD0DCB
NDISKDCBS	SET	NDISKDCBS+1
D0STR	FCC	'D0:'
	FCB	0


FDTIMEOUTBLOCK	FDB	NEXTTIMEOUT	TIMEOUT BLOCK FOR ICOM FLOPPIES
FDTIMEOUTTICKS	FDB	0	FUSE LENGTH
	FDB	DISKTIMEOUT
NTIMEOUTS	SET	NTIMEOUTS+1
NEXTTIMEOUT	SET	FDTIMEOUTBLOCK

FDINTERFACECLEAR	FCB	1	<>0 --> CONTROLLER NOT BUSY
FDINTSTORAGEP	FDB	FD0DCB	POINTER TO DCB FOR INTERRUPT ROUTINES
LASTDRIVE	FCB	$FF	= DRIVE NUMBER OF LAST DRIVE SELECTED
	PAGE
FDDRIVER	FDB	FDRESTORE
	FDB	FDREAD
	FDB	FDWRITE
	FDB	FDWAITDONE
	FDB	FDSTATUS
	FDB	FDCONTROL

*
*	FDCONTROL -- CONTROL OPERATION ENTRY POINT FOR SECTOR I/O DRIVER
*
FDCONTROL	EQU	*
	CMPA	#CC:DISMOUNTDISK	SINCE SDOS PASSES THIS THRU
	BNE	FDCONTROL1	B/ ILLEGAL CONTROL OP
	OKRTS		I'M HAPPY...
FDCONTROL1	JMP	ILLDEVICEOP	GO BITCH
*
*	FDSTATUS-- HANDLE STATUS REQUEST
*
FDSTATUS	CMPA	#SC:ERRORSTATUS
	BEQ	FDERSTAT
	JMP	ILLDEVICEOP	; NO SUCH STATUS AVALIABLE

FDERSTAT	LDX	DCBPOINTER
	STX	FDSTATX
	JSR	SDOS+SDOS:CHECKRDLEN
	FDB	FDOPERCT1-FDSKERRCT+1
	LDX	SCBLK:RDBUF,X
	STX	FDRDBUFX
	LDAB	#(FDOPERCT1-FDSKERRCT+1)
FDSTATUSLP	LDX	FDSTATX
	LDAA	FDSKERRCT,X
	CLR	FDSKERRCT,X
	INX
	STX	FDSTATX
	LDX	FDRDBUFX
	STAA	0,X
	INX
	STX	FDRDBUFX
	DECB
	BNE	FDSTATUSLP
	OKRTS

FDSTATX	FDB	0
FDRDBUFX	FDB	0
	PAGE
*	FDREAD/WRITE -- START SINGLE SECTOR TRANSFER
*
FDWRITE	LDAA	#1
	SK1
FDREAD	CLRA
	JSR	FDSETUPDRIVE	GO SET UP ALL THE PARAMETERS IN THE DCB
	TST	FDINTERFACECLEAR	0=NO
	BNE	FDSTARTIO
	LDX	#FDINTERFACECLEAR
	JSR	SDOS+SDOS:WAITEVENT
FDSTARTIO	LDX	DCBPOINTER	NOW NOBODY'S USING DRIVE
	STX	FDINTSTORAGEP	SET UP POINTER FOR INTERRUPT ROUTINE
	CLR	DCB:DONEFLAG,X	KICK INTERRUPT ROUTINE INTO MOTION
	LDX	#DISKINTSTART
	JSR	SDOS+SDOS:STARTIO
	OKRTS
*
*	WAIT FOR I/O COMPLETE
*
FDWAITDONE	EQU	*
	LDAA	DCB:DONEFLAG,X	IS IT DONE?
	BNE	FDWAIT1	B/ YES
	JSR	SDOS+SDOS:WAITEVENT
	LDX	DCBPOINTER
FDWAIT1	LDX	DCB:LASTERROR,X
	BEQ	FDWAIT2	B/ NO ERRORS
	JMP	ERRETX
FDWAIT2	OKRTS
*
	PAGE
*
*	FDSETUPDRIVE -- SETS UP FDDRIVE TABLE FOR INTERRUPT DRIVEN TRANSFER
*
FDSETUPDRIVE	LDX	DCBPOINTER
	STAA	FDREADWRITE,X	SAVE THE READ/WRITE FLAG
	LDAB	#10
	STAB	FDRETRY,X	SAVE THE READ/WRITE RETRY COUNT
	LDAA	#4	SETUP SEEK RETRY COUNT
	STAA	FDSEEKRETRY,X
	CLR	DCB:LASTERROR,X	"NO ERRORS"
	CLR	DCB:LASTERROR+1,X
	LDAB	DSKINFO:MAPALGORITHM,X
	LDAA	DSKINFO:MAPALGORITHM+1,X
	CMPB	FDMAPALGORITHM,X
	BNE	FDSETUP1	B/ MAP HAS CHANGED
	CMPA	FDMAPALGORITHM+1,X
	BEQ	FDSETUP2	B/ MAP HAS NOT CHANGED
FDSETUP1	STAB	FDMAPALGORITHM,X
	STAA	FDMAPALGORITHM+1,X
*
BUILDMAP	STX	TEMPX
	NEGA
	LDAB	DSKINFO:NSPT+1,X	NUMBER OF TIMES TO DO THIS
BUILDMAP1	LDX	DCBPOINTER
	ADDA	DSKINFO:MAPALGORITHM+1,X
BUILDMAP2	BSR	MODULONSPT
	LDX	DCBPOINTER	SEE IF THIS SECTOR NUMBER
	DEX		ALREADY USED
BUILDMAP3	INX
	CPX	TEMPX
	BEQ	BUILDMAP4	B/ NOT USED, USE IT
	CMPA	FDMAP,X
	BNE	BUILDMAP3	B/ IT'S NOT THIS ONE, KEEP LOOKING
	INCA		OH WELL, LET'S BUMP IT AND TRY AGAIN
	BRA	BUILDMAP2
BUILDMAP4	STAA	FDMAP,X
	INX
	STX	TEMPX
	DECB		ARE WE DONE BUILDING THE MAP?
	BNE	BUILDMAP1	B/ NOPE
*
*	BUILD UP THE SPIRALING INFO
*
	LDX	DCBPOINTER
	LDAA	FDMAPALGORITHM,X
	BSR	MODULONSPT
	STAA	FDK1MODNSPT,X
	ASLA
	BSR	MODULONSPT
	STAA	FDK2MODNSPT,X
	ASLA
	BSR	MODULONSPT
	STAA	FDK4MODNSPT,X
	ASLA
	BSR	MODULONSPT
	STAA	FDK8MODNSPT,X
	ASLA
	BSR	MODULONSPT
	STAA	FDK16MODNSPT,X
*
FDSETUP2	LDX	DSKINFO:SECTORDB,X
	LDAA	RDSI:LSN,X	IS RDSI:LSN < DSKINFO:NLSNS ?
	PSHA
	LDAA	RDSI:LSN+1,X
	LDAB	RDSI:LSN+2,X
	LDX	DCBPOINTER
	SUBB	DSKINFO:NLSN+2,X	I.E., IS RDSI:LSN-DSKINFO:NLSNS < 0 ?
	SBCA	DSKINFO:NLSN+1,X
	PULA
	SBCA	DSKINFO:NLSN,X
	BCS	FDSETUP3	B/ LSN IS OK
	JSR	SDOS+SDOS:ERROR
	FDB	ERR:ILLLSN
	PAGE
MODULONSPTB	SUBB	#FDNSPT
	BCC	MODULONSPTB
	ADDB	#FDNSPT
	RTS
MODULONSPT	SUBA	#FDNSPT
	BCC	MODULONSPT
	ADDA	#FDNSPT
	RTS
*
*	COMPUTE TARGET CYLINDER AND SECTOR
*
FDSETUP3	LDX	DSKINFO:SECTORDB,X	FIND PARAMETERS
*
*	COMPUTE OFFSET FOR SPIRALING
*
	LDAB	RDSI:LSN+2,X
	LDAA	RDSI:LSN+1,X
	LDX	DCBPOINTER
DIVIDEBY26	CLR	FDTARGETCYL+1,X
	LSRA		/2
	RORB
	ROR	FDTARGETCYL+1,X	SAVE LSB OF LSN
	STAA	TEMPX
	STAB	TEMPX+1
	ASLB		*2
	ROLA
	ASLB		*4
	ROLA
	ASLB		*8
	ROLA
	ASLB		*16
	ROLA
	SUBB	TEMPX+1
	SBCA	TEMPX	*15
	STAA	TEMPX
	STAB	TEMPX+1
	ASLB		*2
	ROLA
	ADDB	TEMPX+1	*3
	ADCA	TEMPX
	STAA	TEMPX
	STAB	TEMPX+1
	ASLB		*2
	ROLA
	ASLB		*4
	ROLA
	ASLB		*8
	ROLA
	SUBB	TEMPX+1	*7
	SBCA	TEMPX
	ADDA	#8
	ANDA	#$F
	SUBA	#8
	NEGA
	NEGB
	SBCA	#0
	BEQ	DIVIDEBY26.2
DIVIDEBY26.1	INC	FDTARGETCYL+1,X	GOT QUOTIENT (ALMOST), COMPUTE REMAINDER
	ADDB	#315&$FF
	ADCA	#315/256
	ANDA	#$F	ONLY 12 BITS, PLEASE
	BNE	DIVIDEBY26.1
DIVIDEBY26.2	LDAA	FDTARGETCYL+1,X	ADD LSB OF LSN TO REMAINDER * 2
	ASLA
	ADCA	#0
	STAB	FDTARGETCYL+1,X
	LDAB	DCBPOINTER
	ADDA	DCBPOINTER+1
	ADCB	#0
	STAB	TEMPX
	STAA	TEMPX+1
	LDAB	FDTARGETCYL+1,X
	CLRA
	JSR	MODULONSPTB
	ASRB
	BCC	MAP1
	ADDA	FDK1MODNSPT,X
MAP1	ASRB
	BCC	MAP2
	ADDA	FDK2MODNSPT,X
MAP2	ASRB
	BCC	MAP3
	ADDA	FDK4MODNSPT,X
MAP3	ASRB
	BCC	MAP4
	ADDA	FDK8MODNSPT,X
MAP4	ASRB
	BCC	MAP5
	ADDA	FDK16MODNSPT,X
MAP5	LDX	TEMPX
	ADDA	FDMAP,X
	JSR	MODULONSPT
	LDX	DCBPOINTER
	STAA	FDSECTOR,X
	OKRTS
	PAGE	ICOM FLOPPY DISK INTERRUPT SERVICE ROUTINES
DISKINTSERVICE	LDAA	DKDID	CLEAR INTERRUPT
	CLI		I DON'T NEED THEM OFF
*
	LDX	FDINTSTORAGEP
	JMP	FDJMPINTAD,X
*
DISKINTSTART	CLI		SINCE THIS ISN'T TIME CRITICAL
	LDX	#10*TICKSPERSECOND+NTIMEOUTBLOCKS
	STX	FDTIMEOUTTICKS
	CLR	FDINTERFACECLEAR	SO TASKS KNOW INTERFACE IS BUSY!
SEEK	LDX	FDINTSTORAGEP
	LDAA	FDDRIVE,X	GET THE PHYSICAL DRIVE NUMBER
	LDAB	LASTDRIVE
	STAA	LASTDRIVE
	LDAA	FDTARGETCYL+1,X
	CMPB	LASTDRIVE
	BEQ	SEEK1	B/ DRIVE SAME, DON'T SELECT
	LDAB	LASTDRIVE
	ASRB		ASSERT: LASTDRIVE <= 3
	RORB
	RORB
	INCB		I WANT SECTOR 1 (NOT REALLY, BUT LIE)
	STAB	DKDOD
	LDAB	#$20
	STAB	DKCOD
	BRA	SEEK2
SEEK1	CMPA	FDCYL+1,X
	BNE	SEEK2
	JMP	SEEKDONE
	PAGE
SEEK2	STAA	DKDOD	STORE THE NEW DESTINATION CYL #
	JSR	BUMPOPCOUNT	COUNT # OPERATIONS PERFORMED
	CLR	FDCYL+1,X
	DEC	FDCYL+1,X	;REMEMBER WE DO NOT KNOW WHERE WE ARE?
	LDAA	#$10	LOAD TRACK NUMBER
	STAA	DKCOD
	LDAA	#$8
	JSR	ISSUECOMMAND	AND AWAY WE GO!
*	DON'T CHECK DDMARK
	BITA	#$8	(BECAUSE IBM DISKS COME PRE-WRITTEN WITH SOME!)
	BEQ	SEEKDONE	B/ OK
SEEK3	STAA	FDLSTSKERR+1,X	SAVE SEEK ERROR STATUS
	INC	FDSKERRCT+1,X	BUMP SEEK ERROR COUNT
	BNE	*+4
	INC	FDSKERRCT,X
	BSR	DISKABORT	KILL WHATEVER DISK IS DOING
	LDAA	#$C	RESTORE TO 0
	JSR	ISSUECOMMAND
	DEC	FDSEEKRETRY,X
	BEQ	DISKSERROR	B/ GIVE UP
*	CHECK FOR ERROR ON RESTORE!
	BITA	#$8
	BNE	SEEK3	 B/ DO IT AGAIN
	CLR	FDCYL+1,X	; FINALLY TO TRACK ZERO
	BRA	SEEK

DISKSERROR	LDAA	#ERR:DISKSEEK/256	CAUSE A SEEK ERROR
	LDAB	#ERR:DISKSEEK&$FF
	BRA	DISKERROR1
	PAGE
DISKRERROR	LDAA	#ERR:DISKREAD/256	CAUSE READ ERROR
	LDAB	#ERR:DISKREAD&$FF
	BRA	DISKERROR1	B/ IT'S A READ

DISKWERROR	LDAA	#ERR:DISKWRITE/256
	LDAB	#ERR:DISKWRITE&$FF
DISKERROR1	LDX	FDINTSTORAGEP
	STAA	DCB:LASTERROR,X
	STAB	DCB:LASTERROR+1,X
	CLR	LASTDRIVE	FORCE SEEK NEXT TIME DRIVE IS USED
	DEC	LASTDRIVE	(:FF <> ANY DRIVE)
	BSR	DISKABORT	KILL WHATEVER THE DISK IS DOING!
DISKDONE	LDX	FDINTSTORAGEP
	INC	DCB:DONEFLAG,X	SIGNAL "DISK DONE"
	INC	FDINTERFACECLEAR
DISKDONE1	LDAA	#DISKINTUNEXPECTED/256
	STAA	FDINTSTATEAD,X
	LDAA	#DISKINTUNEXPECTED&$FF
	STAA	FDINTSTATEAD+1,X
	JMP	SDOS+SDOS:RESCHEDULE
DISKINTUNEXPECTED	BSR	DISKABORT
	BRA	DISKDONE1
*
BUMPOPCOUNT	INC	FDOPERCT1,X	BUMP # OPERATIONS PERFORMED
	BNE	BUMPOPCOUNT1
	INC	FDOPERCT2,X
	BNE	BUMPOPCOUNT1
	INC	FDOPERCT3,X
BUMPOPCOUNT1	RTS
	PAGE
DISKABORT	LDAA	#$80	CLEAR DRIVE ELECTRONICS
	NOP		; PREVENT SPURIOUS "DONE" INTERRUPTS
	SEI
	STAA	DKCOD
	LDAA	LASTDRIVE
	ASRA		ASSERT: LASTDRIVE <= 3
	RORA
	RORA
	INCA		; I WANT SECTOR 1
	STAA	DKDOD
	LDAA	#$20
	STAA	DKCOD
	LDAA	DKDID	CLEAR SPURIOUS INTERRUPT
	CLI
	RTS

*
SEEKDONE	BSR	BUMPOPCOUNT	SINCE WE'RE NOW GOING TO READ OR WRITE
	LDX	FDINTSTORAGEP
	LDAA	FDTARGETCYL+1,X
	STAA	FDCYL,X
	LDAA	FDSECTOR,X
	LDAB	LASTDRIVE
	ANDB	#3
	ASRB
	RORB
	RORB
	ORAB	FDSECTOR,X
	INCB		OFFSET
	STAB	DKDOD
	LDAA	#$20	; DATA LINES SPECIFY UNIT & SECTOR
	STAA	DKCOD
	TST	FDREADWRITE,X
	BNE	DISKWRITE	B/ THIS IS A WRITE
	JMP	DISKREAD	B/ THIS IS A READ
	PAGE
DISKWRITE	EQU	*
	LDAA	DKDID	CHECK FOR WRITE PROTECT
	BITA	#$10	...?
	BEQ	DISKWRITE1	B/ NOPE
	BSR	BUMPWRITEERRORS
	LDAA	#ERR:DSKWRTPROT/256
	LDAB	#ERR:DSKWRTPROT&$FF
	JMP	DISKERROR1

DISKWRITE1	EQU	*	PROCEED WITH WRITE
	LDX	DSKINFO:SECTORDB,X
	LDX	RDSI:SECTORBASE,X
	LDAB	#FDNBPS
DISKWRITE2	LDAA	0,X
	INX
	STAA	DKDOD
	LDAA	#$30	; DATA LINES CONTAIN DATA FOR WRITE BUFFER
	STAA	DKCOD
	DECB
	BNE	DISKWRITE2
	LDX	FDINTSTORAGEP
	LDAA	#4
	JSR	ISSUECOMMAND	WRITE IT OUT!
	LDAA	#6
	JSR	ISSUECOMMAND	VERIFY CRC
	LDAA	DKDID	CRC ERROR OR DDMARK ?
	BITA	#$88	CHECK DDMARK SINCE WE WROTE IT ->WITHOUT<- ONE
	BNE	DISKWRITE4	B/ I/O ERROR
	JMP	DISKDONE	ALL IS OK

DISKWRITE4	BSR	BUMPWRITEERRORS	RECORD ERROR STATUS; BUMP COUNT
	BSR	DISKABORT
	LDX	FDINTSTORAGEP
	DEC	FDRETRY,X
	BNE	DISKWRITE5
	JMP	DISKWERROR
DISKWRITE5	EQU	*	DISK TRANSACTION ERROR OCCURRED
	JMP	DISKINTSTART	PLAY IT AGAIN, SAM!
*
BUMPWRITEERRORS	EQU	*
	STAA	FDLSTWERR+1,X	SAVE WRITE ERROR STATUS
	INC	FDWERRCT+1,X
	BNE	*+4
	INC	FDWERRCT,X
	RTS
	PAGE
ISSUECOMMAND	LDAB	DKDID	MAKE SURE DISK IS READY BEFORE ISSUING COMMAND
	BITB	#$20
	BEQ	ISSUECOMMAND1	B/ IT IS
	INS
	INS		POP RETURN ADDRESS OFF STACK
	LDAA	#ERR:DEVICENOTREADY/256
	LDAB	#ERR:DEVICENOTREADY&$FF
	JMP	DISKERROR1	GO CAUSE ERROR
ISSUECOMMAND1	NOP	; LET US FINISH STARTING DISK
* OPERATION BEFORE WE GET ANOTHER DISK INTERRUPT
	SEI
	STAA	DKCOD
WAITFORINTERRUPT	PULA
	PULB
	STAA	FDINTSTATEAD,X
	STAB	FDINTSTATEAD+1,X
DISKRTI	JMP	SDOS+SDOS:RTI
*
DISKTIMEOUT	LDX	FDINTSTORAGEP
	LDAA	DCB:DONEFLAG,X
	BNE	DISKRTI	B/ DISK IS DONE, GO AWAY
	JSR	DISKABORT	; STOP DISK
	LDAA	#ERR:DEVICETIMEDOUT/256
	LDAB	#ERR:DEVICETIMEDOUT&$FF
	JMP	DISKERROR1
*
DISKREAD4	STAA	FDLSTRERR+1,X	SAVE READ ERROR STATUS
	INC	FDRERRCT+1,X	COUNT # READ ERRORS
	BNE	*+4
	INC	FDRERRCT,X
	JSR	DISKABORT
	DEC	FDRETRY,X
	BNE	DISKWRITE5	B/ TRY AGAIN, FROM THE TOP!
	JMP	DISKRERROR	GIVE UP, CAUSE A READ ERROR

DISKREAD	LDAA	#2	READ
	JSR	ISSUECOMMAND
	BITA	#$8	CRC ERROR ???
	BNE	DISKREAD4	(DON'T CHECK DDMARK ON READ BECUZ OF IBM FORMAT!)
	LDX	DSKINFO:SECTORDB,X	GET MEMORY BUFFER ADDRESS TO (X)
	LDX	RDSI:SECTORBASE,X
	PAGE
*
*	SLURP HARDWARE BUFFER CONTENTS OUT INTO MEMORY BUFFER
*	USES OPTIMIZED LOOP TO COPY ONE BYTE EVERY 16.4 ODD MICROSECONDS
*
DISKREADX	EQU	$F9	WE'RE NOT WAVEMATE, SO THIS IS FREE!
	STX	DISKREADX	PAGE ZERO LOCATION USED FOR SPEED
	LDAA	#$3C	SET UP TO READ FIRST BYTE
	STAA	DKCOC	SET CB2 HIGH...
	LDAB	#$40	SO WE CAN READ FIRST BYTE...
	STAB	DKCOD	BEFORE WE CAUSE A "SHIFT DATA" OPERATION
	LDAA	DKDID	GET FIRST BUFFER BYTE
	STAA	0,X	AND STUFF INTO MEMORY BUFFER
	LDAA	#$2C	SET UP CB2 TO PULSE AFTER WRITE TO PIA
	STAA	DKCOC	EACH PULSE CAUSES A "SHIFT DATA" OPERATION
	JMP	DISKREADL1	JUMP INTO QUICK SLURP

DISKREADL	EQU	*	QUICK SLURP LOOP, READ 8 BYTES AT A CRACK
	LDX	DISKREADX	GET POINTER TO TARGET AREA OF 8 BYTES
	LDAA	DKDID	GET NEXT BYTE FROM HARDWARE BUFFER
	STAA	0,X	STORE INTO MEMORY BUFFER
DISKREADL1	EQU	*
	STAB	DKCOD	CAUSE A "SHIFT DATA" OPERATION
	LDAA	DKDID	GET NEXT BYTE FROM HARDWARE BUFFER
	STAA	1,X	STORE INTO MEMORY BUFFER
	STAB	DKCOD	CAUSE A "SHIFT DATA" OPERATION
	LDAA	DKDID	GET NEXT BYTE FROM HARDWARE BUFFER
	STAA	2,X	STORE INTO MEMORY BUFFER
	STAB	DKCOD	CAUSE A "SHIFT DATA" OPERATION
	LDAA	DKDID	GET NEXT BYTE FROM HARDWARE BUFFER
	STAA	3,X	STORE INTO MEMORY BUFFER
	STAB	DKCOD	CAUSE A "SHIFT DATA" OPERATION
	LDAA	DKDID	GET NEXT BYTE FROM HARDWARE BUFFER
	STAA	4,X	STORE INTO MEMORY BUFFER
	STAB	DKCOD	CAUSE A "SHIFT DATA" OPERATION
	LDAA	DKDID	GET NEXT BYTE FROM HARDWARE BUFFER
	STAA	5,X	STORE INTO MEMORY BUFFER
	STAB	DKCOD	CAUSE A "SHIFT DATA" OPERATION
	LDAA	DKDID	GET NEXT BYTE FROM HARDWARE BUFFER
	STAA	6,X	STORE INTO MEMORY BUFFER
	STAB	DKCOD	CAUSE A "SHIFT DATA" OPERATION
	LDAA	DKDID	GET NEXT BYTE FROM HARDWARE BUFFER
	STAA	7,X	STORE INTO MEMORY BUFFER
	STAB	DKCOD	CAUSE A "SHIFT DATA" OPERATION
	LDAA	DISKREADX+1	BUMP MEMORY BUFFER POINTER...
	ADDA	#8	BY # BYTES COPIED INTO BUFFER
	STAA	DISKREADX+1
	BITA	#FDNBPS-1	HARDWARE BUFFER EMPTIED ?
	BNE	DISKREADL	B/ NO, GO SLURP ANOTHER 8 BYTES
DISKDONEJ	JMP	DISKDONE
	PAGE
