DataMuseum.dk

Presents historical artifacts from the history of:

Christian Rovsing CR7, CR8 & CR16 CP/M

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Christian Rovsing CR7, CR8 & CR16 CP/M

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦f66f0fa9c⟧ TextFile

    Length: 18944 (0x4a00)
    Types: TextFile
    Names: »CR16MFD.ASM«

Derivation

└─⟦b445f10af⟧ Bits:30004389 CP/M Plus Source files
    └─ ⟦this⟧ »CR16MFD.ASM« 

TextFile


	TITLE 'CR16 MINI FLOPPY DISK I/O MODULE - DATE:840406'
	PAGE 43

;************************************************************************
;*	THE MFDIO MODULE						*
;*									*
;*	MINI FLOPPY FORMAT IS AS FOLLOWS:				*
;*									*
;*		77 TRACKS						*
;*		8 RECORDS PER TRACK					*
;*		TWO HEADS/SIDES						*
;*		512 BYTE RECORDS					*
;*		LOGICAL DRIVE G,H					*
;*									*
;************************************************************************

	MACLIB	PORTS			;

	MACLIB	CPM3			;

	MACLIB	Z80			;

	if ((hwconfig and cr16mfd) eq cr16mfd)

	PUBLIC	CR160DPH,cr161dph

	EXTRN	DSKTMR,MONCNT		;(BOOT)

	EXTRN	?XMOVE,?MOVE,MA3MIR	;(MOVE)
	EXTRN	?BNKSL

	EXTRN	@ADRV			;ABSOLUTE DRIVE NUMBER (8 BITS)
	EXTRN	@RDRV			;RELATIVE DRIVE NUMBER (8 BITS)
	EXTRN	@DMA			;DISK TRANSFER ADDRESS (16 BITS)
	EXTRN	@TRK			;DISK TRACK ADDRESS (16 BITS)
	EXTRN	@SECT			;DISK SECTOR ADDRESS (16 BITS)
;;	EXTRN	@CNT			;RECORD COUNT FOR MULTI SECTOR TRANSFER
	EXTRN	@DBNK			;DISK TRANSFER BANK (8 BITS)
	EXTRN	@CBNK			;CURRENT CPU BANK

	EXTRN	@ERMDE			;BDOS ERROR MODE

	EXTRN	?PDERR			;PRINT BIOS DISK ERRROR HEADER
	EXTRN	?PMSG			;PRINT MESSAGE UNTIL 0
	EXTRN	?PDEC			;
	EXTRN	?CONIN			;
	EXTRN	?WBOOT			;

