]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c
EmbeddedPkg/MmcDxe: Moved all the 'Print*()' functions to MmcDebug.c
[mirror_edk2.git] / EmbeddedPkg / Universal / MmcDxe / MmcBlockIo.c
... / ...
CommitLineData
1/** @file\r
2*\r
3* Copyright (c) 2011-2013, ARM Limited. All rights reserved.\r
4*\r
5* This program and the accompanying materials\r
6* are licensed and made available under the terms and conditions of the BSD License\r
7* which accompanies this distribution. The full text of the license may be found at\r
8* http://opensource.org/licenses/bsd-license.php\r
9*\r
10* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12*\r
13**/\r
14\r
15#include <Library/BaseMemoryLib.h>\r
16#include <Library/TimerLib.h>\r
17\r
18#include "Mmc.h"\r
19\r
20#define MAX_RETRY_COUNT 1000\r
21#define CMD_RETRY_COUNT 20\r
22\r
23EFI_STATUS\r
24MmcNotifyState (\r
25 IN MMC_HOST_INSTANCE *MmcHostInstance,\r
26 IN MMC_STATE State\r
27 )\r
28{\r
29 MmcHostInstance->State = State;\r
30 return MmcHostInstance->MmcHost->NotifyState (MmcHostInstance->MmcHost, State);\r
31}\r
32\r
33EFI_STATUS\r
34EFIAPI\r
35MmcGetCardStatus (\r
36 IN MMC_HOST_INSTANCE *MmcHostInstance\r
37 )\r
38{\r
39 EFI_STATUS Status;\r
40 UINT32 Response[4];\r
41 UINTN CmdArg;\r
42 EFI_MMC_HOST_PROTOCOL *MmcHost;\r
43\r
44 Status = EFI_SUCCESS;\r
45 MmcHost = MmcHostInstance->MmcHost;\r
46 CmdArg = 0;\r
47\r
48 if (MmcHost == NULL) {\r
49 return EFI_INVALID_PARAMETER;\r
50 }\r
51 if (MmcHostInstance->State != MmcHwInitializationState) {\r
52 //Get the Status of the card.\r
53 CmdArg = MmcHostInstance->CardInfo.RCA << 16;\r
54 Status = MmcHost->SendCommand (MmcHost, MMC_CMD13, CmdArg);\r
55 if (EFI_ERROR (Status)) {\r
56 DEBUG ((EFI_D_ERROR, "MmcGetCardStatus(MMC_CMD13): Error and Status = %r\n", Status));\r
57 return Status;\r
58 }\r
59\r
60 //Read Response\r
61 MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);\r
62 PrintResponseR1 (Response[0]);\r
63 }\r
64\r
65 return Status;\r
66}\r
67\r
68EFI_STATUS\r
69EFIAPI\r
70MmcIdentificationMode (\r
71 IN MMC_HOST_INSTANCE *MmcHostInstance\r
72 )\r
73{\r
74 EFI_STATUS Status;\r
75 UINT32 Response[4];\r
76 UINTN Timeout;\r
77 UINTN CmdArg;\r
78 BOOLEAN IsHCS;\r
79 EFI_MMC_HOST_PROTOCOL *MmcHost;\r
80\r
81 MmcHost = MmcHostInstance->MmcHost;\r
82 CmdArg = 0;\r
83 IsHCS = FALSE;\r
84\r
85 if (MmcHost == NULL) {\r
86 return EFI_INVALID_PARAMETER;\r
87 }\r
88\r
89 // We can get into this function if we restart the identification mode\r
90 if (MmcHostInstance->State == MmcHwInitializationState) {\r
91 // Initialize the MMC Host HW\r
92 Status = MmcNotifyState (MmcHostInstance, MmcHwInitializationState);\r
93 if (EFI_ERROR (Status)) {\r
94 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcHwInitializationState\n"));\r
95 return Status;\r
96 }\r
97 }\r
98\r
99 Status = MmcHost->SendCommand (MmcHost, MMC_CMD0, 0);\r
100 if (EFI_ERROR (Status)) {\r
101 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD0): Error\n"));\r
102 return Status;\r
103 }\r
104\r
105 Status = MmcNotifyState (MmcHostInstance, MmcIdleState);\r
106 if (EFI_ERROR (Status)) {\r
107 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcIdleState\n"));\r
108 return Status;\r
109 }\r
110\r
111 // Are we using SDIO ?\r
112 Status = MmcHost->SendCommand (MmcHost, MMC_CMD5, 0);\r
113 if (Status == EFI_SUCCESS) {\r
114 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD5): Error - SDIO not supported.\n"));\r
115 return EFI_UNSUPPORTED;\r
116 }\r
117\r
118 // Check which kind of card we are using. Ver2.00 or later SD Memory Card (PL180 is SD v1.1)\r
119 CmdArg = (0x0UL << 12 | BIT8 | 0xCEUL << 0);\r
120 Status = MmcHost->SendCommand (MmcHost, MMC_CMD8, CmdArg);\r
121 if (Status == EFI_SUCCESS) {\r
122 DEBUG ((EFI_D_ERROR, "Card is SD2.0 => Supports high capacity\n"));\r
123 IsHCS = TRUE;\r
124 MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R7, Response);\r
125 PrintResponseR1 (Response[0]);\r
126 //check if it is valid response\r
127 if (Response[0] != CmdArg) {\r
128 DEBUG ((EFI_D_ERROR, "The Card is not usable\n"));\r
129 return EFI_UNSUPPORTED;\r
130 }\r
131 } else {\r
132 DEBUG ((EFI_D_ERROR, "Not a SD2.0 Card\n"));\r
133 }\r
134\r
135 // We need to wait for the MMC or SD card is ready => (gCardInfo.OCRData.PowerUp == 1)\r
136 Timeout = MAX_RETRY_COUNT;\r
137 while (Timeout > 0) {\r
138 // SD Card or MMC Card ? CMD55 indicates to the card that the next command is an application specific command\r
139 Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, 0);\r
140 if (Status == EFI_SUCCESS) {\r
141 DEBUG ((EFI_D_INFO, "Card should be SD\n"));\r
142 if (IsHCS) {\r
143 MmcHostInstance->CardInfo.CardType = SD_CARD_2;\r
144 } else {\r
145 MmcHostInstance->CardInfo.CardType = SD_CARD;\r
146 }\r
147\r
148 // Note: The first time CmdArg will be zero\r
149 CmdArg = ((UINTN *) &(MmcHostInstance->CardInfo.OCRData))[0];\r
150 if (IsHCS) {\r
151 CmdArg |= BIT30;\r
152 }\r
153 Status = MmcHost->SendCommand (MmcHost, MMC_ACMD41, CmdArg);\r
154 if (!EFI_ERROR (Status)) {\r
155 MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_OCR, Response);\r
156 ((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0];\r
157 }\r
158 } else {\r
159 DEBUG ((EFI_D_INFO, "Card should be MMC\n"));\r
160 MmcHostInstance->CardInfo.CardType = MMC_CARD;\r
161\r
162 Status = MmcHost->SendCommand (MmcHost, MMC_CMD1, 0x800000);\r
163 if (!EFI_ERROR (Status)) {\r
164 MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_OCR, Response);\r
165 ((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0];\r
166 }\r
167 }\r
168\r
169 if (!EFI_ERROR (Status)) {\r
170 if (!MmcHostInstance->CardInfo.OCRData.PowerUp) {\r
171 MicroSecondDelay (1);\r
172 Timeout--;\r
173 } else {\r
174 if ((MmcHostInstance->CardInfo.CardType == SD_CARD_2) && (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1)) {\r
175 MmcHostInstance->CardInfo.CardType = SD_CARD_2_HIGH;\r
176 DEBUG ((EFI_D_ERROR, "High capacity card.\n"));\r
177 }\r
178 break; // The MMC/SD card is ready. Continue the Identification Mode\r
179 }\r
180 } else {\r
181 MicroSecondDelay (1);\r
182 Timeout--;\r
183 }\r
184 }\r
185\r
186 if (Timeout == 0) {\r
187 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(): No Card\n"));\r
188 return EFI_NO_MEDIA;\r
189 } else {\r
190 PrintOCR (Response[0]);\r
191 }\r
192\r
193 Status = MmcNotifyState (MmcHostInstance, MmcReadyState);\r
194 if (EFI_ERROR (Status)) {\r
195 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcReadyState\n"));\r
196 return Status;\r
197 }\r
198\r
199 Status = MmcHost->SendCommand (MmcHost, MMC_CMD2, 0);\r
200 if (EFI_ERROR (Status)) {\r
201 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD2): Error\n"));\r
202 return Status;\r
203 }\r
204 MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_CID, Response);\r
205 PrintCID (Response);\r
206\r
207 Status = MmcNotifyState (MmcHostInstance, MmcIdentificationState);\r
208 if (EFI_ERROR (Status)) {\r
209 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcIdentificationState\n"));\r
210 return Status;\r
211 }\r
212\r
213 //\r
214 // Note, SD specifications say that "if the command execution causes a state change, it\r
215 // will be visible to the host in the response to the next command"\r
216 // The status returned for this CMD3 will be 2 - identification\r
217 //\r
218 CmdArg = 1;\r
219 Status = MmcHost->SendCommand (MmcHost, MMC_CMD3, CmdArg);\r
220 if (EFI_ERROR (Status)) {\r
221 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD3): Error\n"));\r
222 return Status;\r
223 }\r
224\r
225 MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_RCA, Response);\r
226 PrintRCA (Response[0]);\r
227\r
228 // For MMC card, RCA is assigned by CMD3 while CMD3 dumps the RCA for SD card\r
229 if (MmcHostInstance->CardInfo.CardType != MMC_CARD) {\r
230 MmcHostInstance->CardInfo.RCA = Response[0] >> 16;\r
231 } else {\r
232 MmcHostInstance->CardInfo.RCA = CmdArg;\r
233 }\r
234\r
235 Status = MmcNotifyState (MmcHostInstance, MmcStandByState);\r
236 if (EFI_ERROR (Status)) {\r
237 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcStandByState\n"));\r
238 return Status;\r
239 }\r
240\r
241 return EFI_SUCCESS;\r
242}\r
243\r
244EFI_STATUS InitializeMmcDevice (\r
245 IN MMC_HOST_INSTANCE *MmcHostInstance\r
246 )\r
247{\r
248 UINT32 Response[4];\r
249 EFI_STATUS Status;\r
250 UINTN CardSize, NumBlocks, BlockSize, CmdArg;\r
251 EFI_MMC_HOST_PROTOCOL *MmcHost;\r
252 UINTN BlockCount;\r
253\r
254 BlockCount = 1;\r
255 MmcHost = MmcHostInstance->MmcHost;\r
256\r
257 MmcIdentificationMode (MmcHostInstance);\r
258\r
259 //Send a command to get Card specific data\r
260 CmdArg = MmcHostInstance->CardInfo.RCA << 16;\r
261 Status = MmcHost->SendCommand (MmcHost, MMC_CMD9, CmdArg);\r
262 if (EFI_ERROR (Status)) {\r
263 DEBUG((EFI_D_ERROR, "InitializeMmcDevice(MMC_CMD9): Error, Status=%r\n", Status));\r
264 return Status;\r
265 }\r
266 //Read Response\r
267 MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_CSD, Response);\r
268 PrintCSD (Response);\r
269\r
270 if (MmcHostInstance->CardInfo.CardType == SD_CARD_2_HIGH) {\r
271 CardSize = HC_MMC_CSD_GET_DEVICESIZE (Response);\r
272 NumBlocks = ((CardSize + 1) * 1024);\r
273 BlockSize = 1 << MMC_CSD_GET_READBLLEN (Response);\r
274 } else {\r
275 CardSize = MMC_CSD_GET_DEVICESIZE (Response);\r
276 NumBlocks = (CardSize + 1) * (1 << (MMC_CSD_GET_DEVICESIZEMULT (Response) + 2));\r
277 BlockSize = 1 << MMC_CSD_GET_READBLLEN (Response);\r
278 }\r
279\r
280 //For >=2G card, BlockSize may be 1K, but the transfer size is 512 bytes.\r
281 if (BlockSize > 512) {\r
282 NumBlocks = MultU64x32 (NumBlocks, BlockSize/512);\r
283 BlockSize = 512;\r
284 }\r
285\r
286 MmcHostInstance->BlockIo.Media->LastBlock = (NumBlocks - 1);\r
287 MmcHostInstance->BlockIo.Media->BlockSize = BlockSize;\r
288 MmcHostInstance->BlockIo.Media->ReadOnly = MmcHost->IsReadOnly (MmcHost);\r
289 MmcHostInstance->BlockIo.Media->MediaPresent = TRUE;\r
290 MmcHostInstance->BlockIo.Media->MediaId++;\r
291\r
292 CmdArg = MmcHostInstance->CardInfo.RCA << 16;\r
293 Status = MmcHost->SendCommand (MmcHost, MMC_CMD7, CmdArg);\r
294 if (EFI_ERROR (Status)) {\r
295 DEBUG((EFI_D_ERROR, "InitializeMmcDevice(MMC_CMD7): Error and Status = %r\n", Status));\r
296 return Status;\r
297 }\r
298\r
299 Status = MmcNotifyState (MmcHostInstance, MmcTransferState);\r
300 if (EFI_ERROR (Status)) {\r
301 DEBUG((EFI_D_ERROR, "InitializeMmcDevice(): Error MmcTransferState\n"));\r
302 return Status;\r
303 }\r
304\r
305 // Set Block Length\r
306 Status = MmcHost->SendCommand (MmcHost, MMC_CMD16, MmcHostInstance->BlockIo.Media->BlockSize);\r
307 if (EFI_ERROR (Status)) {\r
308 DEBUG((EFI_D_ERROR, "InitializeMmcDevice(MMC_CMD16): Error MmcHostInstance->BlockIo.Media->BlockSize: %d and Error = %r\n",\r
309 MmcHostInstance->BlockIo.Media->BlockSize, Status));\r
310 return Status;\r
311 }\r
312\r
313 // Block Count (not used). Could return an error for SD card\r
314 if (MmcHostInstance->CardInfo.CardType == MMC_CARD) {\r
315 MmcHost->SendCommand (MmcHost, MMC_CMD23, BlockCount);\r
316 }\r
317\r
318 return EFI_SUCCESS;\r
319}\r
320\r
321EFI_STATUS\r
322EFIAPI\r
323MmcReset (\r
324 IN EFI_BLOCK_IO_PROTOCOL *This,\r
325 IN BOOLEAN ExtendedVerification\r
326 )\r
327{\r
328 MMC_HOST_INSTANCE *MmcHostInstance;\r
329\r
330 MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS (This);\r
331\r
332 if (MmcHostInstance->MmcHost == NULL) {\r
333 // Nothing to do\r
334 return EFI_SUCCESS;\r
335 }\r
336\r
337 // If a card is not present then clear all media settings\r
338 if (!MmcHostInstance->MmcHost->IsCardPresent (MmcHostInstance->MmcHost)) {\r
339 MmcHostInstance->BlockIo.Media->MediaPresent = FALSE;\r
340 MmcHostInstance->BlockIo.Media->LastBlock = 0;\r
341 MmcHostInstance->BlockIo.Media->BlockSize = 512; // Should be zero but there is a bug in DiskIo\r
342 MmcHostInstance->BlockIo.Media->ReadOnly = FALSE;\r
343\r
344 // Indicate that the driver requires initialization\r
345 MmcHostInstance->State = MmcHwInitializationState;\r
346\r
347 return EFI_SUCCESS;\r
348 }\r
349\r
350 // Implement me. Either send a CMD0 (could not work for some MMC host) or just turn off/turn\r
351 // on power and restart Identification mode\r
352 return EFI_SUCCESS;\r
353}\r
354\r
355EFI_STATUS\r
356MmcDetectCard (\r
357 EFI_MMC_HOST_PROTOCOL *MmcHost\r
358 )\r
359{\r
360 if (!MmcHost->IsCardPresent (MmcHost)) {\r
361 return EFI_NO_MEDIA;\r
362 } else {\r
363 return EFI_SUCCESS;\r
364 }\r
365}\r
366\r
367EFI_STATUS\r
368MmcStopTransmission (\r
369 EFI_MMC_HOST_PROTOCOL *MmcHost\r
370 )\r
371{\r
372 EFI_STATUS Status;\r
373 UINT32 Response[4];\r
374 // Command 12 - Stop transmission (ends read or write)\r
375 // Normally only needed for streaming transfers or after error.\r
376 Status = MmcHost->SendCommand (MmcHost, MMC_CMD12, 0);\r
377 if (!EFI_ERROR (Status)) {\r
378 MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1b, Response);\r
379 }\r
380 return Status;\r
381}\r
382\r
383#define MMCI0_BLOCKLEN 512\r
384#define MMCI0_TIMEOUT 10000\r
385\r
386EFI_STATUS\r
387MmcIoBlocks (\r
388 IN EFI_BLOCK_IO_PROTOCOL *This,\r
389 IN UINTN Transfer,\r
390 IN UINT32 MediaId,\r
391 IN EFI_LBA Lba,\r
392 IN UINTN BufferSize,\r
393 OUT VOID *Buffer\r
394 )\r
395{\r
396 UINT32 Response[4];\r
397 EFI_STATUS Status;\r
398 UINTN CmdArg;\r
399 INTN Timeout;\r
400 UINTN Cmd;\r
401 MMC_HOST_INSTANCE *MmcHostInstance;\r
402 EFI_MMC_HOST_PROTOCOL *MmcHost;\r
403 UINTN BytesRemainingToBeTransfered;\r
404 UINTN BlockCount;\r
405\r
406 BlockCount = 1;\r
407 MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS (This);\r
408 ASSERT (MmcHostInstance != NULL);\r
409 MmcHost = MmcHostInstance->MmcHost;\r
410 ASSERT (MmcHost);\r
411\r
412 if (This->Media->MediaId != MediaId) {\r
413 return EFI_MEDIA_CHANGED;\r
414 }\r
415\r
416 if ((MmcHost == NULL) || (Buffer == NULL)) {\r
417 return EFI_INVALID_PARAMETER;\r
418 }\r
419\r
420 // Check if a Card is Present\r
421 if (!MmcHostInstance->BlockIo.Media->MediaPresent) {\r
422 return EFI_NO_MEDIA;\r
423 }\r
424\r
425 // All blocks must be within the device\r
426 if ((Lba + (BufferSize / This->Media->BlockSize)) > (This->Media->LastBlock + 1)) {\r
427 return EFI_INVALID_PARAMETER;\r
428 }\r
429\r
430 if ((Transfer == MMC_IOBLOCKS_WRITE) && (This->Media->ReadOnly == TRUE)) {\r
431 return EFI_WRITE_PROTECTED;\r
432 }\r
433\r
434 // Reading 0 Byte is valid\r
435 if (BufferSize == 0) {\r
436 return EFI_SUCCESS;\r
437 }\r
438\r
439 // The buffer size must be an exact multiple of the block size\r
440 if ((BufferSize % This->Media->BlockSize) != 0) {\r
441 return EFI_BAD_BUFFER_SIZE;\r
442 }\r
443\r
444 // Check the alignment\r
445 if ((This->Media->IoAlign > 2) && (((UINTN)Buffer & (This->Media->IoAlign - 1)) != 0)) {\r
446 return EFI_INVALID_PARAMETER;\r
447 }\r
448\r
449 BytesRemainingToBeTransfered = BufferSize;\r
450 while (BytesRemainingToBeTransfered > 0) {\r
451\r
452 // Check if the Card is in Ready status\r
453 CmdArg = MmcHostInstance->CardInfo.RCA << 16;\r
454 Response[0] = 0;\r
455 Timeout = 20;\r
456 while( (!(Response[0] & MMC_R0_READY_FOR_DATA))\r
457 && (MMC_R0_CURRENTSTATE (Response) != MMC_R0_STATE_TRAN)\r
458 && Timeout--) {\r
459 Status = MmcHost->SendCommand (MmcHost, MMC_CMD13, CmdArg);\r
460 if (!EFI_ERROR (Status)) {\r
461 MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);\r
462 }\r
463 }\r
464\r
465 if (0 == Timeout) {\r
466 DEBUG ((EFI_D_ERROR, "The Card is busy\n"));\r
467 return EFI_NOT_READY;\r
468 }\r
469\r
470 //Set command argument based on the card access mode (Byte mode or Block mode)\r
471 if (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1) {\r
472 CmdArg = Lba;\r
473 } else {\r
474 CmdArg = Lba * This->Media->BlockSize;\r
475 }\r
476\r
477 if (Transfer == MMC_IOBLOCKS_READ) {\r
478 // Read a single block\r
479 Cmd = MMC_CMD17;\r
480 } else {\r
481 // Write a single block\r
482 Cmd = MMC_CMD24;\r
483 }\r
484 Status = MmcHost->SendCommand (MmcHost, Cmd, CmdArg);\r
485 if (EFI_ERROR (Status)) {\r
486 DEBUG ((EFI_D_ERROR, "MmcIoBlocks(MMC_CMD%d): Error %r\n", Cmd, Status));\r
487 return Status;\r
488 }\r
489\r
490 if (Transfer == MMC_IOBLOCKS_READ) {\r
491 // Read one block of Data\r
492 Status = MmcHost->ReadBlockData (MmcHost, Lba, This->Media->BlockSize, Buffer);\r
493 if (EFI_ERROR (Status)) {\r
494 DEBUG ((EFI_D_BLKIO, "MmcIoBlocks(): Error Read Block Data and Status = %r\n", Status));\r
495 MmcStopTransmission (MmcHost);\r
496 return Status;\r
497 }\r
498 Status = MmcNotifyState (MmcHostInstance, MmcProgrammingState);\r
499 if (EFI_ERROR (Status)) {\r
500 DEBUG ((EFI_D_ERROR, "MmcIoBlocks() : Error MmcProgrammingState\n"));\r
501 return Status;\r
502 }\r
503 } else {\r
504 // Write one block of Data\r
505 Status = MmcHost->WriteBlockData (MmcHost, Lba, This->Media->BlockSize, Buffer);\r
506 if (EFI_ERROR (Status)) {\r
507 DEBUG ((EFI_D_BLKIO, "MmcIoBlocks(): Error Write Block Data and Status = %r\n", Status));\r
508 MmcStopTransmission (MmcHost);\r
509 return Status;\r
510 }\r
511 }\r
512\r
513 // Command 13 - Read status and wait for programming to complete (return to tran)\r
514 Timeout = MMCI0_TIMEOUT;\r
515 CmdArg = MmcHostInstance->CardInfo.RCA << 16;\r
516 Response[0] = 0;\r
517 while( (!(Response[0] & MMC_R0_READY_FOR_DATA))\r
518 && (MMC_R0_CURRENTSTATE (Response) != MMC_R0_STATE_TRAN)\r
519 && Timeout--) {\r
520 Status = MmcHost->SendCommand (MmcHost, MMC_CMD13, CmdArg);\r
521 if (!EFI_ERROR (Status)) {\r
522 MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);\r
523 if ((Response[0] & MMC_R0_READY_FOR_DATA)) {\r
524 break; // Prevents delay once finished\r
525 }\r
526 }\r
527 NanoSecondDelay (100);\r
528 }\r
529\r
530 Status = MmcNotifyState (MmcHostInstance, MmcTransferState);\r
531 if (EFI_ERROR (Status)) {\r
532 DEBUG ((EFI_D_ERROR, "MmcIoBlocks() : Error MmcTransferState\n"));\r
533 return Status;\r
534 }\r
535\r
536 BytesRemainingToBeTransfered -= This->Media->BlockSize;\r
537 Lba += BlockCount;\r
538 Buffer = (UINT8 *)Buffer + This->Media->BlockSize;\r
539 }\r
540\r
541 return EFI_SUCCESS;\r
542}\r
543\r
544EFI_STATUS\r
545EFIAPI\r
546MmcReadBlocks (\r
547 IN EFI_BLOCK_IO_PROTOCOL *This,\r
548 IN UINT32 MediaId,\r
549 IN EFI_LBA Lba,\r
550 IN UINTN BufferSize,\r
551 OUT VOID *Buffer\r
552 )\r
553{\r
554 return MmcIoBlocks (This, MMC_IOBLOCKS_READ, MediaId, Lba, BufferSize, Buffer);\r
555}\r
556\r
557EFI_STATUS\r
558EFIAPI\r
559MmcWriteBlocks (\r
560 IN EFI_BLOCK_IO_PROTOCOL *This,\r
561 IN UINT32 MediaId,\r
562 IN EFI_LBA Lba,\r
563 IN UINTN BufferSize,\r
564 IN VOID *Buffer\r
565 )\r
566{\r
567 return MmcIoBlocks (This, MMC_IOBLOCKS_WRITE, MediaId, Lba, BufferSize, Buffer);\r
568}\r
569\r
570EFI_STATUS\r
571EFIAPI\r
572MmcFlushBlocks (\r
573 IN EFI_BLOCK_IO_PROTOCOL *This\r
574 )\r
575{\r
576 return EFI_SUCCESS;\r
577}\r