From 54d02864865a0d341782f1d813d57ff3276b8a1c Mon Sep 17 00:00:00 2001
From: Virgil Dupras <hsoft@hardcoded.net>
Date: Wed, 8 May 2019 20:08:17 -0400
Subject: [PATCH] parts/z80/sdc: add sdcSetBlkSize and sdcReadBlk

---
 parts/z80/sdc.asm                   | 84 ++++++++++++++++++++++++++++++++++++-
 recipes/rc2014/sdcard/glue.asm      |  3 ++
 recipes/rc2014/sdcard/jumptable.inc |  2 +
 recipes/rc2014/sdcard/sdinit.asm    | 66 +++++++++--------------------
 4 files changed, 107 insertions(+), 48 deletions(-)

diff --git a/parts/z80/sdc.asm b/parts/z80/sdc.asm
index e172b60..69f9609 100644
--- a/parts/z80/sdc.asm
+++ b/parts/z80/sdc.asm
@@ -20,6 +20,18 @@
 ; SDC_PORT_CSLOW: Port number to make CS low
 ; SDC_PORT_SPI: Port number to send/receive SPI data
 
+; *** Consts ***
+.equ	SDC_BLKSIZE	512
+
+; *** Variables ***
+; Index of the sector currently contained in SDC_BUF
+.equ	SDC_SECTOR	SDC_RAMSTART
+; Whenever we read a sector, we read a whole block at once and we store it
+; in memory. That's where it goes.
+.equ	SDC_BUF		SDC_SECTOR+1
+.equ	SDC_RAMEND	SDC_BUF+SDC_BLKSIZE
+
+; *** Code ***
 ; Wake the SD card up. After power up, a SD card has to receive at least 74
 ; dummy clocks with CS and DI high. We send 80.
 sdcWakeUp:
@@ -199,7 +211,6 @@ sdcInitialize:
 	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:
@@ -213,3 +224,74 @@ sdcInitialize:
 	pop	de
 	pop	hl
 	ret
+
+; Send a command to set block size to SDC_BLKSIZE to the SD card.
+; Returns zero in A if a success, non-zero otherwise
+sdcSetBlkSize:
+	push	hl
+	push	de
+
+	ld	a, 0b01010000	; CMD16
+	ld	hl, 0
+	ld	de, SDC_BLKSIZE
+	call	sdcCmdR1
+	; Since we're out of idle mode, we expect a 0 response
+	; We need no further processing: A is already the correct value.
+	pop	de
+	pop	hl
+	ret
+
+; Read block index specified in A and place the contents in (SDC_BUF).
+; Doesn't check CRC.
+; Returns 0 in A if success, non-zero if error.
+; Returns SDC_BUF in HL
+sdcReadBlk:
+	push	bc
+
+	out	(SDC_PORT_CSLOW), a
+	ld	hl, 0		; read single block at addr A
+	ld	d, 0
+	ld	e, a
+	ld	a, 0b01010001	; CMD17
+	call	sdcCmd
+	or	a		; cp 0
+	jr	nz, .error
+
+	; Command sent, no error, now let's wait for our data response.
+	ld	b, 20
+.loop1:
+	call	sdcWaitResp
+	; 0xfe is the expected data token for CMD17
+	cp	0xfe
+	jr	z, .loop1end
+	cp	0xff
+	jr	nz, .error
+	djnz	.loop1
+	jr	.error		; timeout. error out
+.loop1end:
+	; We received our data token!
+	; Data packets follow immediately, we have 512 of them to read
+	ld	bc, SDC_BLKSIZE
+	ld	hl, SDC_BUF
+.loop2:
+	call	sdcWaitResp
+	ld	(hl), a
+	cpi			; a trick to inc HL and dec BC at the same time.
+				; P/V indicates whether BC reached 0
+	jp	pe, .loop2	; BC is not zero, loop
+	; Read our 2 CRC bytes
+	call	sdcWaitResp
+	call	sdcWaitResp
+	; success!
+	xor	a
+	jr	.end
+.error:
+	; try to preserve error code
+	or	a		; cp 0
+	jr	nz, .end	; already non-zero
+	inc	a		; zero, adjust
+.end:
+	out	(SDC_PORT_CSHIGH), a
+	ld	hl, SDC_BUF
+	pop	bc
+	ret
diff --git a/recipes/rc2014/sdcard/glue.asm b/recipes/rc2014/sdcard/glue.asm
index 5519c0e..3bd4f3c 100644
--- a/recipes/rc2014/sdcard/glue.asm
+++ b/recipes/rc2014/sdcard/glue.asm
@@ -17,6 +17,8 @@ jr	init
 	jp	sdcCmd
 	jp	sdcCmdR1
 	jp	sdcCmdR7
