3 * Copyright (c) 2011, ARM Limited. All rights reserved.
5 * This program and the accompanying materials
6 * are licensed and made available under the terms and conditions of the BSD License
7 * which accompanies this distribution. The full text of the license may be found at
8 * http://opensource.org/licenses/bsd-license.php
10 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include <Protocol/MmcHost.h>
16 #include <Library/DebugLib.h>
17 #include <Library/BaseMemoryLib.h>
18 #include <Library/TimerLib.h>
25 #define MAX_RETRY_COUNT 1000
26 #define CMD_RETRY_COUNT 20
30 IN MMC_HOST_INSTANCE
*MmcHostInstance
,
34 MmcHostInstance
->State
= State
;
35 return MmcHostInstance
->MmcHost
->NotifyState (MmcHostInstance
->MmcHost
, State
);
43 UINTN minv
, maxv
, volts
;
50 // The MMC register bits [23:8] indicate the working range of the card
51 for (loop
= 8; loop
< 24; loop
++) {
52 if (Ocr
& (1 << loop
)) {
53 if (minv
> volts
) minv
= volts
;
54 if (maxv
< volts
) maxv
= volts
+ 1;
59 DEBUG((EFI_D_ERROR
, "- PrintOCR Ocr (0x%X)\n",Ocr
));
60 DEBUG((EFI_D_ERROR
, "\t- Card operating voltage: %d.%d to %d.%d\n", minv
/10, minv
% 10, maxv
/10, maxv
% 10));
61 if (((Ocr
>> 29) & 3) == 0) {
62 DEBUG((EFI_D_ERROR
, "\t- AccessMode: Byte Mode\n"));
64 DEBUG((EFI_D_ERROR
, "\t- AccessMode: Block Mode (0x%X)\n",((Ocr
>> 29) & 3)));
67 if (Ocr
& MMC_OCR_POWERUP
) {
68 DEBUG((EFI_D_ERROR
, "\t- PowerUp\n"));
70 DEBUG((EFI_D_ERROR
, "\t- Voltage Not Supported\n"));
78 DEBUG((EFI_D_ERROR
, "- PrintCID\n"));
79 DEBUG((EFI_D_ERROR
, "\t- Manufacturing date: %d/%d\n",(Cid
[0] >> 8) & 0xF,(Cid
[0] >> 12) & 0xFF));
80 DEBUG((EFI_D_ERROR
, "\t- Product serial number: 0x%X%X\n",Cid
[1] & 0xFFFFFF,(Cid
[0] >> 24) & 0xFF));
81 DEBUG((EFI_D_ERROR
, "\t- Product revision: %d\n",Cid
[1] >> 24));
82 //DEBUG((EFI_D_ERROR, "\t- Product name: %s\n",(char*)(Cid + 2)));
83 DEBUG((EFI_D_ERROR
, "\t- OEM ID: %c%c\n",(Cid
[3] >> 8) & 0xFF,(Cid
[3] >> 16) & 0xFF));
92 #if !defined(MDEPKG_NDEBUG)
93 CONST CHAR8
* str_unit
[] = { "100kbit/s","1Mbit/s","10Mbit/s","100MBit/s","Unkbown","Unkbown","Unkbown","Unkbown" };
94 CONST CHAR8
* str_value
[] = { "1.0","1.2","1.3","1.5","2.0","2.5","3.0","3.5","4.0","4.5","5.0","Unknown","Unknown","Unknown","Unknown" };
97 if (((Csd
[2] >> 30) & 0x3) == 0) {
98 DEBUG((EFI_D_ERROR
, "- PrintCSD Version 1.01-1.10/Version 2.00/Standard Capacity\n"));
99 } else if (((Csd
[2] >> 30) & 0x3) == 1) {
100 DEBUG((EFI_D_ERROR
, "- PrintCSD Version 2.00/High Capacity\n"));
102 DEBUG((EFI_D_ERROR
, "- PrintCSD Version Higher than v3.3\n"));
105 DEBUG((EFI_D_ERROR
, "\t- Supported card command class: 0x%X\n",MMC_CSD_GET_CCC(Csd
)));
106 DEBUG((EFI_D_ERROR
, "\t- Speed: %a %a\n",str_value
[(MMC_CSD_GET_TRANSPEED(Csd
) >> 3) & 0xF],str_unit
[MMC_CSD_GET_TRANSPEED(Csd
) & 7]));
107 DEBUG((EFI_D_ERROR
, "\t- Maximum Read Data Block: %d\n",2 << (MMC_CSD_GET_READBLLEN(Csd
)-1)));
108 DEBUG((EFI_D_ERROR
, "\t- Maximum Write Data Block: %d\n",2 << (MMC_CSD_GET_WRITEBLLEN(Csd
)-1)));
110 if (!MMC_CSD_GET_FILEFORMATGRP(Csd
)) {
111 Value
= MMC_CSD_GET_FILEFORMAT(Csd
);
112 if (Value
== 0) DEBUG((EFI_D_ERROR
, "\t- Format(0): Hard disk-like file system with partition table\n"));
113 else if (Value
== 1) DEBUG((EFI_D_ERROR
, "\t- Format(1): DOS FAT (floppy-like) with boot sector only (no partition table)\n"));
114 else if (Value
== 2) DEBUG((EFI_D_ERROR
, "\t- Format(2): Universal File Format\n"));
115 else DEBUG((EFI_D_ERROR
, "\t- Format(3): Others/Unknown\n"));
117 DEBUG((EFI_D_ERROR
, "\t- Format: Reserved\n"));
126 DEBUG((EFI_D_ERROR
, "- PrintRCA: 0x%X\n",Rca
));
127 DEBUG((EFI_D_ERROR
, "\t- Status: 0x%X\n",Rca
& 0xFFFF));
128 DEBUG((EFI_D_ERROR
, "\t- RCA: 0x%X\n",(Rca
>> 16) & 0xFFFF));
136 DEBUG((EFI_D_INFO
, "Response: 0x%X\n",Response
));
137 if (Response
& (1 << 8)) DEBUG((EFI_D_INFO
, "\t- READY_FOR_DATA\n"));
139 if (((Response
>> 9) & 0xF) == 0) DEBUG((EFI_D_INFO
, "\t- State: Idle\n"));
140 else if (((Response
>> 9) & 0xF) == 1) DEBUG((EFI_D_INFO
, "\t- State: Ready\n"));
141 else if (((Response
>> 9) & 0xF) == 2) DEBUG((EFI_D_INFO
, "\t- State: Ident\n"));
142 else if (((Response
>> 9) & 0xF) == 3) DEBUG((EFI_D_INFO
, "\t- State: StandBy\n"));
143 else if (((Response
>> 9) & 0xF) == 4) DEBUG((EFI_D_INFO
, "\t- State: Tran\n"));
144 else if (((Response
>> 9) & 0xF) == 5) DEBUG((EFI_D_INFO
, "\t- State: Data\n"));
145 else if (((Response
>> 9) & 0xF) == 6) DEBUG((EFI_D_INFO
, "\t- State: Rcv\n"));
146 else if (((Response
>> 9) & 0xF) == 7) DEBUG((EFI_D_INFO
, "\t- State: Prg\n"));
147 else if (((Response
>> 9) & 0xF) == 8) DEBUG((EFI_D_INFO
, "\t- State: Dis\n"));
148 else DEBUG((EFI_D_INFO
, "\t- State: Reserved\n"));
154 IN MMC_HOST_INSTANCE
*MmcHostInstance
160 EFI_MMC_HOST_PROTOCOL
*MmcHost
;
162 Status
= EFI_SUCCESS
;
163 MmcHost
= MmcHostInstance
->MmcHost
;
166 if (MmcHost
== NULL
) {
167 return EFI_INVALID_PARAMETER
;
169 if(MmcHostInstance
->State
!= MmcHwInitializationState
){
170 //Get the Status of the card.
171 CmdArg
= MmcHostInstance
->CardInfo
.RCA
<< 16;
172 Status
= MmcHost
->SendCommand (MmcHost
, MMC_CMD13
, CmdArg
);
173 if (EFI_ERROR(Status
)) {
174 DEBUG((EFI_D_ERROR
, "MmcGetCardStatus(MMC_CMD13): Error and Status = %r\n", Status
));
179 MmcHost
->ReceiveResponse (MmcHost
, MMC_RESPONSE_TYPE_R1
,Response
);
180 PrintResponseR1(Response
[0]);
188 MmcIdentificationMode (
189 IN MMC_HOST_INSTANCE
*MmcHostInstance
197 EFI_MMC_HOST_PROTOCOL
*MmcHost
;
199 MmcHost
= MmcHostInstance
->MmcHost
;
203 if (MmcHost
== NULL
) {
204 return EFI_INVALID_PARAMETER
;
207 // We can get into this function if we restart the identification mode
208 if (MmcHostInstance
->State
== MmcHwInitializationState
) {
209 // Initialize the MMC Host HW
210 Status
= MmcNotifyState (MmcHostInstance
, MmcHwInitializationState
);
211 if (EFI_ERROR(Status
)) {
212 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode() : Error MmcHwInitializationState\n"));
216 //Note: Could even be used in all cases. But it looks this command could put the state machine into inactive for some cards
217 Status
= MmcHost
->SendCommand (MmcHost
, MMC_CMD0
, 0);
218 if (EFI_ERROR(Status
)) {
219 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode(MMC_CMD0): Error\n"));
224 Status
= MmcNotifyState (MmcHostInstance
, MmcIdleState
);
225 if (EFI_ERROR(Status
)) {
226 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode() : Error MmcIdleState\n"));
230 // Are we using SDIO ?
231 Status
= MmcHost
->SendCommand (MmcHost
, MMC_CMD5
, 0);
232 if (Status
== EFI_SUCCESS
) {
233 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode(MMC_CMD5): Error - SDIO not supported.\n"));
234 return EFI_UNSUPPORTED
;
237 // Check which kind of card we are using. Ver2.00 or later SD Memory Card (PL180 is SD v1.1)
238 CmdArg
= (0x0UL
<< 12 | BIT8
| 0xCEUL
<< 0);
239 Status
= MmcHost
->SendCommand (MmcHost
, MMC_CMD8
, CmdArg
);
240 if (Status
== EFI_SUCCESS
) {
241 DEBUG ((EFI_D_ERROR
, "Card is SD2.0 => Supports high capacity\n"));
243 MmcHost
->ReceiveResponse (MmcHost
, MMC_RESPONSE_TYPE_R7
,Response
);
244 PrintResponseR1(Response
[0]);
245 //check if it is valid response
246 if(Response
[0] != CmdArg
){
247 DEBUG ((EFI_D_ERROR
, "The Card is not usable\n"));
248 return EFI_UNSUPPORTED
;
251 DEBUG ((EFI_D_ERROR
, "Not a SD2.0 Card\n"));
254 // We need to wait for the MMC or SD card is ready => (gCardInfo.OCRData.Busy == 1)
255 Timeout
= MAX_RETRY_COUNT
;
256 while (Timeout
> 0) {
257 // SD Card or MMC Card ? CMD55 indicates to the card that the next command is an application specific command
258 Status
= MmcHost
->SendCommand (MmcHost
, MMC_CMD55
, 0);
259 if (Status
== EFI_SUCCESS
) {
260 DEBUG ((EFI_D_INFO
, "Card should be SD\n"));
262 MmcHostInstance
->CardInfo
.CardType
= SD_CARD_2
;
264 MmcHostInstance
->CardInfo
.CardType
= SD_CARD
;
267 // Note: The first time CmdArg will be zero
268 CmdArg
= ((UINTN
*) &(MmcHostInstance
->CardInfo
.OCRData
))[0];
272 Status
= MmcHost
->SendCommand (MmcHost
, MMC_ACMD41
, CmdArg
);
273 if (!EFI_ERROR(Status
)) {
274 MmcHost
->ReceiveResponse (MmcHost
, MMC_RESPONSE_TYPE_OCR
,Response
);
275 ((UINT32
*) &(MmcHostInstance
->CardInfo
.OCRData
))[0] = Response
[0];
278 DEBUG ((EFI_D_INFO
, "Card should be MMC\n"));
279 MmcHostInstance
->CardInfo
.CardType
= MMC_CARD
;
281 Status
= MmcHost
->SendCommand (MmcHost
, MMC_CMD1
, 0x800000);
282 if (!EFI_ERROR(Status
)) {
283 MmcHost
->ReceiveResponse (MmcHost
, MMC_RESPONSE_TYPE_OCR
,Response
);
284 ((UINT32
*) &(MmcHostInstance
->CardInfo
.OCRData
))[0] = Response
[0];
288 if (!EFI_ERROR(Status
)) {
289 if (MmcHostInstance
->CardInfo
.OCRData
.Busy
== 0) {
293 if ((MmcHostInstance
->CardInfo
.CardType
== SD_CARD_2
) && (MmcHostInstance
->CardInfo
.OCRData
.AccessMode
& BIT1
)) {
294 MmcHostInstance
->CardInfo
.CardType
= SD_CARD_2_HIGH
;
295 DEBUG ((EFI_D_ERROR
, "High capacity card.\n"));
297 break; // The MMC/SD card is ready. Continue the Identification Mode
306 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode(): No Card\n"));
309 PrintOCR(Response
[0]);
312 Status
= MmcNotifyState (MmcHostInstance
, MmcReadyState
);
313 if (EFI_ERROR(Status
)) {
314 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode() : Error MmcReadyState\n"));
318 Status
= MmcHost
->SendCommand (MmcHost
, MMC_CMD2
, 0);
319 if (EFI_ERROR(Status
)) {
320 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode(MMC_CMD2): Error\n"));
323 MmcHost
->ReceiveResponse (MmcHost
, MMC_RESPONSE_TYPE_CID
,Response
);
326 Status
= MmcNotifyState (MmcHostInstance
, MmcIdentificationState
);
327 if (EFI_ERROR(Status
)) {
328 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode() : Error MmcIdentificationState\n"));
333 // Note, SD specifications say that "if the command execution causes a state change, it
334 // will be visible to the host in the response to the next command"
335 // The status returned for this CMD3 will be 2 - identification
338 Status
= MmcHost
->SendCommand (MmcHost
, MMC_CMD3
, CmdArg
);
339 if (EFI_ERROR(Status
)) {
340 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode(MMC_CMD3): Error\n"));
344 MmcHost
->ReceiveResponse (MmcHost
, MMC_RESPONSE_TYPE_RCA
,Response
);
345 PrintRCA(Response
[0]);
347 // For MMC card, RCA is assigned by CMD3 while CMD3 dumps the RCA for SD card
348 if (MmcHostInstance
->CardInfo
.CardType
!= MMC_CARD
) {
349 MmcHostInstance
->CardInfo
.RCA
= Response
[0] >> 16;
351 MmcHostInstance
->CardInfo
.RCA
= CmdArg
;
354 Status
= MmcNotifyState (MmcHostInstance
, MmcStandByState
);
355 if (EFI_ERROR(Status
)) {
356 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode() : Error MmcStandByState\n"));
363 EFI_STATUS
InitializeMmcDevice (
364 IN MMC_HOST_INSTANCE
*MmcHostInstance
369 UINTN CardSize
, NumBlocks
, BlockSize
, CmdArg
;
370 EFI_MMC_HOST_PROTOCOL
*MmcHost
;
371 UINTN BlockCount
= 1;
373 MmcHost
= MmcHostInstance
->MmcHost
;
375 MmcIdentificationMode (MmcHostInstance
);
377 //Send a command to get Card specific data
378 CmdArg
= MmcHostInstance
->CardInfo
.RCA
<< 16;
379 Status
= MmcHost
->SendCommand (MmcHost
, MMC_CMD9
, CmdArg
);
380 if (EFI_ERROR(Status
)) {
381 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode(MMC_CMD9): Error, Status=%r\n", Status
));
385 MmcHost
->ReceiveResponse (MmcHost
, MMC_RESPONSE_TYPE_CSD
,Response
);
388 if (MmcHostInstance
->CardInfo
.CardType
== SD_CARD_2_HIGH
) {
389 CardSize
= HC_MMC_CSD_GET_DEVICESIZE(Response
);
390 NumBlocks
= ((CardSize
+ 1) * 1024);
391 BlockSize
= 1 << MMC_CSD_GET_READBLLEN(Response
);
393 CardSize
= MMC_CSD_GET_DEVICESIZE(Response
);
394 NumBlocks
= (CardSize
+ 1) * (1 << (MMC_CSD_GET_DEVICESIZEMULT(Response
) + 2));
395 BlockSize
= 1 << MMC_CSD_GET_READBLLEN(Response
);
398 //For >=2G card, BlockSize may be 1K, but the transfer size is 512 bytes.
399 if (BlockSize
> 512) {
400 NumBlocks
= MultU64x32(NumBlocks
, BlockSize
/512);
404 MmcHostInstance
->BlockIo
.Media
->LastBlock
= (NumBlocks
- 1);
405 MmcHostInstance
->BlockIo
.Media
->BlockSize
= BlockSize
;
406 MmcHostInstance
->BlockIo
.Media
->ReadOnly
= MmcHost
->IsReadOnly (MmcHost
);
407 MmcHostInstance
->BlockIo
.Media
->MediaPresent
= TRUE
;
408 MmcHostInstance
->BlockIo
.Media
->MediaId
++;
410 CmdArg
= MmcHostInstance
->CardInfo
.RCA
<< 16;
411 Status
= MmcHost
->SendCommand (MmcHost
, MMC_CMD7
, CmdArg
);
412 if (EFI_ERROR(Status
)) {
413 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode(MMC_CMD7): Error and Status = %r\n", Status
));
417 Status
= MmcNotifyState (MmcHostInstance
, MmcTransferState
);
418 if (EFI_ERROR(Status
)) {
419 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode() : Error MmcTransferState\n"));
424 Status
= MmcHost
->SendCommand (MmcHost
, MMC_CMD16
, MmcHostInstance
->BlockIo
.Media
->BlockSize
);
425 if (EFI_ERROR(Status
)) {
426 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode(MMC_CMD16): Error MmcHostInstance->BlockIo.Media->BlockSize: %d and Error = %r\n",MmcHostInstance
->BlockIo
.Media
->BlockSize
, Status
));
430 // Block Count (not used). Could return an error for SD card
431 if (MmcHostInstance
->CardInfo
.CardType
== MMC_CARD
) {
432 MmcHost
->SendCommand (MmcHost
, MMC_CMD23
, BlockCount
);
441 IN EFI_BLOCK_IO_PROTOCOL
*This
,
442 IN BOOLEAN ExtendedVerification
445 MMC_HOST_INSTANCE
*MmcHostInstance
;
447 MmcHostInstance
= MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS(This
);
449 if (MmcHostInstance
->MmcHost
== NULL
) {
454 // If a card is not present then clear all media settings
455 if (!MmcHostInstance
->MmcHost
->IsCardPresent (MmcHostInstance
->MmcHost
)) {
456 MmcHostInstance
->BlockIo
.Media
->MediaPresent
= FALSE
;
457 MmcHostInstance
->BlockIo
.Media
->LastBlock
= 0;
458 MmcHostInstance
->BlockIo
.Media
->BlockSize
= 512; // Should be zero but there is a bug in DiskIo
459 MmcHostInstance
->BlockIo
.Media
->ReadOnly
= FALSE
;
461 // Indicate that the driver requires initialization
462 MmcHostInstance
->State
= MmcHwInitializationState
;
467 // Implement me. Either send a CMD0 (could not work for some MMC host) or just turn off/turn
468 // on power and restart Identification mode
474 EFI_MMC_HOST_PROTOCOL
*MmcHost
477 if (!MmcHost
->IsCardPresent (MmcHost
)) {
484 #define MMCI0_BLOCKLEN 512
485 #define MMCI0_TIMEOUT 10000
489 IN EFI_BLOCK_IO_PROTOCOL
*This
,
502 MMC_HOST_INSTANCE
*MmcHostInstance
;
503 EFI_MMC_HOST_PROTOCOL
*MmcHost
;
504 UINTN BytesRemainingToBeTransfered
;
505 UINTN BlockCount
= 1;
507 MmcHostInstance
= MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS(This
);
508 ASSERT(MmcHostInstance
!= 0);
509 MmcHost
= MmcHostInstance
->MmcHost
;
512 if ((MmcHost
== 0)|| (Buffer
== NULL
)) {
513 return EFI_INVALID_PARAMETER
;
516 // Check if a Card is Present
517 if (!MmcHostInstance
->BlockIo
.Media
->MediaPresent
) {
521 // All blocks must be within the device
522 if ((Lba
+ (BufferSize
/ This
->Media
->BlockSize
)) > (This
->Media
->LastBlock
+ 1)){
523 return EFI_INVALID_PARAMETER
;
526 // The buffer size must not be zero and it must be an exact multiple of the block size
527 if ((BufferSize
== 0) || ((BufferSize
% This
->Media
->BlockSize
) != 0)) {
528 return EFI_BAD_BUFFER_SIZE
;
531 if (This
->Media
->MediaId
!= MediaId
) {
532 return EFI_MEDIA_CHANGED
;
535 if((Transfer
== MMC_IOBLOCKS_WRITE
) && (This
->Media
->ReadOnly
== TRUE
)) {
536 return EFI_WRITE_PROTECTED
;
539 BytesRemainingToBeTransfered
= BufferSize
;
540 while (BytesRemainingToBeTransfered
> 0) {
542 // Check if the Card is in Ready status
543 CmdArg
= MmcHostInstance
->CardInfo
.RCA
<< 16;
546 while(!(Response
[0] & MMC_R0_READY_FOR_DATA
) && (MMC_R0_CURRENTSTATE(Response
) != MMC_R0_STATE_TRAN
) && Timeout
--) {
547 Status
= MmcHost
->SendCommand (MmcHost
, MMC_CMD13
, CmdArg
);
548 if (!EFI_ERROR(Status
)) {
549 MmcHost
->ReceiveResponse (MmcHost
, MMC_RESPONSE_TYPE_R1
,Response
);
554 DEBUG((EFI_D_ERROR
, "The Card is busy\n"));
555 return EFI_NOT_READY
;
558 //Set command argument based on the card access mode (Byte mode or Block mode)
559 if (MmcHostInstance
->CardInfo
.OCRData
.AccessMode
& BIT1
) {
562 CmdArg
= Lba
* This
->Media
->BlockSize
;
565 if (Transfer
== MMC_IOBLOCKS_READ
) {
567 // Read a single block
570 //TODO: Should we support read stream (MMC_CMD11)
574 // Write a single block
577 //TODO: Should we support write stream (MMC_CMD20)
580 Status
= MmcHost
->SendCommand (MmcHost
, Cmd
, CmdArg
);
581 if (EFI_ERROR(Status
)) {
582 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode(MMC_CMD%d): Error %r\n",Cmd
, Status
));
586 if (Transfer
== MMC_IOBLOCKS_READ
) {
588 // Read one block of Data
589 Status
= MmcHost
->ReadBlockData (MmcHost
, Lba
,This
->Media
->BlockSize
,Buffer
);
590 if (EFI_ERROR(Status
)) {
591 DEBUG((EFI_D_BLKIO
, "MmcIdentificationMode(): Error Read Block Data and Status = %r\n", Status
));
598 Status
= MmcNotifyState (MmcHostInstance
, MmcProgrammingState
);
599 if (EFI_ERROR(Status
)) {
600 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode() : Error MmcProgrammingState\n"));
605 // Write one block of Data
606 Status
= MmcHost
->WriteBlockData (MmcHost
, Lba
,This
->Media
->BlockSize
,Buffer
);
607 if (EFI_ERROR(Status
)) {
608 DEBUG((EFI_D_BLKIO
, "MmcIdentificationMode(): Error Write Block Data and Status = %r\n", Status
));
612 //TODO: Write a steam
617 // Command 12 - Stop transmission (ends read)
618 Status
= MmcHost
->SendCommand (MmcHost
, MMC_CMD12
, 0);
619 if (!EFI_ERROR(Status
)) {
620 MmcHost
->ReceiveResponse (MmcHost
, MMC_RESPONSE_TYPE_R1b
,Response
);
623 // Command 13 - Read status and wait for programming to complete (return to tran)
624 Timeout
= MMCI0_TIMEOUT
;
625 CmdArg
= MmcHostInstance
->CardInfo
.RCA
<< 16;
627 while(!(Response
[0] & MMC_R0_READY_FOR_DATA
) && (MMC_R0_CURRENTSTATE(Response
) != MMC_R0_STATE_TRAN
) && Timeout
--) {
628 Status
= MmcHost
->SendCommand (MmcHost
, MMC_CMD13
, CmdArg
);
629 if (!EFI_ERROR(Status
)) {
630 MmcHost
->ReceiveResponse (MmcHost
, MMC_RESPONSE_TYPE_R1
,Response
);
632 NanoSecondDelay(100);
636 Status
= MmcNotifyState (MmcHostInstance
, MmcTransferState
);
637 if (EFI_ERROR(Status
)) {
638 DEBUG((EFI_D_ERROR
, "MmcIdentificationMode() : Error MmcTransferState\n"));
642 BytesRemainingToBeTransfered
-= This
->Media
->BlockSize
;
644 Buffer
= (UINT8
*)Buffer
+ This
->Media
->BlockSize
;
653 IN EFI_BLOCK_IO_PROTOCOL
*This
,
660 return MmcIoBlocks (This
, MMC_IOBLOCKS_READ
, MediaId
, Lba
, BufferSize
, Buffer
);
666 IN EFI_BLOCK_IO_PROTOCOL
*This
,
673 return MmcIoBlocks (This
, MMC_IOBLOCKS_WRITE
, MediaId
, Lba
, BufferSize
, Buffer
);
679 IN EFI_BLOCK_IO_PROTOCOL
*This