	IF	IODRIVERBODY
	PAGE	*** THE SD STORAGE DEMON DRIVER ***
*	DRIVES IMI7710 WITH 7711 INTELLIGENT CONTROLLER...
*	VIA A "VIA" (A WONDERFUL ROCKWELL PART)
*
; EQUATES FOR WINCHESTER DRIVER

WDCNBPS	EQU	512	; 512 BYTES PER SECTOR (TRANSFER)

	IFUND	IMI7711
IMI7711	EQU	0
	FIN
	IF	IMI7711
WDCNSPT	EQU	19000
	FIN

	IFUND	IMI5007
IMI5007	EQU	0
	FIN
	IF	IMI5007	mini-wini
WDCNSPT	EQU	10800
	FIN

	IFUND	WDCNSPT
WDCNSPT	EQU	20020	DEFAULT TO 7710C
	FIN
WDCNTPC	EQU	1
WDCNCYL	EQU	1
WDCFATAL	EQU	$80	; RETRY TYPE ERROR

WDCFORMAT	EQU	1	; FORMAT ENTIRE DISK COMMAND
WDCREADCMD	EQU	2	; CONTROL READ COMMAND
WDCWRITECMD	EQU	3	; CONTROL WRITE COMMAND

WDCRETRY	EQU	5	; FAILURE RETRY COUNT


*	WINCHESTER DISK CONTROLLER DCB DEFINITIONS
*
::	SET	*
	ORG	DSKINFO:SIZE	TACKS ON TO BOTTOM OF DISK INFO TABLE
WDCREADWRITE	RMB	1	0 IS READ, <>0 IS WRITE
WDCDRIVE	RMB	1	DRIVE NUMBER
WDCSIZE	EQU	*
	ORG	::
	PAGE
; BRANCH TABLE POINTED TO BY DCB AND USED BY SDOS

WDCDRIVER	FDB	WDCINIT	; ROUTINE TO CLEAR VIA SO NO INTERRUPTS
	FDB	WDCREAD	; READ SINGLE SECTOR
	FDB	WDCWRITE	; WRITE SINGLE SECTOR
	FDB	WDCWAITDONE
	FDB	ILLDEVICEOP	SDOS HANDLES ALL THE DISK STATUSES NECESSARY !
	FDB	WDCCONTROL	; DISMOUNT OR FORMAT COMMAND

WDCCONTROL	CMPA	#CC:DISMOUNTDISK
	BEQ	WDCOKRTS	B/ DISMOUNT, NOTHING SPECIAL NEEDED.
	CMPA	#CC:FORMAT
	BEQ	WDCFORMATX	B/ FORMAT OPERATION
	JMP	ILLDEVICEOP
WDCFORMATX	LDA	#WDCFORMAT	DO A "SECONDARY" FORMAT OPERATION
	LDX	DCBPOINTER
	STA	WDCREADWRITE,X
	LDA	#1	; SET RETRY COUNT AT 1
	BRA	WDCSETRETRY1

WDCWRITE	LDA	#WDCWRITECMD
	BRA	WDCOPSET

WDCREAD	LDA	#WDCREADCMD
WDCOPSET	LDX	DCBPOINTER
	STA	WDCREADWRITE,X	; SET THE OPERATION
	LDA	#WDCRETRY	; SET RETRY COUNT
WDCSETRETRY1 ; ENTRY POINT FOR WDCFORMATX
	STA	WDCRETRYCNT
	CLR	DCB:LASTERROR,X
	CLR	DCB:LASTERROR+1,X
	LDX	#WDCINTERFACE	; WAIT FOR INTERFACE FREE
	LDA	0,X
	BNE	WDCSETUP
	JSR	SDOS+SDOS:WAITEVENT
WDCSETUP	CLR	WDCINTERFACE	; SET INTERFACE BUSY
	LDX	DCBPOINTER
	STX	WDCDCBPOINTER	; INTERRUPTS SERVICE DCB ADDRESS
	CLR	DCB:DONEFLAG,X	; CLEAR DONE
	LDX	#0
	STX	WDCCONTINUEPC	; SET INTERRUPTS NO GOOD
	LDX	#WDCSTARTIO
	JSR	SDOS+SDOS:STARTIO	; ENTER INTERRUPTS SERVICE CODE
	LDX	DCBPOINTER	; IF FORMAT CONTROL CALL OPERATION
	LDA	WDCREADWRITE,X
	CMPA	#WDCFORMAT
	BEQ	WDCWAITDONE	B/ GO WAIT FOR FORMAT OPERATION COMPLETE
WDCOKRTS	OKRTS

WDCWAITDONE	LDX	DCBPOINTER	; WAIT FOR TRANSFER DONE
	LDA	DCB:DONEFLAG,X
	BNE	WDCWAIT1
	JSR	SDOS+SDOS:WAITEVENT
WDCWAIT1	LDX	DCBPOINTER
	LDX	DCB:LASTERROR,X
	BEQ	WDCOKRTS
	JMP	ERRETX
	OKRTS
	PAGE
