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