]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Universal/MmcDxe/MmcBlockIo.c
Patch from open source community for CryptoPkg to allow it to build for ARM using...
[mirror_edk2.git] / ArmPkg / Universal / MmcDxe / MmcBlockIo.c
1 /** @file
2 *
3 * Copyright (c) 2011, ARM Limited. All rights reserved.
4 *
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
9 *
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.
12 *
13 **/
14
15 #include <Protocol/MmcHost.h>
16 #include <Library/DebugLib.h>
17 #include <Library/BaseMemoryLib.h>
18 #include <Library/TimerLib.h>
19
20 #include "Mmc.h"
21
22 // Untested ...
23 //#define USE_STREAM
24
25 #define MAX_RETRY_COUNT 1000
26 #define CMD_RETRY_COUNT 20
27
28 EFI_STATUS
29 MmcNotifyState (
30 MMC_HOST_INSTANCE *MmcHostInstance,
31 MMC_STATE State
32 ) {
33 MmcHostInstance->State = State;
34 return MmcHostInstance->MmcHost->NotifyState(State);
35 }
36
37 VOID PrintOCR(UINT32 ocr) {
38 UINTN minv, maxv, volts;
39 UINTN loop;
40
41 minv = 36; // 3.6
42 maxv = 20; // 2.0
43 volts = 20; // 2.0
44
45 // The MMC register bits [23:8] indicate the working range of the card
46 for (loop = 8; loop < 24; loop++) {
47 if (ocr & (1 << loop)) {
48 if (minv > volts) minv = volts;
49 if (maxv < volts) maxv = volts + 1;
50 }
51 volts = volts + 1;
52 }
53
54 DEBUG((EFI_D_ERROR, "- PrintOCR ocr (0x%X)\n",ocr));
55 DEBUG((EFI_D_ERROR, "\t- Card operating voltage: %d.%d to %d.%d\n", minv/10, minv % 10, maxv/10, maxv % 10));
56 if (((ocr >> 29) & 3) == 0)
57 DEBUG((EFI_D_ERROR, "\t- AccessMode: Byte Mode\n"));
58 else
59 DEBUG((EFI_D_ERROR, "\t- AccessMode: Block Mode (0x%X)\n",((ocr >> 29) & 3)));
60
61 if (ocr & MMC_OCR_POWERUP)
62 DEBUG((EFI_D_ERROR, "\t- PowerUp\n"));
63 else
64 DEBUG((EFI_D_ERROR, "\t- Voltage Not Supported\n"));
65 }
66
67 VOID PrintCID(UINT32* cid) {
68 DEBUG((EFI_D_ERROR, "- PrintCID\n"));
69 DEBUG((EFI_D_ERROR, "\t- Manufacturing date: %d/%d\n",(cid[0] >> 8) & 0xF,(cid[0] >> 12) & 0xFF));
70 DEBUG((EFI_D_ERROR, "\t- Product serial number: 0x%X%X\n",cid[1] & 0xFFFFFF,(cid[0] >> 24) & 0xFF));
71 DEBUG((EFI_D_ERROR, "\t- Product revision: %d\n",cid[1] >> 24));
72 //DEBUG((EFI_D_ERROR, "\t- Product name: %s\n",(char*)(cid + 2)));
73 DEBUG((EFI_D_ERROR, "\t- OEM ID: %c%c\n",(cid[3] >> 8) & 0xFF,(cid[3] >> 16) & 0xFF));
74 }
75
76 VOID PrintCSD(UINT32* csd) {
77 UINTN val32;
78 CONST CHAR8* str_unit[] = { "100kbit/s","1Mbit/s","10Mbit/s","100MBit/s","Unkbown","Unkbown","Unkbown","Unkbown" };
79 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" };
80
81 if (((csd[2] >> 30) & 0x3) == 0)
82 DEBUG((EFI_D_ERROR, "- PrintCSD Version 1.01-1.10/Version 2.00/Standard Capacity\n"));
83 else if (((csd[2] >> 30) & 0x3) == 1)
84 DEBUG((EFI_D_ERROR, "- PrintCSD Version 2.00/High Capacity\n"));
85 else
86 DEBUG((EFI_D_ERROR, "- PrintCSD Version Higher than v3.3\n"));
87
88 DEBUG((EFI_D_ERROR, "\t- Supported card command class: 0x%X\n",MMC_CSD_GET_CCC(csd)));
89 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]));
90 DEBUG((EFI_D_ERROR, "\t- Maximum Read Data Block: %d\n",2 << (MMC_CSD_GET_READBLLEN(csd)-1)));
91 DEBUG((EFI_D_ERROR, "\t- Maximum Write Data Block: %d\n",2 << (MMC_CSD_GET_WRITEBLLEN(csd)-1)));
92
93 if (!MMC_CSD_GET_FILEFORMATGRP(csd)) {
94 val32 = MMC_CSD_GET_FILEFORMAT(csd);
95 if (val32 == 0) DEBUG((EFI_D_ERROR, "\t- Format(0): Hard disk-like file system with partition table\n"));
96 else if (val32 == 1) DEBUG((EFI_D_ERROR, "\t- Format(1): DOS FAT (floppy-like) with boot sector only (no partition table)\n"));
97 else if (val32 == 2) DEBUG((EFI_D_ERROR, "\t- Format(2): Universal File Format\n"));
98 else DEBUG((EFI_D_ERROR, "\t- Format(3): Others/Unknown\n"));
99 } else {
100 DEBUG((EFI_D_ERROR, "\t- Format: Reserved\n"));
101 }
102 }
103
104 VOID PrintRCA(UINT32 rca) {
105 DEBUG((EFI_D_ERROR, "- PrintRCA: 0x%X\n",rca));
106 DEBUG((EFI_D_ERROR, "\t- Status: 0x%X\n",rca & 0xFFFF));
107 DEBUG((EFI_D_ERROR, "\t- RCA: 0x%X\n",(rca >> 16) & 0xFFFF));
108 }
109
110 VOID PrintResponseR1(UINT32 response) {
111 DEBUG((EFI_D_INFO, "Response: 0x%X\n",response));
112 if (response & (1 << 8)) DEBUG((EFI_D_INFO, "\t- READY_FOR_DATA\n"));
113
114 if (((response >> 9) & 0xF) == 0) DEBUG((EFI_D_INFO, "\t- State: Idle\n"));
115 else if (((response >> 9) & 0xF) == 1) DEBUG((EFI_D_INFO, "\t- State: Ready\n"));
116 else if (((response >> 9) & 0xF) == 2) DEBUG((EFI_D_INFO, "\t- State: Ident\n"));
117 else if (((response >> 9) & 0xF) == 3) DEBUG((EFI_D_INFO, "\t- State: StandBy\n"));
118 else if (((response >> 9) & 0xF) == 4) DEBUG((EFI_D_INFO, "\t- State: Tran\n"));
119 else if (((response >> 9) & 0xF) == 5) DEBUG((EFI_D_INFO, "\t- State: Data\n"));
120 else if (((response >> 9) & 0xF) == 6) DEBUG((EFI_D_INFO, "\t- State: Rcv\n"));
121 else if (((response >> 9) & 0xF) == 7) DEBUG((EFI_D_INFO, "\t- State: Prg\n"));
122 else if (((response >> 9) & 0xF) == 8) DEBUG((EFI_D_INFO, "\t- State: Dis\n"));
123 else DEBUG((EFI_D_INFO, "\t- State: Reserved\n"));
124 }
125
126 EFI_STATUS
127 EFIAPI
128 MmcGetCardStatus(
129 MMC_HOST_INSTANCE *MmcHostInstance
130 ){
131 EFI_STATUS Status=EFI_SUCCESS;
132 UINT32 Response[4];
133 UINTN CmdArg;
134 EFI_MMC_HOST_PROTOCOL *MmcHost;
135
136 MmcHost = MmcHostInstance->MmcHost;
137 CmdArg = 0;
138
139 if (MmcHost == NULL) {
140 return EFI_INVALID_PARAMETER;
141 }
142 if(MmcHostInstance->State != MmcHwInitializationState){
143 //Get the Status of the card.
144 CmdArg = MmcHostInstance->CardInfo.RCA << 16;
145 Status = MmcHost->SendCommand(MMC_CMD13, CmdArg);
146 if (EFI_ERROR(Status)) {
147 DEBUG((EFI_D_ERROR, "MmcGetCardStatus(MMC_CMD13): Error and Status = %r\n", Status));
148 ASSERT(0);
149 return Status;
150 }
151
152 //Read Response
153 MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_R1,Response);
154 PrintResponseR1(Response[0]);
155 }
156
157 return Status;
158 }
159
160 EFI_STATUS
161 EFIAPI
162 MmcIdentificationMode (
163 MMC_HOST_INSTANCE *MmcHostInstance
164 ) {
165 EFI_STATUS Status;
166 UINT32 Response[4];
167 UINTN Timeout;
168 UINTN CmdArg;
169 BOOLEAN bHCS;
170 EFI_MMC_HOST_PROTOCOL *MmcHost;
171 UINTN CmdRetryCnt;
172
173 MmcHost = MmcHostInstance->MmcHost;
174 CmdArg = 0;
175 bHCS = FALSE;
176
177 if (MmcHost == NULL) {
178 return EFI_INVALID_PARAMETER;
179 }
180
181 // We can get into this function if we restart the identification mode
182 if (MmcHostInstance->State == MmcHwInitializationState) {
183 // Initialize the MMC Host HW
184 Status = MmcNotifyState (MmcHostInstance, MmcHwInitializationState);
185 if (EFI_ERROR(Status)) {
186 DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcHwInitializationState\n"));
187 return Status;
188 }
189 } else {
190 //Note: Could even be used in all cases. But it looks this command could put the state machine into inactive for some cards
191 Status = MmcHost->SendCommand(MMC_CMD0, 0);
192 if (EFI_ERROR(Status)) {
193 DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD0): Error\n"));
194 return Status;
195 }
196 }
197
198 Status = MmcNotifyState (MmcHostInstance, MmcIdleState);
199 if (EFI_ERROR(Status)) {
200 DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcIdleState\n"));
201 return Status;
202 }
203
204 // Are we using SDIO ?
205 Status = MmcHost->SendCommand(MMC_CMD5, 0);
206 if (Status == EFI_SUCCESS) {
207 DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD5): Error - SDIO not supported.\n"));
208 return EFI_UNSUPPORTED;
209 }
210
211 // Check which kind of card we are using. Ver2.00 or later SD Memory Card (PL180 is SD v1.1)
212 CmdArg = (0x0UL << 12 | BIT8 | 0xCEUL << 0);
213 Status = MmcHost->SendCommand(MMC_CMD8, CmdArg);
214 if (Status == EFI_SUCCESS) {
215 DEBUG ((EFI_D_ERROR, "Card is SD2.0 => Supports high capacity\n"));
216 bHCS = TRUE;
217 MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_R7,Response);
218 PrintResponseR1(Response[0]);
219 //check if it is valid response
220 if(Response[0] != CmdArg){
221 DEBUG ((EFI_D_ERROR, "The Card is not usable\n"));
222 return EFI_UNSUPPORTED;
223 }
224 } else {
225 DEBUG ((EFI_D_ERROR, "Not a SD2.0 Card\n"));
226 }
227
228 // We need to wait for the MMC or SD card is ready => (gCardInfo.OCRData.Busy == 1)
229 Timeout = MAX_RETRY_COUNT;
230 while (Timeout > 0) {
231 // SD Card or MMC Card ? CMD55 indicates to the card that the next command is an application specific command
232 Status = MmcHost->SendCommand(MMC_CMD55, 0);
233 if (Status == EFI_SUCCESS) {
234 DEBUG ((EFI_D_INFO, "Card should be SD\n"));
235 if (bHCS) {
236 MmcHostInstance->CardInfo.CardType = SD_CARD_2;
237 } else {
238 MmcHostInstance->CardInfo.CardType = SD_CARD;
239 }
240
241 // Note: The first time CmdArg will be zero
242 CmdArg = ((UINTN *) &(MmcHostInstance->CardInfo.OCRData))[0];
243 if (bHCS) {
244 CmdArg |= BIT30;
245 }
246 Status = MmcHost->SendCommand(MMC_ACMD41, CmdArg);
247 if (!EFI_ERROR(Status)) {
248 MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_OCR,Response);
249 ((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0];
250 }
251 } else {
252 DEBUG ((EFI_D_INFO, "Card should be MMC\n"));
253 MmcHostInstance->CardInfo.CardType = MMC_CARD;
254
255 Status = MmcHost->SendCommand(MMC_CMD1, 0x800000);
256 if (!EFI_ERROR(Status)) {
257 MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_OCR,Response);
258 ((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0];
259 }
260 }
261
262 if (!EFI_ERROR(Status)) {
263 if (MmcHostInstance->CardInfo.OCRData.Busy == 0) {
264 MicroSecondDelay(1);
265 Timeout--;
266 } else {
267 if ((MmcHostInstance->CardInfo.CardType == SD_CARD_2) && (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1)) {
268 MmcHostInstance->CardInfo.CardType = SD_CARD_2_HIGH;
269 DEBUG ((EFI_D_ERROR, "High capacity card.\n"));
270 }
271 break; // The MMC/SD card is ready. Continue the Identification Mode
272 }
273 } else {
274 MicroSecondDelay(1);
275 Timeout--;
276 }
277 }
278
279 if (Timeout == 0) {
280 DEBUG((EFI_D_ERROR, "MmcIdentificationMode(): No Card\n"));
281 ASSERT(0);
282 return EFI_NO_MEDIA;
283 } else {
284 PrintOCR(Response[0]);
285 }
286
287 Status = MmcNotifyState (MmcHostInstance, MmcReadyState);
288 if (EFI_ERROR(Status)) {
289 DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcReadyState\n"));
290 return Status;
291 }
292
293 Status = MmcHost->SendCommand(MMC_CMD2, 0);
294 if (EFI_ERROR(Status)) {
295 DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD2): Error\n"));
296 ASSERT(0);
297 return Status;
298 }
299 MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_CID,Response);
300 PrintCID(Response);
301
302 Status = MmcNotifyState (MmcHostInstance, MmcIdentificationState);
303 if (EFI_ERROR(Status)) {
304 DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcIdentificationState\n"));
305 return Status;
306 }
307
308 CmdArg = 0;
309 CmdRetryCnt = CMD_RETRY_COUNT;
310 //Keep sending CMD 3 until card enters to Standby mode and Card status is ready
311 while((MMC_R0_CURRENTSTATE(Response) != MMC_R0_STATE_STDBY) && CmdRetryCnt-- ){
312 Status = MmcHost->SendCommand(MMC_CMD3, CmdArg);
313 if (EFI_ERROR(Status)) {
314 DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD3): Error\n"));
315 return Status;
316 }
317 MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_RCA,Response);
318 PrintRCA(Response[0]);
319 }
320
321 // For MMC card, RCA is assigned by CMD3 while CMD3 dumps the RCA for SD card
322 if (MmcHostInstance->CardInfo.CardType != MMC_CARD) {
323 MmcHostInstance->CardInfo.RCA = Response[0] >> 16;
324 } else {
325 MmcHostInstance->CardInfo.RCA = CmdArg;
326 }
327
328 Status = MmcNotifyState (MmcHostInstance, MmcStandByState);
329 if (EFI_ERROR(Status)) {
330 DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcStandByState\n"));
331 return Status;
332 }
333
334 return EFI_SUCCESS;
335 }
336
337 EFI_STATUS
338 EFIAPI
339 MmcReset (
340 IN EFI_BLOCK_IO_PROTOCOL *This,
341 IN BOOLEAN ExtendedVerification
342 ) {
343 // Implement me. Either send a CMD0 (could not work for some MMC host) or just turn off/turn
344 // on power and restart Identification mode
345 return EFI_SUCCESS;
346 }
347
348 EFI_STATUS
349 MmcDetectCard (
350 EFI_MMC_HOST_PROTOCOL *MmcHost
351 )
352 {
353 if (!MmcHost->IsCardPresent()) {
354 return EFI_NO_MEDIA;
355 } else {
356 return EFI_SUCCESS;
357 }
358 }
359
360 #define MMCI0_BLOCKLEN 512
361 #define MMCI0_TIMEOUT 10000
362
363 EFI_STATUS MmcIoBlocks (
364 IN EFI_BLOCK_IO_PROTOCOL *This,
365 IN UINTN Transfer,
366 IN UINT32 MediaId,
367 IN EFI_LBA Lba,
368 IN UINTN BufferSize,
369 OUT VOID *Buffer
370 ) {
371 UINT32 Response[4];
372 EFI_STATUS Status;
373 UINTN CardSize, NumBlocks, BlockSize, CmdArg;
374 UINTN Timeout;
375 UINTN Cmd;
376 MMC_HOST_INSTANCE *MmcHostInstance;
377 EFI_MMC_HOST_PROTOCOL *MmcHost;
378 UINTN BytesRemainingToBeTransfered;
379 UINTN BlockCount = 1;
380
381 MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS(This);
382 ASSERT(MmcHostInstance != 0);
383 MmcHost = MmcHostInstance->MmcHost;
384 ASSERT(MmcHost);
385
386 if (MmcHost == 0) {
387 return EFI_INVALID_PARAMETER;
388 }
389
390 // Check if a Card is Present
391 if (!MmcHost->IsCardPresent()) {
392 MmcHostInstance->BlockIo.Media->MediaPresent = FALSE;
393 MmcHostInstance->BlockIo.Media->LastBlock = 0;
394 MmcHostInstance->BlockIo.Media->BlockSize = 512; // Should be zero but there is a bug in DiskIo
395 MmcHostInstance->BlockIo.Media->ReadOnly = FALSE;
396 return EFI_NO_MEDIA;
397 }
398
399 // If the driver has not been initialized yet then go into Iddentification Mode
400 if (MmcHostInstance->State == MmcHwInitializationState) {
401 MmcIdentificationMode (MmcHostInstance);
402
403 //Send a command to get Card specific data
404 CmdArg = MmcHostInstance->CardInfo.RCA << 16;
405 Status = MmcHost->SendCommand(MMC_CMD9, CmdArg);
406 if (EFI_ERROR(Status)) {
407 DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD9): Error, Status=%r\n", Status));
408 ASSERT(0);
409 return Status;
410 }
411 //Read Response
412 MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_CSD,Response);
413 PrintCSD(Response);
414
415 if (MmcHostInstance->CardInfo.CardType == SD_CARD_2_HIGH) {
416 ASSERT(0); //TODO: Implementation needed
417 CardSize = MMC_CSD_GET_DEVICESIZE(Response);
418 NumBlocks = ((CardSize + 1) * 1024);;
419 BlockSize = 1 << MMC_CSD_GET_READBLLEN(Response);
420 } else {
421 CardSize = MMC_CSD_GET_DEVICESIZE(Response);
422 NumBlocks = (CardSize + 1) * (1 << (MMC_CSD_GET_DEVICESIZEMULT(Response) + 2));
423 BlockSize = 1 << MMC_CSD_GET_READBLLEN(Response);
424 }
425
426 //For >=2G card, BlockSize may be 1K, but the transfer size is 512 bytes.
427 if (BlockSize > 512) {
428 NumBlocks = MultU64x32(NumBlocks, BlockSize/512);
429 BlockSize = 512;
430 }
431
432 MmcHostInstance->BlockIo.Media->LastBlock = (NumBlocks - 1);
433 MmcHostInstance->BlockIo.Media->BlockSize = BlockSize;
434 MmcHostInstance->BlockIo.Media->ReadOnly = MmcHost->IsReadOnly();
435 MmcHostInstance->BlockIo.Media->MediaPresent = TRUE;
436 MmcHostInstance->BlockIo.Media->MediaId++;
437
438 CmdArg = MmcHostInstance->CardInfo.RCA << 16;
439 Status = MmcHost->SendCommand(MMC_CMD7, CmdArg);
440 if (EFI_ERROR(Status)) {
441 DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD7): Error and Status = %r\n", Status));
442 ASSERT(0);
443 return Status;
444 }
445
446 Status = MmcNotifyState (MmcHostInstance, MmcTransferState);
447 if (EFI_ERROR(Status)) {
448 DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcTransferState\n"));
449 return Status;
450 }
451 } else {
452 // Maybe test if the card has changed to update gMmcMedia information
453 if (MmcHostInstance->State == MmcTransferState) {
454 //DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : MmcTransferState\n"));
455 } else if (MmcHostInstance->State == MmcStandByState) {
456 DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : MmcStandByState\n"));
457 } else {
458 ASSERT(0);
459 }
460 }
461
462 if (Lba > This->Media->LastBlock) {
463 ASSERT(0);
464 return EFI_INVALID_PARAMETER;
465 }
466
467 if ((BufferSize % This->Media->BlockSize) != 0) {
468 ASSERT(0);
469 return EFI_BAD_BUFFER_SIZE;
470 }
471
472 BytesRemainingToBeTransfered = BufferSize;
473 while (BytesRemainingToBeTransfered > 0) {
474
475 //Check if the Card is in Ready status
476 CmdArg = MmcHostInstance->CardInfo.RCA << 16;
477 Response[0] = 0;
478 Timeout = 20;
479 while((Response[0] & (1 << 8)) && Timeout-- ){
480 Status = MmcHost->SendCommand(MMC_CMD13, CmdArg);
481 if (!EFI_ERROR(Status)){
482 MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_R1,Response);
483 }
484 }
485
486 // Set Block Length
487 Status = MmcHost->SendCommand(MMC_CMD16, This->Media->BlockSize);
488 if (EFI_ERROR(Status)) {
489 DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD16): Error This->Media->BlockSize:%d and Error = %r\n",This->Media->BlockSize, Status));
490 return Status;
491 }
492
493 // Block Count (not used). Could return an error for SD card
494 MmcHost->SendCommand(MMC_CMD23, BlockCount);
495
496 //Set command argument based on the card access mode (Byte mode or Block mode)
497 if (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1) {
498 CmdArg = Lba;
499 } else {
500 CmdArg = Lba * This->Media->BlockSize;
501 }
502
503 if (Transfer == MMC_IOBLOCKS_READ) {
504 #ifndef USE_STREAM
505 // Read a single block
506 Cmd = MMC_CMD17;
507 #else
508 //TODO: Should we support read stream (MMC_CMD11)
509 #endif
510 } else {
511 #ifndef USE_STREAM
512 // Write a single block
513 Cmd = MMC_CMD24;
514 #else
515 //TODO: Should we support write stream (MMC_CMD20)
516 #endif
517 }
518 Status = MmcHost->SendCommand(Cmd, CmdArg);
519 if (EFI_ERROR(Status)) {
520 DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD%d): Error %r\n",Cmd, Status));
521 return Status;
522 }
523
524 if (Transfer == MMC_IOBLOCKS_READ) {
525 #ifndef USE_STREAM
526 // Read one block of Data
527 Status = MmcHost->ReadBlockData(Lba,This->Media->BlockSize,Buffer);
528 if (EFI_ERROR(Status)) {
529 DEBUG((EFI_D_BLKIO, "MmcIdentificationMode(): Error Read Block Data and Status = %r\n", Status));
530 return Status;
531 }
532 #else
533 //TODO: Read a steam
534 ASSERT(0);
535 #endif
536 Status = MmcNotifyState (MmcHostInstance, MmcProgrammingState);
537 if (EFI_ERROR(Status)) {
538 DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcProgrammingState\n"));
539 return Status;
540 }
541 } else {
542 #ifndef USE_STREAM
543 // Write one block of Data
544 Status = MmcHost->WriteBlockData(Lba,This->Media->BlockSize,Buffer);
545 if (EFI_ERROR(Status)) {
546 DEBUG((EFI_D_BLKIO, "MmcIdentificationMode(): Error Write Block Data and Status = %r\n", Status));
547 return Status;
548 }
549 #else
550 //TODO: Write a steam
551 ASSERT(0);
552 #endif
553 }
554
555 // Command 12 - Stop transmission (ends read)
556 Status = MmcHost->SendCommand(MMC_CMD12, 0);
557 MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_R1b,Response);
558
559 // Command 13 - Read status and wait for programming to complete (return to tran)
560 Timeout = MMCI0_TIMEOUT;
561 CmdArg = MmcHostInstance->CardInfo.RCA << 16;
562 while ((MMC_R0_CURRENTSTATE(Response) != MMC_R0_STATE_TRAN) && Timeout) {
563 MmcHost->SendCommand(MMC_CMD13, CmdArg);
564 MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_R1,Response);
565 NanoSecondDelay(100);
566 Timeout--;
567 }
568
569 Status = MmcNotifyState (MmcHostInstance, MmcTransferState);
570 if (EFI_ERROR(Status)) {
571 DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcTransferState\n"));
572 return Status;
573 }
574
575 BytesRemainingToBeTransfered -= This->Media->BlockSize;
576 Lba += BlockCount;
577 Buffer = (UINT8 *)Buffer + This->Media->BlockSize;
578 }
579
580 return EFI_SUCCESS;
581 }
582
583 EFI_STATUS
584 EFIAPI
585 MmcReadBlocks (
586 IN EFI_BLOCK_IO_PROTOCOL *This,
587 IN UINT32 MediaId,
588 IN EFI_LBA Lba,
589 IN UINTN BufferSize,
590 OUT VOID *Buffer
591 ) {
592 return MmcIoBlocks (This, MMC_IOBLOCKS_READ, MediaId, Lba, BufferSize, Buffer);
593 }
594
595 EFI_STATUS
596 EFIAPI
597 MmcWriteBlocks (
598 IN EFI_BLOCK_IO_PROTOCOL *This,
599 IN UINT32 MediaId,
600 IN EFI_LBA Lba,
601 IN UINTN BufferSize,
602 IN VOID *Buffer
603 ) {
604 return MmcIoBlocks (This, MMC_IOBLOCKS_WRITE, MediaId, Lba, BufferSize, Buffer);
605 }
606
607 EFI_STATUS
608 EFIAPI
609 MmcFlushBlocks (
610 IN EFI_BLOCK_IO_PROTOCOL *This
611 ) {
612 return EFI_SUCCESS;
613 }
614