* VIA REGISTER DEFINITIONS
	IFUND	CONRAC
CONRAC	EQU	0
	FIN
	IF	CONRAC
STORAGEDEMONVIA	EQU	$FAA0
	FIN
	IFUND	WAVEMATE
WAVEMATE	EQU	0
	FIN
	IF	WAVEMATE
STORAGEDEMONVIA	EQU	$FF40
	FIN
	IFUND	EXORCISOR
EXORCISOR	EQU	0
	FIN
	IF	EXORCISOR
STORAGEDEMONVIA	EQU	$E7F0
	FIN

	IF	CONRAC!WAVEMATE!EXORCISOR
VIAPCR	EQU	STORAGEDEMONVIA+$C	; CONTROL REGISTER
VIAIFR	EQU	VIAPCR+1	; INTERRUPT FLAG
VIAIER	EQU	VIAIFR+1	; INTERRUPT ENABLE

VIADRB	EQU	STORAGEDEMONVIA+$0	; DATA REGISTERS
VIADRA	EQU	VIADRB+1
VIADDRB	EQU	VIADRA+1
VIADDRA	EQU	VIADDRB+1	; DATA DIRECTION REGISTERS
VIAT1LL	EQU	VIADDRA+1
VIAT1CH	EQU	VIAT1LL+1	; INTERVAL TIMER HIGH BYTE
VIAT1LLA	EQU	VIAT1CH+1
VIAT1LH	EQU	VIAT1LLA+1

VIAACR	EQU	STORAGEDEMONVIA+$B	; AUXILIARY CONTROL REGISTER - USED FOR CLOCK
*
VIADRAF	EQU	STORAGEDEMONVIA+$F	; PORT A - NO HANDSHAKE CONTROL

	FIN
	IFUND	WMSERIES2000
WMSERIES2000	EQU	0
	FIN
	IF	WMSERIES2000	WITH ITS INVERTED I/O ADDRESS LINES (YUK!)
::	SET	*
STORAGEDEMONVIA	EQU	$FC20

	ORG	STORAGEDEMONVIA
VIADRAF	RMB	1
VIAIER	RMB	1	INTERRUPT ENABLE REGISTER
VIAIFR	RMB	1	INTERRUPT FLAG REGISTER
VIAPCR	RMB	1	PERIPHERAL CONTROL REGISTER
VIAACR	RMB	1	AUXILIARY CONTROL REGISTER
VIASR	RMB	1	SHIFT REGISTER
VIAT2CH	RMB	1	TIMER 2 CONTROL HIGH
VIAT2LL	RMB	1	TIMER 2 LOW LATCH
VIAT1LH	RMB	1	TIMER 1
VIAT1LLA	RMB	1	TIMER 1
VIAT1CH	RMB	1	TIMER 1 CONTROL HIGH
VIAT1LL	RMB	1	TIMER 1 LOW LATCH
VIADDRA	RMB	1	DATA DIRECTION REGISTER A
VIADDRB	RMB	1	DATA DIRECTION REGISTER B
VIADRA	RMB	1	DATA REGISTER A
VIADRB	RMB	1	DATA REGISTER B
	ORG	::
	FIN	WMSERIES2000
	PAGE
WDCRESET	CLR	VIADDRA	MAKE PA0 SIDE OF VIA BE AN "INPUT" PORT
	LDA	#%11011010	; WATCH FOR READY AND *BUSDIR= 1
	STA	VIAPCR	; VIA PROG CONTROL REG
	LDA	VIADRA	; ISSUE STROBE SO READY PULSE CAN BE SEEN
	LDX	#(20000*2)//8	; PULSE CB2 FOR 20Ms. AS PER 7711 RESET SPECIFICATION
WDCRESETLP	DEX		; WAIT LONG ENOUGH FOR PULSE...
	BNE	WDCRESETLP
	LDA	#%00010010	; RESET INTERRUPT BITS
	STA	VIAIFR	; ACK INTERRUPTS THAT MIGHT ACCIDENTALLY BE PENDING
	STA	VIAIER	; AND CLEAR THE INTERRUPT ENABLE
	LDA	#%11111010
	STA	VIAPCR	; STOP PULSE, LEAVE CA2 IN "PULSE ON R/W"
	OKRTS
	PAGE
; FEED THE WINCHESTER A COMMAND

WDCFORMSERVJ	JMP	WDCFORMSERV	; GO HANDLE "FORMAT" COMMAND

WDCREADSERVJ	JMP	WDCREADSERV	; GO DO READ SECTOR LOGIC

WDCSTARTIO	EQU	*	CONTROL TRANSFERS HERE TO START DISK I/O
WDCCMDFEED	CLI		; RE-ENABLE INTERRUPTS
	LDX	WDCDCBPOINTER
	INC	DSKINFO:OPSCOUNT+2,X
	BNE	WDCCMDFEED0
	INC	DSKINFO:OPSCOUNT+1,X
	BNE	WDCCMDFEED0
	INC	DSKINFO:OPSCOUNT,X
