fb07bb9f4d17cbf16b31b9d206351e40647b53db
[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 \r
25 #include "scsiPhy.h"\r
26 \r
27 #include <string.h>\r
28 \r
29 // Global\r
30 SdDevice sdDev;\r
31 \r
32 static uint8 sdCrc7(uint8* chr, uint8 cnt, uint8 crc)\r
33 {\r
34         uint8 a;\r
35         for(a = 0; a < cnt; a++)\r
36         {\r
37                 uint8 Data = chr[a];\r
38                 uint8 i;\r
39                 for(i = 0; i < 8; i++)\r
40                 {\r
41                         crc <<= 1;\r
42                         if( (Data & 0x80) ^ (crc & 0x80) ) {crc ^= 0x09;}\r
43                         Data <<= 1;\r
44                 }\r
45         }\r
46         return crc & 0x7F;\r
47 }\r
48 \r
49 // Read and write 1 byte.\r
50 static uint8 sdSpiByte(uint8 value)\r
51 {\r
52         SDCard_WriteTxData(value);\r
53         while (!(SDCard_ReadRxStatus() & SDCard_STS_RX_FIFO_NOT_EMPTY)) {}\r
54         return SDCard_ReadRxData();\r
55 }\r
56 \r
57 static void sdSendCRCCommand(uint8 cmd, uint32 param)\r
58 {\r
59         uint8 send[6];\r
60 \r
61         send[0] = cmd | 0x40;\r
62         send[1] = param >> 24;\r
63         send[2] = param >> 16;\r
64         send[3] = param >> 8;\r
65         send[4] = param;\r
66         send[5] = (sdCrc7(send, 5, 0) << 1) | 1;\r
67 \r
68         for(cmd = 0; cmd < sizeof(send); cmd++)\r
69         {\r
70                 sdSpiByte(send[cmd]);\r
71         }\r
72         // Allow command to process before reading result code.\r
73         sdSpiByte(0xFF);\r
74 }\r
75 \r
76 static void sdSendCommand(uint8 cmd, uint32 param)\r
77 {\r
78         uint8 send[6];\r
79 \r
80         send[0] = cmd | 0x40;\r
81         send[1] = param >> 24;\r
82         send[2] = param >> 16;\r
83         send[3] = param >> 8;\r
84         send[4] = param;\r
85         send[5] = 0;\r
86 \r
87         for(cmd = 0; cmd < sizeof(send); cmd++)\r
88         {\r
89                 sdSpiByte(send[cmd]);\r
90         }\r
91         // Allow command to process before reading result code.\r
92         sdSpiByte(0xFF);\r
93 }\r
94 \r
95 static uint8 sdReadResp()\r
96 {\r
97         uint8 v;\r
98         uint8 i = 128;\r
99         do\r
100         {\r
101                 v = sdSpiByte(0xFF);\r
102         } while(i-- && (v & 0x80));\r
103         return v;\r
104 }\r
105 \r
106 static uint8 sdCommandAndResponse(uint8 cmd, uint32 param)\r
107 {\r
108         sdSpiByte(0xFF);\r
109         sdSendCommand(cmd, param);\r
110         return sdReadResp();\r
111 }\r
112 \r
113 static uint8 sdCRCCommandAndResponse(uint8 cmd, uint32 param)\r
114 {\r
115         sdSpiByte(0xFF);\r
116         sdSendCRCCommand(cmd, param);\r
117         return sdReadResp();\r
118 }\r
119 \r
120 // Clear the sticky status bits on error.\r
121 static void sdClearStatus()\r
122 {\r
123         uint8 r2hi = sdCRCCommandAndResponse(SD_SEND_STATUS, 0);\r
124         uint8 r2lo = sdSpiByte(0xFF);\r
125         (void) r2hi; (void) r2lo;\r
126 }\r
127 \r
128 \r
129 void sdPrepareRead()\r
130 {\r
131         uint8 v;\r
132         uint32 scsiLBA = (transfer.lba + transfer.currentBlock);\r
133         uint32 sdLBA = SCSISector2SD(scsiLBA);\r
134         \r
135         if (!sdDev.ccs)\r
136         {\r
137                 sdLBA = sdLBA * SD_SECTOR_SIZE;\r
138         }\r
139         v = sdCommandAndResponse(SD_READ_MULTIPLE_BLOCK, sdLBA);\r
140         if (v)\r
141         {\r
142                 scsiDiskReset();\r
143                 sdClearStatus();\r
144 \r
145                 scsiDev.status = CHECK_CONDITION;\r
146                 scsiDev.sense.code = HARDWARE_ERROR;\r
147                 scsiDev.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
148                 scsiDev.phase = STATUS;\r
149         }\r
150         else\r
151         {\r
152                 transfer.inProgress = 1;\r
153         }\r
154 }\r
155 \r
156 static void doReadSector(uint32_t numBytes)\r
157 {\r
158         int prep, i, guard;\r
159 \r
160         // Wait for a start-block token.\r
161         // Don't wait more than 100ms, which is the timeout recommended\r
162         // in the standard.\r
163         //100ms @ 64Hz = 6400000\r
164         int maxWait = 6400000;\r
165         uint8 token = sdSpiByte(0xFF);\r
166         while (token != 0xFE && (maxWait-- > 0))\r
167         {\r
168                 token = sdSpiByte(0xFF);\r
169         }\r
170         if (token != 0xFE)\r
171         {\r
172                 if (transfer.multiBlock)\r
173                 {\r
174                         sdCompleteRead();\r
175                 }\r
176                 if (scsiDev.status != CHECK_CONDITION)\r
177                 {\r
178                         scsiDev.status = CHECK_CONDITION;\r
179                         scsiDev.sense.code = HARDWARE_ERROR;\r
180                         scsiDev.sense.asc = UNRECOVERED_READ_ERROR;\r
181                         scsiDev.phase = STATUS;\r
182                 }\r
183                 return;\r
184         }\r
185 \r
186         scsiEnterPhase(DATA_IN);\r
187 \r
188         // Quickly seed the FIFO\r
189         prep = 4;\r
190         CY_SET_REG8(SDCard_TXDATA_PTR, 0xFF); // Put a byte in the FIFO\r
191         CY_SET_REG8(SDCard_TXDATA_PTR, 0xFF); // Put a byte in the FIFO\r
192         CY_SET_REG8(SDCard_TXDATA_PTR, 0xFF); // Put a byte in the FIFO\r
193         CY_SET_REG8(SDCard_TXDATA_PTR, 0xFF); // Put a byte in the FIFO\r
194 \r
195         i = 0;\r
196         guard = 0;\r
197 \r
198         // This loop is critically important for performance.\r
199         // We stream data straight from the SDCard fifos into the SCSI component\r
200         // FIFO's. If the loop isn't fast enough, the transmit FIFO's will empty,\r
201         // and performance will suffer. Every clock cycle counts.\r
202         while (i < numBytes && !scsiDev.resetFlag)\r
203         {\r
204                 uint8_t sdRxStatus = CY_GET_REG8(SDCard_RX_STATUS_PTR);\r
205                 uint8_t scsiStatus = CY_GET_REG8(scsiTarget_StatusReg__STATUS_REG);\r
206 \r
207                 // Read from the SPIM fifo if there is room to stream the byte to the\r
208                 // SCSI fifos\r
209                 if((sdRxStatus & SDCard_STS_RX_FIFO_NOT_EMPTY) &&\r
210                         (scsiDev.resetFlag || (scsiStatus & 1)) // SCSI TX FIFO NOT FULL\r
211                         )\r
212                 {\r
213                         uint8_t val = CY_GET_REG8(SDCard_RXDATA_PTR);\r
214                         CY_SET_REG8(scsiTarget_datapath__F0_REG, val);\r
215                         guard++;\r
216                 }\r
217 \r
218                 // Byte has been sent out the SCSI interface.\r
219                 if (scsiDev.resetFlag || (scsiStatus & 2)) // SCSI RX FIFO NOT EMPTY\r
220                 {\r
221                         CY_GET_REG8(scsiTarget_datapath__F1_REG);\r
222                         ++i;\r
223                 }\r
224 \r
225                 // How many bytes are in a 4-byte FIFO ? 5.  4 FIFO bytes PLUS one byte\r
226                 // being processed bit-by-bit. Artifically limit the number of bytes in the \r
227                 // "combined" SPIM TX and RX FIFOS to the individual FIFO size.\r
228                 // Unlike the SCSI component, SPIM doesn't check if there's room in\r
229                 // the output FIFO before starting to transmit.\r
230                 if ((prep - guard < 4) && (prep < numBytes))\r
231                 {\r
232                         CY_SET_REG8(SDCard_TXDATA_PTR, 0xFF); // Put a byte in the FIFO\r
233                         prep++;\r
234                 }\r
235         }\r
236 \r
237         // Read and discard remaining bytes.\r
238         while (i < SD_SECTOR_SIZE)\r
239         {\r
240                 uint8_t sdRxStatus = CY_GET_REG8(SDCard_RX_STATUS_PTR);\r
241                 if(sdRxStatus & SDCard_STS_RX_FIFO_NOT_EMPTY)\r
242                 {\r
243                         CY_GET_REG8(SDCard_RXDATA_PTR);\r
244                         guard++;\r
245                         i++;\r
246                 }\r
247 \r
248                 if ((prep - guard < 4) && (prep < SD_SECTOR_SIZE))\r
249                 {\r
250                         CY_SET_REG8(SDCard_TXDATA_PTR, 0xFF); // Put a byte in the FIFO\r
251                         prep++;\r
252                 }\r
253         }\r
254 \r
255         sdSpiByte(0xFF); // CRC\r
256         sdSpiByte(0xFF); // CRC\r
257         scsiDev.dataLen = numBytes;\r
258         scsiDev.dataPtr = numBytes;\r
259         \r
260         while (SCSI_ReadPin(SCSI_In_ACK) && !scsiDev.resetFlag) {}\r
261 }\r
262 \r
263 static void doReadSectorSingle(uint32 sdBlock, int sdBytes)\r
264 {\r
265         uint8 v;\r
266         if (!sdDev.ccs)\r
267         {\r
268                 sdBlock = sdBlock * SD_SECTOR_SIZE;\r
269         }       \r
270         v = sdCommandAndResponse(SD_READ_SINGLE_BLOCK, sdBlock);\r
271         if (v)\r
272         {\r
273                 scsiDiskReset();\r
274                 sdClearStatus();\r
275 \r
276                 scsiDev.status = CHECK_CONDITION;\r
277                 scsiDev.sense.code = HARDWARE_ERROR;\r
278                 scsiDev.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
279                 scsiDev.phase = STATUS;\r
280         }\r
281         else\r
282         {\r
283                 doReadSector(sdBytes);\r
284         }\r
285 }\r
286 \r
287 \r
288 void sdReadSectorSingle()\r
289 {\r
290         uint32 scsiLBA = (transfer.lba + transfer.currentBlock);\r
291         uint32 sdLBA = SCSISector2SD(scsiLBA);\r
292         \r
293         int sdSectors = SDSectorsPerSCSISector();\r
294         int i;\r
295         for (i = 0; (i < sdSectors - 1) && (scsiDev.status != CHECK_CONDITION); ++i)\r
296         {\r
297                 doReadSectorSingle(sdLBA + i, SD_SECTOR_SIZE);\r
298         }\r
299 \r
300         if (scsiDev.status != CHECK_CONDITION)\r
301         {\r
302                 int remaining = config->bytesPerSector % SD_SECTOR_SIZE;\r
303                 if (remaining == 0) remaining = SD_SECTOR_SIZE; // Full sector needed.\r
304                 doReadSectorSingle(sdLBA + i, remaining);\r
305         }\r
306 }\r
307 \r
308 void sdReadSectorMulti()\r
309 {\r
310         // Pre: sdPrepareRead called.\r
311         int sdSectors = SDSectorsPerSCSISector();\r
312         int i;\r
313         for (i = 0; (i < sdSectors - 1) && (scsiDev.status != CHECK_CONDITION); ++i)\r
314         {\r
315                 doReadSector(SD_SECTOR_SIZE);\r
316         }\r
317 \r
318         if (scsiDev.status != CHECK_CONDITION)\r
319         {\r
320                 int remaining = config->bytesPerSector % SD_SECTOR_SIZE;\r
321                 if (remaining == 0) remaining = SD_SECTOR_SIZE; // Full sector needed.\r
322                 doReadSector(remaining);\r
323         }\r
324 }\r
325 \r
326 \r
327 void sdCompleteRead()\r
328 {\r
329         transfer.inProgress = 0;\r
330 \r
331         // We cannot send even a single "padding" byte, as we normally would when\r
332         // sending a command.  If we've just finished reading the very last block\r
333         // on the card, then reading an additional dummy byte will just trigger\r
334         // an error condition as we're trying to read past-the-end of the storage\r
335         // device.\r
336         // ie. do not use sdCommandAndResponse here.\r
337         uint8 r1b;\r
338         sdSendCommand(SD_STOP_TRANSMISSION, 0);\r
339         r1b = sdReadResp();\r
340 \r
341         if (r1b)\r
342         {\r
343                 // Try very hard to make sure the transmission stops\r
344                 int retries = 255;\r
345                 while (r1b && retries)\r
346                 {\r
347                         r1b = sdCommandAndResponse(SD_STOP_TRANSMISSION, 0);\r
348                         retries--;\r
349                 }\r
350 \r
351                 scsiDev.status = CHECK_CONDITION;\r
352                 scsiDev.sense.code = HARDWARE_ERROR;\r
353                 scsiDev.sense.asc = UNRECOVERED_READ_ERROR;\r
354                 scsiDev.phase = STATUS;\r
355         }\r
356 \r
357         // R1b has an optional trailing "busy" signal.\r
358         {\r
359                 uint8 busy;\r
360                 do\r
361                 {\r
362                         busy = sdSpiByte(0xFF);\r
363                 } while (busy == 0);\r
364         }\r
365 }\r
366 \r
367 static void sdWaitWriteBusy()\r
368 {\r
369         uint8 val;\r
370         do\r
371         {\r
372                 val = sdSpiByte(0xFF);\r
373         } while (val != 0xFF);\r
374 }\r
375 \r
376 static int doWriteSector(uint32_t numBytes)\r
377 {\r
378         int prep, i, guard;\r
379         int result, maxWait;\r
380         uint8 dataToken;\r
381 \r
382         scsiEnterPhase(DATA_OUT);\r
383         \r
384         sdSpiByte(0xFC); // MULTIPLE byte start token\r
385         \r
386         prep = 0;\r
387         i = 0;\r
388         guard = 0;\r
389 \r
390         // This loop is critically important for performance.\r
391         // We stream data straight from the SCSI fifos into the SPIM component\r
392         // FIFO's. If the loop isn't fast enough, the transmit FIFO's will empty,\r
393         // and performance will suffer. Every clock cycle counts.       \r
394         while (i < numBytes && !scsiDev.resetFlag)\r
395         {\r
396                 uint8_t sdRxStatus = CY_GET_REG8(SDCard_RX_STATUS_PTR);\r
397                 uint8_t scsiStatus = CY_GET_REG8(scsiTarget_StatusReg__STATUS_REG);\r
398 \r
399                 // Read from the SCSI fifo if there is room to stream the byte to the\r
400                 // SPIM fifos\r
401                 // See sdReadSector for comment on guard (FIFO size is really 5)\r
402                 if((guard - i < 4) &&\r
403                         (scsiDev.resetFlag || (scsiStatus & 2))\r
404                         ) // SCSI RX FIFO NOT EMPTY\r
405                 {\r
406                         uint8_t val = CY_GET_REG8(scsiTarget_datapath__F1_REG);\r
407                         CY_SET_REG8(SDCard_TXDATA_PTR, val);\r
408                         guard++;\r
409                 }\r
410 \r
411                 // Byte has been sent out the SPIM interface.\r
412                 if (sdRxStatus & SDCard_STS_RX_FIFO_NOT_EMPTY)\r
413                 {\r
414                          CY_GET_REG8(SDCard_RXDATA_PTR);\r
415                         ++i;\r
416                 }\r
417 \r
418                 if (prep < numBytes &&\r
419                         (scsiDev.resetFlag || (scsiStatus & 1)) // SCSI TX FIFO NOT FULL\r
420                         )\r
421                 {\r
422                         // Trigger the SCSI component to read a byte\r
423                         CY_SET_REG8(scsiTarget_datapath__F0_REG, 0xFF);\r
424                         prep++;\r
425                 }\r
426         }\r
427         \r
428         // Write remaining bytes as 0x00\r
429         while (i < SD_SECTOR_SIZE)\r
430         {\r
431                 uint8_t sdRxStatus = CY_GET_REG8(SDCard_RX_STATUS_PTR);\r
432 \r
433                 if(guard - i < 4)\r
434                 {\r
435                         CY_SET_REG8(SDCard_TXDATA_PTR, 0x00);\r
436                         guard++;\r
437                 }\r
438 \r
439                 // Byte has been sent out the SPIM interface.\r
440                 if (sdRxStatus & SDCard_STS_RX_FIFO_NOT_EMPTY)\r
441                 {\r
442                          CY_GET_REG8(SDCard_RXDATA_PTR);\r
443                         ++i;\r
444                 }\r
445         }\r
446         \r
447         sdSpiByte(0x00); // CRC\r
448         sdSpiByte(0x00); // CRC\r
449 \r
450         // Don't wait more than 1s.\r
451         // My 2g Kingston micro-sd card doesn't respond immediately.\r
452         // My 16Gb card does.\r
453         maxWait = 1000000;\r
454         dataToken = sdSpiByte(0xFF); // Response\r
455         while (dataToken == 0xFF && maxWait-- > 0)\r
456         {\r
457                 CyDelayUs(1);\r
458                 dataToken = sdSpiByte(0xFF);\r
459         }\r
460         if (((dataToken & 0x1F) >> 1) != 0x2) // Accepted.\r
461         {\r
462                 uint8 r1b, busy;\r
463                 \r
464                 sdWaitWriteBusy();\r
465 \r
466                 r1b = sdCommandAndResponse(SD_STOP_TRANSMISSION, 0);\r
467                 (void) r1b;\r
468                 sdSpiByte(0xFF);\r
469 \r
470                 // R1b has an optional trailing "busy" signal.\r
471                 do\r
472                 {\r
473                         busy = sdSpiByte(0xFF);\r
474                 } while (busy == 0);\r
475 \r
476                 // Wait for the card to come out of busy.\r
477                 sdWaitWriteBusy();\r
478 \r
479                 transfer.inProgress = 0;\r
480                 scsiDiskReset();\r
481                 sdClearStatus();\r
482 \r
483                 scsiDev.status = CHECK_CONDITION;\r
484                 scsiDev.sense.code = HARDWARE_ERROR;\r
485                 scsiDev.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
486                 scsiDev.phase = STATUS;\r
487                 result = 0;\r
488         }\r
489         else\r
490         {\r
491                 sdWaitWriteBusy();\r
492                 result = 1;\r
493         }\r
494 \r
495         while (SCSI_ReadPin(SCSI_In_ACK) && !scsiDev.resetFlag) {}\r
496 \r
497         return result;\r
498 }\r
499 \r
500 int sdWriteSector()\r
501 {\r
502         int result = 1;\r
503         // Pre: sdPrepareWrite called.\r
504         int sdSectors = SDSectorsPerSCSISector();\r
505         int i;\r
506         for (i = 0; result && (i < sdSectors - 1) && (scsiDev.status != CHECK_CONDITION); ++i)\r
507         {\r
508                 result = doWriteSector(SD_SECTOR_SIZE);\r
509         }\r
510 \r
511         if (result && scsiDev.status != CHECK_CONDITION)\r
512         {\r
513                 int remaining = config->bytesPerSector % SD_SECTOR_SIZE;\r
514                 if (remaining == 0) remaining = SD_SECTOR_SIZE; // Full sector needed.\r
515                 result = doWriteSector(remaining);\r
516         }\r
517         return result;\r
518 }\r
519 \r
520 void sdCompleteWrite()\r
521 {\r
522         transfer.inProgress = 0;\r
523 \r
524         uint8 r1, r2;\r
525 \r
526         sdSpiByte(0xFD); // STOP TOKEN\r
527         // Wait for the card to come out of busy.\r
528         sdWaitWriteBusy();\r
529 \r
530         r1 = sdCommandAndResponse(13, 0); // send status\r
531         r2 = sdSpiByte(0xFF);\r
532         if (r1 || r2)\r
533         {\r
534                 sdClearStatus();\r
535                 scsiDev.status = CHECK_CONDITION;\r
536                 scsiDev.sense.code = HARDWARE_ERROR;\r
537                 scsiDev.sense.asc = WRITE_ERROR_AUTO_REALLOCATION_FAILED;\r
538                 scsiDev.phase = STATUS;\r
539         }\r
540 }\r
541 \r
542 \r
543 // SD Version 2 (SDHC) support\r
544 static int sendIfCond()\r
545 {\r
546         int retries = 50;\r
547 \r
548         do\r
549         {\r
550                 uint8 status = sdCRCCommandAndResponse(SD_SEND_IF_COND, 0x000001AA);\r
551 \r
552                 if (status == SD_R1_IDLE)\r
553                 {\r
554                         // Version 2 card.\r
555                         sdDev.version = 2;\r
556                         // Read 32bit response. Should contain the same bytes that\r
557                         // we sent in the command parameter.\r
558                         sdSpiByte(0xFF);\r
559                         sdSpiByte(0xFF);\r
560                         sdSpiByte(0xFF);\r
561                         sdSpiByte(0xFF);\r
562                         break;\r
563                 }\r
564                 else if (status & SD_R1_ILLEGAL)\r
565                 {\r
566                         // Version 1 card.\r
567                         sdDev.version = 1;\r
568                         sdClearStatus();\r
569                         break;\r
570                 }\r
571 \r
572                 sdClearStatus();\r
573         } while (--retries > 0);\r
574 \r
575         return retries > 0;\r
576 }\r
577 \r
578 static int sdOpCond()\r
579 {\r
580         int retries = 50;\r
581 \r
582         uint8 status;\r
583         do\r
584         {\r
585                 CyDelay(33); // Spec says to retry for 1 second.\r
586 \r
587                 sdCRCCommandAndResponse(SD_APP_CMD, 0);\r
588                 // Host Capacity Support = 1 (SDHC/SDXC supported)\r
589                 status = sdCRCCommandAndResponse(SD_APP_SEND_OP_COND, 0x40000000);\r
590 \r
591                 sdClearStatus();\r
592         } while ((status != 0) && (--retries > 0));\r
593 \r
594         return retries > 0;\r
595 }\r
596 \r
597 static int sdReadOCR()\r
598 {\r
599         uint8 buf[4];\r
600         int i;\r
601         \r
602         uint8 status = sdCRCCommandAndResponse(SD_READ_OCR, 0);\r
603         if(status){goto bad;}\r
604 \r
605         for (i = 0; i < 4; ++i)\r
606         {\r
607                 buf[i] = sdSpiByte(0xFF);\r
608         }\r
609 \r
610         sdDev.ccs = (buf[0] & 0x40) ? 1 : 0;\r
611 \r
612         return 1;\r
613 bad:\r
614         return 0;\r
615 }\r
616 \r
617 static int sdReadCSD()\r
618 {\r
619         uint8 startToken;\r
620         int maxWait, i;\r
621         uint8 buf[16];\r
622         \r
623         uint8 status = sdCRCCommandAndResponse(SD_SEND_CSD, 0);\r
624         if(status){goto bad;}\r
625 \r
626         maxWait = 1023;\r
627         do\r
628         {\r
629                 startToken = sdSpiByte(0xFF);\r
630         } while(maxWait-- && (startToken != 0xFE));\r
631         if (startToken != 0xFE) { goto bad; }\r
632 \r
633         for (i = 0; i < 16; ++i)\r
634         {\r
635                 buf[i] = sdSpiByte(0xFF);\r
636         }\r
637         sdSpiByte(0xFF); // CRC\r
638         sdSpiByte(0xFF); // CRC\r
639 \r
640         if ((buf[0] >> 6) == 0x00)\r
641         {\r
642                 // CSD version 1\r
643                 // C_SIZE in bits [73:62]\r
644                 uint32 c_size = (((((uint32)buf[6]) & 0x3) << 16) | (((uint32)buf[7]) << 8) | buf[8]) >> 6;\r
645                 uint32 c_mult = (((((uint32)buf[9]) & 0x3) << 8) | ((uint32)buf[0xa])) >> 7;\r
646                 uint32 sectorSize = buf[5] & 0x0F;\r
647                 sdDev.capacity = ((c_size+1) * ((uint64)1 << (c_mult+2)) * ((uint64)1 << sectorSize)) / SD_SECTOR_SIZE;\r
648         }\r
649         else if ((buf[0] >> 6) == 0x01)\r
650         {\r
651                 // CSD version 2\r
652                 // C_SIZE in bits [69:48]\r
653 \r
654                 uint32 c_size =\r
655                         ((((uint32)buf[7]) & 0x3F) << 16) |\r
656                         (((uint32)buf[8]) << 8) |\r
657                         ((uint32)buf[7]);\r
658                 sdDev.capacity = (c_size + 1) * 1024;\r
659         }\r
660         else\r
661         {\r
662                 goto bad;\r
663         }\r
664 \r
665         return 1;\r
666 bad:\r
667         return 0;\r
668 }\r
669 \r
670 int sdInit()\r
671 {\r
672         int result = 0;\r
673         int i;\r
674         uint8 v;\r
675         \r
676         sdDev.version = 0;\r
677         sdDev.ccs = 0;\r
678         sdDev.capacity = 0;\r
679 \r
680         SD_CS_Write(1); // Set CS inactive (active low)\r
681         SD_Init_Clk_Start(); // Turn on the slow 400KHz clock\r
682         SD_Clk_Ctl_Write(0); // Select the 400KHz clock source.\r
683         SDCard_Start(); // Enable SPI hardware\r
684 \r
685         // Power on sequence. 74 clock cycles of a "1" while CS unasserted.\r
686         for (i = 0; i < 10; ++i)\r
687         {\r
688                 sdSpiByte(0xFF);\r
689         }\r
690 \r
691         SD_CS_Write(0); // Set CS active (active low)\r
692         CyDelayUs(1);\r
693 \r
694         v = sdCRCCommandAndResponse(SD_GO_IDLE_STATE, 0);\r
695         if(v != 1){goto bad;}\r
696 \r
697         ledOn();\r
698         if (!sendIfCond()) goto bad; // Sets V1 or V2 flag\r
699         if (!sdOpCond()) goto bad;\r
700         if (!sdReadOCR()) goto bad;\r
701 \r
702         // This command will be ignored if sdDev.ccs is set.\r
703         // SDHC and SDXC are always 512bytes.\r
704         v = sdCRCCommandAndResponse(SD_SET_BLOCKLEN, SD_SECTOR_SIZE); //Force sector size\r
705         if(v){goto bad;}\r
706         v = sdCRCCommandAndResponse(SD_CRC_ON_OFF, 0); //crc off\r
707         if(v){goto bad;}\r
708 \r
709         // now set the sd card up for full speed\r
710         // The SD Card spec says we can run SPI @ 25MHz\r
711         // But the PSoC 5LP SPIM datasheet says the most we can do is 18MHz.\r
712         // I've confirmed that no data is ever put into the RX FIFO when run at\r
713         // 20MHz or 25MHz.\r
714         // ... and then we get timing analysis failures if the BUS_CLK is over 62MHz.\r
715         // So we run the MASTER_CLK and BUS_CLK at 60MHz, and run the SPI clock at 30MHz\r
716         // (15MHz SPI transfer clock).\r
717         SDCard_Stop();\r
718         \r
719         // We can't run at full-speed with the pullup resistors enabled.\r
720         SD_MISO_SetDriveMode(SD_MISO_DM_DIG_HIZ);\r
721         SD_MOSI_SetDriveMode(SD_MOSI_DM_STRONG);\r
722         SD_SCK_SetDriveMode(SD_SCK_DM_STRONG);\r
723         \r
724         SD_Data_Clk_Start(); // Turn on the fast clock\r
725         SD_Clk_Ctl_Write(1); // Select the fast clock source.\r
726         SD_Init_Clk_Stop(); // Stop the slow clock.\r
727         CyDelayUs(1);\r
728         SDCard_Start();\r
729 \r
730         // Clear out rubbish data through clock change\r
731         CyDelayUs(1);\r
732         SDCard_ReadRxStatus();\r
733         SDCard_ReadTxStatus();\r
734         SDCard_ClearFIFO();\r
735 \r
736         if (!sdReadCSD()) goto bad;\r
737 \r
738         result = 1;\r
739         goto out;\r
740 \r
741 bad:\r
742         sdDev.capacity = 0;\r
743 \r
744 out:\r
745         sdClearStatus();\r
746         ledOff();\r
747         return result;\r
748 \r
749 }\r
750 \r
751 void sdPrepareWrite()\r
752 {\r
753         uint8 v;\r
754         \r
755         // Set the number of blocks to pre-erase by the multiple block write command\r
756         // We don't care about the response - if the command is not accepted, writes\r
757         // will just be a bit slower.\r
758         // Max 22bit parameter.\r
759         uint32_t sdBlocks = transfer.blocks * SDSectorsPerSCSISector();\r
760         uint32 blocks = sdBlocks > 0x7FFFFF ? 0x7FFFFF : sdBlocks;\r
761         sdCommandAndResponse(SD_APP_CMD, 0);\r
762         sdCommandAndResponse(SD_APP_SET_WR_BLK_ERASE_COUNT, blocks);\r
763 \r
764         uint32 scsiLBA = (transfer.lba + transfer.currentBlock);\r
765         uint32 sdLBA = SCSISector2SD(scsiLBA);\r
766         if (!sdDev.ccs)\r
767         {\r
768                 sdLBA = sdLBA * SD_SECTOR_SIZE;\r
769         }\r
770         v = sdCommandAndResponse(25, sdLBA);\r
771         if (v)\r
772         {\r
773                 scsiDiskReset();\r
774                 sdClearStatus();\r
775                 scsiDev.status = CHECK_CONDITION;\r
776                 scsiDev.sense.code = HARDWARE_ERROR;\r
777                 scsiDev.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
778                 scsiDev.phase = STATUS;\r
779         }\r
780         else\r
781         {\r
782                 transfer.inProgress = 1;\r
783         }\r
784 }\r
785 \r