	LIST	OFF
	LIST	NOCOND
FALSE	EQU	0
TRUE	EQU	NOT FALSE
INCLUD	EQU	FALSE
	LIST	ON
	IF	INCLUD EQ TRUE
	SUBTITLE	DCM MODULE
	ELSE
	TITLE	DISK CONTROLLER MODULE
	ENDIF
;*************************************************************
;
;   DISK CONTROLLER MODULE   (DCM)
;
; Algorithm property of: Jade Computer Products Inc.
;                        4901 W. Rosecrans Blvd.
;                        Hawthorne, CA    90250
;
; Ver.  2.2  for 8" drives by Girvin Herr
;
;   The disk controller module (DCM) resides internal to the 
; Jade Double D Disk Controller board. This program provides 
; a facility to read/write diskette sectors & format diskette 
; tracks (in single & double density). This DCM sets the 
; parameters for each drive during the "LOG-ON" operation. 
; The FORMAT program (not in this module) writes an ident-
; ification sector (0,0) which provides the needed information.
; If this identity sector is not present on the diskette, it 
; is assumed to be a standard 8" IBM 3740 format. This program
; contains a 6 word timing block which should be patched to 
; match the user's disk drives.
; This has normally been set for Shugart SA800/801 drives.
;
;*************************************************************
;
	FORM
;************************************************************
	IF	INCLUDE EQ FALSE

	ENTRY	DCMMOD,DBUFR
;
;************************************************************
	ENDIF