WDCCMDFEED0	JSR	WDCWAITAVAILABLE	; WAIT FOR COMMAND AND DATA BUS AVAILABLE
	LDX	WDCDCBPOINTER
	LDA	WDCREADWRITE,X	; COMMAND TYPE
	JSR	WDCOUTDATA	; OUTPUT COMMAND BYTE
	LDA	WDCDRIVE,X	; DRIVE SELECT
	JSR	WDCOUTDATA
	LDA	WDCREADWRITE,X	; CHECK IF FORMAT COMMAND
	CMPA	#WDCFORMAT
	BEQ	WDCFORMSERVJ	; B/ ALL FORMAT PARAMETERS SENT!
WDCCMDFEED1	LDX	DSKINFO:SECTORDB,X
	LDA	RDSI:LSN+2,X	; FEED LOW BYTE OF
	JSR	WDCOUTDATA	; DISK ADDRESS OUT
	LDA	RDSI:LSN+1,X	; AND HIGH BYTE LOGICAL DISK ADDRESS
	JSR	WDCOUTDATA
	LDX	WDCDCBPOINTER
	LDA	WDCREADWRITE,X
	CMPA	#WDCREADCMD
	BEQ	WDCREADSERVJ	; GO DO READ TRANSFER AND CHECK
	PAGE
; WRITE TRANSFER SECTION

WDCWRITESERV	; WRITE A SECTOR TO 7710
	JSR	WDCSET4TRANS	; SET X	= PAGE ADR
	LDA	#$FF	; SET VIA TO OUTPUT MODE (AND SET UP 255 CYCLE COUNTER)
	STA	VIADDRA	; SO AS TO OUTPUT A 512 BYTE SECTOR
WDCWRITEWAIT1ST	; WAIT FOR 1ST DATA REQUEST
	BITB	VIAIFR	FIRST DATA REQUEST ARRIVE ?
	BNE	WDCWRITELOOP	B/ YES, GIVE THE 7710 ITS DATA
	INX		NO, DELAY AWHILE (???? Us. MAX)
	DEX
	DECA		DOWN COUNT FUSE
	BNE	WDCWRITEWAIT1ST	B/ MORE TIME TO WAIT
	JMP	WDCQUIET1	FUSE EXPIRED, SO DO WE!

WDCWRITELOOP	; OUTPUT BYTES LOOP, OPTIMIZED FOR SPEED!
	LDX	WDCPOINTER	; GET POINTER TO NEXT BLOCK OF 8 BYTES
	LDA	,X	; FETCH BYTE TO FEED TO CONTROLLER
	BITB	VIAIFR	; IS 7710 READY FOR NEXT BYTE ?
	BNE	WDCWRITE0	B/ USUAL CASE, 7710 IS READY FOR ANOTHER
	BSR	WDCWRITEWAIT	SIGH... GO WAIT FOR 7710 TO BE READY
WDCWRITE0	STA	VIADRA	; OUTPUT DATA BYTE AND ISSUE STROBE
	LDA	1,X	; FETCH BYTE TO FEED TO CONTROLLER
	BITB	VIAIFR	; IS 7710 READY FOR NEXT BYTE ?
	BNE	WDCWRITE1	B/ USUAL CASE, 7710 IS READY FOR ANOTHER
	BSR	WDCWRITEWAIT	SIGH... GO WAIT FOR 7710 TO BE READY
WDCWRITE1	STA	VIADRA	; OUTPUT DATA BYTE AND ISSUE STROBE
	LDA	2,X	; FETCH BYTE TO FEED TO CONTROLLER
	BITB	VIAIFR	; IS 7710 READY FOR NEXT BYTE ?
	BNE	WDCWRITE2	B/ USUAL CASE, 7710 IS READY FOR ANOTHER
	BSR	WDCWRITEWAIT	SIGH... GO WAIT FOR 7710 TO BE READY
WDCWRITE2	STA	VIADRA	; OUTPUT DATA BYTE AND ISSUE STROBE
	LDA	3,X	; FETCH BYTE TO FEED TO CONTROLLER
	BITB	VIAIFR	; IS 7710 READY FOR NEXT BYTE ?
	BNE	WDCWRITE3	B/ USUAL CASE, 7710 IS READY FOR ANOTHER
	BSR	WDCWRITEWAIT	SIGH... GO WAIT FOR 7710 TO BE READY
WDCWRITE3	STA	VIADRA	; OUTPUT DATA BYTE AND ISSUE STROBE
	LDA	4,X	; FETCH BYTE TO FEED TO CONTROLLER
	BITB	VIAIFR	; IS 7710 READY FOR NEXT BYTE ?
	BNE	WDCWRITE4	B/ USUAL CASE, 7710 IS READY FOR ANOTHER
	BSR	WDCWRITEWAIT	SIGH... GO WAIT FOR 7710 TO BE READY
