1;
2;TBBlue / ZX Spectrum Next project
3;
4;Copyright (c) 2015 Fabio Belavenuto & Victor Trucco
5;
6;This program is free software: you can redistribute it and/or modify
7;it under the terms of the GNU General Public License as published by
8;the Free Software Foundation, either version 3 of the License, or
9;(at your option) any later version.
10;
11;This program is distributed in the hope that it will be useful,
12;but WITHOUT ANY WARRANTY; without even the implied warranty of
13;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14;GNU General Public License for more details.
15;
16;You should have received a copy of the GNU General Public License
17;along with this program.  If not, see <http://www.gnu.org/licenses/>.
18;
19
20SECTION bss_user
21
22mmc_type:  defs 1
23
24SECTION code_user
25
26EXTERN __IO_SPI_CONTROL
27EXTERN __IO_SPI_DATA
28
29; Comandos SPI:
30CMD0  = 0  | 0x40
31CMD1  = 1  | 0x40
32CMD8  = 8  | 0x40
33CMD9  = 9  | 0x40
34CMD10 = 10 | 0x40
35CMD12 = 12 | 0x40
36CMD16 = 16 | 0x40
37CMD17 = 17 | 0x40
38CMD18 = 18 | 0x40
39CMD24 = 24 | 0x40
40CMD25 = 25 | 0x40
41CMD55 = 55 | 0x40
42CMD58 = 58 | 0x40
43ACMD23   = 23 | 0x40
44ACMD41   = 41 | 0x40
45
46
47; ------------------------------------------------
48; Algorithm to initialize an SD card
49; ------------------------------------------------
50; unsigned char MMC_Init();
51;
52
53PUBLIC _MMC_Init
54
55_MMC_Init:
56   ld    a, 0xFF
57   out      (__IO_SPI_CONTROL), a            ; disable SD
58   ld    b, 10                ; send 80 clock pulses with sd card disabled
59enviaClocksInicio:
60   ld    a, 0xFF
61   out      (__IO_SPI_DATA), a
62   djnz  enviaClocksInicio
63   ld    a, 0xFE
64   out      (__IO_SPI_CONTROL), a            ; enable SD
65   ld    a, CMD12
66   call  SD_SEND_CMD             ; cancel any multi-sector read
67   ld    b, 9
68wait_cancel:
69   in    a, (__IO_SPI_DATA)            ; read 9 bytes to ensure cancellation takes effect
70   djnz     wait_cancel
71   ld    b, 16                ; 16 attempts to CMD0
72SD_SEND_CMD0:
73   ld    a, CMD0              ; first command: CMD0
74   ld    de, 0
75   push  bc
76   call  SD_SEND_CMD_2_ARGS_TEST_BUSY
77   pop      bc
78   jp nc, testaSDCV2             ; sd card responded to CMD0, jump
79   djnz  SD_SEND_CMD0
80   ld    l, 0                 ; cartao nao respondeu ao CMD0, retornar 0
81IF __SCCZ80
82   ld    h, l
83ENDIF
84   ld    a, 0xFF
85   out      (__IO_SPI_CONTROL), a            ; desabilita SD
86   ret
87testaSDCV2:
88   ld    a, CMD8
89   ld    de, 0x1AA
90   call  SD_SEND_CMD_2_ARGS_GET_R3
91   ld    hl, SD_SEND_CMD1        ; HL aponta para rotina correta
92   jr    c, pula4               ; cartao recusou CMD8, enviar comando CMD1
93   ld    hl, SD_SEND_ACMD41         ; cartao aceitou CMD8, enviar comando ACMD41
94pula4:
95   ld    bc, 120              ; 120 tentativas
96loop:
97   push  bc
98   call  jumpHL                 ; chamar rotina correta em HL
99   pop      bc
100   jp nc,   iniciou
101   djnz  loop
102   dec      c
103   jr    nz, loop
104deuerroi:
105   ld    l, 0                 ; erro, retornar 0
106IF __SCCZ80
107   ld    h, l
108ENDIF
109   ld    a, 0xFF
110   out      (__IO_SPI_CONTROL), a            ; desabilita SD
111   ret
112jumpHL:
113   jp    (hl)                 ; chamar rotina correta em HL
114iniciou:
115   ld    a, CMD58             ; ler OCR
116   ld    de, 0
117   call  SD_SEND_CMD_2_ARGS_GET_R3  ; enviar comando e receber resposta tipo R3
118   jp c, deuerroi
119   ld    a, b                 ; testa bit CCS do OCR que informa se cartao eh SDV1 ou SDV2
120   and      0x40
121   ld    (mmc_type), a           ; salva informacao da versao do SD (V1 ou V2)
122   call  z, mudarTamanhoBlocoPara512   ; se bit CCS do OCR for 1, eh cartao SDV2 (Block address - SDHC ou SDXD)
123                              ; e nao precisamos mudar tamanho do bloco para 512
124   ld    a, 0xFF
125   out      (__IO_SPI_CONTROL), a            ; desabilita SD
126   ld    a, (mmc_type)           ; retornar tipo de cartao
127IF __SCCZ80
128   ld    h, 0
129ENDIF
130   ld    l, 3
131   cp    0x40
132   ret z
133   ld    l, 2
134   ret
135
136; ------------------------------------------------
137; Setar o tamanho do bloco para 512 se o cartao
138; for SDV1
139; ------------------------------------------------
140mudarTamanhoBlocoPara512:
141   ld    a, CMD16
142   ld    bc, 0
143   ld    de, 512
144   jp    SD_SEND_CMD_GET_ERROR
145
146
147
148; ------------------------------------------------
149; Ler um bloco de 512 bytes do cartao
150; ------------------------------------------------
151; unsigned char MMC_Read(unsigned long lba, unsigned int *buffer)
152; callee linkage
153
154PUBLIC _MMC_Read
155PUBLIC asm_MMC_Read
156
157_MMC_Read:
158
159IF __SDCC
160	pop   hl
161	pop   de
162	pop   bc
163	ex    (sp),hl
164ENDIF
165
166IF __SCCZ80
167	pop   af
168	pop   hl
169	pop   de
170	pop   bc
171	push  af
172ENDIF
173
174asm_MMC_Read:
175
176	; bcde = unsigned long lba
177	; hl   = unsigned char *buffer
178
179   ld    a, 0xFE
180   out      (__IO_SPI_CONTROL), a            ; habilita SD
181
182   ld    a, (mmc_type)           ; verificar se eh SDV1 ou SDV2
183   or    a
184   call  z, blocoParaByte        ; se for SDV1 converter blocos para bytes
185
186   ld    a, CMD17             ; ler somente um bloco com CMD17 = Read Single Block
187   call  SD_SEND_CMD_GET_ERROR
188   jr    nc, ok2
189erro2:
190   ld    l, 0                 ; informar erro
191IF __SCCZ80
192   ld    h, l
193ENDIF
194   ret
195ok2:
196   call  WAIT_RESP_FE
197   jr c, erro2
198   ld    bc, __IO_SPI_DATA
199   inir
200   inir
201   nop
202   in    a, (__IO_SPI_DATA)            ; descarta CRC
203   nop
204   in    a, (__IO_SPI_DATA)
205   ld    l, 1
206IF __SCCZ80
207   ld    h, 0
208ENDIF
209   ret
210
211; ------------------------------------------------
212; Converte blocos para bytes. Na pratica faz
213; BC DE = (BC DE) * 512
214; ------------------------------------------------
215blocoParaByte:
216   ld    b, c
217   ld    c, d
218   ld    d, e
219   ld    e, 0
220   sla      d
221   rl    c
222   rl    b
223   ret
224
225; ------------------------------------------------
226; Enviar CMD1 para cartao. Carry indica erro
227; Destroi AF, BC, DE
228; ------------------------------------------------
229SD_SEND_CMD1:
230   ld    a, CMD1
231SD_SEND_CMD_NO_ARGS:
232   ld    bc, 0
233   ld    d, b
234   ld    e, c
235SD_SEND_CMD_GET_ERROR:
236   call  SD_SEND_CMD
237   or    a
238   ret   z                       ; se A=0 nao houve erro, retornar
239   ; fall throw
240
241; ------------------------------------------------
242; Informar erro
243; Nao destroi registradores
244; ------------------------------------------------
245setaErro:
246   scf
247   ret
248
249; ------------------------------------------------
250; Enviar comando ACMD41
251; ------------------------------------------------
252SD_SEND_ACMD41:
253   ld    a, CMD55
254   call  SD_SEND_CMD_NO_ARGS
255   ld    a, ACMD41
256   ld    bc, 0x4000
257   ld    d, c
258   ld    e, c
259   jr    SD_SEND_CMD_GET_ERROR
260
261; ------------------------------------------------
262; Enviar comando em A com 2 bytes de parametros
263; em DE e testar retorno BUSY
264; Retorna em A a resposta do cartao
265; Destroi AF, BC
266; ------------------------------------------------
267SD_SEND_CMD_2_ARGS_TEST_BUSY:
268   ld    bc, 0
269   call  SD_SEND_CMD
270   ld    b, a
271   and      0xFE                 ; testar bit 0 (flag BUSY)
272   ld    a, b
273   jr    nz, setaErro            ; BUSY em 1, informar erro
274   ret                           ; sem erros
275
276; ------------------------------------------------
277; Enviar comando em A com 2 bytes de parametros
278; em DE e ler resposta do tipo R3 em BC DE
279; Retorna em A a resposta do cartao
280; Destroi AF, BC, DE, HL
281; ------------------------------------------------
282SD_SEND_CMD_2_ARGS_GET_R3:
283   call  SD_SEND_CMD_2_ARGS_TEST_BUSY
284   ret   c
285   push  af
286   call  WAIT_RESP_NO_FF
287   ld    h, a
288   call  WAIT_RESP_NO_FF
289   ld    l, a
290   call  WAIT_RESP_NO_FF
291   ld    d, a
292   call  WAIT_RESP_NO_FF
293   ld    e, a
294   ld    b, h
295   ld    c, l
296   pop      af
297   ret
298
299; ------------------------------------------------
300; Enviar comando em A com 4 bytes de parametros
301; em BC DE e enviar CRC correto se for CMD0 ou
302; CMD8 e aguardar processamento do cartao
303; Destroi AF, BC
304; ------------------------------------------------
305SD_SEND_CMD:
306   out      (__IO_SPI_DATA), a
307   push  af
308   ld    a, b
309   nop
310   out      (__IO_SPI_DATA), a
311   ld    a, c
312   nop
313   out      (__IO_SPI_DATA), a
314   ld    a, d
315   nop
316   out      (__IO_SPI_DATA), a
317   ld    a, e
318   nop
319   out      (__IO_SPI_DATA), a
320   pop      af
321   cp    CMD0
322   ld    b, 0x95                 ; CRC para CMD0
323   jr    z, enviaCRC
324   cp    CMD8
325   ld    b, 0x87                 ; CRC para CMD8
326   jr    z, enviaCRC
327   ld    b, 0xFF                 ; CRC dummy
328enviaCRC:
329   ld    a, b
330   out      (__IO_SPI_DATA), a
331   jr    WAIT_RESP_NO_FF
332
333; ------------------------------------------------
334; Esperar que resposta do cartao seja $FE
335; Destroi AF, B
336; ------------------------------------------------
337WAIT_RESP_FE:
338   ld    b, 10                ; 10 tentativas
339loop1:
340   push  bc
341   call  WAIT_RESP_NO_FF            ; esperar resposta diferente de $FF
342   pop      bc
343   cp    0xFE                 ; resposta � $FE ?
344   ret   z                       ; sim, retornamos com carry=0
345   djnz  loop1
346   scf                           ; erro, carry=1
347   ret
348
349; ------------------------------------------------
350; Esperar que resposta do cartao seja diferente
351; de $FF
352; Destroi AF, BC
353; ------------------------------------------------
354WAIT_RESP_NO_FF:
355   ld    bc, 100              ; 100 tentativas
356loop2:
357   in    a, (__IO_SPI_DATA)
358   cp    0xFF                 ; testa $FF
359   ret   nz                      ; sai se nao for $FF
360   djnz  loop2
361   dec      c
362   jr    nz, loop2
363   ret
364