diff --git a/Source/HBIOS/Config/mk4_dsd.asm b/Source/HBIOS/Config/mk4_dsd.asm new file mode 100644 index 00000000..4b0f4f2b --- /dev/null +++ b/Source/HBIOS/Config/mk4_dsd.asm @@ -0,0 +1,113 @@ +; +;================================================================================================== +; ROMWBW 2.X CONFIGURATION FOR N8 2312 +;================================================================================================== +; +; BUILD CONFIGURATION OPTIONS +; +CPUOSC .EQU 18432000 ; CPU OSC FREQ +RAMSIZE .EQU 512 ; SIZE OF RAM IN KB, MUST MATCH YOUR HARDWARE!!! +CONBAUD .EQU 38400 ; DEFAULT BAUDRATE USED BELOW +; +SERDEV .EQU CIODEV_ASCI ; PRIMARY SERIAL DEVICE FOR BOOT/DEBUG/MONITOR (TYPICALLY CIODEV_UART OR CIODEV_ASCI) +CRTDEV .EQU CIODEV_VDA ; CRT DEVICE (CIODEV_PRPCON, CIODEV_PPPCON, CIODEV_VDA), USE CIODEV_NUL IF NO CRT +CRTACT .EQU FALSE ; CRT ACTIVATION AT STARTUP +VDADEV .EQU VDADEV_CVDU ; CRT VDA DEVICE (VDADEV_NONE, VDADEV_VDU, VDADEV_CVDU, VDADEV_N8V, VDADEV_UPD7220) +VDAEMU .EQU EMUTYP_ANSI ; DEFAULT VDA EMULATION (EMUTYP_TTY, EMUTYP_ANSI, ...) +; +DSKYENABLE .EQU FALSE ; TRUE FOR DSKY SUPPORT (DO NOT COMBINE WITH PPIDE) +; +SIMRTCENABLE .EQU FALSE ; SIMH CLOCK DRIVER +DSRTCENABLE .EQU TRUE ; DS-1302 CLOCK DRIVER +; +UARTENABLE .EQU FALSE ; TRUE FOR UART SUPPORT (N8 USES ASCI DRIVER) +UARTCNT .EQU 0 ; NUMBER OF UARTS +; +ASCIENABLE .EQU TRUE ; TRUE FOR Z180 ASCI SUPPORT +ASCI0BAUD .EQU CONBAUD ; ASCI0 BAUDRATE (IMPLEMENTED BY Z180_ASCIB0) +ASCI1BAUD .EQU CONBAUD ; ASCI1 BAUDRATE (IMPLEMENTED BY Z180_ASCIB1) +; +VDUENABLE .EQU FALSE ; TRUE FOR VDU BOARD SUPPORT +CVDUENABLE .EQU FALSE ; TRUE FOR CVDU BOARD SUPPORT +UPD7220ENABLE .EQU FALSE ; TRUE FOR uPD7220 BOARD SUPPORT +N8VENABLE .EQU FALSE ; TRUE FOR N8 (TMS9918) VIDEO/KBD SUPPORT +; +MDENABLE .EQU TRUE ; TRUE FOR ROM/RAM DISK SUPPORT (ALMOST ALWAYS WANT THIS ENABLED) +MDTRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF MDENABLE = TRUE) +; +FDENABLE .EQU FALSE ; TRUE FOR FLOPPY SUPPORT +FDMODE .EQU FDMODE_N8 ; FDMODE_DIO, FDMODE_ZETA, FDMODE_DIDE, FDMODE_N8, FDMODE_DIO3 +FDTRACE .EQU 1 ; 0=SILENT, 1=FATAL ERRORS, 2=ALL ERRORS, 3=EVERYTHING (ONLY RELEVANT IF FDENABLE = TRUE) +FDMEDIA .EQU FDM144 ; FDM720, FDM144, FDM360, FDM120 (ONLY RELEVANT IF FDENABLE = TRUE) +FDMEDIAALT .EQU FDM720 ; ALTERNATE MEDIA TO TRY, SAME CHOICES AS ABOVE (ONLY RELEVANT IF FDMAUTO = TRUE) +FDMAUTO .EQU TRUE ; SELECT BETWEEN MEDIA OPTS ABOVE AUTOMATICALLY +; +RFENABLE .EQU FALSE ; TRUE FOR RAM FLOPPY SUPPORT +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) +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) +KBDENABLE .EQU FALSE ; TRUE FOR PS/2 KEYBOARD ON I8242 +KBDTRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF KBDENABLE = TRUE) +; +TTYENABLE .EQU FALSE ; INCLUDE TTY EMULATION SUPPORT +ANSIENABLE .EQU FALSE ; INCLUDE ANSI EMULATION SUPPORT +ANSITRACE .EQU 1 ; 0=SILENT, 1=ERRORS, 2=EVERYTHING (ONLY RELEVANT IF ANSIENABLE = TRUE) +; +BOOTTYPE .EQU BT_MENU ; BT_MENU (WAIT FOR KEYPRESS), BT_AUTO (BOOT_DEFAULT AFTER BOOT_TIMEOUT SECS) +BOOT_TIMEOUT .EQU 20 ; APPROX TIMEOUT IN SECONDS FOR AUTOBOOT, 0 FOR IMMEDIATE +BOOT_DEFAULT .EQU 'Z' ; SELECTION TO INVOKE AT TIMEOUT +; +; 18.432MHz OSC @ FULL SPEED, 38.4Kbps +; +;Z180_CLKDIV .EQU 1 ; 0=OSC/2, 1=OSC, 2=OSC*2 +;Z180_MEMWAIT .EQU 1 ; MEMORY WAIT STATES TO INSERT (0-3) +;Z180_IOWAIT .EQU 1 ; IO WAIT STATES TO INSERT (0-3) +;Z180_ASCIB0 .EQU 20H ; SERIAL PORT 0 DIV, SEE Z180 CLOCKING DOCUMENT +;Z180_ASCIB1 .EQU 20H ; SERIAL PORT 1 DIV, SEE Z180 CLOCKING DOCUMENT +; +; 18.432MHz OSC @ DOUBLE SPEED, 38.4Kbps +; +Z180_CLKDIV .EQU 2 ; 0=OSC/2, 1=OSC, 2=OSC*2 +Z180_MEMWAIT .EQU 1 ; MEMORY WAIT STATES TO INSERT (0-3) +Z180_IOWAIT .EQU 1 ; IO WAIT STATES TO INSERT (0-3) +Z180_ASCIB0 .EQU 21H ; SERIAL PORT 0 DIV, SEE Z180 CLOCKING DOCUMENT +Z180_ASCIB1 .EQU 21H ; SERIAL PORT 1 DIV, SEE Z180 CLOCKING DOCUMENT diff --git a/Source/HBIOS/Config/mk4_std.asm b/Source/HBIOS/Config/mk4_std.asm index ba36768d..4cb4cf3c 100644 --- a/Source/HBIOS/Config/mk4_std.asm +++ b/Source/HBIOS/Config/mk4_std.asm @@ -98,16 +98,16 @@ BOOT_DEFAULT .EQU 'Z' ; SELECTION TO INVOKE AT TIMEOUT ; ; 18.432MHz OSC @ FULL SPEED, 38.4Kbps ; -Z180_CLKDIV .EQU 1 ; 0=OSC/2, 1=OSC, 2=OSC*2 -Z180_MEMWAIT .EQU 1 ; MEMORY WAIT STATES TO INSERT (0-3) -Z180_IOWAIT .EQU 1 ; IO WAIT STATES TO INSERT (0-3) -Z180_ASCIB0 .EQU 20H ; SERIAL PORT 0 DIV, SEE Z180 CLOCKING DOCUMENT -Z180_ASCIB1 .EQU 20H ; SERIAL PORT 1 DIV, SEE Z180 CLOCKING DOCUMENT +;Z180_CLKDIV .EQU 1 ; 0=OSC/2, 1=OSC, 2=OSC*2 +;Z180_MEMWAIT .EQU 1 ; MEMORY WAIT STATES TO INSERT (0-3) +;Z180_IOWAIT .EQU 1 ; IO WAIT STATES TO INSERT (0-3) +;Z180_ASCIB0 .EQU 20H ; SERIAL PORT 0 DIV, SEE Z180 CLOCKING DOCUMENT +;Z180_ASCIB1 .EQU 20H ; SERIAL PORT 1 DIV, SEE Z180 CLOCKING DOCUMENT ; ; 18.432MHz OSC @ DOUBLE SPEED, 38.4Kbps ; -;Z180_CLKDIV .EQU 2 ; 0=OSC/2, 1=OSC, 2=OSC*2 -;Z180_MEMWAIT .EQU 1 ; MEMORY WAIT STATES TO INSERT (0-3) -;Z180_IOWAIT .EQU 1 ; IO WAIT STATES TO INSERT (0-3) -;Z180_ASCIB0 .EQU 21H ; SERIAL PORT 0 DIV, SEE Z180 CLOCKING DOCUMENT -;Z180_ASCIB1 .EQU 21H ; SERIAL PORT 1 DIV, SEE Z180 CLOCKING DOCUMENT +Z180_CLKDIV .EQU 2 ; 0=OSC/2, 1=OSC, 2=OSC*2 +Z180_MEMWAIT .EQU 1 ; MEMORY WAIT STATES TO INSERT (0-3) +Z180_IOWAIT .EQU 1 ; IO WAIT STATES TO INSERT (0-3) +Z180_ASCIB0 .EQU 21H ; SERIAL PORT 0 DIV, SEE Z180 CLOCKING DOCUMENT +Z180_ASCIB1 .EQU 21H ; SERIAL PORT 1 DIV, SEE Z180 CLOCKING DOCUMENT diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index 91cf50db..31dabe89 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -511,6 +511,11 @@ HB_START: CALL PRTDEC PRTS("KB$") ; +; SET UP THE DEFAULT DISK BUFFER ADDRESS +; + LD HL,HB_BUF ; DEFAULT DISK XFR BUF ADDRESS + LD (DIOBUF),HL ; SAVE IT +; ; PERFORM DEVICE INITIALIZATION ; LD B,HB_INITTBLLEN @@ -530,11 +535,6 @@ INITSYS1: POP DE DJNZ INITSYS1 ; -; SET UP THE DEFAULT DISK BUFFER ADDRESS -; - LD HL,HB_BUF ; DEFAULT DISK XFR BUF ADDRESS - LD (DIOBUF),HL ; SAVE IT -; ; NOW SWITCH TO CRT CONSOLE IF CONFIGURED ; #IF CRTACT @@ -1748,6 +1748,8 @@ IDLECOUNT .DB 0 ; ; DISK DEVICE/UNIT ID HSTDSK .DB 0 ; DISK DEVICE/UNIT ID +; FULL 32 BIT LBA +HSTLBA .EQU $ ; REFERS TO START OF 32-BIT LBA ; LBA LOW WORD -OR- TRACK HSTLBALO .EQU $ ; BLOCK ADDRESS LBA LOW WORD HSTTRK .DW 0 ; BLOCK ADDRESS TRACK diff --git a/Source/HBIOS/hdsk.asm b/Source/HBIOS/hdsk.asm index 37be8015..82ed8ac2 100644 --- a/Source/HBIOS/hdsk.asm +++ b/Source/HBIOS/hdsk.asm @@ -68,13 +68,13 @@ HDSK_STATUS: RET ; ; GET DISK CAPACITY -; RETURN HL:DE=BLOCK COUNT, BC=BLOCK SIZE +; RETURN DE:HL=BLOCK COUNT, BC=BLOCK SIZE ; SLICE C/H/S = 65/16/16 OR 16,640 TOTAL SECTORS -; ASSUME 8 SLICES, SO 65 X 8 = 520 CYLS OR 16,640 * 8 = 133,120 TOTAL SECTORS +; ASSUME 8 SLICES, SO 16640 X 8 = 133,120 TOTAL SECTORS ; HDSK_CAP: - LD HL,133120 >> 16 ; BLOCK COUNT MSW - LD DE,133120 & $FFFF ; BLOCK COUNT LSW + LD DE,133120 >> 16 ; BLOCK COUNT MSW + LD HL,133120 & $FFFF ; BLOCK COUNT LSW LD BC,512 ; 512 BYTE SECTOR XOR A ; SIGNAL SUCCESS RET @@ -83,8 +83,8 @@ HDSK_CAP: ; RETURN HL:DE=CYLINDERS, B=HEADS, C=SECTORS ; HDSK_GEOM: - LD HL,0 ; CYLINDER COUNT MSW - LD DE,520 ; CYLINDER COUNT LSW + LD DE,0 ; CYLINDER COUNT MSW + LD HL,520 ; CYLINDER COUNT LSW LD B,16 ; HEADS / CYLINDER LD C,16 ; SECTORS / TRACK XOR A ; SIGNAL SUCCESS diff --git a/Source/HBIOS/ide.asm b/Source/HBIOS/ide.asm index 110d0418..f43eb982 100644 --- a/Source/HBIOS/ide.asm +++ b/Source/HBIOS/ide.asm @@ -62,82 +62,144 @@ IDE_RCBSYTO .EQU 4 ; ; UNIT CONFIGURATION ; -IDE_DEVLIST: +IDE_DEVICES: IDE_DEVICE0 .DB %11100000 ; LBA, MASTER DEVICE IDE_DEVICE1 .DB %11110000 ; LBA, SLAVE DEVICE ; ; ; IDE_INIT: - PRTS("IDE: IO=0x$") - LD A,IDEDATA - CALL PRTHEXBYTE - - CALL IDE_RESET ; INTERFACE RESET - CALL DELAY - - XOR A ; STATUS OK - LD (IDE_STAT),A ; INITIALIZE IT - - LD A,(IDE_DEVICE0) ; DEVICE 0 - DCALL PC_SPACE - DCALL PC_LBKT - CALL IDE_PROBE - DCALL PC_RBKT - JR NZ,IDE_INIT1 - LD HL,IDE_UNITCNT - INC (HL) - LD A,(IDE_DEVICE1) ; DEVICE 1 - DCALL PC_SPACE - DCALL PC_LBKT - CALL IDE_PROBE - DCALL PC_RBKT - JR NZ,IDE_INIT1 - LD HL,IDE_UNITCNT - INC (HL) + PRTS("IDE:$") ; LABEL FOR IO ADDRESS +; +#IF (IDEMODE == IDEMODE_DIO) + PRTS(" MODE=DIO$") +#ENDIF +#IF (IDEMODE == IDEMODE_DIDE) + PRTS(" MODE=DIDE$") +#ENDIF +#IF (IDEMODE == IDEMODE_MK4) + PRTS(" MODE=MK4$") +#ENDIF + ; PRINT IDE INTERFACE PORT ADDRESS + PRTS(" IO=0x$") ; LABEL FOR IO ADDRESS + LD A,IDEDATA ; GET IO ADDRESS + CALL PRTHEXBYTE ; PRINT IT +; + ; RESET INTERFACE + CALL IDE_RESET ; INTERFACE RESET + CALL DELAY ; SMALL DELAY +; + ; SET GLOBAL STATUS TO OK (ZERO) + XOR A ; STATUS OK + LD (IDE_STAT),A ; INITIALIZE IT +; + ; PROBE FOR DEVICE(S) + LD A,(IDE_DEVICE0) ; DEVICE 0 + 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 + 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: - LD A,(IDE_DEVICE0) ; DEVICE 0 - OUT (IDEDEVICE),A ; SELECT IT - CALL DELAY - - PRTS(" UNITS=$") - LD A,(IDE_UNITCNT) - CALL PRTDECB + ; RESTORE DEFAULT DEVICE SELECTION (DEVICE 0) + LD A,(IDE_DEVICE0) ; DEVICE 0 + OUT (IDEDEVICE),A ; SELECT IT + CALL DELAY ; SMALL DELAY AFTER SELECT ; + ; PRINT UNIT COUNT + PRTS(" UNITS=$") ; PRINT LABEL FOR 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 ; + ; DEVICE SETUP LOOP LD B,A ; LOOP ONCE PER UNIT - LD C,0 ; C IS INDEX TO DEVICE LIST + LD C,0 ; C IS UNIT INDEX IDE_INIT2: - PUSH BC - CALL IDE_INIT3 - POP BC - INC C - DJNZ IDE_INIT2 - RET -; -IDE_INIT3: - CALL NEWLINE - LD DE,IDESTR_PREFIX - CALL WRITESTR - LD A,C - CALL PRTDECB - CALL PC_COLON + PUSH BC ; SAVE LOOP CONTROL + CALL IDE_INIT3 ; HANDLE THE NEXT UNIT + POP BC ; RESTORE LOOP CONTROL + INC C ; INCREMENT UNIT INDEX + DJNZ IDE_INIT2 ; 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 - CALL IDE_SELECT + LD A,C ; UNIT NUMBER TO ACCUM + CALL IDE_SELECT ; SELECT THE CORRECT DEVICE +; #IF (IDE8BIT) PRTS(" 8BIT$") - CALL IDE_SET8BIT - RET NZ + CALL IDE_SET8BIT ; SET 8BIT TRANSFER FEATURE + RET NZ ; BAIL OUT ON ERROR #ENDIF - CALL IDE_IDENTIFY - RET NZ - LD DE,(DIOBUF) - DCALL DUMP_BUFFER +; + 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 + 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 + 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) + 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 + CALL PRTHEX32 ; PRINT HEX VALUE +; + ; PRINT STORAGE SIZE IN MB + PRTS(" SIZE=$") ; PRINT FIELD LABEL + LD B,11 ; 11 BIT SHIFT TO CONVERT BLOCKS --> MB + CALL SRL32 ; RIGHT SHIFT + CALL PRTDEC ; PRINT LOW WORD IN DECIMAL (HIGH WORD DISCARDED) + PRTS("MB$") ; PRINT SUFFIX +; RET ; ; @@ -267,7 +329,7 @@ IDE_RESET: ; SELECT DEVICE IN A ; IDE_SELECT: - LD HL,IDE_DEVLIST + LD HL,IDE_DEVICES CALL ADDHLA LD A,(HL) ; LOAD DEVICE LD (IDE_DEVICE),A ; SHADOW REGISTER @@ -622,12 +684,14 @@ 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 @@ -638,6 +702,8 @@ 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 +; ; ; ; diff --git a/Source/HBIOS/loader.asm b/Source/HBIOS/loader.asm index 802b7166..89b975c1 100644 --- a/Source/HBIOS/loader.asm +++ b/Source/HBIOS/loader.asm @@ -153,6 +153,9 @@ CB_DDL: ; START OF LIST ; #IF SDENABLE .DB DIODEV_SD + 0 ; SD0: (SD CARD DISK) +#IF (SDMODE == SDMODE_DSD) + .DB DIODEV_SD + 1 ; SD1: (SD CARD DISK) +#ENDIF #ENDIF ; #IF (PRPENABLE & PRPSDENABLE) diff --git a/Source/HBIOS/sd.asm b/Source/HBIOS/sd.asm index 9138637c..6cc1bcd2 100644 --- a/Source/HBIOS/sd.asm +++ b/Source/HBIOS/sd.asm @@ -1,15 +1,21 @@ ; ;============================================================================= -; SD/SDHC/SDXC CARD STORAGE DRIVER +; MMC/SD/SDHC/SDXC CARD STORAGE DRIVER ;============================================================================= ; +; 1) TESTING +; - TRY TO TEST GOIDLE, FIND CARD THAT REQUIRES 2 REQUESTS +; - DUAL CARDS +; - CARD XC CARD TYPE DETECTION +; - TRY TO GET INIT TO FAIL, REMOVE DELAYS AT START OF GOIDLE? +; ;------------------------------------------------------------------------------ -; SD Signal Active JUHA N8 CSIO PPI UART DSD MK4 -; ------------ ------- ------- ------- ------- ------- ------- ------- ------- -; CS (DAT3) LO -> RTC:2 RTC:2 RTC:2 ~PC:4 ~MCR:3 OPR:2 MK4_SD:2 -; CLK HI -> RTC:1 RTC:1 N/A PC:1 ~MCR:2 OPR:1 N/A -; DI (CMD) HI -> RTC:0 RTC:0 N/A PC:0 ~MCR:0 OPR:0 N/A -; DO (DAT0) HI -> RTC:7 RTC:6 N/A PB:7 ~MSR:5 OPR:0 N/A +; SD Signal Active JUHA N8 CSIO PPI UART DSD MK4 +; ------------ ------- ------- ------- ------- ------- ------- ------- ------- +; CS (DAT3) LO -> RTC:2 RTC:2 RTC:2 ~PC:4 ~MCR:3 OPR:2 MK4_SD:2 +; CLK HI -> RTC:1 RTC:1 N/A PC:1 ~MCR:2 OPR:1 N/A +; DI (CMD) HI -> RTC:0 RTC:0 N/A PC:0 ~MCR:0 OPR:0 N/A +; DO (DAT0) HI -> RTC:7 RTC:6 N/A PB:7 ~MSR:5 OPR:0 N/A ;------------------------------------------------------------------------------ ; ; CS = CHIP SELECT (AKA DAT3 FOR NON-SPI MODE) @@ -19,9 +25,9 @@ ; ; NOTES: ; 1) SIGNAL NAMES ARE FROM THE SD CARD SPEC AND ARE NAMED FROM THE -; PERSPECTIVE OF THE SD CARD: -; DI = DATA IN: HOST -> CARD = MOSI (MASTER OUT/SLAVE IN) -; DO = DATA OUT: HOST <- CARD = MISO (MASTER IN/SLAVE OUT) +; PERSPECTIVE OF THE SD CARD (SLAVE): +; DI = DATA IN: HOST -> CARD = MOSI (MASTER OUT/SLAVE IN) +; DO = DATA OUT: HOST <- CARD = MISO (MASTER IN/SLAVE OUT) ; ; 2) THE QUIESCENT STATE OF THE OUTPUT SIGNALS (HOST -> CARD) IS: ; CS = HI (NOT SELECTED) @@ -30,166 +36,173 @@ ; ; 3) SPI MODE 0 IMPLEMENTATION IS USED (CPOL=0, CPHA=0) ; THE DATA MUST BE AVAILABLE BEFORE THE FIRST CLOCK SIGNAL RISING. -; THE CLOCK IDLE STATE IS ZERO. THE DATA ON MISO AND MOSI LINES +; THE CLOCK IDLE STATE IS ZERO. THE DATA ON MISO AND MOSI LINES ; MUST BE STABLE WHILE THE CLOCK IS HIGH AND CAN BE CHANGED WHEN ; THE CLOCK IS LOW. THE DATA IS CAPTURED ON THE CLOCK'S LOW-TO-HIGH ; TRANSITION AND PROPAGATED ON HIGH-TO-LOW CLOCK TRANSITION. ; ; NOTE: THE CSIO IMPLEMENTATION (INCLUDE MK4) USES SPI MODE 4 ; (CPOL=1, CPHA=1) BECAUSE THAT IS THE WAY THAT THE Z180 CSIO -; INTERFACE WORKS. ALL OF THE CLOCK TRANSITIONS LISTED ABOVE +; INTERFACE WORKS. ALL OF THE CLOCK TRANSITIONS LISTED ABOVE ; ARE REVERSED FOR CSIO. ; ; 4) DI SHOULD BE LEFT HI (ACTIVE) WHENEVER UNUSED (FOR EXAMPLE, WHEN ; HOST IS RECEIVING DATA (HOST <- 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) +;------------------------------------------------------------------------------ +; +; 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) #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 ; ; SD CARD COMMANDS ; -SD_CMD0 .EQU $40 | 0 ; 0x40, GO_IDLE_STATE -SD_CMD1 .EQU $40 | 1 ; 0x41, SEND_OP_COND -SD_CMD8 .EQU $40 | 8 ; 0x48, SEND_IF_COND -SD_CMD9 .EQU $40 | 9 ; 0x49, SEND_CSD -SD_CMD10 .EQU $40 | 10 ; 0x4A, SEND_CID -SD_CMD16 .EQU $40 | 16 ; 0x50, SET_BLOCKLEN -SD_CMD17 .EQU $40 | 17 ; 0x51, READ_SINGLE_BLOCK -SD_CMD24 .EQU $40 | 24 ; 0x58, WRITE_BLOCK -SD_CMD55 .EQU $40 | 55 ; 0x77, APP_CMD -SD_CMD58 .EQU $40 | 58 ; 0x7A, READ_OCR -; SD APPLICATION SPECIFIC COMMANDS -SD_ACMD41 .EQU $40 | 41 ; 0x69, SD_APP_OP_COND +SD_CMD_GO_IDLE_STATE .EQU $40 + 0 ; $40, CMD0 -> R1 +SD_CMD_SEND_OP_COND .EQU $40 + 1 ; $41, CMD1 -> R1 +SD_CMD_SEND_IF_COND .EQU $40 + 8 ; $48, CMD8 -> R7 +SD_CMD_SEND_CSD .EQU $40 + 9 ; $49, CMD9 -> R1 +SD_CMD_SEND_CID .EQU $40 + 10 ; $4A, CMD10 -> R1 +SD_CMD_SET_BLOCKLEN .EQU $40 + 16 ; $50, CMD16 -> R1 +SD_CMD_READ_SNGL_BLK .EQU $40 + 17 ; $51, CMD17 -> R1 +SD_CMD_WRITE_BLOCK .EQU $40 + 24 ; $58, CMD24 -> R1 +SD_CMD_APP_CMD .EQU $40 + 55 ; $77, CMD55 -> R1 +SD_CMD_READ_OCR .EQU $40 + 58 ; $7A, CMD58 -> R3 +; +; SD CARD APPLICATION COMMANDS (PRECEDED BY APP_CMD COMMAND) +; +SD_ACMD_SEND_OP_COND .EQU $40 + 41 ; $69, ACMD41 -> R1 +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/SDXC CARD (V2) +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_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 ; +; PER UNIT DATA OFFSETS (CAREFUL NOT TO EXCEED PER UNIT SPACE IN SD_UNITDATA) +; SEE SD_UNITDATA IN DATA STORAGE BELOW ; -SD_DISPATCH: - LD A,B ; GET REQUESTED FUNCTION - AND $0F - JP Z,SD_READ - DEC A - JP Z,SD_WRITE - DEC A - JP Z,SD_STATUS - DEC A - JP Z,SD_MEDIA - CALL PANIC +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_MEDIA: - CALL SD_SELUNIT -; - ; INITIALIZE THE SD CARD TO ACCOMMODATE HOT SWAPPING - CALL SD_INITCARD - LD A,MID_HD ; ASSUME SUCCESS - RET Z ; RETURN IF GOOD INIT - CALL SD_PRT - LD A,MID_NONE ; IF FAILURE, RETURN NO MEDIA - RET +; SD DRIVER INITIALIZATION ENTRY POINT ; SD_INIT: PRTS("SD:$") - PRTS(" UNITS=$") - LD A,SD_UNITCNT - CALL PRTHEXBYTE +; #IF (SDMODE == SDMODE_JUHA) PRTS(" MODE=JUHA$") PRTS(" IO=0x$") @@ -222,7 +235,7 @@ SD_INIT: ; #IF (SDMODE == SDMODE_PPI) PRTS(" MODE=PPI$") - PRTS(" BASEIO=0x$") + PRTS(" IO=0x$") LD A,SD_PPIBASE CALL PRTHEXBYTE #ENDIF @@ -263,872 +276,1045 @@ SD_INIT: CALL PRTHEXBYTE #ENDIF ; - LD A,SD_STNOTRDY - LD HL,SD_STATLST - LD (SD_STATPTR),HL - LD (HL),A - INC HL - LD (HL),A - LD A,SD_TYPEUNK - LD HL,SD_TYPELST - LD (SD_TYPEPTR),HL - LD (HL),A - INC HL - LD (HL),A + PRTS(" UNITS=$") + LD A,SD_UNITCNT + CALL PRTDECB +; + ; INITIALIZE THE SD INTERFACE NOW + CALL SD_SETUP ; DO HARDWARE SETUP/INIT + RET NZ ; ABORT ON ERROR +; + ; CLEAR OUT ALL DATA (FOR ALL UNITS) + LD HL,SD_UNITDATA + LD BC,SD_DATALEN + XOR A + CALL FILL ; - LD B,SD_UNITCNT - LD C,0 + ; INITIALIZE INDIVIDUAL UNIT(S) + LD B,SD_UNITCNT ; INIT LOOP COUNTER TO UNIT COUNT + LD C,0 ; INIT UNIT INDEX TO ZERO SD_INIT1: - PUSH BC - CALL SD_SELUNIT - CALL SD_INITCARD - CALL SD_PRT - CALL Z,SD_PRTINFO - POP BC - INC C - DJNZ 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 ; - RET + RET ; DONE ; -SD_STATUS: - CALL SD_SELUNIT - LD HL,(SD_STATPTR) +; INITIALIZE UNIT DESIGNATED IN ACCUM +; +SD_INITUNIT: + ; SELECT UNIT + CALL SD_SELUNIT ; SELECT UNIT + JP NZ,SD_PRTERR ; EXIT VIA PRINT STATUS +; + ; CLEAR OUT UNIT SPECIFIC DATA + SD_DPTR(0) ; SET HL TO START OF UNIT DATA + LD BC,SD_UNITDATALEN + XOR A + CALL FILL +; + ; INIT CARD + CALL SD_INITCARD ; INIT THE SELECTED CARD + CALL SD_PRTPREFIX ; + JP NZ,SD_PRTSTAT ; EXIT VIA PRINT STATUS +; + ; PRINT CARD TYPE + PRTS(" TYPE=$") + SD_DPTR(SD_TYPE) ; SET HL TO ADR OF CARD TYPE, TRASHES AF LD A,(HL) - OR A - RET + LD DE,SD_STRTYPEMMC + CP SD_TYPEMMC + JR Z,SD_INITUNIT1 + LD DE,SD_STRTYPESDSC + CP SD_TYPESDSC + JR Z,SD_INITUNIT1 + LD DE,SD_STRTYPESDHC + CP SD_TYPESDHC + JR Z,SD_INITUNIT1 + LD DE,SD_STRTYPESDXC + CP SD_TYPESDXC + JR Z,SD_INITUNIT1 + LD DE,SD_STRTYPEUNK +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 HL,SD_BUF + CALL SD_GETDATA + CALL SD_DONE + JP NZ,SD_ERRDATA ; DATA XFER ERROR + +#IF (SDTRACE >= 2) + CALL SD_PRTPREFIX + LD DE,SD_STRCID + CALL WRITESTR + LD DE,SD_BUF + LD A,16 + CALL PRTHEXBUF +#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 +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 +; + 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 +; + 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 +; +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 +; +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 + JP Z,SD_READ + DEC A + JP Z,SD_WRITE + DEC A + JP Z,SD_STATUS + DEC A + JP Z,SD_MEDIA + DEC A + JR Z,SD_CAP + DEC A + JR Z,SD_GEOM + CALL PANIC ; SD_READ: - CALL SD_SELUNIT - CALL SD_RDSEC - JR SD_PRT + ; 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 ; SD_WRITE: - CALL SD_SELUNIT - CALL SD_CHKWP - CALL NZ,SD_WRTPROT - CALL Z,SD_WRSEC - JR SD_PRT + ; 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 ; -SD_PRT: -#IF (SDTRACE >= 1) - RET Z - PUSH AF - CALL SD_PRTPREFIX - CALL PC_SPACE - CALL SD_PRTSTAT - POP AF -#ENDIF +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_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 +; +SD_CAP: + SD_DPTR(SD_CAPACITY) ; POINT HL TO CAPACITY OF CUR UNIT + CALL LD32 ; GET THE CURRENT CAPACITY DO DE:HL + XOR A ; SIGNAL SUCCESS + RET ; AND DONE +; +SD_GEOM: + LD DE,0 ; CYLINDER COUNT MSW + LD HL,520 ; CYLINDER COUNT LSW + LD B,16 ; HEADS / CYLINDER + LD C,16 ; SECTORS / TRACK + XOR A ; SIGNAL SUCCESS RET ; ;============================================================================= -; SD HARDWARE INTERFACE ROUTINES +; SD I/O ROUTINES ;============================================================================= ; -; TAKE ANY ACTIONS REQUIRED TO SELECT DESIRED PHYSICAL UNIT +; (RE)INITIALIZE CARD ; -SD_SELUNIT: - LD A,C - AND 0FH ; ISOLATE THE UNIT NIBBLE - CP SD_UNITCNT ; CHECK VALIDITY (EXCEED UNIT COUNT?) - CALL NC,PANIC ; PANIC ON INVALID VALUE - LD (SD_UNIT),A ; SAVE CURRENT UNIT NUM -#IF (SDMODE == SDMODE_DSD) - ; SELECT REQUESTED UNIT - OUT (SD_SELREG),A ; ACTUALLY SELECT THE 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 - LD HL,SD_STATLST ; POINT TO START OF STATUS LIST - LD D,0 ; SETUP DE TO HAVE OFFSET - LD E,A ; FOR CURRENT UNIT - ADD HL,DE ; APPLY THE OFFSET - LD (SD_STATPTR),HL ; SAVE IT - LD HL,SD_TYPELST ; POINT TO START OF CARD TYPE LIST - ADD HL,DE ; APPLY THE OFFSET - LD (SD_TYPEPTR),HL ; SAVE IT - RET ; -; PERFORM HARDWARE SPECIFIC INITIALIZATION + ; 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 ; -SD_SETUP: + ; PUT CARD IN IDLE STATE + CALL SD_GOIDLE ; GO TO IDLE + RET NZ ; ABORT IF FAILED ; -#IF ((SDMODE == SDMODE_JUHA) | (SDMODE == SDMODE_N8) | (SDMODE == SDMODE_DSD)) - LD A,SD_OPRDEF - LD (SD_OPRVAL),A - OUT (SD_OPRREG),A -#ENDIF +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 ; -#IF ((SDMODE == SDMODE_CSIO) | (SDMODE == SDMODE_MK4)) - ; CSIO SETUP -; LD A,2 ; 18MHz/20 <= 400kHz - LD A,6 ; ??? - OUT0 (SD_CNTR),A - LD A,SD_OPRDEF - LD (SD_OPRVAL),A - OUT (SD_OPRREG),A -#ENDIF + ; 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 +; + ; GET CARD OUT OF IDLE STATE BY SENDING SD_APP_OP_COND + ; REPEATEDLY UNTIL IDLE BIT IS CLEAR + LD A,0 + LD (SD_LCNT),A +SD_INITCARD3: + ; DELAY A BIT PER SPEC + 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 + ; 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 + ; 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 + ; 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 +; +SD_INITCARD3A: + ; TRY MMC CARD INITIALIZATION + ; CALL SEND_OP_COND UNTIL CARD IS READY (NOT IDLE) + LD A,0 + LD (SD_LCNT),A +SD_INITCARD3B: + ; DELAY A BIT PER SPEC + 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 + ; 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 + ; 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 +; +SD_INITCARD3C: + ; SUCCESSFUL MMC CARD INITIALIZATION + 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 + ; 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 +; +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) + ; 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 ; -#IF (SDMODE == SDMODE_PPI) - LD A,82H ; PPI PORT A=OUT, B=IN, C=OUT - OUT (SD_PPIX),A - LD A,SD_OPRDEF - LD (SD_OPRVAL),A - OUT (SD_OPRREG),A +#IF (SDTRACE >= 2) + ; IF TRACING, DUMP THE SCR CONTENTS + CALL SD_PRTPREFIX + LD DE,SD_STRSCR + CALL WRITESTR + LD DE,SD_BUF + LD A,8 + CALL PRTHEXBUF #ENDIF ; -#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 + ; 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 +; +SD_INITCARD5: + SD_DPTR(SD_TYPE) ; SET HL TO ADR OF CARD TYPE, TRASHES AF + LD (HL),C ; SAVE IT + +#IF (SDTRACE >= 2) + CALL SD_PRTPREFIX + LD DE,SD_STRSDTYPE + CALL WRITESTR + LD A,C + CALL PRTHEXBYTE #ENDIF -; -#IF ((SDMODE == SDMODE_DSD) | (SDMODE == SDMODE_MK4)) - IN A,(SD_OPRREG) - BIT 5,A ; CARD DETECT - JP Z,SD_NOMEDIA ; NO MEDIA DETECTED + + ; 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 + +#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 #ENDIF ; - XOR A - RET -; -; SELECT CARD + ; 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 ; -SD_SELECT: - LD A,(SD_OPRVAL) -#IF ((SDMODE == SDMODE_PPI) | (SDMODE == SDMODE_UART)) - AND ~SD_CS ; SET SD_CS (CHIP SELECT) -#ELSE - OR SD_CS ; SET SD_CS (CHIP SELECT) +#IF (SDTRACE >= 2) + ; IF TRACING, DUMP THE CSD CONTENTS + CALL SD_PRTPREFIX + LD DE,SD_STRCSD + CALL WRITESTR + LD DE,SD_BUF + LD A,16 + CALL PRTHEXBUF #ENDIF - LD (SD_OPRVAL),A - OUT (SD_OPRREG),A - RET -; -; DESELECT CARD ; -SD_DESELECT: - LD A,(SD_OPRVAL) -#IF ((SDMODE == SDMODE_PPI) | (SDMODE == SDMODE_UART)) - OR SD_CS ; RESET SD_CS (CHIP SELECT) -#ELSE - AND ~SD_CS ; RESET SD_CS (CHIP SELECT) -#ENDIF - LD (SD_OPRVAL),A - OUT (SD_OPRREG),A - RET + ; 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 +; +; 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 +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 + ; 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 + ; 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 + ; 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 +; +; 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 + ; ADD 1 TO C_SIZE IN A:HL + 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 +; +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) +; + ; 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 +; +; SECTOR I/O +; SD CARD COMMAND BYTE MUST BE PASSED IN C +; +SD_SECTIO: + PUSH BC + CALL SD_CHKCARD ; CHECK / REINIT CARD AS NEEDED + POP BC + 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 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 +SD_SECTIO1: + ; GET SECTOR DATA + 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 +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 ; -; CHECK FOR WRITE PROTECT (NZ = WRITE PROTECTED) +; CHECK THE SD CARD, ATTEMPT TO REINITIALIZE IF NEEDED ; -SD_CHKWP: -#IF ((SDMODE == SDMODE_DSD) | (SDMODE == SDMODE_MK4)) - IN A,(SD_OPRREG) - BIT 4,A -#ELSE - XOR A -#ENDIF - RET +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 ; +; 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 +; + ; TRANSLATE BLOCK ADDRESS TO BYTE ADDRESS FOR V1 CARDS + LD D,E + LD E,H + LD H,L + LD L,0 + SLA L + RL H + RL E + RL D ; -#IF ((SDMODE == SDMODE_CSIO) | (SDMODE == SDMODE_MK4)) -SD_WAITTX: ; WAIT FOR TX EMPTY - IN0 A,(SD_CNTR) ; GET CSIO STATUS - BIT 4,A ; TX EMPTY? - JR NZ,SD_WAITTX - RET +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 +;================================================================================================== ; +; PUT CARD IN IDLE STATE ; -SD_WAITRX: - IN0 A,(SD_CNTR) ; WAIT FOR RECEIVER TO FINISH - BIT 5,A - JR NZ,SD_WAITRX +SD_GOIDLE: + 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 + + ; SMALL DELAY HERE HELPS SOME CARDS + LD DE,300 ; 16US * 300 = ~5MS + 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 +; +; 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) +SD_INITCMD1: + 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 ; -MIRROR: ; MSB<-->LSB MIRROR BITS IN A, RESULT IN C - #IF (!SDCSIOFAST) ; SLOW SPEED, LEAST 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 - RET - #ELSE ; FASTEST BUT USES MOST 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 - RET - #ENDIF +; EXECUTE COMMAND WITH NO DATA ; -MIRTAB: .DB 00H, 80H, 40H, 0C0H, 20H, 0A0H, 60H, 0E0H, 10H, 90H, 50H, 0D0H, 30H, 0B0H, 70H, 0F0H - .DB 08H, 88H, 48H, 0C8H, 28H, 0A8H, 68H, 0E8H, 18H, 98H, 58H, 0D8H, 38H, 0B8H, 78H, 0F8H - .DB 04H, 84H, 44H, 0C4H, 24H, 0A4H, 64H, 0E4H, 14H, 94H, 54H, 0D4H, 34H, 0B4H, 74H, 0F4H - .DB 0CH, 8CH, 4CH, 0CCH, 2CH, 0ACH, 6CH, 0ECH, 1CH, 9CH, 5CH, 0DCH, 3CH, 0BCH, 7CH, 0FCH - .DB 02H, 82H, 42H, 0C2H, 22H, 0A2H, 62H, 0E2H, 12H, 92H, 52H, 0D2H, 32H, 0B2H, 72H, 0F2H - .DB 0AH, 8AH, 4AH, 0CAH, 2AH, 0AAH, 6AH, 0EAH, 1AH, 9AH, 5AH, 0DAH, 3AH, 0BAH, 7AH, 0FAH - .DB 06H, 86H, 46H, 0C6H, 26H, 0A6H, 66H, 0E6H, 16H, 96H, 56H, 0D6H, 36H, 0B6H, 76H, 0F6H - .DB 0EH, 8EH, 4EH, 0CEH, 2EH, 0AEH, 6EH, 0EEH, 1EH, 9EH, 5EH, 0DEH, 3EH, 0BEH, 7EH, 0FEH - .DB 01H, 81H, 41H, 0C1H, 21H, 0A1H, 61H, 0E1H, 11H, 91H, 51H, 0D1H, 31H, 0B1H, 71H, 0F1H - .DB 09H, 89H, 49H, 0C9H, 29H, 0A9H, 69H, 0E9H, 19H, 99H, 59H, 0D9H, 39H, 0B9H, 79H, 0F9H - .DB 05H, 85H, 45H, 0C5H, 25H, 0A5H, 65H, 0E5H, 15H, 95H, 55H, 0D5H, 35H, 0B5H, 75H, 0F5H - .DB 0DH, 8DH, 4DH, 0CDH, 2DH, 0ADH, 6DH, 0EDH, 1DH, 9DH, 5DH, 0DDH, 3DH, 0BDH, 7DH, 0FDH - .DB 03H, 83H, 43H, 0C3H, 23H, 0A3H, 63H, 0E3H, 13H, 93H, 53H, 0D3H, 33H, 0B3H, 73H, 0F3H - .DB 0BH, 8BH, 4BH, 0CBH, 2BH, 0ABH, 6BH, 0EBH, 1BH, 9BH, 5BH, 0DBH, 3BH, 0BBH, 7BH, 0FBH - .DB 07H, 87H, 47H, 0C7H, 27H, 0A7H, 67H, 0E7H, 17H, 97H, 57H, 0D7H, 37H, 0B7H, 77H, 0F7H - .DB 0FH, 8FH, 4FH, 0CFH, 2FH, 0AFH, 6FH, 0EFH, 1FH, 9FH, 5FH, 0DFH, 3FH, 0BFH, 7FH, 0FFH -#ENDIF +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 ; -; SEND ONE BYTE +; EXECUTE A COMMAND +; WILL FINISH TRANSACTION IF ERROR OCCURS +; RETURNS STATUS IN A WITH ZF SET ACCORDINGLY ; -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 - IN0 A,(SD_CNTR) - SET 4,A ; SET TRANSMIT ENABLE - OUT0 (SD_CNTR),A -#ELSE -#IF (SDMODE == SDMODE_UART) - XOR $FF ; DI IS INVERTED ON UART +SD_EXECCMD: +#IF (SDTRACE >= 2) + PUSH AF + CALL SD_PRTPREFIX + LD DE,SD_CMDBUF + PRTS(" CMD =$") + LD A,6 + CALL PRTHEXBUF + LD DE,SD_STRARROW + CALL WRITESTR + POP AF #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 -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 + + ; 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 + ; SEND THE COMMAND + 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 +; + ; GET RESULT + 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 + 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 +#ENDIF +#IF (DSKYENABLE) + PUSH AF + CALL SD_DSKY ; IF USING DSKY, SHOW IT THERE + POP AF #ENDIF - RET ; DONE + 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 ; -; 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 - 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 -#ELSE - 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 - #IF ((SDMODE == SDMODE_JUHA) | (SDMODE == SDMODE_PPI)) - RLA ; ROTATE INP:7 INTO CF - #ENDIF - #IF (SDMODE == SDMODE_N8) - RLA ; ROTATE INP:6 INTO CF - RLA ; " - #ENDIF - #IF (SDMODE == SDMODE_UART) - RLA ; ROTATE INP:5 INTO CF - RLA ; " - RLA ; " - #ENDIF - #IF (SDMODE == SDMODE_DSD) - 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 -#IF (SDMODE == SDMODE_UART) - XOR $FF ; DO IS INVERTED ON UART -#ENDIF -#ENDIF - RET -; -;================================================================================================== -; SD DISK DRIVER PROTOCOL IMPLEMENTATION -;================================================================================================== -; -; SELECT CARD AND WAIT FOR IT TO BE READY ($FF) -; -SD_WAITRDY: - CALL SD_SELECT ; SELECT CARD - LD DE,0 ; LOOP MAX (TIMEOUT) -SD_WAITRDY1: - CALL SD_GET - 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 -; -; COMPLETE A TRANSACTION - PRESERVE AF -; -SD_DONE: - PUSH AF - CALL SD_DESELECT - LD A,$FF - CALL SD_PUT - POP AF - RET -; -; SD_GETDATA +; 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 - DEC DE + 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 - 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 + LD (SD_TOK),A ; SAVE TOKEN VALUE +#IF (SDTRACE >= 2) + 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 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 - - LD A,$FE ; PACKET START - CALL SD_PUT ; SEND IT + PUSH HL ; SAVE SOURCE ADDRESS + PUSH BC ; SAVE LENGTH TO SEND - POP DE ; RECOVER LENGTH TO SEND - POP HL ; RECOVER SOURCE ADDRESS + LD A,$FE ; PACKET START + CALL SD_PUT ; SEND IT + + 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: - AND $1F LD (SD_TOK),A +#IF (SDTRACE >= 2) + PUSH AF + CALL SD_PRTTOK + POP AF +#ENDIF + AND $1F CP $05 RET NZ XOR A RET ; -; SETUP COMMAND BUFFER +; SELECT CARD AND WAIT FOR IT TO BE READY ($FF) ; -SD_SETCMD0: ; NO PARMS - LD HL,SD_CMDBUF - LD (HL),A - INC HL - XOR A - LD (HL),A - INC HL - LD (HL),A - INC HL - LD (HL),A - INC HL - LD (HL),A - INC HL +SD_WAITRDY: + 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 + 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 +; +; FINISH A TRANSACTION - PRESERVE AF +; +SD_DONE: + PUSH AF LD A,$FF - LD (HL),A + CALL SD_PUT + CALL SD_DESELECT + POP AF RET ; -SD_SETCMDP: ; W/ PARMS IN BC & DE - CALL SD_SETCMD0 - LD HL,SD_CMDP0 - LD (HL),B - INC HL - LD (HL),C - INC HL - LD (HL),D - INC HL - LD (HL),E - RET +;============================================================================= +; SD HARDWARE INTERFACE ROUTINES +;============================================================================= ; -; EXECUTE A SD CARD COMMAND +; PERFORM HARDWARE SPECIFIC INITIALIZATION ; -SD_EXEC: - CALL SD_WAITRDY - JP NZ,SD_ERRRDYTO ; RETURN VIA READY TIMEOUT HANDLER - XOR A - LD (SD_RC),A - LD (SD_TOK),A - LD HL,SD_CMDBUF - LD E,6 ; COMMANDS ARE 6 BYTES -SD_EXEC1: - LD A,(HL) - CALL SD_PUT - INC HL - DEC E - JR NZ,SD_EXEC1 - LD DE,$100 ; LOOP MAX (TIMEOUT) - ;LD DE,$8000 ; *DEBUG* -SD_EXEC2: - CALL SD_GET - ;CALL PRTHEXBYTE ; *DEBUG* - OR A ; SET FLAGS - JP P,SD_EXEC3 ; IF HIGH BIT IS 0, WE HAVE RESULT - DEC DE - BIT 7,D - JR Z,SD_EXEC2 - ;LD (SD_RC),A ; *DEBUG* - ;CALL SD_PRTTRN ; *DEBUG* - JP SD_ERRCMDTO -SD_EXEC3: - LD (SD_RC),A -#IF (SDTRACE >= 2) - CALL SD_PRTTRN +SD_SETUP: +; +#IF ((SDMODE == SDMODE_JUHA) | (SDMODE == SDMODE_N8) | (SDMODE == SDMODE_DSD)) + LD A,SD_OPRDEF + LD (SD_OPRVAL),A + OUT (SD_OPRREG),A #ENDIF -#IF (DSKYENABLE) - CALL SD_DSKY +; +#IF ((SDMODE == SDMODE_CSIO) | (SDMODE == SDMODE_MK4)) + ; CSIO SETUP +; LD A,2 ; 18MHz/20 <= 400kHz + LD A,6 ; ??? + OUT0 (SD_CNTR),A + LD A,SD_OPRDEF + LD (SD_OPRVAL),A + OUT (SD_OPRREG),A #ENDIF - OR A +; +#IF (SDMODE == SDMODE_PPI) + LD A,82H ; PPI PORT A=OUT, B=IN, C=OUT + OUT (SD_PPIX),A + LD A,SD_OPRDEF + LD (SD_OPRVAL),A + OUT (SD_OPRREG),A +#ENDIF +; +#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 +#ENDIF +; + XOR A RET -; -SD_EXECCMD0: ; EXEC COMMAND, NO PARMS - CALL SD_SETCMD0 - JR SD_EXEC ; -SD_EXECCMDP: ; EXEC CMD W/ PARMS IN BC/DE - CALL SD_SETCMDP - JR SD_EXEC +; TAKE ANY ACTIONS REQUIRED TO SELECT DESIRED PHYSICAL UNIT +; UNIT IS SPECIFIED IN A ; -; PUT CARD IN IDLE STATE +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 +; + ; NEW UNIT SELECTED, IMPLEMENT IT + LD (SD_UNIT),A ; SAVE CURRENT UNIT NUMBER +#IF (SDMODE == SDMODE_DSD) + ; SELECT REQUESTED UNIT + OUT (SD_SELREG),A ; ACTUALLY SELECT THE CARD +#ENDIF + XOR A ; SIGNAL SUCCESS + RET ; DONE ; -SD_GOIDLE: - ;CALL SD_DONE ; SEEMS TO HELP SOME CARDS... - - ; SMALL DELAY HERE HELPS SOME CARDS - LD DE,300 ; 16US * 300 = ~5MS - CALL VDELAY ; CPU SPEED NORMALIZED DELAY - - ; PUT CARD IN IDLE STATE - LD A,SD_CMD0 ; CMD0 = ENTER IDLE STATE - CALL SD_SETCMD0 - LD A,$95 - LD (SD_CMDBUF+5),A ; SET CRC=$95 - CALL SD_EXEC ; EXEC CMD - CALL SD_DONE ; SIGNAL COMMAND COMPLETE - JP P,SD_GOIDLE1 ; VALID RESULT, CHECK IT - CALL SD_EXEC ; 2ND TRY - CALL SD_DONE ; SIGNAL COMMAND COMPLETE - RET M ; COMMAND FAILED -; -SD_GOIDLE1: ; COMMAND OK, CHECK FOR EXPECTED RESULT - DEC A ; MAP EXPECTED $01 -> $00 - RET Z ; IF $00, ALL GOOD, RETURN - JP SD_ERRCMD ; OTHERWISE, HANDLE COMMAND ERROR -; -; INIT CARD +; CHECK FOR WRITE PROTECT (NZ = WRITE PROTECTED) ; -SD_INITCARD: - CALL SD_SETUP ; DO HARDWARE SETUP/INIT - RET NZ -; - ; 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_INITCARD000: - LD A,$FF - PUSH BC - CALL SD_PUT - POP BC - DJNZ SD_INITCARD000 - - ;CALL SD_SELECT - - ; PUT CARD IN IDLE STATE - CALL SD_GOIDLE - RET NZ ; FAILED - -SD_INITCARD00: - LD A,SD_TYPESDSC ; ASSUME SDSC CARD TYPE - LD HL,(SD_TYPEPTR) ; LOAD THE CARD TYPE ADDRESS - LD (HL),A ; SAVE IT - - ; CMD8 IS REQUIRED FOR V2 CARDS. FAILURE HERE IS OK AND - ; JUST MEANS THAT IT IS A V1.X CARD - LD A,SD_CMD8 - LD BC,0 - LD D,1 ; VHS=1, 2.7-3.6V - LD E,$AA ; CHECK PATTERN - CALL SD_SETCMDP - LD A,$87 - LD (SD_CMDBUF+5),A ; SET CRC=$87 - CALL SD_EXEC ; EXEC CMD - CALL M,SD_DONE ; CLOSE COMMAND IF ERROR - RET M ; ABORT DUE TO PROCESSING ERROR - AND ~$01 ; IGNORE BIT 0 (IDLE) - JR NZ,SD_INITCARD0 ; CMD RESULT ERR, SKIP AHEAD - - ; CMD8 WORKED, NEED TO CONSUME CMD8 RESPONSE BYTES (4) - CALL SD_GET - CALL SD_GET - CALL SD_GET - CALL SD_GET - -SD_INITCARD0: - CALL SD_DONE +SD_CHKWP: +#IF ((SDMODE == SDMODE_DSD) | (SDMODE == SDMODE_MK4)) + IN A,(SD_OPRREG) ; GET OPERATIONS REGISTER + BIT 4,A ; TEST WP BIT +#ELSE + XOR A ; WP NOT SUPPORTED BY HARDWARE, ASSUME WP OFF +#ENDIF - LD A,0 - LD (SD_LCNT),A -SD_INITCARD1: - ; CALL SD_APP_OP_COND UNTIL CARD IS READY (NOT IDLE) - LD DE,300 ; 16US * 300 = ~5MS - CALL VDELAY ; CPU SPEED NORMALIZED DELAY - LD A,SD_CMD55 ; APP CMD IS NEXT - CALL SD_EXECCMD0 - CALL SD_DONE - RET M ; ABORT ON PROCESSING ERROR - AND ~$01 ; ONLY 0 (OK) OR 1 (IDLE) ARE OK - JP NZ,SD_ERRCMD - LD A,SD_ACMD41 ; SD_APP_OP_COND - LD BC,$4000 ; INDICATE WE SUPPORT HC - LD DE,$0000 - CALL SD_EXECCMDP - CALL SD_DONE - RET M ; ABORT ON PROCESSING ERROR - CP $00 ; INIT DONE? - JR Z,SD_INITCARD2 ; YUP, MOVE ON - CP $01 ; IDLE? - JP NZ,SD_ERRCMD ; NOPE, MUST BE CMD ERROR, ABORT - LD HL,SD_LCNT ; POINT TO LOOP COUNTER - DEC (HL) ; DECREMENT LOOP COUNTER - JR NZ,SD_INITCARD1 ; LOOP UNTIL COUNTER EXHAUSTED - LD A,$FF ; SIGNAL TIMEOUT - OR A - JP SD_ERRINITTO - -SD_INITCARD2: - ; CMD58 RETURNS THE 32 BIT OCR REGISTER, WE WANT TO CHECK - ; BIT 30, IF SET THIS IS SDHC/XC CARD - LD A,SD_CMD58 - CALL SD_EXECCMD0 - CALL NZ,SD_DONE - RET M ; ABORT ON PROCESSING ERROR - JP NZ,SD_ERRCMD - - ; CMD58 WORKED, GET OCR DATA AND SET CARD TYPE - CALL SD_GET ; BITS 31-24 - AND $40 ; ISOLATE BIT 30 (CCS) - JR Z,SD_INITCARD21 ; NOT HC/XC, BYPASS - LD HL,(SD_TYPEPTR) ; LOAD THE CARD TYPE ADDRESS - LD A,SD_TYPESDHC ; CARD TYPE = SDHC - LD (HL),A ; SAVE IT -SD_INITCARD21: - CALL SD_GET ; BITS 23-16, DISCARD - CALL SD_GET ; BITS 15-8, DISCARD - CALL SD_GET ; BITS 7-0, DISCARD - CALL SD_DONE - - ; SET OUR DESIRED BLOCK LENGTH (512 BYTES) - LD A,SD_CMD16 ; SET_BLOCK_LEN - LD BC,0 - LD DE,512 - CALL SD_EXECCMDP - CALL SD_DONE - RET M ; ABORT ON PROCESSING ERROR - JP NZ,SD_ERRCMD - #IF (SDTRACE >= 2) - CALL NEWLINE - LD DE,SDSTR_SDTYPE - CALL WRITESTR - LD HL,(SD_TYPEPTR) - LD A,(HL) - CALL PRTHEXBYTE + CALL NZ,SD_PRTPREFIX #ENDIF -#IF ((SDMODE == SDMODE_CSIO) | (SDMODE == SDMODE_MK4)) - CALL SD_WAITTX ; MAKE SURE WE ARE DONE SENDING - XOR A ; NOW SET CSIO PORT TO FULL SPEED - OUT (Z180_CNTR),A -#ENDIF + JP NZ,SD_WRTPROT ; HANDLE AS ERROR - XOR A ; A = 0 (STATUS = OK) - LD HL,(SD_STATPTR) ; LOAD STATUS ADDRESS - LD (HL),A ; SAVE IT - RET ; RETURN WITH A=0, AND Z SET - + RET ; -; GET AND PRINT CSD, CID +; SELECT CARD ; -SD_PRTINFO: - CALL SD_PRTPREFIX - - ; PRINT CARD TYPE - PRTS(" TYPE=$") - LD HL,(SD_TYPEPTR) - LD A,(HL) - LD DE,SDSTR_TYPEMMC - CP SD_TYPEMMC - JR Z,SD_PRTINFO1 - LD DE,SDSTR_TYPESDSC - CP SD_TYPESDSC - JR Z,SD_PRTINFO1 - LD DE,SDSTR_TYPESDHC - CP SD_TYPESDHC - JR Z,SD_PRTINFO1 - LD DE,SDSTR_TYPEUNK -SD_PRTINFO1: - CALL WRITESTR - - LD A,SD_CMD10 ; SEND_CID - CALL SD_EXECCMD0 - CALL NZ,SD_DONE - JP NZ,SD_ERRCMD ; ABORT IF PROBLEM - LD BC,16 ; 16 BYTES OF CID - LD HL,SD_BUF - CALL SD_GETDATA - CALL SD_DONE - -#IF (SDTRACE >= 2) - CALL SD_PRTPREFIX - LD DE,SDSTR_CID - CALL WRITESTR - LD DE,SD_BUF - LD A,16 - CALL PRTHEXBUF +SD_SELECT: + LD A,(SD_OPRVAL) +#IF ((SDMODE == SDMODE_PPI) | (SDMODE == SDMODE_UART)) + AND ~SD_CS ; SET SD_CS (CHIP SELECT) +#ELSE + OR SD_CS ; SET SD_CS (CHIP SELECT) #ENDIF - - ; PRINT PRODUCT NAME - PRTS(" NAME=$") - LD B,5 - LD HL,SD_BUF + 3 -SD_PRTINFO2: - LD A,(HL) - CALL COUT - INC HL - DJNZ SD_PRTINFO2 - - LD A,SD_CMD9 ; SEND_CSD - CALL SD_EXECCMD0 - CALL NZ,SD_DONE - JP NZ,SD_ERRCMD ; ABORT IF PROBLEM - LD BC,16 ; 16 BYTES OF CSD - LD HL,SD_BUF - CALL SD_GETDATA - CALL SD_DONE - -#IF (SDTRACE >= 2) - CALL SD_PRTPREFIX - LD DE,SDSTR_CSD - CALL WRITESTR - LD DE,SD_BUF - LD A,16 - CALL PRTHEXBUF + LD (SD_OPRVAL),A + OUT (SD_OPRREG),A + RET +; +; DESELECT CARD +; +SD_DESELECT: + LD A,(SD_OPRVAL) +#IF ((SDMODE == SDMODE_PPI) | (SDMODE == SDMODE_UART)) + OR SD_CS ; RESET SD_CS (CHIP SELECT) +#ELSE + AND ~SD_CS ; RESET SD_CS (CHIP SELECT) #ENDIF - - ; PRINT SIZE - PRTS(" SIZE=$") ; PREFIX - PUSH IX ; SAVE IX - LD IX,SD_BUF ; POINT IX TO BUFFER -; - LD HL,(SD_TYPEPTR) ; POINT TO CARD TYPE - LD A,(HL) ; GET CARD TYPE - CP SD_TYPESDSC ; CSD V1? - JR Z,SD_PRTINFO3 ; HANDLE V1 - CP SD_TYPESDHC ; CSD V2? - JR Z,SD_PRTINFO4 ; HANDLE V2 - JR SD_PRTINFO6 ; UNK, CAN'T HANDLE - -SD_PRTINFO3: ; PRINT SIZE FOR V1 CARD - 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_PRTINFO3A: - SRA C ; SHIFT MSB - RR D ; SHIFT NEXT BYTE - RR E ; SHIFT LSB - DJNZ SD_PRTINFO3A ; LOOP TILL DONE - PUSH DE ; DE = C_SIZE - 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 - LD A,18 ; ASSUME RIGHT SHIFT OF 18 - SUB B ; REDUCE BY READ_BL_LEN BITS - SUB C ; REDUCE BY C_SIZE_MULT BITS - LD B,A ; PUT IN LOOP COUNTER - POP HL ; RECOVER C_SIZE - JR Z,SD_PRTINFO5 ; HANDLE ZERO BIT SHIFT CASE -SD_PRTINFO3B: - SRA H ; SHIFT MSB - RR L ; SHIFT LSB - DJNZ SD_PRTINFO3B ; LOOP TILL DONE - JR SD_PRTINFO5 ; GO TO PRINT ROUTINE -; -SD_PRTINFO4: ; PRINT SIZE FOR V2 CARD - 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 - SRA A ; RIGHT SHIFT MSB BY ONE - RR H ; RIGHT SHIFT NEXT BYTE BY ONE - RR L ; RIGHT SHIFT LSB BY ONE - JR SD_PRTINFO5 -; -SD_PRTINFO5: ; COMMON CODE TO PRINT RESULTANT SIZE (IN HL) - CALL PRTDEC ; PRINT SIZE IN DECIMAL - JR SD_PRTINFO7 ; FINISH UP -; -SD_PRTINFO6: ; UNKNOWN CARD TYPE - PRTC('?') ; UNKNOWN SIZE -; -SD_PRTINFO7: - PRTS("MB$") ; PRINT SIZE SUFFIX - POP IX ; RESTORE IX -; - CALL SD_CHKWP ; WRITE PROTECTED? - JR Z,SD_PRTINFO8 ; NOPE, BYPASS - CALL PC_SPACE ; SEPARATOR - PRTX(SDSTR_STWRTPROT) ; TELL THE USER -; -SD_PRTINFO8: - RET ; DONE + LD (SD_OPRVAL),A + OUT (SD_OPRREG),A + RET ; -; CHECK THE SD CARD, ATTEMPT TO REINITIALIZE IF NEEDED +#IF ((SDMODE == SDMODE_CSIO) | (SDMODE == SDMODE_MK4)) ; -SD_CHKCARD: - LD HL,(SD_STATPTR) ; LOAD STATUS ADDRESS - LD A,(HL) ; GET STATUS - OR A ; SET FLAGS - CALL NZ,SD_INITCARD ; INIT CARD IF NOT READY - RET ; RETURN WITH STATUS IN A - -SD_RDSEC: - CALL SD_CHKCARD ; CHECK / REINIT CARD AS NEEDED - RET NZ - - CALL SD_SETADDR ; SETUP BLOCK ADDRESS - - LD A,SD_CMD17 ; READ_SINGLE_BLOCK - CALL SD_EXECCMDP ; EXEC CMD WITH BLOCK ADDRESS AS PARM - CALL NZ,SD_DONE ; TRANSACTION DONE IF ERROR OCCURRED - RET M ; ABORT ON PROCESSING ERROR - JP NZ,SD_ERRCMD ; FAIL IF NON-ZERO RC - - LD HL,(DIOBUF) - LD BC,512 ; LENGTH TO READ - CALL SD_GETDATA ; GET THE BLOCK - CALL SD_DONE - JP NZ,SD_ERRDATA ; DATA XFER ERROR +; 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? + JR NZ,SD_WAITTX RET ; -; WRITE ONE SECTOR +; CSIO WAIT FOR RECEIVER READY (BYTE AVAILABLE) ; -SD_WRSEC: - CALL SD_CHKCARD ; CHECK / REINIT CARD AS NEEDED - RET NZ - - CALL SD_SETADDR ; SETUP BLOCK ADDRESS - - LD A,SD_CMD24 ; WRITE_BLOCK - CALL SD_EXECCMDP ; EXEC CMD WITH BLOCK ADDRESS AS PARM - CALL NZ,SD_DONE ; TRANSACTION DONE IF ERROR OCCURRED - RET M ; ABORT ON PROCESSING ERROR - JP NZ,SD_ERRCMD ; FAIL IF NON-ZERO RC - - LD HL,(DIOBUF) ; SETUP DATA SOURCE ADDRESS - LD BC,512 ; LENGTH TO WRITE - CALL SD_PUTDATA ; PUT THE BLOCK - CALL SD_DONE - JP NZ,SD_ERRDATA ; DATA XFER ERROR +SD_WAITRX: + IN0 A,(SD_CNTR) ; WAIT FOR RECEIVER TO FINISH + BIT 5,A + JR NZ,SD_WAITRX RET ; -; +; MSB<-->LSB MIRROR BITS IN A, RESULT IN C ; -SD_SETADDR: - LD HL,(SD_TYPEPTR) - LD A,(HL) - CP SD_TYPESDSC - JR Z,SD_SETADDRSDSC - CP SD_TYPESDHC - JR Z,SD_SETADDRSDHC - CALL PANIC - +MIRROR: + #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 + RET + #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 + RET + #ENDIF +#ENDIF ; -; SDSC CARDS USE A BYTE OFFSET +; SEND ONE BYTE ; -; TT:SS = BC:DE -> TS:S0, THEN LEFT SHIFT ONE BIT -SD_SETADDRSDSC: - LD BC,(HSTLBAHI) - LD DE,(HSTLBALO) - LD B,C - LD C,D - LD D,E - LD E,0 - SLA E - RL D - RL C - RL B +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 + IN0 A,(SD_CNTR) + SET 4,A ; SET TRANSMIT ENABLE + OUT0 (SD_CNTR),A +#ELSE +#IF (SDMODE == SDMODE_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 +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 +#ENDIF + 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 + 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 +#ELSE + 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 + #IF ((SDMODE == SDMODE_JUHA) | (SDMODE == SDMODE_PPI)) + RLA ; ROTATE INP:7 INTO CF + #ENDIF + #IF (SDMODE == SDMODE_N8) + RLA ; ROTATE INP:6 INTO CF + RLA ; " + #ENDIF + #IF (SDMODE == SDMODE_UART) + RLA ; ROTATE INP:5 INTO CF + RLA ; " + RLA ; " + #ENDIF + #IF (SDMODE == SDMODE_DSD) + 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 +#IF (SDMODE == SDMODE_UART) + XOR $FF ; DO IS INVERTED ON UART +#ENDIF +#ENDIF RET ; -; SDHC CARDS USE SIMPLE LBA, NO TRANSLATION NEEDED +;================================================================================================== +; PRINTING AND DIAGNOSTIC OUTPUT +;================================================================================================== ; -SD_SETADDRSDHC: - LD BC,(HSTLBAHI) ; LBA HIGH WORD - LD DE,(HSTLBALO) ; LBA LOW WORD - RET ; DONE +; 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 ; ; HANDLE READY TIMEOUT ERROR ; @@ -1171,143 +1357,114 @@ SD_WRTPROT: ; GENERIC ERROR HANDLER ; SD_CARDERR: - PUSH HL ; IS THIS NEEDED? - LD HL,(SD_STATPTR) - LD (HL),A - POP HL ; IS THIS NEEDED? + 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? #IF (SDTRACE >= 2) - CALL NEWLINE - PUSH AF ; IS THIS NEEDED? + CALL PC_SPACE + PUSH AF ; IS THIS NEEDED? PRTC('<') CALL SD_PRTSTAT PRTC('>') - POP AF ; IS THIS NEEDED? + POP AF ; IS THIS NEEDED? #ENDIF - OR A + OR A ; SET FLAGS RET ; -; PRINT DIAGNONSTIC PREFIX +; PRINT STATUS IF AN ERROR HAS OCCURRED ; -SD_PRTPREFIX: - CALL NEWLINE - LD DE,SDSTR_PREFIX - CALL WRITESTR - PUSH AF - LD A,(SD_UNIT) - ADD A,'0' - CALL COUT - POP AF - CALL PC_COLON - RET +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 ; ; PRINT STATUS STRING ; SD_PRTSTAT: - PUSH HL ; IS THIS NEEDED? - LD HL,(SD_STATPTR) - LD A,(HL) - POP HL ; IS THIS NEEDED? + 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,SDSTR_STOK + LD DE,SD_STRSTOK JR Z,SD_PRTSTAT1 INC A - LD DE,SDSTR_STNOTRDY + LD DE,SD_STRSTNOTRDY JR Z,SD_PRTSTAT1 INC A - LD DE,SDSTR_STRDYTO + LD DE,SD_STRSTRDYTO JR Z,SD_PRTSTAT1 INC A - LD DE,SDSTR_STINITTO + LD DE,SD_STRSTINITTO JR Z,SD_PRTSTAT1 INC A - LD DE,SDSTR_STCMDTO + LD DE,SD_STRSTCMDTO JR Z,SD_PRTSTAT1 INC A - LD DE,SDSTR_STCMDERR + LD DE,SD_STRSTCMDERR JR Z,SD_PRTSTAT1 INC A - LD DE,SDSTR_STDATAERR + LD DE,SD_STRSTDATAERR JR Z,SD_PRTSTAT1 INC A - LD DE,SDSTR_STDATATO + LD DE,SD_STRSTDATATO JR Z,SD_PRTSTAT1 INC A - LD DE,SDSTR_STCRCERR + LD DE,SD_STRSTCRCERR JR Z,SD_PRTSTAT1 INC A - LD DE,SDSTR_STNOMEDIA + LD DE,SD_STRSTNOMEDIA JR Z,SD_PRTSTAT1 INC A - LD DE,SDSTR_STWRTPROT + LD DE,SD_STRSTWRTPROT JR Z,SD_PRTSTAT1 - LD DE,SDSTR_STUNK + LD DE,SD_STRSTUNK ; SD_PRTSTAT1: CALL WRITESTR - PUSH HL ; IS THIS NEEDED? - LD HL,(SD_STATPTR) - LD A,(HL) - POP HL ; IS THIS NEEDED? - CP SD_STCMDERR - JR Z,SD_PRTCMDERR - CP SD_STDATAERR - JR Z,SD_PRTDATAERR + POP HL + POP DE + POP AF RET ; -SD_PRTCMDERR: - LD A,(SD_RC) - JR SD_PRTCODE -; -SD_PRTDATAERR: - LD A,(SD_TOK) - JR SD_PRTCODE -; -SD_PRTCODE: - CALL PC_LPAREN +SD_PRTRC: PUSH AF - LD A,(SD_CMD) - CALL PRTHEXBYTE - LD DE,SDSTR_ARROW + PUSH DE + LD DE,SD_STRRC CALL WRITESTR - POP AF + LD A,(SD_RC) CALL PRTHEXBYTE - CALL PC_RPAREN + POP DE + POP AF RET ; -; PRT COMMAND TRACE -; -SD_PRTTRN: +SD_PRTTOK: PUSH AF - - CALL SD_PRTPREFIX - - LD DE,SD_CMDBUF - LD A,6 - CALL PRTHEXBUF - LD DE,SDSTR_ARROW - CALL WRITESTR - - LD DE,SDSTR_RC - CALL WRITESTR - LD A,(SD_RC) - CALL PRTHEXBYTE - CALL PC_SPACE - - LD DE,SDSTR_TOK + PUSH DE + LD DE,SD_STRTOK CALL WRITESTR LD A,(SD_TOK) CALL PRTHEXBYTE - + POP DE POP AF - RET - ; ; DISPLAY COMMAND, LOW ORDER WORD OF PARMS, AND RC ; #IF (DSKYENABLE) SD_DSKY: PUSH AF + PUSH HL LD HL,DSKY_HEXBUF LD A,(SD_CMD) LD (HL),A @@ -1320,57 +1477,109 @@ SD_DSKY: INC HL LD A,(SD_RC) CALL DSKY_HEXOUT + POP HL POP AF RET #ENDIF ; +;================================================================================================== +; STRING DATA +;================================================================================================== ; -; -SDSTR_PREFIX .TEXT "SD$" -SDSTR_ARROW .TEXT " -> $" -SDSTR_RC .TEXT "RC=$" -SDSTR_TOK .TEXT "TOK=$" -SDSTR_CSD .TEXT " CSD=$" -SDSTR_CID .TEXT " CID=$" -SDSTR_STOK .TEXT "OK$" -SDSTR_SDTYPE .TEXT "SD CARD TYPE: $" -; -SDSTR_STNOTRDY .TEXT "NOT READY$" -SDSTR_STRDYTO .TEXT "READY TIMEOUT$" -SDSTR_STINITTO .TEXT "INITIALIZATION TIMEOUT$" -SDSTR_STCMDTO .TEXT "COMMAND TIMEOUT$" -SDSTR_STCMDERR .TEXT "COMMAND ERROR$" -SDSTR_STDATAERR .TEXT "DATA ERROR$" -SDSTR_STDATATO .TEXT "DATA TIMEOUT$" -SDSTR_STCRCERR .TEXT "CRC ERROR$" -SDSTR_STNOMEDIA .TEXT "NO MEDIA$" -SDSTR_STWRTPROT .TEXT "WRITE PROTECTED$" -SDSTR_STUNK .TEXT "UNKNOWN$" -SDSTR_TYPEUNK .TEXT "UNK$" -SDSTR_TYPEMMC .TEXT "MMC$" -SDSTR_TYPESDSC .TEXT "SDSC$" -SDSTR_TYPESDHC .TEXT "SDHC/XC$" +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 DISK DRIVER - DATA ;================================================================================================== ; -SD_STATLST .FILL SD_UNITCNT,0 ; LIST OF UNIT STATUSES (2 UNITS) -SD_STATPTR .DW SD_STATLST ; ADDRESS OF STATUS FOR CURRENT UNIT -SD_TYPELST .FILL SD_UNITCNT,0 ; LIST OF CARD TYPES (2 UNITS) -SD_TYPEPTR .Dw SD_TYPELST ; ADDRESS OF CARD TYPE FOR CURRENT UNIT -SD_UNIT .DB 0 ; CURRENT UNIT NUMBER -SD_RC .DB 0 ; RETURN CODE FROM CMD -SD_TOK .DB 0 ; TOKEN FROM DATA XFR -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 -SD_CMDP0 .DB 0 +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 -SD_CMDCRC .DB 0 +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 +; +; UNIT SPECIFIC DATA STORATE +; +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 +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 +; +; LOOKUP TABLE TO MIRROR BITS IN A BYTE +; +#IF (((SDMODE == SDMODE_CSIO) | (SDMODE == SDMODE_MK4)) & SDCSIOFAST) + +MIRTAB .DB 00H, 80H, 40H, 0C0H, 20H, 0A0H, 60H, 0E0H, 10H, 90H, 50H, 0D0H, 30H, 0B0H, 70H, 0F0H + .DB 08H, 88H, 48H, 0C8H, 28H, 0A8H, 68H, 0E8H, 18H, 98H, 58H, 0D8H, 38H, 0B8H, 78H, 0F8H + .DB 04H, 84H, 44H, 0C4H, 24H, 0A4H, 64H, 0E4H, 14H, 94H, 54H, 0D4H, 34H, 0B4H, 74H, 0F4H + .DB 0CH, 8CH, 4CH, 0CCH, 2CH, 0ACH, 6CH, 0ECH, 1CH, 9CH, 5CH, 0DCH, 3CH, 0BCH, 7CH, 0FCH + .DB 02H, 82H, 42H, 0C2H, 22H, 0A2H, 62H, 0E2H, 12H, 92H, 52H, 0D2H, 32H, 0B2H, 72H, 0F2H + .DB 0AH, 8AH, 4AH, 0CAH, 2AH, 0AAH, 6AH, 0EAH, 1AH, 9AH, 5AH, 0DAH, 3AH, 0BAH, 7AH, 0FAH + .DB 06H, 86H, 46H, 0C6H, 26H, 0A6H, 66H, 0E6H, 16H, 96H, 56H, 0D6H, 36H, 0B6H, 76H, 0F6H + .DB 0EH, 8EH, 4EH, 0CEH, 2EH, 0AEH, 6EH, 0EEH, 1EH, 9EH, 5EH, 0DEH, 3EH, 0BEH, 7EH, 0FEH + .DB 01H, 81H, 41H, 0C1H, 21H, 0A1H, 61H, 0E1H, 11H, 91H, 51H, 0D1H, 31H, 0B1H, 71H, 0F1H + .DB 09H, 89H, 49H, 0C9H, 29H, 0A9H, 69H, 0E9H, 19H, 99H, 59H, 0D9H, 39H, 0B9H, 79H, 0F9H + .DB 05H, 85H, 45H, 0C5H, 25H, 0A5H, 65H, 0E5H, 15H, 95H, 55H, 0D5H, 35H, 0B5H, 75H, 0F5H + .DB 0DH, 8DH, 4DH, 0CDH, 2DH, 0ADH, 6DH, 0EDH, 1DH, 9DH, 5DH, 0DDH, 3DH, 0BDH, 7DH, 0FDH + .DB 03H, 83H, 43H, 0C3H, 23H, 0A3H, 63H, 0E3H, 13H, 93H, 53H, 0D3H, 33H, 0B3H, 73H, 0F3H + .DB 0BH, 8BH, 4BH, 0CBH, 2BH, 0ABH, 6BH, 0EBH, 1BH, 9BH, 5BH, 0DBH, 3BH, 0BBH, 7BH, 0FBH + .DB 07H, 87H, 47H, 0C7H, 27H, 0A7H, 67H, 0E7H, 17H, 97H, 57H, 0D7H, 37H, 0B7H, 77H, 0F7H + .DB 0FH, 8FH, 4FH, 0CFH, 2FH, 0AFH, 6FH, 0EFH, 1FH, 9FH, 5FH, 0DFH, 3FH, 0BFH, 7FH, 0FFH +; +#ENDIF +; +;================================================================================================== +; HELPER ROUTINES +;================================================================================================== +; +; IMPLEMENTATION FOR MACRO SD_DPTR +; SET HL TO ADDRESS OF FIELD WITHIN PER UNIT DATA +; HL := ADR OF SD_UNITDATA[(SD_UNIT)][(SP)] +; ENTER WITH TOP-OF-STACK = ADDRESS OF FIELD OFFSET +; AF IS TRASHED +; +SD_DPTRIMP: + LD HL,SD_UNITDATA ; POINT TO START OF UNIT DATA ARRAY + LD A,(SD_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/util.asm b/Source/HBIOS/util.asm index b39a4a58..14c53cea 100644 --- a/Source/HBIOS/util.asm +++ b/Source/HBIOS/util.asm @@ -180,6 +180,19 @@ PRTHEXWORD: POP AF RET ; +; PRINT THE HEX DWORD VALUE IN DE:HL +; +PRTHEX32: + PUSH BC + PUSH DE + POP BC + CALL PRTHEXWORD + PUSH HL + POP BC + CALL PRTHEXWORD + POP BC + RET +; ; CONVERT BINARY VALUE IN A TO ASCII HEX CHARACTERS IN DE ; HEXASCII: @@ -861,6 +874,60 @@ PRTDEC2: PRTDEC3: RET ; +; SHIFT HL:DE BY B BITS +; +SRL32: + ; ROTATE RIGHT 32 BITS, HIGH ORDER BITS BECOME ZERO + SRL D + RR E + RR H + RR L + DJNZ SRL32 + RET +; +SLA32: + ; ROTATE LEFT 32 BITS, LOW ORDER BITS BECOME ZERO + SLA L + RL H + RL E + RL D + DJNZ SLA32 + RET +; +; LOAD OR STORE DE:HL +; +LD32: + ; LD DE:HL,(HL) + PUSH AF + LD E,(HL) + INC HL + LD D,(HL) + INC HL + LD A,(HL) + INC HL + LD H,(HL) + LD L,A + POP AF + EX DE,HL + RET +; +ST32: + ; LD (BC),DE:HL + PUSH AF + LD A,L + LD (BC),A + INC BC + LD A,H + LD (BC),A + INC BC + LD A,E + LD (BC),A + INC BC + LD A,D + LD (BC),A + POP AF + RET +; ;================================================================================================== ; DSKY KEYBOARD ROUTINES ;================================================================================================== diff --git a/Source/RomDsk/mk4_dsd/RTC.COM b/Source/RomDsk/mk4_dsd/RTC.COM new file mode 100644 index 00000000..64788f53 Binary files /dev/null and b/Source/RomDsk/mk4_dsd/RTC.COM differ diff --git a/Source/RomDsk/mk4_dsd/XM-A0.COM b/Source/RomDsk/mk4_dsd/XM-A0.COM new file mode 100644 index 00000000..6afb31f3 Binary files /dev/null and b/Source/RomDsk/mk4_dsd/XM-A0.COM differ diff --git a/Source/RomDsk/mk4_dsd/XM-A1.COM b/Source/RomDsk/mk4_dsd/XM-A1.COM new file mode 100644 index 00000000..42a67c31 Binary files /dev/null and b/Source/RomDsk/mk4_dsd/XM-A1.COM differ diff --git a/Source/RomDsk/mk4_dsd/XM5-A0.COM b/Source/RomDsk/mk4_dsd/XM5-A0.COM new file mode 100644 index 00000000..e233bee9 Binary files /dev/null and b/Source/RomDsk/mk4_dsd/XM5-A0.COM differ diff --git a/Source/RomDsk/mk4_dsd/XM5-A1.COM b/Source/RomDsk/mk4_dsd/XM5-A1.COM new file mode 100644 index 00000000..625e06ac Binary files /dev/null and b/Source/RomDsk/mk4_dsd/XM5-A1.COM differ