WDCWRITE4	STA	VIADRA	; OUTPUT DATA BYTE AND ISSUE STROBE
	LDA	5,X	; FETCH BYTE TO FEED TO CONTROLLER
	BITB	VIAIFR	; IS 7710 READY FOR NEXT BYTE ?
	BNE	WDCWRITE5	B/ USUAL CASE, 7710 IS READY FOR ANOTHER
	BSR	WDCWRITEWAIT	SIGH... GO WAIT FOR 7710 TO BE READY
WDCWRITE5	STA	VIADRA	; OUTPUT DATA BYTE AND ISSUE STROBE
	LDA	6,X	; FETCH BYTE TO FEED TO CONTROLLER
	BITB	VIAIFR	; IS 7710 READY FOR NEXT BYTE ?
	BNE	WDCWRITE6	B/ USUAL CASE, 7710 IS READY FOR ANOTHER
	BSR	WDCWRITEWAIT	SIGH... GO WAIT FOR 7710 TO BE READY
WDCWRITE6	STA	VIADRA	; OUTPUT DATA BYTE AND ISSUE STROBE
	LDA	7,X	; FETCH BYTE TO FEED TO CONTROLLER
	BITB	VIAIFR	; IS 7710 READY FOR NEXT BYTE ?
	BNE	WDCWRITE7	B/ USUAL CASE, 7710 IS READY FOR ANOTHER
	BSR	WDCWRITEWAIT	SIGH... GO WAIT FOR 7710 TO BE READY
WDCWRITE7	STA	VIADRA	; OUTPUT DATA BYTE AND ISSUE STROBE
	LDA	WDCPOINTER+1	ADVANCE POINTER BY 8 BYTES
	ADDA	#8
	STA	WDCPOINTER+1
	BCC	WDCWRITED	B/ UPPER HALF DOES NOT NEED MODIFICATION
	INC	WDCPOINTER	PROPAGATE CARRY TO UPPER HALF
WDCWRITED	DEC	WDCCOUNT	DOWN COUNT NUMBER OF 8 BYTE BLOCKS TO SEND
	BNE	WDCWRITELOOP	B/ MORE 8 BYTE BLOCKS TO WRITE
	CLR	VIADDRA	; MAKE VIA PORT AN INPUT PORT WHEN DONE
	BRA	WDCFORMSERV	GO WAIT FOR 7710 TO FINISH OPERATION
	PAGE
WDCWRITEWAIT	; WAIT FOR 7710 TO BE READY FOR NEXT BYTE
	PSHA		; SAVE THE DATA BYTE TO SEND
	CLRA		; SET TIMEOUT LIMIT IN (A)
WDCWRITEWAITLOOP	BITB	VIAIFR	; LOOK AGAIN
	BNE	WDCWRITEWAITEXIT	; B/ FINALLY, IS READY!
	DECA		DOWN COUNT FUSE
	BNE	WDCWRITEWAITLOOP	B/ SOME FUSE STILL LEFT
	INS		BANG! TIME'S UP...POP DATA BYTE TO BE SENT
WDCQUIETERR	; 7710 DID NOT RESPOND IN REASONABLE LENGTH OF TIME
	LEAS	2,S	POP RETURN ADDRESS
WDCQUIET1	; IMI DRIVE DID NOT RESPOND IN REASONABLE TIME
	JSR	WDCRESET	; MAYBE HITTING BELOW THE BELT WILL RE-SYNCH
	LDA	#%1001111	; PICK UP VERY FUNNY ERROR STATUS
	JMP	WDCFATAL0	; GO STORE ERROR AND RETRY

WDCWRITEWAITEXIT	PULA		; GET THE DATA BYTE BACK
	RTS

WDCFORMSERV	EQU	*
	JSR	WDCWAIT4INT	; GO START INTERRUPT FOR COMMAND DONE
	JSR	WDCINDATA	; CHECK DONE STATUS
	JSR	WDCPROCST	; GO CHECK STATUS RETURN IF OK
WDCDONE	EQU	*
	LDX	WDCDCBPOINTER
	INC	DCB:DONEFLAG,X	; SET DONE
	INC	WDCINTERFACE	; INTERFACE DONE
	JMP	SDOS+SDOS:RESCHEDULE
	PAGE
; READ TRANSFER SECTION

WDCREADSERV	JSR	WDCWAIT4INT	; WAIT FOR 7710 INTERRUPT ON READ COMPLETE
	JSR	WDCINDATA	; GET STATUS ON BUS
	JSR	WDCPROCST	; GO PROCESS STATUS RETRY IF NEEDED
	JSR	WDCSET4TRANS
WDCREADLOOP	; INPUT BYTES FOR SECTOR LOOP, OPTIMIZED FOR SPEED
	LDX	WDCPOINTER	; GET POINTER TO NEXT BLOCK OF 8 BYTES
	BITB	VIAIFR	; IS ANOTHER DATA BYTE READY ?
	BNE	WDCREAD0	B/ DATA IS READY
	BSR	WDCREADWAIT	; GO WAIT FOR 7710 READY WITH ANOTHER BYTE