;
;   THE FOLLOWING IS A LIST OF THE INTERNAL I/O ADDRESS 
; ASSIGNMENTS.
; THESE PORTS AND CONTROLS CAN ONLY BE USED BY THE ONBOARD Z80.
;
;   CONTROLLER PORT ASSIGNMENTS:
;
BLSTS:	EQU	0	;BOARD STATUS PORT
BLCTL:	EQU	0	;BOARD CONTROL PORT
WDCMD:	EQU	4	;1791 COMMAND REGISTER
WDSTS:	EQU	4	;1791 STATUS REGISTER
WDTRK:	EQU	5	;1791 TRACK REGISTER
WDSEC:	EQU	6	;1791 SECTOR REGISTER
WDDTA:	EQU	7	;1791 DATA REGISTER
;
;   CONTROLLER FUNCTION ASSIGNMENTS
;
XPSTP:	EQU	8H	;ISSUE STEP PULSE
XPMTO:	EQU	10H	;MOTOR TURN OFF
XPIRR:	EQU	20H	;S100 INT-REQ RESET
XPMTX:	EQU	40H	;MOTOR TIME EXTEND
XPDSH:	EQU	80H	;DATA SYNC HOLD
;
; THE FOLLOWING ASSIGNS EACH BIT POSITION & FUNCTION OF THE
; BOARD CONTROL PORT (BLCTL).
;
;   BIT ASSIGNMENTS
;
BCDSA:	EQU	00000001B	;DRIVE SELECT A (2*0)
BCDSB:	EQU	00000010B	;DRIVE SELECT B (2*1)
BCDSE:	EQU	00000100B	;DRIVE SELECT ENABLE
BCEIA:	EQU	00001000B	;EIA SIGNAL LEVEL OUT
BCDDE:	EQU	00010000B	;DOUBLE DENSITY ENABLE
BCDAS:	EQU	00100000B	;DIRECTION (& SIDE)
BCPCA:	EQU	01000000B	;PRECOMP SELECT A
BCPCB:	EQU	10000000B	;PRECOMP SELECT B
;
;   FUNCTION ASSIGNMENTS
;
BCDSN:	EQU	BCDSA+BCDSB	;DRIVE # MASK
BCSDS:	EQU	0	;SINGLE DENSITY
BCDDS:	EQU	BCDDE	;DOUBLE DENSITY
BCPCH:	EQU	BCPCA	;PRECOMP. - HEAVY
BCPCM:	EQU	BCPCB	;PRECOMP. - MEDIUM
BCPCL:	EQU	BCPCA+BCPCB	;PRECOMP. - LIGHT
BCPCZ:	EQU	0	;PRECOMP. - OFF
;
;   THE FOLLOWING DEFINES EACH BIT & FUNCTION OF THE BOARD 
; STATUS PORT (BLSTS).
;
BSUS0:	EQU	00000001B	;USER SWITCH 0 = 179X DATA 
;				  INVERT "1"
BSUS1:	EQU	00000010B	;USER SWITCH 1 (NOT USED YET)
BSTST:	EQU	00000100B	;TEST MODE SWITCH
BSINT:	EQU	00001000B	;HOST INTERRUPT REQUEST
BSEIA:	EQU	00010000B	;EIA SIGNAL LEVEL INPUT
BSMOF:	EQU	00100000B	;MOTOR OFF INDICATOR
BSTSD:	EQU	01000000B	;TWO SIDED DRIVE FLAG
BSDCN:	EQU	10000000B	;DISK CHANGE INDICATOR
;
;   FOLLOWING IS A LIST OF COMMAND CODES ISSUED TO THE 179X 
; DISK CONTROLLER
;
DCHDL:	EQU	00011000B	;SEEK/LOAD HEAD
DCHDU:	EQU	00010000B	;SEEK/UNLOAD HEAD
DCRDS:	EQU	10000000B	;READ SECTOR
DCWRS:	EQU	10100000B	;WRITE SECTOR
DCWRT:	EQU	11110000B	;WRITE TRACK FORMAT
DCRDA:	EQU	11000000B	;READ TRACK ADDRESS
DCSTS:	EQU	11010000B	;SET TYPE 1 STATUS OR ABORT 
;				  CMD WITHOUT INT.
DCIFI:	EQU	11011000B	;FORCED INTERRUPT (NOT USED)
;
;  STATUS BIT DEFINITIONS:
;
;  TYPE I:
;
CSDNR:	EQU	10000000B	;DRIVE NOT READY
CSWRP:	EQU	01000000B	;WRITE PROTECTED
CSHLD:	EQU	00100000B	;HEAD LOADED
CSSKE:	EQU	00010000B	;SEEK ERROR
CSCRC:	EQU	00001000B	;CRC ERROR
CSTK0:	EQU	00000100B	;TRACK 0
CSINDX:	EQU	00000010B	;INDEX
CSBSY:	EQU	00000001B	;BUSY
;
;  TYPE II & III:
;
CSTYPE:	EQU	00100000B	;RECORD TYPE
CSWFLT:	EQU	00100000B	;WRITE FAULT
CSRNF:	EQU	00010000B	;RECORD NOT FOUND
CSLDE:	EQU	00000100B	;LOST DATA ERROR
CSDRQ:	EQU	00000010B	;DATA REQUEST
;
;   FOLLOWING CONTAINS ALL THE MASKS USED TO TEST THE 1791 
; STATUS CODE PORT WDSTS
;
DMRER:	EQU	10011101B	;READ ERROR TEST
DMWER:	EQU	11111101B	;WRITE ERROR TEST
DMFER:	EQU	11100100B	;FORMAT ERROR TEST
DMTK0:	EQU	00000100B	;TRACK 0 TEST
DMHDL:	EQU	00100000B	;HEAD LOAD TEST
DMDNR:	EQU	10000000B	;DRIVE NOT READY
DMLDE:	EQU	00000100B	;LOST DATA ERROR
;
;   BASE ADDR FOR DCM
;
BASE:	EQU	1000H	;BASE ADDR
;
;   MEMORY BANKS
;
BANK0:	EQU	BASE+0	;DEFINE BANK 0
BANKL:	EQU	400H	;BANK LENGTH
BANK1:	EQU	BANK0+BANKL
;
;   RESTART VECTORS
;
RST0:	EQU	BANK0+0
RST1:	EQU	BANK0+8H
RST2:	EQU	BANK0+10H
RST3:	EQU	BANK0+18H
RST4:	EQU	BANK0+20H
RST5:	EQU	BANK0+28H
RST6:	EQU	BANK0+30H
RST7:	EQU	BANK0+38H
;
;   INTERRUPT VECTORS
;
HRINT:	EQU	RST7		;MASKABLE
NMINT:	EQU	BANK0+66H	;NON-MASKABLE
;
;   I/O COMMUNICATION
;
IOBLK:	EQU	BANK0+370H	;I/O BLOCK BEGIN
TPSTK:	EQU	IOBLK+0	;TOP OF STACK
CMDBK:	EQU	IOBLK+0	;COMMAND BLOCK
BUFBG:	EQU	IOBLK+10H	;SECTOR BUFFER
FMTBG:	EQU	BANK1+300H	;FORMAT BUFFER
FMTPS:	EQU	FMTBG+8H	;FORMAT PROGRAM
;
;   TIMING CONSTANTS
;
TMRFC:	EQU	19H	;TIMING CONSTANT, 1ST PASS
TMRNC:	EQU	1CH	;TIMING CONSTANT, NORMAL PASS
;
;   RETRY VALUES
;
RTYSK:	EQU	5	;REPOSITION HEAD ON RETRY
RTYLS:	EQU	9D	;LAST REPEATED RETRY
;
	FORM
