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