WDCREAD0	LDA	VIADRA	; READ DATA AND ISSUE ACKNOWLEDGE PULSE
	STA	,X	; SAVE DATA IN SECTOR BUFFER
	BITB	VIAIFR	; IS ANOTHER DATA BYTE READY ?
	BNE	WDCREAD1	B/ DATA IS READY
	BSR	WDCREADWAIT	; GO WAIT FOR 7710 READY WITH ANOTHER BYTE
WDCREAD1	LDA	VIADRA	; READ DATA AND ISSUE ACKNOWLEDGE PULSE
	STA	1,X	; SAVE DATA IN SECTOR BUFFER
	BITB	VIAIFR	; IS ANOTHER DATA BYTE READY ?
	BNE	WDCREAD2	B/ DATA IS READY
	BSR	WDCREADWAIT	; GO WAIT FOR 7710 READY WITH ANOTHER BYTE
WDCREAD2	LDA	VIADRA	; READ DATA AND ISSUE ACKNOWLEDGE PULSE
	STA	2,X	; SAVE DATA IN SECTOR BUFFER
	BITB	VIAIFR	; IS ANOTHER DATA BYTE READY ?
	BNE	WDCREAD3	B/ DATA IS READY
	BSR	WDCREADWAIT	; GO WAIT FOR 7710 READY WITH ANOTHER BYTE
WDCREAD3	LDA	VIADRA	; READ DATA AND ISSUE ACKNOWLEDGE PULSE
	STA	3,X	; SAVE DATA IN SECTOR BUFFER
	BITB	VIAIFR	; IS ANOTHER DATA BYTE READY ?
	BNE	WDCREAD4	B/ DATA IS READY
	BSR	WDCREADWAIT	; GO WAIT FOR 7710 READY WITH ANOTHER BYTE
WDCREAD4	LDA	VIADRA	; READ DATA AND ISSUE ACKNOWLEDGE PULSE
	STA	4,X	; SAVE DATA IN SECTOR BUFFER
	BITB	VIAIFR	; IS ANOTHER DATA BYTE READY ?
	BNE	WDCREAD5	B/ DATA IS READY
	BSR	WDCREADWAIT	; GO WAIT FOR 7710 READY WITH ANOTHER BYTE
WDCREAD5	LDA	VIADRA	; READ DATA AND ISSUE ACKNOWLEDGE PULSE
	STA	5,X	; SAVE DATA IN SECTOR BUFFER
	BITB	VIAIFR	; IS ANOTHER DATA BYTE READY ?
	BNE	WDCREAD6	B/ DATA IS READY
	BSR	WDCREADWAIT	; GO WAIT FOR 7710 READY WITH ANOTHER BYTE
WDCREAD6	LDA	VIADRA	; READ DATA AND ISSUE ACKNOWLEDGE PULSE
	STA	6,X	; SAVE DATA IN SECTOR BUFFER
	BITB	VIAIFR	; IS ANOTHER DATA BYTE READY ?
	BNE	WDCREAD7	B/ DATA IS READY
	BSR	WDCREADWAIT	; GO WAIT FOR 7710 READY WITH ANOTHER BYTE
WDCREAD7	LDA	VIADRA	; READ DATA AND ISSUE ACKNOWLEDGE PULSE
	STA	7,X	; SAVE DATA IN SECTOR BUFFER
	LDA	WDCPOINTER+1	; ADVANCE BUFFER POINTER BY 8
	ADDA	#8
	STA	WDCPOINTER+1
	BCC	WDCREADD	B/ DON'T HAVE TO BUMP UPPER HALF
	INC	WDCPOINTER
WDCREADD	DEC	WDCCOUNT	DOWN COUNT # OF 8 BYTE BLOCKS TO SEND
	BNE	WDCREADLOOP
	JMP	WDCDONE	ALL DONE READING SECTOR !

WDCREADWAIT	; WAIT FOR 7710 TO BE READY TO GIVE US NEXT BYTE
	CLRA
WDCREADWAITLOOP	BITB	VIAIFR	; WAIT FOR READY SIGNAL
	BNE	WDCREADWAITRTS	B/ 7710 IS NOW READY
	DECA		TIMED OUT ?
	BNE	WDCREADWAITLOOP	B/ NOT YET
	JMP	WDCQUIETERR	TIMED OUT, SOMETHING'S WRONG!

WDCREADWAITRTS	RTS
	PAGE
*	WDCOUTDATA --- SEND (A) TO 7710 WHEN 7710 READY
*		USED ONLY FOR PARAMETER BYTES
*
WDCOUTDATA	EQU	*
	LDB	#$FF	; SELECT VIA MODE = OUTPUT
	STB	VIADDRA
	STA	VIADRAF	; OUTPUT THE DATA, DON'T ISSUE PULSE (YET)
	CLRA		; SET A LONG FUSE