;*************************************************************
;
;   THE FOLLOWING AREA IS THE INITIAL START JUMP TABLE.
; THE 1ST JUMP IS EXECUTED WHEN THE ONBOARD Z80 IS RESET. 
; THE SECOND JUMP IS THE DCM ENTRY FROM A BOOTSTRAP LOADER. 
; THIS ENTRY ASSUMES DCM HAS BEEN LOADED INTO DD BANK 1 BY THE 
; LOADER ROUTINE. THE LAST 2 BYTES HOLD THE JUMP ADDRESS USED 
; BY RESTART INTERRUPT ROUTINE @ BANK 0 + 380H.
;
;
	IF	INCLUDE EQ FALSE
	DATA		;PUT IN DATA SEGMENT

	ELSE
	ORG	BASE
	ENDIF
START:
;
	JP	CLEAR 	;RESET & RE-INITIALIZE Z-80 REGS
	JP	INITB+BANKL	;INIT - BOOTSTRAPPED
HRVEC:	DW	XCUTE		;BUS INTERRUPT VECTOR
;
;   THIS SUBROUTINE IS THE ENTRY POINT FOR THE DISK CONTROLLER
; TIMING MODULE. THIS MODULE PROVIDES DELAYS WHICH ARE 
; MULTIPLES OF 100 us. THE CONTENTS OF DE DETERMINES THE TOTAL
; PERIOD. (DELAY=(DE)*100 us).
;
	LD	B,TMRFC		;SET CONSTANT
	DJNZ	$
	JP	TICKE		;GOTO TICK ENTRY
;
;   INITIALIZE Z-80 REGS AFTER RESET & HALT FOR CMD
;
CLEAR:	LD	SP,TPSTK
	IM	1
	LD	C,0	;IF NOT INVERTED DATA SELECT THEN 
;			  CONTINUE
	IN	A,BLSTS
	AND	BSUS0
	JR	NZ,STOP
	LD	C,0FFH		;ELSE SET UP INVERT MASK
STOP:	LD	IX,DTDED	;SET DRIVE TABLE PTR
	EI
	HALT
;
;   RESTART SPARES
;
	DS	RST7-$
;
;  MASKABLE INTERRUPT ROUTINE - EXECUTED WHEN RESTARTING THE 
; Z80 FROM A HALT. THE FUNCTIONS ARE; RESET THE DD INT REQ 
; FLOP, PUT THE INTERRUPTED ADDR IN DE & JUMP ADDR @ HRVEC.
;
	IN	A,XPIRR		;RESET INT REQ
	POP	DE		;PURGE INTERRUPTED ADDR
	LD	HL,(HRVEC)	;GET RETURN ADDR
	JP	(HL)
;
;   END OF SEQUENCE HALT - DURING THIS TIME, THE HOST SYSTEM 
; CAN SWITCH THE CONTROLLER MEMORY INTO THE S100 BUS FOR 
; STATUS CHECK, SETTING COMMAND BLOCK, & SECTOR DATA XFERS.
;
FETCH:	EI		;ENABLE INTERRUPT RESTART
	HALT
;
;   THIS GETS CONTROL AFTER THE DISK CONTROLLER IS INTERRUPTED
; FROM THE HALT CONDITION. IT BRANCHES TO THE INDIVIDUAL 
; COMMAND ROUTINES.
;
XCUTE:	CALL	EXSTS		;GET 179X'S ATTENTION FOR CMDS
	LD	A,(CBCMD)	;GET HOST CMD
	AND	MASK		;LIMIT OPTIONS
	ADD	A		;2*VALUE
	LD	D,0
	LD	E,A		;SET UP OFFSET
	LD	HL,CMDT		;SET TABLE PTR
	ADD	HL,DE
	LD	E,(HL)
	INC	HL
	LD	D,(HL)
	EX	DE,HL
	JP	(HL)		;GOTO COMMAND
;
CMDT:	EQU	$	;COMMAND TABLE
CM0A:	DW	LGON	;LOG-ON DRIVE
CM1A:	DW	READ	;READ SECTOR
CM2A:	DW	WRIT	;WRITE SECTOR
CM3A:	DW	FORM	;FORMAT TRACK
CM4A:	DW	ADDR	;READ ADDRESS
CM5A:	DW	SPAR	;SPARES
CM6A:	DW	SPAR
CM7A:	DW	IDLE	;BACKGROUND
MASK:	EQU	7	;COMMAND MASK
;
;   THIS IS THE NON-MASKABLE INTERRUPT ROUTINE
; UPON 1791 COMMAND TERMINATION, THE Z80 RECEIVES A NMI. THE 
; STATUS PORT IS INTERROGATED & SAVED (SVSTS). IY HAS RETURN 
; ADDR.
;
	DS	NMINT-$
