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