WDCOUTDATAL	LDB	VIAIFR	; IS 7710 READY?
	BITB	#%00000010
	BNE	WDCOUTDATA1	; YES
	DECA		; NO, DOWN COUNT FUSE
	BNE	WDCOUTDATAL
	JMP	WDCQUIETERR

WDCOUTDATA1	EQU	*
	LDB	#%11111010	; WATCH FOR BUSDIR GOING LOW
	STB	VIAPCR
	LDB	#%00010010
	STB	VIAIFR	; SEE WDCWRITE1 FOR COMMENTS
	LDA	VIADRA	; ISSUE STROBE PULSE TO 7710
	CLR	VIADDRA	; RESTORE VIA PORT TO INPUT MODE FOR SAFETY
	RTS
	PAGE
*	WDCINDATA --- GET (A) FROM 7710 WHEN 7710 IS READY
*	USED ONLY TO READ STATUS FROM 7710
*	ASSERT: VIADDRA=0 HERE

WDCINDATA	EQU	*
	CLRA		; SET LONG FUSE
WDCINDATA0	LDB	VIAIFR	; IS 7710 READY WITH DATA?
	BITB	#%00000010
	BNE	WDCINDATA1
	DECA
	BNE	WDCINDATA0	; B/ SOME MORE TIME LEFT
	JMP	WDCQUIETERR

WDCINDATA1	EQU	*	; 7710 IS READY WITH DATA FOR US
	LDB	#%11101010	; WATCH FOR IFACTIVE GOING HIGH
	STB	VIAPCR
	IF	CONRAC	??????? WHY ??????
	JMP	*+3	BECAUSE IT MAKES IT WORK, THAT'S WHY...(?)
	FIN	CONRAC
	LDA	VIADRA	; GET STATUS, ACKNOWLEDGE 'READY' SIGNAL
WDCWAITRTS	RTS
	PAGE
*	WDCWAITAVAILABLE -- WAIT FOR 7710 READY
*
WDCWAITAVAILABLE	EQU	*
	IF	M6800
	LDX	#(2*2500//256)*(1000//(4+2+2+4+2+4))	= 2.5 SECONDS AT 2MHZ
	ELSE	(M6809)
	LDX	#(2*2500//256)*1000//(????))	= 2.5 SECONDS AT 2MHZ
	FIN
WDCWAITAVAILABLELOOP ; WAIT AT MOST 2.5 SECONDS FOR DRIVE TO BE READY
	LDB	VIAIFR
	ANDB	#%00010010	CHECK: IS 7710 READY AND *BUS.DIR HIGH ?
	CMPB	#%00010010	...?
	BEQ	WDCWAITRTS	; B/ 7710 IS READY
	DECA		NO, DOWN COUNT LOWER 8 BITS OF FUSE
	BNE	WDCWAITAVAILABLELOOP	B/ FUSE NOT BURNED UP
	DEX		DOWN COUNT UPPER 16 BITS OF FUSE
	BNE	WDCWAITAVAILABLELOOP
	LEAS	2,S	THROW RETURN ADDRESS AWAY
	JSR	WDCRESET	TRY TO GET DRIVE'S ATTENTION
	LDD	#ERR:DEVICENOTREADY	DECLARE DEVICE NOT READY
	JMP	WDCQUITWITHERR	GO STORE ERROR CODE IN DCB
	PAGE
WDCWAIT4INT	EQU	*	WAIT FOR "DONE" INTERRUPT
	PULD
	NOP		PREVENT WDC SELF INTERRUPT
	SEI
	STD	WDCCONTINUEPC	; SAVE WHERE TO GO ON CMD DONE INTERRUPT
	LDX	WDCDCBPOINTER
	LDA	WDCREADWRITE,X
	CMPA	#WDCFORMAT
	BNE	WDCWAIT4INT2	; B/ STANDARD 3 SEC WAIT
	LDX	#0	; FOREVER FOR FORMAT (TAKES 40 MINUTES ON 7710C)
	BRA	WDCWAIT4INT3

WDCWAIT4INT2	EQU	*
	LDX	#5*TICKSPERSECOND+NTIMEOUTBLOCKS
WDCWAIT4INT3	STX	WDCTIMEOUTCOUNT
	LDB	#%10010000	; SET VIA INTERRUPT ON *BUSDIR GOING HIGH
	STB	VIAIER
	LDA	VIAIFR	; IS DRIVE DONE WITH TRANSFER ?
	BITA	#%00010000	...?
	BNE	WDCINTERRUPT	B/ YES (THIS CODE HERE TO SIMPLIFY SINGLESTEPPING)
WDCINTUNEXPECTED	JMP	SDOS+SDOS:RTI	; EXIT INTERRUPT SERVICE

