; ;================================================================================================== ; CH375/376 USB 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 USB Drive specific support for the CH37x ; driver. This file is included by the core driver file (ch.asm) as ; needed. ; ; The USB support is implemented as pure raw sector I/O. The CH376 ; file-level support is not utilized. ; ; NOTES: ; - There seem to be compatibility issues with older USB thumb drives. ; Such drives will complete DISK_INIT successfully, but then return ; an error attempting to do any I/O. The error is $17 indicating ; the CH37x encountered an overflow during communication with the ; device. I found that adding a DISK_MOUNT command (only possible ; on CH376) resolved the issue for some devices, so that has been ; added to the RESET routine when using CH376. ; ; TODO: ; - Implement auto-recovery on error status? ; CHUSB_FASTIO .EQU TRUE ; USE INIR/OTIR? ; ; CHUSB DEVICE STATUS ; CHUSB_STOK .EQU 0 CHUSB_STNOMEDIA .EQU -1 CHUSB_STCMDERR .EQU -2 CHUSB_STIOERR .EQU -3 CHUSB_STTO .EQU -4 CHUSB_STNOTSUP .EQU -5 ; ; CHUSB DEVICE CONFIGURATION ; CHUSB_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 CHUSB_STAT .EQU 3 ; LAST STATUS (BYTE) CHUSB_MEDCAP .EQU 4 ; MEDIA CAPACITY (DWORD) CHUSB_LBA .EQU 8 ; CURRENT LBA (DWORD) CHUSB_MODE .EQU 12 ; PTR TO MODE BYTE (WORD) ; CHUSB_CFGTBL: ; #IF (CHCNT >= 1) CHUSB_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 (CH0USBENABLE) DEVECHO "CHUSB: IO=" DEVECHO CH0BASE DEVECHO "\n" #ENDIF #ENDIF ; #IF (CHCNT >= 2) CHUSB_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 (CH1USBENABLE) DEVECHO "CHUSB: IO=" DEVECHO CH1BASE DEVECHO "\n" #ENDIF #ENDIF ; #IF ($ - CHUSB_CFGTBL) != (CHCNT * CHUSB_CFGSIZ) .ECHO "*** INVALID CHUSB CONFIG TABLE ***\n" #ENDIF ; .DB $FF ; END OF TABLE MARKER ; ; ; CHUSB_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,(CHUSB_DEVNUM) ; GET NEXT UNIT NUM TO ASSIGN LD (IY+CH_DEV),A ; UPDATE IT INC A ; BUMP TO NEXT UNIT NUM TO ASSIGN LD (CHUSB_DEVNUM),A ; SAVE IT ; ; ADD UNIT TO GLOBAL DISK UNIT TABLE LD BC,CHUSB_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 CHUSB_RESET ; RESET & DISCOVER MEDIA #IF (CHUSBTRACE <= 1) CALL NZ,CHUSB_PRTSTAT #ENDIF RET NZ ; ABORT ON FAILURE ; ; START PRINTING DEVICE INFO CALL CHUSB_PRTPREFIX ; PRINT DEVICE PREFIX ; ; PRINT STORAGE CAPACITY (BLOCK COUNT) PRTS(" BLOCKS=0x$") ; PRINT FIELD LABEL LD A,CHUSB_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 ; CHUSB_FNTBL: .DW CHUSB_STATUS .DW CHUSB_RESET .DW CHUSB_SEEK .DW CHUSB_READ .DW CHUSB_WRITE .DW CHUSB_VERIFY .DW CHUSB_FORMAT .DW CHUSB_DEVICE .DW CHUSB_MEDIA .DW CHUSB_DEFMED .DW CHUSB_CAP .DW CHUSB_GEOM #IF (($ - CHUSB_FNTBL) != (DIO_FNCNT * 2)) .ECHO "*** INVALID CHUSB FUNCTION TABLE ***\n" #ENDIF ; CHUSB_VERIFY: CHUSB_FORMAT: CHUSB_DEFMED: SYSCHKERR(ERR_NOTIMPL) ; NOT IMPLEMENTED RET ; ; ; CHUSB_READ: LD A,CH_MODE_USB ; REQUEST USB MODE CALL CH_SETMODE ; DO IT JP NZ,CHUSB_CMDERR ; HANDLE ERROR ; CALL HB_DSKREAD ; HOOK HBIOS DISK READ SUPERVISOR LD (CHUSB_DSKBUF),HL ; SAVE DISK BUFFER ADDRESS LD A,CH_CMD_DSKRD ; DISK READ COMMAND CALL CHUSB_RWSTART ; SEND CMD AND LBA ; ; READ THE SECTOR IN 64 BYTE CHUNKS LD B,8 ; 8 CHUNKS OF 64 FOR 512 BYTE SECTOR LD HL,(CHUSB_DSKBUF) ; GET DISK BUF ADR CHUSB_READ1: CALL CH_POLL ; WAIT FOR DATA READY CP $1D ; DATA READY TO READ? ;CALL PC_LT ; *DEBUG* ;CALL PRTHEXBYTE ; *DEBUG* JP NZ,CHUSB_IOERR ; HANDLE IO ERROR CALL CH_CMD_RD ; SEND READ USB DATA CMD CALL CH_RD ; READ DATA BLOCK LENGTH CP 64 ; AS EXPECTED? JP NZ,CHUSB_IOERR ; IF NOT, HANDLE ERROR ; #IF (CHUSB_FASTIO) ; READ 64 BYTE CHUNK PUSH BC ; SAVE LOOP CONTROL LD B,64 ; READ 64 BYTES LD C,(IY+CH_IOBASE) ; BASE PORT EZ80_IO INIR ; DO IT FAST POP BC ; RESTORE LOOP CONTROL #ELSE ; BYTE READ LOOP PUSH BC ; SAVE LOOP CONTROL LD B,64 ; READ 64 BYTES CHUSB_READ2: CALL CH_RD ; GET NEXT BYTE LD (HL),A ; SAVE IT INC HL ; INC BUF PTR DJNZ CHUSB_READ2 ; LOOP AS NEEDED POP BC ; RESTORE LOOP CONTROL #ENDIF ; ; PREPARE FOR NEXT CHUNK LD A,CH_CMD_DSKRDGO ; CONTINUE DISK READ CALL CH_CMD ; SEND IT DJNZ CHUSB_READ1 ; LOOP TILL DONE ; ; FINAL CHECK FOR COMPLETION & SUCCESS CALL CH_POLL ; WAIT FOR COMPLETION CP $14 ; SUCCESS? JP NZ,CHUSB_IOERR ; IF NOT, HANDLE ERROR ; ; INCREMENT LBA PUSH HL ; SAVE HL LD A,CHUSB_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 ; ; ; CHUSB_WRITE: LD A,CH_MODE_USB ; REQUEST USB MODE CALL CH_SETMODE ; DO IT JP NZ,CHUSB_CMDERR ; HANDLE ERROR ; CALL HB_DSKWRITE ; HOOK HBIOS DISK WRITE SUPERVISOR LD (CHUSB_DSKBUF),HL ; SAVE DISK BUFFER ADDRESS LD A,CH_CMD_DSKWR ; DISK READ COMMAND CALL CHUSB_RWSTART ; SEND CMD AND LBA ; ; WRITE THE SECTOR IN 64 BYTE CHUNKS LD B,8 ; 8 CHUNKS OF 64 FOR 512 BYTE SECTOR LD HL,(CHUSB_DSKBUF) ; GET DISK BUF ADR CHUSB_WRITE1: CALL CH_POLL ; WAIT FOR DATA READY CP $1E ; DATA READY TO WRITE ;CALL PC_GT ; *DEBUG* ;CALL PRTHEXBYTE ; *DEBUG* JP NZ,CHUSB_IOERR ; HANDLE IO ERROR CALL CH_CMD_WR ; SEND WRITE USB DATA CMD LD A,64 ; 64 BYTE CHUNK CALL CH_WR ; SEND DATA BLOCK LENGTH ; #IF (CHUSB_FASTIO) ; WRITE 64 BYTE CHUNK PUSH BC ; SAVE LOOP CONTROL LD B,64 ; WRITE 64 BYTES LD C,(IY+CH_IOBASE) ; BASE PORT EZ80_IO OTIR ; DO IT FAST POP BC ; RESTORE LOOP CONTROL #ELSE ; BYTE WRITE LOOP PUSH BC ; SAVE LOOP CONTROL LD B,64 ; WRITE 64 BYTES CHUSB_WRITE2: LD A,(HL) ; GET NEXT BYTE INC HL ; INC BUF PTR CALL CH_WR ; WRITE NEXT BYTE DJNZ CHUSB_WRITE2 ; LOOP AS NEEDED POP BC ; RESTORE LOOP CONTROL #ENDIF ; ; PREPARE FOR NEXT CHUNK LD A,CH_CMD_DSKWRGO ; CONTINUE DISK READ CALL CH_CMD ; SEND IT DJNZ CHUSB_WRITE1 ; LOOP TILL DONE ; ; FINAL CHECK FOR COMPLETION & SUCCESS CALL CH_POLL ; WAIT FOR COMPLETION CP $14 ; SUCCESS? JP NZ,CHUSB_IOERR ; IF NOT, HANDLE ERROR ; ; INCREMENT LBA PUSH HL ; SAVE HL LD A,CHUSB_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 ; ; INITIATE A DISK SECTOR READ/WRITE OPERATION ; A: READ OR WRITE OPCODE ; CHUSB_RWSTART: CALL CH_CMD ; SEND R/W COMMAND ; ; SEND LBA, 4 BYTES, LITTLE ENDIAN LD A,CHUSB_LBA ; OFFSET TO CAPACITY FIELD CALL LDHLIYA ; HL := IY + A, REG A TRASHED LD B,4 ; SEND 4 BYTES CHUSB_RWSTART1: LD A,(HL) ; GET BYTE INC HL ; BUMP PTR CALL CH_WR ; SEND BYTE DJNZ CHUSB_RWSTART1 ; LOOP AS NEEDED ; ; REQUEST 1 SECTOR LD A,1 ; 1 SECTOR CALL CH_WR ; SEND IT RET ; ; ; CHUSB_STATUS: ; RETURN UNIT STATUS LD A,(IY+CHUSB_STAT) ; GET STATUS OF SELECTED DEVICE OR A ; SET FLAGS RET ; AND RETURN ; ; RESET THE INTERFACE AND REDISCOVER MEDIA ; CHUSB_RESET: ;PRTS("\n\rRES USB:$") ; *DEBUG* ;CALL CH_FLUSH ; DISCARD ANY GARBAGE ;CALL CH_RESET ; FULL CH37X RESET ; ; RESET THE BUS LD A,CH_CMD_MODE ; SET MODE COMMAND CALL CH_CMD ; SEND IT LD A,7 ; RESET BUS 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 ; ; ACTIVATE USB MODE LD A,CH_CMD_MODE ; SET MODE COMMAND CALL CH_CMD ; SEND IT LD A,6 ; USB ENABLED, SEND SOF 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_USB ; WE ARE NOW IN USB MODE LD L,(IY+CHUSB_MODE+0) ; GET MODE PTR (LSB) LD H,(IY+CHUSB_MODE+1) ; GET MODE PTR (MSB) LD (HL),A ; SAVE IT ; ; INITIALIZE DISK LD B,24 ; TRY A FEW TIMES CHUSB_RESET1: ;PRTS("\n\rDSKINIT:$") ; *DEBUG* LD A,CH_CMD_DSKINIT ; DISK INIT COMMAND CALL CH_CMD ; SEND IT LD DE,10000 ; 10000 * 16 = 160US ??? LD DE,20000 ; 10000 * 16 = 160US ??? LD DE,12500 ; 1250 * 16 = 200US ??? CALL VDELAY ; DELAY CALL CH_POLL ; WAIT FOR RESULT ;CALL PC_SPACE ; *DEBUG* ;CALL PRTHEXBYTE ; *DEBUG* CP $14 ; SUCCESS? JR Z,CHUSB_RESET1A ; IF SO, CHECK READY CP $16 ; NO MEDIA JP Z,CHUSB_NOMEDIA ; HANDLE IT CALL CH_NAP ; SMALL DELAY DJNZ CHUSB_RESET1 ; LOOP AS NEEDED JP CHUSB_TO ; HANDLE TIMEOUT ; CHUSB_RESET1A: ;CALL CHUSB_DSKRES ; DISK RESET ;CP $14 ; GOOD? ;JR Z,CHUSB_RESET2 ;CALL CHUSB_DSKRDY ; CHECK IF DISK READY ;CP $14 ; GOOD? ;JR Z,CHUSB_RESET2 ; IF SO, MOVE ON ;DJNZ CHUSB_RESET1 ; KEEP TRYING ; CHUSB_RESET2: ; USE OF CH376 DISK_MOUNT COMMAND SEEMS TO IMPROVE ; COMPATIBILITY WITH SOME OLDER USB THUMBDRIVES. LD A,(IY+CH_TYPE) ; CH37X TYPE? CP CHTYP_376 ; IS CH376? CALL Z,CHUSB_DSKMNT ; IF SO, TRY MOUNT, IGNORE ERRS ;CALL CHUSB_AUTOSET ; *DEBUG* ;CALL CHUSB_TSTCON ; *DEBUG* ;CALL CHUSB_MAXLUN ; *DEBUG* ;CALL CHUSB_DSKRDY ; *DEBUG* ;CALL CHUSB_DSKINQ ; *DEBUG* ;; CALL CHUSB_DSKSIZ ; GET AND RECORD DISK SIZE RET NZ ; ABORT ON ERROR ; ; SET STATUS AND RETURN XOR A ; CLEAR STATUS LD (IY+CHUSB_STAT),A ; RECORD STATUS OR A ; SET FLAGS RET ; AND RETURN ; ; ; CHUSB_DEVICE: LD D,DIODEV_CHUSB ; D := DEVICE TYPE LD E,(IY+CH_DEV) ; E := PHYSICAL DEVICE NUMBER LD C,%00110011 ; USB 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 ; ; CHUSB_GETMED ; CHUSB_MEDIA: LD A,E ; GET FLAGS OR A ; SET FLAGS JR Z,CHUSB_MEDIA1 ; JUST REPORT CURRENT STATUS AND MEDIA CALL CHUSB_RESET ; RESET CHUSB INTERFACE ; CHUSB_MEDIA1: LD A,(IY+CHUSB_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 ; ; ; CHUSB_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+CHUSB_LBA+0),L ; SAVE NEW LBA LD (IY+CHUSB_LBA+1),H ; ... LD (IY+CHUSB_LBA+2),E ; ... LD (IY+CHUSB_LBA+3),D ; ... XOR A ; SIGNAL SUCCESS RET ; AND RETURN ; ; ; CHUSB_CAP: LD A,(IY+CHUSB_STAT) ; GET STATUS PUSH AF ; SAVE IT LD A,CHUSB_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 ; ; ; CHUSB_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 CHUSB_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 CHUSB_CAP STATUS ; ; CH37X HELPER ROUTINES ; ; ; PERFORM DISK MOUNT ; CHUSB_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 $14 ; SUCCESS? RET NZ ; ABORT IF NOT ; #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 CHUSB_DSKMNT1: CALL CH_RD ; GET A BYTE LD (HL),A ; SAVE IT INC HL ; BUMP BUF PTR DJNZ CHUSB_DSKMNT1 ; LOOP FOR ALL DATA ; ;LD DE,HB_WRKBUF ; *DEBUG* ;CALL DUMP_BUFFER ; *DEBUG* ; CALL CHUSB_PRTPREFIX ; PRINT DEVICE PREFIX LD HL,HB_WRKBUF + 8 LD B,28 CHUSB_DSKMNT2: LD A,(HL) INC HL CALL COUT DJNZ CHUSB_DSKMNT2 #ENDIF ; XOR A RET ; ; PERFORM DISK SIZE ; CHUSB_DSKSIZ: ;PRTS("\n\rDSKSIZ:$") ; *DEBUG* LD A,CH_CMD_DSKSIZ ; DISK SIZE COMMAND CALL CH_CMD ; SEND IT CALL CH_POLL ; WAIT FOR RESULT ;CALL PC_SPACE ; *DEBUG* ;CALL PRTHEXBYTE ; *DEBUG* CP $14 ; SUCCESS? JP NZ,CHUSB_CMDERR ; HANDLE CMD ERROR CALL CH_CMD_RD ; SEND READ USB DATA CMD CALL CH_RD ; GET RD DATA LEN ;CALL PC_SPACE ; *DEBUG* ;CALL PRTHEXBYTE ; *DEBUG* CP $08 ; MAKE SURE IT IS 8 JP NZ,CHUSB_CMDERR ; HANDLE CMD ERROR LD A,CHUSB_MEDCAP ; MEDIA CAPACITY OFFSET CALL LDHLIYA ; HL := IY + A, REG A TRASHED PUSH HL ; SAVE ADDRESS CALL CH_RD LD D,A CALL CH_RD LD E,A CALL CH_RD LD H,A CALL CH_RD LD L,A CALL CH_RD CALL CH_RD CALL CH_RD CALL CH_RD POP BC ; RECOVER ADDRESS TO BC CALL ST32 ; STORE IT XOR A ; SIGNAL SUCCESS RET ; AND DONE ; #IF FALSE ; ; PERFORM DISK INQUIRY ; BASICALLY THE SCSI INQUIRY COMMAND ; CHUSB_DSKINQ: ;PRTS("\n\rINQUIRY:$") ; *DEBUG* LD A,CH_CMD_DSKINQ ; DISK QUERY CALL CH_CMD ; DO IT CALL CH_POLL ; WAIT FOR RESPONSE ;CALL PC_SPACE ; *DEBUG* ;CALL PRTHEXBYTE ; *DEBUG* CP $14 ; SUCCESS? RET NZ ; ABORT IF NOT CALL CH_CMD_RD ; SEND READ COMMAND CALL CH_RD ; GET LENGTH LD B,A ; LOOP COUNTER LD HL,HB_WRKBUF ; USE WORK BUFFER FOR DATA DSKINQ1: CALL CH_RD ; GET A BYTE LD (HL),A ; SAVE IT INC HL ; BUMP BUF PTR DJNZ DSKINQ1 ; LOOP FOR ALL DATA ; ;LD DE,HB_WRKBUF ; *DEBUG* ;CALL DUMP_BUFFER ; *DEBUG* ; ;CALL CHUSB_PRTPREFIX ; PRINT DEVICE PREFIX ;LD HL,HB_WRKBUF + 8 ;LD B,28 DSKINQ2: ;LD A,(HL) ;INC HL ;CALL COUT ;DJNZ DSKINQ2 ; RET ; ; PERFORM SET RETRIES ; CHUSB_SETRETRY: ;PRTS("\n\rSETRETRY:$") ; *DEBUG* LD A,CH_CMD_SETRETRY ; DISK READY CALL CH_CMD ; DO IT CALL CH_NAP LD A,$25 ; CONSTANT CALL CH_WR ; SEND IT CALL CH_NAP LD A,$BF ; MAX CALL CH_WR CALL CH_NAP CALL CH_RD ; GET RESULT ;CALL PC_SPACE ; *DEBUG* ;CALL PRTHEXBYTE ; *DEBUG* ; RET ; ; PERFORM DISK RESET ; CHUSB_DSKRES: ;PRTS("\n\rDSKRES:$") ; *DEBUG* LD A,CH_CMD_DSKRES ; DISK READY CALL CH_CMD ; DO IT CALL CH_POLL ; WAIT FOR RESPONSE ;CALL PC_SPACE ; *DEBUG* ;CALL PRTHEXBYTE ; *DEBUG* ; RET ; ; PERFORM DISK READY ; CHUSB_DSKRDY: ;PRTS("\n\rDSKRDY:$") ; *DEBUG* LD A,CH_CMD_DSKRDY ; DISK READY CALL CH_CMD ; DO IT CALL CH_POLL ; WAIT FOR RESPONSE ;CALL PC_SPACE ; *DEBUG* ;CALL PRTHEXBYTE ; *DEBUG* CP $14 ; *DEBUG* JR NZ,CHUSB_DSKRDY ; *DEBUG* ; RET ; ; PERFORM AUTO SETUP ; CHUSB_AUTOSET: ;PRTS("\n\rAUTOSET:$") ; *DEBUG* LD A,CH_CMD_AUTOSET ; AUTOMATIC SETUP FOR USB CALL CH_CMD ; DO IT CALL LDELAY ; *DEBUG* CALL CH_POLL ; WAIT FOR RESPONSE ;CALL PC_SPACE ; *DEBUG* ;CALL PRTHEXBYTE ; *DEBUG* ; RET ; ; PERFORM TEST CONNECT ; CHUSB_TSTCON: ;PRTS("\n\rTSTCON:$") ; *DEBUG* LD A,CH_CMD_TSTCON ; TEST USB DEVICE CONNECT CALL CH_CMD ; DO IT CALL CH_NAP ; WAIT A BIT CALL CH_RD ; GET RESPONSE ;CALL PC_SPACE ; *DEBUG* ;CALL PRTHEXBYTE ; *DEBUG* ; RET ; ; PERFORM GET MAX LUN ; CHUSB_MAXLUN: ;PRTS("\n\rMAXLUN:$") ; *DEBUG* LD A,CH_CMD_MAXLUN ; TEST USB DEVICE CONNECT CALL CH_CMD ; DO IT CALL CH_NAP ; WAIT A BIT LD A,$38 ; CONSTANT CALL CH_WR ; SEND IT CALL CH_NAP CALL CH_RD ; GET RESPONSE ;CALL PC_SPACE ; *DEBUG* ;CALL PRTHEXBYTE ; *DEBUG* ; RET ; #ENDIF ; ; ERROR HANDLERS ; ; CHUSB_NOMEDIA: LD A,CHUSB_STNOMEDIA JR CHUSB_ERR ; CHUSB_CMDERR: LD A,CHUSB_STCMDERR JR CHUSB_ERR ; CHUSB_IOERR: LD A,CHUSB_STIOERR JR CHUSB_ERR ; CHUSB_TO: LD A,CHUSB_STTO JR CHUSB_ERR ; CHUSB_NOTSUP: LD A,CHUSB_STNOTSUP JR CHUSB_ERR ; CHUSB_ERR: LD (IY+CHUSB_STAT),A ; SAVE NEW STATUS ; CHUSB_ERR2: #IF (CHUSBTRACE >= 2) CALL CHUSB_PRTSTAT #ENDIF OR A ; SET FLAGS RET ; ; ; CHUSB_PRTERR: RET Z ; DONE IF NO ERRORS ; FALL THRU TO CHUSB_PRTSTAT ; ; PRINT FULL DEVICE STATUS LINE ; CHUSB_PRTSTAT: PUSH AF PUSH DE PUSH HL LD A,(IY+CHUSB_STAT) CALL CHUSB_PRTPREFIX ; PRINT UNIT PREFIX CALL PC_SPACE ; FORMATTING CALL CHUSB_PRTSTATSTR POP HL POP DE POP AF RET ; ; PRINT STATUS STRING ; CHUSB_PRTSTATSTR: PUSH AF PUSH DE PUSH HL LD A,(IY+CHUSB_STAT) NEG LD HL,CHUSB_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 ; CHUSB_PRTPREFIX: PUSH AF CALL NEWLINE PRTS("CHUSB$") LD A,(IY+CH_DEV) ; GET CURRENT DEVICE NUM CALL PRTDECB CALL PC_COLON POP AF RET ; ; DATA STORAGE ; CHUSB_DEVNUM .DB 0 ; TEMP DEVICE NUM USED DURING INIT CHUSB_DSKBUF .DW 0 ; CHUSB_STR_ST_MAP: .DW CHUSB_STR_STOK .DW CHUSB_STR_STNOMEDIA .DW CHUSB_STR_STCMDERR .DW CHUSB_STR_STIOERR .DW CHUSB_STR_STTO .DW CHUSB_STR_STNOTSUP ; CHUSB_STR_STOK .TEXT "OK$" CHUSB_STR_STNOMEDIA .TEXT "NO MEDIA$" CHUSB_STR_STCMDERR .TEXT "COMMAND ERROR$" CHUSB_STR_STIOERR .TEXT "IO ERROR$" CHUSB_STR_STTO .TEXT "TIMEOUT$" CHUSB_STR_STNOTSUP .TEXT "NOT SUPPORTED$" CHUSB_STR_STUNK .TEXT "UNKNOWN ERROR$"