;
WDINT:	IN	A,WDSTS		;GET 1791 STATUS & RESET INT.
	XOR	C
	LD	(SVSTS),A
	EX	(SP),IY		;PUT RETURN ADDR ON STACK
	RETN
;
;   REMAINDER OF TIMING SECTION FROM RESTART 1
;
TICKR:	LD	B,TMRNC		;SET NORMAL CONSTANT
	DJNZ	$
TICKE:	DEC	DE		;COUNT -1
	LD	A,D
	OR	E		;IF COUNT NOT 0 THEN REPEAT
	NOP
	NOP
	JR	NZ,TICKR
	RET			;ELSE RETURN
;
;   READ SECTOR COMMAND
;
READ:	CALL	SELECT		;SELECT DRIVE
	JP	NZ,FETCH	;IF DRIVE NOT READY THEN EXIT
	CALL	SEEK		;SEEK TRACK & SET CTLS
	CALL	RDSEC		;READ A SECTOR
	JP	FETCH		;GET NEXT COMMAND
;
;   WRITE SECTOR COMMAND
;
WRIT:	CALL	SELECT
	JP	NZ,FETCH
	CALL	SEEK
	CALL	WRSEC
	JP	FETCH
;
;   FORMAT TRACK COMMAND
;
FORM:	CALL	SELECT
	JP	NZ,FETCH
	LD	A,(CBSEC)	;GET FORMAT FLAGS
	LD	(IX+DVFLG),A	;RESET DRIVE FLAGS
	CALL	SEEK
	CALL	WRTRK		;WRITE DISK TRACK
	JP	FETCH
;
;   DRIVE LOG-ON COMMAND
;
LGON:	CALL	SELECT
	JP	NZ,FETCH
	XOR	A		;SET TRACK=0
	LD	(CBTRK),A
	INC	A		;SET SECTOR =1
	LD	(CBSEC),A
	CALL	SEEK
	JP	NZ,FETCH	;IF ERROR THEN EXIT
	CALL	RDSEC		;READ ID SECTOR
	CALL	LOGON		;LOG ON DISK DRIVE
	JP	FETCH
;
;  READ ADDRESS COMMAND
;
ADDR:	JP	FETCH		;NOT IMPLEMENTED
;
;   SPARE COMMAND
;
SPAR:	JP	FETCH
;
;   IDLE COMMAND
;
IDLE:	IN	A,BLSTS		;IF NO HOST INTERRUPT THEN WAIT
	AND	BSINT
	JR	Z,IDLE
	IN	A,XPIRR	   ;ELSE RESET INTERRUPT REQUEST & EXIT
	JP	FETCH
;
;   THIS SUBROUTINE IS RESPONSIBLE FOR SELECTING THE COMMAND 
; REQUESTED DRIVE #. BEFORE DRIVE SELECTION, THE DRIVE MOTOR 
; STATE IS TESTED AND IF NEEDED, THEY ARE TURNED ON. IX IS SET
; TO POINT TO THE NEW SELECTED DRIVE TABLE.
;
SELECT:	IN	A,BLSTS		;GET BOARD LEVEL STATUS
	AND	BSMOF		;IF MOTOR ON THEN CHECK DRIVE
	JR	Z,CKDV
	IN	A,XPMTX		;ELSE ISSUE MOTOR START
	LD	DE,(TMMTO)
	RST	8H
CKDV:	IN	A,XPMTX		;EXTEND MOTOR TIME
	LD	A,(SVDRV)	;INSURE 179X INTRQ ENABLED FOR
;				 LATER
	OR	BCDSE		;CMDS
	OUT	BLCTL,A
	LD	A,(CBDRV)	;IF THIS DRIVE = OLD DRIVE THEN
;				 OK
	CP	(IX+DVNBR)
	JR	Z,DVOK
	CALL	EXHDU		;ELSE UNLOAD HEAD,
	LD	A,(SVDRV)	;DESELECT CURRENT DRIVE,
	AND	[NOT BCDSE]
	OUT	BLCTL,A
	LD	A,(CBDRV)	;SELECT DESIRED DRIVE,
	AND	BCDSN
	OUT	BLCTL,A
	OR	BCDSE
	OUT	BLCTL,A
	LD	(SVDRV),A
	AND	BCDSN		;SELECT DRIVE TABLE FOR DRIVE
	LD	IX,DVTBL
	LD	DE,DVDES	;DRIVE TABLE ARRAY SIZE
