summaryrefslogtreecommitdiff
path: root/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe.c
diff options
context:
space:
mode:
Diffstat (limited to 'SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe.c')
-rwxr-xr-xSamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe.c1378
1 files changed, 1378 insertions, 0 deletions
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe.c
new file mode 100755
index 000000000..87f937924
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe.c
@@ -0,0 +1,1378 @@
+/** @file
+ MMC/SD Card driver for Secure Digital Host Controller
+
+ This driver always produces a BlockIo protocol but it starts off with no Media
+ present. A TimerCallBack detects when media is inserted or removed and after
+ a media change event a call to BlockIo ReadBlocks/WriteBlocks will cause the
+ media to be detected (or removed) and the BlockIo Media structure will get
+ updated. No MMC/SD Card harward registers are updated until the first BlockIo
+ ReadBlocks/WriteBlocks after media has been insterted (booting with a card
+ plugged in counts as an insertion event).
+
+ Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include <Library/TimerLib.h>
+#include <Library/PcdLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Protocol/ExynosGpio.h>
+#include <Platform/ArmPlatform.h>
+#include <Platform/Exynos5250.h>
+#include <Platform/Arndale5250.h>
+
+#include "eMMCDxe.h"
+
+
+
+#define DateInformation "20120723_007"
+
+
+MSHC_OPERATION_MODE MSHC_operation_mode=MSHC_FIFO;
+//MSHC_OPERATION_MODE MSHC_operation_mode=MSHC_IDMA;
+
+
+//#undef EFI_D_INFO
+//#define EFI_D_INFO 1
+
+
+
+CARD_INFO gCardInfo;
+BOOLEAN gMediaChange = TRUE;
+BOOLEAN gCardInit = FALSE;
+
+
+EFI_BLOCK_IO_MEDIA gSDMMCMedia = {
+ SIGNATURE_32('e','m','m','c'), // MediaId
+ FALSE, // RemovableMedia
+ TRUE, // MediaPresent
+ FALSE, // LogicalPartition
+ FALSE, // ReadOnly
+ FALSE, // WriteCaching
+ 512, // BlockSize
+ 4, // IoAlign
+ 0, // Pad
+ 0 // LastBlock
+};
+
+typedef struct {
+ VENDOR_DEVICE_PATH Mmc;
+ EFI_DEVICE_PATH End;
+} MSHC_DEVICE_PATH;
+
+MSHC_DEVICE_PATH gMSHCDevicePath = {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ (UINT8)(sizeof(VENDOR_DEVICE_PATH)),
+ (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8),
+ 0xb615f1f5, 0x5088, 0x43cd, 0x80, 0x9c, 0xa1, 0x6e, 0x52, 0x48, 0x7d, 0x00
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ sizeof (EFI_DEVICE_PATH_PROTOCOL),
+ 0
+ }
+};
+
+
+
+//
+// Internal Functions
+//
+
+
+
+
+VOID
+ParseCardCIDData (
+ UINT32 Response0,
+ UINT32 Response1,
+ UINT32 Response2,
+ UINT32 Response3
+ )
+{
+ gCardInfo.CIDData.MDT = ((Response0 >> 8) & 0xFFF);
+ gCardInfo.CIDData.PSN = (((Response0 >> 24) & 0xFF) | ((Response1 & 0xFFFFFF) << 8));
+ gCardInfo.CIDData.PRV = ((Response1 >> 24) & 0xFF);
+ gCardInfo.CIDData.PNM[4] = ((Response2) & 0xFF);
+ gCardInfo.CIDData.PNM[3] = ((Response2 >> 8) & 0xFF);
+ gCardInfo.CIDData.PNM[2] = ((Response2 >> 16) & 0xFF);
+ gCardInfo.CIDData.PNM[1] = ((Response2 >> 24) & 0xFF);
+ gCardInfo.CIDData.PNM[0] = ((Response3) & 0xFF);
+ gCardInfo.CIDData.OID = ((Response3 >> 8) & 0xFFFF);
+ gCardInfo.CIDData.MID = ((Response3 >> 24) & 0xFF);
+}
+
+
+EFI_STATUS
+MSHC_SendCmd (
+ UINTN Cmd,
+ UINTN CmdInterruptEnableVal,
+ UINTN CmdArgument
+ )
+{
+ UINTN MmcStatus = 0;
+ volatile UINTN RetryCount = 0;
+ int cmd_flags = 0;
+ int timeout=0;
+ UINT32 SdMmcBaseAddr;
+ //UINT32 MSHCRintStatus=0;
+
+ DEBUG ((EFI_D_INFO, "CMD = %d\n", (Cmd&0x3F)));
+
+ timeout = MAX_RETRY_COUNT;
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcCH0Base);
+
+ //1. Check if Data busy or not
+ while(MmioRead32(SdMmcBaseAddr + MSHCI_STATUS) & (DATA_BUSY))
+ {
+ if (timeout == 0)
+ {
+ DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd timeout : CMD = %d\n", Cmd));
+ return EFI_DEVICE_ERROR;
+ }
+ timeout--;
+ MicroSecondDelay(1);
+ }
+
+ // 2. Check if Raw interrupt is command done
+ /*MSHCRintStatus = MmioRead32(SdMmcBaseAddr + MSHCI_RINTSTS);
+ if ((MSHCRintStatus & (INTMSK_CDONE|INTMSK_ACD)) == 0)
+ {
+ DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd interrupt error : INT = %x\n", MmioRead32(SdMmcBaseAddr + MSHCI_RINTSTS)));
+ } */
+
+ // 3. Clear Raw interrupt
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_RINTSTS), INTMSK_ALL);
+
+ // 4. prepare data
+ //mshci_reset_fifo();
+
+ //5. Set command argument register
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CMDARG), CmdArgument);
+
+ // 6. transfer data
+
+ //Enable interrupt enable events to occur
+ // EVT1 do not need interrupt mask, use Raw interrupt
+ //MmioWrite32 ((SdMmcBaseAddr + MSHCI_INTMSK), CmdInterruptEnableVal);
+
+ // 7. trasfer data
+
+ //8. Send a command
+ cmd_flags = (Cmd & 0x3F);
+ if(Cmd & (RSPTYP48 | RSPTYP48B | RSPTYP136))
+ {
+ cmd_flags |= CMD_RESP_EXP_BIT;
+ if(Cmd & RSPTYP136)
+ cmd_flags |= CMD_RESP_LENGTH_BIT;
+ }
+
+ if((Cmd==CMD17)|(Cmd==CMD18)|(Cmd==CMD8))
+ {
+ cmd_flags |= CMD_DATA_EXP_BIT;
+ //DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd Read\n"));
+ }
+
+ if((Cmd==CMD24)|(Cmd==CMD25))
+ {
+ cmd_flags |= CMD_DATA_EXP_BIT | CMD_RW_BIT;
+ //DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd Write\n"));
+
+ }
+
+ if (Cmd & ENCMDCRC)
+ {
+ cmd_flags |= CMD_CHECK_CRC_BIT;
+ }
+ cmd_flags |= (CMD_STRT_BIT | CMD_USE_HOLD_REG | CMD_WAIT_PRV_DAT_BIT|CMD_SENT_AUTO_STOP_BIT);
+ //cmd_flags |= (CMD_STRT_BIT | CMD_USE_HOLD_REG | CMD_WAIT_PRV_DAT_BIT);
+ DEBUG ((EFI_D_INFO, "CMD flag = 0x%x\n", cmd_flags));
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CMD), cmd_flags);
+ MicroSecondDelay(1);
+
+ //9. Check for the Raw interrupt
+ //wait for command complete by busy waiting.
+ for (RetryCount; RetryCount<MAX_RETRY_COUNT; RetryCount++)
+ {
+ MmcStatus = MmioRead32(SdMmcBaseAddr + MSHCI_RINTSTS);
+ if (MmcStatus & INTMSK_CDONE)
+ {
+ break;
+ }
+ }
+
+ if (RetryCount == MAX_RETRY_COUNT)
+ {
+ DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd timeout CMD:%d RINT:0x%x\n",(Cmd&0x3F) ,MmcStatus));
+ return EFI_TIMEOUT;
+ }
+
+ if(MmcStatus & INTMSK_RTO)
+ {
+ DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd Response timeout CMD:%d RINT:0x%x\n", (Cmd & 0x3F),MmcStatus));
+ return EFI_TIMEOUT;
+
+ }
+ else if (MmcStatus & INTMSK_RE)
+ {
+ DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd Response Error RINT:0x%x\n", MmcStatus));
+ return EFI_TIMEOUT;
+ }
+ else if(MmcStatus & INTMSK_RCRC)
+ DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd Response CRC Err RINT:0x%x\n", MmcStatus));
+ else if(MmcStatus & INTMSK_DCRC)
+ DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd Data CRC Err RINT:0x%x\n", MmcStatus));
+ else if(MmcStatus & INTMSK_HLE)
+ DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd HLE Err RINT:0x%x\n", MmcStatus));
+ else if(MmcStatus & INTMSK_SBE)
+ DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd SBE Err RINT:0x%x\n", MmcStatus));
+ else if(MmcStatus & INTMSK_EBE)
+ DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd EBE Err RINT:0x%x\n", MmcStatus));
+
+ return EFI_SUCCESS;
+}
+
+/**
+Super block size : 4MB (16GB density)
+Argument (Boot Size) =(Number of Super Block for boot partition) / 2
+
+**/
+EFI_STATUS MSHC_BOOT_Partition(UINT32 bootsize, UINT32 rpmbsize)
+{
+ UINTN CmdArgument;
+ EFI_STATUS Status = RETURN_SUCCESS;
+ UINT32 BootSize, RPMBSize;
+
+ /* Only use this command for raw eMMC moviNAND */
+ /* Enter backdoor mode */
+ CmdArgument = 0xefac62ec;
+ Status = MSHC_SendCmd (CMD62, CMD62_INT_EN, CmdArgument);
+
+ /* Boot partition changing mode */
+ CmdArgument = 0xcbaea7;
+ Status = MSHC_SendCmd (CMD62, CMD62_INT_EN, CmdArgument);
+
+ //BootSize = ((bootsize*1024)/128);
+ BootSize = (bootsize*2);
+
+ /* Arg: boot partition size */
+ CmdArgument = BootSize;
+ Status = MSHC_SendCmd (CMD62, CMD62_INT_EN, CmdArgument);
+
+ //RPMBSize = ((rpmbsize*1024)/128);
+ RPMBSize = (rpmbsize*2);
+
+ /* Arg: RPMB partition size */
+ CmdArgument = RPMBSize;
+ Status = MSHC_SendCmd (CMD62, CMD62_INT_EN, CmdArgument);
+
+ return Status;
+
+}
+
+EFI_STATUS MSHC_EMMC_Boot_Open()
+{
+ UINTN CmdArgument;
+ EFI_STATUS Status = RETURN_SUCCESS;
+
+ DEBUG ((EFI_D_INFO, "emmc open\n" ));
+ /* Boot ack enable, boot partition enable , boot partition access */
+ CmdArgument = ((3<<24)|(179<<16)|(((1<<6)|(1<<3)|(1<<0))<<8));
+ Status = MSHC_SendCmd (ACMD6, ACMD6_INT_EN, CmdArgument);
+ if (!EFI_ERROR(Status))
+ {
+ /* 4bit transfer mode at booting time. */
+ CmdArgument = ((3<<24)|(177<<16)|((1<<0)<<8));
+ Status = MSHC_SendCmd (ACMD6, ACMD6_INT_EN, CmdArgument);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "emmc open fail 2nd CMD6\n" ));
+ }
+ }
+ else
+ {
+ DEBUG ((EFI_D_ERROR, "emmc open fail first CMD6\n" ));
+ }
+
+ return Status;
+}
+
+EFI_STATUS MSHC_EMMC_Boot_Close()
+{
+ UINTN CmdArgument;
+ EFI_STATUS Status = RETURN_SUCCESS;
+
+ DEBUG ((EFI_D_INFO, "emmc close\n" ));
+ CmdArgument = ((3<<24)|(179<<16)|(((1<<6)|(1<<3)|(0<<0))<<8));
+ Status = MSHC_SendCmd (ACMD6, ACMD6_INT_EN, CmdArgument);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "emmc close fail \n" ));
+ }
+ return Status;
+}
+
+
+void PrintCardInfo()
+{
+ DEBUG ((EFI_D_INFO, "MSHC::READ_BL_LEN %d\n", gCardInfo.CSDData.READ_BL_LEN));
+ DEBUG ((EFI_D_INFO, "MSHC::CSize %d\n", gCardInfo.CSDData.C_SIZELow2 | (gCardInfo.CSDData.C_SIZEHigh10 << 2)));
+ DEBUG ((EFI_D_INFO, "MSHC::MULTI %d\n", gCardInfo.CSDData.C_SIZE_MULT));
+
+}
+
+
+#define EXT_CSD_SIZE 128
+UINT32 Ext_csd[EXT_CSD_SIZE];
+VOID GetEXTCSD()
+{
+ gCardInfo.NumBlocks = 0;
+ gCardInfo.TotalNumBlocks = 30801920;
+
+ UINTN cmdarg = 0;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+ (EXT_CSD_HS_TIMING << 16) |
+ (0 << 8);
+ Status = MSHC_SendCmd (ACMD6, ACMD6_INT_EN, cmdarg);
+
+ cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+ (EXT_CSD_BUS_WIDTH << 16) |
+ (EXT_CSD_BUS_WIDTH_1 << 8);
+ Status = MSHC_SendCmd (ACMD6, ACMD6_INT_EN, cmdarg);
+
+ cmdarg = 0;
+ Status = MSHC_SendCmd (CMD8, CMD8_INT_EN, cmdarg);
+
+ gCardInfo.BlockSize = BLEN_512BYTES;
+
+ if (!EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_INFO, "MSHC::EXT CSD \n"));
+ //PrepareTransfer(&Ext_csd[0], 1, READ);
+ //MSHC_ReadDMA(&Ext_csd[0], 1);
+ MSHC_ReadFIFO(EXT_CSD_SIZE, &Ext_csd[0]);
+ gCardInfo.NumBlocks = Ext_csd[EXT_CSD_SEC_CNT/4];
+ gCardInfo.Extcsd.boot_size_multi = Ext_csd[BOOT_SIZE_MULTI/4];
+ gCardInfo.Extcsd.boot_size_multi = (gCardInfo.Extcsd.boot_size_multi>>16)&0xff;
+ //MicroSecondDelay(5000);
+
+ DEBUG ((EFI_D_INFO, "MSHC::num blocks %d\n", gCardInfo.NumBlocks));
+ DEBUG ((1, "MSHC::eMMC Size:%dMB\n", (gCardInfo.NumBlocks/2048)));
+ DEBUG ((1, "MSHC::Boot partition Size:%dMB\n", ((gCardInfo.TotalNumBlocks-gCardInfo.NumBlocks)/2048)));
+ DEBUG ((EFI_D_INFO, "MSHC::Ext CSD boot block %d\n", (gCardInfo.Extcsd.boot_size_multi)));
+
+ }
+ else
+ {
+ gCardInfo.NumBlocks = 0x1D4C000;
+ DEBUG ((EFI_D_ERROR, "MSHC:: default block number : 0x1D4C000"));
+ }
+
+}
+
+
+EFI_STATUS
+PerformCardIdenfication (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN CmdArgument = 0;
+ //UINTN Response = 0;
+ //UINTN RetryCount = 0;
+ UINTN TempRes0,TempRes1,TempRes2,TempRes3;
+ //BOOLEAN SDCmd8Supported = FALSE;
+ UINT32 SdMmcBaseAddr;
+ int timeout = MAX_RETRY_COUNT;
+
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcCH0Base);
+ gCardInfo.CardType = MMC_CARD;
+
+ //1. Send CMD0 command. go to IDLE
+ Status = MSHC_SendCmd (CMD0, CMD0_INT_EN, CmdArgument);
+
+ // 2. Send CMD1 while OCR is not busy and get OCR register
+ do {
+ CmdArgument = OCR_HCS | MMC_VDD_32_33 | MMC_VDD_33_34;
+ Status = MSHC_SendCmd (CMD1, CMD1_INT_EN, CmdArgument);
+
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "MSHC::CMD1 fails.\n"));
+ }
+
+ MicroSecondDelay(100);
+ } while (!(MmioRead32 (SdMmcBaseAddr + MSHCI_RESP0)& OCR_BUSY) && timeout--);
+
+ if (timeout <= 0)
+ {
+ DEBUG ((EFI_D_ERROR, "MSHC::CMD1 OCR busy timeout.\n"));
+ return EFI_DEVICE_ERROR;
+ }
+ DEBUG ((EFI_D_INFO, "MSHC::CMD1 OCR 0x%x\n", MmioRead32(SdMmcBaseAddr + MSHCI_RESP0)));
+
+ ((UINT32 *) &(gCardInfo.OCRData))[0] = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP0));
+
+ //3. send CMD2 to get CID register
+ CmdArgument = 0;
+ Status = MSHC_SendCmd (CMD2, CMD2_INT_EN, CmdArgument);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "CMD2 fails. Status: %x\n", Status));
+ return Status;
+ }
+
+ DEBUG ((EFI_D_INFO, "CMD2 response: %x %x %x %x\n", MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP0)), \
+ MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP1)), \
+ MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP2)), \
+ MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP3))));
+
+ TempRes0 = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP0));
+ TempRes1 = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP1));
+ TempRes2 = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP2));
+ TempRes3 = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP3));
+
+ //Parse CID register data.
+ ParseCardCIDData(TempRes0 << 8, (TempRes1 << 8) | (TempRes0 >> 24),
+ (TempRes2 << 8) | (TempRes1 >> 24), (TempRes3 << 8) | (TempRes2 >> 24));
+
+ //4. send CMD3 to get RCA register
+ CmdArgument = 0;
+ Status = MSHC_SendCmd (CMD3, CMD3_INT_EN, CmdArgument);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "CMD3 fails. Status: %x\n", Status));
+ return Status;
+ }
+
+ //Set RCA for the detected card. RCA is CMD3 response.
+ DEBUG ((EFI_D_INFO, "MSHC::CMD3 RCA 0x%x\n", MmioRead32(SdMmcBaseAddr + MSHCI_RESP0)));
+ gCardInfo.RCA = (MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP0)) >> 16);
+ DEBUG ((EFI_D_INFO, "CMD3 response: RCA %x\n", gCardInfo.RCA));
+
+ gBS->Stall(1000); //Need Debug by wprkfgur
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+GetCardSpecificData (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN CmdArgument;
+ UINTN TempRes[4],i;
+ UINT32 SdMmcBaseAddr;
+
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcCH0Base);
+
+ //Send CMD9 to retrieve CSD.
+ CmdArgument = gCardInfo.RCA << 16;
+ Status = MSHC_SendCmd (CMD9, CMD9_INT_EN, CmdArgument);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "CMD9 fails. Status: %x\n", Status));
+ return Status;
+ }
+
+ TempRes[0] = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP0));
+ TempRes[1] = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP1));
+ TempRes[2] = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP2));
+ TempRes[3] = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP3));
+
+ //Populate 128-bit CSD register data.
+ for (i = 0 ; i < 4; i++) {
+ ((UINT32 *)&(gCardInfo.CSDData))[i] = TempRes[i];
+ }
+
+ DEBUG ((EFI_D_INFO, "CMD9 response: %x %x %x %x\n", ((UINT32 *)&(gCardInfo.CSDData))[0], ((UINT32 *)&(gCardInfo.CSDData))[1], ((UINT32 *)&(gCardInfo.CSDData))[2], ((UINT32 *)&(gCardInfo.CSDData))[3]));
+ return Status;
+}
+
+EFI_STATUS
+PerformCardConfiguration (
+ VOID
+ )
+{
+ UINTN CmdArgument = 0;
+ EFI_STATUS Status;
+ UINT32 SdMmcBaseAddr;
+ //UINTN FifoCount = 0;
+ //UINTN Count=0;
+ UINT32 OMval;
+
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcCH0Base);
+ OMval = MmioRead32(0x10040000);
+ DEBUG ((EFI_D_INFO, "MSHC::OM read 0x%x \n", OMval));
+
+ //Send CMD7
+ CmdArgument = gCardInfo.RCA << 16;
+ Status = MSHC_SendCmd (CMD7, CMD7_INT_EN, CmdArgument);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "CMD7 fails. Status: %x\n", Status));
+ return Status;
+ }
+
+ //Send CMD16 to set the block length
+ //CmdArgument = gCardInfo.BlockSize;
+ CmdArgument = BLEN_512BYTES;
+ Status = MSHC_SendCmd (CMD16, CMD16_INT_EN, CmdArgument);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "CMD16 fails. Status: %x\n", Status));
+ return Status;
+ }
+
+ if(OMval!=OM_EMMC)
+ {
+ GetEXTCSD();
+ if(gCardInfo.Extcsd.boot_size_multi!= MSHC_BOOT_SIZE_MULTI)
+ {
+ MSHC_BOOT_Partition(MSHC_BOOT_SIZE, MSHC_RPMB_SIZE);
+ DEBUG ((EFI_D_INFO, "MSHC::Doing Boot partition \n"));
+ }
+ else
+ {
+ DEBUG ((EFI_D_INFO, "MSHC::Alread boot partition \n", Status));
+ }
+ }
+ else
+ {
+ DEBUG ((1, "MSHC::eMMC booting \n"));
+ gCardInfo.TotalNumBlocks = 30801920;
+ gCardInfo.NumBlocks = 30588928;
+ }
+
+ // set device into 4-bit data bus mode
+ //Status = MSHC_SendCmd (ACMD6, ACMD6_INT_EN, 0x2);
+ // set device into 8-bit data bus mode
+ CmdArgument = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+ (EXT_CSD_BUS_WIDTH <<16) |
+ (EXT_CSD_BUS_WIDTH_8_DDR <<8);
+ Status = MSHC_SendCmd (ACMD6, ACMD6_INT_EN, CmdArgument);
+ if (!EFI_ERROR (Status)) {
+ // Set host controler into 8-bit mode
+ MmioOr32 ((SdMmcBaseAddr + MSHCI_CTYPE), CARD_WIDTH8);
+ //MmioOr32 ((SdMmcBaseAddr + MSHCI_CTYPE), CARD_WIDTH14);
+ DEBUG ((EFI_D_INFO, "8-bit mode\n"));
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ReadBlockData (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ OUT VOID *Buffer,
+ IN UINTN BlockCount
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ UINTN DataSize = This->Media->BlockSize/4;
+
+ DEBUG ((EFI_D_INFO, "MSHC::ReadBlockData start \n"));
+
+ if(MSHC_operation_mode == MSHC_FIFO)
+ {
+ Status = MSHC_ReadFIFO(DataSize, Buffer);
+ }
+
+ else if(MSHC_operation_mode == MSHC_IDMA)
+ {
+ Status = MSHC_ReadDMA(Buffer, BlockCount);
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS
+WriteBlockData (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ OUT VOID *Buffer,
+ IN UINTN BlockCount
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ UINTN DataSize = This->Media->BlockSize/4;
+
+ if(MSHC_operation_mode == MSHC_FIFO)
+ {
+ Status = MSHC_WriteFIFO(DataSize, Buffer);
+ }
+ else if(MSHC_operation_mode == MSHC_IDMA)
+ {
+ Status = MSHC_WriteDMA(Buffer, BlockCount);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EraseBlockData (
+ IN UINT32 Partition,
+ IN UINTN StartBlock,
+ IN UINTN NumBlock
+ )
+{
+ UINTN cmdarg = 0;
+ EFI_STATUS status = EFI_SUCCESS;
+
+ if(Partition!=MSHC_BOOT_PARTITION)
+ {
+ DEBUG ((EFI_D_ERROR, "EraseBlockData failed \n"));
+ status = EFI_UNSUPPORTED;
+ goto Exit;
+ }
+
+ /* MMC High Capacity erase minimum size is 512KB */
+ if (NumBlock < 1024) {
+ if (NumBlock < 512)
+ NumBlock = 1;
+ else
+ NumBlock = 2;
+ } else {
+ if (0 == (NumBlock%1024)) {
+ NumBlock = (NumBlock / 1024);
+ } else {
+ NumBlock = (NumBlock / 1024) + 1;
+ }
+ }
+ DEBUG ((EFI_D_INFO, "EraseBlockData start:%d, Numblock:%d\n", StartBlock, NumBlock));
+
+ cmdarg = StartBlock;
+ status = MSHC_SendCmd (CMD35, 0, cmdarg);
+ if(status!=EFI_SUCCESS)
+ {
+ DEBUG ((EFI_D_ERROR, "EraseBlockData CMD35 failed \n"));
+ status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ cmdarg = StartBlock + NumBlock;
+ status = MSHC_SendCmd (CMD36, 0, cmdarg);
+ if(status!=EFI_SUCCESS)
+ {
+ DEBUG ((EFI_D_ERROR, "EraseBlockData CMD36 failed \n"));
+ status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ cmdarg = 0;
+ status = MSHC_SendCmd (CMD38, 0, cmdarg);
+ if(status!=EFI_SUCCESS)
+ {
+ DEBUG ((EFI_D_ERROR, "EraseBlockData CMD38 failed \n"));
+ status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ Exit:
+
+ return status;
+}
+
+
+EFI_STATUS
+TransferBlock (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINTN Lba,
+ IN OUT VOID *Buffer,
+ IN UINTN BlockCount,
+ IN OPERATION_TYPE OperationType
+ )
+{
+ EFI_STATUS Status;
+ UINTN Cmd = 0;
+ UINTN CmdInterruptEnable = 0;
+ UINTN CmdArgument = 0;
+
+ // 1. FIFO reset
+ // MSHC_SendCmd do the fifo reset
+
+ // 2. prepare transfer
+
+ DEBUG ((EFI_D_INFO, "SDHC::TransferBlock : Lba = %d, Buffer = 0x%x, Type = %d\n", Lba, Buffer, OperationType));
+ //Populate the command information based on the operation type.
+ if (OperationType == READ)
+ {
+ if(BlockCount>1)
+ {
+ Cmd = CMD18; //multi block read
+ CmdInterruptEnable = CMD18_INT_EN;
+ }
+ else
+ {
+ Cmd = CMD17; //Single block read
+ CmdInterruptEnable = CMD17_INT_EN;
+ }
+
+ }
+ else if (OperationType == WRITE)
+ {
+ if(BlockCount>1)
+ {
+ Cmd = CMD25; //multi block write
+ CmdInterruptEnable = CMD25_INT_EN;
+ }
+ else
+ {
+ Cmd = CMD24; //Single block write
+ CmdInterruptEnable = CMD24_INT_EN;
+ }
+ }
+ PrepareTransfer(Buffer, BlockCount, OperationType);
+
+ //Set command argument based on the card access mode (Byte mode or Block mode)
+ if (gCardInfo.OCRData.AccessMode & BIT1) {
+ CmdArgument = Lba;
+ } else {
+ CmdArgument = Lba * This->Media->BlockSize;
+ }
+
+ //Send Command.
+ Status = MSHC_SendCmd (Cmd, CmdInterruptEnable, CmdArgument);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "CMD%d fails. Status: %x\n", (Cmd&0x3F), Status));
+ return Status;
+ }
+
+ DEBUG ((EFI_D_INFO, "CMD%d succeed! \n", (Cmd&0x3F)));
+
+ //Read or Write data.
+ if (OperationType == READ) {
+ Status = ReadBlockData (This, Buffer, BlockCount);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "ReadBlockData fails.\n"));
+ return Status;
+ }
+ } else if (OperationType == WRITE) {
+ Status = WriteBlockData (This, Buffer, BlockCount);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "WriteBlockData fails.\n"));
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+CardPresent (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+EFI_STATUS
+DetectCard (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ //UINT32 SdMmcBaseAddr;
+
+ //DEBUG ((EFI_D_INFO, "===================================\n"));
+ DEBUG ((EFI_D_INFO, "===MSHC: Version %a ===\n", DateInformation));
+ //DEBUG ((EFI_D_INFO, "===================================\n"));
+
+ //SdMmcBaseAddr = PcdGet32(PcdSdMmcCH0Base);
+
+ if (!CardPresent ()) {
+ return EFI_NO_MEDIA;
+ }
+
+ //Initialize MMC host controller clocks.
+ Status = InitializeMSHC ();
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "Initialize MMC host controller fails. Status: %x\n", Status));
+ return Status;
+ }
+
+ // EVT1 InitializeSDHC do the SW Reset
+ //Soft reset for all.
+ //MmioWrite32((SdMmcBaseAddr + SDHC_SWRST_OFFSET), SRA);
+ //gBS->Stall(1000);
+ //while ((MmioRead32 ((SdMmcBaseAddr + SDHC_SWRST_OFFSET)) & SRA) != 0x0);
+
+ //Set the clock frequency to 400KHz.
+ UpdateMSHCClkFrequency (MSHC_CLK_400);
+
+ //Card idenfication
+ Status = PerformCardIdenfication ();
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "No MMC/SD card detected.\n"));
+ return Status;
+ }
+
+ //Get CSD (Card specific data) for the detected card.
+ Status = GetCardSpecificData();
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //Configure the card in data transfer mode.
+ Status = PerformCardConfiguration();
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //Patch the Media structure.
+ gSDMMCMedia.LastBlock = (gCardInfo.NumBlocks - 1);
+ //gSDMMCMedia.BlockSize = gCardInfo.BlockSize;
+ gSDMMCMedia.BlockSize = 512;
+ gSDMMCMedia.ReadOnly = 0;
+ gSDMMCMedia.MediaPresent = TRUE;
+ gSDMMCMedia.MediaId++;
+
+ UpdateMSHCClkFrequency(MSHC_CLK_50M);
+ DEBUG ((EFI_D_INFO, "SD Card Media Change on Handle 0x%08x\n", gImageHandle));
+
+ return Status;
+}
+
+
+EFI_STATUS
+SdReadWrite (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINTN Lba,
+ OUT VOID *Buffer,
+ IN UINTN BufferSize,
+ IN OPERATION_TYPE OperationType
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINTN RetryCount = 0;
+ UINTN BlockCount;
+ UINTN BytesToBeTranferedThisPass = 0;
+ UINTN BytesRemainingToBeTransfered=0;
+ EFI_TPL OldTpl;
+ //BOOLEAN Update;
+ UINT32 SdMmcBaseAddr;
+
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcCH0Base);
+
+ if(gMediaChange==TRUE)
+ {
+ Status = DetectCard();
+ gMediaChange = FALSE;
+ gCardInit = TRUE;
+ }
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "MSHC::Card initialization fail .\n"));
+ gCardInit = FALSE;
+ goto Done;
+ }
+
+if(gCardInit)
+{
+ DEBUG ((EFI_D_INFO, "MSHC::SdReadWrite is called Buffersize:%d \n", BufferSize));
+
+ if (Buffer == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if (Lba > This->Media->LastBlock) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((EFI_D_ERROR, "MSHC::SdReadWrite EFI_INVALID_PARAMETER\n"));
+ goto Done;
+ }
+
+ if ((BufferSize % This->Media->BlockSize) != 0) {
+ Status = EFI_BAD_BUFFER_SIZE;
+ DEBUG ((EFI_D_ERROR, "MSHC::SdReadWrite EFI_BAD_BUFFER_SIZE\n"));
+ goto Done;
+ }
+
+ //Check if the data lines are not in use.
+ while ((RetryCount++ < MAX_RETRY_COUNT) && (MmioRead32 ((SdMmcBaseAddr + MSHCI_STATUS)) & DATA_BUSY));
+ if (RetryCount == MAX_RETRY_COUNT) {
+ Status = EFI_TIMEOUT;
+ DEBUG ((EFI_D_ERROR, "MSHC::SdReadWrite EFI_TIMEOUT\n"));
+ goto Done;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ BytesRemainingToBeTransfered = BufferSize;
+
+ if(MSHC_operation_mode == MSHC_IDMA)
+ {
+ while (BytesRemainingToBeTransfered > 0) {
+ // Turn OFF DMA path until it is debugged
+ BytesToBeTranferedThisPass = (BytesRemainingToBeTransfered >= MAX_MSHC_TRANSFER_SIZE) ? MAX_MSHC_TRANSFER_SIZE : BytesRemainingToBeTransfered;
+ //BytesToBeTranferedThisPass = This->Media->BlockSize;
+
+ BlockCount = BytesToBeTranferedThisPass/This->Media->BlockSize;
+ Status = TransferBlock (This, Lba, Buffer,BlockCount, OperationType);
+
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "TransferBlockData fails. %x\n", Status));
+ goto DoneRestoreTPL;
+ }
+
+ BytesRemainingToBeTransfered -= BytesToBeTranferedThisPass;
+ Lba += BlockCount;
+ Buffer = (UINT8 *)Buffer + (This->Media->BlockSize*BlockCount);
+ DEBUG ((EFI_D_INFO, "SdReadWrite::Buf:0x%x, ToBe:0x%x Rema:0x%x \n", BufferSize, BytesToBeTranferedThisPass, BytesRemainingToBeTransfered));
+
+ }
+ }
+ else
+ {
+ while (BytesRemainingToBeTransfered > 0) {
+ // Turn OFF DMA path until it is debugged
+ // BytesToBeTranferedThisPass = (BytesToBeTranferedThisPass >= MAX_SDHC_TRANSFER_SIZE) ? MAX_SDHC_TRANSFER_SIZE : BytesRemainingToBeTransfered;
+ BytesToBeTranferedThisPass = This->Media->BlockSize;
+
+ BlockCount = BytesToBeTranferedThisPass/This->Media->BlockSize;
+
+ if (BlockCount > 1) {
+ // Status = DmaBlocks (This, Lba, Buffer, BlockCount, OperationType);
+ } else {
+ //Transfer a block worth of data.
+ Status = TransferBlock (This, Lba, Buffer, BlockCount,OperationType);
+
+ }
+
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "TransferBlockData fails. %x\n", Status));
+ goto DoneRestoreTPL;
+ }
+
+ BytesRemainingToBeTransfered -= BytesToBeTranferedThisPass;
+ Lba += BlockCount;
+ Buffer = (UINT8 *)Buffer + This->Media->BlockSize;
+ }
+
+ }
+
+
+DoneRestoreTPL:
+
+ gBS->RestoreTPL (OldTpl);
+
+Done:
+
+ return Status;
+}
+else
+ return EFI_TIMEOUT;
+
+
+}
+
+
+/**
+
+ Reset the Block Device.
+
+
+
+ @param This Indicates a pointer to the calling context.
+
+ @param ExtendedVerification Driver may perform diagnostics on reset.
+
+
+
+ @retval EFI_SUCCESS The device was reset.
+
+ @retval EFI_DEVICE_ERROR The device is not functioning properly and could
+
+ not be reset.
+
+
+
+**/
+EFI_STATUS
+EFIAPI
+MSHCReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ DEBUG ((EFI_D_INFO, " MSHC::MSHCReset is called\n"));
+ MSHC_reset_all();
+ return EFI_SUCCESS;
+}
+
+
+/**
+
+ Read BufferSize bytes from Lba into Buffer.
+
+
+
+ @param This Indicates a pointer to the calling context.
+
+ @param MediaId Id of the media, changes every time the media is replaced.
+
+ @param Lba The starting Logical Block Address to read from
+
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+
+ @param Buffer A pointer to the destination buffer for the data. The caller is
+
+ responsible for either having implicit or explicit ownership of the buffer.
+
+
+
+ @retval EFI_SUCCESS The data was read correctly from the device.
+
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
+
+ @retval EFI_NO_MEDIA There is no media in the device.
+
+ @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
+
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
+
+ or the buffer is not on proper alignment.
+
+EFI_STATUS
+
+**/
+
+
+#define EMMC_TEST 0
+#if EMMC_TEST
+#define EMMC_TEST_SIZE (MAX_MSHC_TRANSFER_SIZE+1024)
+UINT32 bWrite[EMMC_TEST_SIZE];
+UINT32 bRead[EMMC_TEST_SIZE];
+//INTN EFIAPI CompareMem (IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
+//two buffers are identical, then 0 is returned. Otherwise, the value returned is the first mismatched byte
+
+void MSHC_Test( IN EFI_BLOCK_IO_PROTOCOL *This)
+{
+ UINTN i=0;
+ UINTN Count;
+ INTN ret;
+ EFI_STATUS Status;
+ DEBUG ((EFI_D_INFO, "MSHC::Read Write test %dB\n", EMMC_TEST_SIZE));
+
+ for(i=0; i<EMMC_TEST_SIZE; i++)
+ {
+ bWrite[i]=i;
+ }
+
+//multi
+ for(Count=100; Count<102; Count++)
+ {
+ //Lba=n;
+ //DEBUG ((EFI_D_INFO, "MSHC::Read Write test : %d\n", Count));
+ ZeroMem (&bRead[0], sizeof(bRead));
+ DEBUG ((EFI_D_INFO, "ZR : 0x%x, 0x%x, 0x%x, 0x%x\n",
+ bRead[0], bRead[1], bRead[2], bRead[3]));
+
+ Status = SdReadWrite (This, (UINTN)Count, &bWrite[0], EMMC_TEST_SIZE, WRITE);
+ Status = SdReadWrite (This, (UINTN)Count, &bRead[0], EMMC_TEST_SIZE, READ);
+
+ DEBUG ((EFI_D_INFO, "W: 0x%x, 0x%x, 0x%x, 0x%x ",
+ bWrite[0], bWrite[1], bWrite[2], bWrite[3]));
+ DEBUG ((EFI_D_INFO, "R : 0x%x, 0x%x, 0x%x, 0x%x\n",
+ bRead[0], bRead[1], bRead[2], bRead[3]));
+
+ ret = CompareMem(&bRead[0],&bWrite[0],EMMC_TEST_SIZE);
+
+ if(ret==0)
+ DEBUG ((1, "MSHC::Read Write OK!!\n"));
+ else
+ DEBUG ((1, "MSHC::Read Write Failed bWrite[%d]=0x%x : bRead[%d]=0x%x\n", ret, bWrite[ret], ret, bRead[ret]));
+
+
+ }
+
+
+}
+#endif
+
+
+#define FVB_TEST 0
+
+#if FVB_TEST
+#define FVB_TEST_SIZE 1336//(64)
+#define FVB_Offset 64 //0
+UINT32 FVB_Read[512*3];
+UINT32 FVB_Write[512*3];
+UINT32 Temp[512*3];
+void FVB_Test(IN EFI_BLOCK_IO_PROTOCOL *This)
+{
+ EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *Fvbhandle;
+ EFI_STATUS status = EFI_SUCCESS;
+ EFI_LBA Lba = 10;
+ UINTN NumBytes=FVB_TEST_SIZE;
+ UINT32 i;
+ INTN ret;
+ UINTN Offset=FVB_Offset;
+ //EFI_FVB_ATTRIBUTES_2 *Attribute=NULL;
+ UINTN blocksize=0, numofblocks=0;
+ UINTN EraseStartBlock=10, EraseNumBlocks=5;
+ EFI_PHYSICAL_ADDRESS *Address=NULL;
+
+
+ Fvbhandle = (EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *)This;
+ DEBUG ((1, "FVB_Test Start \n"));
+
+ status = SdReadWrite (This, 0, &Temp[0], 512, READ);
+ if(status!=EFI_SUCCESS)
+ {
+ DEBUG ((1, "FVB_Test Card Init Failed !!\n"));
+ goto Exit;
+ }
+
+ for(i=0; i<512; i++)
+ {
+ FVB_Write[i]=i;
+ }
+ ZeroMem (&FVB_Read[0], 512);
+
+ //DEBUG ((1, "FVB_Test FvbGetAttributes \n"));
+ //FvbGetAttributes(Fvbhandle, Attribute);
+ FvbGetPhysicalAddress(Fvbhandle, Address);
+ FvbGetBlockSize(Fvbhandle, 0, &blocksize, &numofblocks);
+ DEBUG ((1, "FVB_Test erase\n"));
+ FvbEraseBlocks(Fvbhandle, EraseStartBlock, EraseNumBlocks, EFI_LBA_LIST_TERMINATOR);
+
+ DEBUG ((1, "FVB_Test Offset : %d Num : %d\n", Offset, NumBytes));
+ status = FvbWrite(Fvbhandle, Lba, Offset, &NumBytes, (UINT8 *)&FVB_Write[Offset]);
+ if(status!=EFI_SUCCESS)
+ {
+ DEBUG ((1, "FVB_Test write fail !!\n"));
+ goto Exit;
+ }
+
+ status = FvbRead(Fvbhandle, Lba, Offset, &NumBytes, (UINT8 *)&FVB_Read[0]);
+ if(status!=EFI_SUCCESS)
+ {
+ DEBUG ((1, "FVB_Test read fail !!\n"));
+ goto Exit;
+ }
+
+ DEBUG ((1, "FVB W: 0x%x, 0x%x, 0x%x, 0x%x ",
+ FVB_Write[Offset], FVB_Write[Offset+1], FVB_Write[Offset+2], FVB_Write[Offset+3]));
+ DEBUG ((1, "FVB R : 0x%x, 0x%x, 0x%x, 0x%x\n",
+ FVB_Read[0], FVB_Read[1], FVB_Read[2], FVB_Read[3]));
+
+ ret = CompareMem(&FVB_Write[Offset], &FVB_Read[0], FVB_TEST_SIZE);
+
+ if(ret==0)
+ DEBUG ((1, "MSHC::FVB_Test OK!!\n"));
+ else
+ DEBUG ((1, "MSHC::ERROR !!! FVB_Test Failed bWrite[%d]=0x%x : bRead[%d]=0x%x\n", ret, FVB_Write[ret], ret, FVB_Read[ret]));
+
+ Exit:
+ if(status!=EFI_SUCCESS)
+ DEBUG ((1, "FVB_Test fail !!\n"));
+
+}
+
+#endif
+
+
+
+EFI_STATUS
+EFIAPI
+MSHCReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status=EFI_SUCCESS;
+ DEBUG ((EFI_D_INFO, "MSHC::MSHCReadBlocks : MediaId = %x, Lba = %d, BufferSize = %d, Buffer = 0x%x\n",
+ MediaId, (UINTN)Lba, BufferSize, Buffer));
+
+ Status = SdReadWrite (This, (UINTN)Lba, Buffer, BufferSize, READ);
+
+#if 0
+#if FVB_TEST
+ FVB_Test(This);
+#else
+#if EMMC_TEST
+ MSHC_Test(This);
+#else
+ //Perform Read operation.
+ Status = SdReadWrite (This, (UINTN)Lba, Buffer, BufferSize, READ);
+#endif
+#endif //#if FVB_TEST
+#endif
+
+ return Status;
+
+}
+
+
+/**
+
+ Write BufferSize bytes from Lba into Buffer.
+
+
+
+ @param This Indicates a pointer to the calling context.
+
+ @param MediaId The media ID that the write request is for.
+
+ @param Lba The starting logical block address to be written. The caller is
+
+ responsible for writing to only legitimate locations.
+
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+
+ @param Buffer A pointer to the source buffer for the data.
+
+
+
+ @retval EFI_SUCCESS The data was written correctly to the device.
+
+ @retval EFI_WRITE_PROTECTED The device can not be written to.
+
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
+
+ @retval EFI_NO_MEDIA There is no media in the device.
+
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
+
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
+
+ or the buffer is not on proper alignment.
+
+
+
+**/
+
+
+EFI_STATUS
+EFIAPI
+MSHCWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+#if EMMC_TEST
+ UINT32 Count=0;
+ UINT32 ret;
+#endif
+
+ DEBUG ((EFI_D_INFO, "MSHC::MSHCWriteBlocks : MediaId = 0x%x, Lba = %d, BufferSize = %d, Buffer = 0x%x\n",
+ MediaId, (UINTN)Lba, BufferSize, Buffer));
+
+ //Perform write operation.
+ Status = SdReadWrite (This, (UINTN)Lba, Buffer, BufferSize, WRITE);
+
+
+#if 0
+#if EMMC_TEST
+ Count = (BufferSize >= MAX_MSHC_TRANSFER_SIZE) ? MAX_MSHC_TRANSFER_SIZE : BufferSize;
+ DEBUG ((1, "\nMSHC::Read Write Test [0x%x] Start \n", Count));
+ ZeroMem (&bRead[0], sizeof(bRead));
+ CopyMem(&bWrite[0], (VOID *)Buffer, Count);
+ Status = SdReadWrite (This, (UINTN)Lba, &bRead[0], Count, READ);
+ DEBUG ((1, "W : 0x%x, 0x%x, 0x%x, 0x%x\n",
+ bWrite[7], bWrite[8], bWrite[9], bWrite[10]));
+
+ DEBUG ((1, "R : 0x%x, 0x%x, 0x%x, 0x%x\n",
+ bRead[7], bRead[8], bRead[9], bRead[10]));
+
+ ret = CompareMem(&bRead[0],&bWrite[0],Count);
+
+ if(ret==0)
+ DEBUG ((1, "MSHC::Read Write Test OK!!\n"));
+ else
+ DEBUG ((1, "MSHC::Read Write Test Failed -.- bRead[%d]=0x%x bWrite[%d]=0x%x \n", ret, bRead[ret], ret, bWrite[ret]));
+
+#endif
+#endif
+
+
+ return Status;
+
+}
+
+
+/**
+
+ Flush the Block Device.
+
+
+
+ @param This Indicates a pointer to the calling context.
+
+
+
+ @retval EFI_SUCCESS All outstanding data was written to the device
+
+ @retval EFI_DEVICE_ERROR The device reported an error while writting back the data
+
+ @retval EFI_NO_MEDIA There is no media in the device.
+
+
+
+**/
+EFI_STATUS
+EFIAPI
+MSHCFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+{
+ DEBUG ((EFI_D_INFO, "MSHC::MSHCFlushBlocks is called\n"));
+ return EFI_SUCCESS;
+}
+
+
+EFI_BLOCK_IO_PROTOCOL gBlockIo = {
+ EFI_BLOCK_IO_INTERFACE_REVISION, // Revision
+ &gSDMMCMedia, // *Media
+ MSHCReset, // Reset
+ MSHCReadBlocks, // ReadBlocks
+ MSHCWriteBlocks, // WriteBlocks
+ MSHCFlushBlocks // FlushBlocks
+};
+
+
+EFI_STATUS
+EFIAPI
+MSHCInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ ZeroMem (&gCardInfo, sizeof (CARD_INFO));
+
+//Publish BlockIO.
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gEfiBlockIoProtocolGuid, &gBlockIo,
+ &gEfiDevicePathProtocolGuid, &gMSHCDevicePath,
+ NULL
+ );
+
+ DEBUG ((EFI_D_INFO, "MSHC::MSHCInitialize:0x%x\n", Status));
+ return Status;
+}