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