NEXT:	DEC	A     ;IF DRIVE = 0 THEN EXIT WITH POINTER SET
	JP	M,SLED
	ADD	IX,DE	    ;ELSE POINT TO NEXT ARRAY & REPEAT
	JR	NEXT
;
SLED:	CALL	EXSTS		;SET FLAGS PER DRIVE READY
	AND	DMDNR
	LD	(CBSTS),A
DVOK:	RET	
;
;   HOMED SUBROUTINE STEPS THE DISK DRIVE HEAD OUTWARD UNTIL 
; TRACK 0 FLAG IS TRUE OR 255 STEPS HAVE BEEN ISSUED
;
HOMED:	LD	L,255D		;SET MAX COUNT
STEP:	CALL	EXSTS		;IF ON TRACK 0 THEN EXIT
	AND	DMTK0
	JR	NZ,EXIT
	DEC	L		;IF STEPS = 255 THEN ERROR
	JR	Z,EROR
	IN	A,XPSTP		;ISSUE STEP PULSE
	LD	DE,(TMSTP)	;SET DELAY
	RST	8H
	JR	STEP
;
;      DRIVE IS RESTORED
;
EXIT:	LD	DE,(TMALS)	;WAIT A BIT AFTER LAST STEP
	RST	8H
	LD	A,0		;SET COMPLETE FLAG
	LD	(IX+DVTRK),A	;SET TRACK VALUE
	AND	A		;SET RETURN FLAGS
	RET
;
;   TRACK 0 NOT FOUND
;
EROR:	LD	A,0FFH		;SET FAILURE FLAG
	AND	A
	RET
;
;   LOGON SUBROUTINE READS THE IDENTITY SECTOR FROM THE 
; DISKETTE AND MAKES THE NEEDED ENTRYS INTO THE DRIVE TABLE. 
; THE SECTOR DATA IS ALSO LEFT IN THE SECTOR BUFFER FOR BIOS 
; TO FINISH THE LOG-ON OPERATION.
;
LOGON:	LD	DE,JADEID	;SET STRING PTR
	LD	HL,IDLB	     ;SET SECTOR BUFFER PTR TO COMPARE
	LD	B,IDSZE		;SET ID LENGTH
CKJI:	LD	A,(DE)		;IF ID NOT=JADE THEN 3740
	CP	(HL)
	JR	NZ,I3740
	INC	HL		;ELSE INC PTRS
	INC	DE
	DJNZ	CKJI		;IF NOT DONE THEN REPEAT
	LD	A,(IDSPT)	;SET TRACK SECTOR COUNT
	LD	(IX+DVSPT),A
	LD	A,(IDSTG)	;SET STAGGER #
	LD	(IX+DVSTG),A
	LD	A,(IDFLG)	;SET SIDES & DENSITIES
	LD	(IX+DVFLG),A
	JP	FETCH
;
;      ASSUME 3740 FORMAT
;
I3740:	LD	A,26D		;SECTORS/TRK=26D
	LD	(IX+DVSPT),A
	LD	A,1		;STAGGER=1
	LD	(IX+DVSTG),A
	LD	A,IDFLD		;SIDE & DENSITIES FLAGS=0
	LD	(IX+DVFLG),A
	JP	FETCH
;
;   TRACK SEEK SUBROUTINE
;   EXIT - DENSITY & PRE-COMP CONTROLS SET
;
SEEK:	CALL	EXSTS	    ;IF HEAD ALREADY LOADED THE BYPASS
	AND	DMHDL
	JR	NZ,HLDD
	CALL	EXHDL		;ELSE LOAD HEAD
	LD	DE,(TMHLD)
	RST	8H
HLDD:	LD	A,(CBTRK)	;IF CURRENT TRACK=REQUESTED 
;				 TRACK THEN EXIT
	SUB	(IX+DVTRK)
	JR	NZ,DSET
	LD	A,(IX+DVCTL)	;ELSE GET PREVIOUS CTLS & 
;				 RETURN
	JP	EXITS
;
;      SET DIRECTION & STEP COUNT
;
DSET:	PUSH	AF
	LD	DE,(TMSAW)	;DELAY FOR STEP AFTER WRITE
	RST	8H
	POP	AF
	JR	C,SOUT		;CARRY=STEP OUT
SIN:	LD	L,A
	LD	A,(SVDRV)
	OR	BCDAS
	OUT	BLCTL,A
	JR	STEPS
;
SOUT:	NEG			;COMPLEMENT OFFSET
	JP	M,HOME
	LD	L,A
	LD	A,(SVDRV)
	OUT	BLCTL,A