+	jp	sdcReadBlk
+	jp	sdcSetBlkSize
 
 ; interrupt hook
 .fill	0x38-$
@@ -57,6 +59,7 @@ SHELL_RAMSTART	.equ	BLOCKDEV_RAMEND
 SHELL_EXTRA_CMD_COUNT .equ 0
 #include "shell.asm"
 
+.equ SDC_RAMSTART SHELL_RAMEND
 .equ SDC_PORT_CSHIGH 6
 .equ SDC_PORT_CSLOW 5
 .equ SDC_PORT_SPI 4
diff --git a/recipes/rc2014/sdcard/jumptable.inc b/recipes/rc2014/sdcard/jumptable.inc
index 3e99328..b5b1ab5 100644
--- a/recipes/rc2014/sdcard/jumptable.inc
+++ b/recipes/rc2014/sdcard/jumptable.inc
@@ -6,4 +6,6 @@ JUMP_SDCWAITRESP .equ  0x0e
 JUMP_SDCCMD     .equ   0x11 
 JUMP_SDCCMDR1   .equ   0x14 
 JUMP_SDCCMDR7   .equ   0x17 
+JUMP_SDCREAD    .equ   0x1a
+JUMP_SDCSETBLKSIZE .equ   0x1d
 
diff --git a/recipes/rc2014/sdcard/sdinit.asm b/recipes/rc2014/sdcard/sdinit.asm
index 1442a92..6c6bec0 100644
--- a/recipes/rc2014/sdcard/sdinit.asm
+++ b/recipes/rc2014/sdcard/sdinit.asm
@@ -5,51 +5,30 @@
 	or	a
 	jp	nz, .error
 
-	; 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
-	; to fetch our "Hello World!" and print it and we'll leave the SD card
-	; hanging. Yeah, I know, not very polite.
-
-
-	out	(5), a
-	ld	hl, sCmd
+	ld	hl, sOk
 	call	JUMP_PRINTSTR
-	ld	a, 0b01010001	; CMD17
-	ld	hl, 0		; read single block at addr 0
-	ld	de, 0
-	call	JUMP_SDCCMD
-	cp	0
-	jr	nz, .error
 
-	ld	hl, sCmd
-	call	JUMP_PRINTSTR
-	; Command sent, no error, now let's wait for our data response.
-	ld	b, 20
-.loop1:
-	call	JUMP_SDCWAITRESP
-	; 0xfe is the expected data token for CMD17
-	cp	0xfe
-	jr	z, .loop1end
-	cp	0xff
-	jr	nz, .error
-	djnz	.loop1
-	jr	.error
+	call	JUMP_SDCSETBLKSIZE
+	or	a
+	jp	nz, .error
 
-.loop1end:
-	ld	hl, sGettingData
+	ld	hl, sOk
 	call	JUMP_PRINTSTR
-	; Data packets follow immediately
-	ld	b, 12		; size of "Hello World!"
-	ld	hl, sDest	; sDest has null chars, we'll be alright
-				; printing it.
-.loop2:
-	call	JUMP_SDCWAITRESP
-	ld	(hl), a
-	inc	hl
-	djnz	.loop2
-	out	(6), a
-	ld	hl, sDest
+
+	; read sector 0
+	xor	a
+	call	JUMP_SDCREAD
+	or	a
+	jp	nz, .error
+
+	push	hl
+	ld	hl, sOk
 	call	JUMP_PRINTSTR
+	pop	hl
+	; SDC buffer address is in HL
+	; YOLO! print it!
+	call	JUMP_PRINTSTR
+
 	ret
 .error:
 	call	JUMP_PRINTHEX
@@ -57,14 +36,7 @@
 	call	JUMP_PRINTSTR
 	ret
 
-sCmd:
-	.db "CMD", 0xa, 0xd, 0
-sGettingData:
-	.db "Data", 0xa, 0xd, 0
 sOk:
 	.db "Ok", 0xa, 0xd, 0
 sErr:
 	.db "Err", 0xa, 0xd, 0
-
-sDest:
-	.fill 0x10