diff --git a/parts/z80/sdc.asm b/parts/z80/sdc.asm index c3e599d..e172b60 100644 --- a/parts/z80/sdc.asm +++ b/parts/z80/sdc.asm @@ -131,3 +131,85 @@ sdcCmdR7: out (SDC_PORT_CSHIGH), a ret + +; Initialize a SD card. This should be called at least 1ms after the powering +; up of the card. Sets result code in A. Zero means success, non-zero means +; error. +sdcInitialize: + push hl + push de + push bc + call sdcWakeUp + + ; Call CMD0 and expect a 0x01 response (card idle) + ; This should be called multiple times. We're actually expected to. + ; Let's call this for a maximum of 10 times. + ld b, 10 +.loop1: + ld a, 0b01000000 ; CMD0 + ld hl, 0 + ld de, 0 + ld c, 0x95 + call sdcCmdR1 + cp 0x01 + jp z, .cmd0ok + djnz .loop1 + ; Nothing? error + jr .error +.cmd0ok: + + ; Then comes the CMD8. We send it with a 0x01aa argument and expect + ; a 0x01aa argument back, along with a 0x01 R1 response. + ld a, 0b01001000 ; CMD8 + ld hl, 0 + ld de, 0x01aa + ld c, 0x87 + call sdcCmdR7 + cp 0x01 + jr nz, .error + xor a + cp h ; H is zero + jr nz, .error + cp l ; L is zero + jr nz, .error + ld a, d + cp 0x01 + jp nz, .error + ld a, e + cp 0xaa + jr nz, .error + + ; Now we need to repeatedly run CMD55+CMD41 (0x40000000) until we + ; the card goes out of idle mode, that is, when it stops sending us + ; 0x01 response and send us 0x00 instead. Any other response means that + ; initialization failed. +.loop2: + ld a, 0b01110111 ; CMD55 + ld hl, 0 + ld de, 0 + call sdcCmdR1 + cp 0x01 + jr nz, .error + ld a, 0b01101001 ; CMD41 (0x40000000) + ld hl, 0x4000 + ld de, 0x0000 + call sdcCmdR1 + cp 0x01 + jr z, .loop2 + or a ; cp 0 + jr nz, .error + ; Success! out of idle mode! + ; At this point, you are ready to read and write data. + jr .success + +.error: + ld a, 0x01 + jr .end + +.success: + xor a +.end: + pop bc + pop de + pop hl + ret diff --git a/recipes/rc2014/sdcard/glue.asm b/recipes/rc2014/sdcard/glue.asm index 27bb5d6..5519c0e 100644 --- a/recipes/rc2014/sdcard/glue.asm +++ b/recipes/rc2014/sdcard/glue.asm @@ -11,7 +11,7 @@ jr init ; Why not use this unused space between 0x02 and 0x28 for a jump table? jp printstr jp printHex - jp sdcWakeUp + jp sdcInitialize jp sdcSendRecv jp sdcWaitResp jp sdcCmd @@ -29,6 +29,8 @@ init: ld sp, hl im 1 call aciaInit + xor a + call blkSel call shellInit ; TODO - block device creation @@ -43,9 +45,15 @@ ACIA_RAMSTART .equ RAMSTART .define STDIO_PUTC call aciaPutC STDIO_RAMSTART .equ ACIA_RAMEND #include "stdio.asm" -SHELL_RAMSTART .equ STDIO_RAMEND -.define SHELL_IO_GETC call aciaGetC -.define SHELL_IO_PUTC call aciaPutC +BLOCKDEV_RAMSTART .equ STDIO_RAMEND +BLOCKDEV_COUNT .equ 1 +#include "blockdev.asm" +; List of devices +.dw aciaGetC, aciaPutC, 0, 0 + +SHELL_RAMSTART .equ BLOCKDEV_RAMEND +.define SHELL_IO_GETC call blkGetCW +.define SHELL_IO_PUTC call blkPutC SHELL_EXTRA_CMD_COUNT .equ 0 #include "shell.asm" diff --git a/recipes/rc2014/sdcard/jumptable.inc b/recipes/rc2014/sdcard/jumptable.inc index 372a663..3e99328 100644 --- a/recipes/rc2014/sdcard/jumptable.inc +++ b/recipes/rc2014/sdcard/jumptable.inc @@ -1,9 +1,9 @@ -JUMP_PRINTSTR .equ 0x03 -JUMP_PRINTHEX .equ 0x06 -JUMP_SDCWAKEUP .equ 0x09 -JUMP_SDCSENDRECV .equ 0x0c -JUMP_SDCWAITRESP .equ 0x0f -JUMP_SDCCMD .equ 0x12 -JUMP_SDCCMDR1 .equ 0x15 -JUMP_SDCCMDR7 .equ 0x18 +JUMP_PRINTSTR .equ 0x02 +JUMP_PRINTHEX .equ 0x05 +JUMP_SDCINITALIZE .equ 0x08 +JUMP_SDCSENDRECV .equ 0x0b +JUMP_SDCWAITRESP .equ 0x0e +JUMP_SDCCMD .equ 0x11 +JUMP_SDCCMDR1 .equ 0x14 +JUMP_SDCCMDR7 .equ 0x17 diff --git a/recipes/rc2014/sdcard/sdinit.asm b/recipes/rc2014/sdcard/sdinit.asm index f2d25f6..1442a92 100644 --- a/recipes/rc2014/sdcard/sdinit.asm +++ b/recipes/rc2014/sdcard/sdinit.asm @@ -1,62 +1,9 @@ #include "jumptable.inc" .org 0x9000 - call JUMP_SDCWAKEUP - - ; We expect a 0x01 R1 response - ld hl, sCmd - call JUMP_PRINTSTR - ld a, 0b01000000 ; CMD0 - ld hl, 0 - ld de, 0 - ld c, 0x95 - call JUMP_SDCCMDR1 - cp 0x01 + call JUMP_SDCINITALIZE + or a jp nz, .error - ld hl, sOk - call JUMP_PRINTSTR - - ; We expect a 0x01 R1 response followed by 0x0001aa R7 response - ld hl, sCmd - call JUMP_PRINTSTR - ld a, 0b01001000 ; CMD8 - ld hl, 0 - ld de, 0x01aa - ld c, 0x87 - call JUMP_SDCCMDR7 - ld a, d - cp 0x01 - jp nz, .error - ld a, e - cp 0xaa - jr nz, .error - ld hl, sOk - call JUMP_PRINTSTR - - ; Now we need to repeatedly run CMD55+CMD41 (0x40000000) until we - ; the card goes out of idle mode, that is, when it stops sending us - ; 0x01 response and send us 0x00 instead. Any other response means that - ; initialization failed. - ld hl, sCmd - call JUMP_PRINTSTR -.loop1: - ld a, 0b01110111 ; CMD55 - ld hl, 0 - ld de, 0 - call JUMP_SDCCMDR1 - cp 0x01 - jr nz, .error - ld a, 0b01101001 ; CMD41 (0x40000000) - ld hl, 0x4000 - ld de, 0x0000 - call JUMP_SDCCMDR1 - cp 0x01 - jr z, .loop1 - cp 0 - jr nz, .error - ; Success! out of idle mode! - ld hl, sOk - call JUMP_PRINTSTR ; Alright, normally we should configure block size and all, but this is ; too exciting and we'll play it dirty: we'll read just enough bytes @@ -78,17 +25,17 @@ call JUMP_PRINTSTR ; Command sent, no error, now let's wait for our data response. ld b, 20 -.loop3: +.loop1: call JUMP_SDCWAITRESP ; 0xfe is the expected data token for CMD17 cp 0xfe - jr z, .loop3end + jr z, .loop1end cp 0xff jr nz, .error - djnz .loop3 + djnz .loop1 jr .error -.loop3end: +.loop1end: ld hl, sGettingData call JUMP_PRINTSTR ; Data packets follow immediately