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