;EXTENDED DISK PARAMETER HEADERS (XDPH'S)

	DSEG				;BANKED MEMORY

	dw	mfd$wr$trk
	dw	mfd$rd$trk
	DW	FORMAT			;
	DW	MFD$WRITE		;
	DW	MFD$READ		;
	DW	MFD$LOGIN		;
	DW	MFD$INIT0		;
	DB	0,0			;
CR160DPH:
	DPH	0,MFDDPB

	dw	mfd$wr$trk
	dw	mfd$rd$trk
	DW	FORMAT			;
	DW	MFD$WRITE		;
	DW	MFD$READ		;
	DW	MFD$LOGIN		;
	DW	MFD$INIT0		;
	DB	1,0			;
CR161DPH:
	DPH	0,MFDDPB

	CSEG				;COMMON MEMORY

MFDDPB:
	DPB	512,8,154,2048,64,1

	PAGE

	DSEG				;REST IS BANKED MEMORY

;************************************************************************
;*									*
;************************************************************************

MFD$LOGIN:
	RET

;************************************************************************
;*	THE BOOT ENTRY CALLS EACH INIT ROUTINE DURING THE COLD START	*
;*	AND PRIOR TO ANY OTHER DISK ACCESS,THE INIT ROUTINE PERFORMS	*
;*	ANY NECESSARY HARDWARE INIT SUCH AS SETTING UP THE CONTROLLER	*
;	AND INTERRUPT VECTORS.						*
;************************************************************************

MFD$INIT0:
	RET			;


;************************************************************************
;*	THE PARAMETERS FOR THE READ/WRITE ROUTINES ARE CONTAINED IN	*
;*	THE PUBLIC VARIABLES :@ADRV,@RDRV,@TRK,@SECT,@DMA,@CNT,@DBNK	*
;*									*
;*			INPUT :	<DE> = ADDRESS OF XDPH			*
;*									*
;*			OUTPUT:	 <A> = 00H ,NO ERROR			*
;*				 <A> = 01H ,PERMANENT ERROR		*
;*									*
;************************************************************************

MFD$READ:
	mvi	a,1
	sta	@cnt
	LXI	H,RD$MSG	;POINT AT 'READ'
	MVI	A,C$MFD$RDMSEC	;1793 READ COMMAND
	MVI	B,C$DMA$READ	;Z80-DMA COMMAND
	JMP	RW$COMMON	;

MFD$WRITE:
	mvi	a,1
	sta	@cnt
	LXI	H,WR$MSG	;POINT AT 'WRITE'
	MVI	A,C$MFD$WRMSEC	;1793 WRITE COMMAND
	MVI	B,C$DMA$WRITE	;Z80-DMA COMMAND
	JMP	RW$COMMON	;

mfd$rd$trk:
	MVI	A,8		;SET NUMBER OF SECTORS
	STA	@CNT		;
	MVI	A,0		;SET START SECTOR
	STA	@SECT		;
	LXI	H,RD$MSG	;POINT AT 'READ'
	MVI	A,C$MFD$RDMSEC	;1793 READ COMMAND
	MVI	B,C$DMA$READ	;Z80-DMA COMMAND
	JMP	RW$COMMON	;

mfd$wr$trk:
	MVI	A,8		;SET NUMBER OF SECTORS
	STA	@CNT		;
	MVI	A,0		;SET START SECTOR
	STA	@SECT		;
	LXI	H,WR$MSG	;POINT AT 'WRITE'
	MVI	A,C$MFD$WRMSEC	;1793 WRITE COMMAND
	MVI	B,C$DMA$WRITE	;Z80-DMA COMMAND
	JMP	RW$COMMON	;

MFD$FORMAT:
	LXI	H,FM$MSG	;POINT AT 'FORMAT'
	MVI	A,C$MFD$FWRTRK	;1793 WRITE TRACK COMMAND
	MVI	B,C$DMA$WRITE	;Z80-DMA COMMAND
	JMP	RW$COMMON	;

RW$COMMON:
	SHLD	RW$NAME		;SAVE MESSAGE FOR ERRORS	
	STA	DISK$COMMAND	;SAVE 1793 COMMAND (FDCMD)
	MOV	A,B		;
	STA	DMA$COMMAND	;SAVE DMA DIRECTION CODE (DMCMD)
	XRA	A		;
	STA	DISK$STATUS	;RESET DISK STATUS
	LDA	@TRK		;
	CPI	77
	JNC	SIDE$ONE
	STA	FTRK
	XRA	A
	STA	FSIDE		;select side 0
	JMP	END$SIDE
SIDE$ONE:
	MOV	B,A		;
	MVI	A,153		;
	SUB	B		;
	STA	FTRK		;physical track = 153 - logical track
	MVI	A,1		;
	STA	FSIDE		;select side 1
END$SIDE:
	CALL	SETV		;SETUP UNIT,TRACK AND SECTOR
	ORA	A		;
	CZ	TEST		;FDIO OR FWRTTRK;READ/WRITE "FCNT","FSIZE" BYTE SECTORS
	STA	DISK$STATUS	;
	ORA	A
	RZ			;

RW$ERROR:
	LDA	@ERMDE		;SUPPRESS ERROR MESSAGE, IF BDOS IS RETURNING
	CPI	0FFH		;	ERRORS TO APPLICATION
	JZ	HARD$ERROR	;
	CALL	?PDERR		;PRINT BIOS DISK ERROR HEADER
	LHLD	RW$NAME		;
	CALL	?PMSG		;
	LDA	DISK$STATUS	;GET STATUS BYTE FROM LAST ERROR
	CPI	0FFH		;
	JZ	HARD$ERROR	;
	LXI	H,ERROR$TABLE	;
ERRM1:
	MOV	E,M		;GET NEXT MESSAGE ADDRESS
	INX	H		;
	MOV	D,M		;
	INX	H		;
	ADD	A		;SHIFT LEFT AND PUSH RESIDUAL BITS WITH STATUS
	PUSH	PSW		;
	XCHG			;PRINT MESSAGE ,SAVING TABLE POINTER
	CC	?PMSG		;
	XCHG			;
	POP	PSW		;IF ANY MORE BITS LEFT CONTINUE
	JNZ	ERRM1		;

	CALL	?CONIN		;GET RESPONSE
	CPI	'C'-040H	;IF CTL-C WARM BOOT
	PUSH	PSW
	CALL	HARD$ERROR
	POP	PSW
	JZ	?WBOOT		;
	
HARD$ERROR:
	DI
	XRA	A
	STA	MONCNT		;
	EI			;

	MVI	A,01H		;RETURN HARD ERROR TO BDOS
	RET			;

TEST:	LDA	DISK$COMMAND	;
	CPI	C$MFD$FWRTRK	;
	JZ	FWRTTRK		;
	JMP	FDIO		;

;-------------------------------------------------------------------------

SETV:
	MVI	A,0AH		;SET MINI FLOPPY RETRY COUNT
	STA	MERCNT		;
SETVLP:
	LDA	MA3MIR		;SEE IF DRIVE MOTOR STILL ON 
	ANI	080H		;MASK DRIVE BIT ON 
	MVI	A,XS$DELAY	;SET VERY SHORT SPINUP DELAY
	JNZ	SETSP		;GO SETUP TIMER FOR SPINUP
	MVI	A,M$DELAY	;USE LONG SPINUP TIME DELAY
SETSP:
	STA	DSKTMR		;START COUNTING
	LDA	@RDRV		;GET DRIVE NUMBER
	MOV	E,A		;INDEX DRIVE TABLE FOR PRESENT TRACK
	MVI	D,00H		;
	LXI	H,TRKTAB	;
	DAD	D		;
	MOV	A,M		;GET TRACK NUMBER FROM TABLE
	CPI	0FFH		;SEE IF JUST LOGGED OR
	JNZ	SETNRST		;REQUIRES A RESTORE
	PUSH	H		;
	CALL	FRESTR		;
	POP	H		;
	ORA	A		;CHECK RESTORE STATUS
	RNZ			;RETURN IF ERROR

SETNRST:
	PUSH	H		;SAVE DRIVE TABLE INDEX
	LDA	@RDRV		;GET DRIVE NUMBER AGAIN
	CALL	GETUNMO		;SET UNIT AND GET TRACK NUMBER
	POP	H		;
	PUSH	PSW		;SAVE DESIRED TRACK NUMBER
SPUPLP:
	LDA	DSKTMR		;
	ANA	A		;WAIT FOR SPINUP TIME TO ELAPSE
	JNZ	SPUPLP		;

	MOV	A,M		;GET CURRENT TRACK 
	OUT	P$MFD$TRK	;OUT TO CONTROLLER
	POP	PSW		;RESTORE TRACK NUMBER
	CMP	M		;
	JZ	SETV1		;
	OUT	P$MFD$DATA	;DESIRED TRACK TO CONTROLLER
	MOV	M,A		;

	PUSH	H		;
	MVI	A,C$MFD$SEEK	;MINI FLOPPY SEEK COMMAND
	ORI	MFD$STEP$RATE	;PUT IN THE STEP RATE BITS
	CALL	OCMD		;OUTPUT MINI FLOPPY COMMAND
	PUSH	PSW		;SAVE STATUS
	MVI	A,S$DELAY	;SET HEAD SETTLING DELAY TO 25 mSEK
	STA	DSKTMR		;
SETHSD:
	LDA	DSKTMR		;
	ANA	A		;WAIT FOR HEAD DELAY TO ELAPSE
	JNZ	SETHSD		;
	POP	PSW		;RESTORE STATUS
	POP	H		;RESTORE TRACK TABLE POINTER
	STA	FSTAT		;SAVE FULL STATUS FOR DIAGNOSTIC
	CPI	0FFH		;CHECK THE SEEK FOR TIMEOUT ERROR
	RZ			;
	ANI	01H		;MASK STATUS FOR CONTROLLER BUSY
	JZ	SETV1		;SEEK OK =>FINISH SETUP

	MOV	C,A		;SAVE SEEK STATUS
	LDA	MERCNT		;GET SEEK RETRY COUNT
	DCR	A		;
	STA	MERCNT		;SAVE FOR NEXT LOOP
	MOV	A,C		;RESTORE STATUS
	RZ			;

	MVI	M,0FFH		;SET TRACK TABLE ENTRY TO FORCE A RESTORE
	JMP	SETVLP		;
SETV1:
	LDA	@SECT
	INR	A
	OUT	P$MFD$SECT	;
	XRA	A		;CLEAR FOR NO ERRORS
	RET

;-------------------------------------------------------------------------

SETUPDMA:
	if	crtype eq CR8

	LDA	@DBNK		;
	MOV	B,A
	MOV	C,A
	CALL	?XMOVE
	LXI	B,0
	CALL	?MOVE		;RESET XMOVE FLAG

	else

	LDA	@DBNK		;Get and save DMA-buffer bank
	STA	DBNK
	LDA	@CBNK		;Get and save current CPU bank
	STA	CBNK

	endif

	XRA	A		;
	OUT	P$DMA$CLEAR	;MASTER CLEAR DMA CONTROLLER
	MVI	A,040H		;
	OUT	P$DMA$STAT	;SET HARDWARE ATTRIBUTES
	LDA	DMA$COMMAND	;GET DMA MODE BYTE FOR THIS OPERATION
	OUT	P$DMA$MODE	;TELL DMA WHAT TRANSFER WE WANT
	MVI	A,041H		;
	OUT	P$DMA$MODE	;
	INR	A		;
	OUT	P$DMA$MODE	;
	INR	A		;
	OUT	P$DMA$MODE	;SET UNUSED CHANNELS TO VERIFY MODE
	LHLD	@DMA		;POINT TO THE DATA BUFFER
	OUT	P$DMA$TOGGLE	;RESET HI/LO FLIP-FLOP
	MOV	A,L		;LSB OF DMA BUFFER ADDRESS
	OUT	P$DMA$ADR0	;
	MOV	A,H		;MSB OF DMA BUFFER ADDRESS
	OUT	P$DMA$ADR0	;
	RET
;------------------------------------------------------------------------

INIDMA:				;RESTORE DEFAULT DMA SETUP
	XRA	A		;
	OUT	P$DMA$CLEAR	;MASTER CLEAR DMA CONTROLLER
	MVI	A,C$DMA$BYTE	;
	OUT	P$DMA$STAT	;
	MVI	A,88H		;
	OUT	P$DMA$MODE	;
	MVI	A,85H		;
	OUT	P$DMA$MODE	;
	MVI	A,82H		;
	OUT	P$DMA$MODE	;
	MVI	A,83H		;
	OUT	P$DMA$MODE	;
	RET			;

;----------------------------------------------------------------------------

FDIO:
	MVI	A,10		;
	STA	MRWCNT		;
FPS1:
	CALL	SETUPDMA	;

	LXI	D,512		;2*256 BYTES SECTOR
	LDA	@CNT		;MULTI SECTOR COUNT IN 512 BYTES SECTORS
	LXI	H,0		;
MORESH:
	DAD	D		;MULTIPLY SECTOR COUNT BY SECTOR SIZE
	DCR	A		;
	JNZ	MORESH		;
	DCX	H		;
	MOV	A,L		;LSB
	OUT	P$DMA$TOGGLE	;
	OUT	P$DMA$CNT0	;
	MOV	A,H		;MSB
	OUT	P$DMA$CNT0	;SEND BYTE COUNT TO DMA

	LDA	DISK$COMMAND	;GET COMMAND BYTE
	MOV	D,A		;
	LDA	FSIDE		;GET SIDE BYTE
	ANI	01H		;
	RLC			;
	RLC			;
	RLC			;SIDE BIT INTO POSITION
	ORA	D		;PUT INTO COMMAND
	OUT 	P$MFD$STAT	;SEND COMMAND TO CONTROLLER
	MVI	A,XL$DELAY	;
	STA	DSKTMR		;MAX 2 SEC BEFORE THE CONTROLLER
PBUSY:				;MUST BE BUSY
	LDA	DSKTMR		;GET TIMER VALUE
	ANA	A		;
	JZ	IOTMOUT		;IF TIMEOUT THEN ABORT
	IN	P$MFD$STAT	;GET STATUS
	RRC			;
	JNC	PBUSY		;WAIT UNTIL CONTROLLER IS BUSY

	if	crtype eq CR8

	XRA	A		;
	OUT	P$DMA$MASK	;START DMA
IOLP:
	IN	P$MFD$STAT	;GET STATUS
	RRC			;SHIFT BUSY BIT INTO CARRY
	JNC	FDIOTERM	;OUT IF NOT BUSY
	IN	P$DMA$STAT	;GET DMA STATUS
	ANI	01H		;TEST IF TRANSFER COMPLETE
	JNZ	FDIOTERM	;
	LDA	DSKTMR		;GET TIMER VALUE
	ANA	A		;TEST FOR TIMEOUT
	JNZ	IOLP		;

	else

	JMP	DSK$RW
	CSEG
DSK$RW:
	LDA	DBNK
	CALL	?BNKSL
	XRA	A
	OUT	P$DMA$MASK	;START DMA
IOLP:
	IN	P$MFD$STAT
	RRC	
	JNC	FDTERM
	IN	P$DMA$STAT
	ANI	01H
	JNZ	FDTERM
	LDA	DSKTMR
	ANA	A
	JNZ	IOLP
	CALL	EXIT$RW
	JMP	IOTMOUT

FDTERM:
	CALL	EXIT$RW
	JMP	FDIOTERM

EXIT$RW:
	LDA	CBNK
	CALL	?BNKSL
	LDA	DBNK
	STA	@DBNK
	RET

DBNK	DB	0
CBNK	DB	0

	DSEG
	endif

IOTMOUT:
	CALL	ENDCMD		;FORCE COMMAND TERMINATION
	MVI	A,0FFH		;SET TIMEOUT ERROR
FPS2:
	STA	FSTAT		;
SEEKERR:
	LDA	MRWCNT		;
	DCR	A		;
	STA	MRWCNT		;DECREMENT RETRY COUNT
	JNZ	FPS3		;
	CALL	INIDMA		;RESTORE DEFAULT DMA SETUP
	LDA	FSTAT		;
	RET			;

FPS3:
	CALL	FRESTR		;RESTORE DISK
	ORA	A		;
	JNZ	SEEKERR		;RETRY IF RESTORE ERROR
	CALL	SETV		;
	ORA	A		;
	JNZ	SEEKERR		;
	JMP	FPS1		;SEEK OK TRY AGAIN
FDIOTERM:
	CALL	ENDCMD		;
	STA	FSTAT		;
	MVI	B,0DCH		;ASSUME WRITE BIT MASK'
	LDA	DISK$COMMAND	;
	CPI	C$MFD$WRMSEC	;
	JZ	WROP		;
	MVI	B,09CH		;
WROP:
	LDA	FSTAT		;GET CONTROLLER STATUS
	ANA	B		;MASK OF UNUSED BITS
	JNZ	FPS2		;
	MVI	A,XL$DELAY	;
	STA	DSKTMR		;
	CALL	INIDMA		;RESTORE DEFAULT DMA SETUP
	XRA	A		;
	STA	MONCNT		;CLEAR MOTOR-ON COUNT
	RET			;

;************************************************************************
;	MINI FLOPPY FORMAT ROUTINE WILL FORMAT ALL TRACKS ON BOTH 
;	SIDES OF A MINI FLOPPY DISKETTE. THE TRACK NUMBERS ARE CYCLED
;	TO TWICE THE NUMBER OF TRACKS PER SIDE SO THAT THE LEAST
;	SIGNIFICANT BIT BECOMES THE SIDE SELECT BIT FOR THE DOUBLE
;	HEADED TANDON TM100 96 TPI DRIVE.
;

FORMAT:
	LDA	@TRK		;IF TRACK ZERO RESTORE UNIT
	ORA	A		;
	JNZ	FMT2
FMT1:
	CALL	FRESTR		;RESTORE SELECTED UNIT
	ORA	A		;CHECK RESTORE STATUS
	JNZ	RW$ERROR	;OUT IF ERROR
	MVI	A,M$DELAY
	STA	DSKTMR
DELAY:	
	LDA	DSKTMR		;
	ANA	A		;
	JNZ	DELAY		;
FMT2:
	CALL	MFD$FORMAT	;
	ORA	A		;CHECK ERROR STATUS
	RNZ			;IF WRITE ERROR THEN QUIT
	CALL	mfd$rd$trk	;
	ORA	A		;AND CHECK IT
	RNZ			;IF VERIFY ERROR THEN QUIT
	LXI	H,TRKMSG	;
	CALL	?PMSG		;PRINT 'TRACK'
	MVI	H,0		;
	LDA	@TRK		;
	MOV	L,A		;
	CALL	?PDEC		;PRINT ACTUAL TRACK NUMBER
	XRA	A		;RESET ERROR STATUS
	STA	FSTAT		;
	STA	DISK$STATUS	;
	RET			;

;*************************************************************************
;	ROUTINE TO WRITE COMPLETE TRACK OF A SELECTED MINI FLOPPY
;	DATA IS READ FROM THE DATA BUFFER AT "@DMA" PUT ONTO THE CURRENT 
;	MINI FLOPPY DISK POSITION. "@CNT" 128 BYTE GROUPS OF DATA ARE SENT
;	TO THE MINI FLOPPY.
;
FWRTTRK:
	MVI	A,10		;SET RETRY COUNT
	STA	MRWCNT
WTRET:	
	CALL	SETUPDMA	;

	LXI	H,1900H		;
	MOV	A,L		;LSB
	OUT	P$DMA$TOGGLE	;
	OUT	P$DMA$CNT0	;
	MOV	A,H		;MSB
	OUT	P$DMA$CNT0	;SEND BYTE COUNT TO DMA

	LDA	DISK$COMMAND	;
	OUT	P$MFD$STAT	;
	MVI	E,01H		;
	MVI	A,L$DELAY	;
	STA	DSKTMR		;
	XTHL			;
	XTHL			;DELAY FOR 1793 TO SETUP
WRTWLP:	IN	P$MFD$STAT	;GET CONTROLLER STATUS
	ANA	E		;TEST IF READY FOR DATA
	JNZ	STADMA		;WAIT IF NOT
	LDA	DSKTMR		;GET PRESENT TIMER VALUE
	ANA	A
	JNZ	WRTWLP		;LOOP IF NOT TIMEOUT
WTTMOUT:
	MVI	A,0FFH
	STA	FSTAT		;FLAG TIMEOUT
RTRY:	LDA	MRWCNT		;GET AND DECREMENT RETRY COUNT
	DCR	A
	STA	MRWCNT
	JNZ	WTRET		;GO TRY AGAIN UNTIL RETRY COUNT ZERO
	CALL	ENDCMD		;FORCE TERMINATION
	CALL	INIDMA		;RESTORE DEFAULT DMA SETUP
	LDA	FSTAT		;GET ERROR STATUS
	RET

	if 	crtype eq CR8

STADMA:	XRA	A
	OUT	P$DMA$MASK	;START DMA
	MVI	A,XL$DELAY
	STA	DSKTMR		;ALLOW 2-3 SEC. BEFORE ABORT
FINLP:	IN	P$MFD$STAT	;GET CONTROLLER STATUS
	RRC
	JNC	NOTBSY		;EXIT WHEN CONTROLLER NOT BUSY
	LDA	DSKTMR
	ANA	A
	JNZ	FINLP		;LOOP UNTIL TIMEOUT
 	JMP	WTTMOUT		;GO RETRY

	else
	CSEG

STADMA:
	LDA	DBNK
	CALL	?BNKSL
	XRA	A
	OUT	P$DMA$MASK	;START DMA
	MVI	A,XL$DELAY
	STA	DSKTMR		;ALLOW 2-3 SEC. BEFORE ABORT
FINLP:	IN	P$MFD$STAT	;GET CONTROLLER STATUS
	RRC
	JNC	PRE$NOTBSY	;EXIT WHEN CONTROLLER NOT BUSY
	LDA	DSKTMR
	ANA	A
	JNZ	FINLP		;LOOP UNTIL TIMEOUT
	CALL	EXIT$RW
	JMP	WTTMOUT		;GO RETRY

PRE$NOTBSY:
	CALL	EXIT$RW
	JMP	NOTBSY

	DSEG
	endif

NOTBSY:
	RLC			;SHIFT BITS INTO ORIGINAL POSITION
	STA	FSTAT		;SAVE STATUS
	ANI	04H		;TEST IF CONTROLLER SATISFIED
	JNZ	RTRY		;IF NOT - GO RETRY
	CALL	ENDCMD		;GO FORCE TERMINATION
	STA	FSTAT
	ANI	0DDH		;LEAVE ONLY ACTUAL BITS
	JNZ	RTRY		;SOMETHING WRONG - TRY AGAIN
	CALL	INIDMA		;RESTORE DEFAULT DMA SETUP
	LDA	FSTAT		;GET STATUS
	ANI	0DDH
	RET

;******************************************************************************
;
;	ROUTINE TO CALCULATE MAP3 OUTPUT BYTE FOR MINI FLOPPY ADDRESSED BY
;	PHYSICAL UNIT NUMBER IN (A), WITHOUT CHANGING MAP BITS.
;	HEAD SELECT BIT BASED UPON THE PHYSICAL SIDE SELECT BYTE OF FSIDE.
;	SUBROUTINE RETURNS WITH (A) EQUAL TO THE APPROPIATE PHYSICAL
;	TRACK NUMBER FOR SUBSEQUENT SEEK ROUTINE CALL.
;
GETUNMO:
	ANI	01H		;LIMIT SELECT TO ONLY TWO DISKS
	MOV	B,A
	INR	B		;ADJUST DRIVE NUMBER FOR 1 BASED LOOP
	MVI	A,08H		;CONVERT BINARY TO LINEAR SELECT
BINLIN:
	RLC			;ROTATE BIT INTO POSITION
	DCR	B		;DONE SHIFTING?
	JNZ	BINLIN
	ORI	080H		;TURN ON MINI FLOPPY MOTORS
	MOV	B,A		;SAVE CODE SO'S WE CAN FIGURE OUT HEAD 
	LDA	FSIDE		;GET SINGLE BYTE FLOPPY SIDE NUMBER
	RRC			;MOVE INTO POSITION
	RRC
	ANI	040H		;STRIP OFF ALL BUT HEAD BIT
	ORA	B		;GET FINAL COPY OF DRIVE CONFIG BYTE
	MOV	B,A
	LDA	MA3MIR		;GET MAP3 MIRROR
	ANI	0FH		;STRIP PREVIOUS DISK CONTROL BITS
	ORA	B		;INSERT NEW DISK CONTROL BITS
	STA	MA3MIR		;SAVE TILL NEXT TIME WE COME HERE
	OUT	P$MAP3		;UPDATE REGISTER
	LDA	FTRK		;RETURN TRACK NUMBER FOR CALLER
	RET

******************************************************************************
;
;	ROUTINE TO OUTPUT MINI FLOPPY COMMAND IN (A). ROUTINE WAITS A
;	MAXIMUM OF THREE SECONDS FOR A READY CONDITION BEFORE RETURNING
;	A "0FFH" TIMEOUT CODE IN THE (A) REGISTER
;
OCMD:
	OUT	P$MFD$STAT	;SET COMMAND TO THE 1793
	PUSH	D
	LXI	D,04FFFH	;MAXIMUM DELAY
	CALL	WAIT1
	POP	D
	RET
;
******************************************************************************
;
;	WAIT FOR 1793 FLOPPY DISK CONTROLLER TO BECOME READY. THE ENTRY AT 
;	"WAIT1:"USES THE DELAY PARAMETER SET BY THE (DE) REGISTER PAIR.
;
WAIT1:
	XTHL			;NOP TYPE DELAY
	XTHL
	XTHL
	XTHL
	IN	P$MFD$STAT	;GET 1793 STATUS
	MOV	C,A		;SAVE IN (C)
	ANI	01H		;SEE IF BUSY
	JZ	WAIT2		;RETURN IF NOT BUSY
	DCX	D		;IF STILL BUSY THEN DEC LOOP DELAY COUNT
	MOV	A,E
	ORA	D		;DELAY COUNT DOWN TO ZERO YET?
	JNZ	WAIT1
	MVI	C,0FFH		;SET TIMEOUT ERROR CODE
WAIT2:
	PUSH	B		;SAVE OPERATION STATUS
	CALL	ENDCMD		;GO FORCE A TERMINATE
	POP	B
	MOV	A,C		;RESTORE STATUS TO (A) REGISTER
	RET

;******************************************************************************
;
;	ROUTINE TO FORCE RESET THE 1793 CHIP TO END A MULTIPLE COMMAND
;	OR TO TERMINATE A HUNG COMMAND. INITIAL DELAY IS TO ALLOW THE 
;	1793 CONTROLLER TO GET BY THE CRC BYTES ON READ/WRITE IF THIS
;	SUBROUTINE HAD BEEN CALLED TO TERMINATE A MULTIPLE COMMAND.
;
ENDCMD:
	MVI	B,29		;SHORT DELAY VALUE
ENDWAT:
	NOP
	DCR	B		;DEC LOOP DELAY COUNT
	JNZ	ENDWAT
	IN	P$MFD$STAT	;GET 1793 STATUS
	MOV	B,A
	MVI	A,C$MFD$FBD	;FORCE RESET COMMAND
	OUT	P$MFD$STAT	;
	MOV	A,B		;
	RET

;------------------------------------------------------------------------

FRESTR:
	MVI	A,10		;RETRY COUNT
	MOV	B,A		;
FREST1:
	PUSH	B		;
	LDA	@RDRV		;GET PHYSICAL DRIVE NUMBER
	MOV	E,A		;
	MVI	D,00H		;SET THIS DRIVE TRACK TABLE TO ZERO
	LXI	H,TRKTAB	;TRACK TABLE BASE ADDRESS
	DAD	D		;
	MVI	M,00H		;MOVE A ZERO INTO THE TRACK TABLE
	CALL	GETUNMO		;GET MINI FLOPPY UNIT MODE WORD
	MVI	A,C$MFD$RESTORE	;GET RESTORE COMMAND
	ORI	MFD$STEP$RATE	;PUT IN THE STEP RATE BITS
	CALL	OCMD		;SEND RESTORE COMMAND TO 1793
	POP	B		;
	STA	FSTAT		;SAVE STATUS FOR DIAGNOSTIC
	CPI	0FFH		;
	JZ	RESTEX		;
	XRI	04H		;COMPLEMENT TRACK ZERO BIT
	ANI	05H		;SEE IF DRIVE BUSY OR NOT TRACK ZERO
	JZ	RESTEX		;
	DCR	B		;
	JNZ	FREST1		;
RESTEX:
	PUSH	PSW		;
	XRA	A		;
	OUT	P$MFD$TRK	;
	POP	PSW		;
	RET			;


	PAGE
;-------------------------------------------------------------------------

DISK$STATUS:	DB	00H	;LAST ERROR STATUS CODE FOR MESSAGES

TRKMSG:		DB	CR,'TRACK ',0

RD$MSG:		DB	' CR16-READ ',CR,LF,0
WR$MSG:		DB	' CR16-WRITE ',CR,LF,0
FM$MSG:		DB	' CR16-FORMAT ',CR,LF,0

RW$NAME:	DW	RD$MSG	;TEXT FOR ERROR MESSAGE

ERROR$TABLE:	DW	B7$MSG	;TABLE OF POINTERS TO ERROR
		DW	B6$MSG	;MESSAGE STRINGS
		DW	B5$MSG	;FIRST ENTRY IS FOR BIT 7
		DW	B4$MSG	;OF 1793 STATUS BYTE
		DW	B3$MSG
		DW	B2$MSG
		DW	B1$MSG
		DW	B0$MSG

B7$MSG:		DB	'NOT READY',CR,LF,0
B6$MSG:		DB	'PROTECT',CR,LF,0
B5$MSG:		DB	'FAULT',CR,LF,0
B4$MSG:		DB	'RECORD NOT FOUND',CR,LF,0
B3$MSG:		DB	'CRC',CR,LF,0
B2$MSG:		DB	'LOST DATA',CR,LF,0
B1$MSG:		DB	'DREQ',CR,LF,0
B0$MSG:		DB	'BUSY',CR,LF,0

	PAGE
;*************************************************************************
@cnt		db	1			;

FSTAT		DB	0			;
FSIDE		DB	0			;
FTRK		DB	0			;
TRKTAB		DB	0FFH,0FFH		;
MRWCNT		DB	0			;
MERCNT		DB	0			;
DMA$COMMAND	DB	0			;(DMCMD)
DISK$COMMAND	DB	0			;(FDCMD)

	endif

	END
«eof»