mirror of https://github.com/wwarthen/RomWBW.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
852 lines
20 KiB
852 lines
20 KiB
;
|
|
;=============================================================================
|
|
; S100 ESP32 SD DISK DRIVER
|
|
;=============================================================================
|
|
;
|
|
; DISK DEVICE DRIVER FOR THE S100 ESP32-BASED SD INTERFACE FOUND
|
|
; ON THE S100 2CF+1CF BOARD AND THE DUAL SD BOARD AS DESIGNED BY
|
|
; JOHN MONAHAN.
|
|
;
|
|
; http://www.s100computers.com/My%20System%20Pages/IDE%202CF+SD%20Board/IDE%202CF+1SD%20Board.htm
|
|
; http://www.s100computers.com/My%20System%20Pages/Dual%20SD%20card%20Board/Dual%20SD%20card%20Board.htm
|
|
;
|
|
;
|
|
; TODO:
|
|
; - AVOID RESELECTING PRI/SEC ON EVERY I/O CALL
|
|
;
|
|
; NOTES:
|
|
;
|
|
; THE ESP32 IMPLEMENTS AN INTELLIGENT SD CARD CONTROLLER THAT HANDLES
|
|
; ALL OF THE SD CARD INTIALIZATION AND LOW-LEVEL I/O. IT EXPOSES A
|
|
; COMMAND/RESPONSE PROTOCOL. THE DUAL SD BOARD SUPPORTS TWO SD CARD
|
|
; DEVICES. SEPARATE INIT AND SELECT COMMANDS ARE PROVIDED TO HANDLE
|
|
; THIS AS NEEDED. THE 2CF+1SD SUPPORTS ONLY A SINGLE SD CARD DEVICE.
|
|
;
|
|
; TWO SEQUENTIAL I/O ADDRESSES ARE IMPLEMENTED. THE FIRST IS
|
|
; FOR STATUS AND THE SECOND IS FOR COMMAND & DATA EXCHANGE.
|
|
;
|
|
; === STATUS REGISTER (READ) ===
|
|
;
|
|
; 7 6 5 4 3 2 1 0
|
|
; +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
; | XIN | ERR | DSW | CS1 | CS0 | CD1 | CD0 | XOUT |
|
|
; +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
;
|
|
; XIN: DATA READ FROM ESP32 PENDING
|
|
; ERR: ERROR ACTIVE
|
|
; DSW: OLED DISPLAY ACTIVATION
|
|
; CS1: SD CARD 1 CHIP SELECT
|
|
; CS0: SD CARD 0 CHIP SELECT
|
|
; CD1: SD CARD 1 MEDIA PRESENT (CARD DETECT)
|
|
; CD0: SD CARD 0 MEDIA PRESENT (CARD DETECT)
|
|
; XOUT: DATA WRITE TO ESP32 PENDING
|
|
;
|
|
; === STATUS REGISTER (WRITE) ===
|
|
;
|
|
; 7 6 5 4 3 2 1 0
|
|
; +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
; | XIN | | | | | | | XOUT |
|
|
; +-------+-------+-------+-------+-------+-------+-------+-------+
|
|
;
|
|
; XIN: UNUSED???
|
|
; XOUT: ACTIVATE WRITE TO ESP32
|
|
;
|
|
ESPSD_IO_STATUS .EQU 0 ; OFFSET OF STATUS PORT FROM BASE I/O ADDRESS
|
|
ESPSD_IO_DATA .EQU 1 ; OFFSET OF DATA PORT FROM BASE I/O ADDRESS
|
|
;
|
|
ESPSD_CMD_INIT0 .EQU $80 ; Initialize primary SD Card
|
|
ESPSD_CMD_INIT1 .EQU $81 ; INITIALIZE SECONDARY SD CARD
|
|
ESPSD_CMD_SEL0 .EQU $82 ; (RE)SELECT PRIMARY SD CARD
|
|
ESPSD_CMD_SEL1 .EQU $83 ; (RE)SELECT SECONDARY SD CARD
|
|
ESPSD_CMD_SETLBA .EQU $84 ; SET LBA FOR SUBSEQUENT I/O
|
|
ESPSD_CMD_READ .EQU $85 ; READ SECTOR FROM SELECTED SD CARD AT CURRENT LBA
|
|
ESPSD_CMD_WRITE .EQU $86 ; WRITE SECTOR TO SELECTED SD CARD AT CURRENT LBA
|
|
ESPSD_CMD_FORMAT .EQU $87 ; FORMAT SECTOR ON SELECTED SD CARD AT CURRENT LBA
|
|
ESPSD_CMD_RESET .EQU $88 ; RESET ESP32 MODULE
|
|
;
|
|
; ESPSD DEVICE STATUS CODES
|
|
;
|
|
ESPSD_STOK .EQU 0
|
|
ESPSD_STNOMEDIA .EQU -1
|
|
ESPSD_STIOERR .EQU -2
|
|
ESPSD_STTO .EQU -3
|
|
ESPSD_STNOTRDY .EQU -4
|
|
;
|
|
; IDE DEVICE CONFIGURATION
|
|
;
|
|
ESPSD_CFGSIZ .EQU 12 ; SIZE OF CFG TBL ENTRIES
|
|
;
|
|
; PER DEVICE DATA OFFSETS
|
|
;
|
|
ESPSD_DEV .EQU 0 ; OFFSET OF DEVICE NUMBER (BYTE)
|
|
ESPSD_ROLE .EQU 1 ; 0=PRIMARY, 1=SECONDARY
|
|
ESPSD_IOBASE .EQU 2 ; IO BASE ADDRESS (BYTE)
|
|
ESPSD_STAT .EQU 3 ; LAST STATUS (BYTE)
|
|
ESPSD_MEDCAP .EQU 4 ; MEDIA CAPACITY (DWORD)
|
|
ESPSD_LBA .EQU 8 ; OFFSET OF LBA (DWORD)
|
|
;
|
|
ESPSD_CFGTBL:
|
|
;
|
|
#IF (ESPSDCNT >= 1)
|
|
;
|
|
ESPSD_DEV0P: ; DEVICE 0, PRIMARY
|
|
.DB $FE ; DRIVER DEVICE NUMBER (FILLED DYNAMICALLY)
|
|
.DB 0 ; PRIMARY
|
|
.DB ESPSD0BASE ; IO BASE ADDRESS
|
|
.DB ESPSD_STNOTRDY ; DEVICE STATUS
|
|
.DW $0000,$0001 ; DEVICE CAPACITY
|
|
.DW 0,0 ; CURRENT LBA
|
|
;
|
|
DEVECHO "ESPSD: IO="
|
|
DEVECHO ESPSD0BASE
|
|
DEVECHO ", PRIMARY"
|
|
DEVECHO "\n"
|
|
;
|
|
#IF (ESPSD0DUAL)
|
|
;
|
|
ESPSD_DEV0S: ; DEVICE 0, SECONDARY
|
|
.DB $FE ; DRIVER DEVICE NUMBER (FILLED DYNAMICALLY)
|
|
.DB 1 ; SECONDARY
|
|
.DB ESPSD0BASE ; IO BASE ADDRESS
|
|
.DB ESPSD_STNOTRDY ; DEVICE STATUS
|
|
.DW $0000,$0001 ; DEVICE CAPACITY
|
|
.DW 0,0 ; CURRENT LBA
|
|
;
|
|
DEVECHO "ESPSD: IO="
|
|
DEVECHO ESPSD0BASE
|
|
DEVECHO ", SECONDARY"
|
|
DEVECHO "\n"
|
|
;
|
|
#ENDIF
|
|
;
|
|
#ENDIF
|
|
;
|
|
#IF (ESPSDCNT >= 2)
|
|
;
|
|
ESPSD_DEV1P: ; DEVICE 1, PRIMARY
|
|
.DB $FE ; DRIVER DEVICE NUMBER (FILLED DYNAMICALLY)
|
|
.DB 0 ; PRIMARY
|
|
.DB ESPSD1BASE ; IO BASE ADDRESS
|
|
.DB ESPSD_STNOTRDY ; DEVICE STATUS
|
|
.DW $0000,$0001 ; DEVICE CAPACITY
|
|
.DW 0,0 ; CURRENT LBA
|
|
;
|
|
DEVECHO "ESPSD: IO="
|
|
DEVECHO ESPSD1BASE
|
|
DEVECHO ", PRIMARY"
|
|
DEVECHO "\n"
|
|
;
|
|
#IF (ESPSD1DUAL)
|
|
;
|
|
ESPSD_DEV1S: ; DEVICE 1, SECONDARY
|
|
.DB $FE ; DRIVER DEVICE NUMBER (FILLED DYNAMICALLY)
|
|
.DB 1 ; SECONDARY
|
|
.DB ESPSD1BASE ; IO BASE ADDRESS
|
|
.DB ESPSD_STNOTRDY ; DEVICE STATUS
|
|
.DW $0000,$0001 ; DEVICE CAPACITY
|
|
.DW 0,0 ; CURRENT LBA
|
|
;
|
|
DEVECHO "ESPSD: IO="
|
|
DEVECHO ESPSD1BASE
|
|
DEVECHO ", SECONDARY"
|
|
DEVECHO "\n"
|
|
;
|
|
#ENDIF
|
|
;
|
|
#ENDIF
|
|
;
|
|
#IF ($ - ESPSD_CFGTBL) != (ESPSDCNT * 2 * ESPSD_CFGSIZ)
|
|
.ECHO "*** INVALID ESPSD CONFIG TABLE ***\n"
|
|
#ENDIF
|
|
;
|
|
.DB $FF ; END OF TABLE MARKER
|
|
;
|
|
;=============================================================================
|
|
; INITIALIZATION ENTRY POINT
|
|
;=============================================================================
|
|
;
|
|
ESPSD_INIT:
|
|
;
|
|
XOR A ; ZERO ACCUM
|
|
LD (ESPSD_DEVNUM),A ; INIT DEV UNIT NUM FOR DYNAMIC ASSIGNMENT
|
|
LD IY,ESPSD_CFGTBL ; POINT TO START OF CONFIG TABLE
|
|
;
|
|
ESPSD_INIT1:
|
|
LD A,(IY) ; LOAD FIRST BYTE TO CHECK FOR END
|
|
CP $FF ; CHECK FOR END OF TABLE VALUE
|
|
JR NZ,ESPSD_INIT2 ; IF NOT END OF TABLE, CONTINUE
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; AND RETURN
|
|
;
|
|
ESPSD_INIT2:
|
|
CALL NEWLINE ; FORMATTING
|
|
PRTS("ESPSD:$") ; TAG
|
|
;
|
|
PRTS(" IO=0x$") ; LABEL FOR IO ADDRESS
|
|
LD A,(IY+ESPSD_IOBASE) ; GET IO BASE ADDRES
|
|
CALL PRTHEXBYTE ; DISPLAY IT
|
|
;
|
|
BIT 0,(IY+ESPSD_ROLE) ; GET ROLE BIT
|
|
JR NZ,ESPSD_INIT2A ; JUMP IF SECONDARY
|
|
PRTS(" PRIMARY$") ; SHOW PRIMATY
|
|
JR ESPSD_INIT2B ; JUMP AHEAD
|
|
ESPSD_INIT2A:
|
|
PRTS(" SECONDARY$") ; SHOW SECONDARY
|
|
ESPSD_INIT2B:
|
|
CALL ESPSD_DETECT ; PROBE FOR INTERFACE
|
|
JR Z,ESPSD_INIT3 ; GOT IT, MOVE ON TO INIT UNITS
|
|
PRTS(" NOT PRESENT$") ; SHOW NOT PRESENT
|
|
JR ESPSD_INIT4 ; SKIP CFG ENTRY
|
|
;
|
|
ESPSD_INIT3:
|
|
CALL ESPSD_INIT5 ; REGISTER & INIT DEVICE
|
|
;
|
|
ESPSD_INIT4:
|
|
LD DE,ESPSD_CFGSIZ ; SIZE OF CFG TABLE ENTRY
|
|
ADD IY,DE ; BUMP POINTER
|
|
JP ESPSD_INIT1 ; AND LOOP
|
|
;
|
|
ESPSD_INIT5:
|
|
; UPDATE DRIVER RELATIVE UNIT NUMBER IN CONFIG TABLE
|
|
LD A,(ESPSD_DEVNUM) ; GET NEXT UNIT NUM TO ASSIGN
|
|
LD (IY+ESPSD_DEV),A ; UPDATE IT
|
|
INC A ; BUMP TO NEXT UNIT NUM TO ASSIGN
|
|
LD (ESPSD_DEVNUM),A ; SAVE IT
|
|
;
|
|
; ADD UNIT TO GLOBAL DISK UNIT TABLE
|
|
LD BC,ESPSD_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 ESPSD_INITDEV ; INITIALIZE DEVICE
|
|
#IF (ESPSDTRACE < 2)
|
|
JP NZ,ESPSD_PRTSTAT
|
|
#ENDIF
|
|
RET NZ
|
|
;
|
|
CALL ESPSD_PRTPREFIX ; TAG FOR ACTIVE DEVICE
|
|
;
|
|
; PRINT STORAGE CAPACITY (BLOCK COUNT)
|
|
PRTS(" BLOCKS=0x$") ; PRINT FIELD LABEL
|
|
LD A,ESPSD_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 ; SUCCESS
|
|
RET
|
|
;
|
|
;=============================================================================
|
|
; DRIVER FUNCTION TABLE
|
|
;=============================================================================
|
|
;
|
|
ESPSD_FNTBL:
|
|
.DW ESPSD_STATUS
|
|
.DW ESPSD_RESET
|
|
.DW ESPSD_SEEK
|
|
.DW ESPSD_READ
|
|
.DW ESPSD_WRITE
|
|
.DW ESPSD_VERIFY
|
|
.DW ESPSD_FORMAT
|
|
.DW ESPSD_DEVICE
|
|
.DW ESPSD_MEDIA
|
|
.DW ESPSD_DEFMED
|
|
.DW ESPSD_CAP
|
|
.DW ESPSD_GEOM
|
|
#IF (($ - ESPSD_FNTBL) != (DIO_FNCNT * 2))
|
|
.ECHO "*** INVALID IDE FUNCTION TABLE ***\n"
|
|
#ENDIF
|
|
;
|
|
ESPSD_VERIFY:
|
|
ESPSD_FORMAT:
|
|
ESPSD_DEFMED:
|
|
SYSCHKERR(ERR_NOTIMPL) ; NOT IMPLEMENTED
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
ESPSD_READ:
|
|
CALL HB_DSKREAD ; HOOK HBIOS DISK READ SUPERVISOR
|
|
|
|
;;;CALL NEWLINE
|
|
;;;LD A,'R'
|
|
;;;CALL COUT
|
|
;;;CALL PRTHEXWORDHL
|
|
|
|
LD A,ESPSD_CMD_READ ; SETUP FOR BLOCK READ CMD
|
|
JP ESPSD_IO ; CONTINUE TO GENERIC IO ROUTINE
|
|
;
|
|
;
|
|
;
|
|
ESPSD_WRITE:
|
|
CALL HB_DSKWRITE ; HOOK HBIOS DISK WRITE SUPERVISOR
|
|
|
|
;;;CALL NEWLINE
|
|
;;;LD A,'W'
|
|
;;;CALL COUT
|
|
;;;CALL PRTHEXWORDHL
|
|
|
|
LD A,ESPSD_CMD_WRITE ; SETUP FOR BLOCK WRITE CMD
|
|
JP ESPSD_IO ; CONTINUE TO GENERIC IO ROUTINE
|
|
;
|
|
;
|
|
;
|
|
ESPSD_STATUS:
|
|
;;;LD A,'S'
|
|
;;;CALL COUT
|
|
; RETURN UNIT STATUS
|
|
LD A,(IY+ESPSD_STAT) ; GET STATUS OF SELECTED DEVICE
|
|
OR A ; SET FLAGS
|
|
RET ; AND RETURN
|
|
;
|
|
;
|
|
;
|
|
ESPSD_RESET:
|
|
;;;LD A,'R'
|
|
;;;CALL COUT
|
|
CALL ESPSD_INITDEV ; REINITIALIZE UNIT
|
|
OR A ; SET RESULT FLAGS
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
ESPSD_DEVICE:
|
|
;;;LD A,'D'
|
|
;;;CALL COUT
|
|
LD D,DIODEV_ESPSD ; D := DEVICE TYPE
|
|
LD E,(IY+ESPSD_DEV) ; E := PHYSICAL DEVICE NUMBER
|
|
LD C,%00110010 ; C := ATTRIBUTES, REMOVABLE, SD CARD
|
|
LD H,0 ; H := MODE
|
|
LD L,(ESPSD_IOBASE) ; L := BASE I/O ADDRESS
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
; ESPSD_GETMED
|
|
;
|
|
ESPSD_MEDIA:
|
|
;;;LD A,'M'
|
|
;;;CALL COUT
|
|
LD A,E ; GET FLAGS
|
|
OR A ; SET FLAGS
|
|
JR Z,ESPSD_MEDIA1 ; JUST REPORT CURRENT STATUS AND MEDIA
|
|
;
|
|
CALL ESPSD_INITDEV ; REINITIALIZE DEVICE
|
|
;
|
|
ESPSD_MEDIA1:
|
|
LD A,(IY+ESPSD_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
|
|
;
|
|
;
|
|
;
|
|
ESPSD_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+ESPSD_LBA+0),L ; SAVE NEW LBA
|
|
LD (IY+ESPSD_LBA+1),H ; ...
|
|
LD (IY+ESPSD_LBA+2),E ; ...
|
|
LD (IY+ESPSD_LBA+3),D ; ...
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; AND RETURN
|
|
;
|
|
;
|
|
;
|
|
ESPSD_CAP:
|
|
;;;LD A,'C'
|
|
;;;CALL COUT
|
|
LD A,(IY+ESPSD_STAT) ; GET STATUS
|
|
PUSH AF ; SAVE IT
|
|
LD A,ESPSD_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
|
|
;
|
|
;
|
|
;
|
|
ESPSD_GEOM:
|
|
;;;LD A,'G'
|
|
;;;CALL COUT
|
|
; 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 ESPSD_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 ESPSD_CAP STATUS
|
|
;
|
|
;=============================================================================
|
|
; FUNCTION SUPPORT ROUTINES
|
|
;=============================================================================
|
|
;
|
|
; ON RETURN, ZF SET INDICATES HARDWARE FOUND
|
|
;
|
|
ESPSD_DETECT:
|
|
; WE USE A DUMMY SETLBA COMMAND TO TEST FOR PRESENCE
|
|
LD HL,0 ; IRRELEVANT
|
|
JP ESPSD_SETLBA ; PASS OFF TO SETLBA
|
|
;
|
|
; INITIALIZE DEVICE
|
|
;
|
|
ESPSD_INITDEV:
|
|
; CHECK CARD DETECT
|
|
LD A,(IY+ESPSD_ROLE) ; GET ROLE
|
|
LD B,%00000010 ; MASK FOR PRIMARY
|
|
OR A ; TEST ROLE
|
|
JR Z,ESPSD_INITDEV1 ; IF PRIMARY, JUMP AHEAD
|
|
LD B,%00000100 ; MASK FOR SECONDARY
|
|
ESPSD_INITDEV1:
|
|
LD C,(IY+ESPSD_IOBASE) ; STATUS PORT
|
|
IN A,(C) ; GET STATUS
|
|
AND B ; APPLY MASK
|
|
JP Z,ESPSD_NOMEDIA ; IF NO CARD, HANDLE AS NO MEDIA
|
|
;
|
|
CALL ESPSD_INITCARD ; PERFORM DEVICE INIT
|
|
JP NZ,ESPSD_NOMEDIA ; CONVERT TO NO MEDIA ERROR
|
|
;
|
|
; GET CAPACITY
|
|
; NOT CURRENTLY AVAILABLE IN ESP32 API
|
|
; CAPACITY IS HARD-CODED ABOVE AT API MAX OF $10000 BLOCKS
|
|
;
|
|
; RESET STATUS
|
|
LD A,ESPSD_STOK
|
|
LD (IY+ESPSD_STAT),A
|
|
XOR A
|
|
RET
|
|
;
|
|
; COMMON SECTOR I/O
|
|
;
|
|
ESPSD_IO:
|
|
LD (ESPSD_CMDVAL),A ; SAVE THE COMMAND
|
|
LD (ESPSD_DSKBUF),HL ; SAVE DISK BUFFER ADDRESS
|
|
;
|
|
; CHECK FOR ERROR STATUS AND REINIT?
|
|
;
|
|
#IF (ESPSDTRACE == 1)
|
|
LD HL,ESPSD_PRTERR ; SET UP SD_PRTERR
|
|
PUSH HL ; ... TO FILTER ALL EXITS
|
|
#ENDIF
|
|
;
|
|
; SELECT PRI/SEC DEVICE
|
|
CALL ESPSD_SELECT ; SELECT DEVICE
|
|
JP NZ,ESPSD_ERR ; ON ERROR, RECORD AND BAIL OUT
|
|
;CALL LDELAY ; *DEBUG*
|
|
;
|
|
; SET LBA
|
|
LD A,ESPSD_LBA ; OFFSET OF LBA VALUE
|
|
CALL LDHLIYA ; HL := IY + A, REG A TRASHED
|
|
CALL HB_DSKACT ; SHOW ACTIVITY
|
|
CALL LD32 ; LOAD IT TO DE:HL, AF IS TRASHED
|
|
CALL ESPSD_SETLBA ; SEND LBA TO DEVICE
|
|
;JP ESPSD_IOERR ; *DEBUG*
|
|
JP NZ,ESPSD_ERR ; ON ERROR, RECORD AND BAIL OUT
|
|
;CALL LDELAY ; *DEBUG*
|
|
;
|
|
; PERFORM BLOCK READ/WRITE
|
|
LD HL,(ESPSD_DSKBUF) ; RECOVER THE DISK BUFFER ADR
|
|
LD A,(ESPSD_CMDVAL) ; GET ORIGINAL CMD
|
|
CP ESPSD_CMD_READ ; READ?
|
|
JR NZ,ESPSD_IO2 ; IF NOT, SKIP AHEAD
|
|
CALL ESPSD_BLKREAD ; DO THE READ
|
|
JR ESPSD_IO3 ; CONTINUE
|
|
ESPSD_IO2:
|
|
CALL ESPSD_BLKWRITE ; DO THE WRITE
|
|
ESPSD_IO3:
|
|
JP NZ,ESPSD_ERR ; ON ERROR, RECORD AND BAIL OUT
|
|
;CALL LDELAY ; *DEBUG*
|
|
;
|
|
; INCREMENT LBA
|
|
LD A,ESPSD_LBA ; LBA OFFSET
|
|
CALL LDHLIYA ; HL := IY + A, REG A TRASHED
|
|
CALL INC32HL ; INCREMENT THE VALUE
|
|
;
|
|
; INCREMENT DMA
|
|
LD HL,ESPSD_DSKBUF+1 ; POINT TO MSB OF BUFFER ADR
|
|
INC (HL) ; BUMP DMA BY
|
|
INC (HL) ; ... 512 BYTES
|
|
;
|
|
; CLEAN UP
|
|
LD HL,(ESPSD_DSKBUF) ; CURRENT DMA TO HL
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; AND DONE
|
|
;
|
|
;=============================================================================
|
|
; COMMAND PROCESSING
|
|
;=============================================================================
|
|
;
|
|
; INITIALIZE DEVICE
|
|
;
|
|
ESPSD_INITCARD:
|
|
LD A,ESPSD_CMD_INIT0 ; INIT PRIMARY DEVICE
|
|
ADD A,(IY+ESPSD_ROLE) ; ADJUST FOR PRI/SEC
|
|
JR ESPSD_RUNCMD ; USE COMMON CMD ROUTINE
|
|
;
|
|
; (RE)SELECT DEVICE
|
|
;
|
|
ESPSD_SELECT:
|
|
LD A,ESPSD_CMD_SEL0 ; INIT PRIMARY DEVICE
|
|
ADD A,(IY+ESPSD_ROLE) ; ADJUST FOR PRI/SEC
|
|
JR ESPSD_RUNCMD ; USE COMMON CMD ROUTINE
|
|
;
|
|
; SIMPLE COMMAND COMMON CODE
|
|
;
|
|
ESPSD_RUNCMD:
|
|
LD E,A ; PUT IN E
|
|
CALL ESPSD_CMD_SLOW ; SEND COMMAND
|
|
RET NZ ; HANDLE ERROR
|
|
CALL ESPSD_GETBYTE_SLOW ; GET RESULT
|
|
RET NZ ; HANDLE ERROR
|
|
LD A,E ; RESULT TO ACCUM
|
|
OR A ; SET FLAGS
|
|
RET Z ; RETURN SUCCESS
|
|
LD A,ESPSD_STNOTRDY ; CALL THIS A NOT READY ERR
|
|
OR A ; SET FLAGS
|
|
RET ; DONE
|
|
;
|
|
; SET CURRENT LBA TO VALUE IN DE:HL
|
|
; HIGH WORD (DE) IS CURRENTLY IGNORED BECAUSE API ONLY SUPPORTS
|
|
; A 16-BIT LBA.
|
|
;
|
|
ESPSD_SETLBA:
|
|
LD E,ESPSD_CMD_SETLBA
|
|
CALL ESPSD_CMD_SLOW
|
|
RET NZ
|
|
LD E,H
|
|
CALL ESPSD_PUTBYTE_SLOW
|
|
RET NZ
|
|
LD E,L
|
|
CALL ESPSD_PUTBYTE_SLOW
|
|
RET NZ
|
|
CALL ESPSD_GETBYTE_SLOW
|
|
RET NZ
|
|
LD A,E ; RESULT TO ACCUM
|
|
OR A ; SET FLAGS
|
|
RET Z ; GOOD RETURN
|
|
LD A,ESPSD_STIOERR ; CALL THIS AN IO ERROR
|
|
OR A
|
|
RET
|
|
;
|
|
; BLOCK READ 512 BYTES TO ADDRESS IN HL
|
|
;
|
|
ESPSD_BLKREAD:
|
|
LD E,ESPSD_CMD_READ
|
|
CALL ESPSD_CMD_SLOW
|
|
RET NZ
|
|
;
|
|
LD B,0 ; LOOP COUNTER
|
|
ESPSD_BLKREAD1:
|
|
PUSH BC
|
|
CALL ESPSD_GETBYTE_SLOW
|
|
RET NZ
|
|
LD (HL),E
|
|
INC HL
|
|
CALL ESPSD_GETBYTE_SLOW
|
|
RET NZ
|
|
LD (HL),E
|
|
INC HL
|
|
POP BC
|
|
DJNZ ESPSD_BLKREAD1
|
|
;
|
|
CALL ESPSD_GETBYTE_SLOW ; GET RESULT
|
|
RET NZ ; HANDLE ERROR
|
|
LD A,E ; RESULT TO ACCUM
|
|
OR A ; SET FLAGS
|
|
RET Z ; GOOD RETURN
|
|
LD A,ESPSD_STIOERR ; CALL THIS AN IO ERROR
|
|
OR A ; SET FLAGS
|
|
RET ; DONE
|
|
;
|
|
; BLOCK WRITE
|
|
;
|
|
ESPSD_BLKWRITE:
|
|
LD E,ESPSD_CMD_WRITE
|
|
CALL ESPSD_CMD_SLOW
|
|
RET NZ
|
|
;
|
|
LD B,0 ; LOOP COUNTER
|
|
ESPSD_BLKWRITE1:
|
|
PUSH BC
|
|
LD E,(HL)
|
|
INC HL
|
|
CALL ESPSD_PUTBYTE_SLOW
|
|
RET NZ
|
|
LD E,(HL)
|
|
INC HL
|
|
CALL ESPSD_PUTBYTE_SLOW
|
|
RET NZ
|
|
POP BC
|
|
DJNZ ESPSD_BLKWRITE1
|
|
;
|
|
CALL ESPSD_GETBYTE_SLOW ; GET RESULT
|
|
RET NZ ; HANDLE ERROR
|
|
LD A,E ; RESULT TO ACCUM
|
|
OR A ; SET FLAGS
|
|
RET Z ; GOOD RETURN
|
|
LD A,ESPSD_STIOERR ; CALL THIS AN IO ERROR
|
|
OR A ; SET FLAGS
|
|
RET ; DONE
|
|
;
|
|
;=============================================================================
|
|
; HARDWARE INTERFACE ROUTINES
|
|
;=============================================================================
|
|
;
|
|
; SEND COMMAND BYTE IN E TO ESP32
|
|
;
|
|
ESPSD_CMD:
|
|
PUSH DE
|
|
LD E,$33
|
|
CALL ESPSD_PUTBYTE
|
|
POP DE
|
|
RET NZ
|
|
JR ESPSD_PUTBYTE
|
|
;
|
|
; SEND COMMAND BYTE IN E TO ESP32
|
|
;
|
|
ESPSD_CMD_SLOW:
|
|
PUSH DE
|
|
LD E,$33
|
|
CALL ESPSD_PUTBYTE_SLOW
|
|
POP DE
|
|
RET NZ
|
|
JR ESPSD_PUTBYTE_SLOW
|
|
;
|
|
; WRITE BYTE IN E TO ESP32
|
|
; RETURN STATUS IN A (0=SUCCESS)
|
|
;
|
|
ESPSD_PUTBYTE:
|
|
#IF (ESPSDTRACE >= 3)
|
|
CALL PC_GT
|
|
#ENDIF
|
|
LD B,0
|
|
LD C,(IY+ESPSD_IOBASE)
|
|
ESPSD_PUTBYTE1:
|
|
IN A,(C)
|
|
BIT 0,A
|
|
JR Z,ESPSD_PUTBYTE2
|
|
;JR ESPSD_PUTBYTE1 ; *DEBUG*
|
|
DJNZ ESPSD_PUTBYTE1
|
|
LD A,ESPSD_STTO
|
|
OR A
|
|
RET
|
|
ESPSD_PUTBYTE2:
|
|
INC C
|
|
OUT (C),E
|
|
;
|
|
#IF (ESPSDTRACE >= 3)
|
|
LD A,E
|
|
CALL PRTHEXBYTE
|
|
#ENDIF
|
|
;
|
|
XOR A
|
|
RET
|
|
;
|
|
; WRITE BYTE TO ESP32 FROM E WITH EXTRA LONG TIMEOUT
|
|
;
|
|
ESPSD_PUTBYTE_SLOW:
|
|
PUSH HL
|
|
LD HL,50 * CPUMHZ ; CPU SPEED SCALED TIMEOUT
|
|
ESPSD_PUTBYTE_SLOW1:
|
|
PUSH HL
|
|
CALL ESPSD_PUTBYTE
|
|
POP HL
|
|
JR Z,ESPSD_PUTBYTE_SLOW_Z
|
|
DEC HL
|
|
LD A,H
|
|
OR L
|
|
JR NZ,ESPSD_PUTBYTE_SLOW1
|
|
LD A,ESPSD_STTO
|
|
ESPSD_PUTBYTE_SLOW_Z:
|
|
;CALL PC_SPACE ; *DEBUG*
|
|
;CALL PRTHEXWORDHL ; *DEBUG*
|
|
POP HL
|
|
OR A ; SET FLAGS
|
|
RET
|
|
;
|
|
; READ BYTE FROM ESP32 INTO E
|
|
; RETURN STATUS IN A (0=SUCCESS)
|
|
;
|
|
ESPSD_GETBYTE:
|
|
#IF (ESPSDTRACE >= 3)
|
|
CALL PC_LT
|
|
#ENDIF
|
|
LD B,0
|
|
LD C,(IY+ESPSD_IOBASE)
|
|
ESPSD_GETBYTE1:
|
|
IN A,(C)
|
|
BIT 7,A
|
|
JR NZ,ESPSD_GETBYTE2
|
|
DJNZ ESPSD_GETBYTE1
|
|
LD A,ESPSD_STTO
|
|
OR A
|
|
RET
|
|
ESPSD_GETBYTE2:
|
|
INC C
|
|
IN E,(C)
|
|
;
|
|
#IF (ESPSDTRACE >= 3)
|
|
LD A,E
|
|
CALL PRTHEXBYTE
|
|
#ENDIF
|
|
;
|
|
XOR A
|
|
RET
|
|
;
|
|
; READ BYTE FROM ESP32 INTO E WITH EXTRA LONG TIMEOUT
|
|
;
|
|
ESPSD_GETBYTE_SLOW:
|
|
PUSH HL
|
|
LD HL,50 * CPUMHZ ; CPU SPEED SCALED TIMEOUT
|
|
ESPSD_GETBYTE_SLOW1:
|
|
PUSH HL
|
|
CALL ESPSD_GETBYTE
|
|
POP HL
|
|
JR Z,ESPSD_GETBYTE_SLOW_Z
|
|
DEC HL
|
|
LD A,H
|
|
OR L
|
|
JR NZ,ESPSD_GETBYTE_SLOW1
|
|
LD A,ESPSD_STTO
|
|
ESPSD_GETBYTE_SLOW_Z:
|
|
;CALL PC_SPACE ; *DEBUG*
|
|
;CALL PRTHEXWORDHL ; *DEBUG*
|
|
POP HL
|
|
OR A ; SET FLAGS
|
|
RET
|
|
;
|
|
;=============================================================================
|
|
; ERROR HANDLING AND DIAGNOSTICS
|
|
;=============================================================================
|
|
;
|
|
; ERROR HANDLERS
|
|
;
|
|
ESPSD_NOMEDIA:
|
|
LD A,ESPSD_STNOMEDIA
|
|
JR ESPSD_ERR
|
|
;
|
|
ESPSD_IOERR:
|
|
LD A,ESPSD_STIOERR
|
|
JR ESPSD_ERR
|
|
;
|
|
ESPSD_TO:
|
|
LD A,ESPSD_STTO
|
|
JR ESPSD_ERR
|
|
;
|
|
ESPSD_NOTRDY:
|
|
LD A,ESPSD_STNOTRDY
|
|
JR ESPSD_ERR
|
|
;
|
|
ESPSD_ERR:
|
|
LD (IY+ESPSD_STAT),A ; SAVE NEW STATUS
|
|
;
|
|
#IF (ESPSDTRACE >= 2)
|
|
CALL ESPSD_PRTSTAT
|
|
#ENDIF
|
|
OR A ; SET FLAGS
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
ESPSD_PRTERR:
|
|
RET Z ; DONE IF NO ERRORS
|
|
; FALL THRU TO ESPSD_PRTSTAT
|
|
;
|
|
; PRINT FULL DEVICE STATUS LINE
|
|
;
|
|
ESPSD_PRTSTAT:
|
|
PUSH AF
|
|
PUSH DE
|
|
PUSH HL
|
|
LD A,(IY+ESPSD_STAT)
|
|
CALL ESPSD_PRTPREFIX ; PRINT UNIT PREFIX
|
|
JR ESPSD_PRTSTAT3
|
|
ESPSD_PRTSTAT2:
|
|
CALL NEWLINE
|
|
PRTS("ESPSD:$") ; NO UNIT NUM IN PREFIX FOR INVALID UNIT
|
|
ESPSD_PRTSTAT3:
|
|
CALL PC_SPACE ; FORMATTING
|
|
CALL ESPSD_PRTSTATSTR
|
|
POP HL
|
|
POP DE
|
|
POP AF
|
|
RET
|
|
;
|
|
; PRINT STATUS STRING
|
|
;
|
|
ESPSD_PRTSTATSTR:
|
|
PUSH AF
|
|
PUSH DE
|
|
LD A,(IY+ESPSD_STAT)
|
|
OR A
|
|
LD DE,ESPSD_STR_STOK
|
|
JR Z,ESPSD_PRTSTATSTR1
|
|
INC A
|
|
LD DE,ESPSD_STR_STNOMEDIA
|
|
JR Z,ESPSD_PRTSTATSTR1
|
|
INC A
|
|
LD DE,ESPSD_STR_STIOERR
|
|
JR Z,ESPSD_PRTSTATSTR1
|
|
INC A
|
|
LD DE,ESPSD_STR_STTO
|
|
JR Z,ESPSD_PRTSTATSTR1
|
|
INC A
|
|
LD DE,ESPSD_STR_STNOTRDY
|
|
JR Z,ESPSD_PRTSTATSTR1
|
|
LD DE,ESPSD_STR_STUNK
|
|
ESPSD_PRTSTATSTR1:
|
|
CALL WRITESTR
|
|
POP DE
|
|
POP AF
|
|
RET
|
|
;
|
|
; PRINT DIAGNONSTIC PREFIX
|
|
;
|
|
ESPSD_PRTPREFIX:
|
|
PUSH AF
|
|
CALL NEWLINE
|
|
PRTS("ESPSD$")
|
|
LD A,(IY+ESPSD_DEV) ; GET CURRENT DEVICE NUM
|
|
CP $FE ; NOT YET ASSIGNED?
|
|
JR Z,ESPSD_PRTPREFIX1 ; SKIP DEV NUM IF SO
|
|
CALL PRTDECB
|
|
ESPSD_PRTPREFIX1:
|
|
CALL PC_COLON
|
|
POP AF
|
|
RET
|
|
;
|
|
;=============================================================================
|
|
; STRING DATA
|
|
;=============================================================================
|
|
;
|
|
ESPSD_STR_STOK .TEXT "OK$"
|
|
ESPSD_STR_STNOMEDIA .TEXT "NO MEDIA$"
|
|
ESPSD_STR_STIOERR .TEXT "IO ERROR$"
|
|
ESPSD_STR_STTO .TEXT "TIMEOUT$"
|
|
ESPSD_STR_STNOTRDY .TEXT "NOT READY$"
|
|
ESPSD_STR_STUNK .TEXT "UNKNOWN ERROR$"
|
|
;
|
|
;=============================================================================
|
|
; DATA STORAGE
|
|
;=============================================================================
|
|
;
|
|
ESPSD_CMDVAL .DB 0 ; PENDING COMMAND FOR IO FUCNTIONS
|
|
ESPSD_DSKBUF .DW 0 ; ACTIVE DISK BUFFER
|
|
;
|
|
ESPSD_DEVNUM .DB 0 ; TEMP DEVICE NUM USED DURING INIT
|
|
|