WDCINTERRUPT	LDX	#0
	STX	WDCTIMEOUTCOUNT	; CLEAR TIME OUT
	LDB	#%00010000	; KILL THE INTERRUPT ENABLE
	STB	VIAIER
	LDX	WDCCONTINUEPC
	LDD	#WDCINTUNEXPECTED	RESET WHERE TO GO IF INTERRUPT
	STD	WDCCONTINUEPC
	CLI		; RE ENABLE INTERRUPTS - SO FLOPPY AND RTC CAN WORK
	JMP	0,X	; RETURN TO CALLER
	PAGE
WDCPROCST	TSTA		PROCESS STATUS BITS
	BEQ	WDCPROCSTOKRTS	B/ NO TROUBLE AT ALL
	BSR	WDCSAVESTATUS	OOPS, HAD SOME KIND OF PROBLEM
	BITA	#WDCFATAL	WAS ERROR FATAL ?
	BNE	WDCFATALERR	B/ YES
WDCPROCSTOKRTS	RTS		NON-FATAL ERROR, CONTINUE

WDCFATAL0	BSR	WDCSAVESTATUS
	BRA	WDCFATAL2

WDCFATALERR	LEAS	2,S	; POP RETURN OFF STACK
WDCFATAL2	DEC	WDCRETRYCNT	; ALL 9 LIVES USED UP ?
	BEQ	WDCQUIT	; B/ YES, WE'RE DEAD
	LDA	WDCRETRYCNT	ON PENULTIMATE RETRY ?
	CMPA	#1
	BNE	JWDCCMDFEED	B/ NO, JUST SEND COMMANDS AGAIN
	JSR	WDCRESET	; ON LAST TRY, HIT BELOW THE BELT
JWDCCMDFEED	JMP	WDCCMDFEED

WDCSAVESTATUS	LDX	WDCDCBPOINTER	; SAVE ERROR STATUS
	LDX	DSKINFO:SECTORDB,X	SAVE RDSI:LSN AS DSKINFO:ERRLSN
	LDB	RDSI:LSN,X
	PSHD		SAVE ERROR STATUS BYTE, UPPER 8 BITS OF LSN
	LDD	RDSI:LSN+1,X
	LDX	WDCDCBPOINTER
	STD	DSKINFO:ERRLSN+1,X
	PULD		RESTORE ERROR STATUS BYTE, UPPER 8 BITS OF LSN
	STB	DSKINFO:ERRLSN,X
	LDB	WDCREADWRITE,X
	CMPB	#WDCREADCMD	IS THIS A READ OR A WRITE COMMAND ?
	BEQ	WDCSAVEREADSTATUS
	STA	DSKINFO:WRITEERRSTS,X	; LAST WRITE (OR FORMAT) ERROR STATUS
	INC	DSKINFO:WRITEERRCNT+1,X	; 2 BYTE ERROR COUNT
	BNE	WDCSAVEWRITESTATUS1
	INC	DSKINFO:WRITEERRCNT,X
WDCSAVEWRITESTATUS1
	RTS

WDCSAVEREADSTATUS	STA	DSKINFO:READERRSTS,X	; LOG LAST READ ERROR
	INC	DSKINFO:READERRCNT+1,X
	BNE	WDCSAVEREADSTATUS1
	INC	DSKINFO:READERRCNT,X
WDCSAVEREADSTATUS1
	RTS
	PAGE
WDCQUIT	CMPA	#%10011111	A TIMEOUT IN MIDDLE OF TRANSFER ?
	BEQ	WDCTIMEDOUT1	B/ YES, LET THE USER KNOW!
	CMPB	#WDCREADCMD
	BEQ	WDCQUITREAD
	LDD	#ERR:DISKWRITE
	BRA	WDCQUITWITHERR

WDCQUITREAD	LDD	#ERR:DISKREAD
WDCQUITWITHERR	LDX	WDCDCBPOINTER	JUST TO BE SAFE...
	STD	DCB:LASTERROR,X
	JMP	WDCDONE

WDCTIMEDOUT	EQU	*
WDCTIMEDOUT1	LDX	#WDCINTUNEXPECTED	REMEMBER THAT WE DON'T EXPECT AN INTERRUPT!
	STX	WDCCONTINUEPC
	JSR	WDCRESET	; HIT HIM SO MAYBE HE WILL WAKE UP
	LDD	#ERR:DEVICETIMEDOUT
	BRA	WDCQUITWITHERR

WDCSET4TRANS	LDA	#WDCNBPS/8	; SET NUMBER OF 8 BYTE BLOCKS TO TRANSFER
	STA	WDCCOUNT
	LDX	WDCDCBPOINTER
	LDX	DSKINFO:SECTORDB,X
	LDX	RDSI:SECTORBASE,X
	STX	WDCPOINTER	; SET UP POINTER TO 1ST BLOCK OF 8 TO MOVE
	LDB	#%00000010	; GET 'READY' LINE SENSE MASK
	RTS
	FIN	IODRIVERBODY
	IF	IODRIVERPOLL
	IF	USEDEMONASCLOCK
	LDA	VIAIFR	CHECK FOR CLOCK INTERRUPT FROM VIA
	ANDA	#%11000000	IRQ + CLOCK DONE ?
	CMPA	#%11000000	...?
	BNE	WDCPOLL1	B/ NO
	STA	VIAIFR	ACKNOWLEDGE THE CLOCK INTERRUPT
	LDA	#1	= 1/60TH SECOND
	JMP	SDOS+SDOS:CLOCKTICKED