STEPS:	IN	A,XPSTP		;ISSUE STEP PULSE
	LD	DE,(TMSTP)
	RST	8H
	DEC	L	     ;IF STEPS-1 NOT 0 THEN STEP AGAIN
	JR	NZ,STEPS
	LD	DE,(TMALS)	;ELSE EXTEND LAST PULSE
	RST	8H
;
;      TRACK SECTION DISTRIBUTE
;
	LD	A,(CBTRK)	;IF TRACK 0 THEN GOTO TRK0
	CP	1
	JR	C,TRK0
	JR	Z,TRK1		;ELSE IF TRACK 1 THEN GOTO TRK1
	CP	26D	      ;ELSE IF <TRACK 26 THEN GOTO OUTS
	JR	C,OUTS
	CP	52D	     ;ELSE IF <TRACK 52 THEN GOTO MIDS
	JR	C,MIDS
	JR	NC,INSD
;
;      TRACK 0
;
TRK0:	LD	A,(SVDRV)	;SET UP TO SET CONTROLS
	OR	BCSDS+BCPCL	;SGL DEN AND PRECOMP=LOW
	JR	CTLS
;
;      TRACK 1
;
TRK1:	BIT	1,(IX+DVFLG)	;IF DDEN THEN SET DDEN CTRLS
	LD	A,(SVDRV)
	JR	NZ,T1DD
	OR	BCSDS+BCPCL	;ELSE SET SDEN CTRLS
	JR	CTLS
;
T1DD:	OR	BCDDS+BCPCL
	JR	CTLS
;
;      OUTSIDE TRACKS
;
OUTS:	BIT	2,(IX+DVFLG)	;IF DDEN THEN SET DDEN CTRLS
	LD	A,(SVDRV)
	JR	NZ,OTDD
	OR	BCSDS+BCPCL	;ELSE SET SDEN CTRLS
	JR	CTLS
;
OTDD:	OR	BCDDS+BCPCL	;SET DDEN CTRLS
	JR	CTLS
;
;      MIDDLE TRACKS
;
MIDS:	BIT	2,(IX+DVFLG)	;IF DDEN THEN SET DDEN CTRLS
	LD	A,(SVDRV)
	JR	NZ,MDDD
	OR	BCSDS+BCPCL	;ELSE SET SDEN CTRLS
	JR	CTLS
;
MDDD:	OR	BCDDS+BCPCM	;DDEN AND PRECOMP = MEDIUM
	JR	CTLS
;
;      INSIDE TRACKS
;
INSD:	BIT	2,(IX+DVFLG)	;IF DDEN THEN SET DDEN CTRLS
	LD	A,(SVDRV)
	JR	NZ,INDD
	OR	BCSDS+BCPCL	;ELSE SET SDEN CTRLS
	JR	CTLS
;
INDD:	OR	BCDDS+BCPCH	;SET DDEN AND PRECOMP= HIGH
	JR	CTLS
;
;      SET CONTROLS
;
CTLS:	LD	(IX+DVCTL),A
EXITS:	OUT	BLCTL,A
TKVL:	LD	A,(CBTRK)	;SET REQUESTED TRACK
	LD	(IX+DVTRK),A
	XOR	C
	OUT	WDTRK,A		;SET TRACK REGISTER
	XOR	A		;SET Z FLAG
	RET
;
;      CALIBRATE TRACK #
;
HOME:	CALL	HOMED		;HOME SELECTED DRIVE
	JP	HLDD		;NOW SEEK TRACK
;
;   HEAD LOAD/UNLOAD SUBROUTINES
;
EXHDL:	POP	IY		;IY=RETURN ADDR
	IN	A,WDTRK	   ;PERFORM SEEK TO CURRENT TRACK WITH 
;			    HEAD LOAD
	OUT	WDDTA,A
	LD	A,DCHDL
	XOR	C
	OUT	WDCMD,A
	JR	$		;WAIT FOR INTERRUPT
;
EXHDU:	POP	IY
	IN	A,WDTRK
	OUT	WDDTA,A
	LD	A,DCHDU		;HEAD UNLOAD
	XOR	C
	OUT	WDCMD,A
	JR	$
;
;   GET STATUS SUBROUTINE RETURNS 1791 STATUS IN A
;
EXSTS:	LD	A,DCSTS	     ;OUTPUT SET STATUS COMMAND TO 1791
	XOR	C
	OUT	WDCMD,A
	EX	(SP),HL		;PAUSE
	EX	(SP),HL
	EX	(SP),HL
	EX	(SP),HL
	IN	A,WDSTS		;GET LATEST STATUS
	XOR	C
	RET
