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