WDCPOLL1	EQU	*
	FIN	USEDEMONASCLOCK
	LDA	VIAIFR	ACCEPT DISK INTERRUPT ONLY IF NO CLOCK INTERRUPT PENDING
	ANDA	#%11010000	MASK TO OBTAIN CLOCK AND DISK INT BITS
	CMPA	#%10010000	DISK ONLY ?
	BNE	WDCPOLLNEXT	B/ NO
	JMP	WDCINTERRUPT	YES, GO SERVICE DISK INTERRUPT
WDCPOLLNEXT	EQU	*
	FIN	IODRIVERPOLL
	IF	IODRIVERINIT
WDCINIT	LDX	#OKRTS	INITIALIZE 7710 INTELLIGENT CONTROLLER
	STX	WDCINIT	SO WE DON'T DO THIS MORE THAN ONCE!
	JMP	WDCRESET	INITIALIZE 7710 INTELLIGENT CONTROLLER
	IF	USEDEMONASCLOCK
CLOCKRESET
	LDD	#2*16666	ASSUME 2MHZ CPU
	STB	VIAT1LL	; SET INTERVAL IN LOW LATCH
	STA	VIAT1CH	; LOAD HIGH LATCH AND INTO COUNTER
	LDA	#%01000000
	STA	VIAACR	; SET CONTINUOUS INTERRUPTS FROM COUNTER
	LDA	#%11000000
	STA	VIAIER	; ENABLE INTERRUPT REQUEST FROM CLOCK
	OKRTS
	FIN	USEDEMONASCLOCK
	FIN	IODRIVERINIT
	IF	IODRIVERRAM
	PAGE	*** STORAGE DEMON WORKING RAM ***
WDCINTERFACE	FCB	1	; WDC CONTROLLER IS AVAILABLE
WDCDCBPOINTER	FDB	0	; CURRENT UNIT IN USE BY INTERRUPT ROUTINES
WDCCONTINUEPC	FDB	WDCINTUNEXPECTED	; WHERE TO GO WHEN TRANSFER DONE INTERRUPT
WDCCOUNT	FCB	0	; COUNTS # OF 8 BYTE BLOCKS TO XFER TO 7710
WDCPOINTER	FDB	0	; POINTER TO NEXT BLOCK OF 8 BYTES TO XFER
WDCRETRYCNT	FCB	0	; USED TO COUNT # OF READ/WRITE ATTEMPTS

WDC1DCB	FCB	1	DCB:DONEFLAG
	FDB	0	DCB:LASTERROR
	FDB	WDC1STR
	FDB	NEXTDISKDCB	DCB:NEXT
	FDB	WDCDRIVER	DCB:DRIVER
	FDB	WDCNBPS
	FDB	WDCNSPT	DSKINFO:NSPT
	FDB	WDCNTPC	DSKINFO:NTPC
	FDB	WDCNCYL	DSKINFO:NCYL
	RPT	WDC1DCB+DSKINFO:SIZE-*
	FCB	0
	FCB	0	WDCREADWRITE: 2 IS READ 3 IS WRITE ETC.
	FCB	1	DRIVE SELECT 1
WDC1STR	FCC	'WD1:'
	FCB	0
NEXTDISKDCB	SET	WDC1DCB
NDISKDCBS	SET	NDISKDCBS+1

WDC0DCB	FCB	1	DCB:DONEFLAG
	FDB	0	DCB:LASTERROR
	FDB	WDC0STR
	FDB	NEXTDISKDCB	DCB:NEXT
	FDB	WDCDRIVER	DCB:DRIVER
	FDB	WDCNBPS
	FDB	WDCNSPT	DSKINFO:NSPT
	FDB	WDCNTPC	DSKINFO:NTPC
	FDB	WDCNCYL	DSKINFO:NCYL
	RPT	WDC0DCB+DSKINFO:SIZE-*
	FCB	0
	FCB	0	WDCREADWRITE: CONTAINS DESIRED DISK OPCODE
	FCB	0	DRIVE 0
WDC0STR	FCC	'WD0:'
	FCB	0
NEXTDISKDCB	SET	WDC0DCB
NDISKDCBS	SET	NDISKDCBS+1

WDCTIMEOUTBLOCK	FDB	NEXTTIMEOUT
WDCTIMEOUTCOUNT	FDB	0
	FDB	WDCTIMEDOUT

*
NEXTTIMEOUT	SET	WDCTIMEOUTBLOCK
NTIMEOUTS	SET	NTIMEOUTS+1
	FIN	IODRIVERRAM