;
;   READ SECTOR SUBROUTINE INITIATES DISK XFER, SEVICES THE 
; CONTROLLER CHIP DURING DATA XFER, & TERMINATES OPERATION 
; WHEN FINISHED. ERROR DETECTION IS IMPLEMENTED & RETRIES ARE 
; EXECUTED IF DATA ERRORS ARE DETECTED.
;
RDSEC:	XOR	A		;0 ERROR COUNT
	LD	(ERRCT),A
	LD	A,(CBSEC)	;SET 1791 SECTOR REGISTER
	XOR	C
	OUT	WDSEC,A
RTRY:	LD	IY,NMI		;SET NMI VECTOR FOR RETURN
	LD	HL,(BUFST)	;SET SECTOR BUFFER PTR
	LD	A,DCRDS		;OUTPUT READ SECTOR COMMAND
	XOR	C
	OUT	WDCMD,A
	EX	(SP),HL
	EX	(SP),HL		;WAIT FOR 1791
	EX	(SP),HL
	EX	(SP),HL
REPT:	IN	A,XPDSH	     ;GENERATE "HOLD" UNTIL 179X READY
	IN	A,WDDTA		;XFER DATA TO BUFFER
	XOR	C
	LD	(HL),A
	INC	HL		;PTR +1
	JR	REPT
;
;   CHECK STATUS
;
NMI:	AND	DMRER		;IF NO ERRORS THEN RETURN
	LD	(CBSTS),A
	RET	Z
	CALL	CHKRT	   ;IF RETRYS NOT EXHAUSTED THEN RETRY
	JR	Z,RTRY
	RET			;ELSE RETURN WITH ERROR
;
;   WRITE SECTOR SUBROUTINE
;
WRSEC:	XOR	A		;ERROR COUNT =0
	LD	(ERRCT),A
	LD	A,(CBSEC)	;SET 1791 SECTOR REG
	XOR	C
	OUT	WDSEC,A
RTRYW:	LD	IY,NMIW		;SET RETURN ADDR
	LD	HL,(BUFST)	;SET SECTOR BUFFER PTR
	LD	A,DCWRS	   ;OUTPUT WRITE SECTOR COMMAND TO 1791
	XOR	C
	OUT	WDCMD,A
	EX	(SP),HL
	EX	(SP),HL
	EX	(SP),HL
	EX	(SP),HL
REPTW:	IN	A,XPDSH		;HOLD FOR DATA REQ
	LD	A,(HL)		;OUTPUT DATA TO 1791
	XOR	C
	OUT	WDDTA,A
	INC	HL
	JR	REPTW
;
NMIW:	AND	DMWER		;IF NO ERRORS THEN RETURN
	LD	(CBSTS),A
	RET	Z
	CALL	CHKRT	   ;IF RETRYS NOT EXHAUSTED THEN RETRY
	JR	Z,RTRYW
	RET			;ELSE RETURN WITH ERROR
;
;   WRITE TRACK SUBROUTINE FORMATS A TRACK
;
WRTRK:	LD	IY,NMIWT	;SET RETURN ADDR
	LD	A,DCWRT	    ;OUTPUT WRITE TRACK COMMAND TO 1791
	XOR	C
	OUT	WDCMD,A
	EX	(SP),HL		;WAIT FOR 1791
	EX	(SP),HL
	EX	(SP),HL
	EX	(SP),HL
	JP	FMTPS
;
NMIWT:	AND	DMFER		;SET ANY ERRORS
	LD	(CBSTS),A
	LD	(CWLNG),HL	;DISPLAY TRAIL BYTES
	RET
;
;   CHECK FOR RETRYS SUBROUTINE
;
CHKRT:	AND	DMDNR		;IF NOT READY THEN EXIT
	JR	NZ,EXITC
	LD	A,(CBMOD)	;IF NO RETRYS CHECK THEN EXIT
	AND	CMNRT
	JR	NZ,EXITC
	IN	A,XPMTX
	LD	A,(ERRCT)	;ERROR COUNT +1
	INC	A
	LD	(ERRCT),A
	CP	RTYSK	      ;IF NOT TRY SEEK THEN CHECK LAST
	JR	NZ,CKLS
	CALL	HOMED		;HOME SELECTED DRIVE
	JR	NZ,EXITC	;IF ERROR THEN EXIT
	CALL	SEEK		;RE-SEEK DESIRED TRACK
CKLS:	CP	RTYLS	  ;IF LAST RETRY THEN RETURN WITH ERROR
	JR	Z,STNZ
	LD	DE,(TMPLD)	;ELSE WAIT & RETURN WITH NO 
;				 ERRORS
	RST	8H
	XOR	A
	RET
