08d6a195312afac5525e6f5b0ad263d0c5357bf6
[SCSI2SD-V6.git] / src / firmware / sd.c
1 //      Copyright (C) 2013 Michael McMaster <michael@codesrc.com>\r
2 //\r
3 //      This file is part of SCSI2SD.\r
4 //\r
5 //      SCSI2SD is free software: you can redistribute it and/or modify\r
6 //      it under the terms of the GNU General Public License as published by\r
7 //      the Free Software Foundation, either version 3 of the License, or\r
8 //      (at your option) any later version.\r
9 //\r
10 //      SCSI2SD is distributed in the hope that it will be useful,\r
11 //      but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 //      GNU General Public License for more details.\r
14 //\r
15 //      You should have received a copy of the GNU General Public License\r
16 //      along with SCSI2SD.  If not, see <http://www.gnu.org/licenses/>.\r
17 \r
18 #include "stm32f2xx.h"\r
19 #include "sdio.h"\r
20 #include "bsp_driver_sd.h"\r
21 \r
22 \r
23 #include "scsi.h"\r
24 #include "config.h"\r
25 #include "disk.h"\r
26 #include "sd.h"\r
27 #include "led.h"\r
28 #include "time.h"\r
29 #include "trace.h"\r
30 \r
31 #include "scsiPhy.h"\r
32 \r
33 #include <string.h>\r
34 \r
35 // Global\r
36 SdDevice sdDev;\r
37 \r
38 #if 0\r
39 enum SD_CMD_STATE { CMD_STATE_IDLE, CMD_STATE_READ, CMD_STATE_WRITE };\r
40 static int sdCmdState = CMD_STATE_IDLE;\r
41 static uint32_t sdCmdNextLBA; // Only valid in CMD_STATE_READ or CMD_STATE_WRITE\r
42 static uint32_t sdCmdTime;\r
43 static uint32_t sdLastCmdState = CMD_STATE_IDLE;\r
44 \r
45 enum SD_IO_STATE { SD_DMA, SD_ACCEPTED, SD_IDLE };\r
46 static int sdIOState = SD_IDLE;\r
47 \r
48 // Private DMA variables.\r
49 static uint8 sdDMARxChan = CY_DMA_INVALID_CHANNEL;\r
50 static uint8 sdDMATxChan = CY_DMA_INVALID_CHANNEL;\r
51 \r
52 // Dummy location for DMA to send unchecked CRC bytes to\r
53 static uint8 discardBuffer __attribute__((aligned(4)));\r
54 \r
55 // 2 bytes CRC, response, 8bits to close the clock..\r
56 // "NCR" time is up to 8 bytes.\r
57 static uint8_t writeResponseBuffer[8]  __attribute__((aligned(4)));\r
58 \r
59 // Padded with a dummy byte just to allow the tx DMA channel to\r
60 // use 2-byte bursts for performance.\r
61 static uint8_t writeStartToken[2]  __attribute__((aligned(4))) = {0xFF, 0xFC};\r
62 \r
63 // Source of dummy SPI bytes for DMA\r
64 static uint8_t dummyBuffer[2]  __attribute__((aligned(4))) = {0xFF, 0xFF};\r
65 \r
66 volatile uint8_t sdRxDMAComplete;\r
67 volatile uint8_t sdTxDMAComplete;\r
68 \r
69 static void sdCompleteRead();\r
70 static void sdCompleteWrite();\r
71 \r
72 CY_ISR_PROTO(sdRxISR);\r
73 CY_ISR(sdRxISR)\r
74 {\r
75         sdRxDMAComplete = 1;\r
76 }\r
77 CY_ISR_PROTO(sdTxISR);\r
78 CY_ISR(sdTxISR)\r
79 {\r
80         sdTxDMAComplete = 1;\r
81 }\r
82 \r
83 static uint8 sdCrc7(uint8* chr, uint8 cnt, uint8 crc)\r
84 {\r
85         uint8 a;\r
86         for(a = 0; a < cnt; a++)\r
87         {\r
88                 uint8 Data = chr[a];\r
89                 uint8 i;\r
90                 for(i = 0; i < 8; i++)\r
91                 {\r
92                         crc <<= 1;\r
93                         if( (Data & 0x80) ^ (crc & 0x80) ) {crc ^= 0x09;}\r
94                         Data <<= 1;\r
95                 }\r
96         }\r
97         return crc & 0x7F;\r
98 }\r
99 \r
100 \r
101 // Read and write 1 byte.\r
102 static uint8_t sdSpiByte(uint8_t value)\r
103 {\r
104         SDCard_WriteTxData(value);\r
105         trace(trace_spinSpiByte);\r
106         while (!(SDCard_ReadRxStatus() & SDCard_STS_RX_FIFO_NOT_EMPTY)) {}\r
107         trace(trace_sdSpiByte);\r
108         return SDCard_ReadRxData();\r
109 }\r
110 \r
111 static void sdWaitWriteBusy()\r
112 {\r
113         uint8 val;\r
114         do\r
115         {\r
116                 val = sdSpiByte(0xFF);\r
117         } while (val != 0xFF);\r
118 }\r
119 \r
120 static void sdPreCmdState(uint32_t newState)\r
121 {\r
122         if (sdCmdState == CMD_STATE_READ)\r
123         {\r
124                 sdCompleteRead();\r
125         }\r
126         else if (sdCmdState == CMD_STATE_WRITE)\r
127         {\r
128                 sdCompleteWrite();\r
129         }\r
130         sdCmdState = CMD_STATE_IDLE;\r
131 \r
132         if (sdLastCmdState != newState && newState != CMD_STATE_IDLE)\r
133         {\r
134                 sdWaitWriteBusy();\r
135                 sdLastCmdState = newState;\r
136         }\r
137 }\r
138 \r
139 static uint16_t sdDoCommand(\r
140         uint8_t cmd,\r
141         uint32_t param,\r
142         int useCRC,\r
143         int use2byteResponse)\r
144 {\r
145         int waitWhileBusy = (cmd != SD_GO_IDLE_STATE) && (cmd != SD_STOP_TRANSMISSION);\r
146 \r
147         // "busy" probe. We'll examine the results later.\r
148         if (waitWhileBusy)\r
149         {\r
150                 SDCard_WriteTxData(0xFF);\r
151         }\r
152 \r
153         // send is static as the address must remain consistent for the static\r
154         // DMA descriptors to work.\r
155         // Size must be divisible by 2 to suit 2-byte-burst TX DMA channel.\r
156         static uint8_t send[6] __attribute__((aligned(4)));\r
157         send[0] = cmd | 0x40;\r
158         send[1] = param >> 24;\r
159         send[2] = param >> 16;\r
160         send[3] = param >> 8;\r
161         send[4] = param;\r
162         if (unlikely(useCRC))\r
163         {\r
164                 send[5] = (sdCrc7(send, 5, 0) << 1) | 1;\r
165         }\r
166         else\r
167         {\r
168                 send[5] = 1; // stop bit\r
169         }\r
170 \r
171         static uint8_t dmaRxTd = CY_DMA_INVALID_TD;\r
172         static uint8_t dmaTxTd = CY_DMA_INVALID_TD;\r
173         if (unlikely(dmaRxTd == CY_DMA_INVALID_TD))\r
174         {\r
175                 dmaRxTd = CyDmaTdAllocate();\r
176                 dmaTxTd = CyDmaTdAllocate();\r
177                 CyDmaTdSetConfiguration(dmaTxTd, sizeof(send), CY_DMA_DISABLE_TD, TD_INC_SRC_ADR|SD_TX_DMA__TD_TERMOUT_EN);\r
178                 CyDmaTdSetAddress(dmaTxTd, LO16((uint32)&send), LO16((uint32)SDCard_TXDATA_PTR));\r
179                 CyDmaTdSetConfiguration(dmaRxTd, sizeof(send), CY_DMA_DISABLE_TD, SD_RX_DMA__TD_TERMOUT_EN);\r
180                 CyDmaTdSetAddress(dmaRxTd, LO16((uint32)SDCard_RXDATA_PTR), LO16((uint32)&discardBuffer));\r
181         }\r
182 \r
183         sdTxDMAComplete = 0;\r
184         sdRxDMAComplete = 0;\r
185 \r
186         CyDmaChSetInitialTd(sdDMARxChan, dmaRxTd);\r
187         CyDmaChSetInitialTd(sdDMATxChan, dmaTxTd);\r
188 \r
189         // Some Samsung cards enter a busy-state after single-sector reads.\r
190         // But we also need to wait for R1B to complete from the multi-sector\r
191         // reads.\r
192         if (waitWhileBusy)\r
193         {\r
194                 trace(trace_spinSDRxFIFO);\r
195                 while (!(SDCard_ReadRxStatus() & SDCard_STS_RX_FIFO_NOT_EMPTY)) {}\r
196                 int busy = SDCard_ReadRxData() != 0xFF;\r
197                 if (unlikely(busy))\r
198                 {\r
199                         trace(trace_spinSDBusy);\r
200                         while (sdSpiByte(0xFF) != 0xFF) {}\r
201                 }\r
202         }\r
203 \r
204         // The DMA controller is a bit trigger-happy. It will retain\r
205         // a drq request that was triggered while the channel was\r
206         // disabled.\r
207         CyDmaChSetRequest(sdDMATxChan, CY_DMA_CPU_REQ);\r
208         CyDmaClearPendingDrq(sdDMARxChan);\r
209 \r
210         // There is no flow control, so we must ensure we can read the bytes\r
211         // before we start transmitting\r
212         CyDmaChEnable(sdDMARxChan, 1);\r
213         CyDmaChEnable(sdDMATxChan, 1);\r
214 \r
215         trace(trace_spinSDDMA);\r
216         int allComplete = 0;\r
217         while (!allComplete)\r
218         {\r
219                 uint8_t intr = CyEnterCriticalSection();\r
220                 allComplete = sdTxDMAComplete && sdRxDMAComplete;\r
221                 if (!allComplete)\r
222                 {\r
223                         __WFI();\r
224                 }\r
225                 CyExitCriticalSection(intr);\r
226         }\r
227 \r
228         uint16_t response = sdSpiByte(0xFF); // Result code or stuff byte\r
229         if (unlikely(cmd == SD_STOP_TRANSMISSION))\r
230         {\r
231                 // Stuff byte is required for this command only.\r
232                 // Part 1 Simplified standard 3.01\r
233                 // "The stop command has an execution delay due to the serial command\r
234                 // transmission."\r
235                 response = sdSpiByte(0xFF);\r
236         }\r
237 \r
238         uint32_t start = getTime_ms();\r
239 \r
240         trace(trace_spinSDBusy);\r
241         while ((response & 0x80) && likely(elapsedTime_ms(start) <= 200))\r
242         {\r
243                 response = sdSpiByte(0xFF);\r
244         }\r
245         if (unlikely(use2byteResponse))\r
246         {\r
247                 response = (response << 8) | sdSpiByte(0xFF);\r
248         }\r
249         return response;\r
250 }\r
251 \r
252 \r
253 static inline uint16_t sdCommandAndResponse(uint8_t cmd, uint32_t param)\r
254 {\r
255         return sdDoCommand(cmd, param, 0, 0);\r
256 }\r
257 \r
258 static inline uint16_t sdCRCCommandAndResponse(uint8_t cmd, uint32_t param)\r
259 {\r
260         return sdDoCommand(cmd, param, 1, 0);\r
261 }\r
262 \r
263 // Clear the sticky status bits on error.\r
264 static void sdClearStatus()\r
265 {\r
266         sdSpiByte(0xFF);\r
267         uint16_t r2 = sdDoCommand(SD_SEND_STATUS, 0, 1, 1);\r
268         (void) r2;\r
269 }\r
270 \r
271 void\r
272 sdReadMultiSectorPrep(uint32_t sdLBA, uint32_t sdSectors)\r
273 {\r
274         uint32_t tmpNextLBA = sdLBA + sdSectors;\r
275 \r
276         if (!sdDev.ccs)\r
277         {\r
278                 sdLBA = sdLBA * SD_SECTOR_SIZE;\r
279                 tmpNextLBA = tmpNextLBA * SD_SECTOR_SIZE;\r
280         }\r
281 \r
282         if (sdCmdState == CMD_STATE_READ && sdCmdNextLBA == sdLBA)\r
283         {\r
284                 // Well, that was lucky. We're already reading this data\r
285                 sdCmdNextLBA = tmpNextLBA;\r
286                 sdCmdTime = getTime_ms();\r
287         }\r
288         else\r
289         {\r
290                 sdPreCmdState(CMD_STATE_READ);\r
291 \r
292                 uint8_t v = sdCommandAndResponse(SD_READ_MULTIPLE_BLOCK, sdLBA);\r
293                 if (unlikely(v))\r
294                 {\r
295                         scsiDiskReset();\r
296                         sdClearStatus();\r
297 \r
298                         scsiDev.status = CHECK_CONDITION;\r
299                         scsiDev.target->sense.code = HARDWARE_ERROR;\r
300                         scsiDev.target->sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
301                         scsiDev.phase = STATUS;\r
302                 }\r
303                 else\r
304                 {\r
305                         sdCmdNextLBA = tmpNextLBA;\r
306                         sdCmdState = CMD_STATE_READ;\r
307                         sdCmdTime = getTime_ms();\r
308                 }\r
309         }\r
310 }\r
311 \r
312 static void\r
313 dmaReadSector(uint8_t* outputBuffer)\r
314 {\r
315         // Wait for a start-block token.\r
316         // Don't wait more than 200ms.  The standard recommends 100ms.\r
317         uint32_t start = getTime_ms();\r
318         uint8_t token = sdSpiByte(0xFF);\r
319         trace(trace_spinSDBusy);\r
320         while (token != 0xFE && likely(elapsedTime_ms(start) <= 200))\r
321         {\r
322                 if (unlikely(token && ((token & 0xE0) == 0)))\r
323                 {\r
324                         // Error token!\r
325                         break;\r
326                 }\r
327                 token = sdSpiByte(0xFF);\r
328         }\r
329         if (unlikely(token != 0xFE))\r
330         {\r
331                 if (transfer.multiBlock)\r
332                 {\r
333                         sdCompleteRead();\r
334                 }\r
335                 if (scsiDev.status != CHECK_CONDITION)\r
336                 {\r
337                         scsiDev.status = CHECK_CONDITION;\r
338                         scsiDev.target->sense.code = HARDWARE_ERROR;\r
339                         scsiDev.target->sense.asc = UNRECOVERED_READ_ERROR;\r
340                         scsiDev.phase = STATUS;\r
341                 }\r
342                 sdClearStatus();\r
343                 return;\r
344         }\r
345 \r
346         static uint8_t dmaRxTd[2] = { CY_DMA_INVALID_TD, CY_DMA_INVALID_TD};\r
347         static uint8_t dmaTxTd = CY_DMA_INVALID_TD;\r
348         if (unlikely(dmaRxTd[0] == CY_DMA_INVALID_TD))\r
349         {\r
350                 dmaRxTd[0] = CyDmaTdAllocate();\r
351                 dmaRxTd[1] = CyDmaTdAllocate();\r
352                 dmaTxTd = CyDmaTdAllocate();\r
353 \r
354                 // Receive 512 bytes of data and then 2 bytes CRC.\r
355                 CyDmaTdSetConfiguration(dmaRxTd[0], SD_SECTOR_SIZE, dmaRxTd[1], TD_INC_DST_ADR);\r
356                 CyDmaTdSetConfiguration(dmaRxTd[1], 2, CY_DMA_DISABLE_TD, SD_RX_DMA__TD_TERMOUT_EN);\r
357                 CyDmaTdSetAddress(dmaRxTd[1], LO16((uint32)SDCard_RXDATA_PTR), LO16((uint32)&discardBuffer));\r
358 \r
359                 CyDmaTdSetConfiguration(dmaTxTd, SD_SECTOR_SIZE + 2, CY_DMA_DISABLE_TD, SD_TX_DMA__TD_TERMOUT_EN);\r
360                 CyDmaTdSetAddress(dmaTxTd, LO16((uint32)&dummyBuffer), LO16((uint32)SDCard_TXDATA_PTR));\r
361 \r
362         }\r
363         CyDmaTdSetAddress(dmaRxTd[0], LO16((uint32)SDCard_RXDATA_PTR), LO16((uint32)outputBuffer));\r
364 \r
365         sdIOState = SD_DMA;\r
366         sdTxDMAComplete = 0;\r
367         sdRxDMAComplete = 0;\r
368 \r
369         // Re-loading the initial TD's here is very important, or else\r
370         // we'll be re-using the last-used TD, which would be the last\r
371         // in the chain (ie. CRC TD)\r
372         CyDmaChSetInitialTd(sdDMARxChan, dmaRxTd[0]);\r
373         CyDmaChSetInitialTd(sdDMATxChan, dmaTxTd);\r
374 \r
375         // The DMA controller is a bit trigger-happy. It will retain\r
376         // a drq request that was triggered while the channel was\r
377         // disabled.\r
378         CyDmaChSetRequest(sdDMATxChan, CY_DMA_CPU_REQ);\r
379         CyDmaClearPendingDrq(sdDMARxChan);\r
380 \r
381         // There is no flow control, so we must ensure we can read the bytes\r
382         // before we start transmitting\r
383         CyDmaChEnable(sdDMARxChan, 1);\r
384         CyDmaChEnable(sdDMATxChan, 1);\r
385 }\r
386 \r
387 int\r
388 sdReadSectorDMAPoll()\r
389 {\r
390         if (sdRxDMAComplete && sdTxDMAComplete)\r
391         {\r
392                 // DMA transfer is complete\r
393                 sdIOState = SD_IDLE;\r
394                 return 1;\r
395         }\r
396         else\r
397         {\r
398                 return 0;\r
399         }\r
400 }\r
401 \r
402 void sdReadSingleSectorDMA(uint32_t lba, uint8_t* outputBuffer)\r
403 {\r
404         sdPreCmdState(CMD_STATE_READ);\r
405 \r
406         uint8 v;\r
407         if (!sdDev.ccs)\r
408         {\r
409                 lba = lba * SD_SECTOR_SIZE;\r
410         }\r
411         v = sdCommandAndResponse(SD_READ_SINGLE_BLOCK, lba);\r
412         if (unlikely(v))\r
413         {\r
414                 scsiDiskReset();\r
415                 sdClearStatus();\r
416 \r
417                 scsiDev.status = CHECK_CONDITION;\r
418                 scsiDev.target->sense.code = HARDWARE_ERROR;\r
419                 scsiDev.target->sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
420                 scsiDev.phase = STATUS;\r
421         }\r
422         else\r
423         {\r
424                 dmaReadSector(outputBuffer);\r
425         }\r
426 }\r
427 \r
428 void\r
429 sdReadMultiSectorDMA(uint8_t* outputBuffer)\r
430 {\r
431         // Pre: sdReadMultiSectorPrep called.\r
432         dmaReadSector(outputBuffer);\r
433 }\r
434 \r
435 static void sdCompleteRead()\r
436 {\r
437         if (unlikely(sdIOState != SD_IDLE))\r
438         {\r
439                 // Not much choice but to wait until we've completed the transfer.\r
440                 // Cancelling the transfer can't be done as we have no way to reset\r
441                 // the SD card.\r
442                 trace(trace_spinSDCompleteRead);\r
443                 while (!sdReadSectorDMAPoll()) { /* spin */ }\r
444         }\r
445 \r
446 \r
447         if (sdCmdState == CMD_STATE_READ)\r
448         {\r
449                 uint8 r1b = sdCommandAndResponse(SD_STOP_TRANSMISSION, 0);\r
450 \r
451                 if (unlikely(r1b) && (scsiDev.phase == DATA_IN))\r
452                 {\r
453                         scsiDev.status = CHECK_CONDITION;\r
454                         scsiDev.target->sense.code = HARDWARE_ERROR;\r
455                         scsiDev.target->sense.asc = UNRECOVERED_READ_ERROR;\r
456                         scsiDev.phase = STATUS;\r
457                 }\r
458         }\r
459 \r
460         // R1b has an optional trailing "busy" signal, but we defer waiting on this.\r
461         // The next call so sdCommandAndResponse will wait for the busy state to\r
462         // clear.\r
463 \r
464         sdCmdState = CMD_STATE_IDLE;\r
465 }\r
466 \r
467 void\r
468 sdWriteMultiSectorDMA(uint8_t* outputBuffer)\r
469 {\r
470         static uint8_t dmaRxTd[2] = { CY_DMA_INVALID_TD, CY_DMA_INVALID_TD};\r
471         static uint8_t dmaTxTd[3] = { CY_DMA_INVALID_TD, CY_DMA_INVALID_TD, CY_DMA_INVALID_TD};\r
472         if (unlikely(dmaRxTd[0] == CY_DMA_INVALID_TD))\r
473         {\r
474                 dmaRxTd[0] = CyDmaTdAllocate();\r
475                 dmaRxTd[1] = CyDmaTdAllocate();\r
476                 dmaTxTd[0] = CyDmaTdAllocate();\r
477                 dmaTxTd[1] = CyDmaTdAllocate();\r
478                 dmaTxTd[2] = CyDmaTdAllocate();\r
479 \r
480                 // Transmit 512 bytes of data and then 2 bytes CRC, and then get the response byte\r
481                 // We need to do this without stopping the clock\r
482                 CyDmaTdSetConfiguration(dmaTxTd[0], 2, dmaTxTd[1], TD_INC_SRC_ADR);\r
483                 CyDmaTdSetAddress(dmaTxTd[0], LO16((uint32)&writeStartToken), LO16((uint32)SDCard_TXDATA_PTR));\r
484 \r
485                 CyDmaTdSetConfiguration(dmaTxTd[1], SD_SECTOR_SIZE, dmaTxTd[2], TD_INC_SRC_ADR);\r
486 \r
487                 CyDmaTdSetConfiguration(dmaTxTd[2], 2 + sizeof(writeResponseBuffer), CY_DMA_DISABLE_TD, SD_TX_DMA__TD_TERMOUT_EN);\r
488                 CyDmaTdSetAddress(dmaTxTd[2], LO16((uint32)&dummyBuffer), LO16((uint32)SDCard_TXDATA_PTR));\r
489 \r
490                 CyDmaTdSetConfiguration(dmaRxTd[0], SD_SECTOR_SIZE + 4, dmaRxTd[1], 0);\r
491                 CyDmaTdSetAddress(dmaRxTd[0], LO16((uint32)SDCard_RXDATA_PTR), LO16((uint32)&discardBuffer));\r
492                 CyDmaTdSetConfiguration(dmaRxTd[1], sizeof(writeResponseBuffer), CY_DMA_DISABLE_TD, SD_RX_DMA__TD_TERMOUT_EN|TD_INC_DST_ADR);\r
493                 CyDmaTdSetAddress(dmaRxTd[1], LO16((uint32)SDCard_RXDATA_PTR), LO16((uint32)&writeResponseBuffer));\r
494         }\r
495         CyDmaTdSetAddress(dmaTxTd[1], LO16((uint32)outputBuffer), LO16((uint32)SDCard_TXDATA_PTR));\r
496 \r
497 \r
498         sdIOState = SD_DMA;\r
499         // The DMA controller is a bit trigger-happy. It will retain\r
500         // a drq request that was triggered while the channel was\r
501         // disabled.\r
502         CyDmaChSetRequest(sdDMATxChan, CY_DMA_CPU_REQ);\r
503         CyDmaClearPendingDrq(sdDMARxChan);\r
504 \r
505         sdTxDMAComplete = 0;\r
506         sdRxDMAComplete = 0;\r
507 \r
508         // Re-loading the initial TD's here is very important, or else\r
509         // we'll be re-using the last-used TD, which would be the last\r
510         // in the chain (ie. CRC TD)\r
511         CyDmaChSetInitialTd(sdDMARxChan, dmaRxTd[0]);\r
512         CyDmaChSetInitialTd(sdDMATxChan, dmaTxTd[0]);\r
513 \r
514         // There is no flow control, so we must ensure we can read the bytes\r
515         // before we start transmitting\r
516         CyDmaChEnable(sdDMARxChan, 1);\r
517         CyDmaChEnable(sdDMATxChan, 1);\r
518 }\r
519 \r
520 int\r
521 sdWriteSectorDMAPoll()\r
522 {\r
523         if (sdRxDMAComplete && sdTxDMAComplete)\r
524         {\r
525                 if (sdIOState == SD_DMA)\r
526                 {\r
527                         // Retry a few times. The data token format is:\r
528                         // XXX0AAA1\r
529                         int i = 0;\r
530                         uint8_t dataToken;\r
531                         do\r
532                         {\r
533                                 dataToken = writeResponseBuffer[i]; // Response\r
534                                 ++i;\r
535                         } while (((dataToken & 0x0101) != 1) && (i < sizeof(writeResponseBuffer)));\r
536 \r
537                         // At this point we should either have an accepted token, or we'll\r
538                         // timeout and proceed into the error case below.\r
539                         if (unlikely(((dataToken & 0x1F) >> 1) != 0x2)) // Accepted.\r
540                         {\r
541                                 sdIOState = SD_IDLE;\r
542 \r
543                                 sdWaitWriteBusy();\r
544                                 sdSpiByte(0xFD); // STOP TOKEN\r
545                                 sdWaitWriteBusy();\r
546 \r
547                                 sdCmdState = CMD_STATE_IDLE;\r
548                                 scsiDiskReset();\r
549                                 sdClearStatus();\r
550 \r
551                                 scsiDev.status = CHECK_CONDITION;\r
552                                 scsiDev.target->sense.code = HARDWARE_ERROR;\r
553                                 scsiDev.target->sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
554                                 scsiDev.phase = STATUS;\r
555                         }\r
556                         else\r
557                         {\r
558                                 sdIOState = SD_ACCEPTED;\r
559                         }\r
560                 }\r
561 \r
562                 if (sdIOState == SD_ACCEPTED)\r
563                 {\r
564                         // Wait while the SD card is busy\r
565                         if (sdSpiByte(0xFF) == 0xFF)\r
566                         {\r
567                                 sdIOState = SD_IDLE;\r
568                         }\r
569                 }\r
570 \r
571                 return sdIOState == SD_IDLE;\r
572         }\r
573         else\r
574         {\r
575                 return 0;\r
576         }\r
577 }\r
578 \r
579 static void sdCompleteWrite()\r
580 {\r
581         if (unlikely(sdIOState != SD_IDLE))\r
582         {\r
583                 // Not much choice but to wait until we've completed the transfer.\r
584                 // Cancelling the transfer can't be done as we have no way to reset\r
585                 // the SD card.\r
586                 trace(trace_spinSDCompleteWrite);\r
587                 while (!sdWriteSectorDMAPoll()) { /* spin */ }\r
588         }\r
589 \r
590         if (sdCmdState == CMD_STATE_WRITE)\r
591         {\r
592                 sdWaitWriteBusy();\r
593 \r
594                 sdSpiByte(0xFD); // STOP TOKEN\r
595 \r
596                 sdWaitWriteBusy();\r
597         }\r
598 \r
599 \r
600         if (likely(scsiDev.phase == DATA_OUT))\r
601         {\r
602                 uint16_t r2 = sdDoCommand(SD_SEND_STATUS, 0, 0, 1);\r
603                 if (unlikely(r2))\r
604                 {\r
605                         sdClearStatus();\r
606                         scsiDev.status = CHECK_CONDITION;\r
607                         scsiDev.target->sense.code = HARDWARE_ERROR;\r
608                         scsiDev.target->sense.asc = WRITE_ERROR_AUTO_REALLOCATION_FAILED;\r
609                         scsiDev.phase = STATUS;\r
610                 }\r
611         }\r
612         sdCmdState = CMD_STATE_IDLE;\r
613 }\r
614 \r
615 void sdCompleteTransfer()\r
616 {\r
617         sdPreCmdState(CMD_STATE_IDLE);\r
618 }\r
619 \r
620 \r
621 // SD Version 2 (SDHC) support\r
622 static int sendIfCond()\r
623 {\r
624         int retries = 50;\r
625 \r
626         do\r
627         {\r
628                 // 11:8 Host voltage. 1 = 2.7-3.6V\r
629                 // 7:0 Echo bits. Ignore.\r
630                 uint8 status = sdCRCCommandAndResponse(SD_SEND_IF_COND, 0x000001AA);\r
631 \r
632                 if (status == SD_R1_IDLE)\r
633                 {\r
634                         // Version 2 card.\r
635                         sdDev.version = 2;\r
636                         // Read 32bit response. Should contain the same bytes that\r
637                         // we sent in the command parameter.\r
638                         sdSpiByte(0xFF);\r
639                         sdSpiByte(0xFF);\r
640                         sdSpiByte(0xFF);\r
641                         sdSpiByte(0xFF);\r
642                         break;\r
643                 }\r
644                 else if (status & SD_R1_ILLEGAL)\r
645                 {\r
646                         // Version 1 card.\r
647                         sdDev.version = 1;\r
648                         sdClearStatus();\r
649                         break;\r
650                 }\r
651 \r
652                 sdClearStatus();\r
653         } while (--retries > 0);\r
654 \r
655         return retries > 0;\r
656 }\r
657 \r
658 static int sdOpCond()\r
659 {\r
660         uint32_t start = getTime_ms();\r
661 \r
662         uint8 status;\r
663         do\r
664         {\r
665                 sdCRCCommandAndResponse(SD_APP_CMD, 0);\r
666                 // Host Capacity Support = 1 (SDHC/SDXC supported)\r
667                 status = sdCRCCommandAndResponse(SD_APP_SEND_OP_COND, 0x40000000);\r
668 \r
669                 sdClearStatus();\r
670 \r
671         // Spec says to poll for 1 second.\r
672         } while ((status != 0) && (elapsedTime_ms(start) < 1000));\r
673 \r
674         return status == 0;\r
675 }\r
676 \r
677 static int sdReadOCR()\r
678 {\r
679         uint32_t start = getTime_ms();\r
680         int complete;\r
681         uint8 status;\r
682 \r
683         do\r
684         {\r
685                 uint8 buf[4];\r
686                 int i;\r
687 \r
688                 status = sdCRCCommandAndResponse(SD_READ_OCR, 0);\r
689                 if(status) { break; }\r
690 \r
691                 for (i = 0; i < 4; ++i)\r
692                 {\r
693                         buf[i] = sdSpiByte(0xFF);\r
694                 }\r
695 \r
696                 sdDev.ccs = (buf[0] & 0x40) ? 1 : 0;\r
697                 complete = (buf[0] & 0x80);\r
698 \r
699         } while (!status &&\r
700                 !complete &&\r
701                 (elapsedTime_ms(start) < 1000));\r
702 \r
703         return (status == 0) && complete;\r
704 }\r
705 \r
706 static void sdReadCID()\r
707 {\r
708         uint8 startToken;\r
709         int maxWait, i;\r
710 \r
711         uint8 status = sdCRCCommandAndResponse(SD_SEND_CID, 0);\r
712         if(status){return;}\r
713 \r
714         maxWait = 1023;\r
715         do\r
716         {\r
717                 startToken = sdSpiByte(0xFF);\r
718         } while(maxWait-- && (startToken != 0xFE));\r
719         if (startToken != 0xFE) { return; }\r
720 \r
721         for (i = 0; i < 16; ++i)\r
722         {\r
723                 sdDev.cid[i] = sdSpiByte(0xFF);\r
724         }\r
725         sdSpiByte(0xFF); // CRC\r
726         sdSpiByte(0xFF); // CRC\r
727 }\r
728 \r
729 static int sdReadCSD()\r
730 {\r
731         uint8 startToken;\r
732         int maxWait, i;\r
733 \r
734         uint8 status = sdCRCCommandAndResponse(SD_SEND_CSD, 0);\r
735         if(status){goto bad;}\r
736 \r
737         maxWait = 1023;\r
738         do\r
739         {\r
740                 startToken = sdSpiByte(0xFF);\r
741         } while(maxWait-- && (startToken != 0xFE));\r
742         if (startToken != 0xFE) { goto bad; }\r
743 \r
744         for (i = 0; i < 16; ++i)\r
745         {\r
746                 sdDev.csd[i] = sdSpiByte(0xFF);\r
747         }\r
748         sdSpiByte(0xFF); // CRC\r
749         sdSpiByte(0xFF); // CRC\r
750 \r
751         if ((sdDev.csd[0] >> 6) == 0x00)\r
752         {\r
753                 // CSD version 1\r
754                 // C_SIZE in bits [73:62]\r
755                 uint32 c_size = (((((uint32)sdDev.csd[6]) & 0x3) << 16) | (((uint32)sdDev.csd[7]) << 8) | sdDev.csd[8]) >> 6;\r
756                 uint32 c_mult = (((((uint32)sdDev.csd[9]) & 0x3) << 8) | ((uint32)sdDev.csd[0xa])) >> 7;\r
757                 uint32 sectorSize = sdDev.csd[5] & 0x0F;\r
758                 sdDev.capacity = ((c_size+1) * ((uint64)1 << (c_mult+2)) * ((uint64)1 << sectorSize)) / SD_SECTOR_SIZE;\r
759         }\r
760         else if ((sdDev.csd[0] >> 6) == 0x01)\r
761         {\r
762                 // CSD version 2\r
763                 // C_SIZE in bits [69:48]\r
764 \r
765                 uint32 c_size =\r
766                         ((((uint32)sdDev.csd[7]) & 0x3F) << 16) |\r
767                         (((uint32)sdDev.csd[8]) << 8) |\r
768                         ((uint32)sdDev.csd[7]);\r
769                 sdDev.capacity = (c_size + 1) * 1024;\r
770         }\r
771         else\r
772         {\r
773                 goto bad;\r
774         }\r
775 \r
776         return 1;\r
777 bad:\r
778         return 0;\r
779 }\r
780 \r
781 #endif\r
782 static void sdInitDMA()\r
783 {\r
784         // One-time init only.\r
785         static uint8_t init = 0;\r
786         if (init == 0)\r
787         {\r
788                 init = 1;\r
789 \r
790  //TODO MM SEE STUPID SD_DMA_RxCplt that require the SD IRQs to preempt\r
791 // Configured with 4 bits preemption, NO sub priority.\r
792   HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 8, 0);\r
793   HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);\r
794   HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 8, 0);\r
795   HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);\r
796 #if 0\r
797                 sdDMATxChan =\r
798                         SD_TX_DMA_DmaInitialize(\r
799                                 2, // Bytes per burst\r
800                                 1, // request per burst\r
801                                 HI16(CYDEV_SRAM_BASE),\r
802                                 HI16(CYDEV_PERIPH_BASE)\r
803                                 );\r
804 \r
805                 sdDMARxChan =\r
806                         SD_RX_DMA_DmaInitialize(\r
807                                 1, // Bytes per burst\r
808                                 1, // request per burst\r
809                                 HI16(CYDEV_PERIPH_BASE),\r
810                                 HI16(CYDEV_SRAM_BASE)\r
811                                 );\r
812 \r
813                 CyDmaChDisable(sdDMATxChan);\r
814                 CyDmaChDisable(sdDMARxChan);\r
815 \r
816                 SD_RX_DMA_COMPLETE_StartEx(sdRxISR);\r
817                 SD_TX_DMA_COMPLETE_StartEx(sdTxISR);\r
818 #endif\r
819         }\r
820 }\r
821 \r
822 void sdTmpRead(uint8_t* data, uint32_t lba, int sectors)\r
823 {\r
824         BSP_SD_ReadBlocks_DMA((uint32_t*) data, lba * 512ll, 512, sectors);\r
825 }\r
826 \r
827 void sdTmpWrite(uint8_t* data, uint32_t lba, int sectors)\r
828 {\r
829         BSP_SD_WriteBlocks_DMA((uint32_t*) data, lba * 512ll, 512, sectors);\r
830 }\r
831 \r
832 int sdInit()\r
833 {\r
834         int result = 0;\r
835         //int i;\r
836 \r
837         // TODO sdCmdState = CMD_STATE_IDLE;\r
838         sdDev.version = 0;\r
839         sdDev.ccs = 0;\r
840         sdDev.capacity = 0;\r
841         memset(sdDev.csd, 0, sizeof(sdDev.csd));\r
842         memset(sdDev.cid, 0, sizeof(sdDev.cid));\r
843 \r
844 // TODO should be in POLL method!\r
845 \r
846         sdInitDMA();\r
847 #if 0\r
848 \r
849         SD_CS_SetDriveMode(SD_CS_DM_STRONG);\r
850         SD_CS_Write(1); // Set CS inactive (active low)\r
851 \r
852         // Set the SPI clock for 400kHz transfers\r
853         // 25MHz / 400kHz approx factor of 63.\r
854         // The register contains (divider - 1)\r
855         uint16_t clkDiv25MHz =  SD_Data_Clk_GetDividerRegister();\r
856         SD_Data_Clk_SetDivider(((clkDiv25MHz + 1) * 63) - 1);\r
857         // Wait for the clock to settle.\r
858         CyDelayUs(1);\r
859 \r
860         SDCard_Start(); // Enable SPI hardware\r
861 \r
862         // Power on sequence. 74 clock cycles of a "1" while CS unasserted.\r
863         for (i = 0; i < 10; ++i)\r
864         {\r
865                 sdSpiByte(0xFF);\r
866         }\r
867 \r
868         SD_CS_Write(0); // Set CS active (active low)\r
869         CyDelayUs(1);\r
870 \r
871         sdSpiByte(0xFF);\r
872         v = sdDoCommand(SD_GO_IDLE_STATE, 0, 1, 0);\r
873         if(v != 1){goto bad;}\r
874 \r
875         ledOn();\r
876         if (!sendIfCond()) goto bad; // Sets V1 or V2 flag  CMD8\r
877         if (!sdOpCond()) goto bad; // ACMD41. Wait for init completes.\r
878         if (!sdReadOCR()) goto bad; // CMD58. Get CCS flag. Only valid after init.\r
879 \r
880         // This command will be ignored if sdDev.ccs is set.\r
881         // SDHC and SDXC are always 512bytes.\r
882         v = sdCRCCommandAndResponse(SD_SET_BLOCKLEN, SD_SECTOR_SIZE); //Force sector size\r
883         if(v){goto bad;}\r
884         v = sdCRCCommandAndResponse(SD_CRC_ON_OFF, 0); //crc off\r
885         if(v){goto bad;}\r
886 \r
887         // now set the sd card back to full speed.\r
888         // The SD Card spec says we can run SPI @ 25MHz\r
889         SDCard_Stop();\r
890 \r
891         // We can't run at full-speed with the pullup resistors enabled.\r
892         SD_MISO_SetDriveMode(SD_MISO_DM_DIG_HIZ);\r
893         SD_MOSI_SetDriveMode(SD_MOSI_DM_STRONG);\r
894         SD_SCK_SetDriveMode(SD_SCK_DM_STRONG);\r
895 \r
896         SD_Data_Clk_SetDivider(clkDiv25MHz);\r
897         CyDelayUs(1);\r
898         SDCard_Start();\r
899 \r
900         // Clear out rubbish data through clock change\r
901         CyDelayUs(1);\r
902         SDCard_ReadRxStatus();\r
903         SDCard_ReadTxStatus();\r
904         SDCard_ClearFIFO();\r
905 \r
906         if (!sdReadCSD()) goto bad;\r
907         sdReadCID();\r
908 \r
909         result = 1;\r
910         goto out;\r
911 \r
912 bad:\r
913         SD_Data_Clk_SetDivider(clkDiv25MHz); // Restore the clock for our next retry\r
914         sdDev.capacity = 0;\r
915 \r
916 out:\r
917         sdClearStatus();\r
918         ledOff();\r
919         return result;\r
920 \r
921 #endif\r
922         uint8_t error = BSP_SD_Init();\r
923         if (error == MSD_OK)\r
924         {\r
925                 memcpy(sdDev.csd, &SDCardInfo.SD_csd, sizeof(sdDev.csd));\r
926                 memcpy(sdDev.cid, &SDCardInfo.SD_cid, sizeof(sdDev.cid));\r
927                 sdDev.capacity = SDCardInfo.CardCapacity / SD_SECTOR_SIZE;\r
928                 blockDev.state |= DISK_PRESENT | DISK_INITIALISED;\r
929                 result = 1;\r
930 \r
931                 // SD Benchmark code\r
932                 // Currently 8MB/s\r
933                 #ifdef SD_BENCHMARK\r
934                 while(1)\r
935                 {\r
936                         s2s_ledOn();\r
937                         // 100MB\r
938                         int maxSectors = MAX_SECTOR_SIZE / SD_SECTOR_SIZE;\r
939                         for (\r
940                                 int i = 0;\r
941                                 i < (100LL * 1024 * 1024 / (maxSectors * SD_SECTOR_SIZE));\r
942                                 ++i)\r
943                         {\r
944                                 sdTmpRead(&scsiDev.data[0], 0, maxSectors);\r
945                         }\r
946                         s2s_ledOff();\r
947 \r
948                         for(int i = 0; i < 10; ++i) s2s_delay_ms(1000);\r
949                 }\r
950                 #endif\r
951 \r
952                 goto out;\r
953         }\r
954 \r
955 //bad:\r
956         blockDev.state &= ~(DISK_PRESENT | DISK_INITIALISED);\r
957 \r
958         sdDev.capacity = 0;\r
959 \r
960 out:\r
961         s2s_ledOff();\r
962         return result;\r
963 }\r
964 \r
965 #if 0\r
966 void sdWriteMultiSectorPrep(uint32_t sdLBA, uint32_t sdSectors)\r
967 {\r
968         uint32_t tmpNextLBA = sdLBA + sdSectors;\r
969 \r
970         if (!sdDev.ccs)\r
971         {\r
972                 sdLBA = sdLBA * SD_SECTOR_SIZE;\r
973                 tmpNextLBA = tmpNextLBA * SD_SECTOR_SIZE;\r
974         }\r
975 \r
976         if (sdCmdState == CMD_STATE_WRITE && sdCmdNextLBA == sdLBA)\r
977         {\r
978                 // Well, that was lucky. We're already writing this data\r
979                 sdCmdNextLBA = tmpNextLBA;\r
980                 sdCmdTime = getTime_ms();\r
981         }\r
982         else\r
983         {\r
984                 sdPreCmdState(CMD_STATE_WRITE);\r
985 \r
986                 // Set the number of blocks to pre-erase by the multiple block write\r
987                 // command. We don't care about the response - if the command is not\r
988                 // accepted, writes will just be a bit slower. Max 22bit parameter.\r
989                 uint32 blocks = sdSectors > 0x7FFFFF ? 0x7FFFFF : sdSectors;\r
990                 sdCommandAndResponse(SD_APP_CMD, 0);\r
991                 sdCommandAndResponse(SD_APP_SET_WR_BLK_ERASE_COUNT, blocks);\r
992 \r
993                 uint8_t v = sdCommandAndResponse(SD_WRITE_MULTIPLE_BLOCK, sdLBA);\r
994                 if (unlikely(v))\r
995                 {\r
996                         scsiDiskReset();\r
997                         sdClearStatus();\r
998                         scsiDev.status = CHECK_CONDITION;\r
999                         scsiDev.target->sense.code = HARDWARE_ERROR;\r
1000                         scsiDev.target->sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
1001                         scsiDev.phase = STATUS;\r
1002                 }\r
1003                 else\r
1004                 {\r
1005                         sdCmdTime = getTime_ms();\r
1006                         sdCmdNextLBA = tmpNextLBA;\r
1007                         sdCmdState = CMD_STATE_WRITE;\r
1008                 }\r
1009         }\r
1010 }\r
1011 \r
1012 void sdPoll()\r
1013 {\r
1014         if ((scsiDev.phase == BUS_FREE) &&\r
1015                 (sdCmdState != CMD_STATE_IDLE) &&\r
1016                 (elapsedTime_ms(sdCmdTime) >= 50))\r
1017         {\r
1018                 sdPreCmdState(CMD_STATE_IDLE);\r
1019         }\r
1020 }\r
1021 \r
1022 void sdCheckPresent()\r
1023 {\r
1024         // Check if there's an SD card present.\r
1025         if ((scsiDev.phase == BUS_FREE) &&\r
1026                 (sdIOState == SD_IDLE) &&\r
1027                 (sdCmdState == CMD_STATE_IDLE))\r
1028         {\r
1029                 // The CS line is pulled high by the SD card.\r
1030                 // De-assert the line, and check if it's high.\r
1031                 // This isn't foolproof as it'll be left floating without\r
1032                 // an SD card. We can't use the built-in pull-down resistor as it will\r
1033                 // overpower the SD pullup resistor.\r
1034                 SD_CS_Write(0);\r
1035                 SD_CS_SetDriveMode(SD_CS_DM_DIG_HIZ);\r
1036 \r
1037                 // Delay extended to work with 60cm cables running cards at 2.85V\r
1038                 CyDelayCycles(128);\r
1039                 uint8_t cs = SD_CS_Read();\r
1040                 SD_CS_SetDriveMode(SD_CS_DM_STRONG)     ;\r
1041 \r
1042                 if (cs && !(blockDev.state & DISK_PRESENT))\r
1043                 {\r
1044                         static int firstInit = 1;\r
1045 \r
1046                         // Debounce\r
1047                         CyDelay(250);\r
1048 \r
1049                         if (sdInit())\r
1050                         {\r
1051                                 blockDev.state |= DISK_PRESENT | DISK_INITIALISED;\r
1052 \r
1053                                 // Always "start" the device. Many systems (eg. Apple System 7)\r
1054                                 // won't respond properly to\r
1055                                 // LOGICAL_UNIT_NOT_READY_INITIALIZING_COMMAND_REQUIRED sense\r
1056                                 // code, even if they stopped it first with\r
1057                                 // START STOP UNIT command.\r
1058                                 blockDev.state |= DISK_STARTED;\r
1059 \r
1060                                 if (!firstInit)\r
1061                                 {\r
1062                                         int i;\r
1063                                         for (i = 0; i < MAX_SCSI_TARGETS; ++i)\r
1064                                         {\r
1065                                                 scsiDev.targets[i].unitAttention = PARAMETERS_CHANGED;\r
1066                                         }\r
1067                                 }\r
1068                                 firstInit = 0;\r
1069                         }\r
1070                 }\r
1071                 else if (!cs && (blockDev.state & DISK_PRESENT))\r
1072                 {\r
1073                         sdDev.capacity = 0;\r
1074                         blockDev.state &= ~DISK_PRESENT;\r
1075                         blockDev.state &= ~DISK_INITIALISED;\r
1076                         int i;\r
1077                         for (i = 0; i < MAX_SCSI_TARGETS; ++i)\r
1078                         {\r
1079                                 scsiDev.targets[i].unitAttention = PARAMETERS_CHANGED;\r
1080                         }\r
1081                 }\r
1082         }\r
1083 }\r
1084 \r
1085 #endif\r