]> git.sur5r.net Git - freertos/blob - Demo/CORTEX_AT91SAM3U256_IAR/AT91Lib/peripherals/mci/mci.c
Start to re-arrange files to include FreeRTOS+ in main download.
[freertos] / Demo / CORTEX_AT91SAM3U256_IAR / AT91Lib / peripherals / mci / mci.c
1 /* ----------------------------------------------------------------------------\r
2  *         ATMEL Microcontroller Software Support\r
3  * ----------------------------------------------------------------------------\r
4  * Copyright (c) 2008, Atmel Corporation\r
5  *\r
6  * All rights reserved.\r
7  *\r
8  * Redistribution and use in source and binary forms, with or without\r
9  * modification, are permitted provided that the following conditions are met:\r
10  *\r
11  * - Redistributions of source code must retain the above copyright notice,\r
12  * this list of conditions and the disclaimer below.\r
13  *\r
14  * Atmel's name may not be used to endorse or promote products derived from\r
15  * this software without specific prior written permission.\r
16  *\r
17  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR\r
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
20  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,\r
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
23  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
24  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
25  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
26  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
27  * ----------------------------------------------------------------------------\r
28  */\r
29 \r
30 //------------------------------------------------------------------------------\r
31 //         Headers\r
32 //------------------------------------------------------------------------------\r
33 \r
34 #include "mci.h"\r
35 #include <utility/assert.h>\r
36 #include <utility/trace.h>\r
37 \r
38 //------------------------------------------------------------------------------\r
39 //         Local constants\r
40 //------------------------------------------------------------------------------\r
41 \r
42 /// Bit mask for status register errors.\r
43 #define STATUS_ERRORS (AT91C_MCI_UNRE  \\r
44                        | AT91C_MCI_OVRE \\r
45                        | AT91C_MCI_DTOE \\r
46                        | AT91C_MCI_DCRCE \\r
47                        | AT91C_MCI_RTOE \\r
48                        | AT91C_MCI_RENDE \\r
49                        | AT91C_MCI_RCRCE \\r
50                        | AT91C_MCI_RDIRE \\r
51                        | AT91C_MCI_RINDE)\r
52 \r
53 /// MCI data timeout configuration with 1048576 MCK cycles between 2 data transfers.\r
54 #define DTOR_1MEGA_CYCLES           (AT91C_MCI_DTOCYC | AT91C_MCI_DTOMUL)\r
55 \r
56 /// MCI MR: disable MCI Clock when FIFO is full\r
57 #ifndef AT91C_MCI_WRPROOF\r
58     #define AT91C_MCI_WRPROOF 0\r
59 #endif\r
60 #ifndef AT91C_MCI_RDPROOF\r
61     #define AT91C_MCI_RDPROOF 0\r
62 #endif\r
63 \r
64 #define SDCARD_APP_OP_COND_CMD      (41 | AT91C_MCI_SPCMD_NONE  | AT91C_MCI_RSPTYP_48   | AT91C_MCI_TRCMD_NO )\r
65 #define MMC_SEND_OP_COND_CMD        (1  | AT91C_MCI_TRCMD_NO    | AT91C_MCI_SPCMD_NONE  | AT91C_MCI_RSPTYP_48 | AT91C_MCI_OPDCMD)\r
66 \r
67 \r
68 #define DISABLE    0    // Disable MCI interface\r
69 #define ENABLE     1    // Enable MCI interface\r
70 \r
71 \r
72 //------------------------------------------------------------------------------\r
73 //         Local macros\r
74 //------------------------------------------------------------------------------\r
75 \r
76 /// Used to write in PMC registers.\r
77 #define WRITE_PMC(pPmc, regName, value)     pPmc->regName = (value)\r
78 \r
79 /// Used to write in MCI registers.\r
80 #define WRITE_MCI(pMci, regName, value)     pMci->regName = (value)\r
81 \r
82 /// Used to read from MCI registers.\r
83 #define READ_MCI(pMci, regName)             (pMci->regName)\r
84 \r
85 //------------------------------------------------------------------------------\r
86 //         Global functions\r
87 //------------------------------------------------------------------------------\r
88 \r
89 //------------------------------------------------------------------------------\r
90 /// Enable/disable a MCI driver instance.\r
91 /// \param pMci  Pointer to a MCI driver instance.\r
92 /// \param enb  0 for disable MCI and 1 for enable MCI.\r
93 //------------------------------------------------------------------------------\r
94 void MCI_Enable(Mci *pMci, unsigned char enb)\r
95 {\r
96     AT91S_MCI *pMciHw = pMci->pMciHw;\r
97 \r
98     SANITY_CHECK(pMci);\r
99     SANITY_CHECK(pMci->pMciHw);\r
100 \r
101     // Set the Control Register: Enable/Disable MCI interface clock\r
102     if(enb == DISABLE) {\r
103         WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIDIS);\r
104     }\r
105     else {\r
106         WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIEN);\r
107     }\r
108 }\r
109 \r
110 //------------------------------------------------------------------------------\r
111 /// Initializes a MCI driver instance and the underlying peripheral.\r
112 /// \param pMci  Pointer to a MCI driver instance.\r
113 /// \param pMciHw  Pointer to a MCI peripheral.\r
114 /// \param mciId  MCI peripheral identifier.\r
115 /// \param mode  Slot and type of connected card.\r
116 //------------------------------------------------------------------------------\r
117 void MCI_Init(\r
118     Mci *pMci,\r
119     AT91S_MCI *pMciHw,\r
120     unsigned char mciId,\r
121     unsigned int mode)\r
122 {\r
123     unsigned short clkDiv;\r
124 \r
125     SANITY_CHECK(pMci);\r
126     SANITY_CHECK(pMciHw);\r
127     SANITY_CHECK((mode == MCI_MMC_SLOTA) || (mode == MCI_MMC_SLOTB)\r
128                  || (mode == MCI_SD_SLOTA) || (mode == MCI_SD_SLOTB));\r
129 \r
130     // Initialize the MCI driver structure\r
131     pMci->pMciHw = pMciHw;\r
132     pMci->mciId  = mciId;\r
133     pMci->semaphore = 1;\r
134     pMci->pCommand = 0;\r
135 \r
136     // Enable the MCI clock\r
137     WRITE_PMC(AT91C_BASE_PMC, PMC_PCER, (1 << mciId));\r
138 \r
139      // Reset the MCI\r
140     WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_SWRST);\r
141 \r
142     // Disable the MCI\r
143     WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIDIS | AT91C_MCI_PWSDIS);\r
144 \r
145     // Disable all the interrupts\r
146     WRITE_MCI(pMciHw, MCI_IDR, 0xFFFFFFFF);\r
147 \r
148     // Set the Data Timeout Register\r
149     WRITE_MCI(pMciHw, MCI_DTOR, DTOR_1MEGA_CYCLES);\r
150 \r
151     // Set the Mode Register: 400KHz for MCK = 48MHz (CLKDIV = 58)\r
152     clkDiv = (BOARD_MCK / (400000 * 2)) - 1;\r
153     WRITE_MCI(pMciHw, MCI_MR, (clkDiv | (AT91C_MCI_PWSDIV & (0x7 << 8))));\r
154 \r
155     // Set the SDCard Register\r
156     WRITE_MCI(pMciHw, MCI_SDCR, mode);\r
157 \r
158     // Enable the MCI and the Power Saving\r
159     WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIEN);\r
160 \r
161     // Disable the MCI peripheral clock.\r
162     WRITE_PMC(AT91C_BASE_PMC, PMC_PCDR, (1 << mciId));\r
163 }\r
164 \r
165 //------------------------------------------------------------------------------\r
166 /// Close a MCI driver instance and the underlying peripheral.\r
167 /// \param pMci  Pointer to a MCI driver instance.\r
168 /// \param pMciHw  Pointer to a MCI peripheral.\r
169 /// \param mciId  MCI peripheral identifier.\r
170 //------------------------------------------------------------------------------\r
171 void MCI_Close(Mci *pMci)\r
172 {\r
173     AT91S_MCI *pMciHw = pMci->pMciHw;\r
174 \r
175     SANITY_CHECK(pMci);\r
176     SANITY_CHECK(pMciHw);\r
177 \r
178     // Initialize the MCI driver structure\r
179     pMci->semaphore = 1;\r
180     pMci->pCommand = 0;\r
181 \r
182     // Disable the MCI peripheral clock.\r
183     WRITE_PMC(AT91C_BASE_PMC, PMC_PCDR, (1 << pMci->mciId));\r
184 \r
185     // Disable the MCI\r
186     WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIDIS);\r
187 \r
188     // Disable all the interrupts\r
189     WRITE_MCI(pMciHw, MCI_IDR, 0xFFFFFFFF);\r
190 }\r
191 \r
192 //------------------------------------------------------------------------------\r
193 /// Configure the  MCI CLKDIV in the MCI_MR register. The max. for MCI clock is\r
194 /// MCK/2 and corresponds to CLKDIV = 0\r
195 /// \param pMci  Pointer to the low level MCI driver.\r
196 /// \param mciSpeed  MCI clock speed in Hz.\r
197 //------------------------------------------------------------------------------\r
198 void MCI_SetSpeed(Mci *pMci, unsigned int mciSpeed)\r
199 {\r
200     AT91S_MCI *pMciHw = pMci->pMciHw;\r
201     unsigned int mciMr;\r
202     unsigned int clkdiv;\r
203 \r
204     SANITY_CHECK(pMci);\r
205     SANITY_CHECK(pMci->pMciHw);\r
206 \r
207     // Set the Mode Register: 400KHz for MCK = 48MHz (CLKDIV = 58)\r
208     mciMr = READ_MCI(pMciHw, MCI_MR) & (~AT91C_MCI_CLKDIV);\r
209 \r
210     // Multimedia Card Interface clock (MCCK or MCI_CK) is Master Clock (MCK)\r
211     // divided by (2*(CLKDIV+1))\r
212     if (mciSpeed > 0) {\r
213 \r
214         clkdiv = (BOARD_MCK / (mciSpeed * 2));\r
215         if (clkdiv > 0) {\r
216 \r
217             clkdiv -= 1;\r
218         }\r
219         ASSERT( (clkdiv & 0xFFFFFF00) == 0, "mciSpeed too small");\r
220     }\r
221     else {\r
222 \r
223         clkdiv = 0;\r
224     }\r
225 \r
226     WRITE_MCI(pMciHw, MCI_MR, mciMr | clkdiv);\r
227 }\r
228 \r
229 //------------------------------------------------------------------------------\r
230 /// Configure the  MCI SDCBUS in the MCI_SDCR register. Only two modes available\r
231 ///\r
232 /// \param pMci  Pointer to the low level MCI driver.\r
233 /// \param busWidth  MCI bus width mode.\r
234 //------------------------------------------------------------------------------\r
235 void MCI_SetBusWidth(Mci *pMci, unsigned char busWidth)\r
236 {\r
237     AT91S_MCI *pMciHw = pMci->pMciHw;\r
238     unsigned int mciSdcr;\r
239 \r
240     SANITY_CHECK(pMci);\r
241     SANITY_CHECK(pMci->pMciHw);\r
242 \r
243     mciSdcr = (READ_MCI(pMciHw, MCI_SDCR) & ~(AT91C_MCI_SCDBUS));\r
244 \r
245     WRITE_MCI(pMciHw, MCI_SDCR, mciSdcr | busWidth);\r
246 }\r
247 \r
248 //------------------------------------------------------------------------------\r
249 /// Starts a MCI  transfer. This is a non blocking function. It will return\r
250 /// as soon as the transfer is started.\r
251 /// Return 0 if successful; otherwise returns MCI_ERROR_LOCK if the driver is\r
252 /// already in use.\r
253 /// \param pMci  Pointer to an MCI driver instance.\r
254 /// \param pCommand  Pointer to the command to execute.\r
255 //------------------------------------------------------------------------------\r
256 unsigned char MCI_SendCommand(Mci *pMci, MciCmd *pCommand)\r
257 {\r
258     AT91PS_MCI pMciHw = pMci->pMciHw;\r
259     unsigned int mciIer, mciMr;\r
260 \r
261     SANITY_CHECK(pMci);\r
262     SANITY_CHECK(pMciHw);\r
263     SANITY_CHECK(pCommand);\r
264 \r
265     // Try to acquire the MCI semaphore\r
266     if (pMci->semaphore == 0) {\r
267 \r
268         return MCI_ERROR_LOCK;\r
269     }\r
270     pMci->semaphore--;\r
271     // TRACE_DEBUG("MCI_SendCommand %x %d\n\r", READ_MCI(pMciHw, MCI_SR), pCommand->cmd & 0x3f);\r
272 \r
273     // Command is now being executed\r
274     pMci->pCommand = pCommand;\r
275     pCommand->status = MCI_STATUS_PENDING;\r
276 \r
277     // Enable the MCI clock\r
278     WRITE_PMC(AT91C_BASE_PMC, PMC_PCER, (1 << pMci->mciId));\r
279 \r
280     //Disable MCI clock, for multi-block data transfer\r
281     MCI_Enable(pMci, DISABLE);\r
282 \r
283     // Set PDC data transfer direction\r
284     if(pCommand->blockSize > 0) {\r
285         if(pCommand->isRead) {\r
286             WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_RXTEN);\r
287         }\r
288         else {\r
289             WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_TXTEN);\r
290         }\r
291     }\r
292     // Disable transmitter and receiver\r
293     WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS);\r
294 \r
295     mciMr = READ_MCI(pMciHw, MCI_MR) & (~(AT91C_MCI_WRPROOF|AT91C_MCI_RDPROOF|AT91C_MCI_BLKLEN | AT91C_MCI_PDCMODE));\r
296 \r
297     // Command with DATA stage\r
298     if (pCommand->blockSize > 0) {\r
299         // Enable PDC mode and set block size\r
300         if(pCommand->conTrans != MCI_CONTINUE_TRANSFER) {\r
301 \r
302             WRITE_MCI(pMciHw, MCI_MR, mciMr | AT91C_MCI_PDCMODE |AT91C_MCI_RDPROOF|AT91C_MCI_WRPROOF|(pCommand->blockSize << 16));\r
303         }\r
304 \r
305         // DATA transfer from card to host\r
306         if (pCommand->isRead) {\r
307             WRITE_MCI(pMciHw, MCI_RPR, (int) pCommand->pData);\r
308 \r
309             // Sanity check\r
310             if (pCommand->nbBlock == 0)\r
311                 pCommand->nbBlock = 1;\r
312             ////////\r
313             if ((pCommand->blockSize & 0x3) != 0) {\r
314                 WRITE_MCI(pMciHw, MCI_RCR, (pCommand->nbBlock * pCommand->blockSize) / 4 + 1);\r
315             }\r
316             else {\r
317                 WRITE_MCI(pMciHw, MCI_RCR, (pCommand->nbBlock * pCommand->blockSize) / 4);\r
318             }\r
319 \r
320             WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_RXTEN);\r
321             mciIer = AT91C_MCI_ENDRX | STATUS_ERRORS;\r
322             // mciIer = AT91C_MCI_RXBUFF | STATUS_ERRORS;\r
323         }\r
324 \r
325         // DATA transfer from host to card\r
326         else {\r
327             // Sanity check\r
328             if (pCommand->nbBlock == 0)\r
329                 pCommand->nbBlock = 1;\r
330             WRITE_MCI(pMciHw, MCI_TPR, (int) pCommand->pData);\r
331             // Update the PDC counter\r
332             if ((pCommand->blockSize & 0x3) != 0) {\r
333                 WRITE_MCI(pMciHw, MCI_TCR, (pCommand->nbBlock * pCommand->blockSize) / 4 + 1);\r
334             }\r
335             else {\r
336                 WRITE_MCI(pMciHw, MCI_TCR, (pCommand->nbBlock * pCommand->blockSize) / 4);\r
337             }\r
338             // MCI_BLKE notifies the end of Multiblock command\r
339             mciIer = AT91C_MCI_BLKE | STATUS_ERRORS;\r
340         }\r
341     }\r
342     // No data transfer: stop at the end of the command\r
343     else {\r
344         WRITE_MCI(pMciHw, MCI_MR, mciMr);\r
345         mciIer = AT91C_MCI_CMDRDY | STATUS_ERRORS;\r
346     }\r
347     // Enable MCI clock\r
348     MCI_Enable(pMci, ENABLE);\r
349 \r
350     // Send the command\r
351     if((pCommand->conTrans != MCI_CONTINUE_TRANSFER)\r
352         || (pCommand->blockSize == 0)) {\r
353 \r
354         WRITE_MCI(pMciHw, MCI_ARGR, pCommand->arg);\r
355         WRITE_MCI(pMciHw, MCI_CMDR, pCommand->cmd);\r
356     }\r
357 \r
358     // In case of transmit, the PDC shall be enabled after sending the command\r
359     if ((pCommand->blockSize > 0) && !(pCommand->isRead)) {\r
360         WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_TXTEN);\r
361     }\r
362 \r
363     // Ignore data error\r
364     mciIer &= ~(AT91C_MCI_UNRE | AT91C_MCI_OVRE \\r
365               | AT91C_MCI_DTOE | AT91C_MCI_DCRCE);\r
366 \r
367     // Interrupt enable shall be done after PDC TXTEN and RXTEN\r
368     WRITE_MCI(pMciHw, MCI_IER, mciIer);\r
369 \r
370     return 0;\r
371 }\r
372 \r
373 //------------------------------------------------------------------------------\r
374 /// Check NOTBUSY and DTIP bits of status register on the given MCI driver.\r
375 /// Return value, 0 for bus ready, 1 for bus busy\r
376 /// \param pMci  Pointer to a MCI driver instance.\r
377 //------------------------------------------------------------------------------\r
378 unsigned char MCI_CheckBusy(Mci *pMci)\r
379 {\r
380     AT91S_MCI *pMciHw = pMci->pMciHw;\r
381     unsigned int status;\r
382 \r
383     // Enable MCI clock\r
384     MCI_Enable(pMci, ENABLE);\r
385 \r
386     status = READ_MCI(pMciHw, MCI_SR);\r
387     // TRACE_DEBUG("status %x\n\r",status);\r
388 \r
389 \r
390     if(((status & AT91C_MCI_NOTBUSY)!=0)\r
391         && ((status & AT91C_MCI_DTIP)==0)) {\r
392 \r
393         // Disable MCI clock\r
394         MCI_Enable(pMci, DISABLE);\r
395 \r
396         return 0;\r
397     }\r
398     else {\r
399         return 1;\r
400     }\r
401 }\r
402 \r
403 //------------------------------------------------------------------------------\r
404 /// Check BLKE bit of status register on the given MCI driver.\r
405 /// \param pMci  Pointer to a MCI driver instance.\r
406 //------------------------------------------------------------------------------\r
407 unsigned char MCI_CheckBlke(Mci *pMci)\r
408 {\r
409     AT91S_MCI *pMciHw = pMci->pMciHw;\r
410     unsigned int status;\r
411 \r
412     status = READ_MCI(pMciHw, MCI_SR);\r
413     // TRACE_DEBUG("status %x\n\r",status);\r
414 \r
415     if((status & AT91C_MCI_BLKE)!=0) {\r
416         return 0;\r
417     }\r
418     else {\r
419         return 1;\r
420     }\r
421 }\r
422 \r
423 //------------------------------------------------------------------------------\r
424 /// Processes pending events on the given MCI driver.\r
425 /// \param pMci  Pointer to a MCI driver instance.\r
426 //------------------------------------------------------------------------------\r
427 void MCI_Handler(Mci *pMci)\r
428 {\r
429     AT91S_MCI *pMciHw = pMci->pMciHw;\r
430     MciCmd *pCommand = pMci->pCommand;\r
431     unsigned int status;\r
432     unsigned char i;\r
433     #if defined(at91rm9200)\r
434     unsigned int mciCr, mciSdcr, mciMr, mciDtor;\r
435     #endif\r
436 \r
437     SANITY_CHECK(pMci);\r
438     SANITY_CHECK(pMciHw);\r
439     SANITY_CHECK(pCommand);\r
440 \r
441     // Read the status register\r
442     status = READ_MCI(pMciHw, MCI_SR) & READ_MCI(pMciHw, MCI_IMR);\r
443     // TRACE_DEBUG("status %x\n\r", status);\r
444 \r
445     // Check if an error has occured\r
446     if ((status & STATUS_ERRORS) != 0) {\r
447 \r
448         // Check error code\r
449         if ((status & STATUS_ERRORS) == AT91C_MCI_RTOE) {\r
450 \r
451             pCommand->status = MCI_STATUS_NORESPONSE;\r
452         }\r
453         // if the command is SEND_OP_COND the CRC error flag is always present\r
454         // (cf : R3 response)\r
455         else if (((status & STATUS_ERRORS) != AT91C_MCI_RCRCE)\r
456                   || ((pCommand->cmd != SDCARD_APP_OP_COND_CMD)\r
457                       && (pCommand->cmd != MMC_SEND_OP_COND_CMD))) {\r
458 \r
459             pCommand->status = MCI_STATUS_ERROR;\r
460         }\r
461     }\r
462 \r
463     // Check if a transfer has been completed\r
464     if (((status & AT91C_MCI_CMDRDY) != 0)\r
465         || ((status & AT91C_MCI_ENDRX) != 0)\r
466         || ((status & AT91C_MCI_RXBUFF) != 0)\r
467         || ((status & AT91C_MCI_ENDTX) != 0)\r
468         || ((status & AT91C_MCI_BLKE) != 0)\r
469         || ((status & AT91C_MCI_RTOE) != 0)) {\r
470 \r
471         if (((status & AT91C_MCI_ENDRX) != 0)\r
472             || ((status & AT91C_MCI_RXBUFF) != 0)\r
473             || ((status & AT91C_MCI_ENDTX) != 0)) {\r
474 \r
475             MCI_Enable(pMci, DISABLE);\r
476         }\r
477 \r
478         /// On AT91RM9200-EK, if stop transmission, software reset MCI.\r
479         #if defined(at91rm9200)\r
480         if ((pCommand->cmd & AT91C_MCI_TRCMD_STOP) != 0) {\r
481             mciMr = READ_MCI(pMciHw, MCI_MR);\r
482             mciSdcr = READ_MCI(pMciHw, MCI_SDCR);\r
483             mciDtor = READ_MCI(pMciHw, MCI_DTOR);\r
484             WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_SWRST);\r
485             // TRACE_DEBUG("reset MCI\n\r");\r
486 \r
487             WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIDIS | AT91C_MCI_PWSDIS);\r
488             WRITE_MCI(pMciHw, MCI_MR, mciMr);\r
489             WRITE_MCI(pMciHw, MCI_SDCR, mciSdcr);\r
490             WRITE_MCI(pMciHw, MCI_DTOR, mciDtor);\r
491         }\r
492         #endif\r
493 \r
494         // If no error occured, the transfer is successful\r
495         if (pCommand->status == MCI_STATUS_PENDING) {\r
496             pCommand->status = 0;\r
497         }\r
498 #if 0\r
499         if ((status & AT91C_MCI_CMDRDY) != 0)\r
500             TRACE_DEBUG_WP(".");\r
501         if ((status & AT91C_MCI_ENDRX) != 0)\r
502             TRACE_DEBUG_WP("<");\r
503         if ((status & AT91C_MCI_ENDTX) != 0)\r
504             TRACE_DEBUG_WP("-");\r
505         if ((status & AT91C_MCI_BLKE) != 0)\r
506             TRACE_DEBUG_WP(">");\r
507         TRACE_DEBUG_WP("\n\r");\r
508 #endif\r
509         // Store the card response in the provided buffer\r
510         if (pCommand->pResp) {\r
511             unsigned char resSize;\r
512 \r
513             switch (pCommand->resType) {\r
514                 case 1:\r
515                 resSize = 1;\r
516                 break;\r
517 \r
518                 case 2:\r
519                 resSize = 4;\r
520                 break;\r
521 \r
522                 case 3:\r
523                 resSize = 1;\r
524                 break;\r
525 \r
526                 case 4:\r
527                 resSize = 1;\r
528                 break;\r
529 \r
530                 case 5:\r
531                 resSize = 1;\r
532                 break;\r
533 \r
534                 case 6:\r
535                 resSize = 1;\r
536                 break;\r
537 \r
538                 case 7:\r
539                 resSize = 1;\r
540                 break;\r
541 \r
542                 default:\r
543                 resSize = 0;\r
544                 break;\r
545             }\r
546             for (i=0; i < resSize; i++) {\r
547 \r
548                 pCommand->pResp[i] = READ_MCI(pMciHw, MCI_RSPR[0]);\r
549             }\r
550         }\r
551 \r
552         // Disable interrupts\r
553         WRITE_MCI(pMciHw, MCI_IDR, READ_MCI(pMciHw, MCI_IMR));\r
554 \r
555         // Release the semaphore\r
556         pMci->semaphore++;\r
557 \r
558         // Invoke the callback associated with the current command (if any)\r
559         if (pCommand->callback) {\r
560             (pCommand->callback)(pCommand->status, pCommand);\r
561         }\r
562     }\r
563 }\r
564 \r
565 //------------------------------------------------------------------------------\r
566 /// Returns 1 if the given MCI transfer is complete; otherwise returns 0.\r
567 /// \param pCommand  Pointer to a MciCmd instance.\r
568 //------------------------------------------------------------------------------\r
569 unsigned char MCI_IsTxComplete(MciCmd *pCommand)\r
570 {\r
571     if (pCommand->status != MCI_STATUS_PENDING) {\r
572         if (pCommand->status != 0) {\r
573             TRACE_DEBUG("MCI_IsTxComplete %d\n\r", pCommand->status);\r
574         }\r
575         return 1;\r
576     }\r
577     else {\r
578         return 0;\r
579     }\r
580 }\r