;
STNZ:	INC	A	;SET NO RETRY FLAG (NZ)
EXITC:	RET
;
;   BUFFER PTRS
;
BUFST:	DW	BUFBG	;BUFFER START ADDR
ERRCT:	DB	0	;RETRY ERROR COUNTER
SVDRV:	DB	0	;BLCTL DRIVE BITS
SVSTS:	DB	0	;1791 STATUS SAVE
TMHLD:	DW	350D	;HEAD ENGAGE TIME
TMSTP:	DW	80D	;STEPPER INTERVAL
TMALS:	DW	80D	;AFTER LAST STEP
TMMTO:	DW	1	;MOTOR START UP
TMPLD:	DW	1200D	;PHASE LOCK RECOVERY
TMSAW:	DW	10D	;STEP AFTER WRITING
;
;   DISKETTE FORMAT LABEL
;
JADEID:	DB	'Jade DD '  	;DISKETTE ID LABLE
IDSZE:	EQU	$-JADEID	;LABEL LENGTH
IDLBL:	EQU	BUFBG+0		;ID SECTOR LABEL
IDBLK:	EQU	IDLBL+20H	;ID BLOCK AREA
IDSPT:	EQU	IDBLK+0		;SECTORS PER TRACK
IDSTG:	EQU	IDBLK+10H	;SECTOR STAGGER
IDFLG:	EQU	IDBLK+11H	;DISKETTE FLAGS
IDFLD:	EQU	00000000B	;3740 FLAGS
;
;   DRIVE TABLE ENTRIES
;
DVNBR:	EQU	0	;CURRENT DRIVE #
DVTRK:	EQU	1	;CURRENT TRACK #
DVSEC:	EQU	2	;CURRENT SECTOR #
DVSPT:	EQU	3	;SECTORS/TRACK
DVSTG:	EQU	4	;SECTOR STAGGER #
DVFLG:	EQU	5	;SIDE & DENSITY FLAGS
DVCTL:	EQU	6	;LAST CONTROLS USED
;
DVTBL:	EQU	$			;DRIVE TABLE
DTDE0:	DB	0,255D,0,0,0,DFDFL,0C4H	;DRIVE 0
DTDE1:	DB	1,255D,0,0,0,DFDFL,0C5H	;DRIVE 1
	DB	2,255D,0,0,0,DFDFL,0C6H	;DRIVE 2
	DB	3,255D,0,0,0,DFDFL,0C7H	;DRIVE 3
DTDED:	DB	4,255D,0,0,0,0,0	;DUMMY
DVDES:	EQU	DTDE1-DTDE0		;ENTRY SIZE
;
;FLAG BIT DEFINITIONS
;
DFT1D:	EQU	1		;TRK 1 DENSITY (1=DBL)
DFDTD:	EQU	2		;DATA TRKS DENSITY (1=DBL)
DFTSD:	EQU	3		;2 SIDED  (1=2 SIDES)
DFDFL:	EQU	DFT1D+DFT1D	;DEFAULT FLAGS
;
;   COMMAND BLOCK
;
	DS	CMDBK-$
;
CBCMD:	DB	0		;CONTROL COMMAND
CBDRV:	DB	0		;DRIVE #
CBTRK:	DB	0		;TRACK #
CBSEC:	DB	0		;SECTOR #
CBFFG:	DB	0		;FORMAT FLAGS
CBSPR:	DB	0		;UNASSIGNED
CBMOD:	DB	0		;MODE SELECTS
CBSTS:	DB	0		;CONTROLLER STATUS
CWLAD:	DW	0		;LOAD ADDR
CWLNG:	DW	0		;LOAD LENGTH
CMNRT:	EQU	10000000B	;NO RETRYS (=1)
;
;   INITIALIZATION RTN
;
	DS	BUFBG-$
INITB:	LD	BC,BANKL	;SET BYTE COUNT TO MOVE
	LD	DE,BANK0
	LD	HL,BANK1
	LDIR			;XFER DCM TO BANK 0 FROM LOAD
	JP	DOWN
;
DOWN:	LD	SP,TPSTK
	IM	1
	LD	C,0		;INIT 1791
	IN	A,BLSTS
	AND	BSUS0		;IF SW 1= OPEN THEN 1793
	JR	NZ,LDBLT
	LD	C,0FFH
LDBLT:	LD	IX,DTDED	;INIT DRIVE TABLE
	LD	A,2		;LOAD IN BIOS LOADER SECTOR
	LD	(CBSEC),A
	IN	A,XPMTX
	LD	HL,BUFBG	;SET RETURN TO EXECUT BLT
	PUSH	HL
	JP	RDSEC
;
;DBUFR	EQU	$
;
	END
