;
;==================================================================================================
; CH376 SD CARD SUB-DRIVER
;==================================================================================================
;
; Thanks and credit to Alan Cox.  Much of this driver is based on
; his code in FUZIX (https://github.com/EtchedPixels/FUZIX).
;
; This file contains the SD Card specific support for the CH37x
; driver.  This file is included by the core driver file (ch.asm) as
; needed.  Note that only the CH376 actually supports SD Card access.
;
; The SD Card support is implemented using the CH376 file-level
; support.  It is *not* possible to access SD Cards using raw
; sector I/O.
;
; TODO:
;  - Implement auto-recovery on error status?
;
#DEFINE	CHSD_IMGFILE "DISK.IMG"
;
CHSD_FASTIO	.EQU	FALSE		; USE INIR/OTIR?
;
; CHUSB DEVICE STATUS
;
CHSD_STOK	.EQU	0
CHSD_STNOMEDIA	.EQU	-1
CHSD_STCMDERR	.EQU	-2
CHSD_STIOERR	.EQU	-3
CHSD_STTO	.EQU	-4
CHSD_STNOTSUP	.EQU	-5
CHSD_STNOFILE	.EQU	-6
;
; CHSD DEVICE CONFIGURATION
;
CHSD_CFGSIZ	.EQU	14		; SIZE OF USB CFG TBL ENTRIES
;
; CONFIG ENTRY DATA OFFSETS
;
; THE LOCATION OF CHSD_MODE IS SHARED BY ALL SUB-DRIVERS AND THE
; CH_SETMODE FUNCTION IN THE MAIN DRIVER (CH.ASM).  IF YOU CHANGE
; IT, YOU MUST SYNC UP THE MAIN DRIVER AND ALL SUB-DRIVERS!
;
; FIRST 3 BYTES SAME AS CH CONFIG
CHSD_STAT	.EQU	3		; LAST STATUS (BYTE)
CHSD_MEDCAP	.EQU	4		; MEDIA CAPACITY (DWORD)
CHSD_LBA	.EQU	8		; CURRENT LBA (DWORD)
CHSD_MODE	.EQU	12		; PTR TO MODE BYTE (WORD)
;
CHSD_CFGTBL:
;
#IF (CHCNT >= 1)
CHSD_CFG0:
	.DB	0			; DEV NUM, FILLED DYNAMICALLY
	.DB	CHTYP_NONE		; DEV TYPE, FILLED DYNCAMICALLY
	.DB	CH0BASE			; IO BASE ADDRESS
	.DB	0			; DEVICE STATUS
	.DW	0,0			; DEVICE CAPACITY
	.DW	0,0			; CURRENT LBA
	.DW	CH0_MODE		; POINTER TO MODE BYTE
;
  #IF (CH0SDENABLE)
	DEVECHO	"CHSD: IO="
	DEVECHO	CH0BASE
	DEVECHO	"\n"
  #ENDIF
#ENDIF
;
#IF (CHCNT >= 2)
CHSD_CFG1:
	.DB	0			; DEV NUM
	.DB	CHTYP_NONE		; DEV TYPE, FILLED DYNCAMICALLY
	.DB	CH1BASE			; IO BASE ADDRESS
	.DB	0			; DEVICE STATUS
	.DW	0,0			; DEVICE CAPACITY
	.DW	0,0			; CURRENT LBA
	.DW	CH1_MODE		; POINTER TO MODE BYTE
;
  #IF (CH1SDENABLE)
	DEVECHO	"CHSD: IO="
	DEVECHO	CH1BASE
	DEVECHO	"\n"
  #ENDIF
#ENDIF
;
#IF ($ - CHSD_CFGTBL) != (CHCNT * CHSD_CFGSIZ)
	.ECHO	"*** INVALID CHSD CONFIG TABLE ***\n"
#ENDIF
;
	.DB	$FF			; END OF TABLE MARKER
;
;
;
CHSD_INIT:
	LD	A,(IY+CH_TYPE)		; GET DEVICE TYPE
	PUSH	HL			; COPY INCOMING HL
	POP	IY			; ... TO IY
	LD	(IY+CH_TYPE),A		; SAVE DEVICE TYPE
;
	; UPDATE DRIVER RELATIVE UNIT NUMBER IN CONFIG TABLE
	LD	A,(CHSD_DEVNUM)		; GET NEXT UNIT NUM TO ASSIGN
	LD	(IY+CH_DEV),A		; UPDATE IT
	INC	A			; BUMP TO NEXT UNIT NUM TO ASSIGN
	LD	(CHSD_DEVNUM),A		; SAVE IT
;
	; ADD UNIT TO GLOBAL DISK UNIT TABLE
	LD	BC,CHSD_FNTBL		; BC := FUNC TABLE ADR
	PUSH	IY			; CFG ENTRY POINTER
	POP	DE			; COPY TO DE
	CALL	DIO_ADDENT		; ADD ENTRY TO GLOBAL DISK DEV TABLE
;
	CALL	CHSD_RESET		; RESET & DISCOVER MEDIA
#IF (CHSDTRACE <= 1)
	CALL	NZ,CHSD_PRTSTAT
#ENDIF
	RET	NZ			; ABORT ON FAILURE
;
	; START PRINTING DEVICE INFO
	CALL	CHSD_PRTPREFIX		; PRINT DEVICE PREFIX
;
	; PRINT STORAGE CAPACITY (BLOCK COUNT)
	PRTS(" BLOCKS=0x$")		; PRINT FIELD LABEL
	LD	A,CHSD_MEDCAP		; OFFSET TO CAPACITY FIELD
	CALL	LDHLIYA			; HL := IY + A, REG A TRASHED
	CALL	LD32			; GET THE CAPACITY VALUE
	CALL	PRTHEX32		; PRINT HEX VALUE
;
	; PRINT STORAGE SIZE IN MB
	PRTS(" SIZE=$")			; PRINT FIELD LABEL
	LD	B,11			; 11 BIT SHIFT TO CONVERT BLOCKS --> MB
	CALL	SRL32			; RIGHT SHIFT
	CALL	PRTDEC32		; PRINT DWORD IN DECIMAL
	PRTS("MB$")			; PRINT SUFFIX
;
	XOR	A			; SIGNAL SUCCESS
	RET
;
; DRIVER FUNCTION TABLE
;
CHSD_FNTBL:
	.DW	CHSD_STATUS
	.DW	CHSD_RESET
	.DW	CHSD_SEEK
	.DW	CHSD_READ
	.DW	CHSD_WRITE
	.DW	CHSD_VERIFY
	.DW	CHSD_FORMAT
	.DW	CHSD_DEVICE
	.DW	CHSD_MEDIA
	.DW	CHSD_DEFMED
	.DW	CHSD_CAP
	.DW	CHSD_GEOM
#IF (($ - CHSD_FNTBL) != (DIO_FNCNT * 2))
	.ECHO	"*** INVALID CHSD FUNCTION TABLE ***\n"
#ENDIF
;
CHSD_VERIFY:
CHSD_FORMAT:
CHSD_DEFMED:
	SYSCHKERR(ERR_NOTIMPL)		; NOT IMPLEMENTED
	RET
;
;
;
CHSD_READ:
	LD	A,CH_MODE_SD		; REQUEST SD MODE
	CALL	CH_SETMODE		; DO IT
	JP	NZ,CHSD_CMDERR		; HANDLE ERROR
;
	CALL	HB_DSKREAD		; HOOK HBIOS DISK READ SUPERVISOR
	LD	(CHSD_DSKBUF),HL	; SAVE DISK BUFFER ADDRESS
	CALL	CHSD_RWSTART		; SET LBA OFFSET
	RET	NZ
;
	;PRTS("\n\rREAD:$")		; *DEBUG*
	LD	A,CH_CMD_BYTERD		; BYTE READ
	CALL	CH_CMD			; SEND COMMAND
	CALL	CH_NAP
	LD	A,0			; LSB
	CALL	CH_WR			; SEND IT
	LD	A,2			; MSB
	CALL	CH_WR			; SEND IT
	CALL	CH_POLL			; GET RESULT
	;CALL	PC_SPACE		; *DEBUG*
	;CALL	PRTHEXBYTE		; *DEBUG*
	CP	$1D			; DATA READY TO READ?
	JP	NZ,CHSD_IOERR		; HANDLE I/O ERROR
;
	LD	HL,(CHSD_DSKBUF)
CHSD_READ1:
	CALL	CH_CMD_RD		; SEND READ USB DATA CMD
	CALL	CH_RD			; GET DATA LENGTH
	;CALL	PC_SPACE		; *DEBUG*
	;CALL	PRTHEXBYTE		; *DEBUG*
;
#IF (CHSD_FASTIO)
	LD	B,A			; BYTE COUNT TO READ
	LD	C,(IY+CH_IOBASE)	; BASE PORT
	EZ80_IO ;!! NOT SUPPORT INIR YET
	INIR				; DO IT FAST
#ELSE
	LD	B,A			; SAVE IT
CHSD_READ2:
	CALL	CH_RD			; GET DATA BYTE
	LD	(HL),A			; SAVE IN BUFFER
	INC	HL			; INC BUF PTR
	DJNZ	CHSD_READ2		; LOOP TILL DONE W/ ALL BYTES
#ENDIF
;
	LD	A,CH_CMD_BYTERDGO	; BYTE READ GO COMMAND
	CALL	CH_CMD			; SEND IT
	CALL	CH_NAP
	CALL	CH_POLL			; GET RESULT
	;CALL	PC_SPACE		; *DEBUG*
	;CALL	PRTHEXBYTE		; *DEBUG*
	CP	$1D			; MORE?
	JR	Z,CHSD_READ1		; IF SO, GET MORE
	CP	$14			; GOOD FINISH?
	JP	NZ,CHSD_IOERR		; HANDLE ERROR
;
	; INCREMENT LBA
	PUSH	HL			; SAVE HL
	LD	A,CHSD_LBA		; LBA OFFSET
	CALL	LDHLIYA			; HL := IY + A, REG A TRASHED
	CALL	INC32HL			; INCREMENT THE VALUE
	POP	HL			; RESTORE HL
;
	XOR	A			; SIGNAL SUCCESS
	RET
;
;
;
CHSD_WRITE:
	LD	A,CH_MODE_SD		; REQUEST SD MODE
	CALL	CH_SETMODE		; DO IT
	JP	NZ,CHSD_CMDERR		; HANDLE ERROR
;
	CALL	HB_DSKWRITE		; HOOK HBIOS DISK WRITE SUPERVISOR
	LD	(CHSD_DSKBUF),HL	; SAVE DISK BUFFER ADDRESS
	CALL	CHSD_RWSTART		; SET LBA OFFSET'
	RET	NZ
;
	;PRTS("\n\rWRITE:$")		; *DEBUG*
	LD	A,CH_CMD_BYTEWR		; BYTE WRITE
	CALL	CH_CMD			; SEND COMMAND
	LD	A,0			; LSB
	CALL	CH_WR			; SEND IT
	LD	A,2			; MSB
	CALL	CH_WR			; SEND IT
	CALL	CH_POLL			; GET RESULT
	;CALL	PC_SPACE		; *DEBUG*
	;CALL	PRTHEXBYTE		; *DEBUG*
	CP	$1E			; DATA READY TO GO?
	JP	NZ,CHSD_IOERR		; HANDLE I/O ERROR
;
	LD	HL,(CHSD_DSKBUF)
CHSD_WRITE1:
	LD	A,CH_CMD_WRREQDAT	; WRITE REQUESTED DATA CMD
	CALL	CH_CMD			; SEND IT
	CALL	CH_RD			; GET DATA LENGTH
	;CALL	PC_SPACE		; *DEBUG*
	;CALL	PRTHEXBYTE		; *DEBUG*
;
#IF (CHSD_FASTIO)
	LD	B,A			; BYTE COUNT TO WRITE
	LD	C,(IY+CH_IOBASE)	; BASE PORT
	EZ80_IO ;!! NOT SUPPORT OTIR YET
	OTIR				; DO IT FAST
#ELSE
	LD	B,A			; SAVE IT
CHSD_WRITE2:
	CALL	CH_WR			; WRITE DATA BYTE
	LD	(HL),A			; SAVE IN BUFFER
	INC	HL			; INC BUF PTR
	DJNZ	CHSD_WRITE2		; LOOP TILL DONE W/ ALL BYTES
#ENDIF
;
	LD	A,CH_CMD_BYTEWRGO	; BYTE WRITE GO COMMAND
	CALL	CH_CMD			; SEND IT
	CALL	CH_NAP
	CALL	CH_POLL			; GET RESULT
	;CALL	PC_SPACE		; *DEBUG*
	;CALL	PRTHEXBYTE		; *DEBUG*
	CP	$1E			; MORE?
	JR	Z,CHSD_WRITE1		; IF SO, SEND MORE
	CP	$14			; GOOD FINISH?
	JP	NZ,CHSD_IOERR		; HANDLE ERROR
;
	; INCREMENT LBA
	PUSH	HL			; SAVE HL
	LD	A,CHSD_LBA		; LBA OFFSET
	CALL	LDHLIYA			; HL := IY + A, REG A TRASHED
	CALL	INC32HL			; INCREMENT THE VALUE
	POP	HL			; RESTORE HL
;
	XOR	A			; SIGNAL SUCCESS
	RET
;
; SEEK TO CURRENT LBA
;
CHSD_RWSTART:
	;PRTS("\n\rRWST:$")		; *DEBUG*
	LD	A,CH_CMD_BYTE_LOC	; BYTE LOCATE COMMAND (SEEK)
	CALL	CH_CMD			; SEND IT
;
	; GET CURRENT LBA OFFSET
	LD	A,CHSD_LBA		; OFFSET TO CAPACITY FIELD
	CALL	LDHLIYA			; HL := IY + A, REG A TRASHED
	CALL	LD32			; OFFSET = DE:HL
;
	; CONVERT OFFSET FROM LBA TO BYTE
	LD	B,9
CHSD_RWSTART1:
	SLA	L
	RL	H
	RL	E
	RL	D
	DJNZ	CHSD_RWSTART1
	;CALL	PRTHEX32		; *DEBUG*
;
	; SEND THE BYTE OFFSET (LSB FIRST)
	LD	A,L
	CALL	CH_WR
	LD	A,H
	CALL	CH_WR
	LD	A,E
	CALL	CH_WR
	LD	A,D
	CALL	CH_WR
;
	CALL	CH_POLL			; WAIT FOR RESPONSE
	;CALL	PC_SPACE		; *DEBUG*
	;CALL	PRTHEXBYTE		; *DEBUG*
	CP	$14			; CHECK RESULT
	JP	NZ,CHSD_CMDERR		; HANDLE CMD ERROR
;
	XOR	A
	RET
;
;
;
CHSD_STATUS:
	; RETURN UNIT STATUS
	LD	A,(IY+CHSD_STAT)	; GET STATUS OF SELECTED DEVICE
	OR	A			; SET FLAGS
	RET				; AND RETURN
;
; RESET THE INTERFACE AND REDISCOVER MEDIA
;
CHSD_RESET:
	;PRTS("\n\rRES SD:$")		; *DEBUG*
;
	; ACTIVATE SD MODE
	LD	A,CH_CMD_MODE		; SET MODE COMMAND
	CALL	CH_CMD			; SEND IT
	LD	A,3			; SD MODE
	CALL	CH_WR			; SEND IT
	CALL	CH_NAP			; SMALL WAIT
	CALL	CH_RD			; GET RESULT
	;CALL	PC_SPACE		; *DEBUG*
	;CALL	PRTHEXBYTE		; *DEBUG*
	CALL	CH_NAP			; SMALL WAIT
;
	LD	A,CH_MODE_SD		; WE ARE NOW IN SD MODE
	LD	L,(IY+CHSD_MODE+0)	; GET MODE PTR (LSB)
	LD	H,(IY+CHSD_MODE+1)	; GET MODE PTR (MSB)
	LD	(HL),A			; SAVE IT
;
	CALL	CHSD_DSKMNT		; MOUNT DISK
	RET	NZ
;
	; OPEN DISK IMAGE FILE
	LD	DE,CHSD_FNAME
	CALL	CHSD_FOPEN
	RET	NZ
;
	; GET FILESIZE
	CALL	CHSD_FILESIZE
	RET	NZ
;
	; SET STATUS AND RETURN
	XOR	A			; CLEAR STATUS
	LD	(IY+CHSD_STAT),A	; RECORD STATUS
	OR	A			; SET FLAGS
	RET				; AND RETURN
;
;
;
CHSD_DEVICE:
	LD	D,DIODEV_CHSD		; D := DEVICE TYPE
	LD	E,(IY+CH_DEV)		; E := PHYSICAL DEVICE NUMBER
	LD	C,%00110010		; SD HARD DISK ATTRIBUTES
	LD	H,(IY+CH_TYPE)		; H := MODE
	LD	L,(IY+CH_IOBASE)	; L := BASE I/O ADDRESS
	XOR	A			; SIGNAL SUCCESS
	RET
;
; CHSD_GETMED
;
CHSD_MEDIA:
	LD	A,E			; GET FLAGS
	OR	A			; SET FLAGS
	JR	Z,CHSD_MEDIA1		; JUST REPORT CURRENT STATUS AND MEDIA
	CALL	CHSD_RESET		; RESET CHSD INTERFACE
;
CHSD_MEDIA1:
	LD	A,(IY+CHSD_STAT)	; GET STATUS
	OR	A			; SET FLAGS
	LD	D,0			; NO MEDIA CHANGE DETECTED
	LD	E,MID_HD		; ASSUME WE ARE OK
	RET	Z			; RETURN IF GOOD INIT
	LD	E,MID_NONE		; SIGNAL NO MEDIA
	LD	A,ERR_NOMEDIA		; NO MEDIA ERROR
	OR	A			; SET FLAGS
	RET				; AND RETURN
;
;
;
CHSD_SEEK:
	BIT	7,D			; CHECK FOR LBA FLAG
	CALL	Z,HB_CHS2LBA		; CLEAR MEANS CHS, CONVERT TO LBA
	RES	7,D			; CLEAR FLAG REGARDLESS (DOES NO HARM IF ALREADY LBA)
	LD	(IY+CHSD_LBA+0),L	; SAVE NEW LBA
	LD	(IY+CHSD_LBA+1),H	; ...
	LD	(IY+CHSD_LBA+2),E	; ...
	LD	(IY+CHSD_LBA+3),D	; ...
	XOR	A			; SIGNAL SUCCESS
	RET				; AND RETURN
;
;
;
CHSD_CAP:
	LD	A,(IY+CHSD_STAT)	; GET STATUS
	PUSH	AF			; SAVE IT
	LD	A,CHSD_MEDCAP		; OFFSET TO CAPACITY FIELD
	CALL	LDHLIYA			; HL := IY + A, REG A TRASHED
	CALL	LD32			; GET THE CURRENT CAPACITY INTO DE:HL
	LD	BC,512			; 512 BYTES PER BLOCK
	POP	AF			; RECOVER STATUS
	OR	A			; SET FLAGS
	RET
;
;
;
CHSD_GEOM:
	; FOR LBA, WE SIMULATE CHS ACCESS USING 16 HEADS AND 16 SECTORS
	; RETURN HS:CC -> DE:HL, SET HIGH BIT OF D TO INDICATE LBA CAPABLE
	CALL	CHSD_CAP		; GET TOTAL BLOCKS IN DE:HL, BLOCK SIZE TO BC
	LD	L,H			; DIVIDE BY 256 FOR # TRACKS
	LD	H,E			; ... HIGH BYTE DISCARDED, RESULT IN HL
	LD	D,16 | $80		; HEADS / CYL = 16, SET LBA CAPABILITY BIT
	LD	E,16			; SECTORS / TRACK = 16
	RET				; DONE, A STILL HAS CHSD_CAP STATUS
;
; CH37X HELPER ROUTINES
;
;
; PERFORM DISK MOUNT
;
CHSD_DSKMNT:
	;PRTS("\n\rMOUNT:$")		; *DEBUG*
	LD	A,CH_CMD_DSKMNT		; DISK QUERY
	CALL	CH_CMD			; DO IT
	CALL	CH_POLL			; WAIT FOR RESPONSE
	;CALL	PC_SPACE		; *DEBUG*
	;CALL	PRTHEXBYTE		; *DEBUG*
	CP	$82			; NO DISK?
	JP	Z,CHSD_NOMEDIA		; HANDLE NO MEDIA ERROR
	CP	$14			; SUCCESS?
	JP	NZ,CHSD_CMDERR		; HANDLE ERROR
;
#IF FALSE
	CALL	CH_CMD_RD		; SEND READ COMMAND
	CALL	CH_RD			; GET LENGTH
	;CALL	PC_SPACE		; *DEBUG*
	;CALL	PRTHEXBYTE		; *DEBUG*
	LD	B,A			; LOOP COUNTER
	LD	HL,HB_WRKBUF		; USE WORK BUFFER FOR DATA
CHSD_DSKMNT1:
	CALL	CH_RD			; GET A BYTE
	LD	(HL),A			; SAVE IT
	INC	HL			; BUMP BUF PTR
	DJNZ	CHSD_DSKMNT1		; LOOP FOR ALL DATA
;
	;LD	DE,HB_WRKBUF		; *DEBUG*
	;CALL	DUMP_BUFFER		; *DEBUG*
;
	CALL	CHSD_PRTPREFIX		; PRINT DEVICE PREFIX
	LD	HL,HB_WRKBUF + 8
	LD	B,28
CHSD_DSKMNT2:
	LD	A,(HL)
	INC	HL
	CALL	COUT
	DJNZ	CHSD_DSKMNT2
#ENDIF
;
	XOR	A
	RET
;
; SET FILE NAME
;
CHSD_SETFNAME:
	;PRTS("\n\rSETFNAME:$")		; *DEBUG*
	LD	A,CH_CMD_SET_FN		; SET FILE NAME COMMAND
	CALL	CH_CMD			; SEND IT
	CALL	CH_NAP
	;CALL	DELAY			; MAY NOT BE NEEDED
	;CALL	PC_SPACE		; *DEBUG*
CHSD_SETFNAME1:
	;CALL	DELAY
	LD	A,(DE)			; GET NEXT BYTE
	INC	DE			; BUMP POINTER
	CALL	CH_WR			; SEND IT
	;CALL	COUT			; *DEBUG*
	OR	A			; CHECK FOR NUL (EOS)
	RET	Z			; IF NUL, DONE
	JR	CHSD_SETFNAME1		; SEND MORE CHARACTERS
;
; OPEN FILE
;
CHSD_FOPEN:
	CALL	CHSD_SETFNAME
	;PRTS("\n\rFOPEN:$")		; *DEBUG*
	LD	A,CH_CMD_FOPEN		; FILE OPEN  COMMAND
	CALL	CH_CMD			; SEND IT
	CALL	CH_POLL			; WAIT FOR RESULT
	;CALL	PC_SPACE		; *DEBUG*
	;CALL	PRTHEXBYTE		; *DEBUG*
	CP	$42			; MISSING FILE?
	JP	Z,CHSD_NOFILE		; HANDLE ERROR
	CP	$14			; SUCCESS?
	JP	NZ,CHSD_IOERR		; HANDLE ERROR
	RET				; RETURN WITH ZF SET APPROPRIATELY
;
; GET FILE SIZE
;
CHSD_FILESIZE:
	;PRTS("\n\rFSIZE:$")
	LD	A,CH_CMD_FILESIZE	; FILE SIZE COMMAND
	CALL	CH_CMD			; SEND IT
	LD	A,$68			; REQUIRED CMD PARAMETER
	CALL	CH_WR			; SEND IT
	CALL	CH_NAP
	LD	A,CHSD_MEDCAP		; MEDIA CAPACITY OFFSET
	CALL	LDHLIYA			; HL := IY + A, REG A TRASHED
	PUSH	HL			; SAVE ADDRESS
	CALL	CH_RD
	LD	L,A
	CALL	CH_RD
	LD	H,A
	CALL	CH_RD
	LD	E,A
	CALL	CH_RD
	LD	D,A
	;CALL	PC_SPACE		; *DEBUG*
	;CALL	PRTHEX32		; *DEBUG*
	LD	B,9			; ROTATE 9 BITS FOR DIV 512
CHSD_FILESIZE1:
	SRL	D
	RR	E
	RR	H
	RR	L
	DJNZ	CHSD_FILESIZE1		; LOOP TILL DONE
	POP	BC			; RECOVER ADDRESS TO BC
	;CALL	PC_SPACE		; *DEBUG*
	;CALL	PRTHEX32		; *DEBUG*
	CALL	ST32			; STORE IT
	XOR	A			; SIGNAL SUCCESS
	RET				; AND DONE
;
; ERROR HANDLERS
;
;
CHSD_NOFILE:
	LD	A,CHSD_STNOFILE
	JR	CHSD_ERR
;
CHSD_NOMEDIA:
	LD	A,CHSD_STNOMEDIA
	JR	CHSD_ERR
;
CHSD_CMDERR:
	LD	A,CHSD_STCMDERR
	JR	CHSD_ERR
;
CHSD_IOERR:
	LD	A,CHSD_STIOERR
	JR	CHSD_ERR
;
CHSD_TO:
	LD	A,CHSD_STTO
	JR	CHSD_ERR
;
CHSD_NOTSUP:
	LD	A,CHSD_STNOTSUP
	JR	CHSD_ERR
;
CHSD_ERR:
	LD	(IY+CHSD_STAT),A	; SAVE NEW STATUS
;
CHSD_ERR2:
#IF (CHSDTRACE >= 2)
	CALL	CHSD_PRTSTAT
#ENDIF
	OR	A			; SET FLAGS
	RET
;
;
;
CHSD_PRTERR:
	RET	Z			; DONE IF NO ERRORS
	; FALL THRU TO CHSD_PRTSTAT
;
; PRINT FULL DEVICE STATUS LINE
;
CHSD_PRTSTAT:
	PUSH	AF
	PUSH	DE
	PUSH	HL
	LD	A,(IY+CHSD_STAT)
	CALL	CHSD_PRTPREFIX		; PRINT UNIT PREFIX
	CALL	PC_SPACE		; FORMATTING
	CALL	CHSD_PRTSTATSTR
	POP	HL
	POP	DE
	POP	AF
	RET
;
; PRINT STATUS STRING
;
CHSD_PRTSTATSTR:
	PUSH	AF
	PUSH	DE
	PUSH	HL
	LD	A,(IY+CHSD_STAT)
	NEG
	LD	HL,CHSD_STR_ST_MAP
	ADD	A,A
	CALL	ADDHLA
	LD	E,(HL)
	INC	HL
	LD	D,(HL)
	CALL	WRITESTR
	POP	HL
	POP	DE
	POP	AF
	RET
;
; PRINT DIAGNONSTIC PREFIX
;
CHSD_PRTPREFIX:
	PUSH	AF
	CALL	NEWLINE
	PRTS("CHSD$")
	LD	A,(IY+CH_DEV)		; GET CURRENT DEVICE NUM
	CALL	PRTDECB
	CALL	PC_COLON
	POP	AF
	RET
;
; DATA STORAGE
;
CHSD_DEVNUM	.DB	0		; TEMP DEVICE NUM USED DURING INIT
CHSD_DSKBUF	.DW	0
;
CHSD_FNAME	.DB	"/", CHSD_IMGFILE, 0
;
CHSD_STR_ST_MAP:
	.DW		CHSD_STR_STOK
	.DW		CHSD_STR_STNOMEDIA
	.DW		CHSD_STR_STCMDERR
	.DW		CHSD_STR_STIOERR
	.DW		CHSD_STR_STTO
	.DW		CHSD_STR_STNOTSUP
	.DW		CHSD_STR_STNOFILE
;
CHSD_STR_STOK		.TEXT	"OK$"
CHSD_STR_STNOMEDIA	.TEXT	"NO MEDIA$"
CHSD_STR_STCMDERR	.TEXT	"COMMAND ERROR$"
CHSD_STR_STIOERR	.TEXT	"IO ERROR$"
CHSD_STR_STTO		.TEXT	"TIMEOUT$"
CHSD_STR_STNOTSUP	.TEXT	"NOT SUPPORTED$"
CHSD_STR_STNOFILE	.TEXT	"MISSING "
			.TEXT	CHSD_IMGFILE
			.TEXT	" FILE$"
CHSD_STR_STUNK		.TEXT	"UNKNOWN ERROR$"
