forked from MirrorRepos/RomWBW
Browse Source
- Split out the SD and USB specific support from the main CH37x driver to optimize code space usage. - Ensure CH37x mode switch is handled properly when there are multiple devices active in a system.patch v3.4.0-dev.38
6 changed files with 1541 additions and 1448 deletions
File diff suppressed because it is too large
@ -0,0 +1,685 @@ |
|||
; |
|||
;================================================================================================== |
|||
; 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 TRUE ; 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) |
|||
.ECHO "CHSD: IO=" |
|||
.ECHO CH0BASE |
|||
.ECHO "\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) |
|||
.ECHO "CHSD: IO=" |
|||
.ECHO CH1BASE |
|||
.ECHO "\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 |
|||
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 |
|||
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$" |
|||
@ -0,0 +1,792 @@ |
|||
; |
|||
;================================================================================================== |
|||
; 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) |
|||
.ECHO "CHUSB: IO=" |
|||
.ECHO CH0BASE |
|||
.ECHO "\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) |
|||
.ECHO "CHUSB: IO=" |
|||
.ECHO CH1BASE |
|||
.ECHO "\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 |
|||
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 |
|||
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$" |
|||
Loading…
Reference in new issue