diff --git a/Doc/Source/RomWBW Architecture.docx b/Doc/Source/RomWBW Architecture.docx index 026bf8c5..3071afbc 100644 Binary files a/Doc/Source/RomWBW Architecture.docx and b/Doc/Source/RomWBW Architecture.docx differ diff --git a/Doc/Source/WBW.vsdx b/Doc/Source/WBW.vsdx new file mode 100644 index 00000000..5bdd6536 Binary files /dev/null and b/Doc/Source/WBW.vsdx differ diff --git a/Source/HBIOS/Config/mk4_dsd.asm b/Source/HBIOS/Config/mk4_dsd.asm index 4b0f4f2b..71a35c91 100644 --- a/Source/HBIOS/Config/mk4_dsd.asm +++ b/Source/HBIOS/Config/mk4_dsd.asm @@ -50,38 +50,32 @@ IDEMODE .EQU IDEMODE_MK4 ; IDEMODE_DIO, IDEMODE_DIDE, IDEMODE_MK4 IDECNT .EQU 1 ; NUMBER OF IDE UNITS IDETRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF IDEENABLE = TRUE) IDE8BIT .EQU TRUE ; USE IDE 8BIT TRANSFERS (PROBABLY ONLY WORKS FOR CF CARDS!) -IDECAPACITY .EQU 64 ; CAPACITY OF DEVICE (IN MB) ; PPIDEENABLE .EQU FALSE ; TRUE FOR PPIDE SUPPORT (DO NOT COMBINE WITH DSKYENABLE) PPIDEIOB .EQU $60 ; PPIDE IOBASE PPIDECNT .EQU 1 ; NUMBER OF PPIDE UNITS PPIDETRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF PPIDEENABLE = TRUE) PPIDE8BIT .EQU FALSE ; USE IDE 8BIT TRANSFERS (PROBABLY ONLY WORKS FOR CF CARDS!) -PPIDECAPACITY .EQU 64 ; CAPACITY OF DEVICE (IN MB) PPIDESLOW .EQU FALSE ; ADD DELAYS TO HELP PROBLEMATIC HARDWARE (TRY THIS IF PPIDE IS UNRELIABLE) ; SDENABLE .EQU TRUE ; TRUE FOR SD SUPPORT SDMODE .EQU SDMODE_DSD ; SDMODE_JUHA, SDMODE_CSIO, SDMODE_UART, SDMODE_PPI, SDMODE_DSD, SDMODE_MK4 SDTRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF IDEENABLE = TRUE) -SDCAPACITY .EQU 64 ; CAPACITY OF DEVICE (IN MB) SDCSIOFAST .EQU TRUE ; TABLE-DRIVEN BIT INVERTER ; PRPENABLE .EQU FALSE ; TRUE FOR PROPIO SD SUPPORT (FOR N8VEM PROPIO ONLY!) PRPIOB .EQU $A8 ; PORT IO ADDRESS BASE PRPSDENABLE .EQU TRUE ; TRUE FOR PROPIO SD SUPPORT (FOR N8VEM PROPIO ONLY!) PRPSDTRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF PRPSDENABLE = TRUE) -PRPSDCAPACITY .EQU 64 ; CAPACITY OF DEVICE (IN MB) PRPCONENABLE .EQU TRUE ; TRUE FOR PROPIO CONSOLE SUPPORT (PS/2 KBD & VGA VIDEO) ; PPPENABLE .EQU FALSE ; TRUE FOR PARPORTPROP SUPPORT PPPSDENABLE .EQU TRUE ; TRUE FOR PARPORTPROP SD SUPPORT PPPSDTRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF PPPENABLE = TRUE) -PPPSDCAPACITY .EQU 64 ; CAPACITY OF PPP SD DEVICE (IN MB) PPPCONENABLE .EQU TRUE ; TRUE FOR PROPIO CONSOLE SUPPORT (PS/2 KBD & VGA VIDEO) ; HDSKENABLE .EQU FALSE ; TRUE FOR SIMH HDSK SUPPORT HDSKTRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF IDEENABLE = TRUE) -HDSKCAPACITY .EQU 64 ; CAPACITY OF DEVICE (IN MB) ; PPKENABLE .EQU FALSE ; TRUE FOR PARALLEL PORT KEYBOARD PPKTRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF PPKENABLE = TRUE) diff --git a/Source/HBIOS/Config/mk4_std.asm b/Source/HBIOS/Config/mk4_std.asm index 4cb4cf3c..49ceab34 100644 --- a/Source/HBIOS/Config/mk4_std.asm +++ b/Source/HBIOS/Config/mk4_std.asm @@ -47,41 +47,35 @@ RFCNT .EQU 1 ; NUMBER OF RAM FLOPPY UNITS ; IDEENABLE .EQU TRUE ; TRUE FOR IDE SUPPORT IDEMODE .EQU IDEMODE_MK4 ; IDEMODE_DIO, IDEMODE_DIDE, IDEMODE_MK4 -IDECNT .EQU 1 ; NUMBER OF IDE UNITS -IDETRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF IDEENABLE = TRUE) +IDECNT .EQU 2 ; NUMBER OF IDE UNITS +IDETRACE .EQU 2 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF IDEENABLE = TRUE) IDE8BIT .EQU TRUE ; USE IDE 8BIT TRANSFERS (PROBABLY ONLY WORKS FOR CF CARDS!) -IDECAPACITY .EQU 64 ; CAPACITY OF DEVICE (IN MB) ; PPIDEENABLE .EQU FALSE ; TRUE FOR PPIDE SUPPORT (DO NOT COMBINE WITH DSKYENABLE) PPIDEIOB .EQU $60 ; PPIDE IOBASE PPIDECNT .EQU 1 ; NUMBER OF PPIDE UNITS PPIDETRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF PPIDEENABLE = TRUE) PPIDE8BIT .EQU FALSE ; USE IDE 8BIT TRANSFERS (PROBABLY ONLY WORKS FOR CF CARDS!) -PPIDECAPACITY .EQU 64 ; CAPACITY OF DEVICE (IN MB) PPIDESLOW .EQU FALSE ; ADD DELAYS TO HELP PROBLEMATIC HARDWARE (TRY THIS IF PPIDE IS UNRELIABLE) ; SDENABLE .EQU TRUE ; TRUE FOR SD SUPPORT SDMODE .EQU SDMODE_MK4 ; SDMODE_JUHA, SDMODE_CSIO, SDMODE_UART, SDMODE_PPI, SDMODE_DSD, SDMODE_MK4 -SDTRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF IDEENABLE = TRUE) -SDCAPACITY .EQU 64 ; CAPACITY OF DEVICE (IN MB) +SDTRACE .EQU 2 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF IDEENABLE = TRUE) SDCSIOFAST .EQU TRUE ; TABLE-DRIVEN BIT INVERTER ; PRPENABLE .EQU FALSE ; TRUE FOR PROPIO SD SUPPORT (FOR N8VEM PROPIO ONLY!) PRPIOB .EQU $A8 ; PORT IO ADDRESS BASE PRPSDENABLE .EQU TRUE ; TRUE FOR PROPIO SD SUPPORT (FOR N8VEM PROPIO ONLY!) PRPSDTRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF PRPSDENABLE = TRUE) -PRPSDCAPACITY .EQU 64 ; CAPACITY OF DEVICE (IN MB) PRPCONENABLE .EQU TRUE ; TRUE FOR PROPIO CONSOLE SUPPORT (PS/2 KBD & VGA VIDEO) ; PPPENABLE .EQU FALSE ; TRUE FOR PARPORTPROP SUPPORT PPPSDENABLE .EQU TRUE ; TRUE FOR PARPORTPROP SD SUPPORT PPPSDTRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF PPPENABLE = TRUE) -PPPSDCAPACITY .EQU 64 ; CAPACITY OF PPP SD DEVICE (IN MB) PPPCONENABLE .EQU TRUE ; TRUE FOR PROPIO CONSOLE SUPPORT (PS/2 KBD & VGA VIDEO) ; HDSKENABLE .EQU FALSE ; TRUE FOR SIMH HDSK SUPPORT HDSKTRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF IDEENABLE = TRUE) -HDSKCAPACITY .EQU 64 ; CAPACITY OF DEVICE (IN MB) ; PPKENABLE .EQU FALSE ; TRUE FOR PARALLEL PORT KEYBOARD PPKTRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF PPKENABLE = TRUE) diff --git a/Source/HBIOS/hdsk.asm b/Source/HBIOS/hdsk.asm index ce70779f..a5fa3efe 100644 --- a/Source/HBIOS/hdsk.asm +++ b/Source/HBIOS/hdsk.asm @@ -79,7 +79,7 @@ HDSK_CAP: XOR A ; SIGNAL SUCCESS RET ; -SD_GEOM: +HDSK_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 SD_CAP ; GET TOTAL BLOCKS IN DE:HL, BLOCK SIZE TO BC diff --git a/Source/HBIOS/ide.asm b/Source/HBIOS/ide.asm index f43eb982..4c7ec737 100644 --- a/Source/HBIOS/ide.asm +++ b/Source/HBIOS/ide.asm @@ -1,72 +1,205 @@ ; -;================================================================================================== +;============================================================================= ; IDE DISK DRIVER -;================================================================================================== -; -#IF (IDETRACE >= 2) +;============================================================================= +; +; TODO: +; - IMPLEMENT IDE_INITDEVICE +; +; +-----------------------------------------------------------------------+ +; | CONTROL BLOCK REGISTERS | +; +-----------------------+-------+-------+-------------------------------+ +; | REGISTER | PORT | DIR | DESCRIPTION | +; +-----------------------+-------+-------+-------------------------------+ +; | IDE_IO_ALTSTAT | 0x0E | R | ALTERNATE STATUS REGISTER | +; | IDE_IO_CTRL | 0x0E | W | DEVICE CONTROL REGISTER | +; | IDE_IO_DRVADR | 0x0F | R | DRIVE ADDRESS REGISTER | +; +-----------------------+-------+-------+-------------------------------+ +; +; +-----------------------+-------+-------+-------------------------------+ +; | COMMAND BLOCK REGISTERS | +; +-----------------------+-------+-------+-------------------------------+ +; | REGISTER | PORT | DIR | DESCRIPTION | +; +-----------------------+-------+-------+-------------------------------+ +; | IDE_IO_DATA | 0x00 | R/W | DATA INPUT/OUTPUT | +; | IDE_IO_ERR | 0x01 | R | ERROR REGISTER | +; | IDE_IO_FEAT | 0x01 | W | FEATURES REGISTER | +; | IDE_IO_COUNT | 0x02 | R/W | SECTOR COUNT REGISTER | +; | IDE_IO_SECT | 0x03 | R/W | SECTOR NUMBER REGISTER | +; | IDE_IO_CYLLO | 0x04 | R/W | CYLINDER NUM REGISTER (LSB) | +; | IDE_IO_CYLHI | 0x05 | R/W | CYLINDER NUM REGISTER (MSB) | +; | IDE_IO_DRVHD | 0x06 | R/W | DRIVE/HEAD REGISTER | +; | IDE_IO_LBA0* | 0x03 | R/W | LBA BYTE 0 (BITS 0-7) | +; | IDE_IO_LBA1* | 0x04 | R/W | LBA BYTE 1 (BITS 8-15) | +; | IDE_IO_LBA2* | 0x05 | R/W | LBA BYTE 2 (BITS 16-23) | +; | IDE_IO_LBA3* | 0x06 | R/W | LBA BYTE 3 (BITS 24-27) | +; | IDE_IO_STAT | 0x07 | R | STATUS REGISTER | +; | IDE_IO_CMD | 0x07 | W | COMMAND REGISTER (EXECUTE) | +; +-----------------------+-------+-------+-------------------------------+ +; * LBA0-4 ARE ALTERNATE DEFINITIONS OF SECT, CYL, AND DRVHD PORTS +; +; === STATUS REGISTER === +; +; 7 6 5 4 3 2 1 0 +; +-------+-------+-------+-------+-------+-------+-------+-------+ +; | BSY | DRDY | DWF | DSC | DRQ | CORR | IDX | ERR | +; +-------+-------+-------+-------+-------+-------+-------+-------+ +; +; BSY: BUSY +; DRDY: DRIVE READY +; DWF: DRIVE WRITE FAULT +; DSC: DRIVE SEEK COMPLETE +; DRQ: DATA REQUEST +; CORR: CORRECTED DATA +; IDX: INDEX +; ERR: ERROR +; +; === ERROR REGISTER === +; +; 7 6 5 4 3 2 1 0 +; +-------+-------+-------+-------+-------+-------+-------+-------+ +; | BBK | UNC | MC | IDNF | MCR | ABRT | TK0NF | AMNF | +; +-------+-------+-------+-------+-------+-------+-------+-------+ +; (VALID WHEN ERR BIT IS SET IN STATUS REGISTER) +; +; BBK: BAD BLOCK DETECTED +; UNC: UNCORRECTABLE DATA ERROR +; MC: MEDIA CHANGED +; IDNF: ID NOT FOUND +; MCR: MEDIA CHANGE REQUESTED +; ABRT: ABORTED COMMAND +; TK0NF: TRACK 0 NOT FOUND +; AMNF: ADDRESS MARK NOT FOUND +; +; === DRIVE/HEAD / LBA3 REGISTER === +; +; 7 6 5 4 3 2 1 0 +; +-------+-------+-------+-------+-------+-------+-------+-------+ +; | 1 | L | 1 | DRV | HS3 | HS2 | HS1 | HS0 | +; +-------+-------+-------+-------+-------+-------+-------+-------+ +; +; L: 0 = CHS ADDRESSING, 1 = LBA ADDRESSING +; DRV: 0 = DRIVE 0 (PRIMARY) SELECTED, 1 = DRIVE 1 (SLAVE) SELECTED +; HS: CHS = HEAD ADDRESS (0-15), LBA = BITS 24-27 OF LBA +; +; === DEVICE CONTROL REGISTER === +; +; 7 6 5 4 3 2 1 0 +; +-------+-------+-------+-------+-------+-------+-------+-------+ +; | X | X | X | X | 1 | SRST | ~IEN | 0 | +; +-------+-------+-------+-------+-------+-------+-------+-------+ +; +; SRST: SOFTWARE RESET +; ~IEN: INTERRUPT ENABLE +; +#IF (IDETRACE >= 3) #DEFINE DCALL CALL #ELSE #DEFINE DCALL \; #ENDIF ; -; IO PORT ADDRESSES +; UNIT MAPPING IS AS FOLLOWS: +; IDE0: PRIMARY MASTER +; IDE1: PRIMARY SLAVE +; IDE2: SECONDARY MASTER +; IDE3: SECONDARY SLAVE +; +IDE_UNITCNT .EQU 2 ; ASSUME ONLY PRIMARY INTERFACE ; #IF (IDEMODE == IDEMODE_MK4) -IDEBASE .EQU MK4_IDE +IDE_IO_BASE .EQU MK4_IDE #ELSE -IDEBASE .EQU $20 +IDE_IO_BASE .EQU $20 #ENDIF #IF ((IDEMODE == IDEMODE_DIO) | (IDEMODE == IDEMODE_MK4)) #IF (IDE8BIT) -IDEDATA .EQU $IDEBASE + $00 ; DATA PORT (8 BIT) +IDE_IO_DATA .EQU $IDE_IO_BASE + $00 ; DATA PORT (8 BIT PIO) (R/W) #ELSE -IDEDATALO .EQU $IDEBASE + $00 ; DATA PORT (16 BIT LO BYTE) -IDEDATAHI .EQU $IDEBASE + $08 ; DATA PORT (16 BIT HI BYTE) -IDEDATA .EQU IDEDATALO +IDE_IO_DATALO .EQU $IDE_IO_BASE + $00 ; DATA PORT (16 BIT PIO LO BYTE) (R/W) +IDE_IO_DATAHI .EQU $IDE_IO_BASE + $08 ; DATA PORT (16 BIT PIO HI BYTE) (R/W) +IDE_IO_DATA .EQU IDE_IO_DATALO #ENDIF #ENDIF ; #IF (IDEMODE == IDEMODE_DIDE) +IDE_UNITCNT .SET 4 ; DIDE HAS PRIMARY AND SECONDARY INTERACES #IF (IDE8BIT) -IDEDATA .EQU $IDEBASE + $00 ; DATA PORT (8 BIT OR 16 BIT PIO LO/HI BYTES) +IDE_IO_DATA .EQU $IDE_IO_BASE + $00 ; DATA PORT (8 BIT PIO) (R/W) #ELSE -IDEDATA .EQU $IDEBASE + $08 ; DATA PORT (16 BIT PIO LO/HI BYTES) -IDEDMA .EQU $IDEBASE + $09 ; DATA PORT (16 BIT DMA LO/HI BYTES) +IDE_IO_DATA .EQU $IDE_IO_BASE + $08 ; DATA PORT (16 BIT PIO LO/HI BYTES) (R/W) +IDE_IO_DMA .EQU $IDE_IO_BASE + $09 ; DATA PORT (16 BIT DMA LO/HI BYTES) (R/W) #ENDIF #ENDIF ; -IDEERR .EQU $IDEBASE + $01 ; READ: ERROR REGISTER; WRITE: PRECOMP -IDESECTC .EQU $IDEBASE + $02 ; SECTOR COUNT -IDESECTN .EQU $IDEBASE + $03 ; SECTOR NUMBER -IDECYLLO .EQU $IDEBASE + $04 ; CYLINDER LOW -IDECYLHI .EQU $IDEBASE + $05 ; CYLINDER HIGH -IDEDEVICE .EQU $IDEBASE + $06 ; DRIVE/HEAD -IDESTTS .EQU $IDEBASE + $07 ; READ: STATUS; WRITE: COMMAND -IDECTRL .EQU $IDEBASE + $0E ; READ: ALTERNATIVE STATUS; WRITE; DEVICE CONTROL -IDEADDR .EQU $IDEBASE + $0F ; DRIVE ADDRESS (READ ONLY) +;IDE_IO_DATA .EQU $IDE_IO_BASE + $00 ; DATA INPUT/OUTPUT (R/W) +IDE_IO_ERR .EQU $IDE_IO_BASE + $01 ; ERROR REGISTER (R) +IDE_IO_FEAT .EQU $IDE_IO_BASE + $01 ; FEATURES REGISTER (W) +IDE_IO_COUNT .EQU $IDE_IO_BASE + $02 ; SECTOR COUNT REGISTER (R/W) +IDE_IO_SECT .EQU $IDE_IO_BASE + $03 ; SECTOR NUMBER REGISTER (R/W) +IDE_IO_CYLLO .EQU $IDE_IO_BASE + $04 ; CYLINDER NUM REGISTER (LSB) (R/W) +IDE_IO_CYLHI .EQU $IDE_IO_BASE + $05 ; CYLINDER NUM REGISTER (MSB) (R/W) +IDE_IO_DRVHD .EQU $IDE_IO_BASE + $06 ; DRIVE/HEAD REGISTER (R/W) +IDE_IO_LBA0 .EQU $IDE_IO_BASE + $03 ; LBA BYTE 0 (BITS 0-7) (R/W) +IDE_IO_LBA1 .EQU $IDE_IO_BASE + $03 ; LBA BYTE 1 (BITS 8-15) (R/W) +IDE_IO_LBA2 .EQU $IDE_IO_BASE + $03 ; LBA BYTE 2 (BITS 16-23) (R/W) +IDE_IO_LBA3 .EQU $IDE_IO_BASE + $03 ; LBA BYTE 3 (BITS 24-27) (R/W) +IDE_IO_STAT .EQU $IDE_IO_BASE + $07 ; STATUS REGISTER (R) +IDE_IO_CMD .EQU $IDE_IO_BASE + $07 ; COMMAND REGISTER (EXECUTE) (W) +IDE_IO_ALTSTAT .EQU $IDE_IO_BASE + $0E ; ALTERNATE STATUS REGISTER (R) +IDE_IO_CTRL .EQU $IDE_IO_BASE + $0E ; DEVICE CONTROL REGISTER (W) +IDE_IO_DRVADR .EQU $IDE_IO_BASE + $0F ; DRIVE ADDRESS REGISTER (R) +; +; COMMAND BYTES +; +IDE_CMD_RECAL .EQU $10 +IDE_CMD_READ .EQU $20 +IDE_CMD_WRITE .EQU $30 +IDE_CMD_IDDEV .EQU $EC +IDE_CMD_SETFEAT .EQU $EF +; +; FEATURE BYTES ; +IDE_FEAT_ENABLE8BIT .EQU $01 +IDE_FEAT_DISABLE8BIT .EQU $81 ; +; IDE DEVICE TYPES ; -IDECMD_RECAL .EQU $10 -IDECMD_READ .EQU $20 -IDECMD_WRITE .EQU $30 -IDECMD_IDDEV .EQU $EC -IDECMD_SETFEAT .EQU $EF +IDE_TYPEUNK .EQU 0 +IDE_TYPEATA .EQU 1 +IDE_TYPEATAPI .EQU 2 ; -IDE_RCOK .EQU 0 -IDE_RCCMDERR .EQU 1 -IDE_RCRDYTO .EQU 2 -IDE_RCBUFTO .EQU 3 -IDE_RCBSYTO .EQU 4 +; IDE DEVICE STATUS ; -; UNIT CONFIGURATION +IDE_STOK .EQU 0 +IDE_STINVUNIT .EQU -1 +IDE_STNOMEDIA .EQU -2 +IDE_STCMDERR .EQU -3 +IDE_STIOERR .EQU -4 +IDE_STRDYTO .EQU -5 +IDE_STDRQTO .EQU -6 +IDE_STBSYTO .EQU -7 ; -IDE_DEVICES: -IDE_DEVICE0 .DB %11100000 ; LBA, MASTER DEVICE -IDE_DEVICE1 .DB %11110000 ; LBA, SLAVE DEVICE +; DRIVE SELECTION BYTES (FOR USE IN DRIVE/HEAD REGISTER) ; +IDE_DRVSEL: +IDE_DRVMASTER .DB %11100000 ; LBA, MASTER DEVICE +IDE_DRVSLAVE .DB %11110000 ; LBA, SLAVE DEVICE ; +; PER UNIT DATA OFFSETS (CAREFUL NOT TO EXCEED PER UNIT SPACE IN IDE_UNITDATA) +; SEE IDE_UNITDATA IN DATA STORAGE BELOW +; +IDE_STAT .EQU 0 ; LAST STATUS (1 BYTE) +IDE_TYPE .EQU 1 ; DEVICE TYPE (1 BYTE) +IDE_CAPACITY .EQU 2 ; DEVICE CAPACITY (1 DWORD/4 BYTES) +; +; MACRO TO RETURN POINTER TO FIELD WITHIN UNIT DATA +; +#DEFINE IDE_DPTR(FIELD) CALL IDE_DPTRIMP \ .DB FIELD +; +;============================================================================= +; INITIALIZATION ENTRY POINT +;============================================================================= ; IDE_INIT: PRTS("IDE:$") ; LABEL FOR IO ADDRESS @@ -81,116 +214,87 @@ IDE_INIT: PRTS(" MODE=MK4$") #ENDIF ; PRINT IDE INTERFACE PORT ADDRESS - PRTS(" IO=0x$") ; LABEL FOR IO ADDRESS - LD A,IDEDATA ; GET IO ADDRESS + PRTS(" IO=0x$") ; LABEL FOR IO ADDRESS + LD A,IDE_IO_DATA ; GET IO ADDRESS CALL PRTHEXBYTE ; PRINT IT ; - ; RESET INTERFACE - CALL IDE_RESET ; INTERFACE RESET - CALL DELAY ; SMALL DELAY + ; CLEAR OUT ALL DATA (FOR ALL UNITS) + LD HL,IDE_UDATA + LD BC,IDE_UDLEN + XOR A + CALL FILL ; - ; SET GLOBAL STATUS TO OK (ZERO) - XOR A ; STATUS OK - LD (IDE_STAT),A ; INITIALIZE IT + ; INITIALIZE THE IDE INTERFACE NOW + CALL IDE_RESET ; DO HARDWARE SETUP/INIT + JR NZ,IDE_INIT2 ; SKIP PROBING IF INTERFACE SETUP FAILS ; - ; PROBE FOR DEVICE(S) - LD A,(IDE_DEVICE0) ; DEVICE 0 + ; INITIAL DEVICE PROBING (CHECKING SIGNATURES) + LD B,IDE_UNITCNT ; NUMBER OF UNITS TO TRY + LD C,0 ; UNIT INDEX FOR LOOP +IDE_INIT1: + LD A,C ; UNIT NUMBER TO A DCALL PC_SPACE ; IF DEBUGGING, PRINT A SPACE DCALL PC_LBKT ; IF DEBUGGING, PRINT LEFT BRACKET - CALL IDE_PROBE ; PROBE FOR DEVICE 0 PRESENCE - DCALL PC_RBKT ; IF DEBUGGING, PRINT A RIGHT BRACKET - JR NZ,IDE_INIT1 ; IF DEVCIE 0 NOT PRESENT, SKIP DEVICE 1 PROBE - LD HL,IDE_UNITCNT ; POINT TO UNIT COUNT - INC (HL) ; INCREMENT IT - LD A,(IDE_DEVICE1) ; DEVICE 1 - DCALL PC_SPACE ; IF DEBUGGING, PRINT A SPACE - DCALL PC_LBKT ; IF DEBUGGING, PRINT A LEFT BRACKET - CALL IDE_PROBE ; PROBE FOR DEVICE 1 PRESENT + PUSH BC + CALL IDE_PROBE ; PROBE FOR DEVICE PRESENCE + POP BC DCALL PC_RBKT ; IF DEBUGGING, PRINT A RIGHT BRACKET - JR NZ,IDE_INIT1 ; IF DEVICE 1 NOT PRESENT, SKIP - LD HL,IDE_UNITCNT ; POINT TO UNIT COUNT - INC (HL) ; INCREMENT IT -; -IDE_INIT1: - ; RESTORE DEFAULT DEVICE SELECTION (DEVICE 0) - LD A,(IDE_DEVICE0) ; DEVICE 0 - OUT (IDEDEVICE),A ; SELECT IT - CALL DELAY ; SMALL DELAY AFTER SELECT + INC C ; NEXT UNIT + DJNZ IDE_INIT1 ; LOOP AS NEEDED ; ; PRINT UNIT COUNT PRTS(" UNITS=$") ; PRINT LABEL FOR UNIT COUNT - LD A,(IDE_UNITCNT) ; GET UNIT COUNT + LD A,IDE_UNITCNT ; GET UNIT COUNT CALL PRTDECB ; PRINT IT IN DECIMAL ; - ; CHECK FOR ZERO DEVICES AND BAIL OUT IF SO - LD A,(IDE_UNITCNT) ; GET UNIT COUNT - OR A ; SET FLAGS - RET Z ; IF ZERO, WE ARE DONE +IDE_INIT2: + ; CHECK FOR ZERO UNITS AND GET OUT IF SO! ; ; DEVICE SETUP LOOP LD B,A ; LOOP ONCE PER UNIT LD C,0 ; C IS UNIT INDEX -IDE_INIT2: +IDE_INIT3: PUSH BC ; SAVE LOOP CONTROL - CALL IDE_INIT3 ; HANDLE THE NEXT UNIT + LD A,C ; UNIT NUM TO ACCUM + CALL IDE_INITUNIT ; IF EXISTS (NZ), INIT UNIT +#IF (IDETRACE < 2) + CALL NZ,IDE_PRTSTAT ; IF ERROR, NOTIFY USER IF NOT DONE PREVIOUSLY +#ENDIF POP BC ; RESTORE LOOP CONTROL INC C ; INCREMENT UNIT INDEX - DJNZ IDE_INIT2 ; LOOP UNTIL DONE + DJNZ IDE_INIT3 ; LOOP UNTIL DONE RET ; INIT FINISHED ; -IDE_INIT3: ; SUBROUTINE TO QUERY A DEVICE - - ; PRINT PREFIX FOR UNIT INFO "IDE#:" - CALL NEWLINE ; FORMATTING: START A NEW LINE - LD DE,IDESTR_PREFIX ; POINT TO STRING "IDE" - CALL WRITESTR ; PRINT STRING - LD A,C ; UNIT NUMBER TO ACCUM - LD (IDE_CURUNIT),A ; SAVE THE CURRENT UNIT - CALL PRTDECB ; PRINT IT IN DECIMAL - CALL PC_COLON ; PRINT THE ENDING COLON -; - LD A,C ; UNIT NUMBER TO ACCUM - CALL IDE_SELECT ; SELECT THE CORRECT DEVICE +; INITIALIZE UNIT DESIGNATED IN ACCUM +; +IDE_INITUNIT: + CALL IDE_SELUNIT ; SELECT UNIT + RET NZ ; ABORT ON ERROR +; + CALL IDE_INITDEV ; INIT DEVICE; FILL DIOBUF W/ IDENTIFY RESULTS + RET NZ ; ABORT ON ERROR +; + CALL IDE_PRTPREFIX ; PRINT DEVICE PREFIX ; #IF (IDE8BIT) PRTS(" 8BIT$") - CALL IDE_SET8BIT ; SET 8BIT TRANSFER FEATURE - RET NZ ; BAIL OUT ON ERROR #ENDIF -; - CALL IDE_IDENTIFY ; EXECUTE IDENTIFY COMMAND - RET NZ ; BAIL OUT ON ERROR -; - LD DE,(DIOBUF) ; POINT TO BUFFER - DCALL DUMP_BUFFER ; DUMP IT IF DEBUGGING ; ; PRINT LBA/NOLBA - CALL PC_SPACE ; SPACING + CALL PC_SPACE ; FORMATTING LD HL,(DIOBUF) ; POINT TO BUFFER START LD DE,98+1 ; OFFSET OF BYTE CONTAINING LBA FLAG ADD HL,DE ; POINT TO FINAL BUFFER ADDRESS LD A,(HL) ; GET THE BYTE BIT 1,A ; CHECK THE LBA BIT - LD DE,IDESTR_NO ; POINT TO "NO" STRING + LD DE,IDE_STR_NO ; POINT TO "NO" STRING CALL Z,WRITESTR ; PRINT "NO" BEFORE "LBA" IF LBA NOT SUPPORTED PRTS("LBA$") ; PRINT "LBA" REGARDLESS ; - ; PRECOMPUTE LOC TO STORE 32-BIT CAPACITY - LD HL,IDE_CAPLIST ; POINT TO CAPACITY ARRAY - LD A,(IDE_CURUNIT) ; GET CUR UNIT NUM - RLCA ; MULTIPLY BY 4 - RLCA ; ... TO OFFSET BY DWORDS - CALL ADDHLA ; ADD OFFSET TO POINTER - PUSH HL ; SAVE POINTER -; - ; GET, SAVE, AND PRINT STORAGE CAPACITY (BLOCK COUNT) + ; PRINT STORAGE CAPACITY (BLOCK COUNT) PRTS(" BLOCKS=0x$") ; PRINT FIELD LABEL - LD HL,(DIOBUF) ; POINT TO BUFFER START - LD DE,120 ; OFFSET OF SECGTOR COUNT - ADD HL,DE ; POINT TO ADDRESS OF SECTOR COUNT - CALL LD32 ; LOAD IT TO DE:HL - POP BC ; RECOVER POINTER TO CAPACITY ARRAY ENTRY - CALL ST32 ; SAVE CAPACITY + IDE_DPTR(IDE_CAPACITY) ; SET HL TO ADR OF DEVICE CAPACITY + CALL LD32 ; GET THE CAPACITY VALUE CALL PRTHEX32 ; PRINT HEX VALUE ; ; PRINT STORAGE SIZE IN MB @@ -200,12 +304,19 @@ IDE_INIT3: ; SUBROUTINE TO QUERY A DEVICE CALL PRTDEC ; PRINT LOW WORD IN DECIMAL (HIGH WORD DISCARDED) PRTS("MB$") ; PRINT SUFFIX ; - RET -; + XOR A ; SIGNAL SUCCESS + RET ; RETURN WITH A=0, AND Z SET ; +;============================================================================= +; FUNCTION DISPATCH ENTRY POINT +;============================================================================= ; IDE_DISPATCH: - LD A,B ; GET REQUESTED FUNCTION + LD A,C ; DEVICE/UNIT TO A + AND $0F ; REMOVE DEVICE BITS LEAVING JUST UNIT ID + CALL IDE_SELUNIT ; SELECT DESIRED UNIT + RET NZ ; ABORT ON ERROR + LD A,B ; GET REQUESTED FUNCTION AND $0F JR Z,IDE_READ DEC A @@ -214,189 +325,434 @@ IDE_DISPATCH: JR Z,IDE_STATUS DEC A JR Z,IDE_MEDIA + DEC A + JR Z,IDE_CAP + DEC A + JR Z,IDE_GEOM CALL PANIC ; ; ; IDE_READ: - LD A,IDECMD_READ - LD (IDE_CMD),A - CALL IDE_RW - RET NZ - CALL IDE_BUFRD - RET + JP IDE_RDSEC ; ; ; IDE_WRITE: - LD A,IDECMD_WRITE - LD (IDE_CMD),A - CALL IDE_RW - RET NZ - CALL IDE_BUFWR - RET + JP IDE_WRSEC ; ; ; IDE_STATUS: - LD A,(IDE_STAT) ; LOAD STATUS - OR A ; SET FLAGS - RET + ; RETURN UNIT STATUS + IDE_DPTR(IDE_STAT) ; HL := ADR OF STATUS, AF TRASHED + LD A,(HL) ; GET STATUS OF SELECTED UNIT + OR A ; SET FLAGS + RET ; AND RETURN ; ; IDE_MEDIA ; IDE_MEDIA: - LD A,C ; GET THE DEVICE/UNIT - AND $0F ; ISOLATE UNIT - LD HL,IDE_UNITCNT ; POINT TO UNIT COUNT - CP (HL) ; COMPARE TO UNIT COUNT - LD A,MID_HD ; ASSUME WE ARE OK - RET C ; RETURN - XOR A ; NO MEDIA - RET ; AND RETURN -; -; -; -IDE_RW: - ; SELECT DEVICE - LD A,(HSTDSK) ; HSTDSK -> HEAD BIT 4 TO SELECT UNIT - AND $0F - CALL IDE_SELECT - CALL IDE_SETUP ; SETUP CYL, TRK, HEAD - JR IDE_RUNCMD ; RETURN THRU RUNCMD -; + CALL IDE_INITDEVICE ; RE-INIT SELECTED UNIT + LD A,MID_HD ; ASSUME WE ARE OK + RET Z ; RETURN IF GOOD INIT + LD A,MID_NONE ; SIGNAL NO MEDA + OR A ; SET FLAGS + RET ; AND RETURN ; +; NEED TO IMPLEMENT BELOW!!!! ; -IDE_RUNCMD: - ; CLEAR RESULTS - XOR A ; A = 0 - LD (IDE_STAT),A ; CLEAR DRIVER STATUS CODE - LD (IDE_STTS),A ; CLEAR SAVED STTS - LD (IDE_ERRS),A ; CLEAR SAVED ERR - CALL IDE_WAITRDY ; WAIT FOR DRIVE READY - RET NZ ; BAIL OUT ON TIMEOUT - LD A,(IDE_CMD) ; GET THE COMMAND - OUT (IDESTTS),A ; SEND IT (STARTS EXECUTION) - CALL IDE_WAITRDY ; WAIT FOR DRIVE READY (COMMAND DONE) - RET NZ ; BAIL OUT ON TIMEOUT - CALL IDE_CHKERR ; CHECK FOR ERRORS - RET NZ ; BAIL OUT ON TIMEOUT - DCALL IDE_PRT ; PRINT COMMAND IF DEBUG ENABLED - XOR A ; SET RESULT - RET ; DONE +IDE_INITDEVICE: + XOR A + RET ; ; ; -IDE_ERRCMD: - LD A,IDE_RCCMDERR - JR IDE_ERR +IDE_CAP: + IDE_DPTR(IDE_CAPACITY) ; POINT HL TO CAPACITY OF CUR UNIT + CALL LD32 ; GET THE CURRENT CAPACITY DO DE:HL + LD BC,512 ; 512 BYTES PER BLOCK + XOR A ; SIGNAL SUCCESS + RET ; AND DONE ; -IDE_ERRRDYTO: - LD A,IDE_RCRDYTO - JR IDE_ERR ; -IDE_ERRBUFTO: - LD A,IDE_RCBUFTO - JR IDE_ERR ; -IDE_ERRBSYTO: - LD A,IDE_RCBSYTO - JR IDE_ERR +IDE_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 IDE_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 + XOR A ; SIGNAL SUCCESS + RET ; -IDE_ERR: - LD (IDE_STAT),A ; SAVE ERROR AS STATUS -#IF (IDETRACE >= 1) - PUSH AF ; SAVE ACCUM - CALL IDE_PRT ; PRINT COMMAND SUMMARY - POP AF ; RESTORE ACCUM -#ENDIF - OR A ; MAKE SURE FLAGS ARE SET - RET ; DONE +;============================================================================= +; FUNCTION SUPPORT ROUTINES +;============================================================================= ; -; SOFT RESET OF ALL DEVICES +; SOFT RESET OF ALL DEVICES ON BUS ; IDE_RESET: LD A,%00001110 ; NO INTERRUPTS, ASSERT RESET BOTH DRIVES - OUT (IDECTRL),A + OUT (IDE_IO_CTRL),A LD DE,16 ; DELAY ~250US CALL VDELAY LD A,%00001010 ; NO INTERRUPTS, DEASSERT RESET - OUT (IDECTRL),A - XOR A - LD (IDE_STAT),A ; STATUS OK - RET ; SAVE IT + OUT (IDE_IO_CTRL),A + CALL DELAY ; SMALL DELAY + XOR A ; SIGNAL SUCCESS + RET ; RETURN ; -; SELECT DEVICE IN A +; TAKE ANY ACTIONS REQUIRED TO SELECT DESIRED PHYSICAL UNIT +; UNIT IS SPECIFIED IN A ; -IDE_SELECT: - LD HL,IDE_DEVICES - CALL ADDHLA - LD A,(HL) ; LOAD DEVICE - LD (IDE_DEVICE),A ; SHADOW REGISTER - - CALL IDE_WAITBSY - RET NZ +IDE_SELUNIT: + LD HL,IDE_UNIT ; POINT TO PREVIOUSLY SELECTED UNIT + CP (HL) ; SAME? + RET Z ; IF SO, NOTHING MORE TO DO - LD A,(IDE_DEVICE) ; RECOVER DEVICE VALUE - OUT (IDEDEVICE),A ; SELECT DEVICE - ; DELAY??? + CP IDE_UNITCNT ; CHECK VALIDITY (EXCEED UNIT COUNT?) + JP NC,IDE_INVUNIT ; HANDLE INVALID UNIT +; + ; NEW UNIT SELECTED, IMPLEMENT IT + LD (IDE_UNIT),A ; RECORD NEW UNIT NUMBER +; +#IF (IDEMODE == IDEMODE_DIDE) + ; SELECT PRIMARY/SECONDARY INTERFACE FOR DIDE HARDWARE +#ENDIF +; + AND $01 ; LS BIT DETERMINES MASTER/SLAVE + LD HL,IDE_DRVSEL + CALL ADDHLA + LD A,(HL) ; LOAD DRIVE/HEAD VALUE +; + OUT (IDE_IO_DRVHD),A ; SELECT DRIVE + LD (IDE_DRVHD),A ; UPDATE SHADOW REGISTER +; + ; SPEC REQUIRES 400NS DELAY BEFORE CHECKING STATUS REGISTER +; + XOR A RET ; +; (RE)INITIALIZE DEVICE +; +IDE_INITDEV: +; + IDE_DPTR(IDE_TYPE) ; POINT HL TO UNIT TYPE FIELD, A IS TRASHED + LD A,(HL) ; GET THE DEVICE TYPE + OR A ; SET FLAGS + JP Z,IDE_NOMEDIA ; EXIT SETTING NO MEDIA STATUS +; + ; CLEAR OUT UNIT SPECIFIC DATA, BUT PRESERVE THE EXISTING + ; VALUE OF THE UNIT TYPE WHICH WAS ESTABLISHED BY THE DEVICE + ; PROBES WHEN THE IDE BUS WAS RESET + PUSH AF ; SAVE UNIT TYPE VALUE FROM ABOVE + PUSH HL ; SAVE UNIT TYPE FIELD POINTER + IDE_DPTR(0) ; SET HL TO START OF UNIT DATA + LD BC,IDE_UDLEN + XOR A + CALL FILL + POP HL ; RECOVER UNIT TYPE FIELD POINTER + POP AF ; RECOVER UNIT TYPE VALUE + LD (HL),A ; AND PUT IT BACK +; +#IF (IDE8BIT) + LD A,IDE_FEAT_ENABLE8BIT ; FEATURE VALUE = ENABLE 8-BIT PIO + CALL IDE_SETFEAT ; SET FEATURE + RET NZ ; BAIL OUT ON ERROR +#ENDIF +; + CALL IDE_IDENTIFY ; EXECUTE IDENTIFY COMMAND + RET NZ ; BAIL OUT ON ERROR +; + LD DE,(DIOBUF) ; POINT TO BUFFER + DCALL DUMP_BUFFER ; DUMP IT IF DEBUGGING +; + ; GET DEVICE CAPACITY AND SAVE IT + IDE_DPTR(IDE_CAPACITY) ; POINT HL TO UNIT CAPACITY FIELD + PUSH HL ; SAVE POINTER + LD HL,(DIOBUF) ; POINT TO BUFFER START + LD A,120 ; OFFSET OF SECTOR COUNT + CALL ADDHLA ; POINT TO ADDRESS OF SECTOR COUNT + CALL LD32 ; LOAD IT TO DE:HL + POP BC ; RECOVER POINTER TO CAPACITY ENTRY + CALL ST32 ; SAVE CAPACITY +; + ; RESET CARD STATUS TO 0 (OK) + IDE_DPTR(IDE_STAT) ; HL := ADR OF STATUS, AF TRASHED + XOR A ; A := 0 (STATUS = OK) + LD (HL),A ; SAVE IT +; + RET ; RETURN, A=0, Z SET +; ; ; IDE_PROBE: - OUT (IDEDEVICE),A ; SELECT IT + CALL IDE_SELUNIT ; SELECT UNIT + RET NZ ; ABORT ON ERROR CALL DELAY - IN A,(IDESECTC) +; + ; CHECK STATUS + IN A,(IDE_IO_STAT) ; GET STATUS + DCALL PRTHEXBYTE ; IF DEBUG, PRINT STATUS + OR A ; SET FLAGS TO TEST FOR ZERO + JR NZ,IDE_PROBE0 ; CONTINUE IF NON-ZERO + DEC A ; ZERO MEANS NO MEDIA, SIGNAL ERROR + RET ; AND DONE +; +IDE_PROBE0: + ;CALL IDE_WAITBSY ; WAIT FOR BUSY TO CLEAR + ;RET NZ ; ABORT ON TIMEOUT +; + ;; CHECK STATUS + ;IN A,(IDE_IO_STAT) ; GET STATUS + ;DCALL PRTHEXBYTE ; IF DEBUG, PRINT STATUS + ;OR A ; SET FLAGS TO TEST FOR ZERO + ;JR NZ,IDE_PROBE1 ; CONTINUE IF NON-ZERO + ;DEC A ; ZERO MEANS NO MEDIA, SIGNAL ERROR + ;RET ; AND DONE +; +IDE_PROBE1: + ; CHECK SIGNATURE + DCALL PC_SPACE + IN A,(IDE_IO_COUNT) DCALL PRTHEXBYTE CP $01 RET NZ DCALL PC_SPACE - IN A,(IDESECTN) + IN A,(IDE_IO_SECT) DCALL PRTHEXBYTE CP $01 RET NZ DCALL PC_SPACE - IN A,(IDECYLLO) + IN A,(IDE_IO_CYLLO) DCALL PRTHEXBYTE CP $00 RET NZ DCALL PC_SPACE - IN A,(IDECYLHI) + IN A,(IDE_IO_CYLHI) DCALL PRTHEXBYTE CP $00 RET NZ - DCALL PC_SPACE - IN A,(IDESTTS) - DCALL PRTHEXBYTE ; PRINT STATUS - CP 0 - JR NZ,IDE_PROBE1 - OR $FF ; SIGNAL ERROR - RET - -IDE_PROBE1: +; + ; SIGNATURE MATCHES ATA DEVICE, RECORD TYPE AND RETURN SUCCESS + IDE_DPTR(IDE_TYPE) ; POINT HL TO UNIT TYPE FIELD, A IS TRASHED + LD (HL),IDE_TYPEATA ; SET THE DEVICE TYPE XOR A ; SIGNAL SUCCESS - RET + RET ; DONE, NOTE THAT A=0 AND Z IS SET ; ; -; -IDE_SET8BIT: - ; DEVICE *MUST* ALREADY BE SELECTED! - LD A,IDECMD_SETFEAT - LD (IDE_CMD),A - LD A,$01 ; $01 ENABLES 8-BIT XFR FEATURE - OUT (IDEERR),A ; SET FEATURS VALUE - JP IDE_RUNCMD ; EXIT THRU RUNCMD +; +IDE_SETFEAT: + PUSH AF +#IF (IDETRACE >= 3) + CALL IDE_PRTPREFIX + PRTS(" SETFEAT$") +#ENDIF + LD A,(IDE_DRVHD) + OUT (IDE_IO_DRVHD),A + DCALL PC_SPACE + DCALL PRTHEXBYTE + POP AF + OUT (IDE_IO_FEAT),A ; SET THE FEATURE VALUE + DCALL PC_SPACE + DCALL PRTHEXBYTE + LD A,IDE_CMD_SETFEAT ; CMD = SETFEAT + LD (IDE_CMD),A ; SAVE IT + JP IDE_RUNCMD ; RUN COMMAND AND EXIT ; ; ; IDE_IDENTIFY: - ; DEVICE *MUST* ALREADY BE SELECTED! - LD A,IDECMD_IDDEV +#IF (IDETRACE >= 3) + CALL IDE_PRTPREFIX + PRTS(" IDDEV$") +#ENDIF + LD A,(IDE_DRVHD) + OUT (IDE_IO_DRVHD),A + DCALL PC_SPACE + DCALL PRTHEXBYTE + LD A,IDE_CMD_IDDEV + LD (IDE_CMD),A + CALL IDE_RUNCMD + RET NZ + JP IDE_GETBUF ; EXIT THRU BUFRD +; +; +; +IDE_RDSEC: + CALL IDE_CHKDEVICE + RET NZ +; +#IF (IDETRACE >= 3) + CALL IDE_PRTPREFIX + PRTS(" READ$") +#ENDIF + LD A,(IDE_DRVHD) + OUT (IDE_IO_DRVHD),A + DCALL PC_SPACE + DCALL PRTHEXBYTE + CALL IDE_SETADDR ; SETUP CYL, TRK, HEAD + LD A,IDE_CMD_READ LD (IDE_CMD),A CALL IDE_RUNCMD RET NZ - JP IDE_BUFRD ; EXIT THRU BUFRD + JP IDE_GETBUF +; +; +; +IDE_WRSEC: + CALL IDE_CHKDEVICE + RET NZ +; +#IF (IDETRACE >= 3) + CALL IDE_PRTPREFIX + PRTS(" WRITE$") +#ENDIF + LD A,(IDE_DRVHD) + OUT (IDE_IO_DRVHD),A + DCALL PC_SPACE + DCALL PRTHEXBYTE + CALL IDE_SETADDR ; SETUP CYL, TRK, HEAD + LD A,IDE_CMD_WRITE + LD (IDE_CMD),A + CALL IDE_RUNCMD + RET NZ + JP IDE_PUTBUF +; +; +; +IDE_CHKDEVICE: + IDE_DPTR(IDE_STAT) + LD A,(HL) + OR A + RET Z ; RETURN IF ALL IS WELL +; + ; ATTEMPT TO REINITIALIZE HERE??? + JP IDE_ERR + RET +; +; +; +IDE_SETADDR: + ; SEND 3 LOWEST BYTES OF LBA IN REVERSE ORDER + ; IDE_IO_LBA3 HAS ALREADY BEEN SET BY IDE_SELECT + ; HSTLBA2-0 --> IDE_IO_LBA2-0 + LD C,IDE_IO_LBA0 + 3 ; STARTING IO PORT (NOT PRE-DEC BELOW) + LD HL,HSTLBA + 2 ; STARTING LBA BYTE ADR + LD B,3 ; SEND 3 BYTES +IDE_SETADDR1: +; +#IF (IDETRACE >= 3) + LD A,(HL) + CALL PC_SPACE + CALL PRTHEXBYTE +#ENDIF +; + DEC C ; NEXT PORT + OUTD ; SEND NEXT BYTE + JR NZ,IDE_SETADDR1 ; LOOP TILL DONE +; + ; SEND COUNT OF BLOCKS TO TRANSFER + ; 1 --> IDE_IO_COUNT + LD A,1 ; COUNT VALUE IS 1 BLOCK +; +#IF (IDETRACE >= 3) + DCALL PC_SPACE + DCALL PRTHEXBYTE +#ENDIF +; + DEC C ; PORT := IDE_IO_COUNT + OUT (C),A ; SEND IT +; +#IF (DSKYENABLE) + CALL IDE_DSKY +#ENDIF +; + RET +; +; +; +IDE_RUNCMD: + CALL IDE_WAITRDY ; WAIT FOR DRIVE READY + RET NZ ; BAIL OUT ON TIMEOUT +; + LD A,(IDE_CMD) ; GET THE COMMAND + DCALL PC_SPACE + DCALL PRTHEXBYTE + OUT (IDE_IO_CMD),A ; SEND IT (STARTS EXECUTION) +#IF (IDETRACE >= 3) + PRTS(" -->$") +#ENDIF +; + CALL IDE_WAITBSY ; WAIT FOR DRIVE READY (COMMAND DONE) + RET NZ ; BAIL OUT ON TIMEOUT +; + CALL IDE_GETRES + JP NZ,IDE_CMDERR + RET +; +; +; +IDE_GETBUF: +#IF (IDETRACE >= 3) + PRTS(" GETBUF$") +#ENDIF + + CALL IDE_WAITDRQ ; WAIT FOR BUFFER READY + RET NZ ; BAIL OUT IF TIMEOUT + + LD HL,(DIOBUF) + LD B,0 + +#IF (IDE8BIT | (IDEMODE == IDEMODE_DIDE)) + LD C,IDE_IO_DATA + INIR + INIR +#ELSE + LD C,IDE_IO_DATAHI +IDE_GETBUF1: + IN A,(IDE_IO_DATALO) ; READ THE LO BYTE + LD (HL),A ; SAVE IN BUFFER + INC HL ; INC BUFFER POINTER + INI ; READ AND SAVE HI BYTE, INC HL, DEC B + JP NZ,IDE_GETBUF1 ; LOOP AS NEEDED +#ENDIF + CALL IDE_GETRES + JP NZ,IDE_IOERR + RET +; +; +; +IDE_PUTBUF: +#IF (IDETRACE >= 3) + PRTS(" GETBUF$") +#ENDIF + + CALL IDE_WAITDRQ ; WAIT FOR BUFFER READY + RET NZ ; BAIL OUT IF TIMEOUT + + LD HL,(DIOBUF) + LD B,0 + +#IF (IDE8BIT | (IDEMODE == IDEMODE_DIDE)) + LD C,IDE_IO_DATA + OTIR + OTIR +#ELSE + LD C,IDE_IO_DATAHI +IDE_PUTBUF1: + LD A,(HL) ; GET THE LO BYTE AND KEEP IT IN A FOR LATER + INC HL ; BUMP TO NEXT BYTE IN BUFFER + OUTI ; WRITE HI BYTE, INC HL, DEC B + OUT (IDE_IO_DATALO),A ; NOW WRITE THE SAVED LO BYTE TO LO BYTE + JP NZ,IDE_PUTBUF1 ; LOOP AS NEEDED +#ENDIF + CALL IDE_GETRES + JP NZ,IDE_IOERR + RET ; ; ; @@ -405,11 +761,10 @@ IDE_WAITRDY: IDE_WAITRDY1: LD DE,-1 ; ~1 SECOND INNER LOOP IDE_WAITRDY2: - IN A,(IDESTTS) ; READ STATUS - LD (IDE_STTS),A ; SAVE IT + IN A,(IDE_IO_STAT) ; READ STATUS + LD C,A ; SAVE IT AND %11000000 ; ISOLATE BUSY AND RDY BITS XOR %01000000 ; WE WANT BUSY(7) TO BE 0 AND RDY(6) TO BE 1 - ;JR Z,IDE_WAITRPT ; DIAGNOSTIC RET Z ; ALL SET, RETURN WITH Z SET CALL DELAY ; DELAY 16US DEC DE @@ -417,28 +772,27 @@ IDE_WAITRDY2: OR E JR NZ,IDE_WAITRDY2 ; INNER LOOP RETURN DJNZ IDE_WAITRDY1 ; OUTER LOOP RETURN - JP IDE_ERRRDYTO ; EXIT WITH RDYTO ERR + JP IDE_RDYTO ; EXIT WITH RDYTO ERR ; ; ; -IDE_WAITBUF: +IDE_WAITDRQ: LD B,3 ; ~3 SECOND TIMEOUT??? -IDE_WAITBUF1: +IDE_WAITDRQ1: LD DE,-1 ; ~1 SECOND INNER LOOP -IDE_WAITBUF2: - IN A,(IDESTTS) ; WAIT FOR DRIVE'S 512 BYTE READ BUFFER - LD (IDE_STTS),A ; SAVE IT +IDE_WAITDRQ2: + IN A,(IDE_IO_STAT) ; WAIT FOR DRIVE'S 512 BYTE READ BUFFER + LD C,A ; SAVE IT AND %10001000 ; TO FILL (OR READY TO FILL) XOR %00001000 - ;JR Z,IDE_WAITRPT ; DIAGNOSTIC RET Z CALL DELAY ; DELAY 16US DEC DE LD A,D OR E - JR NZ,IDE_WAITBUF2 - DJNZ IDE_WAITBUF1 - JP IDE_ERRBUFTO ; EXIT WITH BUFTO ERR + JR NZ,IDE_WAITDRQ2 + DJNZ IDE_WAITDRQ1 + JP IDE_DRQTO ; EXIT WITH BUFTO ERR ; ; ; @@ -447,10 +801,9 @@ IDE_WAITBSY: IDE_WAITBSY1: LD DE,-1 ; ~1 SECOND INNER LOOP IDE_WAITBSY2: - IN A,(IDESTTS) ; WAIT FOR DRIVE'S 512 BYTE READ BUFFER - LD (IDE_STTS),A ; SAVE IT + IN A,(IDE_IO_STAT) ; WAIT FOR DRIVE'S 512 BYTE READ BUFFER + LD C,A ; SAVE IT AND %10000000 ; TO FILL (OR READY TO FILL) - ;JR Z,IDE_WAITRPT ; DIAGNOSTIC RET Z CALL DELAY ; DELAY 16US DEC DE @@ -458,273 +811,222 @@ IDE_WAITBSY2: OR E JR NZ,IDE_WAITBSY2 DJNZ IDE_WAITBSY1 - JP IDE_ERRBSYTO ; EXIT WITH BSYTO ERR + JP IDE_BSYTO ; EXIT WITH BSYTO ERR ; ; ; -IDE_WAITRPT: - PUSH AF - CALL PC_SPACE - LD A,B - CALL PRTHEXBYTE - LD A,D - CALL PRTHEXBYTE - LD A,E - CALL PRTHEXBYTE - POP AF - RET +IDE_GETRES: + IN A,(IDE_IO_STAT) ; GET STATUS + DCALL PC_SPACE + DCALL PRTHEXBYTE + AND %00000001 ; ERROR BIT SET? + RET Z ; NOPE, RETURN WITH ZF ; + IN A,(IDE_IO_ERR) ; READ ERROR REGISTER + DCALL PC_SPACE + DCALL PRTHEXBYTE + OR $FF ; FORCE NZ TO SIGNAL ERROR + RET ; RETURN ; +;============================================================================= +; HARDWARE INTERFACE ROUTINES +;============================================================================= ; -IDE_CHKERR: - IN A,(IDESTTS) ; GET STATUS - LD (IDE_STTS),A ; SAVE IT - AND %00000001 ; ERROR BIT SET? - RET Z ; NOPE, RETURN WITH ZF ; - IN A,(IDEERR) ; READ ERROR REGISTER - LD (IDE_ERRS),A ; SAVE IT - JP IDE_ERRCMD ; EXIT VIA ERRCMD +;============================================================================= +; ERROR HANDLING AND DIAGNOSTICS +;============================================================================= ; +; ERROR HANDLERS ; +IDE_INVUNIT: + LD A,IDE_STINVUNIT + JR IDE_ERR2 ; SPECIAL CASE FOR INVALID UNIT ; -IDE_BUFRD: - CALL IDE_WAITBUF ; WAIT FOR BUFFER READY - RET NZ ; BAIL OUT IF TIMEOUT - - LD HL,(DIOBUF) - LD B,0 - -#IF (IDE8BIT | (IDEMODE == IDEMODE_DIDE)) - LD C,IDEDATA - INIR - INIR -#ELSE - LD C,IDEDATAHI -IDE_BUFRD1: - IN A,(IDEDATALO) ; READ THE LO BYTE - LD (HL),A ; SAVE IN BUFFER - INC HL ; INC BUFFER POINTER - INI ; READ AND SAVE HI BYTE, INC HL, DEC B - JP NZ,IDE_BUFRD1 ; LOOP AS NEEDED -#ENDIF - JP IDE_CHKERR ; RETURN THRU CHKERR +IDE_NOMEDIA: + LD A,IDE_STNOMEDIA + JR IDE_ERR ; +IDE_CMDERR: + LD A,IDE_STCMDERR + JR IDE_ERR ; +IDE_IOERR: + LD A,IDE_STIOERR + JR IDE_ERR ; -IDE_BUFWR: - CALL IDE_WAITBUF ; WAIT FOR BUFFER READY - RET NZ ; BAIL OUT IF TIMEOUT - - LD HL,(DIOBUF) - LD B,0 - -#IF (IDE8BIT | (IDEMODE == IDEMODE_DIDE)) - LD C,IDEDATA - OTIR - OTIR -#ELSE - LD C,IDEDATAHI -IDE_BUFWR1: - LD A,(HL) ; GET THE LO BYTE AND KEEP IT IN A FOR LATER - INC HL ; BUMP TO NEXT BYTE IN BUFFER - OUTI ; WRITE HI BYTE, INC HL, DEC B - OUT (IDEDATALO),A ; NOW WRITE THE SAVED LO BYTE TO LO BYTE - JP NZ,IDE_BUFWR1 ; LOOP AS NEEDED -#ENDIF - JP IDE_CHKERR ; RETURN THRU CHKERR -; -; -; -IDE_SETUP: - LD A,1 - OUT (IDESECTC),A - - ; SEND 3 BYTES OF LBA T:SS -> CYL:SEC (CC:S) - LD A,(HSTLBAHI) ; LBA HIGH LSB - LD (IDE_CYLHI),A ; SAVE IT - OUT (IDECYLHI),A ; -> CYLINDER HI - LD A,(HSTLBALO + 1) ; LBA LOW MSB - LD (IDE_CYLLO),A ; SAVE IT - OUT (IDECYLLO),A ; -> CYLINDER LO - LD A,(HSTLBALO) ; LBA LOW LSB - LD (IDE_SEC),A ; SAVE IT - OUT (IDESECTN),A ; -> SECTOR NUM -#IF (DSKYENABLE) - CALL IDE_DSKY -#ENDIF - RET +IDE_RDYTO: + LD A,IDE_STRDYTO + JR IDE_ERR ; +IDE_DRQTO: + LD A,IDE_STDRQTO + JR IDE_ERR ; +IDE_BSYTO: + LD A,IDE_STBSYTO + JR IDE_ERR ; -#IF (DSKYENABLE) -IDE_DSKY: - LD HL,DSKY_HEXBUF - LD A,(IDE_DEVICE) - LD (HL),A - INC HL - LD A,(IDE_CYLHI) - LD (HL),A - INC HL - LD A,(IDE_CYLLO) - LD (HL),A - INC HL - LD A,(IDE_SEC) - LD (HL),A - CALL DSKY_HEXOUT - RET +IDE_ERR: + PUSH HL ; IS THIS NEEDED? + PUSH AF ; SAVE INCOMING STATUS + IDE_DPTR(IDE_STAT) ; GET STATUS ADR IN HL, AF TRASHED + POP AF ; RESTORE INCOMING STATUS + LD (HL),A ; UPDATE STATUS + POP HL ; IS THIS NEEDED? +IDE_ERR2: +#IF (IDETRACE >= 2) + CALL IDE_PRTSTAT + CALL IDE_REGDUMP #ENDIF + OR A ; SET FLAGS + RET ; +; PRINT STATUS STRING (STATUS NUM IN A) ; -; -IDE_PRT: +IDE_PRTSTAT: + PUSH AF + PUSH DE + PUSH HL + OR A + LD DE,IDE_STR_STOK + JR Z,IDE_PRTSTAT1 + INC A + LD DE,IDE_STR_STINVUNIT + JR Z,IDE_PRTSTAT2 ; INVALID UNIT IS SPECIAL CASE + INC A + LD DE,IDE_STR_STNOMEDIA + JR Z,IDE_PRTSTAT1 + INC A + LD DE,IDE_STR_STCMDERR + JR Z,IDE_PRTSTAT1 + INC A + LD DE,IDE_STR_STIOERR + JR Z,IDE_PRTSTAT1 + INC A + LD DE,IDE_STR_STRDYTO + JR Z,IDE_PRTSTAT1 + INC A + LD DE,IDE_STR_STDRQTO + JR Z,IDE_PRTSTAT1 + INC A + LD DE,IDE_STR_STBSYTO + JR Z,IDE_PRTSTAT1 + LD DE,IDE_STR_STUNK +IDE_PRTSTAT1: + CALL IDE_PRTPREFIX ; PRINT UNIT PREFIX + JR IDE_PRTSTAT3 +IDE_PRTSTAT2: CALL NEWLINE - - LD DE,IDESTR_PREFIX - CALL WRITESTR - CALL PC_COLON - - CALL PC_SPACE - LD DE,IDESTR_CMD + PRTS("IDE:$") ; NO UNIT NUM IN PREFIX FOR INVALID UNIT +IDE_PRTSTAT3: + CALL PC_SPACE ; FORMATTING CALL WRITESTR - LD A,(IDE_CMD) - CALL PRTHEXBYTE - + POP HL + POP DE + POP AF + RET +; +; +; +IDE_REGDUMP: + PUSH AF + PUSH BC CALL PC_SPACE CALL PC_LBKT - LD A,(IDE_CMD) - LD DE,IDESTR_READ - CP IDECMD_READ - JP Z,IDE_PRTCMD - LD DE,IDESTR_WRITE - CP IDECMD_WRITE - JP Z,IDE_PRTCMD - LD DE,IDESTR_SETFEAT - CP IDECMD_SETFEAT - JP Z,IDE_PRTCMD - LD DE,IDESTR_IDDEV - CP IDECMD_IDDEV - JP Z,IDE_PRTCMD - LD DE,IDESTR_RECAL - CP IDECMD_RECAL - JP Z,IDE_PRTCMD - LD DE,IDESTR_UNKCMD -IDE_PRTCMD: - CALL WRITESTR - CALL PC_RBKT - - CALL PC_SPACE - LD A,(IDE_DEVICE) - CALL PRTHEXBYTE - LD A,(IDE_CYLHI) - CALL PRTHEXBYTE - LD A,(IDE_CYLLO) - CALL PRTHEXBYTE - LD A,(IDE_SEC) + LD C,IDE_IO_CMD + LD B,7 +IDE_REGDUMP1: + IN A,(C) CALL PRTHEXBYTE - - CALL PC_SPACE - LD DE,IDESTR_ARROW - CALL WRITESTR - - CALL PC_SPACE - IN A,(IDESTTS) - CALL PRTHEXBYTE - - CALL PC_SPACE - IN A,(IDEERR) - CALL PRTHEXBYTE - - CALL PC_SPACE - LD DE,IDESTR_RC - CALL WRITESTR - LD A,(IDE_STAT) - CALL PRTHEXBYTE - - CALL PC_SPACE - CALL PC_LBKT - LD A,(IDE_STAT) - LD DE,IDESTR_RCOK - CP IDE_RCOK - JP Z,IDE_PRTRC - LD DE,IDESTR_RCCMDERR - CP IDE_RCCMDERR - JP Z,IDE_PRTRC - LD DE,IDESTR_RCRDYTO - CP IDE_RCRDYTO - JP Z,IDE_PRTRC - LD DE,IDESTR_RCBUFTO - CP IDE_RCBUFTO - JP Z,IDE_PRTRC - LD DE,IDESTR_RCBSYTO - CP IDE_RCBSYTO - JP Z,IDE_PRTRC - LD DE,IDESTR_RCUNK -IDE_PRTRC: - CALL WRITESTR + DEC C + DJNZ IDE_REGDUMP1 CALL PC_RBKT - + POP BC + POP AF RET ; +; PRINT DIAGNONSTIC PREFIX ; +IDE_PRTPREFIX: + PUSH AF + CALL NEWLINE + PRTS("IDE$") + LD A,(IDE_UNIT) + ADD A,'0' + CALL COUT + CALL PC_COLON + POP AF + RET +; +; +; +#IF (DSKYENABLE) +IDE_DSKY: + LD HL,DSKY_HEXBUF ; POINT TO DSKY BUFFER + IN A,(IDE_IO_DRVHD) ; GET DRIVE/HEAD + LD (HL),A ; SAVE IN BUFFER + INC HL ; INCREMENT BUFFER POINTER + IN A,(IDE_IO_CYLHI) ; GET DRIVE/HEAD + LD (HL),A ; SAVE IN BUFFER + INC HL ; INCREMENT BUFFER POINTER + IN A,(IDE_IO_CYLLO) ; GET DRIVE/HEAD + LD (HL),A ; SAVE IN BUFFER + INC HL ; INCREMENT BUFFER POINTER + IN A,(IDE_IO_SECT) ; GET DRIVE/HEAD + LD (HL),A ; SAVE IN BUFFER + CALL DSKY_HEXOUT ; SEND IT TO DSKY + RET +#ENDIF ; -IDESTR_PREFIX .TEXT "IDE$" -IDESTR_CMD .TEXT "CMD=$" -IDESTR_RC .TEXT "RC=$" -IDESTR_ARROW .TEXT "-->$" -IDESTR_READ .TEXT "READ$" -IDESTR_WRITE .TEXT "WRITE$" -IDESTR_SETFEAT .TEXT "SETFEAT$" -IDESTR_IDDEV .TEXT "IDDEV$" -IDESTR_RECAL .TEXT "RECAL$" -IDESTR_UNKCMD .TEXT "UNKCMD$" -IDESTR_RCOK .TEXT "OK$" -IDESTR_RCCMDERR .TEXT "COMMAND ERROR$" -IDESTR_RCRDYTO .TEXT "READY TIMEOUT$" -IDESTR_RCBUFTO .TEXT "BUFFER TIMEOUT$" -IDESTR_RCBSYTO .TEXT "BUSY TIMEOUT$" -IDESTR_RCUNK .TEXT "UNKNOWN ERROR$" -IDESTR_NO .TEXT "NO$" -; -;================================================================================================== -; IDE DISK DRIVER - DATA -;================================================================================================== -; -IDE_UNITCNT .DB 0 -IDE_CURUNIT .DB 0 -IDE_STAT .DB 0 -; -IDE_CMD .DB 0 -IDE_DEVICE .DB 0 -IDE_CYLHI .DB 0 -IDE_CYLLO .DB 0 -IDE_SEC .DB 0 -IDE_STTS .DB 0 -IDE_ERRS .DB 0 -; -IDE_CAPLIST .FILL 2 * 4,0 ; CAPACITY OF EACH UNIT IN BLOCKS, 1 DWORD PER UNIT -; -; -; -; -; Error Register (ERR bit being set in the Status Register) -; -; Bit 7: BBK (Bad Block Detected) Set when a Bad Block is detected. -; Bit 6: UNC (Uncorrectable Data Error) Set when Uncorrectable Error is encountered. -; Bit 5: MC (Media Changed) Set to 0. -; Bit 4: IDNF (ID Not Found) Set when Sector ID not found. -; Bit 3: MCR (Media Change Request) Set to 0. -; Bit 2: ABRT (Aborted Command) Set when Command Aborted due to drive error. -; Bit 1: TKONF (Track 0 Not Found) Set when Executive Drive Diagnostic Command. -; Bit 0: AMNF (Address mark Not Found) Set in case of a general error. -; -; Status Register (When the contents of this register are read by the host, the IREQ# bit is cleared) -; -; Bit 7: BSY (Busy) Set when the drive is busy and unable to process any new ATA commands. -; Bit 6: DRDY (Data Ready) Set when the device is ready to accept ATA commands from the host. -; Bit 5: DWF (Drive Write Fault) Always set to 0. -; Bit 4: DSC (Drive Seek Complete) Set when the drive heads have been positioned over a specific track. -; Bit 3: DRQ (Data Request) Set when device is ready to transfer a word or byte of data to or from the host and the device. -; Bit 2: CORR (Corrected Data) Always set to 0. -; Bit 1: IDX (Index) Always set to 0. -; Bit 0: ERR (Error) Set when an error occurred during the previous ATA command. \ No newline at end of file +;============================================================================= +; STRING DATA +;============================================================================= +; +IDE_STR_STOK .TEXT "OK$" +IDE_STR_STINVUNIT .TEXT "INVALID UNIT$" +IDE_STR_STNOMEDIA .TEXT "NO MEDIA$" +IDE_STR_STCMDERR .TEXT "COMMAND ERROR$" +IDE_STR_STIOERR .TEXT "IO ERROR$" +IDE_STR_STRDYTO .TEXT "READY TIMEOUT$" +IDE_STR_STDRQTO .TEXT "DRQ TIMEOUT$" +IDE_STR_STBSYTO .TEXT "BUSY TIMEOUT$" +IDE_STR_STUNK .TEXT "UNKNOWN ERROR$" +; +IDE_STR_NO .TEXT "NO$" +; +;============================================================================= +; DATA STORAGE +;============================================================================= +; +IDE_CMD .DB 0 ; PENDING COMMAND TO PROCESS +IDE_DRVHD .DB 0 ; CURRENT DRIVE/HEAD MASK +; +; UNIT SPECIFIC DATA STORAGE +; +IDE_UNIT .DB -1 ; ACTIVE UNIT, INIT TO -1 TO INDICATE NOTHING SELECTED +IDE_UDATA .FILL IDE_UNITCNT*8,0 ; PER UNIT DATA, 8 BYTES +IDE_DLEN .EQU $ - IDE_UDATA ; LENGTH OF ENTIRE DATA STORAGE FOR ALL UNITS +IDE_UDLEN .EQU IDE_DLEN / IDE_UNITCNT ; LENGTH OF PER UNIT DATA +; +;============================================================================= +; HELPER ROUTINES +;============================================================================= +; +; IMPLEMENTATION FOR MACRO IDE_DPTR +; SET HL TO ADDRESS OF FIELD WITHIN PER UNIT DATA +; HL := ADR OF IDE_UNITDATA[(IDE_UNIT)][(SP)] +; ENTER WITH TOP-OF-STACK = ADDRESS OF FIELD OFFSET +; AF IS TRASHED +; +IDE_DPTRIMP: + LD HL,IDE_UDATA ; POINT TO START OF UNIT DATA ARRAY + LD A,(IDE_UNIT) ; GET CURRENT UNIT NUM + RLCA ; MULTIPLY BY + RLCA ; ... SIZE OF PER UNIT DATA + RLCA ; ... (8 BYTES) + EX (SP),HL ; GET PTR TO FIELD OFFSET VALUE FROM TOS + ADD A,(HL) ; ADD IT TO START OF UNIT DATA IN ACCUM + INC HL ; BUMP HL TO NEXT REAL INSTRUCTION + EX (SP),HL ; AND PUT IT BACK ON STACK, HL GETS ADR OF START OF DATA + JP ADDHLA ; CALC FINAL ADR IN HL AND RETURN diff --git a/Source/HBIOS/sd.asm b/Source/HBIOS/sd.asm index 38782356..70ed9341 100644 --- a/Source/HBIOS/sd.asm +++ b/Source/HBIOS/sd.asm @@ -1,6 +1,6 @@ ; ;============================================================================= -; MMC/SD/SDHC/SDXC CARD STORAGE DRIVER +; MMC/SD/SDHC/SDXC CARD STORAGE DRIVER ;============================================================================= ; ; 1) TESTING @@ -51,98 +51,109 @@ ; ;------------------------------------------------------------------------------ ; -; ALL COMMAND RESPONSES START WITH R1 DEFINED AS FOLLOWS: -; -; R1 RESPONSE CODE: -; -; 7 6 5 4 3 2 1 0 -; +---+---+---+---+---+---+---+---+ -; | 0 | X | X | X | X | X | X | X | -; +---+---+---+---+---+---+---+---+ -; | | | | | | | -; | | | | | | +--- IDLE -; | | | | | +------- ERASE RESET -; | | | | +----------- ILLEGAL COMMAND -; | | | +--------------- COM CRC ERROR -; | | +------------------- ERASE SEQUENCE ERROR -; | +----------------------- ADDRESS ERROR -; +--------------------------- PARAMETER ERROR -; -#IF (SDMODE == SDMODE_JUHA) ; JUHA MINI-BOARD -SD_UNITCNT .EQU 1 ; NUMBER OF PHYSICAL UNITS (SOCKETS) -SD_OPRREG .EQU RTC ; USES RTC LATCHES FOR OPERATION -SD_OPRDEF .EQU %00000001 ; QUIESCENT STATE??? -SD_INPREG .EQU RTC ; INPUT REGISTER IS RTC -SD_CS .EQU %00000100 ; RTC:2 IS SELECT -SD_CLK .EQU %00000010 ; RTC:1 IS CLOCK -SD_DI .EQU %00000001 ; RTC:0 IS DATA IN (CARD <- CPU) -SD_DO .EQU %10000000 ; RTC:7 IS DATA OUT (CARD -> CPU) +; === R1 RESPONSE === +; ALL COMMAND RESPONSES START WITH R1 +; +; 7 6 5 4 3 2 1 0 +; +---+---+---+---+---+---+---+---+ +; | 0 | X | X | X | X | X | X | X | +; +---+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | | | | | | | +; | | | | | | +--- IDLE +; | | | | | +------- ERASE RESET +; | | | | +----------- ILLEGAL COMMAND +; | | | +--------------- COM CRC ERROR +; | | +------------------- ERASE SEQUENCE ERROR +; | +----------------------- ADDRESS ERROR +; +--------------------------- PARAMETER ERROR +; +; === DATA ERROR TOKEN === +; +; 7 6 5 4 3 2 1 0 +; +---+---+---+---+---+---+---+---+ +; | 0 | 0 | 0 | 0 | X | X | X | X | +; +---+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | | | | +; | | | +--- ERROR - GENERAL OR UNKNOWN ERROR +; | | +------- CC ERROR - INTERNAL CARD CONTROLER ERROR +; | +----------- CARD ECC FAILED - CARD INTERNAL ECC FAILED TO CORRECT DATA +; +--------------- OUT OF RANGE - PARAMAETER OUT OF RANGE ALLOWED FOR CARD +; +#IF (SDMODE == SDMODE_JUHA) ; JUHA MINI-BOARD +SD_UNITCNT .EQU 1 ; NUMBER OF PHYSICAL UNITS (SOCKETS) +SD_OPRREG .EQU RTC ; USES RTC LATCHES FOR OPERATION +SD_OPRDEF .EQU %00000001 ; QUIESCENT STATE??? +SD_INPREG .EQU RTC ; INPUT REGISTER IS RTC +SD_CS .EQU %00000100 ; RTC:2 IS SELECT +SD_CLK .EQU %00000010 ; RTC:1 IS CLOCK +SD_DI .EQU %00000001 ; RTC:0 IS DATA IN (CARD <- CPU) +SD_DO .EQU %10000000 ; RTC:7 IS DATA OUT (CARD -> CPU) #ENDIF ; -#IF (SDMODE == SDMODE_N8) ; UNMODIFIED N8-2511 -SD_UNITCNT .EQU 1 ; NUMBER OF PHYSICAL UNITS (SOCKETS) -SD_OPRREG .EQU RTC ; USES RTC LATCHES FOR OPERATION -SD_OPRDEF .EQU %00000001 ; QUIESCENT STATE??? -SD_INPREG .EQU RTC ; INPUT REGISTER IS RTC -SD_CS .EQU %00000100 ; RTC:2 IS SELECT -SD_CLK .EQU %00000010 ; RTC:1 IS CLOCK -SD_DI .EQU %00000001 ; RTC:0 IS DATA IN (CARD <- CPU) -SD_DO .EQU %01000000 ; RTC:6 IS DATA OUT (CARD -> CPU) +#IF (SDMODE == SDMODE_N8) ; UNMODIFIED N8-2511 +SD_UNITCNT .EQU 1 ; NUMBER OF PHYSICAL UNITS (SOCKETS) +SD_OPRREG .EQU RTC ; USES RTC LATCHES FOR OPERATION +SD_OPRDEF .EQU %00000001 ; QUIESCENT STATE??? +SD_INPREG .EQU RTC ; INPUT REGISTER IS RTC +SD_CS .EQU %00000100 ; RTC:2 IS SELECT +SD_CLK .EQU %00000010 ; RTC:1 IS CLOCK +SD_DI .EQU %00000001 ; RTC:0 IS DATA IN (CARD <- CPU) +SD_DO .EQU %01000000 ; RTC:6 IS DATA OUT (CARD -> CPU) #ENDIF ; -#IF (SDMODE == SDMODE_CSIO) ; N8-2312 -SD_UNITCNT .EQU 1 ; NUMBER OF PHYSICAL UNITS (SOCKETS) -SD_OPRREG .EQU RTC ; USES RTC LATCHES FOR OPERATION -SD_OPRDEF .EQU %00000000 ; QUIESCENT STATE -SD_CS .EQU %00000100 ; RTC:2 IS SELECT +#IF (SDMODE == SDMODE_CSIO) ; N8-2312 +SD_UNITCNT .EQU 1 ; NUMBER OF PHYSICAL UNITS (SOCKETS) +SD_OPRREG .EQU RTC ; USES RTC LATCHES FOR OPERATION +SD_OPRDEF .EQU %00000000 ; QUIESCENT STATE +SD_CS .EQU %00000100 ; RTC:2 IS SELECT SD_CNTR .EQU Z180_CNTR SD_TRDR .EQU Z180_TRDR #ENDIF ; -#IF (SDMODE == SDMODE_PPI) ; PPISD -SD_UNITCNT .EQU 1 ; NUMBER OF PHYSICAL UNITS (SOCKETS) -SD_PPIBASE .EQU PPIBASE ; BASE IO PORT FOR PPI -SD_PPIB .EQU PPIBASE + 1 ; PPI PORT B (INPUT: DOUT) -SD_PPIC .EQU PPIBASE + 2 ; PPI PORT C (OUTPUT: CS, CLK, DIN) -SD_PPIX .EQU PPIBASE + 3 ; PPI CONTROL PORT -SD_OPRREG .EQU SD_PPIC ; PPI PORT C IS OPR REG -SD_OPRDEF .EQU %00110001 ; CS HI, DI HI -SD_INPREG .EQU SD_PPIB ; INPUT REGISTER IS PPI PORT B -SD_CS .EQU %00010000 ; PPIC:4 IS SELECT -SD_CLK .EQU %00000010 ; PPIC:1 IS CLOCK -SD_DI .EQU %00000001 ; PPIC:0 IS DATA IN (CARD <- CPU) -SD_DO .EQU %10000000 ; PPIB:7 IS DATA OUT (CARD -> CPU) +#IF (SDMODE == SDMODE_PPI) ; PPISD +SD_UNITCNT .EQU 1 ; NUMBER OF PHYSICAL UNITS (SOCKETS) +SD_PPIBASE .EQU PPIBASE ; BASE IO PORT FOR PPI +SD_PPIB .EQU PPIBASE + 1 ; PPI PORT B (INPUT: DOUT) +SD_PPIC .EQU PPIBASE + 2 ; PPI PORT C (OUTPUT: CS, CLK, DIN) +SD_PPIX .EQU PPIBASE + 3 ; PPI CONTROL PORT +SD_OPRREG .EQU SD_PPIC ; PPI PORT C IS OPR REG +SD_OPRDEF .EQU %00110001 ; CS HI, DI HI +SD_INPREG .EQU SD_PPIB ; INPUT REGISTER IS PPI PORT B +SD_CS .EQU %00010000 ; PPIC:4 IS SELECT +SD_CLK .EQU %00000010 ; PPIC:1 IS CLOCK +SD_DI .EQU %00000001 ; PPIC:0 IS DATA IN (CARD <- CPU) +SD_DO .EQU %10000000 ; PPIB:7 IS DATA OUT (CARD -> CPU) #ENDIF ; #IF (SDMODE == SDMODE_UART) -SD_UNITCNT .EQU 1 ; NUMBER OF PHYSICAL UNITS (SOCKETS) -SD_OPRREG .EQU SIO_MCR ; UART MCR PORT (OUTPUT: CS, CLK, DIN) -SD_OPRDEF .EQU %00001100 ; QUIESCENT STATE -SD_INPREG .EQU SIO_MSR ; INPUT REGISTER IS MSR -SD_CS .EQU %00001000 ; UART MCR:3 IS SELECT -SD_CLK .EQU %00000100 ; UART MCR:2 IS CLOCK -SD_DI .EQU %00000001 ; UART MCR:0 IS DATA IN (CARD <- CPU) -SD_DO .EQU %00100000 ; UART MSR:5 IS DATA OUT (CARD -> CPU) +SD_UNITCNT .EQU 1 ; NUMBER OF PHYSICAL UNITS (SOCKETS) +SD_OPRREG .EQU SIO_MCR ; UART MCR PORT (OUTPUT: CS, CLK, DIN) +SD_OPRDEF .EQU %00001100 ; QUIESCENT STATE +SD_INPREG .EQU SIO_MSR ; INPUT REGISTER IS MSR +SD_CS .EQU %00001000 ; UART MCR:3 IS SELECT +SD_CLK .EQU %00000100 ; UART MCR:2 IS CLOCK +SD_DI .EQU %00000001 ; UART MCR:0 IS DATA IN (CARD <- CPU) +SD_DO .EQU %00100000 ; UART MSR:5 IS DATA OUT (CARD -> CPU) #ENDIF ; -#IF (SDMODE == SDMODE_DSD) ; DUAL SD -SD_UNITCNT .EQU 2 ; NUMBER OF PHYSICAL UNITS (SOCKETS) -SD_OPRREG .EQU $08 ; DEDICATED OPERATIONS REGISTER -SD_OPRDEF .EQU %00000001 ; QUIESCENT STATE -SD_INPREG .EQU SD_OPRREG ; INPUT REGISTER IS OPRREG -SD_SELREG .EQU SD_OPRREG + 1 ; DEDICATED SELECTION REGISTER -SD_SELDEF .EQU %00000000 ; SELECTION REGISTER DEFAULT -SD_CS .EQU %00000100 ; RTC:2 IS SELECT -SD_CLK .EQU %00000010 ; RTC:1 IS CLOCK -SD_DI .EQU %00000001 ; RTC:6 IS DATA IN (CARD <- CPU) -SD_DO .EQU %00000001 ; RTC:0 IS DATA OUT (CARD -> CPU) +#IF (SDMODE == SDMODE_DSD) ; DUAL SD +SD_UNITCNT .EQU 2 ; NUMBER OF PHYSICAL UNITS (SOCKETS) +SD_OPRREG .EQU $08 ; DEDICATED OPERATIONS REGISTER +SD_OPRDEF .EQU %00000001 ; QUIESCENT STATE +SD_INPREG .EQU SD_OPRREG ; INPUT REGISTER IS OPRREG +SD_SELREG .EQU SD_OPRREG + 1 ; DEDICATED SELECTION REGISTER +SD_SELDEF .EQU %00000000 ; SELECTION REGISTER DEFAULT +SD_CS .EQU %00000100 ; RTC:2 IS SELECT +SD_CLK .EQU %00000010 ; RTC:1 IS CLOCK +SD_DI .EQU %00000001 ; RTC:6 IS DATA IN (CARD <- CPU) +SD_DO .EQU %00000001 ; RTC:0 IS DATA OUT (CARD -> CPU) #ENDIF ; -#IF (SDMODE == SDMODE_MK4) ; MARK IV (CSIO STYLE INTERFACE) -SD_UNITCNT .EQU 1 ; NUMBER OF PHYSICAL UNITS (SOCKETS) -SD_OPRREG .EQU MK4_SD ; DEDICATED MK4 SDCARD REGISTER -SD_OPRDEF .EQU %00000000 ; QUIESCENT STATE -SD_CS .EQU %00000100 ; SELECT ACTIVE +#IF (SDMODE == SDMODE_MK4) ; MARK IV (CSIO STYLE INTERFACE) +SD_UNITCNT .EQU 1 ; NUMBER OF PHYSICAL UNITS (SOCKETS) +SD_OPRREG .EQU MK4_SD ; DEDICATED MK4 SDCARD REGISTER +SD_OPRDEF .EQU %00000000 ; QUIESCENT STATE +SD_CS .EQU %00000100 ; SELECT ACTIVE SD_CNTR .EQU Z180_CNTR SD_TRDR .EQU Z180_TRDR #ENDIF @@ -167,38 +178,40 @@ SD_ACMD_SEND_SCR .EQU $40 + 51 ; $73, ACMD51 -> R1 ; ; SD CARD TYPE ; -SD_TYPEUNK .EQU 0 ; CARD TYPE UNKNOWN/UNDETERMINED -SD_TYPEMMC .EQU 1 ; MULTIMEDIA CARD (MMC STANDARD) -SD_TYPESDSC .EQU 2 ; SDSC CARD (V1) -SD_TYPESDHC .EQU 3 ; SDHC CARD (V2) -SD_TYPESDXC .EQU 4 ; SDXC CARD (V3) +SD_TYPEUNK .EQU 0 ; CARD TYPE UNKNOWN/UNDETERMINED +SD_TYPEMMC .EQU 1 ; MULTIMEDIA CARD (MMC STANDARD) +SD_TYPESDSC .EQU 2 ; SDSC CARD (V1) +SD_TYPESDHC .EQU 3 ; SDHC CARD (V2) +SD_TYPESDXC .EQU 4 ; SDXC CARD (V3) ; ; SD CARD STATUS (SD_STAT) ; -SD_STOK .EQU 0 ; OK -SD_STNOTRDY .EQU -1 ; NOT READY (INITIALIZATION PENDING) -SD_STRDYTO .EQU -2 ; TIMEOUT WAITING FOR CARD TO BE READY -SD_STINITTO .EQU -3 ; INITIALIZATOIN TIMEOUT -SD_STCMDTO .EQU -4 ; TIMEOUT WAITING FOR COMMAND RESPONSE -SD_STCMDERR .EQU -5 ; COMMAND ERROR OCCURRED (REF SD_RC) -SD_STDATAERR .EQU -6 ; DATA ERROR OCCURRED (REF SD_TOK) -SD_STDATATO .EQU -7 ; DATA TRANSFER TIMEOUT -SD_STCRCERR .EQU -8 ; CRC ERROR ON RECEIVED DATA PACKET -SD_STNOMEDIA .EQU -9 ; NO MEDIA IN CONNECTOR -SD_STWRTPROT .EQU -10 ; ATTEMPT TO WRITE TO WRITE PROTECTED MEDIA +SD_STOK .EQU 0 ; OK +SD_STINVUNIT .EQU -1 ; INVALID UNIT +SD_STRDYTO .EQU -2 ; TIMEOUT WAITING FOR CARD TO BE READY +SD_STINITTO .EQU -3 ; INITIALIZATOIN TIMEOUT +SD_STCMDTO .EQU -4 ; TIMEOUT WAITING FOR COMMAND RESPONSE +SD_STCMDERR .EQU -5 ; COMMAND ERROR OCCURRED (REF SD_RC) +SD_STDATAERR .EQU -6 ; DATA ERROR OCCURRED (REF SD_TOK) +SD_STDATATO .EQU -7 ; DATA TRANSFER TIMEOUT +SD_STCRCERR .EQU -8 ; CRC ERROR ON RECEIVED DATA PACKET +SD_STNOMEDIA .EQU -9 ; NO MEDIA IN CONNECTOR +SD_STWRTPROT .EQU -10 ; ATTEMPT TO WRITE TO WRITE PROTECTED MEDIA ; ; PER UNIT DATA OFFSETS (CAREFUL NOT TO EXCEED PER UNIT SPACE IN SD_UNITDATA) ; SEE SD_UNITDATA IN DATA STORAGE BELOW ; -SD_STAT .EQU 0 ; LAST STATUS (1 BYTE) -SD_TYPE .EQU 1 ; CARD TYPE (1 BYTE) -SD_CAPACITY .EQU 2 ; CARD CAPACITY (1 DWORD/4 BYTES) +SD_STAT .EQU 0 ; LAST STATUS (1 BYTE) +SD_TYPE .EQU 1 ; CARD TYPE (1 BYTE) +SD_CAPACITY .EQU 2 ; CARD CAPACITY (1 DWORD/4 BYTES) ; ; MACRO TO RETURN POINTER TO FIELD WITHIN UNIT DATA ; #DEFINE SD_DPTR(FIELD) CALL SD_DPTRIMP \ .DB FIELD ; -; SD DRIVER INITIALIZATION ENTRY POINT +;============================================================================= +; INITIALIZATION ENTRY POINT +;============================================================================= ; SD_INIT: PRTS("SD:$") @@ -281,8 +294,8 @@ SD_INIT: CALL PRTDECB ; ; INITIALIZE THE SD INTERFACE NOW - CALL SD_SETUP ; DO HARDWARE SETUP/INIT - RET NZ ; ABORT ON ERROR + CALL SD_SETUP ; DO HARDWARE SETUP/INIT + RET NZ ; ABORT ON ERROR ; ; CLEAR OUT ALL DATA (FOR ALL UNITS) LD HL,SD_UNITDATA @@ -291,70 +304,66 @@ SD_INIT: CALL FILL ; ; INITIALIZE INDIVIDUAL UNIT(S) - LD B,SD_UNITCNT ; INIT LOOP COUNTER TO UNIT COUNT - LD C,0 ; INIT UNIT INDEX TO ZERO + LD B,SD_UNITCNT ; INIT LOOP COUNTER TO UNIT COUNT + LD C,0 ; INIT UNIT INDEX TO ZERO SD_INIT1: - PUSH BC ; SAVE LOOP COUNTER/INDEX - LD A,C ; UNIT ID TO A - CALL SD_INITUNIT ; INITIALIZE IT - POP BC ; RESTORE LOOP COUNTER/INDEX - INC C ; INCREMENT UNIT INDEX - DJNZ SD_INIT1 ; DECREMENT LOOP COUNTER AND LOOP AS NEEDED + PUSH BC ; SAVE LOOP COUNTER/INDEX + LD A,C ; UNIT ID TO A + CALL SD_INITUNIT ; INITIALIZE IT +#IF (SDTRACE < 2) + CALL NZ,SD_PRTSTAT ; IF ERROR, SHOW IT +#ENDIF + POP BC ; RESTORE LOOP COUNTER/INDEX + INC C ; INCREMENT UNIT INDEX + DJNZ SD_INIT1 ; DECREMENT LOOP COUNTER AND LOOP AS NEEDED ; - RET ; DONE + RET ; DONE ; ; INITIALIZE UNIT DESIGNATED IN ACCUM ; SD_INITUNIT: - ; SELECT UNIT - CALL SD_SELUNIT ; SELECT UNIT - JP NZ,SD_PRTERR ; EXIT VIA PRINT STATUS + CALL SD_SELUNIT ; SELECT UNIT + RET NZ ; ABORT ON ERROR ; - ; CLEAR OUT UNIT SPECIFIC DATA - SD_DPTR(0) ; SET HL TO START OF UNIT DATA - LD BC,SD_UNITDATALEN - XOR A - CALL FILL + CALL SD_INITCARD ; INIT THE SELECTED CARD + RET NZ ; ABORT ON ERROR ; - ; INIT CARD - CALL SD_INITCARD ; INIT THE SELECTED CARD - CALL SD_PRTPREFIX ; - JP NZ,SD_PRTSTAT ; EXIT VIA PRINT STATUS + CALL SD_PRTPREFIX ; ; PRINT CARD TYPE PRTS(" TYPE=$") - SD_DPTR(SD_TYPE) ; SET HL TO ADR OF CARD TYPE, TRASHES AF + SD_DPTR(SD_TYPE) ; SET HL TO ADR OF CARD TYPE, TRASHES AF LD A,(HL) - LD DE,SD_STRTYPEMMC + LD DE,SD_STR_TYPEMMC CP SD_TYPEMMC JR Z,SD_INITUNIT1 - LD DE,SD_STRTYPESDSC + LD DE,SD_STR_TYPESDSC CP SD_TYPESDSC JR Z,SD_INITUNIT1 - LD DE,SD_STRTYPESDHC + LD DE,SD_STR_TYPESDHC CP SD_TYPESDHC JR Z,SD_INITUNIT1 - LD DE,SD_STRTYPESDXC + LD DE,SD_STR_TYPESDXC CP SD_TYPESDXC JR Z,SD_INITUNIT1 - LD DE,SD_STRTYPEUNK + LD DE,SD_STR_TYPEUNK SD_INITUNIT1: CALL WRITESTR ; GET CID (WHICH CONTAINS PRODUCT NAME) - LD A,SD_CMD_SEND_CID ; SEND_CID - CALL SD_INITCMD ; SETUP COMMAND BUFFER - CALL SD_EXECCMD ; RUN COMMAND - RET NZ ; ABORT ON ERROR - LD BC,16 ; 16 BYTES OF CID + LD A,SD_CMD_SEND_CID ; SEND_CID + CALL SD_INITCMD ; SETUP COMMAND BUFFER + CALL SD_EXECCMD ; RUN COMMAND + RET NZ ; ABORT ON ERROR + LD BC,16 ; 16 BYTES OF CID LD HL,SD_BUF CALL SD_GETDATA CALL SD_DONE - JP NZ,SD_ERRDATA ; DATA XFER ERROR + JP NZ,SD_ERRDATA ; DATA XFER ERROR -#IF (SDTRACE >= 2) +#IF (SDTRACE >= 3) CALL SD_PRTPREFIX - LD DE,SD_STRCID + LD DE,SD_STR_CID CALL WRITESTR LD DE,SD_BUF LD A,16 @@ -362,49 +371,45 @@ SD_INITUNIT1: #ENDIF ; PRINT PRODUCT NAME - PRTS(" NAME=$") ; PRINT LABEL - LD B,5 ; PREPARE TO PRINT 5 BYTES - LD HL,SD_BUF + 3 ; AT BYTE OFFSET 3 IN RESULT BUFFER + PRTS(" NAME=$") ; PRINT LABEL + LD B,5 ; PREPARE TO PRINT 5 BYTES + LD HL,SD_BUF + 3 ; AT BYTE OFFSET 3 IN RESULT BUFFER SD_INITUNIT2: - LD A,(HL) ; GET NEXT BYTE - CALL COUT ; PRINT IT - INC HL ; POINT TO NEXT BYTE - DJNZ SD_INITUNIT2 ; LOOP FOR ALL 5 BYTES + LD A,(HL) ; GET NEXT BYTE + CALL COUT ; PRINT IT + INC HL ; POINT TO NEXT BYTE + DJNZ SD_INITUNIT2 ; LOOP FOR ALL 5 BYTES ; - PRTS(" BLOCKS=0x$") ; LABEL - SD_DPTR(SD_CAPACITY) ; SET HL TO ADR OF CARD CAPACITY, TRASHES AF - CALL LD32 ; GET THE VALUE - CALL PRTHEX32 ; PRINT IT + PRTS(" BLOCKS=0x$") ; LABEL + SD_DPTR(SD_CAPACITY) ; SET HL TO ADR OF CARD CAPACITY, TRASHES AF + CALL LD32 ; GET THE VALUE + CALL PRTHEX32 ; PRINT IT ; ; CONVERT VALUE TO MEGABYTES AND PRINT IT - LD B,11 ; SHIFT 11 BITS TO CONVERT FROM - CALL SRL32 ; ... 512 BYTE BLOCKS TO MEGABYTES + LD B,11 ; SHIFT 11 BITS TO CONVERT FROM + CALL SRL32 ; ... 512 BYTE BLOCKS TO MEGABYTES ; - PRTS(" SIZE=$") ; PRINT LABEL - CALL PRTDEC ; PRINT VALUE - PRTS("MB$") ; PRINT SUFFIX + PRTS(" SIZE=$") ; PRINT LABEL + CALL PRTDEC ; PRINT VALUE + PRTS("MB$") ; PRINT SUFFIX ; ; CHECK FOR WRITE PROTECT AND NOTIFY USER IF SO - CALL SD_CHKWP ; WRITE PROTECTED? - JR Z,SD_INITUNIT3 ; NOPE, BYPASS - CALL PC_SPACE ; SEPARATOR - CALL NZ,SD_PRTSTAT - ; WE DON'T EXIT HERE SINCE WRITE PROTECTION IS NOT A FATAL ERROR + CALL SD_CHKWP ; WRITE PROTECTED? + RET Z ; IF NOT, DONE + PRTS(" WP$") ; NOTIFY USER + RET ; DONE ; -SD_INITUNIT3: - SD_DPTR(SD_STAT) ; HL := ADR OF STATUS, AF TRASHED - XOR A ; SIGNAL SUCCESS - LD A,(HL) ; GET STATUS OF SELECTED UNIT - RET ; RETURN WITH A=0, AND Z SET -; -; SD DRIVER FUNCTION DISPATCH ENTRY POINT +;============================================================================= +; FUNCTION DISPATCH ENTRY POINT +;============================================================================= ; SD_DISPATCH: - LD A,C ; DEVICE/UNIT TO A - AND $0F ; REMOVE DEVICE BITS LEAVING JUST UNIT ID - CALL SD_SELUNIT ; SELECT DESIRED UNIT - LD A,B ; GET REQUESTED FUNCTION - AND $0F ; ISOLATE SUB-FUNCTION BITS + LD A,C ; DEVICE/UNIT TO A + AND $0F ; REMOVE DEVICE BITS LEAVING JUST UNIT ID + CALL SD_SELUNIT ; SELECT DESIRED UNIT + RET NZ ; ABORT ON ERROR + LD A,B ; GET REQUESTED FUNCTION + AND $0F ; ISOLATE SUB-FUNCTION BITS JP Z,SD_READ DEC A JP Z,SD_WRITE @@ -419,102 +424,105 @@ SD_DISPATCH: CALL PANIC ; SD_READ: +#IF (SDTRACE == 1) + LD HL,SD_PRTERR ; SET UP SD_PRTERR + PUSH HL ; ... TO FILTER ALL EXITS +#ENDIF ; READ A SECTOR - LD C,SD_CMD_READ_SNGL_BLK ; SET READ_SINGLE_BLOCK COMMAND - CALL SD_SECTIO ; DO SECTOR I/O - RET Z ; NO ERRORS, DONE - JP SD_PRTERR ; RETURN VIA PRINT ERROR + LD C,SD_CMD_READ_SNGL_BLK ; SET READ_SINGLE_BLOCK COMMAND + JP SD_SECTIO ; DO SECTOR I/O ; SD_WRITE: +#IF (SDTRACE == 1) + LD HL,SD_PRTERR ; SET UP SD_PRTERR + PUSH HL ; ... TO FILTER ALL EXITS +#ENDIF ; WRITE A SECTOR - CALL SD_CHKWP ; CHECK FOR WRITE PROTECT - JP NZ,SD_PRTERR ; IF PROTECTED, EXIT VIA PRINT ERROR - LD C,SD_CMD_WRITE_BLOCK ; SET WRITE_BLOCK COMMAND - CALL SD_SECTIO ; DO SECTOR I/O - RET Z ; NO ERRORS, DONE - JP SD_PRTERR ; RETURN VIA PRINT ERROR + CALL SD_CHKWP ; CHECK FOR WRITE PROTECT + JP NZ,SD_WRTPROT ; HANDLE IT IF SO + LD C,SD_CMD_WRITE_BLOCK ; SET WRITE_BLOCK COMMAND + JP SD_SECTIO ; DO SECTOR I/O ; SD_STATUS: ; RETURN UNIT STATUS - SD_DPTR(SD_STAT) ; HL := ADR OF STATUS, AF TRASHED - LD A,(HL) ; GET STATUS OF SELECTED UNIT - OR A ; SET FLAGS - RET ; AND RETURN + SD_DPTR(SD_STAT) ; HL := ADR OF STATUS, AF TRASHED + LD A,(HL) ; GET STATUS OF SELECTED UNIT + OR A ; SET FLAGS + RET ; AND RETURN ; SD_MEDIA: ; RE-INITIALIZE THE SD CARD TO ACCOMMODATE HOT SWAPPING - CALL SD_INITCARD ; RE-INIT SELECTED UNIT - LD A,MID_HD ; ASSUME SUCCESS, SETUP MEDIA ID - RET Z ; RETURN IF GOOD INIT - CALL SD_PRTERR ; FAILURE, PRINT ERROR - LD A,MID_NONE ; SIGNAL NO MEDA - OR A ; SET FLAGS - RET ; AND RETURN + CALL SD_INITCARD ; RE-INIT SELECTED UNIT + LD A,MID_HD ; ASSUME SUCCESS, SETUP MEDIA ID + RET Z ; RETURN IF GOOD INIT + LD A,MID_NONE ; SIGNAL NO MEDA + OR A ; SET FLAGS + RET ; AND RETURN ; SD_CAP: - SD_DPTR(SD_CAPACITY) ; POINT HL TO CAPACITY OF CUR UNIT - CALL LD32 ; GET THE CURRENT CAPACITY DO DE:HL - LD BC,512 ; 512 BYTES PER BLOCK - XOR A ; SIGNAL SUCCESS - RET ; AND DONE + SD_DPTR(SD_CAPACITY) ; POINT HL TO CAPACITY OF CUR UNIT + CALL LD32 ; GET THE CURRENT CAPACITY DO DE:HL + LD BC,512 ; 512 BYTES PER BLOCK + XOR A ; SIGNAL SUCCESS + RET ; AND DONE ; SD_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 SD_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 BIT - LD E,16 ; SECTORS / TRACK = 16 - XOR A ; SIGNAL SUCCESS + CALL SD_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 BIT + LD E,16 ; SECTORS / TRACK = 16 + XOR A ; SIGNAL SUCCESS RET ; ;============================================================================= -; SD I/O ROUTINES +; FUNCTION SUPPORT ROUTINES ;============================================================================= ; ; (RE)INITIALIZE CARD ; SD_INITCARD: ; -#IF ((SDMODE == SDMODE_DSD) | (SDMODE == SDMODE_MK4)) - IN A,(SD_OPRREG) ; GET OPERATIONS REGISTER - BIT 5,A ; TEST CARD DETECT BIT -#IF (SDTRACE >= 2) - CALL Z,SD_PRTPREFIX -#ENDIF - JP Z,SD_NOMEDIA ; NO MEDIA DETECTED IF ZERO -#ENDIF + ; CLEAR OUT UNIT SPECIFIC DATA + SD_DPTR(0) ; SET HL TO START OF UNIT DATA + LD BC,SD_UNITDATALEN + XOR A + CALL FILL +; + CALL SD_CHKCD ; CHECK CARD DETECT + JP Z,SD_NOMEDIA ; Z=NO MEDIA, HANDLE IF SO ; ; WAKE UP THE CARD, KEEP DIN HI (ASSERTED) AND /CS HI (DEASSERTED) LD B,$10 ; MIN 74 CLOCKS REQUIRED, WE USE 128 ($10 * 8) SD_INITCARD1: - LD A,$FF ; KEEP DIN HI - PUSH BC ; SAVE LOOP CONTROL - CALL SD_PUT ; SEND 8 CLOCKS - POP BC ; RESTORE LOOP CONTROL - DJNZ SD_INITCARD1 ; LOOP AS NEEDED + LD A,$FF ; KEEP DIN HI + PUSH BC ; SAVE LOOP CONTROL + CALL SD_PUT ; SEND 8 CLOCKS + POP BC ; RESTORE LOOP CONTROL + DJNZ SD_INITCARD1 ; LOOP AS NEEDED ; ; PUT CARD IN IDLE STATE - CALL SD_GOIDLE ; GO TO IDLE - RET NZ ; ABORT IF FAILED + CALL SD_GOIDLE ; GO TO IDLE + RET NZ ; ABORT IF FAILED ; SD_INITCARD2: - SD_DPTR(SD_TYPE) ; SET HL TO ADR OF CARD TYPE, TRASHES AF - LD A,SD_TYPESDSC ; ASSUME SDSC CARD TYPE - LD (HL),A ; SAVE IT + SD_DPTR(SD_TYPE) ; SET HL TO ADR OF CARD TYPE, TRASHES AF + LD A,SD_TYPESDSC ; ASSUME SDSC CARD TYPE + LD (HL),A ; SAVE IT ; ; CMD8 IS REQUIRED FOR V2 CARDS. FAILURE HERE IS OK AND ; JUST MEANS THAT IT IS A V1 CARD - LD A,SD_CMD_SEND_IF_COND ; SEND_IF_COND - CALL SD_INITCMD ; SETUP COMMAND BUFFER - LD HL,SD_CMDP2 ; POINT TO 3RD PARM BYTE - LD (HL),1 ; VHS=1, 2.7-3.6V - INC HL ; POINT TO 4TH PARM BYTE - LD (HL),$AA ; CHECK PATTERN - INC HL ; POINT TO CRC - LD (HL),$87 ; ... AND SET IT TO KNOWN VALUE OF $87 - CALL SD_EXECCMDND ; EXEC COMMAND W/ NO DATA RETURNED + LD A,SD_CMD_SEND_IF_COND ; SEND_IF_COND + CALL SD_INITCMD ; SETUP COMMAND BUFFER + LD HL,SD_CMDP2 ; POINT TO 3RD PARM BYTE + LD (HL),1 ; VHS=1, 2.7-3.6V + INC HL ; POINT TO 4TH PARM BYTE + LD (HL),$AA ; CHECK PATTERN + INC HL ; POINT TO CRC + LD (HL),$87 ; ... AND SET IT TO KNOWN VALUE OF $87 + CALL SD_EXECCMDND ; EXEC COMMAND W/ NO DATA RETURNED ; ; GET CARD OUT OF IDLE STATE BY SENDING SD_APP_OP_COND ; REPEATEDLY UNTIL IDLE BIT IS CLEAR @@ -522,30 +530,30 @@ SD_INITCARD2: LD (SD_LCNT),A SD_INITCARD3: ; DELAY A BIT PER SPEC - LD DE,300 ; 16US * 300 = ~5MS - CALL VDELAY ; CPU SPEED NORMALIZED DELAY + LD DE,300 ; 16US * 300 = ~5MS + CALL VDELAY ; CPU SPEED NORMALIZED DELAY ; SEND APP CMD INTRODUCER - CALL SD_EXECACMD ; SEND APP COMMAND INTRODUCER - CP SD_STCMDERR ; COMMAND ERROR? - JR Z,SD_INITCARD3A ; IF SO, TRY MMC CARD INIT - OR A ; SET FLAGS - RET NZ ; ABORT IF ANY OTHER ERROR + CALL SD_EXECACMD ; SEND APP COMMAND INTRODUCER + CP SD_STCMDERR ; COMMAND ERROR? + JR Z,SD_INITCARD3A ; IF SO, TRY MMC CARD INIT + OR A ; SET FLAGS + RET NZ ; ABORT IF ANY OTHER ERROR ; SEND APP_OP_COND - LD A,SD_ACMD_SEND_OP_COND ; SD_APP_OP_COND - CALL SD_INITCMD ; SETUP COMMAND BUFFER - LD A,$40 ; P0 = $40 INDICATES WE SUPPORT V2 CARDS - LD (SD_CMDP0),A ; SET COMMAND PARM 0 - CALL SD_EXECCMDND ; EXEC COMMAND W/ NO DATA RETURNED - RET NZ ; ABORT ON ERROR + LD A,SD_ACMD_SEND_OP_COND ; SD_APP_OP_COND + CALL SD_INITCMD ; SETUP COMMAND BUFFER + LD A,$40 ; P0 = $40 INDICATES WE SUPPORT V2 CARDS + LD (SD_CMDP0),A ; SET COMMAND PARM 0 + CALL SD_EXECCMDND ; EXEC COMMAND W/ NO DATA RETURNED + RET NZ ; ABORT ON ERROR ; CHECK FOR IDLE, EXIT LOOP IF IDLE CLEARED - LD A,(SD_RC) ; GET CARD RESULT CODE - OR A ; SET FLAGS - JR Z,SD_INITCARD4 ; IF IDLE BIT CLEAR, EXIT LOOP + LD A,(SD_RC) ; GET CARD RESULT CODE + OR A ; SET FLAGS + JR Z,SD_INITCARD4 ; IF IDLE BIT CLEAR, EXIT LOOP ; LOOP AS NEEDED - LD HL,SD_LCNT ; POINT TO LOOP COUNTER - DEC (HL) ; DECREMENT LOOP COUNTER - JR NZ,SD_INITCARD3 ; LOOP UNTIL COUNTER EXHAUSTED - JP SD_ERRINITTO ; HANDLE INIT TIMEOUT ERROR + LD HL,SD_LCNT ; POINT TO LOOP COUNTER + DEC (HL) ; DECREMENT LOOP COUNTER + JR NZ,SD_INITCARD3 ; LOOP UNTIL COUNTER EXHAUSTED + JP SD_ERRINITTO ; HANDLE INIT TIMEOUT ERROR ; SD_INITCARD3A: ; TRY MMC CARD INITIALIZATION @@ -554,62 +562,62 @@ SD_INITCARD3A: LD (SD_LCNT),A SD_INITCARD3B: ; DELAY A BIT PER SPEC - LD DE,300 ; 16US * 300 = ~5MS - CALL VDELAY ; CPU SPEED NORMALIZED DELAY + LD DE,300 ; 16US * 300 = ~5MS + CALL VDELAY ; CPU SPEED NORMALIZED DELAY ; SEND OP_COND COMMAND - LD A,SD_CMD_SEND_OP_COND ; SD_OP_COND - CALL SD_INITCMD ; SETUP COMMAND BUFFER - CALL SD_EXECCMDND ; EXEC COMMAND WITH NO DATA - RET NZ ; ABORT ON ERROR + LD A,SD_CMD_SEND_OP_COND ; SD_OP_COND + CALL SD_INITCMD ; SETUP COMMAND BUFFER + CALL SD_EXECCMDND ; EXEC COMMAND WITH NO DATA + RET NZ ; ABORT ON ERROR ; CHECK FOR IDLE, EXIT LOOP IF IDLE CLEARED - LD A,(SD_RC) ; GET CARD RESULT CODE - OR A ; SET FLAGS - JR Z,SD_INITCARD3C ; IDLE BIT CLEAR, EXIT LOOP + LD A,(SD_RC) ; GET CARD RESULT CODE + OR A ; SET FLAGS + JR Z,SD_INITCARD3C ; IDLE BIT CLEAR, EXIT LOOP ; LOOP AS NEEDED - LD HL,SD_LCNT ; POINT TO LOOP COUNTER - DEC (HL) ; DECREMENT LOOP COUNTER - JR NZ,SD_INITCARD3B ; LOOP UNTIL COUNTER EXHAUSTED - JP SD_ERRINITTO ; HANDLE INIT TIMEOUT ERROR + LD HL,SD_LCNT ; POINT TO LOOP COUNTER + DEC (HL) ; DECREMENT LOOP COUNTER + JR NZ,SD_INITCARD3B ; LOOP UNTIL COUNTER EXHAUSTED + JP SD_ERRINITTO ; HANDLE INIT TIMEOUT ERROR ; SD_INITCARD3C: ; SUCCESSFUL MMC CARD INITIALIZATION - LD C,SD_TYPEMMC ; MMC CARD TYPE - JR SD_INITCARD5 ; RESUME FLOW + LD C,SD_TYPEMMC ; MMC CARD TYPE + JR SD_INITCARD5 ; RESUME FLOW ; SD_INITCARD4: ; CMD58 RETURNS THE 32 BIT OCR REGISTER (R3), WE WANT TO CHECK ; BIT 30, IF SET THIS IS SDHC/XC CARD - LD A,SD_CMD_READ_OCR ; READ_OCR - CALL SD_INITCMD ; SETUP COMMAND BUFFER - CALL SD_EXECCMD ; EXECUTE COMMAND - RET NZ ; ABORT ON ERROR + LD A,SD_CMD_READ_OCR ; READ_OCR + CALL SD_INITCMD ; SETUP COMMAND BUFFER + CALL SD_EXECCMD ; EXECUTE COMMAND + RET NZ ; ABORT ON ERROR ; CMD58 WORKED, GET OCR DATA AND SET CARD TYPE - CALL SD_GET ; BITS 31-24 - CALL SD_DONE ; FINISH THE TRANSACTION - AND $40 ; ISOLATE BIT 30 (CCS) - LD C,SD_TYPESDSC ; ASSUME V1 CARD - JR Z,SD_INITCARD5 ; IF BIT NOT SET, THIS IS SDSC CARD + CALL SD_GET ; BITS 31-24 + CALL SD_DONE ; FINISH THE TRANSACTION + AND $40 ; ISOLATE BIT 30 (CCS) + LD C,SD_TYPESDSC ; ASSUME V1 CARD + JR Z,SD_INITCARD5 ; IF BIT NOT SET, THIS IS SDSC CARD ; SD_INITCARD4A: ; ACMD51 RETURNS THE 64 BIT SCR REGISTER (ONLY AVAILABLE ON SDSC AND ABOVE) ; SD_SPEC3 (BIT 47) IS SET IF CARD IS SDXC OR GREATER - CALL SD_EXECACMD ; SEND APP COMMAND INTRODUCER - RET NZ ; ABORT ON ERROR (THIS SHOULD ALWAYS WORK) - LD A,SD_ACMD_SEND_SCR ; APP CMD SEND_SCR - CALL SD_INITCMD ; SETUP COMMAND BUFFER - CALL SD_EXECCMD ; EXECUTE COMMAND - RET NZ ; ABORT ON ERROR (THIS SHOULD ALWAYS WORK) + CALL SD_EXECACMD ; SEND APP COMMAND INTRODUCER + RET NZ ; ABORT ON ERROR (THIS SHOULD ALWAYS WORK) + LD A,SD_ACMD_SEND_SCR ; APP CMD SEND_SCR + CALL SD_INITCMD ; SETUP COMMAND BUFFER + CALL SD_EXECCMD ; EXECUTE COMMAND + RET NZ ; ABORT ON ERROR (THIS SHOULD ALWAYS WORK) ; ACMD51 SUCCEEDED, NOW GET THE SCR REGISTER CONTENTS - LD BC,8 ; 8 BYTES OF SCR - LD HL,SD_BUF ; PUT IN OUR PRIVATE BUFFER - CALL SD_GETDATA ; GET THE DATA - CALL SD_DONE ; CLOSE THE TRANSACTION - JP NZ,SD_ERRDATA ; DATA XFER ERROR + LD BC,8 ; 8 BYTES OF SCR + LD HL,SD_BUF ; PUT IN OUR PRIVATE BUFFER + CALL SD_GETDATA ; GET THE DATA + CALL SD_DONE ; CLOSE THE TRANSACTION + JP NZ,SD_ERRDATA ; DATA XFER ERROR ; -#IF (SDTRACE >= 2) +#IF (SDTRACE >= 3) ; IF TRACING, DUMP THE SCR CONTENTS CALL SD_PRTPREFIX - LD DE,SD_STRSCR + LD DE,SD_STR_SCR CALL WRITESTR LD DE,SD_BUF LD A,8 @@ -617,59 +625,59 @@ SD_INITCARD4A: #ENDIF ; ; EXTRACT THE SD_SECURITY FIELD AND SET SDHC/SDXC BASED ON VALUE - LD A,(SD_BUF + 1) ; GET THIRD BYTE (BITS 47-40) (55-48) - AND %01110000 ; ISOLATE SD_SECURITY BITS - CP $40 ; CHECK FOR SDXC VALUE - LD C,SD_TYPESDHC ; ASSUME CARD TYPE = SDHC - JR NZ,SD_INITCARD5 ; IF NOT SDXC, DONE - LD C,SD_TYPESDXC ; OTHERWISE, THIS IS SDXC CARD + LD A,(SD_BUF + 1) ; GET THIRD BYTE (BITS 47-40) (55-48) + AND %01110000 ; ISOLATE SD_SECURITY BITS + CP $40 ; CHECK FOR SDXC VALUE + LD C,SD_TYPESDHC ; ASSUME CARD TYPE = SDHC + JR NZ,SD_INITCARD5 ; IF NOT SDXC, DONE + LD C,SD_TYPESDXC ; OTHERWISE, THIS IS SDXC CARD ; SD_INITCARD5: - SD_DPTR(SD_TYPE) ; SET HL TO ADR OF CARD TYPE, TRASHES AF - LD (HL),C ; SAVE IT + SD_DPTR(SD_TYPE) ; SET HL TO ADR OF CARD TYPE, TRASHES AF + LD (HL),C ; SAVE IT -#IF (SDTRACE >= 2) +#IF (SDTRACE >= 3) CALL SD_PRTPREFIX - LD DE,SD_STRSDTYPE + LD DE,SD_STR_SDTYPE CALL WRITESTR LD A,C CALL PRTHEXBYTE #ENDIF ; SET OUR DESIRED BLOCK LENGTH (512 BYTES) - LD A,SD_CMD_SET_BLOCKLEN ; SET_BLOCKLEN - CALL SD_INITCMD ; SETUP COMMAND BUFFER - LD DE,512 ; 512 BYTE BLOCK LENGTH - LD HL,SD_CMDP2 ; PUT VALUE INTO PARMS - LD (HL),D ; ... HIGH WORD (P0, P1) REMAIN ZERO - INC HL ; ... VALUE OF DE GET PUT IN LOW WORD (P2, P3) - LD (HL),E ; ... BUT OBSERVE BIG ENDIAN LAYOUT - CALL SD_EXECCMDND ; EXEC COMMAND W/ NO DATA - RET NZ ; ABORT ON ERROR + LD A,SD_CMD_SET_BLOCKLEN ; SET_BLOCKLEN + CALL SD_INITCMD ; SETUP COMMAND BUFFER + LD DE,512 ; 512 BYTE BLOCK LENGTH + LD HL,SD_CMDP2 ; PUT VALUE INTO PARMS + LD (HL),D ; ... HIGH WORD (P0, P1) REMAIN ZERO + INC HL ; ... VALUE OF DE GET PUT IN LOW WORD (P2, P3) + LD (HL),E ; ... BUT OBSERVE BIG ENDIAN LAYOUT + CALL SD_EXECCMDND ; EXEC COMMAND W/ NO DATA + RET NZ ; ABORT ON ERROR #IF ((SDMODE == SDMODE_CSIO) | (SDMODE == SDMODE_MK4)) ; PER SPEC, THE CARD SHOULD NOW BE ABLE TO HANDLE FULL SPEED OPERATION ; SO, FOR CSIO OPERATION, WE SET CSIO TO MAXIMUM SPEED - CALL SD_WAITTX ; MAKE SURE WE ARE DONE SENDING - XOR A ; ZERO MEANS MAX SPEED - OUT (Z180_CNTR),A ; NOW SET CSIO PORT + CALL SD_WAITTX ; MAKE SURE WE ARE DONE SENDING + XOR A ; ZERO MEANS MAX SPEED + OUT (Z180_CNTR),A ; NOW SET CSIO PORT #ENDIF ; ; ISSUE SEND_CSD (TO DERIVE CARD CAPACITY) - LD A,SD_CMD_SEND_CSD ; SEND_CSD - CALL SD_INITCMD ; SETUP COMMAND BUFFER - CALL SD_EXECCMD ; EXECUTE COMMAND - RET NZ ; ABORT ON ERROR - LD BC,16 ; 16 BYTES OF CSD - LD HL,SD_BUF ; PUT IN OUR PRIVATE BUFFER - CALL SD_GETDATA ; GET THE DATA - CALL SD_DONE ; CLOSE THE TRANSACTION - JP NZ,SD_ERRDATA ; DATA XFER ERROR -; -#IF (SDTRACE >= 2) + LD A,SD_CMD_SEND_CSD ; SEND_CSD + CALL SD_INITCMD ; SETUP COMMAND BUFFER + CALL SD_EXECCMD ; EXECUTE COMMAND + RET NZ ; ABORT ON ERROR + LD BC,16 ; 16 BYTES OF CSD + LD HL,SD_BUF ; PUT IN OUR PRIVATE BUFFER + CALL SD_GETDATA ; GET THE DATA + CALL SD_DONE ; CLOSE THE TRANSACTION + JP NZ,SD_ERRDATA ; DATA XFER ERROR +; +#IF (SDTRACE >= 3) ; IF TRACING, DUMP THE CSD CONTENTS CALL SD_PRTPREFIX - LD DE,SD_STRCSD + LD DE,SD_STR_CSD CALL WRITESTR LD DE,SD_BUF LD A,16 @@ -677,155 +685,154 @@ SD_INITCARD5: #ENDIF ; ; GET SIZE OF DEVICE IN BLOCKS - SD_DPTR(SD_TYPE) ; SET HL TO ADR OF CARD TYPE, TRASHES AF - LD A,(HL) ; GET CARD TYPE - OR A ; SET FLAGS - CALL Z,PANIC ; PANIC IF CARD TYPE UNKNOWN - CP SD_TYPESDHC ; COMPARE TO SDHC (V2) - JP NC,SD_INITCARD8 ; HANDLE SDHC (V2) OR BETTER - JR SD_INITCARD6 ; HANDLE MMC OR SDSC + SD_DPTR(SD_TYPE) ; SET HL TO ADR OF CARD TYPE, TRASHES AF + LD A,(HL) ; GET CARD TYPE + OR A ; SET FLAGS + CALL Z,PANIC ; PANIC IF CARD TYPE UNKNOWN + CP SD_TYPESDHC ; COMPARE TO SDHC (V2) + JP NC,SD_INITCARD8 ; HANDLE SDHC (V2) OR BETTER + JR SD_INITCARD6 ; HANDLE MMC OR SDSC ; ; CAPACITY CALCULATION FOR MMC OR SDSD (V1) CARDS: ; BYTES = (C_SIZE + 1) * 2^(2+C_SIZE_MULT+READ_BL_LEN) = (C_SIZE+1) << (2+C_SIZE_MULT+READ_BL_LEN) ; BLOCKS = BYTES / 512 = BYTES >> 9 ; SD_INITCARD6: ; GET SIZE FOR V1 CARD - PUSH IX ; SAVE IX - LD IX,SD_BUF ; POINT IX TO BUFFER - LD A,(IX+6) ; GET C_SIZE MSB - AND %00000011 ; MASK OFF TOP 6 BITS (NOT PART OF C_SIZE) - LD C,A ; MSB -> C - LD D,(IX+7) ; D - LD E,(IX+8) ; LSB -> E - LD B,6 ; RIGHT SHIFT WHOLE THING BY 6 BITS + PUSH IX ; SAVE IX + LD IX,SD_BUF ; POINT IX TO BUFFER + LD A,(IX+6) ; GET C_SIZE MSB + AND %00000011 ; MASK OFF TOP 6 BITS (NOT PART OF C_SIZE) + LD C,A ; MSB -> C + LD D,(IX+7) ; D + LD E,(IX+8) ; LSB -> E + LD B,6 ; RIGHT SHIFT WHOLE THING BY 6 BITS SD_INITCARD7: - SRA C ; SHIFT MSB - RR D ; SHIFT NEXT BYTE - RR E ; SHIFT LSB - DJNZ SD_INITCARD7 ; LOOP TILL DONE - PUSH DE ; DE = C_SIZE, SAVE IT - LD A,(IX+9) ; GET C_SIZE_MULT MSB - LD B,(IX+10) ; GET C_SIZE_MULT LSB - SLA B ; SHIFT LEFT MSB - RLA ; SHIFT LEFT LSB - AND %00000111 ; ISOLATE RELEVANT BITS - LD C,A ; C := C_SIZE_MULT - LD A,(IX+5) ; GET READ_BL_LEN - AND %00001111 ; ISLOATE RELEVANT BITS - LD B,A ; B := READ_BL_LEN + SRA C ; SHIFT MSB + RR D ; SHIFT NEXT BYTE + RR E ; SHIFT LSB + DJNZ SD_INITCARD7 ; LOOP TILL DONE + PUSH DE ; DE = C_SIZE, SAVE IT + LD A,(IX+9) ; GET C_SIZE_MULT MSB + LD B,(IX+10) ; GET C_SIZE_MULT LSB + SLA B ; SHIFT LEFT MSB + RLA ; SHIFT LEFT LSB + AND %00000111 ; ISOLATE RELEVANT BITS + LD C,A ; C := C_SIZE_MULT + LD A,(IX+5) ; GET READ_BL_LEN + AND %00001111 ; ISLOATE RELEVANT BITS + LD B,A ; B := READ_BL_LEN ; FINAL MULTIPLIER IS 2^(C_SIZE_MULT + READ_BL_LEN + 2) - LD A,B ; READ_BL_LEN - ADD A,C ; AND C_SIZE_MULT - ADD A,2 ; AND 2 MORE BY DEFINITION + LD A,B ; READ_BL_LEN + ADD A,C ; AND C_SIZE_MULT + ADD A,2 ; AND 2 MORE BY DEFINITION ; RELOAD C_SIZE AND CONVERT TO 32 BIT VALUE IN DE:HL - POP HL ; RECOVE C_SIZE - INC HL ; ADD 1 - LD DE,0 ; HI WORD IS ZERO + POP HL ; RECOVE C_SIZE + INC HL ; ADD 1 + LD DE,0 ; HI WORD IS ZERO ; ADJUST TO 512 BYTE BLOCK COUNT - LD B,A ; NORMALIZE TO BYTE COUNT - CALL SLA32 ; BIT SHIFT LEFT ACCORDING TO MULTIPLIERS - LD B,9 ; NORMALIZE TO 512 BYTE BLOCK COUNT - CALL SRL32 ; BIT SHIFT RIGHT 9 BITS - POP IX ; RESTORE IX - JR SD_INITCARD9 ; RECORD VALUE + LD B,A ; NORMALIZE TO BYTE COUNT + CALL SLA32 ; BIT SHIFT LEFT ACCORDING TO MULTIPLIERS + LD B,9 ; NORMALIZE TO 512 BYTE BLOCK COUNT + CALL SRL32 ; BIT SHIFT RIGHT 9 BITS + POP IX ; RESTORE IX + JR SD_INITCARD9 ; RECORD VALUE ; ; CAPACITY CALCULATION FOR SDHC/SDXC (V2/V3) CARDS: ; BLOCKS = (C_SIZE + 1) * 1024 = C_SIZE << 10 ; SD_INITCARD8: ; GET SIZE FOR V2 CARD - PUSH IX ; SAVE IX - LD IX,SD_BUF ; POINT IX TO BUFFER - LD A,(IX + 7) ; GET C_SIZE MSB TO A - AND %00111111 ; ISOLATE RELEVANT BITS - LD H,(IX + 8) ; GET NEXT BYTE TO H - LD L,(IX + 9) ; GET C_SIZE LSB TO L - POP IX ; RESTORE IX + PUSH IX ; SAVE IX + LD IX,SD_BUF ; POINT IX TO BUFFER + LD A,(IX + 7) ; GET C_SIZE MSB TO A + AND %00111111 ; ISOLATE RELEVANT BITS + LD H,(IX + 8) ; GET NEXT BYTE TO H + LD L,(IX + 9) ; GET C_SIZE LSB TO L + POP IX ; RESTORE IX ; ADD 1 TO C_SIZE IN A:HL - LD DE,1 ; LOAD 1 - ADD HL,DE ; ADD TO HL - ADC A,0 ; HANDLE CARRY + LD DE,1 ; LOAD 1 + ADD HL,DE ; ADD TO HL + ADC A,0 ; HANDLE CARRY ; CONVERT TO 32 BIT, A:HL -> DE:HL LD D,0 LD E,A ; DIVIDE BY 1024 TO NORMALIZE, LEFT SHIFT 10 BITS - LD B,10 ; SHIFT BY 10 BITS - CALL SLA32 ; SHIFT THE 32 BIT VALUE - JR SD_INITCARD9 ; CONTINUE + LD B,10 ; SHIFT BY 10 BITS + CALL SLA32 ; SHIFT THE 32 BIT VALUE + JR SD_INITCARD9 ; CONTINUE ; SD_INITCARD9: ; COMMON CODE TO RECORD RESULTANT SIZE (IN DE:HL) ; SAVE DERIVED CAPACITY VALUE - PUSH HL ; SAVE HL - SD_DPTR(SD_CAPACITY) ; SET HL TO ADR OF CARD CAPACITY, TRASHES AF - PUSH HL ; MOVE ADDRESS - POP BC ; ... TO BC - POP HL ; RECOVER HL - CALL ST32 ; SAVE THE CAPACITY VALUE (DWORD) + PUSH HL ; SAVE HL + SD_DPTR(SD_CAPACITY) ; SET HL TO ADR OF CARD CAPACITY, TRASHES AF + PUSH HL ; MOVE ADDRESS + POP BC ; ... TO BC + POP HL ; RECOVER HL + CALL ST32 ; SAVE THE CAPACITY VALUE (DWORD) ; ; RESET CARD STATUS TO 0 (OK) - SD_DPTR(SD_STAT) ; HL := ADR OF STATUS, AF TRASHED - XOR A ; A := 0 (STATUS = OK) - LD (HL),A ; SAVE IT -; - XOR A ; SIGNAL SUCCESS - RET ; RETURN + SD_DPTR(SD_STAT) ; HL := ADR OF STATUS, AF TRASHED + XOR A ; A := 0 (STATUS = OK) + LD (HL),A ; SAVE IT ; + RET ; RETURN, A=0, Z SET + ; SECTOR I/O ; SD CARD COMMAND BYTE MUST BE PASSED IN C ; SD_SECTIO: PUSH BC - CALL SD_CHKCARD ; CHECK / REINIT CARD AS NEEDED + CALL SD_CHKCARD ; CHECK / REINIT CARD AS NEEDED POP BC - RET NZ ; ABORT IF REINIT FAILED + RET NZ ; ABORT IF REINIT FAILED - LD A,C ; LOAD SD CARD COMMADN BYTE - CALL SD_INITCMD ; SETUP COMMAND BUFFER - CALL SD_SETADDR ; SETUP LBA ADDRESS - CALL SD_EXECCMD ; EXECUTE COMMAND - RET NZ ; ABORT ON ERROR + LD A,C ; LOAD SD CARD COMMAND BYTE + CALL SD_INITCMD ; SETUP COMMAND BUFFER + CALL SD_SETADDR ; SETUP LBA ADDRESS + CALL SD_EXECCMD ; EXECUTE COMMAND + RET NZ ; ABORT ON ERROR LD HL,(DIOBUF) - LD BC,512 ; LENGTH TO READ - LD A,(SD_CMD) ; GET THE COMMAND - CP SD_CMD_READ_SNGL_BLK ; READ_SINGLE_BLOCK? - JR Z,SD_SECTIO1 ; HANDLE READ - CP SD_CMD_WRITE_BLOCK ; WRITE_BLOCK? - JR Z,SD_SECTIO2 ; HANDLE WRITE - CALL PANIC ; PANIC ON ANYTHING ELSE + LD BC,512 ; LENGTH TO READ + LD A,(SD_CMD) ; GET THE COMMAND + CP SD_CMD_READ_SNGL_BLK ; READ_SINGLE_BLOCK? + JR Z,SD_SECTIO1 ; HANDLE READ + CP SD_CMD_WRITE_BLOCK ; WRITE_BLOCK? + JR Z,SD_SECTIO2 ; HANDLE WRITE + CALL PANIC ; PANIC ON ANYTHING ELSE SD_SECTIO1: ; GET SECTOR DATA - CALL SD_GETDATA ; GET THE BLOCK - JR SD_SECTIO3 ; AND CONTINUE + CALL SD_GETDATA ; GET THE BLOCK + JR SD_SECTIO3 ; AND CONTINUE SD_SECTIO2: ; PUT SECTOR DATA - CALL SD_PUTDATA ; PUT THE BLOCK AND FALL THRU + CALL SD_PUTDATA ; PUT THE BLOCK AND FALL THRU SD_SECTIO3: ; CONTINUE WITH COMMON CODE - CALL SD_DONE ; CLOSE THE TRANSACTION - RET Z ; RETURN WITH A=0 AND Z SET - JP SD_ERRDATA ; DATA XFER ERROR + CALL SD_DONE ; CLOSE THE TRANSACTION + RET Z ; RETURN WITH A=0 AND Z SET + JP SD_ERRDATA ; DATA XFER ERROR ; ; CHECK THE SD CARD, ATTEMPT TO REINITIALIZE IF NEEDED ; SD_CHKCARD: - SD_DPTR(SD_STAT) ; HL = ADR OF STATUS, AF TRASHED - LD A,(HL) ; GET CURRENT STATUS - OR A ; SET FLAGS - RET Z ; RETURN WITH A=0 AND Z SET - JP SD_INITCARD ; OTHERWISE INIT CARD + SD_DPTR(SD_STAT) ; HL = ADR OF STATUS, AF TRASHED + LD A,(HL) ; GET CURRENT STATUS + OR A ; SET FLAGS + RET Z ; RETURN WITH A=0 AND Z SET + JP SD_INITCARD ; OTHERWISE INIT CARD ; ; CONVERT LBA ADDRESS IN HSTLBA TO CARD SPECIFIC ADDRESS IN CMD PARMS ; V1 CARDS REQUIRE BYTE ADDRESSING, SO A TRANSLATION IS DONE IN THAT CASE ; SD_SETADDR: - SD_DPTR(SD_TYPE) ; SET HL TO ADR OF CARD TYPE, TRASHES AF - LD A,(HL) ; GET CARD TYPE - PUSH AF ; SAVE IT - LD HL,HSTLBA ; POINT TO INCOMING LBA VALUE - CALL LD32 ; LOAD IT TO DE:HL, AF IS TRASHED - POP AF ; GET CARD TYPE BACK - CP SD_TYPESDHC ; IS IT V2 OR BETTER? - JR NC,SD_SETADDR1 ; IF SO, BYPASS TRANSLATION + SD_DPTR(SD_TYPE) ; SET HL TO ADR OF CARD TYPE, TRASHES AF + LD A,(HL) ; GET CARD TYPE + PUSH AF ; SAVE IT + LD HL,HSTLBA ; POINT TO INCOMING LBA VALUE + CALL LD32 ; LOAD IT TO DE:HL, AF IS TRASHED + POP AF ; GET CARD TYPE BACK + CP SD_TYPESDHC ; IS IT V2 OR BETTER? + JR NC,SD_SETADDR1 ; IF SO, BYPASS TRANSLATION ; ; TRANSLATE BLOCK ADDRESS TO BYTE ADDRESS FOR V1 CARDS LD D,E @@ -839,208 +846,209 @@ SD_SETADDR: ; SD_SETADDR1: ; STORE RESULTANT ADDRESS INTO PARMS (BIG ENDIAN!) - PUSH HL ; SAVE LOW WORD OF ADDRESS - LD HL,SD_CMDP0 ; POINT TO START OF PARM BYTES - LD (HL),D ; SAVE MSB OF HI WORD - INC HL ; NEXT BYTE - LD (HL),E ; SAVE LSB OF HI WORD - INC HL ; NEXT BYTE - POP DE ; RECOVER LOW WORD OF ADDRESS INTO DE - LD (HL),D ; SAVE MSB OF LO WORD - INC HL ; NEXT BYTE - LD (HL),E ; SAVE LSB OF LO WORD - RET ; DONE -; -;================================================================================================== -; SD DISK DRIVER COMMAND PROCESSING -;================================================================================================== + PUSH HL ; SAVE LOW WORD OF ADDRESS + LD HL,SD_CMDP0 ; POINT TO START OF PARM BYTES + LD (HL),D ; SAVE MSB OF HI WORD + INC HL ; NEXT BYTE + LD (HL),E ; SAVE LSB OF HI WORD + INC HL ; NEXT BYTE + POP DE ; RECOVER LOW WORD OF ADDRESS INTO DE + LD (HL),D ; SAVE MSB OF LO WORD + INC HL ; NEXT BYTE + LD (HL),E ; SAVE LSB OF LO WORD + RET ; DONE +; +;============================================================================= +; COMMAND PROCESSING +;============================================================================= ; ; PUT CARD IN IDLE STATE ; SD_GOIDLE: - CALL SD_GOIDLE1 ; FIRST ATTEMPT - RET Z ; DONE IF SUCCEEDED + CALL SD_GOIDLE1 ; FIRST ATTEMPT + RET Z ; DONE IF SUCCEEDED ; FALL THRU FOR SECOND ATTEMPT IF NEEDED ; SD_GOIDLE1: ; SEEMS TO HELP SOME CARDS? - ;CALL SD_SELECT ; ASSERT CS - ;CALL SD_DONE ; SEND 8 CLOCKS AND DEASSERT CS + ;CALL SD_SELECT ; ASSERT CS + ;CALL SD_DONE ; SEND 8 CLOCKS AND DEASSERT CS ; SMALL DELAY HERE HELPS SOME CARDS - LD DE,300 ; 16US * 300 = ~5MS - CALL VDELAY ; CPU SPEED NORMALIZED DELAY + ;;LD DE,300 ; 16US * 300 = ~5MS + ;LD DE,60 ; 16US * 60 = ~1MS + ;CALL VDELAY ; CPU SPEED NORMALIZED DELAY ; PUT CARD IN IDLE STATE - LD A,SD_CMD_GO_IDLE_STATE ; CMD0 = ENTER IDLE STATE - CALL SD_INITCMD ; INIT COMMAND BUFFER - LD A,$95 ; CRC FOR GO_IDLE_STATE COMMAND IS $95 - LD (SD_CMDCRC),A ; SET CRC - CALL SD_EXECCMDND ; EXECUTE COMMAND W/ NO DATA RETURNED - RET NZ ; ABORT ON ERROR - LD A,(SD_RC) ; GET CARD RESULT - DEC A ; MAP EXPECTED $01 -> $00 - RET Z ; ALL IS GOOD, RETURN WITH Z=0 AND Z SET - LD A,SD_STCMDERR ; SET COMMAND ERROR VALUE, NZ ALREADY SET - RET ; AND RETURN + LD A,SD_CMD_GO_IDLE_STATE ; CMD0 = ENTER IDLE STATE + CALL SD_INITCMD ; INIT COMMAND BUFFER + LD A,$95 ; CRC FOR GO_IDLE_STATE COMMAND IS $95 + LD (SD_CMDCRC),A ; SET CRC + CALL SD_EXECCMDND ; EXECUTE COMMAND W/ NO DATA RETURNED + RET NZ ; ABORT ON ERROR + LD A,(SD_RC) ; GET CARD RESULT + DEC A ; MAP EXPECTED $01 -> $00 + RET Z ; ALL IS GOOD, RETURN WITH Z=0 AND Z SET + LD A,SD_STCMDERR ; SET COMMAND ERROR VALUE, NZ ALREADY SET + RET ; AND RETURN ; ; INITIALIZE COMMAND BUFFER ; COMMAND BYTE IN ACCUM ; HL AND AF DESTROYED ; SD_INITCMD: - LD HL,SD_CMDBUF ; POINT TO START OF BUFFER - LD (HL),A ; SET THE COMMAND BYTE - XOR A ; CLEAR ACCUM - LD B,7 ; PREPARE TO CLEAR NEXT 7 BYTES (PARMS, CRC, RC, TOK) + LD HL,SD_CMDBUF ; POINT TO START OF BUFFER + LD (HL),A ; SET THE COMMAND BYTE + XOR A ; CLEAR ACCUM + LD B,7 ; PREPARE TO CLEAR NEXT 7 BYTES (PARMS, CRC, RC, TOK) SD_INITCMD1: - INC HL ; POINT TO NEXT BYTE - LD (HL),A ; CLEAR IT - DJNZ SD_INITCMD1 ; LOOP TILL DONE + INC HL ; POINT TO NEXT BYTE + LD (HL),A ; CLEAR IT + DJNZ SD_INITCMD1 ; LOOP TILL DONE RET ; ; EXECUTE APP COMMAND ; SD_EXECACMD: - LD A,SD_CMD_APP_CMD ; APP_CMD, AN APP CMD IS NEXT - CALL SD_INITCMD ; SETUP COMMAND BUFFER - JR SD_EXECCMDND ; EXEC COMMAND W/ NO DATA RETURNED + LD A,SD_CMD_APP_CMD ; APP_CMD, AN APP CMD IS NEXT + CALL SD_INITCMD ; SETUP COMMAND BUFFER + JR SD_EXECCMDND ; EXEC COMMAND W/ NO DATA RETURNED ; ; EXECUTE COMMAND WITH NO DATA ; SD_EXECCMDND: - CALL SD_EXECCMD ; RUN THE COMMAND - JP Z,SD_DONE ; RETURN THRU SD_DONE IF NO ERROR - RET ; ERROR STATUS, JUST RETURN, SD_DONE WAS ALREADY RUN + CALL SD_EXECCMD ; RUN THE COMMAND + JP Z,SD_DONE ; RETURN THRU SD_DONE IF NO ERROR + RET ; ERROR STATUS, JUST RETURN, SD_DONE WAS ALREADY RUN ; ; EXECUTE A COMMAND ; WILL FINISH TRANSACTION IF ERROR OCCURS ; RETURNS STATUS IN A WITH ZF SET ACCORDINGLY ; SD_EXECCMD: -#IF (SDTRACE >= 2) +#IF (SDTRACE >= 3) PUSH AF CALL SD_PRTPREFIX LD DE,SD_CMDBUF - PRTS(" CMD =$") + PRTS(" CMD$") LD A,6 CALL PRTHEXBUF - LD DE,SD_STRARROW + LD DE,SD_STR_ARROW CALL WRITESTR POP AF #ENDIF ; WAIT FOR CARD TO BE READY - CALL SD_WAITRDY ; WAIT FOR CARD TO BE READY FOR A COMMAND - JP NZ,SD_ERRRDYTO ; HANDLE TIMEOUT ERROR + CALL SD_WAITRDY ; WAIT FOR CARD TO BE READY FOR A COMMAND + JP NZ,SD_ERRRDYTO ; HANDLE TIMEOUT ERROR ; SEND THE COMMAND - LD HL,SD_CMDBUF ; POINT TO COMMAND BUFFER - LD E,6 ; COMMANDS ARE 6 BYTES + LD HL,SD_CMDBUF ; POINT TO COMMAND BUFFER + LD E,6 ; COMMANDS ARE 6 BYTES SD_EXECCMD1: - LD A,(HL) ; PREPARE TO SEND NEXT BYTE - CALL SD_PUT ; SEND IT - INC HL ; POINT TO NEXT BYTE - DEC E ; DEC LOOP COUNTER - JR NZ,SD_EXECCMD1 ; LOOP TILL DONE W/ ALL 6 BYTES + LD A,(HL) ; PREPARE TO SEND NEXT BYTE + CALL SD_PUT ; SEND IT + INC HL ; POINT TO NEXT BYTE + DEC E ; DEC LOOP COUNTER + JR NZ,SD_EXECCMD1 ; LOOP TILL DONE W/ ALL 6 BYTES ; ; GET RESULT - LD E,0 ; INIT TIMEOUT LOOP COUNTER + LD E,0 ; INIT TIMEOUT LOOP COUNTER SD_EXECCMD2: - CALL SD_GET ; GET A BYTE FROM THE CARD - OR A ; SET FLAGS - JP P,SD_EXECCMD3 ; IF HIGH BIT IS 0, WE HAVE RESULT - DEC E ; OTHERWISE DECREMENT LOOP COUNTER - JR NZ,SD_EXECCMD2 ; AND LOOP UNTIL TIMEOUT + CALL SD_GET ; GET A BYTE FROM THE CARD + OR A ; SET FLAGS + JP P,SD_EXECCMD3 ; IF HIGH BIT IS 0, WE HAVE RESULT + DEC E ; OTHERWISE DECREMENT LOOP COUNTER + JR NZ,SD_EXECCMD2 ; AND LOOP UNTIL TIMEOUT JP SD_ERRCMDTO ; SD_EXECCMD3: ; COMMAND COMPLETE, SAVE RC AND PRINT DIAGNOSTICS AS APPROPRIATE - LD (SD_RC),A ; RECORD THE RESULT -#IF (SDTRACE >= 2) - CALL SD_PRTRC ; IF MAX TRACING, PRINT RC + LD (SD_RC),A ; RECORD THE RESULT +#IF (SDTRACE >= 3) + CALL SD_PRTRC ; IF MAX TRACING, PRINT RC #ENDIF #IF (DSKYENABLE) PUSH AF - CALL SD_DSKY ; IF USING DSKY, SHOW IT THERE + CALL SD_DSKY ; IF USING DSKY, SHOW IT THERE POP AF #ENDIF - AND ~$01 ; MASK OFF IDLE BIT AND SET FLAGS - RET Z ; IF RC = 0, NO ERROR, RETURN - CALL SD_DONE ; IF ERROR, COMPLETE TRANSACTION - JP SD_ERRCMD ; ... AND HANDLE IT + AND ~$01 ; MASK OFF IDLE BIT AND SET FLAGS + RET Z ; IF RC = 0, NO ERROR, RETURN + CALL SD_DONE ; IF ERROR, COMPLETE TRANSACTION + JP SD_ERRCMD ; ... AND HANDLE IT ; ; SD_GETDATA ; SD_GETDATA: - PUSH HL ; SAVE DESTINATION ADDRESS - PUSH BC ; SAVE LENGTH TO RECEIVE - LD DE,$7FFF ; LOOP MAX (TIMEOUT) + PUSH HL ; SAVE DESTINATION ADDRESS + PUSH BC ; SAVE LENGTH TO RECEIVE + LD DE,$7FFF ; LOOP MAX (TIMEOUT) SD_GETDATA1: CALL SD_GET - CP $FF ; WANT BYTE != $FF - JR NZ,SD_GETDATA2 ; NOT $FF, MOVE ON + CP $FF ; WANT BYTE != $FF + JR NZ,SD_GETDATA2 ; NOT $FF, MOVE ON DEC DE BIT 7,D - JR Z,SD_GETDATA1 ; KEEP TRYING UNTIL TIMEOUT + JR Z,SD_GETDATA1 ; KEEP TRYING UNTIL TIMEOUT SD_GETDATA2: - LD (SD_TOK),A ; SAVE TOKEN VALUE -#IF (SDTRACE >= 2) + LD (SD_TOK),A ; SAVE TOKEN VALUE +#IF (SDTRACE >= 3) PUSH AF CALL SD_PRTTOK POP AF #ENDIF - POP DE ; RESTORE LENGTH TO RECEIVE - POP HL ; RECOVER DEST ADDRESS - CP $FE ; PACKET START? - JR NZ,SD_GETDATA4 ; NOPE, ABORT, A HAS ERROR CODE + POP DE ; RESTORE LENGTH TO RECEIVE + POP HL ; RECOVER DEST ADDRESS + CP $FE ; PACKET START? + JR NZ,SD_GETDATA4 ; NOPE, ABORT, A HAS ERROR CODE SD_GETDATA3: - CALL SD_GET ; GET NEXT BYTE - LD (HL),A ; SAVE IT + CALL SD_GET ; GET NEXT BYTE + LD (HL),A ; SAVE IT INC HL DEC DE LD A,D OR E - JR NZ,SD_GETDATA3 ; LOOP FOR ALL BYTES - CALL SD_GET ; DISCARD CRC BYTE 1 - CALL SD_GET ; DISCARD CRC BYTE 2 - XOR A ; RESULT IS ZERO + JR NZ,SD_GETDATA3 ; LOOP FOR ALL BYTES + CALL SD_GET ; DISCARD CRC BYTE 1 + CALL SD_GET ; DISCARD CRC BYTE 2 + XOR A ; RESULT IS ZERO SD_GETDATA4: RET ; ; SD_PUTDATA ; SD_PUTDATA: - PUSH HL ; SAVE SOURCE ADDRESS - PUSH BC ; SAVE LENGTH TO SEND + PUSH HL ; SAVE SOURCE ADDRESS + PUSH BC ; SAVE LENGTH TO SEND - LD A,$FE ; PACKET START - CALL SD_PUT ; SEND IT + LD A,$FE ; PACKET START + CALL SD_PUT ; SEND IT - POP DE ; RECOVER LENGTH TO SEND - POP HL ; RECOVER SOURCE ADDRESS + POP DE ; RECOVER LENGTH TO SEND + POP HL ; RECOVER SOURCE ADDRESS SD_PUTDATA1: - LD A,(HL) ; GET NEXT BYTE TO SEND - CALL SD_PUT ; SEND IF + LD A,(HL) ; GET NEXT BYTE TO SEND + CALL SD_PUT ; SEND IF INC HL DEC DE LD A,D OR E - JR NZ,SD_PUTDATA1 ; LOOP FOR ALL BYTES - LD A,$FF ; DUMMY CRC BYTE + JR NZ,SD_PUTDATA1 ; LOOP FOR ALL BYTES + LD A,$FF ; DUMMY CRC BYTE CALL SD_PUT - LD A,$FF ; DUMMY CRC BYTE + LD A,$FF ; DUMMY CRC BYTE CALL SD_PUT - LD DE,$7FFF ; LOOP MAX (TIMEOUT) + LD DE,$7FFF ; LOOP MAX (TIMEOUT) SD_PUTDATA2: CALL SD_GET - CP $FF ; WANT BYTE != $FF - JR NZ,SD_PUTDATA3 ; NOT $FF, MOVE ON + CP $FF ; WANT BYTE != $FF + JR NZ,SD_PUTDATA3 ; NOT $FF, MOVE ON DEC DE BIT 7,D - JR Z,SD_PUTDATA2 ; KEEP TRYING UNTIL TIMEOUT + JR Z,SD_PUTDATA2 ; KEEP TRYING UNTIL TIMEOUT SD_PUTDATA3: LD (SD_TOK),A -#IF (SDTRACE >= 2) +#IF (SDTRACE >= 3) PUSH AF CALL SD_PRTTOK POP AF @@ -1054,19 +1062,19 @@ SD_PUTDATA3: ; SELECT CARD AND WAIT FOR IT TO BE READY ($FF) ; SD_WAITRDY: - CALL SD_SELECT ; SELECT CARD - LD DE,$FFFF ; LOOP MAX (TIMEOUT) + CALL SD_SELECT ; SELECT CARD + LD DE,$FFFF ; LOOP MAX (TIMEOUT) SD_WAITRDY1: CALL SD_GET - INC A ; $FF -> $00 - RET Z ; IF READY, RETURN + INC A ; $FF -> $00 + RET Z ; IF READY, RETURN DEC DE LD A,D OR E - JR NZ,SD_WAITRDY1 ; KEEP TRYING UNTIL TIMEOUT - XOR A ; ZERO ACCUM - DEC A ; ACCUM := $FF TO SIGNAL ERROR - RET ; TIMEOUT + JR NZ,SD_WAITRDY1 ; KEEP TRYING UNTIL TIMEOUT + XOR A ; ZERO ACCUM + DEC A ; ACCUM := $FF TO SIGNAL ERROR + RET ; TIMEOUT ; ; FINISH A TRANSACTION - PRESERVE AF ; @@ -1087,7 +1095,7 @@ SD_DONE: RET ; ;============================================================================= -; SD HARDWARE INTERFACE ROUTINES +; HARDWARE INTERFACE ROUTINES ;============================================================================= ; ; PERFORM HARDWARE SPECIFIC INITIALIZATION @@ -1102,8 +1110,8 @@ SD_SETUP: ; #IF ((SDMODE == SDMODE_CSIO) | (SDMODE == SDMODE_MK4)) ; CSIO SETUP -; LD A,2 ; 18MHz/20 <= 400kHz - LD A,6 ; ??? +; LD A,2 ; 18MHz/20 <= 400kHz + LD A,6 ; ??? OUT0 (SD_CNTR),A LD A,SD_OPRDEF LD (SD_OPRVAL),A @@ -1111,7 +1119,7 @@ SD_SETUP: #ENDIF ; #IF (SDMODE == SDMODE_PPI) - LD A,82H ; PPI PORT A=OUT, B=IN, C=OUT + LD A,82H ; PPI PORT A=OUT, B=IN, C=OUT OUT (SD_PPIX),A LD A,SD_OPRDEF LD (SD_OPRVAL),A @@ -1120,11 +1128,11 @@ SD_SETUP: ; #IF (SDMODE == SDMODE_UART) SD_OPRMSK .EQU (SD_CS | SD_CLK | SD_DI) - IN A,(SD_OPRREG) ; OPRREG == SIO_MCR - AND ~SD_OPRMSK ; MASK OFF SD CONTROL BITS - OR SD_OPRDEF ; SET DEFAULT BITS - LD (SD_OPRVAL),A ; RECORD THE WORKING VALLUE - OUT (SD_OPRREG),A ; OPRREG == SIO_MCR + IN A,(SD_OPRREG) ; OPRREG == SIO_MCR + AND ~SD_OPRMSK ; MASK OFF SD CONTROL BITS + OR SD_OPRDEF ; SET DEFAULT BITS + LD (SD_OPRVAL),A ; RECORD THE WORKING VALLUE + OUT (SD_OPRREG),A ; OPRREG == SIO_MCR #ENDIF ; XOR A @@ -1134,47 +1142,52 @@ SD_OPRMSK .EQU (SD_CS | SD_CLK | SD_DI) ; UNIT IS SPECIFIED IN A ; SD_SELUNIT: - LD HL,SD_UNIT ; POINT TO PREVIOUSLY SELECTED UNIT - CP (HL) ; SAME? - RET Z ; IF SO, NOTHING MORE TO DO - CP SD_UNITCNT ; CHECK VALIDITY (EXCEED UNIT COUNT?) - CALL NC,PANIC ; PANIC ON INVALID VALUE + LD HL,SD_UNIT ; POINT TO PREVIOUSLY SELECTED UNIT + CP (HL) ; SAME? + RET Z ; IF SO, NOTHING MORE TO DO +; + CP SD_UNITCNT ; CHECK VALIDITY (EXCEED UNIT COUNT?) + JP NC,SD_INVUNIT ; HANDLE INVALID UNIT ; ; NEW UNIT SELECTED, IMPLEMENT IT - LD (SD_UNIT),A ; SAVE CURRENT UNIT NUMBER + LD (SD_UNIT),A ; SAVE CURRENT UNIT NUMBER #IF (SDMODE == SDMODE_DSD) ; SELECT REQUESTED UNIT - OUT (SD_SELREG),A ; ACTUALLY SELECT THE CARD + OUT (SD_SELREG),A ; ACTUALLY SELECT THE CARD +#ENDIF + XOR A ; SIGNAL SUCCESS + RET ; DONE +; +; CHECK FOR CARD DETECT (NZ = MEDIA PRESENT) +; +SD_CHKCD: +#IF ((SDMODE == SDMODE_DSD) | (SDMODE == SDMODE_MK4)) + IN A,(SD_OPRREG) ; GET OPERATIONS REGISTER + BIT 5,A ; TEST CARD DETECT BIT +#ELSE + OR $FF ; ASSUME CARD PRESENT #ENDIF - XOR A ; SIGNAL SUCCESS - RET ; DONE + RET ; DONE ; ; CHECK FOR WRITE PROTECT (NZ = WRITE PROTECTED) ; SD_CHKWP: #IF ((SDMODE == SDMODE_DSD) | (SDMODE == SDMODE_MK4)) - IN A,(SD_OPRREG) ; GET OPERATIONS REGISTER - BIT 4,A ; TEST WP BIT + IN A,(SD_OPRREG) ; GET OPERATIONS REGISTER + BIT 4,A ; TEST WP BIT #ELSE - XOR A ; WP NOT SUPPORTED BY HARDWARE, ASSUME WP OFF + XOR A ; WP NOT SUPPORTED BY HARDWARE, ASSUME WP OFF #ENDIF - -#IF (SDTRACE >= 2) - CALL NZ,SD_PRTPREFIX -#ENDIF - - JP NZ,SD_WRTPROT ; HANDLE AS ERROR - - RET + RET ; AND RETURN ; ; SELECT CARD ; SD_SELECT: LD A,(SD_OPRVAL) #IF ((SDMODE == SDMODE_PPI) | (SDMODE == SDMODE_UART)) - AND ~SD_CS ; SET SD_CS (CHIP SELECT) + AND ~SD_CS ; SET SD_CS (CHIP SELECT) #ELSE - OR SD_CS ; SET SD_CS (CHIP SELECT) + OR SD_CS ; SET SD_CS (CHIP SELECT) #ENDIF LD (SD_OPRVAL),A OUT (SD_OPRREG),A @@ -1185,9 +1198,9 @@ SD_SELECT: SD_DESELECT: LD A,(SD_OPRVAL) #IF ((SDMODE == SDMODE_PPI) | (SDMODE == SDMODE_UART)) - OR SD_CS ; RESET SD_CS (CHIP SELECT) + OR SD_CS ; RESET SD_CS (CHIP SELECT) #ELSE - AND ~SD_CS ; RESET SD_CS (CHIP SELECT) + AND ~SD_CS ; RESET SD_CS (CHIP SELECT) #ENDIF LD (SD_OPRVAL),A OUT (SD_OPRREG),A @@ -1197,16 +1210,16 @@ SD_DESELECT: ; ; CSIO WAIT FOR TRANSMIT READY (TX REGSITER EMPTY) ; -SD_WAITTX: ; WAIT FOR TX EMPTY - IN0 A,(SD_CNTR) ; GET CSIO STATUS - BIT 4,A ; TX EMPTY? +SD_WAITTX: ; WAIT FOR TX EMPTY + IN0 A,(SD_CNTR) ; GET CSIO STATUS + BIT 4,A ; TX EMPTY? JR NZ,SD_WAITTX RET ; ; CSIO WAIT FOR RECEIVER READY (BYTE AVAILABLE) ; SD_WAITRX: - IN0 A,(SD_CNTR) ; WAIT FOR RECEIVER TO FINISH + IN0 A,(SD_CNTR) ; WAIT FOR RECEIVER TO FINISH BIT 5,A JR NZ,SD_WAITRX RET @@ -1214,22 +1227,22 @@ SD_WAITRX: ; MSB<-->LSB MIRROR BITS IN A, RESULT IN C ; MIRROR: - #IF (SDCSIOFAST) ; SLOW SPEED, LEAST CODE SPACE - LD BC,MIRTAB ; 256 BYTE MIRROR TABLE - ADD A,C ; ADD OFFSET + #IF (SDCSIOFAST) ; SLOW SPEED, LEAST CODE SPACE + LD BC,MIRTAB ; 256 BYTE MIRROR TABLE + ADD A,C ; ADD OFFSET LD C,A JR NC,MIRROR2 INC B MIRROR2: - LD A,(BC) ; GET RESULT - LD C,A ; RETURN RESULT IN C + LD A,(BC) ; GET RESULT + LD C,A ; RETURN RESULT IN C RET - #ELSE ; FASTEST BUT USES MOST CODE SPACE - LD B,8 ; BIT COUNTER + #ELSE ; FASTEST BUT USES MOST CODE SPACE + LD B,8 ; BIT COUNTER MIRROR1: - RLA ; ROTATE BIT 7 INTO CARRY - RR C ; ROTATE CARRY INTO RESULT - DJNZ MIRROR1 ; DO ALL 8 BITS + RLA ; ROTATE BIT 7 INTO CARRY + RR C ; ROTATE CARRY INTO RESULT + DJNZ MIRROR1 ; DO ALL 8 BITS RET #ENDIF #ENDIF @@ -1238,166 +1251,145 @@ MIRROR1: ; SD_PUT: #IF ((SDMODE == SDMODE_CSIO) | (SDMODE == SDMODE_MK4)) - CALL MIRROR ; MSB<-->LSB MIRROR BITS, RESULT IN C - CALL SD_WAITTX ; MAKE SURE WE ARE DONE SENDING - OUT0 (SD_TRDR),C ; PUT BYTE IN BUFFER + CALL MIRROR ; MSB<-->LSB MIRROR BITS, RESULT IN C + CALL SD_WAITTX ; MAKE SURE WE ARE DONE SENDING + OUT0 (SD_TRDR),C ; PUT BYTE IN BUFFER IN0 A,(SD_CNTR) - SET 4,A ; SET TRANSMIT ENABLE + SET 4,A ; SET TRANSMIT ENABLE OUT0 (SD_CNTR),A #ELSE #IF (SDMODE == SDMODE_UART) - XOR $FF ; DI IS INVERTED ON UART + XOR $FF ; DI IS INVERTED ON UART #ENDIF - LD C,A ; C=BYTE TO SEND - LD B,8 ; SEND 8 BITS (LOOP 8 TIMES) - LD A,(SD_OPRVAL) ; LOAD CURRENT OPR VALUE + LD C,A ; C=BYTE TO SEND + LD B,8 ; SEND 8 BITS (LOOP 8 TIMES) + LD A,(SD_OPRVAL) ; LOAD CURRENT OPR VALUE SD_PUT1: - RRA ; PREPARE TO GET DATA BIT FROM CF - RL C ; ROTATE NEXT BIT FROM C INTO CF - RLA ; ROTATE CF INTO A:0, SD_DO is OPR:0 - OUT (SD_OPRREG),A ; ASSERT DATA BIT - XOR SD_CLK ; TOGGLE CLOCK - OUT (SD_OPRREG),A ; UPDATE CLOCK AND ASSERT DATA BIT - XOR SD_CLK ; TOGGLE CLOCK - OUT (SD_OPRREG),A ; UPDATE CLOCK - DJNZ SD_PUT1 ; REPEAT FOR ALL 8 BITS - LD A,(SD_OPRVAL) ; LOAD CURRENT OPR VALUE - OUT (SD_OPRREG),A ; LEAVE WITH CLOCK LOW + RRA ; PREPARE TO GET DATA BIT FROM CF + RL C ; ROTATE NEXT BIT FROM C INTO CF + RLA ; ROTATE CF INTO A:0, SD_DO is OPR:0 + OUT (SD_OPRREG),A ; ASSERT DATA BIT + XOR SD_CLK ; TOGGLE CLOCK + OUT (SD_OPRREG),A ; UPDATE CLOCK AND ASSERT DATA BIT + XOR SD_CLK ; TOGGLE CLOCK + OUT (SD_OPRREG),A ; UPDATE CLOCK + DJNZ SD_PUT1 ; REPEAT FOR ALL 8 BITS + LD A,(SD_OPRVAL) ; LOAD CURRENT OPR VALUE + OUT (SD_OPRREG),A ; LEAVE WITH CLOCK LOW #ENDIF - RET ; DONE + RET ; DONE ; ; RECEIVE ONE BYTE ; SD_GET: #IF ((SDMODE == SDMODE_CSIO) | (SDMODE == SDMODE_MK4)) - CALL SD_WAITTX ; MAKE SURE WE ARE DONE SENDING - IN0 A,(Z180_CNTR) ; GET CSIO STATUS - SET 5,A ; START RECEIVER + CALL SD_WAITTX ; MAKE SURE WE ARE DONE SENDING + IN0 A,(Z180_CNTR) ; GET CSIO STATUS + SET 5,A ; START RECEIVER OUT0 (Z180_CNTR),A CALL SD_WAITRX - IN0 A,(Z180_TRDR) ; GET RECEIVED BYTE - CALL MIRROR ; MSB<-->LSB MIRROR BITS - LD A,C ; KEEP RESULT + IN0 A,(Z180_TRDR) ; GET RECEIVED BYTE + CALL MIRROR ; MSB<-->LSB MIRROR BITS + LD A,C ; KEEP RESULT #ELSE - LD B,8 ; RECEIVE 8 BITS (LOOP 8 TIMES) - LD A,(SD_OPRVAL) ; LOAD CURRENT OPR VALUE + LD B,8 ; RECEIVE 8 BITS (LOOP 8 TIMES) + LD A,(SD_OPRVAL) ; LOAD CURRENT OPR VALUE SD_GET1: - XOR SD_CLK ; TOGGLE CLOCK - OUT (SD_OPRREG),A ; UPDATE CLOCK - IN A,(SD_INPREG) ; READ THE DATA WHILE CLOCK IS ACTIVE + XOR SD_CLK ; TOGGLE CLOCK + OUT (SD_OPRREG),A ; UPDATE CLOCK + IN A,(SD_INPREG) ; READ THE DATA WHILE CLOCK IS ACTIVE #IF ((SDMODE == SDMODE_JUHA) | (SDMODE == SDMODE_PPI)) - RLA ; ROTATE INP:7 INTO CF + RLA ; ROTATE INP:7 INTO CF #ENDIF #IF (SDMODE == SDMODE_N8) - RLA ; ROTATE INP:6 INTO CF - RLA ; " + RLA ; ROTATE INP:6 INTO CF + RLA ; " #ENDIF #IF (SDMODE == SDMODE_UART) - RLA ; ROTATE INP:5 INTO CF - RLA ; " - RLA ; " + RLA ; ROTATE INP:5 INTO CF + RLA ; " + RLA ; " #ENDIF #IF (SDMODE == SDMODE_DSD) - RRA ; ROTATE INP:0 INTO CF + RRA ; ROTATE INP:0 INTO CF #ENDIF - RL C ; ROTATE CF INTO C:0 - LD A,(SD_OPRVAL) ; BACK TO INITIAL VALUES (TOGGLE CLOCK) - OUT (SD_OPRREG),A ; DO IT - DJNZ SD_GET1 ; REPEAT FOR ALL 8 BITS - LD A,C ; GET BYTE RECEIVED INTO A + RL C ; ROTATE CF INTO C:0 + LD A,(SD_OPRVAL) ; BACK TO INITIAL VALUES (TOGGLE CLOCK) + OUT (SD_OPRREG),A ; DO IT + DJNZ SD_GET1 ; REPEAT FOR ALL 8 BITS + LD A,C ; GET BYTE RECEIVED INTO A #IF (SDMODE == SDMODE_UART) - XOR $FF ; DO IS INVERTED ON UART + XOR $FF ; DO IS INVERTED ON UART #ENDIF #ENDIF RET ; -;================================================================================================== -; PRINTING AND DIAGNOSTIC OUTPUT -;================================================================================================== -; -; PRINT DIAGNONSTIC PREFIX +;============================================================================= +; ERROR HANDLING AND DIAGNOSTICS +;============================================================================= ; -SD_PRTPREFIX: - CALL NEWLINE - PRTS("SD$") - PUSH AF - LD A,(SD_UNIT) - ADD A,'0' - CALL COUT - POP AF - CALL PC_COLON - RET +; ERROR HANDLERS ; -; HANDLE READY TIMEOUT ERROR +SD_INVUNIT: + LD A,SD_STINVUNIT + JR SD_ERR2 ; SPECIAL CASE FOR INVALID UNIT ; SD_ERRRDYTO: LD A,SD_STRDYTO - JR SD_CARDERR + JR SD_ERR ; SD_ERRINITTO: LD A,SD_STINITTO - JR SD_CARDERR + JR SD_ERR ; SD_ERRCMDTO: LD A,SD_STCMDTO - JR SD_CARDERR + JR SD_ERR ; SD_ERRCMD: LD A,SD_STCMDERR - JR SD_CARDERR + JR SD_ERR ; SD_ERRDATA: LD A,SD_STDATAERR - JR SD_CARDERR + JR SD_ERR ; SD_ERRDATATO: LD A,SD_STDATATO - JR SD_CARDERR + JR SD_ERR ; SD_ERRCRC: LD A,SD_STCRCERR - JR SD_CARDERR + JR SD_ERR ; SD_NOMEDIA: LD A,SD_STNOMEDIA - JR SD_CARDERR + JR SD_ERR ; SD_WRTPROT: LD A,SD_STWRTPROT - JR SD_CARDERR -; -; GENERIC ERROR HANDLER -; -SD_CARDERR: - PUSH HL ; IS THIS NEEDED? - PUSH AF ; SAVE INCOMING STATUS - SD_DPTR(SD_STAT) ; GET STATUS ADR IN HL, AF TRASHED - POP AF ; RESTORE INCOMING STATUS - LD (HL),A ; UPDATE STATUS - POP HL ; IS THIS NEEDED? + JR SD_ERR2 ; DO NOT UPDATE UNIT STATUS! +; +SD_ERR: + PUSH HL ; IS THIS NEEDED? + PUSH AF ; SAVE INCOMING STATUS + SD_DPTR(SD_STAT) ; GET STATUS ADR IN HL, AF TRASHED + POP AF ; RESTORE INCOMING STATUS + LD (HL),A ; UPDATE STATUS + POP HL ; IS THIS NEEDED? +SD_ERR2: #IF (SDTRACE >= 2) - CALL PC_SPACE - PUSH AF ; IS THIS NEEDED? - PRTC('<') CALL SD_PRTSTAT - PRTC('>') - POP AF ; IS THIS NEEDED? + CALL SD_REGDUMP #ENDIF - OR A ; SET FLAGS + OR A ; SET FLAGS RET ; -; PRINT STATUS IF AN ERROR HAS OCCURRED +; ; SD_PRTERR: -#IF (SDTRACE >= 1) - ;RET Z ; IF NO ERROR, GET OUT - PUSH AF ; SAVE ACCUM/FLAGS - CALL SD_PRTPREFIX ; PRINT UNIT PREFIX - CALL PC_SPACE ; FORMATTING - CALL SD_PRTSTAT ; PRINT STATUS - POP AF ; RESTORE ACCUM/FLAGS -#ENDIF - RET ; DONE + RET Z ; DONE IF NO ERRORS + ; FALL THRU TO SD_PRTSTAT ; ; PRINT STATUS STRING ; @@ -1405,44 +1397,48 @@ SD_PRTSTAT: PUSH AF PUSH DE PUSH HL - SD_DPTR(SD_STAT) ; GET ADR OF STATUS IN HL, AF TRASHED - LD A,(HL) ; GET STATUS OR A - LD DE,SD_STRSTOK + LD DE,SD_STR_STOK JR Z,SD_PRTSTAT1 INC A - LD DE,SD_STRSTNOTRDY - JR Z,SD_PRTSTAT1 + LD DE,SD_STR_STINVUNIT + JR Z,SD_PRTSTAT2 ; INVALID UNIT IS SPECIAL CASE INC A - LD DE,SD_STRSTRDYTO + LD DE,SD_STR_STRDYTO JR Z,SD_PRTSTAT1 INC A - LD DE,SD_STRSTINITTO + LD DE,SD_STR_STINITTO JR Z,SD_PRTSTAT1 INC A - LD DE,SD_STRSTCMDTO + LD DE,SD_STR_STCMDTO JR Z,SD_PRTSTAT1 INC A - LD DE,SD_STRSTCMDERR + LD DE,SD_STR_STCMDERR JR Z,SD_PRTSTAT1 INC A - LD DE,SD_STRSTDATAERR + LD DE,SD_STR_STDATAERR JR Z,SD_PRTSTAT1 INC A - LD DE,SD_STRSTDATATO + LD DE,SD_STR_STDATATO JR Z,SD_PRTSTAT1 INC A - LD DE,SD_STRSTCRCERR + LD DE,SD_STR_STCRCERR JR Z,SD_PRTSTAT1 INC A - LD DE,SD_STRSTNOMEDIA + LD DE,SD_STR_STNOMEDIA JR Z,SD_PRTSTAT1 INC A - LD DE,SD_STRSTWRTPROT + LD DE,SD_STR_STWRTPROT JR Z,SD_PRTSTAT1 - LD DE,SD_STRSTUNK -; + LD DE,SD_STR_STUNK SD_PRTSTAT1: + CALL SD_PRTPREFIX ; PRINT UNIT PREFIX + JR SD_PRTSTAT3 +SD_PRTSTAT2: + CALL NEWLINE + PRTS("SD:$") ; NO UNIT NUM IN PREFIX FOR INVALID UNIT +SD_PRTSTAT3: + CALL PC_SPACE ; FORMATTING CALL WRITESTR POP HL POP DE @@ -1452,7 +1448,7 @@ SD_PRTSTAT1: SD_PRTRC: PUSH AF PUSH DE - LD DE,SD_STRRC + LD DE,SD_STR_RC CALL WRITESTR LD A,(SD_RC) CALL PRTHEXBYTE @@ -1463,7 +1459,7 @@ SD_PRTRC: SD_PRTTOK: PUSH AF PUSH DE - LD DE,SD_STRTOK + LD DE,SD_STR_TOK CALL WRITESTR LD A,(SD_TOK) CALL PRTHEXBYTE @@ -1471,6 +1467,41 @@ SD_PRTTOK: POP AF RET ; +; +; +SD_REGDUMP: + PUSH AF + PUSH BC + PUSH HL + CALL PC_SPACE + CALL PC_LBKT + LD HL,SD_CMDBUF + LD B,8 +SD_REGDUMP1: + LD A,(HL) + INC HL + CALL PRTHEXBYTE + DJNZ SD_REGDUMP1 + CALL PC_RBKT + POP HL + POP BC + POP AF + RET + +; +; PRINT DIAGNONSTIC PREFIX +; +SD_PRTPREFIX: + CALL NEWLINE + PRTS("SD$") + PUSH AF + LD A,(SD_UNIT) + ADD A,'0' + CALL COUT + POP AF + CALL PC_COLON + RET +; ; DISPLAY COMMAND, LOW ORDER WORD OF PARMS, AND RC ; #IF (DSKYENABLE) @@ -1494,60 +1525,61 @@ SD_DSKY: RET #ENDIF ; -;================================================================================================== +;============================================================================= ; STRING DATA -;================================================================================================== -; -SD_STRARROW .TEXT " ->$" -SD_STRRC .TEXT " RC=$" -SD_STRTOK .TEXT " TOK=$" -SD_STRCSD .TEXT " CSD =$" -SD_STRCID .TEXT " CID =$" -SD_STRSCR .TEXT " SCR =$" -SD_STRSDTYPE .TEXT " SD CARD TYPE ID=$" -; -SD_STRSTOK .TEXT "OK$" -SD_STRSTNOTRDY .TEXT "NOT READY$" -SD_STRSTRDYTO .TEXT "READY TIMEOUT$" -SD_STRSTINITTO .TEXT "INITIALIZATION TIMEOUT$" -SD_STRSTCMDTO .TEXT "COMMAND TIMEOUT$" -SD_STRSTCMDERR .TEXT "COMMAND ERROR$" -SD_STRSTDATAERR .TEXT "DATA ERROR$" -SD_STRSTDATATO .TEXT "DATA TIMEOUT$" -SD_STRSTCRCERR .TEXT "CRC ERROR$" -SD_STRSTNOMEDIA .TEXT "NO MEDIA$" -SD_STRSTWRTPROT .TEXT "WRITE PROTECTED$" -SD_STRSTUNK .TEXT "UNKNOWN$" -SD_STRTYPEUNK .TEXT "UNK$" -SD_STRTYPEMMC .TEXT "MMC$" -SD_STRTYPESDSC .TEXT "SDSC$" -SD_STRTYPESDHC .TEXT "SDHC$" -SD_STRTYPESDXC .TEXT "SDXC$" -; -;================================================================================================== -; SD DISK DRIVER - DATA -;================================================================================================== -; -SD_OPRVAL .DB 0 ; CURRENT OPR REG VALUE -SD_LCNT .DB 0 ; LOOP COUNTER -; -SD_BUF .FILL 16,0 ; WORK BUFFER -; -SD_CMDBUF: ; START OF STD CMD BUF -SD_CMD .DB 0 ; COMMAND BYTE -SD_CMDP0 .DB 0 ; FIRST PARM BYTE (MSB) +;============================================================================= +; +SD_STR_ARROW .TEXT " -->$" +SD_STR_RC .TEXT " RC=$" +SD_STR_TOK .TEXT " TOK=$" +SD_STR_CSD .TEXT " CSD =$" +SD_STR_CID .TEXT " CID =$" +SD_STR_SCR .TEXT " SCR =$" +SD_STR_SDTYPE .TEXT " SD CARD TYPE ID=$" +; +SD_STR_STOK .TEXT "OK$" +SD_STR_STINVUNIT .TEXT "INVALID UNIT$" +SD_STR_STRDYTO .TEXT "READY TIMEOUT$" +SD_STR_STINITTO .TEXT "INITIALIZATION TIMEOUT$" +SD_STR_STCMDTO .TEXT "COMMAND TIMEOUT$" +SD_STR_STCMDERR .TEXT "COMMAND ERROR$" +SD_STR_STDATAERR .TEXT "DATA ERROR$" +SD_STR_STDATATO .TEXT "DATA TIMEOUT$" +SD_STR_STCRCERR .TEXT "CRC ERROR$" +SD_STR_STNOMEDIA .TEXT "NO MEDIA$" +SD_STR_STWRTPROT .TEXT "WRITE PROTECTED$" +SD_STR_STUNK .TEXT "UNKNOWN$" +SD_STR_TYPEUNK .TEXT "UNK$" +SD_STR_TYPEMMC .TEXT "MMC$" +SD_STR_TYPESDSC .TEXT "SDSC$" +SD_STR_TYPESDHC .TEXT "SDHC$" +SD_STR_TYPESDXC .TEXT "SDXC$" +; +;============================================================================= +; DATA STORAGE +;============================================================================= +; +SD_OPRVAL .DB 0 ; CURRENT OPR REG VALUE +SD_LCNT .DB 0 ; LOOP COUNTER +; +SD_BUF .FILL 16,0 ; WORK BUFFER +; +SD_CMDBUF: ; START OF STD CMD BUF +SD_CMD .DB 0 ; COMMAND BYTE +SD_CMDP0 .DB 0 ; FIRST PARM BYTE (MSB) SD_CMDP1 .DB 0 SD_CMDP2 .DB 0 -SD_CMDP3 .DB 0 ; LAST PARM BYTE (LSB) -SD_CMDCRC .DB 0 ; CRC +SD_CMDP3 .DB 0 ; LAST PARM BYTE (LSB) +SD_CMDCRC .DB 0 ; CRC ; -SD_RC .DB 0 ; RETURN CODE FROM CMD -SD_TOK .DB 0 ; TOKEN FROM DATA XFR +SD_RC .DB 0 ; RETURN CODE FROM CMD +SD_TOK .DB 0 ; TOKEN FROM DATA XFR ; -; UNIT SPECIFIC DATA STORATE +SD_UNIT .DB 0 ; ACTIVE UNIT, DEFAULT TO ZERO ; -SD_UNIT .DB -1 ; ACTIVE UNIT, INIT TO -1 TO INDICATE NOTHING SELECTED -SD_UNITDATA .FILL SD_UNITCNT*8,0 ; PER UNIT DATA, 8 BYTES +; UNIT SPECIFIC DATA STORAGE +; +SD_UNITDATA .FILL SD_UNITCNT * 8, 0 ; PER UNIT DATA, 8 BYTES SD_DATALEN .EQU $ - SD_UNITDATA ; LENGTH OF ENTIRE DATA STORAGE FOR ALL UNITS SD_UNITDATALEN .EQU SD_DATALEN / SD_UNITCNT ; LENGTH OF PER UNIT DATA ; @@ -1574,9 +1606,9 @@ MIRTAB .DB 00H, 80H, 40H, 0C0H, 20H, 0A0H, 60H, 0E0H, 10H, 90H, 50H, 0D0H, 30H, ; #ENDIF ; -;================================================================================================== +;============================================================================= ; HELPER ROUTINES -;================================================================================================== +;============================================================================= ; ; IMPLEMENTATION FOR MACRO SD_DPTR ; SET HL TO ADDRESS OF FIELD WITHIN PER UNIT DATA