[Feature]Upload Modem source code

Change-Id: Id4294f30faced84d3e6fd6d5e61e1111bf287a37
diff --git a/mcu/driver/storage/mc/src/sd.c b/mcu/driver/storage/mc/src/sd.c
new file mode 100644
index 0000000..a35e6be
--- /dev/null
+++ b/mcu/driver/storage/mc/src/sd.c
@@ -0,0 +1,6853 @@
+ /*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   sd.c
+ *
+ * Project:
+ * --------
+ *   Maui_Software
+ *
+ * Description:
+ * ------------
+ *   driver functons for SD/MMC
+ *
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+#include "drv_features.h"
+#ifndef DRV_MSDC_OFF
+#include "kal_public_api.h" //MSBB change #include "kal_release.h"
+
+#include "kal_general_types.h"
+//#include "btif_sw.h"
+//#include "kal_public_api.h"
+#include "kal_public_defs.h"
+#include "kal_debug.h"
+#include "init.h"
+
+#include "kal_trace.h"
+#include "dcl.h"
+#include "drv_comm.h"
+#include "drv_features.h"
+#include "kal_public_defs.h" //MSBB change #include "stack_config.h"
+#include "qmu_bm.h"
+#include "qmu_bm_util.h"
+
+#if !defined(__UBL__) || defined(__CARD_DOWNLOAD__) || defined(__EMMC_BOOTING__)
+#include "us_timer.h"
+#include "msdc_reg_adap.h"
+#include "reg_base.h"
+#include "msdc_api.h"
+#include "msdc_def.h"
+#include "sd_def.h"
+#include "upll_ctrl.h"
+#include "drv_trc.h"
+#if defined(__AUDIO_DSP_LOWPOWER__)
+#include "audlp_exp.h"
+#endif
+
+#if defined(__EMMC_BOOTING__)
+#include "FTL.h"
+#endif
+
+#ifdef DRV_LSD
+#include "msdc_lsd.h"
+
+
+
+extern void LSD_Host74TCMDHigh(void);
+extern kal_bool LSD_HostDetectBusy(void);
+#endif
+
+#if defined(__MSDC_SD_MMC__)
+//global variables
+T_SDC_HANDLE	gSD_blk[SD_NUM];
+T_SDC_HANDLE	*gSD = gSD_blk;
+
+/*global veriable ,operation by DMA ,alloc in uncached memory*/
+#ifdef MSDC_GPD_BD_BUF_CACHED
+msdc_gpd_t MSDC_gpd[SD_NUM];
+msdc_gpd_t MSDC_gpd_end[SD_NUM];
+
+msdc_bd_t  MSDC_bd[SD_NUM][MSDC_BD_MAX];
+#else
+__attribute__ ( (section ("NONCACHEDRW")))msdc_gpd_t MSDC_gpd[SD_NUM];
+__attribute__ ( (section ("NONCACHEDRW")))msdc_gpd_t MSDC_gpd_end[SD_NUM];
+
+__attribute__ ( (section ("NONCACHEDRW")))msdc_bd_t  MSDC_bd[SD_NUM][MSDC_BD_MAX];
+#endif
+
+//static SDC_CMD_STATUS gblSDsta;
+
+extern MSDC_Custom_Handle msdc_custom_handle;
+void SD_Sleep4Wait(kal_int32 sleep_tick);
+void SD_Use13M_Clock(void);
+extern kal_uint8 MSDC_GetIOCtrlParam(void);
+extern kal_bool INT_USBBoot(void);
+#if defined(DRV_MSDC_LATCH_MT6276_SERIES)
+extern void MSDC_SetLatchTuning(void);
+#else
+extern void MSDC_SetIOCONRegDLT(void);
+#endif//#if defined(DRV_MSDC_LATCH_MT6276_SERIES)
+//kal_uint32 sd_writeFailReason; // fix Lint warning
+#if !defined(DRV_MSDC_LATCH_MT6276_SERIES)
+void SD_SetRedDlt(kal_uint32 redDlt);
+#endif//#if !defined(DRV_MSDC_LATCH_MT6276_SERIES)
+extern void SLA_CustomLogging(kal_char *customJob, kal_int32 saAction); 
+
+/*#ifdef DRV_MSDC_SDC_V3
+static kal_uint32 sd_cmd_extra = ((64) << 24);	// CTOC = 64
+#else
+static kal_uint32 sd_cmd_extra = 0;
+#endif*/
+
+#if defined(__SIM_PLUS__)
+#if !defined(__CUST_NEW__)
+kal_char MSDC_GetClockWithoutSIMPlus(void);
+#endif
+#endif
+
+
+
+#ifdef DCL_MSDC_INTERFACE
+#include "dcl.h"
+
+SDC_CMD_STATUS SD_SetCallBack(MSDC_CALLBACK callback1, MSDC_CALLBACK callback2, MSDC_CALLBACK callback3, MSDC_CALLBACK callback4, MSDC_CALLBACK callback5, MSDC_CALLBACK callback6);
+SDC_CMD_STATUS SD_SetReadTestFlag(kal_uint32 readTestFlag);
+SDC_CMD_STATUS SD_readTest(void);
+SDC_CMD_STATUS SD_SetUpllClock(void);
+
+#ifdef __MEUT__
+SDDriver_t sd_driver_MTK1 =
+{
+    (DCL_SINGLE_BLK_RD)SD_ReadSingleBlock,
+    (DCL_MUL_BLK_RD)SD_ReadMultiBlock,
+    (DCL_SINGLE_BLK_WR)SD_WriteSingleBlock,
+    (DCL_MUL_BLK_WR)SD_WriteMultiBlock,
+    (DCL_SD_INITITALIZE)SD_Initialize,
+    (DCL_SET_PRE_ERASE_CNT)SD_SetPreEraseBlk,
+    (DCL_SD_SET_CALLBACK)SD_SetCallBack,
+    (DCL_SET_READ_TEST_FLAG)SD_SetReadTestFlag,
+    (DCL_SD_READ_TEST)SD_readTest,
+    (DCL_SD_SET_UPLL_CLOCK_TEST)SD_SetUpllClock,
+    (DCL_SD_ERASE_BLK)SD_FlushSectors,
+};
+#else
+SDDriver_t sd_driver_MTK1 =
+{
+    (DCL_SINGLE_BLK_RD)SD_ReadSingleBlock,
+    (DCL_MUL_BLK_RD)SD_ReadMultiBlock,
+    (DCL_SINGLE_BLK_WR)SD_WriteSingleBlock,
+    (DCL_MUL_BLK_WR)SD_WriteMultiBlock,
+    (DCL_SD_INITITALIZE)SD_Initialize,
+    (DCL_SET_PRE_ERASE_CNT)SD_SetPreEraseBlk,
+    (DCL_SD_SET_CALLBACK)NULL,
+    (DCL_SET_READ_TEST_FLAG)NULL,
+    (DCL_SD_READ_TEST)NULL,
+    (DCL_SD_SET_UPLL_CLOCK_TEST)NULL,
+    (DCL_SD_ERASE_BLK)SD_FlushSectors,
+    (DCL_GPD_MUL_BLK_RD)SD_GpdReadMultiBlock,
+    (DCL_GPD_MUL_BLK_WR)SD_GpdWriteMultiBlock,
+};
+#endif
+
+#endif
+
+#if defined( __MSDC_BASIC_LOAD__) || defined( __MEUT__)
+#define MSDC_TESTBUFFER_SIZE	512
+kal_uint32	msdc_testBuffer[(MSDC_TESTBUFFER_SIZE / 4)];
+kal_uint32	msdc_writeBuffer[(MSDC_TESTBUFFER_SIZE / 4)];
+
+#define CMD_DVT_TEST_STATUS 7
+kal_uint32 msdc_ReadTestFlag;
+MSDC_CALLBACK msdc_TestCallBack1;
+MSDC_CALLBACK msdc_TestCallBack2;
+MSDC_CALLBACK msdc_TestCallBack3;
+MSDC_CALLBACK msdc_TestCallBack4;
+MSDC_CALLBACK msdc_TestCallBack5;
+MSDC_CALLBACK msdc_TestCallBack6;
+static kal_uint32 sendCmdTimes = 0;
+#endif
+
+#ifdef __CARD_DOWNLOAD__
+extern kal_bool MSDC_QueryIsPowerControllable(void);
+extern void MSDC_SetPower(kal_bool enable);
+#endif
+
+
+
+
+/*************************************************************************
+* FUNCTION
+*  SD_Acmd42
+*
+* DESCRIPTION
+*	connect/disconnect the 50K Ohm pull-up resistor on CD/DAT3
+*
+* PARAMETERS
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*	gSD
+*
+* NOTE
+*
+*
+*************************************************************************/
+
+// Get CID(CMD2)
+SDC_CMD_STATUS SD_Acmd42(kal_bool connect)
+{
+    SDC_CMD_STATUS status;
+    MSDC_DEBUG("[SD][%s %d]send cmd55\r\n",__FUNCTION__,__LINE__);
+
+    // send APP_CMD
+    if ((status = SD_Cmd55(gSD->mRCA)) != NO_ERROR)
+        return status;
+    
+    MSDC_DEBUG("[SD][%s %d]send acmd42\r\n",__FUNCTION__,__LINE__);
+
+    // send cmd6
+    if ((status = SD_SendCmd(SDC_CMD_ACMD42, connect,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+        return status;
+
+    //read R1
+    if ((status = SD_CheckStatus()) != NO_ERROR)
+        return status;
+
+    gSD->mCD_DAT3 = KAL_FALSE;	// pull-up resistor is disconnected for data trnasfer
+    return NO_ERROR;
+}
+
+
+#if defined(MSDC_MMC441_SUPPORT)
+
+kal_bool SD_eMMC_ECSD_setValue(kal_uint8 addr, kal_uint8 value)
+{
+    //kal_uint32 r0; // [TODO]: eMMC
+    //kal_bool status = KAL_FALSE;
+    kal_uint8 *pData;
+
+    if (192 <= addr) //addr above 192 is information registers, we can't write these registers
+        ASSERT(0);
+
+    MSDC_PDNControl(KAL_FALSE);
+
+    if (NO_ERROR != SD_Switch_MMC40(SET_BYTE, addr, value, 0))
+        ASSERT(0);
+
+    //if(NO_ERROR != SD_GetStatus(gSD->mRCA,(kal_uint32*)&r0))
+    //	ASSERT(0);
+    if (NO_ERROR != SD_SendEXTCSD_MMC40(MSDC_Sector))
+        ASSERT(0);
+
+    pData = (kal_uint8 *)MSDC_Sector;
+
+    if (value !=  *(pData + addr))
+        ASSERT(0);
+
+    //status = KAL_TRUE;
+    MSDC_PDNControl(KAL_TRUE);
+    return KAL_TRUE;
+}
+
+/*
+	This API is to ask eMMC to start the partition.
+	That is, this API should be called after configuring partition settings.
+*/
+kal_bool SD_eMMC_ECSD_StartPartition()
+{
+    kal_bool status;
+
+    /*if this is not eMMC 4.4, assert it */
+    //EMMC44_CHECK_AND_ASSERT;
+
+    /*the device has been partitioned*/
+    if (EMMC_MASK_PARTITION_SETTING & gSD->mCSD.ext_csd->partition_settig)
+    {
+        ASSERT(0);
+    }
+
+    status = SD_eMMC_ECSD_setValue(EXT_CSD_PARTITION_CONFIG_INDEX, 1);
+
+    return status;
+}
+
+// unit: 512-byte
+kal_uint32 SD_eMMC_getWpgSize()
+{
+     if ((1 & gSD->mCSD.ext_csd->erase_grp_def) && (gSD->mCSD.ext_csd->hc_wp_grp_size > 0))
+        return 1024 * gSD->mCSD.ext_csd->hc_erase_grp_size * gSD->mCSD.ext_csd->hc_wp_grp_size;
+    else
+        return (gSD->mCSD.wp_grp_size_mmc >> 9);
+}
+
+/*
+	This API is called to configure partition settings. Size unit is 512-byte.
+*/
+kal_bool SD_eMMC_ECSD_configPartition(eMMC_partitions partition, kal_uint32 startAddr, kal_uint32 size, kal_bool isEnhanced)
+{
+    
+	kal_bool status;
+	kal_uint32 maxEnhSizeMult;
+	kal_uint32 wpgSize;
+	kal_uint32 wpgNum;
+	kal_uint32 partitionSize[5];
+	kal_uint8	regIndex;
+	kal_uint8 value[3];
+
+	if (eMMC_GP_partition1 > partition || eMMC_user_Area < partition)
+		ASSERT(0);
+
+	/*if this is not eMMC 4.4, assert it */
+	//EMMC44_CHECK_AND_ASSERT;
+
+	/*1st, if this card does not support enhanced feature or does not support partition feature, we can not do this function*/
+
+	/*	2nd, there is a limitation for the total size of enhanced memory area.
+		we have to know the total size of other existed enhanced area and check whether the setting violet the limitation.
+	*/
+	maxEnhSizeMult = gSD->mCSD.ext_csd->max_enh_size_mult[0] | ( gSD->mCSD.ext_csd->max_enh_size_mult[1] << 8) | ( gSD->mCSD.ext_csd->max_enh_size_mult[2] << 16);
+
+	/*get current all partition size*/
+	partitionSize[eMMC_GP_partition1 - eMMC_GP_partition1] = gSD->mCSD.ext_csd->gp_size_mult[0] | ( gSD->mCSD.ext_csd->gp_size_mult[1] << 8) | ( gSD->mCSD.ext_csd->gp_size_mult[2] << 16);
+	partitionSize[eMMC_GP_partition2 - eMMC_GP_partition1] = gSD->mCSD.ext_csd->gp_size_mult[3] | ( gSD->mCSD.ext_csd->gp_size_mult[4] << 8) | ( gSD->mCSD.ext_csd->gp_size_mult[5] << 16);
+	partitionSize[eMMC_GP_partition3 - eMMC_GP_partition1] = gSD->mCSD.ext_csd->gp_size_mult[6] | ( gSD->mCSD.ext_csd->gp_size_mult[7] << 8) | ( gSD->mCSD.ext_csd->gp_size_mult[8] << 16);
+	partitionSize[eMMC_GP_partition4 - eMMC_GP_partition1] = gSD->mCSD.ext_csd->gp_size_mult[9] | ( gSD->mCSD.ext_csd->gp_size_mult[10] << 8) | ( gSD->mCSD.ext_csd->gp_size_mult[11] << 16);
+	partitionSize[eMMC_user_Area - eMMC_GP_partition1] = gSD->mCSD.ext_csd->enh_size_mult[0] | ( gSD->mCSD.ext_csd->enh_size_mult[1] << 8) | ( gSD->mCSD.ext_csd->enh_size_mult[2] << 16);
+
+	/*calculate how many wpg we need to set*/
+	wpgSize = SD_eMMC_getWpgSize();
+	wpgNum = (size / wpgSize) + ((size % wpgSize) > 0 ? 1 : 0);
+
+	/*replace old size with the new size we want to set*/
+	partitionSize [partition - eMMC_GP_partition1] = wpgNum;
+
+	if ((partitionSize[0] + partitionSize[1] + partitionSize[2] + partitionSize[3] + partitionSize[4]) > maxEnhSizeMult)
+		return KAL_FALSE;
+
+	/*everything check passed, now we can set the value*/
+	if (eMMC_user_Area > partition)
+		regIndex = EXT_CSD_GP_SIZE_MULT_GP0_INDEX + 3 * (partition - eMMC_GP_partition1);
+	else
+		regIndex = EXT_CSD_ENH_SIZE_MULT_INDEX;
+
+	value[2] = wpgNum / 64;
+	value[1] = (wpgNum - (value[2] * 64)) / 8;
+	value[0] = wpgNum - (value[2] * 64) - (value[1] * 8);
+	status = SD_eMMC_ECSD_setValue(regIndex, value[0]);
+
+	if (KAL_TRUE != status)
+		goto err_exit;
+
+	status = SD_eMMC_ECSD_setValue(regIndex + 1, value[1]);
+
+	if (KAL_TRUE != status)
+		goto err_exit;
+
+	status = SD_eMMC_ECSD_setValue(regIndex + 2, value[2]);
+
+	if (KAL_TRUE != status)
+		goto err_exit;
+
+err_exit:
+	return status;
+    
+}
+
+/*
+	This API is to configure to boot from specified partition.
+	By this API, DA can decide from wich partition, will card output the boot code in boot mode.
+*/
+kal_bool SD_eMMC_ECSD_setCurrentPart(eMMC_partitions partition)
+{
+    kal_uint8 regValue;
+    kal_bool status;
+    eMMC_partitions pt;
+
+  	if (0 == partition || eMMC_user_Area < partition)
+        ASSERT(0);
+
+    /*if this is not eMMC 4.4, assert it */
+    //EMMC44_CHECK_AND_ASSERT;
+
+    pt = (partition == eMMC_user_Area) ? 0 : partition;
+
+    regValue = gSD->mCSD.ext_csd->partition_config;
+
+    /*currently it uses the setting DA want, no need to change*/
+    if (pt == (EMMC_MASK_PARTITION_CONFIG & regValue))
+        return KAL_TRUE;
+
+    regValue &= ~EMMC_MASK_PARTITION_CONFIG;
+    regValue |= pt;
+    status = SD_eMMC_ECSD_setValue(EXT_CSD_PARTITION_CONFIG_INDEX, regValue);
+
+#if 0
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#if defined(__EMMC_BOOTING__)
+/* under construction !*/
+#endif
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#endif
+
+    return status;
+}
+
+/*************************************************************************
+* FUNCTION
+*  SD_IsEMMC
+*
+* DESCRIPTION
+*	Check inserted card is e-MMC 4.4
+*
+* PARAMETERS
+*
+* RETURNS
+*
+* GLOBALS AFFECTED
+*	gSD
+*
+*************************************************************************/
+void SD_IsEmmcV44()
+{
+    /*	from eMMC 4.3, EXT_CSD_REV has maximum value 3, and from eMMC 4.4, EXT_CSD_REV new value 4, 5
+    */
+    if (3 < gSD->mCSD.ext_csd->ext_csd_rev)
+    {
+        if (0 != gSD->mCSD.ext_csd->boot_size_mul) //has boot partition, this is eMMC
+        {
+            gSD->emmc_info.isEmmcV44 = (kal_bool)KAL_TRUE;
+            gSD->emmc_info.bootPartitionSize = 2 * 128 * gSD->mCSD.ext_csd->boot_size_mul;
+            gSD->emmc_info.gp1PartitionSize = SD_eMMC_getWpgSize() *
+                                              (gSD->mCSD.ext_csd->gp_size_mult[0]
+                                               + ( gSD->mCSD.ext_csd->gp_size_mult[1] * 256)
+                                               + ( gSD->mCSD.ext_csd->gp_size_mult[2] * 65536));
+
+            /*from spec, alternated boot method is mandatory for eMMC4.4*/
+            if ( 0 == (0x1 & gSD->mCSD.ext_csd->boot_info))
+                ASSERT(0);
+
+            /*we can't use the card that don't have RST signal support*/
+            if ( 0x2 == (0x3 & gSD->mCSD.ext_csd->rst_function))
+                ASSERT(0);
+
+            if ( 0x1 == (0x1 & gSD->mCSD.ext_csd->partition_support))
+                gSD->emmc_info.supportPartition = (kal_bool)KAL_TRUE;
+            else
+                gSD->emmc_info.supportPartition = (kal_bool)KAL_FALSE;
+
+            if ( 0x2 == (0x2 & gSD->mCSD.ext_csd->partition_support))
+                gSD->emmc_info.supportEnhancedPart = (kal_bool)KAL_TRUE;
+            else
+                gSD->emmc_info.supportEnhancedPart = (kal_bool)KAL_FALSE;
+        }
+        else   //normal mmc card without boot support
+        {
+            gSD->emmc_info.isEmmcV44 = (kal_bool)KAL_FALSE;
+        }
+    }
+    else   //spec version below or equals to eMMC 4.3
+    {
+        gSD->emmc_info.isEmmcV44 = (kal_bool)KAL_FALSE;
+    }
+}
+
+#endif//defined(MSDC_MMC441_SUPPORT)
+
+
+/*************************************************************************
+* FUNCTION
+*  SD_SetMMC40_4bit_high_speed
+*
+* DESCRIPTION
+*	Check inserted card is SD or MMC
+*
+* PARAMETERS
+*
+*
+* RETURNS
+*  SD_CARD or MMC_CARD
+*
+* GLOBALS AFFECTED
+*	gMSDC_Handle
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_SetMMC40_bus_high_speed(void)
+{
+	kal_uint32 clock, hs;
+    //    kal_uint8 *pData;
+
+    #if !defined(__EMMC_BOOTING__)
+
+    if (SD_SetBlength(512) != NO_ERROR)
+        goto err;
+
+    #endif
+
+    #ifndef MSDC_SPECIAL_MMC_41_CARD
+
+    // read the EXT_CSD
+    if (SD_SendEXTCSD_MMC40(MSDC_Sector) != NO_ERROR)
+        goto err;
+
+    #endif
+
+    /*calculate size*/
+    if (MMC42_CARD == gMSDC_Handle->mMSDC_type)
+    {
+        gSD->mCSD.capacity = (kal_uint64)gSD->mCSD.ext_csd->sec_count * 512;
+    }
+
+    #if defined(MSDC_MMC441_SUPPORT)
+        SD_IsEmmcV44();
+    #endif
+
+    // set high speed
+    #ifndef MSDC_SPECIAL_MMC_41_CARD
+
+    if (gSD->mCSD.ext_csd->card_type & HS_52M)
+    #endif
+    {
+        // should be 52000
+        clock = 52000000;
+        //clock = gMSDC_Handle->msdc_clock / 2;
+
+        //if (52000000 < clock)
+        //    clock = clock / 2;
+
+        hs = 1;
+        //MSDC_LSD_WriteReg32(MSDC_IOCON,0x010002FF)
+        
+	    MSDC_DEBUG("[MSDC][%s %d]1.Set clock to %d \r\n",__FUNCTION__,__LINE__,clock);
+    }
+
+    #ifndef MSDC_SPECIAL_MMC_41_CARD
+    else if (gSD->mCSD.ext_csd->card_type & HS_26M)
+    {
+        // should be 26000
+        clock = 26000000;
+        hs = 1;
+    }
+    else
+    {
+        clock = 13000000;
+        hs = 0;
+    }
+
+    #endif
+    
+    if (hs)
+    {
+        //! [TODO]: eMMC
+        /* select proper power class
+        if(SD_Switch_MMC40(SET_BYTE,EXT_CSD_POW_CLASS_INDEX,
+        	(gSD->mCSD.ext_csd->pwr_52_360&0xf) ,0) != NO_ERROR)
+        	goto err;
+        */
+
+
+       
+        /* enable high speed (26M or 52M)*/
+        if(SD_Switch_MMC40(SET_BYTE,EXT_CSD_HIGH_SPPED_INDEX,EXT_CSD_ENABLE_HIGH_SPEED,0) != NO_ERROR)
+        	goto err;
+        
+
+        // latch data at falling edge to cover the card driving capability
+        // MSDC_LSD_SetBits32(MSDC_CFG,MSDC_CFG_RED);
+    }
+
+    #ifndef DRV_LSD
+
+    //#ifndef DRV_MSDC_CLK_SEARCH
+    //gMSDC_Handle->msdc_clock = MSDC_CLOCK;
+    MSDC_SetClock(clock,KAL_FALSE);
+    //#endif
+    #else
+    LSD_HostSetClock(LSD_SPEED_52M);
+    #endif
+
+
+
+    if (NO_SINGLE_LINE == gMSDC_Handle->trySingleLine)
+    {
+        // select bus width
+        #if defined(MMC40_USE_4BIT_BUS)
+        // enable 4-bit bus width
+        if (SD_Switch_MMC40(SET_BYTE, EXT_CSD_BUS_WIDTH_INDEX, BIT_4_MMC40, 0) != NO_ERROR)
+            goto err;
+
+        #ifdef MSDC_SPECIAL_MMC_41_CARD
+
+        if (KAL_TRUE == kal_query_systemInit()
+            || KAL_TRUE == FTL_isPollingMode()
+           )
+        {
+            MSDC_GPTI_BusyWait(2);
+        }
+        else
+        {
+            kal_sleep_task(4);
+        }
+
+        #endif
+
+        MSDC_SetBusWidth(BIT_4W);
+        gSD->bus_width = 4;
+        #elif defined(MMC40_USE_8BIT_BUS)
+
+        // enable 8-bit bus width
+        if (SD_Switch_MMC40(SET_BYTE, EXT_CSD_BUS_WIDTH_INDEX, BIT_8_MMC40, 0) != NO_ERROR)
+            goto err;
+        MSDC_SetBusWidth(BIT_8W);
+        gSD->bus_width = 8;
+        #endif
+    }
+    else
+    {
+        gMSDC_Handle->trySingleLine&=(~TEMP_SINGLE_LINE);
+    }
+
+    #ifndef MSDC_SPECIAL_MMC_41_CARD
+
+    if (SD_SendEXTCSD_MMC40(MSDC_Sector) != NO_ERROR)
+        goto err;;
+
+    #endif
+    
+    return NO_ERROR;
+err:
+
+    return ERR_MMC_BUS_HS_ERROR;
+}
+/*************************************************************************
+* FUNCTION
+*  SD_CheckSDorMMC
+*
+* DESCRIPTION
+*	Check inserted card is SD or MMC
+*
+* PARAMETERS
+*
+*
+* RETURNS
+*  SD_CARD or MMC_CARD
+*
+* GLOBALS AFFECTED
+*	gMSDC_Handle
+*
+*************************************************************************/
+T_MSDC_CARD SD_CheckSDorMMC()
+{
+    SDC_CMD_STATUS status;
+
+#if defined(SD_MMC_HIGH_DENSITY_SUPPORT)
+    SD_Cmd8();
+#endif
+    status = SD_Acmd41_SD();
+
+    if (status == NO_ERROR)
+        return gMSDC_Handle->mMSDC_type;	// SD_CARD
+    else
+        MSDC_ERR("[SD]SD_Acmd41_SD returns error code: %d\r\n", status);
+
+    status = SD_Cmd1_MMC();
+
+    if (status == NO_ERROR)
+        return gMSDC_Handle->mMSDC_type;	// MMC_CARD
+    else
+        MSDC_ERR("[SD]SD_Cmd1_MMC returns error code: %d\r\n", status);
+
+    return UNKNOWN_CARD;
+}
+
+/*************************************************************************
+* FUNCTION
+*  SD_SetDefault
+*
+* DESCRIPTION
+*	set default values to gSD
+*
+* PARAMETERS
+*
+*
+* RETURNS
+*
+* GLOBALS AFFECTED
+*	gSD
+*
+*************************************************************************/
+void SD_SetDefault(void)
+{
+     MSDC_LOCK_TAG tempLock;
+    kal_mem_cpy(&tempLock, &gSD->mSDdrv_lock, sizeof(MSDC_LOCK_TAG));
+    kal_mem_set(gSD, 0, sizeof(T_SDC_HANDLE));
+
+    gSD->mBKLength = 0;
+    gSD->mRCA = 0;
+    gSD->mInactive = KAL_FALSE;
+    gSD->mState = IDLE_STA;
+    gSD->bus_width = 1;
+    //gSD->mCD_DAT3 = KAL_TRUE;
+
+    kal_mem_cpy(&gSD->mSDdrv_lock, &tempLock, sizeof(MSDC_LOCK_TAG));
+}
+
+void SD_Use24M_Clock(void)
+{
+
+}
+
+void SD_Use13M_Clock(void)
+{
+
+}
+
+#ifdef	DRV_MSDC_CLK_MT6268_SERIES
+void SD_Use30M_Clock(void)
+{
+    
+}
+
+void SD_Use45M_Clock(void)
+{
+   
+}
+#endif
+
+#ifdef DRV_MSDC_CLK_SEARCH
+
+kal_uint32 whenToStop;
+kal_uint32 stopTimeout = 300;
+
+#if !defined(DRV_MSDC_LATCH_MT6276_SERIES)
+
+void SD_SetRedDlt(kal_uint32 redDlt)
+{
+    
+}
+#endif//#if !defined(DRV_MSDC_LATCH_MT6276_SERIES)
+
+kal_bool sd_DltTestWithClkStopped(kal_uint32 data_adrs)
+{
+	return 0;
+    
+}
+
+#if !defined(DRV_MSDC_LATCH_MT6276_SERIES)
+
+kal_bool SD_setCLKAndTest(kal_uint32 targetCLK)
+{
+   return 0;
+}
+
+
+kal_uint32 SD_tuneCLK2()
+{
+    return 0;
+}
+
+#else//!defined(DRV_MSDC_LATCH_MT6276_SERIES)
+
+kal_bool SD_IsClkInRange(kal_uint32 clk)
+{
+     return 0;
+}
+
+kal_bool SD_CanCmdBeLatched(void)
+{
+     return 0;
+}
+
+/*kal_bool SD_CanDataBeLatched(msdc_clk_setting cs)
+{
+   
+}*/
+
+/*SDC_CMD_STATUS MSDC_AutoCalibrate(
+    msdc_acb_mode		mode,
+    msdc_acb_scan_mode	scanMode,
+    msdc_acb_tun_scheme	tunScheme,
+    kal_uint8			tunBlockNum
+)
+{
+   
+}*/
+
+/*kal_uint32 MSDC_ManuCalibrate(
+    msdc_clk_setting	cs,
+    msdc_acb_mode 		mode
+)
+{
+    
+}*/
+
+#define MAX_NUM_MULTI_PHASE	32
+SDC_CMD_STATUS FindMostConsecutiveBits(
+    kal_uint32 word,
+    kal_uint8 wordLen,
+    kal_uint8 threshold,
+    kal_uint8 *pos
+)
+{
+    return 0;
+}
+
+/*SDC_CMD_STATUS MSDC_AutoCalibrate_FindBestLatchWindow(
+    msdc_acb_scan_mode scanMode,
+    kal_uint8 *pos
+)
+{
+    
+}*/
+
+/*SDC_CMD_STATUS MSDC_ManuCali_FindBestLatchWindow(
+    msdc_clk_setting cs,
+    kal_uint32 phaseArraySeamless,
+    kal_uint8 *pos
+)
+{
+    
+}*/
+
+/*kal_uint32 SD_ClkTuning_AutoCalibrate(msdc_clk_setting cs)
+{
+
+}*/
+
+/*kal_uint32 SD_ClkTuning_ManualCalibrate(msdc_clk_setting cs)
+{
+   
+}*/
+
+/*kal_uint32 SD_ClkTuning_FeedbackClk(msdc_clk_setting cs)
+{
+    
+}*/
+
+kal_uint32 SD_tuneCLK2()
+{
+    return 0;
+}
+
+#endif//!defined(DRV_MSDC_LATCH_MT6276_SERIES)
+
+#endif//#ifdef DRV_MSDC_CLK_SEARCH
+
+#ifdef __MEUT__
+kal_bool	msdcOddNumberSizeTestByDMA;
+kal_bool	msdcDoNotRST;
+SDC_CMD_STATUS msdcReadTest(kal_uint32 size, kal_uint8 *compareBuffer, kal_uint32 data_adrs)
+{
+	
+    return 0;
+}
+
+#endif
+
+
+#ifdef __MSDC_BASIC_LOAD__
+
+kal_bool	msdcOddNumberSizeTestByDMA;
+kal_bool	msdcDoNotRST;
+SDC_CMD_STATUS msdcTransferLengthTest(kal_uint32 size, kal_uint8 *compareBuffer, kal_uint32 data_adrs)
+{
+	 return 0;
+   }
+
+SDC_CMD_STATUS msdcWriteLengthTest(kal_uint32 size, kal_uint8 *compareBuffer, kal_uint32 data_adrs, kal_bool notChange)
+{
+	 return 0;
+    
+}
+#endif
+
+#if defined(MSDC_QMU_ENABLE)
+#define MSDC_QBM_BPS_NUM        1
+#define MSDC_QBM_BPS_BUF_SZ		QBM_QUEUE_GET_MEM_SIZE(QBM_SIZE_TGPD_BPS, MSDC_QBM_BPS_NUM)
+kal_uint8 msdc_bps_buf[MSDC_QBM_BPS_BUF_SZ];
+void *g_p_msdc_bps[MSDC_QBM_BPS_NUM];
+
+/* Initialize the QUM buffer for MSDC queue transfer */
+kal_bool SD_QMU_Init(void)
+{
+    kal_bool ret = KAL_TRUE;
+    unsigned char idx = 0;
+    bm_queue_config conf;
+    qbm_gpd *p_cur_gpd = NULL ,*p_head_gpd = NULL , *p_tail_gpd = NULL;
+
+    /* Init the BPS pointer */
+    for (idx = 0; idx < MSDC_QBM_BPS_NUM; idx++)
+        g_p_msdc_bps[idx] = NULL;
+
+    /*initial non-free bypass GPD buffer pool*/
+    qbm_init_q_config(&conf);
+    conf.buff_num = MSDC_QBM_BPS_NUM;
+    conf.p_mem_pool_str = msdc_bps_buf;
+    conf.p_mem_pool_end = msdc_bps_buf + MSDC_QBM_BPS_BUF_SZ;
+
+    /*user must flush the GPD after this non-free init queue*/
+    if (QBM_ERROR_OK != qbm_init_queue_non_free(QBM_TYPE_TGPD_BPS, &conf , (void **)&p_head_gpd, (void **)&p_tail_gpd)) {
+        return KAL_FALSE;
+    }
+
+    idx = 0;
+    p_cur_gpd = p_head_gpd;
+
+    do {
+        qbm_set_non_free(p_cur_gpd);
+		qbm_set_used(p_cur_gpd);
+		QBM_DES_CLR_HWO(p_cur_gpd);
+		QBM_DES_SET_NEXT(p_cur_gpd, NULL);
+
+		g_p_msdc_bps[idx] = p_cur_gpd;
+		
+        /*flush GPD here because qbm_init_queue_non_free don't flush GPD*/
+        QBM_CACHE_FLUSH(p_cur_gpd, sizeof(qbm_gpd));
+        idx ++;
+
+        /*should consider the bps_ptr array count*/
+        if ((p_cur_gpd == p_tail_gpd) || (idx >= MSDC_QBM_BPS_NUM)) {
+            break;
+        }
+
+        p_cur_gpd = p_cur_gpd->p_next;
+    } while(1);
+
+    return ret;
+}
+#endif
+
+/*************************************************************************
+* FUNCTION
+*  SD_Initialize
+*
+* DESCRIPTION
+*	Initial SD controller and card
+*
+* PARAMETERS
+*
+*
+* RETURNS
+*  SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*	gSD
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_Initialize(void)
+{
+    SDC_CMD_STATUS status;
+    kal_uint32 cid[4], csd[4], scr[4];
+    kal_uint32 sd_status[16];
+    kal_uint16 rca;
+    
+    /*check if init or not*/
+    if (gMSDC_Handle->mIsInitialized==KAL_TRUE)
+    {
+    	return NO_ERROR;
+    }
+
+#if defined(MSDC_MMC441_SUPPORT)
+    gSD->emmc_info.isEmmcV44 = KAL_FALSE;
+#endif
+
+    /* Re-Init gSD */
+	kal_mem_set(&gSD->mSCR, 0, sizeof(T_SCR));
+
+    /*reset event*/
+    kal_set_eg_events(gMSDC_Handle->MSDC_Events,0,KAL_AND);
+
+    /*reset MSDC*/
+    MSDC_RESET();
+
+    /*may switch to 1.8 last time,we should set signal volt to 3.3v and power cycle*/
+    gMSDC_Handle->signal_volt=3300;
+    MSDC_SetSignalPower(KAL_TRUE, gMSDC_Handle->signal_volt);
+    power_cycle(20);
+
+    /* Set INIT clock */
+    MSDC_SetClock(MSDC_INIT_CLOCK,KAL_FALSE);
+    /*set to 1 bit data line*/
+    MSDC_SetBusWidth(BIT_1W);
+    /*SD_SetDefault*/
+    SD_SetDefault();					//need check the function !!!!!!
+    /*set latch tuning*/
+
+    /*set IOCON1  */
+    /*set CARD_CK_PWDN=0 */
+    MSDC_ClearBits32(MSDC_CFG,MSDC_CFG_CKPDN);
+    /*enable bus clk*/
+    MSDC_SetBits32(MSDC_CFG,MSDC_CFG_CKDRV_EN);
+
+    /*reset cmd0*/
+    status=SD_Reset();
+    SD_INITIALIZE_STATUS_CHECK();                   /*need check this function !!!!!!!!!!!!*/
+    /*checkSDorMMC cmd8 acmd41 cmd1*/
+    if (SD_CheckSDorMMC() == UNKNOWN_CARD)
+    {
+        MSDC_ERR("[SD][%s %d]unknow card\r\n",__FUNCTION__,__LINE__);
+        SD_TRACE2(TRACE_GROUP_5, MSDC_GENERAL_FAIL, MSDC_DRV_TRC_FILE_SD, __LINE__);
+        status = ERR_STATUS;
+        goto err;
+    }
+    /*getCID cmd2*/
+    status = SD_GetCID(cid);
+    SD_INITIALIZE_STATUS_CHECK();
+    /*validateRCA cmd3*/
+    status = SD_ValidateRCA(&rca);
+    SD_INITIALIZE_STATUS_CHECK();
+    /*GetCSD cmd9*/
+    status = SD_GetCSD(gSD->mRCA, csd);
+    SD_INITIALIZE_STATUS_CHECK();
+    MSDC_DEBUG("[SD][%s %d]send cmd4\r\n",__FUNCTION__,__LINE__);
+    /*setSDR cmd4*/
+    if (gSD->mCSD.dsr_imp){
+        if ((status = SD_SetDSR()) != NO_ERROR)
+        {
+            //dbg_print("6\r\n");
+            SD_TRACE2(TRACE_GROUP_5, MSDC_GENERAL_FAIL, MSDC_DRV_TRC_FILE_SD, __LINE__);
+            goto err;
+        }
+    }
+    /*check Write Protected*/
+#if defined(MSDC_WR_PROT_EN)
+#if defined(_MSDC_INTERNAL_CD_INT_PIN_)
+    if(!(MSDC_Reg32(MSDC_PS)&MSDC_PS_WP))
+    {
+        //gSD->mWPEnabled=KAL_TRUE;
+        if (gSD->mWPEnabled!=KAL_TRUE)
+            gSD->mWPEnabled=KAL_FALSE;
+    }
+    else
+    {
+        //gSD->mWPEnabled=KAL_FALSE;
+        gSD->mWPEnabled=KAL_TRUE;
+    }
+#else
+    {
+    DCL_HANDLE handle;
+
+    GPIO_CTRL_READ_T data;
+
+    /* when use EINT for card detect,get the status */
+    handle = DclGPIO_Open(DCL_GPIO, MSDC_WP_GPIO);
+    DclGPIO_Control(handle, GPIO_CMD_READ, (DCL_CTRL_DATA_T *)&data);
+
+    if (data.u1IOData)
+        gSD->mWPEnabled = KAL_TRUE;
+    else
+        gSD->mWPEnabled = KAL_FALSE;
+        
+    DclGPIO_Close(handle);
+    }
+#endif
+#else       /* MSDC_WR_PROT_EN */
+    gSD->mWPEnabled = KAL_FALSE;
+#endif
+
+    MSDC_CRIT("[SD][%s %d]Card is %s\r\n",__FUNCTION__,__LINE__,
+        gSD->mWPEnabled ? "WP-ed" : "Not WP-ed");
+        
+    /*select Card cmd7*/
+    status = SD_SelectCard(gSD->mRCA);
+    if (status == CARD_IS_LOCKED)
+        gSD->mIsLocked = KAL_TRUE;
+    SD_INITIALIZE_STATUS_CHECK();
+
+
+    /*read SCR cmd16 acmd51*/
+    if (gMSDC_Handle->mMSDC_type==SD_CARD\
+        ||gMSDC_Handle->mMSDC_type==SD20_HCS_CARD ||gMSDC_Handle->mMSDC_type==SD20_LCS_CARD\
+        ||gMSDC_Handle->mMSDC_type==SD30_CARD)
+    {
+        status = SD_ReadSCR(scr);
+        SD_INITIALIZE_STATUS_CHECK();
+
+        status = SD_ReadSDStatus(sd_status);
+        SD_INITIALIZE_STATUS_CHECK();
+        
+    	/*set bus width acmd6*/
+        if (NO_SINGLE_LINE == gMSDC_Handle->trySingleLine)
+        {
+            status = SD_SetBusWidth(BIT_4W);
+            SD_INITIALIZE_STATUS_CHECK();
+        }
+        else
+        {
+            gMSDC_Handle->trySingleLine&=~(TEMP_SINGLE_LINE);
+        }
+     
+    	/*acmd42*/
+    	#if !defined(__MSDC_TFLASH_DAT3_1BIT_HOT_PLUG__)
+        status = SD_Acmd42(KAL_FALSE);
+        SD_INITIALIZE_STATUS_CHECK();
+    	#endif
+
+        status=SD_SwitchSpeedMode();
+        SD_INITIALIZE_STATUS_CHECK();
+        
+#if defined(MSDC_CONFIG_SD30_SUPPORT)
+        if (gMSDC_Handle->mMSDC_type==SD30_CARD)
+        {
+         
+            switch (gSD->function_set.function1)
+            {
+                case FUN1_SET_SDR104:
+                    MSDC_SetClock(208000000,KAL_FALSE);
+                    gMSDC_Handle->msdc_clkTuneUpperBund = 100000000;
+                    break;
+                case FUN1_SET_SDR50:
+                    MSDC_SetClock(100000000,KAL_FALSE);
+                    gMSDC_Handle->msdc_clkTuneUpperBund = 50000000;
+                    break;
+                case FUN1_SET_SDR25_HS:
+                    MSDC_SetClock(50000000,KAL_FALSE);
+                    gMSDC_Handle->msdc_clkTuneUpperBund = 25000000;
+                    break;
+                case FUN1_SET_SDR12_DS:
+                    MSDC_SetClock(25000000,KAL_FALSE);
+                    gMSDC_Handle->msdc_clkTuneUpperBund = 12500000;
+                    break;
+                case FUN1_SET_DDR50:
+                    MSDC_SetClock(50000000,KAL_TRUE);
+                    gMSDC_Handle->msdc_clkTuneUpperBund = 25000000;
+                    break;
+            }
+        }
+        else
+#endif
+        {
+            if (gSD->function_set.function1==1)
+            {
+                MSDC_CRIT("[SD][%s %d]set Bus Clock to 50M(HS)\r\n",__FUNCTION__,__LINE__);
+                MSDC_SetClock(50000000,KAL_FALSE);
+                gMSDC_Handle->msdc_clkTuneUpperBund = 25000000;
+            }
+            else
+            {
+                MSDC_CRIT("[SD][%s %d]set Bus Clock to 25M(DS)\r\n",__FUNCTION__,__LINE__);
+                MSDC_SetClock(25000000,KAL_FALSE);
+                gMSDC_Handle->msdc_clkTuneUpperBund = 12500000;
+            }
+        }
+
+        /* For SDA compliance test */
+        if (((gSD->mSCR.spec_ver==SD_SPEC_101)||(gSD->mSCR.spec_ver==SD_SPEC_110)||(gSD->mCSD.csd_ver==CSD_VER_1_0))&&
+             ((kal_uint32)(gSD->mCSD.capacity / (1024 * 1024)) > 2048)&&(status==NO_ERROR)) {
+            status = ERR_STATUS;
+            MSDC_ERR("[SD] We would not mount >2G Card which is compliant to SD1.x\r\n");
+            goto err;
+        }
+        if (((gSD->mSCR.spec_ver<=SD_SPEC_200))&&
+             ((kal_uint32)(gSD->mCSD.capacity / (1024 * 1024)) > 32768)&&(status==NO_ERROR)) {
+            status = ERR_STATUS;
+            MSDC_ERR("[SD] We would not mount >32GB Card which is compliant to SD2.0\r\n");
+            goto err;
+        }
+    }
+    else
+    {
+    	MSDC_CRIT("[SD][%s %d]init mmc \r\n",__FUNCTION__,__LINE__);
+        //mmc card
+        if ((gMSDC_Handle->mMSDC_type == MMC_CARD || gMSDC_Handle->mMSDC_type == MMC42_CARD) && gSD->mCSD.spec_ver >= 4)
+        {
+            if (gMSDC_Handle->mMSDC_type == MMC_CARD) /*we don't need to change MMC42_CARD to MMC40_CARD*/
+                gMSDC_Handle->mMSDC_type = MMC40_CARD;
+            status = SD_SetMMC40_bus_high_speed();
+            SD_INITIALIZE_STATUS_CHECK();
+            #if defined(MSDC_MMC441_SUPPORT)
+            if ( gSD->mCSD.ext_csd->ext_csd_rev >= 5 )
+            {
+                // set ERASE_GROUP_DEF[175] before issuing read, write, erase, write protect
+                status = SD_Switch_MMC40(SET_BYTE, EXT_CSD_ERASE_GRP_DEF, 1 , 0);
+                SD_INITIALIZE_STATUS_CHECK();
+            }
+            #endif
+        }
+        else
+        {
+            MSDC_SetClock(13000000,KAL_FALSE);
+        }
+       
+    }
+    
+    /* Set block length cmd16 */
+    status = SD_SetBlength(512);
+    SD_INITIALIZE_STATUS_CHECK();
+    
+err:
+
+    if (status != NO_ERROR)
+    {
+    	MSDC_ERR("[SD][%s %d]mount fail %x\r\n",__FUNCTION__,__LINE__,status);
+        SD_SetDefault();
+        gMSDC_Handle->mIsInitialized = KAL_FALSE;
+        gMSDC_Handle->mIsPresent = KAL_FALSE;
+        MSDC_turnOnVMC(gMSDC_Handle->mIsPresent);
+        MSDC_SetVddPower(KAL_FALSE, gMSDC_Handle->vdd_volt);
+    	MSDC_PDNControl(KAL_TRUE);
+     }
+     else
+     {
+    	MSDC_CRIT("[SD][%s %d]mount ok %x\r\n",__FUNCTION__,__LINE__,status);
+        gMSDC_Handle->mIsInitialized = KAL_TRUE;
+     }
+     
+    /*reset event*/
+     kal_set_eg_events(gMSDC_Handle->MSDC_Events, 0, KAL_AND);
+    return status;
+
+}
+
+#ifdef __MEUT__
+SDC_CMD_STATUS SD_SetCallBack(MSDC_CALLBACK callback1, MSDC_CALLBACK callback2, MSDC_CALLBACK callback3, MSDC_CALLBACK callback4, MSDC_CALLBACK callback5, MSDC_CALLBACK callback6)
+{
+     return 0;
+}
+SDC_CMD_STATUS SD_SetReadTestFlag(kal_uint32 readTestFlag)
+{
+     return 0;
+}
+SDC_CMD_STATUS SD_readTest(void)
+{
+
+     return 0;
+}
+
+SDC_CMD_STATUS SD_SetUpllClock(void)
+{
+
+    return 0;
+}
+#endif
+
+
+void SD_InvertN(kal_uint8 *dest, kal_uint8 *src, kal_uint8 len)
+{
+    int i;
+
+    for (i = 0; i < len; i++)
+        *(dest + len - 1 - i) = *(src + i);
+
+}
+/*************************************************************************
+* FUNCTION
+*  power2
+*
+* DESCRIPTION
+*	Calculate the power of 2
+*
+* PARAMETERS
+*	num:
+*
+* RETURNS
+*  2^num
+*
+* GLOBALS AFFECTED
+*
+*************************************************************************/
+static kal_uint32 power2(kal_uint32 num)
+{
+    return 1 << num;
+}
+
+/*************************************************************************
+* FUNCTION
+*  SD_AnalysisCSD
+*
+* DESCRIPTION
+*	Analysis Card Specific Data and store in the member of gSD
+*
+* PARAMETERS
+*	csd: input csd for analysis
+* RETURNS
+*
+* GLOBALS AFFECTED
+*	gSD
+*
+*************************************************************************/
+void SD_AnalysisCSD(kal_uint32* csd)
+{
+    kal_uint8 *ptr;
+    kal_uint32 c_mult, c_size;
+
+    ptr = (kal_uint8*)csd;
+    c_mult = c_size = 0;
+    // these offsets refer to the spec. of SD and MMC
+    GetBitFieldN((kal_uint8*)&gSD->mCSD.csd_ver, ptr, 126, 2);
+    GetBitFieldN((kal_uint8*)&gSD->mCSD.tacc, ptr, 112, 8);
+    GetBitFieldN((kal_uint8*)&gSD->mCSD.nsac, ptr, 104, 8);
+    GetBitFieldN((kal_uint8*)&gSD->mCSD.tran_speed, ptr, 96, 8);
+    GetBitFieldN((kal_uint8*)&gSD->mCSD.ccc, ptr, 84, 12);
+    GetBitFieldN((kal_uint8*)&gSD->mCSD.r_blk_len, ptr, 80, 4);
+    gSD->mCSD.r_blk_len = power2(gSD->mCSD.r_blk_len);
+    GetBitFieldN((kal_uint8*)&gSD->mCSD.r_blk_part, ptr, 79, 1);
+    GetBitFieldN((kal_uint8*)&gSD->mCSD.w_blk_misali, ptr, 78, 1);
+    GetBitFieldN((kal_uint8*)&gSD->mCSD.r_blk_misali, ptr, 77, 1);
+    GetBitFieldN((kal_uint8*)&gSD->mCSD.dsr_imp, ptr, 76, 1);
+    GetBitFieldN((kal_uint8*)&gSD->mCSD.w_blk_part, ptr, 21, 1);
+    GetBitFieldN((kal_uint8*)&gSD->mCSD.w_blk_len, ptr, 22, 4);
+    gSD->mCSD.w_blk_len = power2(gSD->mCSD.w_blk_len);
+    GetBitFieldN((kal_uint8*)&gSD->mCSD.wp_grp_enable, ptr, 31, 1);
+    GetBitFieldN((kal_uint8*)&gSD->mCSD.temp_wp,ptr,12,1);
+    GetBitFieldN((kal_uint8*)&gSD->mCSD.perm_wp,ptr,13,1);
+    if (gSD->mCSD.temp_wp || gSD->mCSD.perm_wp)
+        gSD->mWPEnabled = KAL_TRUE;
+
+    // there are some difference of CSD between SD and MMC
+    if (gMSDC_Handle->mMSDC_type == MMC_CARD || gMSDC_Handle->mMSDC_type == MMC42_CARD)
+    {
+        GetBitFieldN((kal_uint8*)&gSD->mCSD.spec_ver, ptr, 122, 4);
+        GetBitFieldN((kal_uint8*)&gSD->mCSD.erase_sec_size_mmc, ptr, 42, 5);
+        gSD->mCSD.erase_sec_size_mmc = (gSD->mCSD.erase_sec_size_mmc + 1) * gSD->mCSD.w_blk_len;
+        GetBitFieldN((kal_uint8*)&gSD->mCSD.erase_grp_size_mmc, ptr, 37, 5);
+        gSD->mCSD.erase_grp_size_mmc = (gSD->mCSD.erase_grp_size_mmc + 1) * gSD->mCSD.erase_sec_size_mmc;
+        GetBitFieldN((kal_uint8*)&gSD->mCSD.wp_grp_size_mmc, ptr, 32, 5);
+        gSD->mCSD.wp_grp_size_mmc = (gSD->mCSD.wp_grp_size_mmc + 1) * gSD->mCSD.erase_grp_size_mmc;
+    }
+    else // SD_CARD
+    {
+        if (gSD->mCSD.csd_ver == CSD_VER_2_0)
+            gSD->mIsBlkAddr = 1;
+        else
+            gSD->mIsBlkAddr = 0;
+            
+        GetBitFieldN((kal_uint8*)&gSD->mCSD.erase_sec_size_sd, ptr, 39, 7);
+        gSD->mCSD.erase_sec_size_sd += 1;
+        GetBitFieldN((kal_uint8*)&gSD->mCSD.wp_prg_size_sd, ptr, 32, 7);
+        gSD->mCSD.wp_prg_size_sd = (gSD->mCSD.wp_prg_size_sd + 1) * gSD->mCSD.erase_sec_size_sd;
+        GetBitFieldN((kal_uint8*)&gSD->mCSD.erase_blk_en_sd, ptr, 46, 1);
+    }
+
+#if defined(SD_MMC_HIGH_DENSITY_SUPPORT)
+
+    if ((gMSDC_Handle->mMSDC_type == SD20_HCS_CARD||\
+        gMSDC_Handle->mMSDC_type == SD30_CARD) && gSD->mCSD.csd_ver >= SD_CSD_VER_20)
+    {
+        GetBitFieldN((kal_uint8*)&c_size, ptr, 48, 22);
+        gSD->mBKNum = (c_size + 1);
+        gSD->mCSD.capacity = (kal_uint64)gSD->mBKNum * 512 * 1024;
+    }
+    else
+#endif
+    {
+        GetBitFieldN((kal_uint8*)&c_mult, ptr, 47, 3);
+        c_mult = power2(c_mult + 2);
+        GetBitFieldN((kal_uint8*)&c_size, ptr, 62, 12);
+        gSD->mBKNum = (c_size + 1) * c_mult;
+        gSD->mCSD.capacity = (kal_uint64)(c_size + 1) * (kal_uint64)c_mult * (kal_uint64)gSD->mCSD.r_blk_len;
+    }
+    if (!(gSD->mCSD.ccc &CCC_BLOCK_WRITE))
+        gSD->mWPEnabled = KAL_TRUE;  //unsupport write command
+
+    MSDC_CRIT("[SD][%s %d]The capacity is %d MB, BLK_ADDR(%d)\r\n", __FUNCTION__, __LINE__,
+        (kal_uint32)(gSD->mCSD.capacity / (1024 * 1024)), gSD->mIsBlkAddr);
+}
+
+/*************************************************************************
+* FUNCTION
+*  SD_AnalysisCID
+*
+* DESCRIPTION
+*	Analysis Card Identificaton and store in the member of gSD
+*
+* PARAMETERS
+*	cid: input of card ID for analysis
+* RETURNS
+*
+* GLOBALS AFFECTED
+*	gSD
+*
+*************************************************************************/
+void SD_AnalysisCID(kal_uint32* cid)
+{
+    kal_uint8	i;
+    kal_uint8* pcid;
+    pcid = (kal_uint8*)cid;
+
+    if (gMSDC_Handle->mMSDC_type == MMC_CARD || MMC42_CARD == gMSDC_Handle->mMSDC_type)
+    {
+        GetBitFieldN((kal_uint8*)&gSD->mCID.year, pcid, 8, 4);
+        gSD->mCID.year += 1997;
+        GetBitFieldN((kal_uint8*)&gSD->mCID.month, pcid, 12, 4);
+        GetBitFieldN((kal_uint8*)&gSD->mCID.psn, pcid, 16, 32);
+        GetBitFieldN((kal_uint8*)&gSD->mCID.prv, pcid, 48, 8);
+
+        for (i = 0; i < 6; i++)
+            gSD->mCID.pnm[i] = *(pcid + 7 + i);
+
+        GetBitFieldN((kal_uint8*)&gSD->mCID.oid, pcid, 104, 16);
+        GetBitFieldN((kal_uint8*)&gSD->mCID.mid, pcid, 120, 8);
+
+        // special case handling
+        {
+            kal_uint8 pnm[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x36, 0x31};
+
+            if (gSD->mCID.mid == 6 && gSD->mCID.oid == 0 &&
+                !kal_mem_cmp(gSD->mCID.pnm, pnm, 6))
+            {
+                gSD->flags |= SD_FLAG_MMC_MRSW_FAIL;
+            }
+        }
+#ifdef __CMMB_CAS_FULL_CARD_SUPPORT__
+        {
+            kal_uint8 fullCardPnm[] = {0x55, 0x59, 0x4E, 0x41, 0x49, 0x54};
+
+            if (!kal_mem_cmp(gSD->mCID.pnm, fullCardPnm, 6)) /*Tianyu does not provide MID and OID*/
+            {
+                SD_setFullCard(KAL_TRUE);
+                gMSDC_Handle->msdc_clkTuneUpperBund = 15000;
+            }
+            else
+                SD_setFullCard(KAL_FALSE);
+        }
+#endif
+
+    }
+    else // SD_CARD
+    {
+        gSD->mCID.mid = *(pcid + 15);
+        gSD->mCID.oid = *(pcid + 13) + 256 * (*(pcid + 14));
+
+        for (i = 0; i < 5; i++)
+            gSD->mCID.pnm[i] = *(pcid + 8 + i);
+
+        gSD->mCID.prv = *(pcid + 7);
+        //gSD->mCID.psn = *(kal_uint32*)(pcid+3);
+        gSD->mCID.psn = (*(kal_uint32*)(pcid + 4) << 8) | *(pcid + 3);
+        gSD->mCID.month = (kal_uint8)GET_BIT(*(pcid + 1), 0, BIT_MASK_4);
+        gSD->mCID.year = GET_BIT(*(pcid + 1), 4, BIT_MASK_4) + 16 * GET_BIT(*(pcid + 2), 0, BIT_MASK_4) + 2000;
+    }
+
+#ifdef MSDC_TRACE_LEVEL1
+    MD_TRC_MSDC_INFORM_CID(gSD->mCID.mid, gSD->mCID.oid);
+#endif
+}
+
+/*************************************************************************
+* FUNCTION
+*  SD_AnalysisSCR
+*
+* DESCRIPTION
+*	Analysis SD Card Configuration Register and store in the member of gSD
+*
+* PARAMETERS
+*	scr: input of scr for analysis
+* RETURNS
+*
+* GLOBALS AFFECTED
+*	gSD
+*
+* NOTE
+*	Only for SD card.
+*
+*************************************************************************/
+void SD_AnalysisSCR(kal_uint32* scr)
+{
+    kal_uint8 *pscr;
+
+    pscr = (kal_uint8*)scr;
+    gSD->mSCR.spec_ver = (SD_SPEC)((kal_uint8)GET_BIT(*(pscr), 0, BIT_MASK_4));
+
+    if (gSD->mSCR.spec_ver > SD_SPEC_101)
+        gSD->flags |= SD_FLAG_CMD6_SUPPORT;
+
+    gSD->mSCR.dat_after_erase = (kal_uint8)GET_BIT(*(pscr + 1), 7, BIT_MASK_1);
+    gSD->mSCR.security = (kal_uint8)GET_BIT(*(pscr + 1), 4, BIT_MASK_3);
+    gSD->mSCR.bus_width = (kal_uint8)GET_BIT(*(pscr + 1), 0, BIT_MASK_4);
+    gSD->mSCR.cmd_support = (kal_uint8)GET_BIT(*(pscr + 3), 0, BIT_MASK_2);
+    
+    gSD->mSCR.sd_spec3 = (kal_uint8)GET_BIT(*(pscr + 2), 7, BIT_MASK_1);
+    if ((gSD->mSCR.spec_ver == SD_SPEC_200) && (gSD->mSCR.sd_spec3))
+        gSD->mSCR.spec_ver = SD_SPEC_30X;
+    else
+        gSD->mSCR.spec_ver = SD_SPEC_200;
+
+    MSDC_CRIT("[SD] SD_SPEC(%d) SD_SPEC3(%d) SD_BUS_WIDTH=%d\r\n", 
+            gSD->mSCR.spec_ver, gSD->mSCR.sd_spec3, gSD->mSCR.bus_width);
+    MSDC_CRIT("[SD] SD_SECU(%d) CMD_SUPP(%d): CMD23(%d), CMD20(%d)\r\n", 
+            gSD->mSCR.security, gSD->mSCR.cmd_support,
+            (gSD->mSCR.cmd_support >> 1) & 0x1, gSD->mSCR.cmd_support & 0x1);
+}
+
+kal_uint32  SD_CmdPollResp(kal_uint32 * error,kal_uint32 pollTime_ms)
+{
+	kal_uint32 status;
+	
+	if (!MSDC_TIMEOUT_WAIT(MSDC_Reg32(MSDC_INT)&MSDC_CMD_INTS,pollTime_ms))
+	{
+		status=MSDC_Reg32(MSDC_INT);
+		MSDC_WriteReg32(MSDC_INT,(status&MSDC_CMD_INTS));
+		if (status & MSDC_INT_CMDTMO)
+		{
+			MSDC_ERR("[SD][%s %d]CMDTMO(%d)\r\n",__FUNCTION__,
+			    __LINE__, gMSDC_Handle->cmd);
+			*error=ERR_CMD_TIMEOUT;
+		}
+		else if (status & MSDC_INT_RSPCRCERR)
+		{
+			MSDC_ERR("[SD][%s %d]CMDCRC(%d)\r\n",__FUNCTION__,
+			    __LINE__, gMSDC_Handle->cmd);
+			*error=ERR_CMD_RSPCRCERR;
+		}
+		else if (status & MSDC_INT_CMDRDY)
+		{
+			*error=NO_ERROR;
+		}
+		/*we get the interrupt information*/
+		return 0;
+	}
+	/*polling  timeout ,so we need sleep and  try wait interrupt*/
+	return 1;	//tiemeout
+}
+
+/*************************************************************************
+* FUNCTION
+*  SD_WaitCmdRdyOrTo
+*
+* DESCRIPTION
+*	Wait until command ready or timeout
+*
+* PARAMETERS
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*	Interrupt driven and polling are both implemented
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_WaitCmdRdyOrTo(void)
+{
+	kal_uint32 ret;
+	kal_uint32 status;
+	kal_uint32 flag;
+	/*poll 5 ms first to check response*/
+	ret=SD_CmdPollResp(&(gMSDC_Handle->error),5);
+	if (ret)
+	{
+		MSDC_START_TIMER(MSDC_CMD_TIMEOUT/10);
+		/*enable interrupt*/
+		MSDC_SetBits32(MSDC_INTEN,MSDC_CMD_INTS|MSDC_INT_CDSC);
+		/*use interrupt handler*/
+		kal_retrieve_eg_events(gMSDC_Handle->MSDC_Events,EVENT_CMD_DONE,KAL_OR_CONSUME,&flag,KAL_SUSPEND);	
+		/*disable interrupt*/
+		MSDC_ClearBits32(MSDC_INTEN, MSDC_CMD_INTS);
+		MSDC_STOP_TIMER();
+        if (gMSDC_Handle->is_timeout)
+        {
+            gMSDC_Handle->error=MSDC_GPT_TIMEOUT_ERR;
+        }
+        else
+        {
+    		status=gMSDC_Handle->msdc_int&MSDC_CMD_INTS;
+    		
+    		if (status &MSDC_INT_CMDRDY)
+    		{
+    			gMSDC_Handle->error=NO_ERROR;
+    		}
+    		else if (status& MSDC_INT_CMDTMO)
+    		{
+    			MSDC_ERR("[SD][%s %d]CMDTMO(%d), MSDC_CMD_INTS:%x\r\n",__FUNCTION__,
+    			    __LINE__, gMSDC_Handle->cmd, status);
+    			gMSDC_Handle->error=ERR_CMD_TIMEOUT;
+    		}
+    		else if (status & MSDC_INT_RSPCRCERR)
+    		{
+    			MSDC_ERR("[SD][%s %d]CMDCRC(%d), MSDC_CMD_INTS:%x\r\n",__FUNCTION__,
+    			    __LINE__, gMSDC_Handle->cmd, status);
+    			gMSDC_Handle->error=ERR_CMD_RSPCRCERR;
+    		}
+    		else
+    		{
+    			MSDC_ERR("[SD][%s %d]ERR(%d), MSDC_CMD_INTS:%x\r\n",__FUNCTION__,
+    			    __LINE__, gMSDC_Handle->cmd, status);
+    			gMSDC_Handle->error=ERR_CMD_TIMEOUT;
+    		}
+    		ret=status;
+        }
+	}
+	return gMSDC_Handle->error;
+}
+
+/*************************************************************************
+* FUNCTION
+*  SD_WaitDatRdyOrTo
+*
+* DESCRIPTION
+*	Wait until data ready or timeout ,just for pio read and write
+*
+* PARAMETERS
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*	just polling 
+*
+*************************************************************************/
+	SDC_CMD_STATUS SD_WaitDatRdyOrTo(kal_uint32 *buffer,kal_uint32 byte_len,kal_bool isWrite)
+	{
+		kal_uint32 intsts;
+		kal_uint8 * u8ptr;
+		kal_uint32 * ptr;
+        ptr=buffer;
+        
+		gMSDC_Handle->abort=0;
+		MSDC_SetBits32(MSDC_INTEN,MSDC_INTEN_DATTMO|MSDC_INTEN_DATCRCERR);
+		if(!isWrite)
+		{
+			/*poll to read data from FIFO*/
+			while(byte_len)
+			{
+			   
+				if ((byte_len>=MSDC_FIFO_THD)&&(MSDC_RXFIFOCNT()>=MSDC_FIFO_THD)){
+					int count =MSDC_FIFO_THD>>2;	
+					do{
+						*ptr++=MSDC_FIFO_READ32();
+					}while(--count);
+					byte_len-=MSDC_FIFO_THD;
+					
+				}
+				else if  ((byte_len<MSDC_FIFO_THD)&&(MSDC_RXFIFOCNT()>=byte_len))
+				{
+					while(byte_len>3){
+						*ptr++=MSDC_FIFO_READ32();
+						byte_len-=4;
+					}
+					u8ptr=(kal_uint8 *)ptr;
+					while(byte_len){
+						*u8ptr++=MSDC_FIFO_READ8();
+						byte_len--;
+					}
+				}
+				if (gMSDC_Handle->abort){
+				   	gMSDC_Handle->abort=0;
+					MSDC_ERR("[SD][%s %d]pio read abort ,byte_len=%d \r\n",__FUNCTION__,__LINE__,byte_len);
+					break;
+				}
+			}
+		}
+		else
+		{
+			/*poll to write data into FIFO*/
+			while(byte_len){
+				if (byte_len >= MSDC_FIFO_SZ){
+					if (MSDC_TXFIFOCNT()==0){
+						int count =MSDC_FIFO_SZ>>2;
+						do {
+							MSDC_FIFO_WRITE32(*ptr);
+							ptr++;
+						}while(--count);
+						byte_len-=MSDC_FIFO_SZ;
+					}
+				}
+				else if ((byte_len<MSDC_FIFO_SZ)&&(MSDC_TXFIFOCNT()==0)){
+					while(byte_len){
+						while(byte_len>3){
+							MSDC_FIFO_WRITE32(*ptr);
+							ptr++;
+							byte_len-=4;
+						}
+						u8ptr=(kal_uint8 *)ptr;
+						while(byte_len){
+							MSDC_FIFO_WRITE8(*u8ptr);
+							u8ptr++;
+							byte_len--;
+						}
+					}
+				}
+				if (gMSDC_Handle->abort)
+				{
+					gMSDC_Handle->abort=0;
+					MSDC_ERR("[SD][%s %d]pio write abort ,byte_len=%d \r\n",__FUNCTION__,__LINE__,byte_len);
+					break;
+				}
+			}
+			
+		}
+		
+		MSDC_ClearBits32(MSDC_INTEN, MSDC_INTEN_DATTMO|MSDC_INTEN_DATCRCERR);
+		if (byte_len)
+			goto end;
+		intsts =MSDC_PollInts(MSDC_INT_XFER_COMPL|MSDC_INT_DATTMO|MSDC_INT_DATCRCERR,100);
+		MSDC_DEBUG("[SD][%s %d]intsts =%x \r\n",__FUNCTION__,__LINE__,intsts);
+		MSDC_CLR_FIFO();
+		if (intsts&MSDC_INT_XFER_COMPL)
+		{
+			gMSDC_Handle->error=NO_ERROR;
+		}
+		else if (intsts&MSDC_INT_DATCRCERR){
+			gMSDC_Handle->error=ERR_DAT_CRCERR;
+		}
+		else if (intsts&MSDC_INT_DATTMO)
+		{
+			gMSDC_Handle->error=ERR_DAT_TIMEOUT;
+		}
+end:
+		if (gMSDC_Handle->error)
+		{
+			MSDC_FatalErrorHandle();
+		}
+		
+		/*wait busy for write operation*/
+		if (isWrite)
+		{
+		    dbg_print("isWrite=%x ,go to MSDC_CheckCardBusy",isWrite);
+			MSDC_CheckCardBusy(KAL_FALSE,30*1000);
+		}
+		return gMSDC_Handle->error;
+	}
+
+/*************************************************************************
+* FUNCTION
+*  SD_WaitCardNotBusy
+*
+* DESCRIPTION
+*	Wait until card is not busy (R1b)
+*
+* PARAMETERS
+*
+* RETURNS
+*	void
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*	Interrupt driven and polling are both implemented
+*
+*************************************************************************/
+extern kal_bool FTL_isPollingMode();
+kal_uint32 direct_msdc_entry = 0;
+
+SDC_CMD_STATUS SD_WaitCardNotBusy(kal_uint32 timeout_ms)
+{
+    	if(MSDC_TIMEOUT_WAIT((!SD_IS_R1B_BUSY())&&MSDC_Check_Card_Present(),timeout_ms))
+    	{
+    		gMSDC_Handle->error=ERR_CMD_TIMEOUT;
+    		MSDC_ERR("[SD][%s %d]R1B busy timeout ,wait %d ms\r\n",__FUNCTION__,__LINE__,timeout_ms);
+    		return ERR_CMD_TIMEOUT;
+    	}
+	return  NO_ERROR;
+}
+
+/*************************************************************************
+* FUNCTION
+*  SD_CheckStatus
+*
+* DESCRIPTION
+*	Check command status
+*
+* PARAMETERS
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_CheckStatus(void)
+{
+	     kal_uint32 status;
+
+	    status= MSDC_Reg32(SDC_RESP0);
+	    if ((status & SDC_CSTA_MASK) == 0 )
+	        return NO_ERROR;
+
+	    MSDC_ERR("[SD][%s %d]check status<%x>\r\n",__FUNCTION__,__LINE__,status);
+	    if (status & SDC_CARD_IS_LOCKED)
+	    {
+	    	
+	        return CARD_IS_LOCKED;
+	    }
+	    return ERR_STATUS;
+    
+}
+
+
+
+/*************************************************************************
+* FUNCTION
+*  SD_Send_Cmd
+*
+* DESCRIPTION
+*	to launch the command packet to the card
+*
+* PARAMETERS
+*	1. cmd: the content of SDC_CMD register
+*	2. arg: the argument(if the command need no argument, fill it with 0)
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*	1. Check if controller is available  before launch any commands
+*	2. Maybe add check if card is busy (R1b)
+*************************************************************************/
+SDC_CMD_STATUS SD_SendCmdOnly( kal_uint32 cmd, kal_uint32 arg,kal_uint32 timeout_ms)
+{
+	kal_uint32 retry_count=0;
+check_busy:
+	/*wait CMD busy and SDC busy*/
+   	if (cmd == SDC_CMD_CMD12||cmd==SDC_CMD_CMD13)
+   	{
+		if (MSDC_TIMEOUT_WAIT((!SD_IS_CMD_BUSY()),timeout_ms))
+   		{
+			gMSDC_Handle->error=ERR_CMD_TIMEOUT;
+			MSDC_FatalErrorHandle();
+			MSDC_ERR("[SD][%s %d]wait cmd busy timeout !!,retry %d times\r\n",__FUNCTION__,__LINE__,retry_count);
+		}
+   	}
+   	else
+   	{
+		if (MSDC_TIMEOUT_WAIT((!SD_IS_SDC_BUSY()), timeout_ms))
+		{
+			gMSDC_Handle->error=ERR_CMD_TIMEOUT;
+			MSDC_FatalErrorHandle();
+			MSDC_ERR("[SD][%s %d]wait SDC busy %d ms timeout!!,retry %d times\r\n",__FUNCTION__,__LINE__,timeout_ms,retry_count);
+			goto retry;
+		}
+   	}
+	if (gSD->mBKLength&&(gSD->mBKLength <= 0xfff))
+	{
+		cmd|=(gSD->mBKLength<<16);
+	}
+
+    /* If the card supports CMD23, enable AUTOCMD23 function of MSDC */
+    if (((cmd & 0x3F) == 18) || ((cmd & 0x3F) == 25)) {
+        if ((gSD->mSCR.cmd_support >> 1) & 0x1)
+            cmd |= (2 << 28);
+    }
+
+    MSDC_DEBUG("[SD]CMD=%d, arg=%X\r\n", cmd & 0x3F, arg);
+	
+	/*set argument*/
+	MSDC_WriteReg32(SDC_ARG,arg);
+	/*set command*/
+	MSDC_WriteReg32(SDC_CMD,cmd);
+	gMSDC_Handle->cmd = (kal_uint8)(cmd & 0x3F);
+    gMSDC_Handle->error=NO_ERROR;
+	return gMSDC_Handle->error;
+	
+retry:
+	if ((!SD_IS_SDC_BUSY())&&(retry_count<3)){
+		retry_count++;
+		goto check_busy;
+	}
+	return gMSDC_Handle->error;
+	
+}
+
+#define MSDC_TUNE_CMD_RESP_TA_MAX           (8)
+#define MSDC_TUNE_INT_DAT_LATCH_CK_MAX      (8)
+#define MSDC_TUNE_WCRC_TA_MAX               (8)
+
+static kal_uint8 fgCMDTuneLargeScale = 1;
+static kal_uint32 times_large = 0;
+static kal_uint32 times_small = 0;
+
+static kal_uint8 fgWrTuneLargeScale = 1;
+static kal_uint32 times_large_w = 0;
+static kal_uint32 times_small_w = 0;
+
+static kal_uint8 fgReadTuneLargeScale = 1;
+static kal_uint32 times_large_r = 0;
+static kal_uint32 times_small_r = 0;
+    
+static kal_uint32 msdc_tune_cmd_retry(kal_uint32 cmd, kal_uint32 arg, kal_uint32 timeout_ms)
+{
+    kal_uint32 result = ERR_CMD_RSPCRCERR;
+
+    /* CMD12 CRCERR should not tune */
+    if ((cmd & 0x3F) == 12) {
+        result = NO_ERROR;
+        goto done;
+    }
+    
+    /* Send 'STOP' command to complete 'TRANS' state */
+    if (MSDC_Reg32(SDC_CMD)&0x1800)
+    {
+        /*check if has data phase*/
+        result=SD_SendCmdOnly(SDC_CMD_CMD12,SDC_NO_ARG,1000);
+        result=SD_WaitCmdRdyOrTo();
+        if (result!=NO_ERROR)
+            goto err;
+    }
+    
+    if (gMSDC_Handle->app_cmd)
+    {
+        /*for acmd ,we should send cmd55 again*/
+        result=SD_SendCmdOnly(SDC_CMD_CMD55,gSD->mRCA,1000);
+        if (result!=NO_ERROR)
+            goto err;
+        result=SD_WaitCmdRdyOrTo();
+        if (result!=NO_ERROR)
+            goto err;
+    }
+    
+    result=SD_SendCmdOnly(cmd,arg,timeout_ms);
+
+    if (result!=NO_ERROR)
+        goto err;
+        
+    result=SD_WaitCmdRdyOrTo();
+    if (result==NO_ERROR)
+        goto done;
+    if (result != ERR_CMD_RSPCRCERR)
+        goto err;
+
+err:
+    MSDC_FatalErrorHandle();
+done:    
+    return result;
+}
+
+kal_uint32 msdc_tune_cmd_large_scale()
+{
+    kal_uint32 ret = 0;
+    kal_uint32 clk_mode, cmd_resp_ta_cntr, r_smpl;
+
+    times_large++;
+    
+    MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD, clk_mode);
+    MSDC_GET_FIELD(MSDC_PATCH_BIT1, MSDC_CMD_RSP_TA_CNTR, cmd_resp_ta_cntr);
+    MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_RSPL, r_smpl);
+
+    /* 
+     * If MSDC_CFG.CLK_MODE = 1 && Bus_Speed > 100MHz 
+     * that is ultra high speed mode, tune CMD_RESP_TA first
+     */
+    if ((clk_mode == 1) || (clk_mode == 2) || 
+        (gMSDC_Handle->op_clock >= MSDC_TUNE_UHS_SCLK)) {
+        cmd_resp_ta_cntr++;
+        MSDC_SET_FIELD(MSDC_PATCH_BIT1, MSDC_CMD_RSP_TA_CNTR, 
+            cmd_resp_ta_cntr & (MSDC_TUNE_CMD_RESP_TA_MAX - 1));
+
+        if (cmd_resp_ta_cntr >= MSDC_TUNE_CMD_RESP_TA_MAX) {
+            r_smpl++;
+            MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_RSPL, r_smpl % 2);
+        }
+    }
+    else {
+        /* 
+         * In low speed mode, just tune R_SMPL 
+         * and set MSDC_CMD_RSP_TA_CNTR back to 0
+         */
+        r_smpl++;
+        cmd_resp_ta_cntr = 0;
+        MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_RSPL, r_smpl % 2);
+        MSDC_SET_FIELD(MSDC_PATCH_BIT1, MSDC_CMD_RSP_TA_CNTR, cmd_resp_ta_cntr & 
+            (MSDC_TUNE_CMD_RESP_TA_MAX - 1));
+    }
+
+    /* Now all the parameters are set to 0 */
+    if (r_smpl >= 2)
+        ret = 1;
+
+    MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD, clk_mode);
+    MSDC_GET_FIELD(MSDC_PATCH_BIT1, MSDC_CMD_RSP_TA_CNTR, cmd_resp_ta_cntr);
+    MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_RSPL, r_smpl);
+    
+    MSDC_NOTICE("[SD] <TUNE_CMD_LS><%d> CKMOD=%d, CMD_RSP_TA=%d, R_SMPL=%d\r\n",
+            times_large, clk_mode, cmd_resp_ta_cntr, r_smpl);
+   
+    if (ret)
+        times_large = 0;
+
+    return ret;
+}
+
+kal_uint32 msdc_tune_cmd_small_scale()
+{
+    kal_uint32 ret = 0;
+    kal_uint32 cmd_rxdly, clk_mode, cmd_resp_ta_cntr, r_smpl;
+
+    times_small++;
+    MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD, clk_mode);
+    MSDC_GET_FIELD(MSDC_PATCH_BIT1, MSDC_CMD_RSP_TA_CNTR, cmd_resp_ta_cntr);
+    MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_RSPL, r_smpl);
+    MSDC_GET_FIELD(MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRDLY, cmd_rxdly);
+
+    /* Adjust CMD_RXDLY in PAD macro */
+    cmd_rxdly++;
+    MSDC_SET_FIELD(MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRDLY, cmd_rxdly & 0x1F);
+
+    /* Adjust R_SMPL */
+    if (cmd_rxdly >= 32) {
+        r_smpl++;
+        MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_RSPL, r_smpl % 2);
+    }
+
+    /* 
+     * Adjust CMD_RSP_TA_CNTR
+     * if MSDC_CFG.CLK_MODE = 1 && Bus_Speed > 100MHz
+     */
+    if (r_smpl >= 2) {
+        if ((clk_mode == 1) || (clk_mode == 2) || (gMSDC_Handle->op_clock >= MSDC_TUNE_UHS_SCLK)) {
+            cmd_resp_ta_cntr++;
+            MSDC_SET_FIELD(MSDC_PATCH_BIT1, MSDC_CMD_RSP_TA_CNTR, 
+                cmd_resp_ta_cntr & (MSDC_TUNE_CMD_RESP_TA_MAX - 1));
+
+            if (cmd_resp_ta_cntr >= MSDC_TUNE_CMD_RESP_TA_MAX) 
+                ret = 1;
+        }
+        else
+            ret= 1;
+    }
+
+    MSDC_GET_FIELD(MSDC_PATCH_BIT1, MSDC_CMD_RSP_TA_CNTR, cmd_resp_ta_cntr);
+    MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_RSPL, r_smpl);
+    MSDC_GET_FIELD(MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRDLY, cmd_rxdly);
+
+    MSDC_NOTICE("[SD] <TUNE_CMD_SS><%d> CMD_RXDLY=%d, R_SMPL=%d, CMD_RSP_TA=%d\r\n",
+            times_small, cmd_rxdly, r_smpl, cmd_resp_ta_cntr);
+
+    /* Now all the parameters are set to 0 */
+    if (ret)
+        times_small = 0;
+        
+    return ret;    
+}
+
+SDC_CMD_STATUS SD_CmdTuneResp(kal_uint32 cmd,kal_uint32 arg,kal_uint32 timeout_ms)
+{
+    kal_uint32 result = ERR_CMD_RSPCRCERR;
+    
+    do {
+        /* Retry the CMD with error handling */
+        result = msdc_tune_cmd_retry(cmd, arg, timeout_ms);
+
+        if ((result == ERR_CMD_TIMEOUT) ||
+            (result == NO_ERROR)) {
+            if (result == NO_ERROR) {
+                if (times_large)
+                    fgCMDTuneLargeScale = 0;
+
+                times_small = 0;
+            }
+            goto done;
+        }
+
+        /* Large scale timing tuning */
+        if (fgCMDTuneLargeScale) {
+            if (msdc_tune_cmd_large_scale())
+                fgCMDTuneLargeScale = 0;
+        } 
+        /* Small scale timing tuning */
+        else {
+            if (msdc_tune_cmd_small_scale())
+                goto done;
+        }
+
+    } while (1);
+
+done:
+    MSDC_CRIT("[SD] <TUNE_CMD%d_DONE>", cmd & 0x3F);
+    if (result == NO_ERROR) 
+        MSDC_CRIT(" %s\r\n", "PASS");
+    else if (result == ERR_CMD_RSPCRCERR)
+        MSDC_CRIT(" %s\r\n", "CRCERR");
+    else if (result == ERR_CMD_TIMEOUT)
+        MSDC_CRIT(" %s\r\n", "TIMEOUT");
+
+    return result;
+}
+
+SDC_CMD_STATUS SD_SendCmd(kal_uint32 cmd,kal_uint32 arg,kal_uint32 timeout_ms)
+{
+	kal_uint32 status;
+	/*send command */
+	status = SD_SendCmdOnly(cmd,arg,timeout_ms);
+	if (status!=NO_ERROR)
+	{
+		MSDC_ERR("[SD][%s %d]send cmd %d error \r\n",__FUNCTION__,__LINE__,cmd);
+		return status;
+	}
+	/*wait command complete*/
+	status=SD_WaitCmdRdyOrTo();
+	if (status != NO_ERROR)
+	{
+		MSDC_FatalErrorHandle();
+		if (status == ERR_CMD_RSPCRCERR)
+		{
+			SD_CmdTuneResp(cmd, arg,timeout_ms);
+		}
+		status = gMSDC_Handle->error;
+		
+		return status;
+	}
+	if (cmd== SDC_CMD_CMD55 )
+	{
+		gMSDC_Handle->app_cmd=1;
+	}
+	else
+    {
+		gMSDC_Handle->app_cmd=0;
+		
+	}
+	return status;
+}
+kal_uint32 SD_PioRead(kal_uint32 * buffer,kal_uint32 num)
+{
+	kal_uint32 *ptr=buffer;
+	kal_uint8 *u8ptr;
+	kal_uint32 left;
+	ptr =buffer;
+	left=num;
+	while(left)
+	{
+		if ((left>=MSDC_FIFO_THD)&&(MSDC_RXFIFOCNT()>=MSDC_FIFO_THD)){
+			int count =MSDC_FIFO_THD>>2;	
+			do{
+				*ptr++=MSDC_FIFO_READ32();
+			}while(--count);
+			left-=MSDC_FIFO_THD;
+			
+		}
+		else if  ((left<MSDC_FIFO_THD)&&(MSDC_RXFIFOCNT()>=left))
+		{
+			while(left>3){
+				*ptr++=MSDC_FIFO_READ32();
+				left-=4;
+			}
+			u8ptr=(kal_uint8 *)ptr;
+			while(left){
+				*u8ptr++=MSDC_FIFO_READ8();
+				left--;
+			}
+			
+			if (gMSDC_Handle->abort){
+				gMSDC_Handle->abort=0;
+				MSDC_ERR("[SD][%s %d]pio read abort!!, num= %d \r\n",__FUNCTION__,__LINE__,num);
+				goto end;
+			}
+		}
+	}
+end:
+	return left;
+}
+
+kal_uint32 SD_PioWrite(kal_uint32 * buffer,kal_uint32 num)
+{
+	kal_uint32 * ptr=buffer;
+	kal_uint8 *u8ptr;
+	kal_uint32 left;
+	ptr=buffer;
+	left=num;
+	while(left){
+		if (left >= MSDC_FIFO_SZ){
+			if (MSDC_TXFIFOCNT()==0){
+				int count =MSDC_FIFO_SZ>>2;
+				do {
+					MSDC_FIFO_WRITE32(*ptr);
+					ptr++;
+				}while(--count);
+				left-=MSDC_FIFO_SZ;
+			}
+		}
+		else if ((left<MSDC_FIFO_SZ)&&(MSDC_TXFIFOCNT()==0)){
+			while(left){
+				while(left>3){
+					MSDC_FIFO_WRITE32(*ptr);
+					ptr++;
+					left-=4;
+				}
+				u8ptr=(kal_uint8 *)ptr;
+				while(left){
+					MSDC_FIFO_WRITE8(*u8ptr);
+					u8ptr++;
+					left--;
+				}
+			}
+		}
+		if (gMSDC_Handle->abort)
+		{
+			gMSDC_Handle->abort=0;
+			MSDC_ERR("[SD][%s %d]pio write abort %d \r\n",__FUNCTION__,__LINE__,num);
+			goto done;
+		}
+	}
+
+done:
+	return left;
+}
+
+#if !defined(MSDC_QMU_ENABLE)
+static kal_uint8 msdc_cal_checksum(const void *buf,kal_uint32 len)
+{
+    kal_uint32 i,sum=0;
+    kal_char *data=(char*)buf;
+    for(i=0;i<len;i++)
+    {
+        sum+=*data++;
+    }
+    return 0xFF-(kal_uint8)sum;
+}
+#endif
+
+static DCL_STATUS SD_ConfigGpdList(kal_uint32 size)
+{
+#if !defined(MSDC_QMU_ENABLE)
+    kal_uint32 i,buflen,data_count;
+    kal_uint32 * data_ptr;
+    kal_uint32 t1;
+    qbm_gpd* cur_gpd=NULL,*cur_bd=NULL;
+    msdc_gpd_t *gpd;
+    msdc_gpd_t *gpd_end;
+    qbm_gpd *head;
+    qbm_gpd *tail;
+    kal_uint8 sel = 0;
+    
+    #define CONFIG_GPDLIST_TIMEOUT 10000
+    
+    head = MSDC_Blk[sel].head;
+    tail = MSDC_Blk[sel].tail;
+    gpd = MSDC_Blk[sel].gpd;
+    gpd_end = MSDC_Blk[sel].gpd_end;
+    
+    gpd->intr   =1;     /*don't generate DMA_done interrupt*/
+    gpd->extlen =0;     /*ignore cmd,arg etc*/
+    gpd->hwo    =1;     /*config hardware owner*/
+    gpd->bdp    =1;     /*use buffer descriptor list*/
+    gpd->ptr    =(void*)(&MSDC_bd[sel][0]);
+    gpd->next   =(void*)gpd_end;
+    
+    #ifdef MSDC_DMA_CHKSUM_EN
+    gpd->chksum =0;
+    gpd->chksum =msdc_cal_checksum(gpd,16);
+    #endif
+   
+    gpd_end->intr   =0;     /*don't generate DMA_done interrupt*/
+    gpd_end->extlen =0;     /*ignore cmd,arg etc*/
+    gpd_end->hwo    =0;     /*config hardware owner*/
+    gpd_end->bdp    =0;     /*use buffer descriptor list*/
+    gpd_end->ptr    =0;
+    gpd_end->next   =NULL;
+
+    #ifdef MSDC_DMA_CHKSUM_EN
+    gpd_end->chksum =0;
+    gpd_end->chksum =msdc_cal_checksum(gpd_end,16);
+    #endif
+    
+    data_count = 0;
+    t1 = drv_get_current_time();
+    
+    for (i=0,cur_gpd=head;;cur_gpd=QBM_DES_GET_NEXT(cur_gpd)) {
+        if (i > MSDC_BD_MAX)
+        {
+            MSDC_ERR("[%s %d]qbm_gpd list is to long,only supprot %d object \r\n",__FUNCTION__,__LINE__,MSDC_BD_MAX);
+            return STATUS_INVALID_ARGUMENT;
+        }
+
+        /* NULL pointer check */
+        if (cur_gpd == NULL) {
+            MSDC_ERR("[%s %d]cur_gpd is NULL pointer!\r\n",__FUNCTION__,__LINE__);
+            return STATUS_INVALID_ARGUMENT;
+        }
+        
+        if (QBM_DES_GET_BDP(cur_gpd))
+        {
+            // if GPD with BD with data buffer
+            cur_bd=QBM_DES_GET_DATAPTR(cur_gpd);
+            while(1)
+            {
+                buflen=QBM_DES_GET_DATALEN(cur_bd);
+                data_ptr=(kal_uint32 *)QBM_DES_GET_DATAPTR(cur_bd);
+                if ((data_count+buflen)>size)
+                { //if buffer length is large the secotors we want to transfer            
+                   buflen=size-data_count;
+                   data_count=size;
+                }
+                else
+                {
+                    data_count+=buflen;
+                }
+                if (buflen)
+                { // if point to a buffer adress on this BD
+                    
+                    if (((cur_gpd==tail)&&(QBM_DES_GET_EOL(cur_bd)))||(data_count==size))
+                        MSDC_bd[sel][i].eol     =1;
+                    else
+                        MSDC_bd[sel][i].eol     =0;
+                    MSDC_bd[sel][i].next    =&MSDC_bd[sel][i+1];
+                    MSDC_bd[sel][i].ptr     =data_ptr;               
+                    MSDC_bd[sel][i].buflen  =buflen;
+                    clean_and_invalidate_dcache(CPU_CACHE_LINE_ALIGN_ADDR((kal_uint32)data_ptr),CPU_CACHE_LINE_ALIGN_LEN((kal_uint32)data_ptr,buflen));                 
+                    MSDC_bd[sel][i].blkpad   =0;
+                    MSDC_bd[sel][i].dwpad   =0;
+                    MSDC_bd[sel][i].chksum=0;
+                    MSDC_bd[sel][i].chksum=msdc_cal_checksum(&MSDC_bd[sel][i],16);
+                    i++;
+                }          
+                if(QBM_DES_GET_EOL(cur_bd))
+                {
+                    break;
+                }
+                cur_bd=QBM_DES_GET_NEXT(cur_bd);
+            }
+        }
+        else
+        {   
+            // if GPD with data buffer
+            buflen=QBM_DES_GET_DATALEN(cur_gpd);
+            //dbg_print("%d  buflen=%d\r\n",i,buflen);
+            data_ptr=(kal_uint32 *)QBM_DES_GET_DATAPTR(cur_gpd);
+            if ((data_count+buflen)>size)
+            {             
+               buflen=size-data_count;
+               data_count=size;
+               //dbg_print("entry last data_count %d,buflen %d size %d\r\n",data_count,buflen,size);
+            }
+            else
+            {
+                data_count+=buflen;
+            }
+            if (buflen)
+            {
+                if (cur_gpd==tail||data_count==size)
+                    MSDC_bd[sel][i].eol     =1;
+                else
+                    MSDC_bd[sel][i].eol     =0;
+                MSDC_bd[sel][i].next    =&MSDC_bd[sel][i+1];
+                MSDC_bd[sel][i].ptr     =data_ptr;               
+                MSDC_bd[sel][i].buflen  =buflen;
+
+                /* 
+                 * There is NO need to clean the data cache, which is transfered
+                 * from MSD and USB, because the buffer is directly read or write 
+                 * by DMA, CPU are not involved in.
+                 */
+                #if defined(MSDC_SCAT_BUF_FLUSH) || defined(ATEST_DRV_MSDC)
+                clean_and_invalidate_dcache(CPU_CACHE_LINE_ALIGN_ADDR((kal_uint32)data_ptr),CPU_CACHE_LINE_ALIGN_LEN((kal_uint32)data_ptr,buflen));
+                #endif
+                
+                MSDC_bd[sel][i].blkpad   =0;
+                MSDC_bd[sel][i].dwpad   =0;
+
+                #ifdef MSDC_DMA_CHKSUM_EN
+                MSDC_bd[sel][i].chksum=0;
+                MSDC_bd[sel][i].chksum=msdc_cal_checksum(&MSDC_bd[sel][i], 16);
+                #endif
+                
+                i++;
+            }          
+        }
+        if (cur_gpd==tail)
+            break;
+            
+    }
+
+    if (drv_get_duration_ms(t1)>CONFIG_GPDLIST_TIMEOUT)
+    {
+        MSDC_INFO("[%s %d]config gpd list timeout\r\n",__FUNCTION__,__LINE__,MSDC_BD_MAX);
+        return STATUS_INVALID_ARGUMENT;
+    }
+    
+    //if data buffer is not enough 
+    if (data_count!=size)
+    {
+        MSDC_INFO("[%s %d]data_count %d,size %d\r\n",__FUNCTION__,__LINE__,data_count,size);
+        return STATUS_INVALID_ARGUMENT;
+    }
+
+    /* Flush the GPD and BD from cache to memory */
+    #ifdef MSDC_GPD_BD_BUF_CACHED
+    clean_and_invalidate_dcache(CPU_CACHE_LINE_ALIGN_ADDR((kal_uint32)gpd),
+        CPU_CACHE_LINE_ALIGN_LEN((kal_uint32)gpd, sizeof(msdc_gpd_t)));
+    clean_and_invalidate_dcache(CPU_CACHE_LINE_ALIGN_ADDR((kal_uint32)gpd_end),
+        CPU_CACHE_LINE_ALIGN_LEN((kal_uint32)gpd_end, sizeof(msdc_gpd_t)));
+    clean_and_invalidate_dcache(CPU_CACHE_LINE_ALIGN_ADDR((kal_uint32)&MSDC_bd[sel][0]),
+        CPU_CACHE_LINE_ALIGN_LEN((kal_uint32)&MSDC_bd[sel][0], i * sizeof(msdc_bd_t)));
+    #endif
+
+    return STATUS_OK;
+
+#else
+    
+    qbm_gpd *head, *tail, *tail_bak, *p_bps_gpd, *p_cur_gpd;
+    kal_uint8 sel = 0;
+        
+    head = MSDC_Blk[sel].head;
+    tail = MSDC_Blk[sel].tail;
+    tail_bak = tail;
+
+    /* In case of normal transfer */
+    if (!gMSDC_Handle->f_tuning) {
+        p_bps_gpd = g_p_msdc_bps[sel];
+        if (!p_bps_gpd) {
+            MSDC_ERR("[%s %d]Invalid loacal bypass GPD buffer!\r\n",__FUNCTION__,__LINE__);
+            return STATUS_FAIL;
+        }
+
+        /* Link the bypass GPD to tail */
+        qbmt_common_en_q_rx(p_bps_gpd, p_bps_gpd, (void **)&head, (void **)&tail);
+
+        /* Set HWO = 1, cause it is cleared by USB QMU */
+        p_cur_gpd = head;
+        do {
+            if (p_cur_gpd == tail_bak)
+                break;
+
+            QBM_DES_SET_HWO(p_cur_gpd);
+            QBM_CACHE_FLUSH(p_cur_gpd, 2);
+
+            p_cur_gpd = p_cur_gpd->p_next;
+        } while(1);
+    }
+    /* In case of re-try on tuning */
+    else {
+        p_cur_gpd = head;
+
+        /* Re-Set HWO = 1, and flush cache */
+        do {
+            QBM_DES_SET_HWO(p_cur_gpd);
+            QBM_CACHE_FLUSH(p_cur_gpd, sizeof(qbm_gpd));
+
+            if ((p_cur_gpd == tail))
+                break;
+
+            p_cur_gpd = p_cur_gpd->p_next;
+
+        } while(1);
+    }
+
+    /* Set the QMU start address */
+    gMSDC_Handle->buf_addr = (void *)MSDC_Blk[sel].head;
+		    
+    return STATUS_OK;
+    
+#endif
+}
+
+SDC_CMD_STATUS SD_ReqHandleData(kal_uint32 data_adrs, void* buffer, kal_uint32 num,kal_bool isWrite,kal_bool isLinkListBuf)
+{
+	kal_uint32 status ;
+	kal_bool dma;
+	kal_uint32 intsts;
+	kal_uint8 cmd23_sup = 0;
+
+    MSDC_INFO("[SD]SD_Req: CMD%s Addr=%x BlkNum=%d Buf=%x\r\n", 
+        isWrite ? "25(24)" : "18(17)", data_adrs, num, buffer);
+
+	/*Set block size and block num*/
+	if (gSD->mBKLength!=512)
+	{
+		status =SD_SetBlength(512);
+		if (status != NO_ERROR)
+		{
+			return status;
+		}
+			
+	}
+	MSDC_WriteReg32(SDC_BLK_NUM,num);
+	/*set read timeout*/
+	/*check we use dma or pio*/
+	if(gSD->mBKLength*num <512)
+	{
+		/*use pio*/
+		dma=0;
+		//set to PIO mode
+  		 BitFieldWrite32((kal_uint32 *)MSDC_CFG, 1, MSDC_CFG_PIO);
+		gMSDC_Handle->dma_xfer=0;
+	}
+	else
+	{
+		/*use dma*/
+		dma=1;
+		//set to DMA mode
+   		BitFieldWrite32((kal_uint32 *)MSDC_CFG, 0, MSDC_CFG_PIO);
+		gMSDC_Handle->dma_xfer=1;
+	}
+	
+	dma=1;						/*driver unsupport PIO now*/
+	gMSDC_Handle->dma_xfer=1;
+	if (dma)
+	{
+		kal_set_eg_events(gMSDC_Handle->MSDC_Events, 0,KAL_AND);
+		/*enable DMA*/
+		MSDC_ClearBits32(MSDC_CFG,MSDC_CFG_PIO);
+		/*start command*/
+        if (!isWrite)
+        {
+            if (num==1)
+            {
+                status=SD_SendCmdOnly(SDC_CMD_CMD17,data_adrs,MSDC_CMD_TIMEOUT);
+            }
+            else
+            {
+		        status=SD_SendCmdOnly(SDC_CMD_CMD18,data_adrs,MSDC_CMD_TIMEOUT);
+            }
+        }
+        else
+        {
+            if (num==1)
+            {
+                status=SD_SendCmdOnly(SDC_CMD_CMD24,data_adrs,MSDC_CMD_TIMEOUT);
+            }
+            else
+            {
+                status=SD_SendCmdOnly(SDC_CMD_CMD25,data_adrs,MSDC_CMD_TIMEOUT);
+            }
+        }
+		if (status !=NO_ERROR)
+		{
+			goto done;
+		}
+		/*map dma data*/
+		
+		/*config dma*/
+		gMSDC_Handle->total_count=num*gSD->mBKLength;
+		gMSDC_Handle->buf_addr=buffer;
+
+		if (isLinkListBuf) {
+		    status = SD_ConfigGpdList(gMSDC_Handle->total_count);
+		    if (status != STATUS_OK) {
+		        MSDC_ERR("[%s %d]Config GPD list fail!\r\n",__FUNCTION__,__LINE__);
+		        return status;
+		    }
+		}
+		    
+		MSDC_DMATransferFirst(isWrite,isLinkListBuf);
+		
+		/*wait cmd rsp*/
+		status=SD_WaitCmdRdyOrTo();
+		if (status != NO_ERROR)
+		{
+			MSDC_FatalErrorHandle();
+			if (status == ERR_CMD_RSPCRCERR)
+			{
+			    if (!isWrite)
+                {   if (num==1)      
+				        status=SD_CmdTuneResp(SDC_CMD_CMD17, data_adrs,MSDC_CMD_TIMEOUT);
+                    else
+                        status=SD_CmdTuneResp(SDC_CMD_CMD18, data_adrs,MSDC_CMD_TIMEOUT);   
+                }
+                else
+                {
+                    if(num==1)
+                        status=SD_CmdTuneResp(SDC_CMD_CMD24, data_adrs,MSDC_CMD_TIMEOUT);
+                    else
+                        status=SD_CmdTuneResp(SDC_CMD_CMD25, data_adrs,MSDC_CMD_TIMEOUT);     
+                }
+			}
+			if(status != NO_ERROR)
+			    goto done;
+		}
+		/*start dma and wait data complete*/
+		status = MSDC_DMATransferFinal(isWrite,isLinkListBuf);
+	}
+	else
+	{
+		/*pio mode*/
+		if (SD_SendCmd(((isWrite==KAL_TRUE) ?SDC_CMD_CMD25:SDC_CMD_CMD18),data_adrs,MSDC_CMD_TIMEOUT))
+		{
+			goto done;
+		}
+		MSDC_SetBits32(MSDC_INTEN,MSDC_INTEN_DATTMO|MSDC_INTEN_DATCRCERR);
+		if(!isWrite)
+		{
+			/*poll to read data from FIFO*/
+			status =SD_PioRead(buffer,num*gSD->mBKLength);
+		}
+		else
+		{
+			/*poll to write data to FIFO*/
+			status =SD_PioWrite(buffer,num*gSD->mBKLength);
+		}
+		
+		MSDC_ClearBits32(MSDC_INTEN, MSDC_INTEN_DATTMO|MSDC_INTEN_DATCRCERR);
+		if (status)
+		{
+			goto done;
+		}
+		intsts =MSDC_PollInts(MSDC_INT_XFER_COMPL|MSDC_INT_DATTMO|MSDC_INT_DATCRCERR,100);
+		if (intsts&MSDC_INT_XFER_COMPL)
+		{
+			status=gMSDC_Handle->error=NO_ERROR;
+		}
+		else if (intsts&MSDC_INT_DATCRCERR){
+			status=gMSDC_Handle->error=ERR_DAT_CRCERR;
+		}
+		else if (intsts&MSDC_INT_DATTMO)
+		{
+			status=gMSDC_Handle->error=ERR_DAT_TIMEOUT;
+		}
+		else
+        	MSDC_ERR("[SD][%s %d]SW timeout in wait PIO data done\r\n",__FUNCTION__,__LINE__);
+	}
+done:
+	if (status)
+	{
+		MSDC_FatalErrorHandle();
+	}
+	
+	/*cmd12 to stop data*/
+	cmd23_sup = (gSD->mSCR.cmd_support >> 1) & 0x1;
+    if (((num>1) && !cmd23_sup) || ((num>1) && cmd23_sup && status))
+	    SD_SendCmd(SDC_CMD_CMD12, SDC_NO_ARG, MSDC_CMD_TIMEOUT);
+	
+	/* Check card status after each operation */
+	MSDC_CheckCardBusy(KAL_FALSE, 10*1000);
+	
+	return status;
+}
+
+kal_uint32 msdc_tune_write_large_scale()
+{
+    kal_uint32 ret = 0;
+    kal_uint32 ultra_hs = 0;
+    kal_uint32 clk_mode, wr_datcrc_ta, w_d_smpl;
+    
+    times_large_w++;
+    
+    MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD, clk_mode);
+    MSDC_GET_FIELD(MSDC_PATCH_BIT1, MSDC_WRDAT_CRCS_TA_CNTR, wr_datcrc_ta);
+    MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_WDSPL, w_d_smpl);
+
+    /* 
+     * If MSDC_CFG.CLK_MODE = 1 && Bus_Speed > 100MHz 
+     * that is ultra high speed mode, tune WRDAT_CRCS_TA_CNTR first
+     */
+    if ((clk_mode == 1) || (clk_mode == 2) ||  (gMSDC_Handle->op_clock > MSDC_TUNE_UHS_SCLK))
+        ultra_hs = 1;
+
+    if (ultra_hs) {
+        wr_datcrc_ta++;
+        MSDC_SET_FIELD(MSDC_PATCH_BIT1, MSDC_WRDAT_CRCS_TA_CNTR, 
+            wr_datcrc_ta & (MSDC_TUNE_WCRC_TA_MAX - 1));
+
+        if (wr_datcrc_ta >= MSDC_TUNE_WCRC_TA_MAX) {
+            w_d_smpl++;
+            MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_WDSPL, w_d_smpl % 2);
+        }
+    }
+    else {
+        w_d_smpl++;
+        wr_datcrc_ta = 0;
+        MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_WDSPL, w_d_smpl % 2);
+        MSDC_SET_FIELD(MSDC_PATCH_BIT1, MSDC_WRDAT_CRCS_TA_CNTR, 
+            wr_datcrc_ta & (MSDC_TUNE_WCRC_TA_MAX - 1));
+    }
+
+    if (w_d_smpl >= 2) {
+        ret = 1;    
+    }
+
+    MSDC_GET_FIELD(MSDC_PATCH_BIT1, MSDC_WRDAT_CRCS_TA_CNTR, wr_datcrc_ta);
+    MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_WDSPL, w_d_smpl);
+    
+    MSDC_NOTICE("[SD] <TUNE_WR_LS><%d> %s=%d, %s=%d, %s=%d\r\n",
+            times_large_w, "CKMOD", clk_mode, 
+            "WR_DATCRC_TA", wr_datcrc_ta, "W_D_SMPL", w_d_smpl);
+   
+    if (ret)
+        times_large_w = 0;
+
+    return ret;
+}
+
+kal_uint32 msdc_tune_write_small_scale()
+{
+    kal_uint32 ret = 0;
+    kal_uint32 ultra_hs = 0;
+    kal_uint32 clk_mode, wr_datcrc_ta, w_d_smpl, dat0_rd_dly, dat_wr_rxdly;
+    
+    times_small_w++;
+
+    /* 
+     * When re-enter the tuning flow, 
+     * Clear the pad macro then tune from the beginning
+     */
+    if (times_small_w == 1) {
+        MSDC_SET_FIELD(MSDC_PAD_TUNE, MSDC_PAD_TUNE_DATWRDLY, 0);
+    }
+    
+    MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD, clk_mode);
+    MSDC_GET_FIELD(MSDC_PATCH_BIT1, MSDC_WRDAT_CRCS_TA_CNTR, wr_datcrc_ta);
+    MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_WDSPL, w_d_smpl);
+    MSDC_GET_FIELD(MSDC_DAT_RDDLY0, MSDC_DAT_RDDLY0_D0, dat0_rd_dly);
+    MSDC_GET_FIELD(MSDC_PAD_TUNE, MSDC_PAD_TUNE_DATWRDLY, dat_wr_rxdly);
+
+    /* 
+     * If MSDC_CFG.CLK_MODE = 1 && Bus_Speed > 100MHz 
+     * that is ultra high speed mode, tune WRDAT_CRCS_TA_CNTR 
+     * and PAT_DAT_WR_RXDLY at last
+     */
+    if ((clk_mode == 1) || (clk_mode == 2) || (gMSDC_Handle->op_clock > MSDC_TUNE_UHS_SCLK))
+        ultra_hs = 1;
+
+    dat_wr_rxdly++;
+    MSDC_SET_FIELD(MSDC_PAD_TUNE, MSDC_PAD_TUNE_DATWRDLY, dat_wr_rxdly & 0x1F);
+
+    if (dat_wr_rxdly >= 32) {
+        w_d_smpl++;
+        MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_WDSPL, w_d_smpl % 2);
+    }
+
+    if (ultra_hs) {
+        if (w_d_smpl >= 2) {
+            wr_datcrc_ta++;
+            MSDC_SET_FIELD(MSDC_PATCH_BIT1, MSDC_WRDAT_CRCS_TA_CNTR, 
+                wr_datcrc_ta & (MSDC_TUNE_WCRC_TA_MAX - 1));
+        }
+
+        if (wr_datcrc_ta >= MSDC_TUNE_WCRC_TA_MAX)
+            ret = 1;
+    }
+
+    if (w_d_smpl >= 2) 
+        ret = 1;
+
+    MSDC_GET_FIELD(MSDC_PATCH_BIT1, MSDC_WRDAT_CRCS_TA_CNTR, wr_datcrc_ta);
+    MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_WDSPL, w_d_smpl);
+    MSDC_GET_FIELD(MSDC_DAT_RDDLY0, MSDC_DAT_RDDLY0_D0, dat0_rd_dly);
+    MSDC_GET_FIELD(MSDC_PAD_TUNE, MSDC_PAD_TUNE_DATWRDLY, dat_wr_rxdly);
+    
+    MSDC_NOTICE("[SD] <TUNE_WR_SS><%d> %s=%d, %s=%d, %s=%d\r\n",
+            times_small_w, "CKMOD", clk_mode, 
+            "WR_DATCRC_TA", wr_datcrc_ta, "W_D_SMPL", w_d_smpl);
+    MSDC_NOTICE("                        %s=%d, %s=%d\r\n",
+            "DAT0_RD_DLY", dat0_rd_dly, "DAT_WR_RXDLY", dat_wr_rxdly);
+            
+    if (ret)
+        times_small_w = 0;
+
+    return ret;
+}
+
+kal_uint32 SD_TuneWrite(kal_uint32 address,void * txbuffer,kal_uint32 num,kal_bool isLinkListBuf)
+{
+    kal_uint32 result = ERR_DAT_CRCERR;
+    
+    do {
+        /* Retry the Write with error handling */
+        result = SD_ReqHandleData(address,txbuffer,num,KAL_TRUE,isLinkListBuf);
+
+        if (/*(result == ERR_DAT_TIMEOUT) ||*/
+            (result == NO_ERROR)) {
+            if (times_large_w)
+                fgWrTuneLargeScale = 0;
+
+            times_small_w = 0;
+            
+            goto done;
+        }
+
+        /* Large scale timing tuning */
+        if (fgWrTuneLargeScale) {
+            if (msdc_tune_write_large_scale())
+                fgWrTuneLargeScale = 0;
+        } 
+        /* Small scale timing tuning */
+        else {
+            if (msdc_tune_write_small_scale())
+                goto done;
+        }
+
+    } while (1);
+
+done:
+    MSDC_CRIT("[SD] <TUNE_WRITE_DONE>");
+    if (result == NO_ERROR) 
+        MSDC_CRIT(" %s\r\n", "PASS");
+    else if (result == ERR_DAT_CRCERR)
+        MSDC_CRIT(" %s\r\n", "CRCERR");
+    else if (result == ERR_DAT_TIMEOUT)
+        MSDC_CRIT(" %s\r\n", "TIMEOUT");
+
+    return result;
+}
+
+
+kal_uint32 msdc_tune_read_large_scale()
+{
+    kal_uint32 ret = 0;
+    kal_uint32 ultra_hs = 0;
+    kal_uint32 clk_mode, int_dat_latch, ckgen_dly, r_d_smpl;
+    
+    times_large_r++;
+    
+    MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD, clk_mode);
+    MSDC_GET_FIELD(MSDC_PATCH_BIT0, MSDC_INT_DAT_LATCH_CK_SEL, int_dat_latch);
+    MSDC_GET_FIELD(MSDC_PATCH_BIT0, MSDC_CKGEN_MSDC_DLY_SEL, ckgen_dly);
+    MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_RDSPL, r_d_smpl);
+
+    /* 
+     * If MSDC_CFG.CLK_MODE = 1 && Bus_Speed > 100MHz 
+     * that is ultra high speed mode, tune INT_DAT_LATCH_CK_SEL
+     * and CKGEN_MSDC_DLY_SEL first
+     */
+    if ((clk_mode == 1) || (clk_mode == 2) || (gMSDC_Handle->op_clock > MSDC_TUNE_UHS_SCLK))
+        ultra_hs = 1;
+
+    if (ultra_hs) {
+        /* Sampling edge is fixed by default setting - rising edge */
+        int_dat_latch++;
+        MSDC_SET_FIELD(MSDC_PATCH_BIT0, MSDC_INT_DAT_LATCH_CK_SEL, 
+            int_dat_latch & (MSDC_TUNE_INT_DAT_LATCH_CK_MAX - 1));
+
+        if (int_dat_latch >= MSDC_TUNE_INT_DAT_LATCH_CK_MAX) {
+            ckgen_dly++;
+            MSDC_SET_FIELD(MSDC_PATCH_BIT0, MSDC_CKGEN_MSDC_DLY_SEL, ckgen_dly & 0x1F);
+
+            if (ckgen_dly >= 32)
+                ret = 1;
+        }
+    }
+    else {
+        /* 
+         * In low speed mode, just tune R_D_SMPL 
+         * and set other parameters back to 0
+         */
+        r_d_smpl++;
+        int_dat_latch = 0;
+        ckgen_dly = 0;
+        MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_RDSPL, r_d_smpl % 2);
+        MSDC_SET_FIELD(MSDC_PATCH_BIT0, MSDC_INT_DAT_LATCH_CK_SEL, 
+            int_dat_latch & (MSDC_TUNE_INT_DAT_LATCH_CK_MAX - 1));
+        MSDC_SET_FIELD(MSDC_PATCH_BIT0, MSDC_CKGEN_MSDC_DLY_SEL, ckgen_dly & 0x1F);
+        
+    }
+
+    if (r_d_smpl >= 2)
+        ret = 1;
+
+    MSDC_GET_FIELD(MSDC_PATCH_BIT0, MSDC_INT_DAT_LATCH_CK_SEL, int_dat_latch);
+    MSDC_GET_FIELD(MSDC_PATCH_BIT0, MSDC_CKGEN_MSDC_DLY_SEL, ckgen_dly);
+    MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_RDSPL, r_d_smpl);
+    
+    MSDC_NOTICE("[SD] <TUNE_RD_LS><%d> %s=%d, %s=%d, %s=%d, %s=%d\r\n",
+            times_large_r, "CKMOD", clk_mode, 
+            "INT_DAT_L", int_dat_latch, "CKGEN_DLY", ckgen_dly,
+            "R_D_SMPL", r_d_smpl);
+   
+    if (ret)
+        times_large_r = 0;
+
+    return ret;
+    
+}
+
+kal_uint32 msdc_tune_read_small_scale()
+{
+    kal_uint32 ret = 0;
+    kal_uint32 ultra_hs = 0;
+    kal_uint32 clk_mode, int_dat_latch, ckgen_dly, r_d_smpl, dat_rddly0, dat_rddly1;
+    kal_uint32 dat0_rd_dly, dat1_rd_dly, dat2_rd_dly, dat3_rd_dly;
+    kal_uint32 dat4_rd_dly, dat5_rd_dly, dat6_rd_dly, dat7_rd_dly;
+
+    kal_uint32 ddr = 0, dcrc_sts;
+    
+    times_small_r++;
+    
+    MSDC_GET_FIELD(MSDC_CFG, MSDC_CFG_CKMOD, clk_mode);
+    
+    /* 
+     * If MSDC_CFG.CLK_MODE = 1 && Bus_Speed > 100MHz 
+     * that is ultra high speed mode, tune INT_DAT_LATCH_CK_SEL
+     * and CKGEN_MSDC_DLY_SEL at last
+     */
+    if ((clk_mode == 1) || (clk_mode == 2) || (gMSDC_Handle->op_clock > MSDC_TUNE_UHS_SCLK))
+        ultra_hs = 1;
+
+    /* 
+     * When re-enter the tune in Non-UHS mode, 
+     * Clear the pad macro then tune from the beginning
+     */
+    if ((times_small_r == 1) && (ultra_hs == 0)) {
+        MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_RDSPL, 0);
+        MSDC_WriteReg32(MSDC_DAT_RDDLY0, 0);
+        MSDC_WriteReg32(MSDC_DAT_RDDLY1, 0);
+    }
+    
+    MSDC_GET_FIELD(MSDC_PATCH_BIT0, MSDC_INT_DAT_LATCH_CK_SEL, int_dat_latch);
+    MSDC_GET_FIELD(MSDC_PATCH_BIT0, MSDC_CKGEN_MSDC_DLY_SEL, ckgen_dly);
+    MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_RDSPL, r_d_smpl);
+    dat_rddly0 = MSDC_Reg32(MSDC_DAT_RDDLY0);
+    dat_rddly1 = MSDC_Reg32(MSDC_DAT_RDDLY1);
+    
+    /* Get data CRC status */
+    MSDC_GET_FIELD(SDC_DCRC_STS, SDC_DCRC_STS_NEG | SDC_DCRC_STS_POS, dcrc_sts);
+
+    /* Check output clock is SDR mode or DDR mode */
+    ddr =  (clk_mode == 2) ? 1 : 0;
+    if (!ddr) 
+        dcrc_sts &= ~SDC_DCRC_STS_NEG;
+    
+    /* Tune PAD macro first */
+    MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_DDLSEL, 1);
+    
+    dat0_rd_dly = (dat_rddly0 >> 24) & 0x1F;
+    dat1_rd_dly = (dat_rddly0 >> 16) & 0x1F;
+    dat2_rd_dly = (dat_rddly0 >>  8) & 0x1F;
+    dat3_rd_dly = (dat_rddly0 >>  0) & 0x1F;
+    dat4_rd_dly = (dat_rddly1 >> 24) & 0x1F;
+    dat5_rd_dly = (dat_rddly1 >> 16) & 0x1F;
+    dat6_rd_dly = (dat_rddly1 >>  8) & 0x1F;
+    dat7_rd_dly = (dat_rddly1 >>  0) & 0x1F;
+
+    if (ddr) {
+        dat0_rd_dly = (dcrc_sts & (1 << 0) || dcrc_sts & (1 <<  8)) ? (dat0_rd_dly + 1) : dat0_rd_dly;
+        dat1_rd_dly = (dcrc_sts & (1 << 1) || dcrc_sts & (1 <<  9)) ? (dat1_rd_dly + 1) : dat1_rd_dly;
+        dat2_rd_dly = (dcrc_sts & (1 << 2) || dcrc_sts & (1 << 10)) ? (dat2_rd_dly + 1) : dat2_rd_dly;
+        dat3_rd_dly = (dcrc_sts & (1 << 3) || dcrc_sts & (1 << 11)) ? (dat3_rd_dly + 1) : dat3_rd_dly;
+        dat4_rd_dly = (dcrc_sts & (1 << 4) || dcrc_sts & (1 << 12)) ? (dat4_rd_dly + 1) : dat4_rd_dly;
+        dat5_rd_dly = (dcrc_sts & (1 << 5) || dcrc_sts & (1 << 13)) ? (dat5_rd_dly + 1) : dat5_rd_dly;
+        dat6_rd_dly = (dcrc_sts & (1 << 6) || dcrc_sts & (1 << 14)) ? (dat6_rd_dly + 1) : dat6_rd_dly;
+        dat7_rd_dly = (dcrc_sts & (1 << 7) || dcrc_sts & (1 << 15)) ? (dat7_rd_dly + 1) : dat7_rd_dly;
+    } else {
+        dat0_rd_dly = (dcrc_sts & (1 << 0)) ? (dat0_rd_dly + 1) : dat0_rd_dly;
+        dat1_rd_dly = (dcrc_sts & (1 << 1)) ? (dat1_rd_dly + 1) : dat1_rd_dly;
+        dat2_rd_dly = (dcrc_sts & (1 << 2)) ? (dat2_rd_dly + 1) : dat2_rd_dly;
+        dat3_rd_dly = (dcrc_sts & (1 << 3)) ? (dat3_rd_dly + 1) : dat3_rd_dly;
+        dat4_rd_dly = (dcrc_sts & (1 << 4)) ? (dat4_rd_dly + 1) : dat4_rd_dly;
+        dat5_rd_dly = (dcrc_sts & (1 << 5)) ? (dat5_rd_dly + 1) : dat5_rd_dly;
+        dat6_rd_dly = (dcrc_sts & (1 << 6)) ? (dat6_rd_dly + 1) : dat6_rd_dly;
+        dat7_rd_dly = (dcrc_sts & (1 << 7)) ? (dat7_rd_dly + 1) : dat7_rd_dly;
+    }
+
+    dat_rddly0 = ((dat0_rd_dly & 0x1F) << 24) | ((dat1_rd_dly & 0x1F) << 16) |
+                 ((dat2_rd_dly & 0x1F) << 8)  | ((dat3_rd_dly & 0x1F) << 0);    
+    dat_rddly1 = ((dat4_rd_dly & 0x1F) << 24) | ((dat5_rd_dly & 0x1F) << 16) |
+                 ((dat6_rd_dly & 0x1F) << 8)  | ((dat7_rd_dly & 0x1F) << 0);
+
+    MSDC_WriteReg32(MSDC_DAT_RDDLY0, dat_rddly0);
+    MSDC_WriteReg32(MSDC_DAT_RDDLY1, dat_rddly1);   
+    
+    /* Then R_D_SMPL */
+    if( (dat0_rd_dly >= 32) || (dat1_rd_dly >= 32) || (dat2_rd_dly >= 32) || (dat3_rd_dly >= 32)||
+        (dat4_rd_dly >= 32) || (dat5_rd_dly >= 32) || (dat6_rd_dly >= 32) || (dat7_rd_dly >= 32)){
+
+        /* 
+         * On ultra-hs mode, do NOT tune sampling edge,
+         * because of the 'internal boundary' issue of the current IP
+         */
+        if (!ultra_hs) {
+            r_d_smpl++;
+            MSDC_SET_FIELD(MSDC_IOCON, MSDC_IOCON_RDSPL, r_d_smpl % 2);
+        }
+
+        /* Re-tune the data pad macro */
+        MSDC_WriteReg32(MSDC_DAT_RDDLY0, 0);
+        MSDC_WriteReg32(MSDC_DAT_RDDLY1, 0);
+
+        /* Then CKGEN_MSDC_DLY_SEL if it is SDR104 mode */
+        if (ultra_hs) {
+            ckgen_dly++;
+            MSDC_SET_FIELD(MSDC_PATCH_BIT0, MSDC_CKGEN_MSDC_DLY_SEL, ckgen_dly & 0x1F);
+
+            if (ckgen_dly >= 32)
+                ret = 1;
+        }
+        else {
+            if (r_d_smpl >= 2)
+                ret = 1;
+        }
+        
+    }
+
+    MSDC_GET_FIELD(MSDC_PATCH_BIT0, MSDC_INT_DAT_LATCH_CK_SEL, int_dat_latch);
+    MSDC_GET_FIELD(MSDC_PATCH_BIT0, MSDC_CKGEN_MSDC_DLY_SEL, ckgen_dly);
+    MSDC_GET_FIELD(MSDC_IOCON, MSDC_IOCON_RDSPL, r_d_smpl);
+    dat_rddly0 = MSDC_Reg32(MSDC_DAT_RDDLY0);
+    dat_rddly1 = MSDC_Reg32(MSDC_DAT_RDDLY1);
+    
+    MSDC_NOTICE("[SD] <TUNE_RD_SS><%d> %s=%d, %s=%d, %s=%d, %s=%d\r\n",
+            times_small_r, "CKMOD", clk_mode, 
+            "INT_DAT_L", int_dat_latch, "CKGEN_DLY", ckgen_dly,
+            "R_D_SMPL", r_d_smpl);
+    MSDC_NOTICE("                        %s=0x%x, %s=0x%x\r\n",
+            "DAT_RDDLY0", dat_rddly0, "DAT_RDDLY1", dat_rddly1);
+            
+    if (ret)
+        times_small_r = 0;
+
+    return ret;
+    
+}
+
+SDC_CMD_STATUS SD_TuneRead(kal_uint32 data_adrs,void *rxbuffer,kal_uint32 num,kal_bool isLinkListBuf)
+{
+    kal_uint32 result = ERR_DAT_CRCERR;
+    
+    do {
+        /* Retry the Read with error handling */
+        result = SD_ReqHandleData(data_adrs,rxbuffer,num,KAL_FALSE,isLinkListBuf);
+
+        if ((result == ERR_DAT_TIMEOUT) ||
+            (result == NO_ERROR)) {
+            if (result == NO_ERROR) {
+                if (times_large_r)
+                    fgReadTuneLargeScale = 0;
+
+                times_small_r = 0;
+            }
+            
+            goto done;
+        }
+
+        /* Large scale timing tuning */
+        if (fgReadTuneLargeScale) {
+            if (msdc_tune_read_large_scale())
+                fgReadTuneLargeScale = 0;
+        } 
+        /* Small scale timing tuning */
+        else {
+            if (msdc_tune_read_small_scale())
+                goto done;
+        }
+
+    } while (1);
+
+done:
+    MSDC_CRIT("[SD] <TUNE_READ_DONE>");
+    if (result == NO_ERROR) 
+        MSDC_CRIT(" %s\r\n", "PASS");
+    else if (result == ERR_DAT_CRCERR)
+        MSDC_CRIT(" %s\r\n", "CRCERR");
+    else if (result == ERR_DAT_TIMEOUT)
+        MSDC_CRIT(" %s\r\n", "TIMEOUT");
+
+    return result;
+}
+
+void msdc_tune_init(void) 
+{
+    /* Initialize the tuning releated parameters and registers */
+    fgCMDTuneLargeScale = 1;
+    times_large = 0;
+    times_small = 0;
+    MSDC_SET_FIELD_NPW(MSDC_PATCH_BIT1, MSDC_CMD_RSP_TA_CNTR, 0);
+    MSDC_SET_FIELD_NPW(MSDC_IOCON, MSDC_IOCON_RSPL, 0);
+    MSDC_SET_FIELD_NPW(MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRDLY, 0);
+    
+    fgWrTuneLargeScale = 1;
+    times_large_w = 0;
+    times_small_w = 0;
+    MSDC_SET_FIELD_NPW(MSDC_PATCH_BIT1, MSDC_WRDAT_CRCS_TA_CNTR, 0);
+    MSDC_SET_FIELD_NPW(MSDC_IOCON, MSDC_IOCON_WDSPL, 0);
+    MSDC_SET_FIELD_NPW(MSDC_PAD_TUNE, MSDC_PAD_TUNE_DATWRDLY, 0);
+    
+    fgReadTuneLargeScale = 1;
+    times_large_r = 0;
+    times_small_r = 0;
+    MSDC_WriteReg32_NPW(MSDC_DAT_RDDLY0, 0);
+    MSDC_WriteReg32_NPW(MSDC_DAT_RDDLY1, 0);
+    MSDC_SET_FIELD_NPW(MSDC_PATCH_BIT0, MSDC_INT_DAT_LATCH_CK_SEL, 0);
+    MSDC_SET_FIELD_NPW(MSDC_PATCH_BIT0, MSDC_CKGEN_MSDC_DLY_SEL, 0);
+    MSDC_SET_FIELD_NPW(MSDC_IOCON, MSDC_IOCON_RDSPL, 0);    
+}
+
+SDC_CMD_STATUS SD_HandleWriteTMO(kal_uint32 address,void *txbuffer,kal_uint32 num,kal_bool isLinkListBuf)
+{
+	kal_uint32 cur_wrta,orig_wr_crcta;
+	kal_uint32 status,i,ret;
+	
+	ret=SD_GetStatus(gSD->mRCA,&status);
+	if (ret){
+		return ERR_DAT_TIMEOUT;
+	}
+	if (status&(R1_OUT_OF_RANGE_31|R1_ADDRESS_ERROR_30)){
+		return ERR_DAT_TIMEOUT;
+	}
+	orig_wr_crcta=(MSDC_Reg32(MSDC_PATCH_BIT1)&MSDC_PATCH_BIT1_WRDAT_CRCS)>>(uffs(MSDC_PATCH_BIT1_WRDAT_CRCS)-1);
+	/*Ncrc may cause Write data timeout*/
+	for (i=0;i<8;i++){
+		cur_wrta=(orig_wr_crcta+i)%8;
+		MSDC_SetData32(MSDC_PATCH_BIT1,MSDC_PATCH_BIT1_WRDAT_CRCS,cur_wrta<<(uffs(MSDC_PATCH_BIT1_WRDAT_CRCS)-1));
+		ret=SD_ReqHandleData(address,txbuffer,num,KAL_TRUE,isLinkListBuf);
+		if (ret==0)
+			return 0;
+		if (ret==ERR_DAT_CRCERR||ret==ERR_CMD_RSPCRCERR)
+		{
+			return ret;
+		}
+	}
+	if (ret)
+	{
+		return ret;
+	}
+	ret=SD_TuneWrite( address,txbuffer,num,isLinkListBuf);
+	return ret;
+}
+/*************************************************************************
+* FUNCTION
+*  SD_Reset
+*
+* DESCRIPTION
+*	reset all cards to idle state
+*
+* PARAMETERS
+*	1. cmd: the content of SDC_CMD register
+*	2. arg: the argument(if the command need no argument, fill it with 0)
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_Reset(void)
+{
+	SDC_CMD_STATUS status;
+	status=SD_SendCmd(SDC_CMD_CMD0,SDC_NO_ARG,MSDC_CMD_TIMEOUT);
+	gSD->mState=IDLE_STA;
+	return status;
+    
+}
+
+/*************************************************************************
+* FUNCTION
+*  SD_Cmd55
+*
+* DESCRIPTION
+*	APP_CMD: inidicate to the card that the next command is an application specified command
+*			rather than a standard command
+*
+* PARAMETERS
+*	rca: relative card address
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_Cmd55(kal_uint16 rca)
+{
+	SDC_CMD_STATUS status;
+
+    if ((status = SD_SendCmd(SDC_CMD_CMD55, ((kal_uint32)rca << 16),MSDC_CMD_TIMEOUT)) != NO_ERROR)
+        return status;
+        
+    //read R1
+    if ((status = SD_CheckStatus()) != NO_ERROR)
+        return status;
+
+    //check APP_CMD bit in status register
+    status=MSDC_Reg32(SDC_RESP0);
+
+    if (!(status & R1_APP_CMD_5))
+        return ERR_APPCMD_FAILED;
+
+    return NO_ERROR;
+   
+}
+/*************************************************************************
+* FUNCTION
+*  SD_Cmd8
+*
+* DESCRIPTION
+*	1. Sends SD Memory Card interface conditions for support larger than 2G cards
+*	2. check if the card is compliant to SD2.0 or higher
+*	3. only performed while at IDLE state.
+*
+* PARAMETERS
+*
+* RETURNS
+*
+* GLOBALS AFFECTED
+*	gSD->mIsCMD8
+*
+*************************************************************************/
+void SD_Cmd8(void)
+{
+    kal_uint32 resp;
+    kal_uint32 retry = 4;
+    MSDC_DEBUG("[SD][%s %d]Cmd8 arg=%x\r\n",__FUNCTION__,__LINE__,SDC_CMD8_ARG);
+
+cmd8_retry:	
+    if (SD_SendCmd(SDC_CMD_CMD8, SDC_CMD8_ARG,MSDC_CMD_TIMEOUT) != NO_ERROR)
+    {
+        MSDC_ERR("[SD][%s %d]SDC_Cmd8 fail\r\n",__FUNCTION__,__LINE__);
+        SD_Reset();
+        gSD->mCMD8Resp = SD_CMD8_RESP_NORESP;
+        return;
+    }
+
+    resp= MSDC_Reg32(SDC_RESP0);
+    MSDC_DEBUG("[SD][%s %d]Cmd8 resp=%x\r\n",__FUNCTION__,__LINE__,resp);
+
+    if (resp == SDC_CMD8_ARG)
+        gSD->mCMD8Resp = SD_CMD8_RESP_VALID;
+    else {
+        MSDC_ERR("[SD]CMD8 check pattern error, %X(%X)\r\n",SDC_CMD8_ARG,resp);
+        
+        if (retry--)
+            goto cmd8_retry;
+
+        gSD->mCMD8Resp = SD_CMD8_RESP_INVALID;
+    }
+
+    return;
+}
+
+/*************************************************************************
+* FUNCTION
+*  SD_Cmd1_MMC
+*
+* DESCRIPTION
+*	 asks all cards in idle state to send their OCR in the response on the CMD line
+*
+* PARAMETERS
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*	gSD
+*
+* NOTE
+*	only works for MMC
+*
+*************************************************************************/
+extern kal_bool FTL_isPollingMode();
+
+SDC_CMD_STATUS SD_Cmd1_MMC(void)
+{
+    SDC_CMD_STATUS status;
+    kal_uint32 _ocr, ocr_i,  t2;
+
+    #if defined(SD_MMC_HIGH_DENSITY_SUPPORT)
+
+    if (gSD->mCMD8Resp == SD_CMD8_RESP_INVALID)
+        return ERR_CMD8_INVALID;
+
+    ocr_i = (SDC_OCR_DEFAULT | MMC_HIGH_DESITY_CHECK_BIT);
+    #else
+    ocr_i = SDC_OCR_DEFAULT;
+    #endif
+
+    if (gMSDC_Handle->is_init_timeout == KAL_TRUE)
+        return ERR_R3_OCR_BUSY;
+
+    t2 = drv_get_current_time();
+
+    do
+    {
+        /*send cmd1*/
+        if ((status=SD_SendCmd(SDC_CMD_CMD1,ocr_i,MSDC_CMD_TIMEOUT))  != NO_ERROR)
+            return status;
+
+        _ocr=MSDC_Reg32(SDC_RESP0);
+        MSDC_NOTICE("[SD]OCR = %x\r\n", _ocr);
+
+        if ((_ocr & SDC_OCR_DEFAULT) == 0)
+            return ERR_OCR_NOT_SUPPORT;
+
+        if (!gMSDC_Handle->mIsPresent)
+            return MSDC_CARD_NOT_PRESENT;
+
+        if (!(_ocr & SDC_OCR_BUSY))
+        {
+            if (drv_get_duration_ms(t2) > MSDC_TIMEOUT_PERIOD_INI)
+            {
+                gMSDC_Handle->is_init_timeout = KAL_TRUE;
+                break;
+            }
+
+            msdc_sleep(2);
+        }
+        else {
+            MSDC_CRIT("[SD]OCR = %x\r\n", _ocr);
+            break;
+        }
+    }
+    while (1);
+
+    if (gMSDC_Handle->is_init_timeout)
+        return ERR_CMD_TIMEOUT;
+
+#if defined(SD_MMC_HIGH_DENSITY_SUPPORT)
+
+    if ((_ocr & MMC_HIGH_DESITY_CHECK_MSK) == MMC_HIGH_DESITY_CHECK_BIT)
+    {
+        gSD->flags |= SD_FLAG_HCS_SUPPORT;
+        gMSDC_Handle->mMSDC_type = MMC42_CARD;
+        gSD->mIsBlkAddr = 1;
+    }
+    else
+#endif
+        gMSDC_Handle->mMSDC_type = MMC_CARD;
+
+    gSD->mInactive = KAL_FALSE;
+    gSD->mSDC_ocr = _ocr;
+    gSD->mState = READY_STA;
+
+    return NO_ERROR;
+}
+SDC_CMD_STATUS SD_Cmd11(void)
+{
+    SDC_CMD_STATUS status;
+
+    if ((status = SD_SendCmd(SDC_CMD_CMD11, SDC_NO_ARG,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+    {
+        return status;
+    }
+    //read R1
+    if ((status = SD_CheckStatus()) != NO_ERROR)
+        return status;
+
+    return NO_ERROR;
+   
+}
+kal_int32 SD_SwitchVolt18()
+{
+    kal_uint32 status,t2;
+    status=SD_Cmd11();
+    if (status !=NO_ERROR)
+        return status;
+    /*make sure SDC is not BUSY*/
+    if (MSDC_TIMEOUT_WAIT((!SD_IS_SDC_BUSY())&&MSDC_Check_Card_Present(),MSDC_CMD_TIMEOUT))
+    {
+	    MSDC_ERR("[SD][%s %d]wait SDC busy timeout\r\n",__FUNCTION__,__LINE__);
+        return ERR_STATUS;
+    }
+    /*check data[3:0] and cmd is lower by card*/
+    if(MSDC_Reg32(MSDC_PS)&((1<<24)|(0xf<<16)))
+        return CHECK_DATA_CMD_LOW_FAIL;
+    /*pull up disabled in CMD and DAT[3:0]*/
+    MSDC_ConfigPin(MSDC_PIN_PULL_NONE);
+    /*switch signal voltage to 1.8v*/
+    gMSDC_Handle->signal_volt=1800;
+    MSDC_SetSignalPower(1,gMSDC_Handle->signal_volt);
+    /*wait 5ms*/
+    msdc_sleep(2);
+    /*PULL UP enable in CMD and DAT[3:0]*/
+    MSDC_ConfigPin(MSDC_PIN_PULL_UP);
+    msdc_sleep(1);
+    /*start to detect volt change */
+    MSDC_SetBits32(MSDC_CFG,MSDC_CFG_BV18SDT);
+    msdc_sleep(20);
+    t2=drv_get_current_time();
+    do{
+        if(((status=MSDC_Reg32(MSDC_CFG))& MSDC_CFG_BV18SDT)==0);
+        {
+            if (status&MSDC_CFG_BV18PSS)
+            {
+                //pass to switch volt to 1.8v
+                return NO_ERROR;
+            }
+            else
+            {
+                //fail to switch volt to 1.8v
+	            MSDC_ERR("[SD][%s %d]1.8v fail ,MSDC_CFG %x\r\n",__FUNCTION__,__LINE__,status);
+                break;
+            }
+        }
+        if (drv_get_duration_ms(t2) > MSDC_TIMEOUT_PERIOD_INI)
+        {
+            //detect volt change timeout
+	        MSDC_ERR("[SD][%s %d]detect volt change timeout\r\n",__FUNCTION__,__LINE__);
+            break;
+        }
+    }while(1);
+
+    //come to here ,mean timeout or switch 1.8v fail
+    
+    return ERR_STATUS;
+}
+/*************************************************************************
+* FUNCTION
+*  SD_Acmd41_SD
+*
+* DESCRIPTION
+*	asks all cards in idle state to send their OCR in the response on the CMD line
+*	OCR: Operation Condition Register
+*
+* PARAMETERS
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*	gSD
+*
+* NOTE
+*	only works for SD
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_Acmd41_SD(void)
+{
+	SDC_CMD_STATUS		status;
+    kal_uint32			_ocr = 0, ocr_i = 0,  t2;
+    
+#if defined(SD_MMC_HIGH_DENSITY_SUPPORT)
+
+    if (gSD->mCMD8Resp == SD_CMD8_RESP_NORESP)
+        ocr_i = SDC_OCR_DEFAULT;
+    else if (gSD->mCMD8Resp == SD_CMD8_RESP_VALID) {
+        #if defined(MSDC_CONFIG_SD30_SUPPORT)
+        if (TEMP_SINGLE_LINE == gMSDC_Handle->trySingleLine)
+            ocr_i = (SDC_OCR_DEFAULT | SD_ACMD41_HCS);
+        else
+            ocr_i = (SDC_OCR_DEFAULT | SD_ACMD41_HCS |SD_ACMD41_S18R | SD_ACMD41_XPC);
+           
+        #else
+        ocr_i = (SDC_OCR_DEFAULT | SD_ACMD41_HCS);
+        #endif
+    }
+    else if (gSD->mCMD8Resp == SD_CMD8_RESP_INVALID)
+        return ERR_CMD8_INVALID;
+
+#else
+    ocr_i = SDC_OCR_DEFAULT;
+#endif
+    MSDC_CRIT("[SD][%s %d]Host OCR = %x\r\n",__FUNCTION__,__LINE__,ocr_i);
+ retry:
+    gMSDC_Handle->is_init_timeout = KAL_FALSE;
+    t2 = drv_get_current_time();
+
+    do
+    {
+        /*send ACMD41*/
+        status = SD_Cmd55(SDC_RCA_DEFAULT);
+
+        if (status != NO_ERROR)
+        {
+            return status;
+        }   
+
+        status=SD_SendCmd(SDC_CMD_ACMD41, ocr_i, MSDC_CMD_TIMEOUT);
+        if (status != NO_ERROR)
+        {
+            return status;
+        }
+        
+        /*check response*/
+        _ocr = MSDC_Reg32(SDC_RESP0);
+        MSDC_NOTICE("[SD]ACMD41 resp = %x\r\n", _ocr);
+
+        if ((_ocr & SDC_OCR_DEFAULT) == 0)
+            return ERR_OCR_NOT_SUPPORT;
+
+        if (!gMSDC_Handle->mIsPresent)
+            return ERR_CARD_NOT_PRESENT;
+
+        if (!(_ocr & SDC_OCR_BUSY))
+        {
+            /*if return busy ,we check timeout or not*/
+            if (drv_get_duration_ms(t2) > MSDC_TIMEOUT_PERIOD_INI)
+            {
+                gMSDC_Handle->is_init_timeout = KAL_TRUE;
+                MSDC_ERR("[SD]ACMD41 Polling BUSY timeout!\r\n");
+                break;
+            }
+
+            msdc_sleep(5);
+        }
+        else
+        {
+            /*not busy */
+            MSDC_CRIT("[SD]OCR = %x\r\n", _ocr);
+            break;
+        }
+    }
+    while (1);
+
+    if (gMSDC_Handle->is_init_timeout)
+        return ERR_R3_OCR_BUSY;
+
+    gSD->mInactive = KAL_FALSE;
+    gSD->mSDC_ocr = _ocr;
+#if defined(SD_MMC_HIGH_DENSITY_SUPPORT)
+    gSD->flags |= SD_FLAG_SD_TYPE_CARD;
+
+    if (_ocr & SD_ACMD41_HCS)
+    {
+        #if defined(MSDC_CONFIG_SD30_SUPPORT)
+        if (_ocr & SD_ACMD41_S18R )
+        {
+            status=SD_SwitchVolt18();
+            if (status != NO_ERROR)
+            {
+                return status;  //need delete
+                //fail to switch to 1.8v ,so set signal voltage back to 3.3.v
+                gMSDC_Handle->signal_volt=3300;
+                MSDC_SetSignalPower(1,gMSDC_Handle->signal_volt);
+                power_cycle(1);
+                SD_Reset();
+                SD_Cmd8();
+                ocr_i = (SDC_OCR_DEFAULT | SD_ACMD41_HCS);
+                goto retry;
+            }
+
+            gSD->flags|=SD_FLAG_UHS_SUPPORT;
+            gMSDC_Handle->mMSDC_type=SD30_CARD;
+ 	        MSDC_CRIT("[SD][%s %d]SD3.0 UHS Card\r\n",__FUNCTION__,__LINE__);
+        }
+        else
+        #endif
+        {
+            gSD->flags |= SD_FLAG_HCS_SUPPORT;
+            gMSDC_Handle->mMSDC_type = SD20_HCS_CARD;
+ 	        MSDC_CRIT("[SD][%s %d]SD2.0 High Capacity Card\r\n",__FUNCTION__,__LINE__);
+            
+        }
+      
+        
+    }
+    else if (gSD->mCMD8Resp == SD_CMD8_RESP_VALID)
+        gMSDC_Handle->mMSDC_type = SD20_LCS_CARD;
+    else
+#endif
+        gMSDC_Handle->mMSDC_type = SD_CARD;
+
+    gSD->mState = READY_STA;
+
+    return NO_ERROR;
+    
+}
+
+/*************************************************************************
+* FUNCTION
+*  SD_GetCID
+*
+* DESCRIPTION
+*	Read Card Identification.
+*
+* PARAMETERS
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*	gSD
+*
+* NOTE
+*
+*
+*************************************************************************/
+
+// Get CID(CMD2)
+SDC_CMD_STATUS SD_GetCID(kal_uint32 *Cid)
+{
+     int i;
+    SDC_CMD_STATUS status;
+
+    if ((status = SD_SendCmd(SDC_CMD_CMD2, SDC_NO_ARG,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+    {
+        	return status;
+    }
+     
+    //read R2
+    for (i = 0; i < 4; i++)
+    {
+        Cid[i]=MSDC_Reg32((SDC_RESP0 + i * sizeof(kal_uint32)));
+    }
+    
+    SD_AnalysisCID(Cid);
+    gSD->mState = IDENT_STA;
+
+    return NO_ERROR;
+    
+}
+
+/*************************************************************************
+* FUNCTION
+*  SD_ValidateRCA
+*
+* DESCRIPTION
+*	assing or read RCA
+*
+* PARAMETERS
+*	pRca: used for input or output RCA
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*	gSD
+*
+* NOTE
+*	RCA is assinged to MMC card fixed to SDC_RCA_MMC(1)
+*
+*************************************************************************/
+
+// assign or read RCA
+SDC_CMD_STATUS SD_ValidateRCA(kal_uint16* pRca)
+{
+    SDC_CMD_STATUS status;
+    kal_uint32 resp;
+    kal_uint8  state;
+    kal_uint32 retry;
+
+#if defined(SD_MMC_HIGH_DENSITY_SUPPORT)
+
+    if (gSD->flags & SD_FLAG_SD_TYPE_CARD )
+#else
+    if (gMSDC_Handle->mMSDC_type == SD_CARD)
+#endif
+    {
+        //read RCA form card
+        retry=10;
+	/*if card return RCA=0  we will retry,*/
+        while(retry--)
+        {
+     		MSDC_DEBUG("[SD][%s %d]send cmd3\r\n",__FUNCTION__,__LINE__);
+	        if ((status = SD_SendCmd(SDC_CMD_CMD3, SDC_NO_ARG,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+	            return status;
+
+	        //read R6
+	        resp=MSDC_Reg32(SDC_RESP0);
+    		MSDC_DEBUG("[SD][%s %d]cmd3 reps=%x\r\n",__FUNCTION__,__LINE__,resp);	
+#ifdef MSDC_TRACE_LEVEL1
+	        MD_TRC_MSDC_INFORM_R0(resp, __LINE__);
+#endif
+    		if ((resp>>16)!=0)
+    		{
+    	       	 *pRca = resp >>  16;
+    	       	 gSD->mRCA = *pRca;
+    			 break;
+    		}
+    		MSDC_DEBUG("[SD][%s %d]gSD->mRCA=%x\r\n",__FUNCTION__,__LINE__,gSD->mRCA);	
+        }
+	 if (retry==0)
+	 {
+	 	/*always return RCA=0*/
+	 	return ERR_RCA_FAIL;
+	 }
+
+    }
+    else
+    {
+        //assign RCA to card
+        if ((status = SD_SendCmd(SDC_CMD_CMD3_MMC, ((kal_uint32)SDC_RCA_MMC << 16),MSDC_CMD_TIMEOUT)) != NO_ERROR)
+            return status;
+
+        //read R1
+        resp=MSDC_Reg32(SDC_RESP0);
+#ifdef MSDC_TRACE_LEVEL1
+        MD_TRC_MSDC_INFORM_R0(resp, __LINE__);
+#endif
+        SD_GetStatus(SDC_RCA_MMC, &resp);
+        state = 0;
+        GetBitFieldN((kal_uint8*)&state, (kal_uint8*)&resp, 9, 4);
+
+        if (STBY_STA != state)
+            return ERR_RCA_FAIL;
+
+        *pRca = gSD->mRCA = SDC_RCA_MMC;
+    }
+
+    gSD->mState = STBY_STA;
+    return NO_ERROR;
+}
+
+/*************************************************************************
+* FUNCTION
+*  SD_SetDSR
+*
+* DESCRIPTION
+*	set default value to the DSR
+*
+* PARAMETERS
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*	SDC_DSR_DEFAULT(0x404)
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_SetDSR(void)
+{
+    return SD_SendCmd(SDC_CMD_CMD4, (kal_uint32)SDC_DSR_DEFAULT << 16,MSDC_CMD_TIMEOUT);
+}
+
+/*************************************************************************
+* FUNCTION
+*  SD_SelectCard
+*
+* DESCRIPTION
+*	select/deselect card
+*
+* PARAMETERS
+*	rca: relative card address
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_SelectCard(kal_uint16 rca)
+{
+    SDC_CMD_STATUS status;
+    MSDC_DEBUG("[SD][%s %d]send cmd7\r\n",__FUNCTION__,__LINE__);
+
+    if ((status = SD_SendCmd(SDC_CMD_CMD7, ((kal_uint32)rca << 16),MSDC_CMD_TIMEOUT)) != NO_ERROR)
+    {
+        return status;
+    }
+	
+    //read R1b
+    if ((status = SD_WaitCardNotBusy(MSDC_DATA_TIMEOUT)) != NO_ERROR)
+        return status;
+
+    if ((status = SD_CheckStatus()) != NO_ERROR)
+        return status;
+
+    return NO_ERROR;
+}
+
+/*************************************************************************
+* FUNCTION
+*  SD_GetCSD
+*
+* DESCRIPTION
+*	Get CSD from addressed card
+*
+* PARAMETERS
+*	rca: relative card address
+*	Csd: used for containing read CSD
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_GetCSD(kal_uint16 rca, kal_uint32 Csd[4])
+{
+    SDC_CMD_STATUS status;
+    kal_uint32 i;
+    MSDC_DEBUG("[SD][%s %d]send cmd9\r\n",__FUNCTION__,__LINE__);
+
+    if ((status = SD_SendCmd(SDC_CMD_CMD9, ((kal_uint32)rca << 16),MSDC_CMD_TIMEOUT)) != NO_ERROR)
+    {
+        return status;
+    }
+	
+
+    // read R2
+    for (i = 0; i < 4; i++)
+    {
+        Csd[i]=MSDC_Reg32((volatile kal_uint32 *)(SDC_RESP0 + i * 4));
+	    #ifdef MSDC_DEBUG_PRINT
+	    MSDC_DEBUG("%x ",Csd[i]);
+	    #endif
+    }
+	#ifdef MSDC_DEBUG_PRINT
+	MSDC_DEBUG("\r\n ");
+	#endif
+    // analysis CSD...
+    SD_AnalysisCSD(Csd);
+
+    return NO_ERROR;
+}
+
+// addressed send CID
+SDC_CMD_STATUS SD_GetAddressedCID(kal_uint16 rca, kal_uint32 Cid[4])
+{
+     SDC_CMD_STATUS status;
+    kal_uint32 i;
+
+    if ((status = SD_SendCmd(SDC_CMD_CMD10, (kal_uint32)rca << 16,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+        return status;
+
+    // read R2
+    for (i = 0; i < 4; i++)
+    {
+#ifndef DRV_LSD
+       Cid[i]=MSDC_Reg32((volatile kal_uint32 *)(SDC_RESP0 + i * 4));
+#else
+       Cid[i]=MSDC_Reg32(SDC_RESP0 + i);
+#endif
+    }
+
+    return NO_ERROR;
+}
+
+
+/*************************************************************************
+* FUNCTION
+*  SD_StopTrans
+*
+* DESCRIPTION
+*	Stop Muli-Block operation
+*
+* PARAMETERS
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*	definition of SD_STOP_SLOW is used for some erroneous card
+*************************************************************************/
+SDC_CMD_STATUS SD_StopTrans(void)
+{
+	SDC_CMD_STATUS status;
+	#define CMD12_TIMEOUT_MS	1000		
+	status = SD_SendCmd(SDC_CMD_CMD12,SDC_NO_ARG,MSDC_CMD_TIMEOUT);
+	MSDC_CLR_FIFO();
+	return status;
+    
+}
+
+/*************************************************************************
+* FUNCTION
+*  SD_GetStatus
+*
+* DESCRIPTION
+*	addressed send status
+*
+* PARAMETERS
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_GetStatus(kal_uint16 rca, kal_uint32* resp)
+{
+    SDC_CMD_STATUS status;
+
+    if ((status = SD_SendCmd(SDC_CMD_CMD13, ((kal_uint32)rca << 16),MSDC_CMD_TIMEOUT)) != NO_ERROR)
+        return status;
+
+    *resp=MSDC_Reg32(SDC_RESP0);
+    
+    return NO_ERROR;
+}
+
+/*************************************************************************
+* FUNCTION
+*  SD_SetBlength
+*
+* DESCRIPTION
+*	set block length
+*
+* PARAMETERS
+*	BKLength: block length u want to set
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*	gSD->mBKLength
+*
+* NOTE
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_SetBlength(kal_uint32 BKLength)
+{
+    SDC_CMD_STATUS status;
+    
+    // maximal value of block length is 2048
+    if (BKLength > SDC_MAX_BKLENGTH)
+        return ERR_INVALID_BKLENGTH;
+
+    if (!gSD->mCSD.r_blk_part && BKLength < gSD->mCSD.max_r_blk_len )
+        return ERR_INVALID_BKLENGTH;
+    if ((status = SD_SendCmd(SDC_CMD_CMD16, BKLength,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+        return status;
+
+    //read R1
+    status = SD_CheckStatus();
+    // 2. configure the controller
+    gSD->mBKLength = BKLength;
+   // BitFieldWrite32((kal_uint32*)SDC_CMD, BKLength, SDC_CMD_BLKLEN);
+    return status;
+}
+
+
+/*************************************************************************
+* FUNCTION
+*  SD_ReadSingleBlock
+*
+* DESCRIPTION
+*	1. read a single block form data_adrs of card to the rxbuffer
+*	2. the block length is set by set block length
+*
+* PARAMETERS
+*	data_adrs: starting address to read
+*	rxbuffer: as name
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*	the size of rxbuffer should be 4*n (n : integer)
+*
+*************************************************************************/
+#ifdef DRV_MSDC_SLIM
+SDC_CMD_STATUS SD_ReadSingleBlock(kal_uint32 data_adrs, kal_uint32* rxbuffer) // slim
+{
+    return SD_ReadMultiBlock(data_adrs, rxbuffer, 1); // slim
+}
+#else
+SDC_CMD_STATUS SD_ReadSingleBlock(kal_uint32 data_adrs, kal_uint32* rxbuffer)
+{
+    return SD_ReadMultiBlock(data_adrs, rxbuffer, 1);
+}
+#endif
+/*************************************************************************
+* FUNCTION
+*  SD_ReadMultiBlock
+*
+* DESCRIPTION
+*	read num of blocks into rxbuffer
+*
+* PARAMETERS
+*	data_adrs: starting address to read
+*	rxbuffer: as name
+*	num: number of blocks to read
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*
+*************************************************************************/
+#ifdef DRV_MSDC_SLIM
+SDC_CMD_STATUS 
+SD_ReadMultiBlock(kal_uint32 data_adrs, kal_uint32* rxbuffer, kal_uint32 num_blk) // slim
+{
+    
+
+}
+#else
+SDC_CMD_STATUS SD_ReadMultiBlock(kal_uint32 data_adrs, kal_uint32* rxbuffer, kal_uint32 num_blk)
+{
+   kal_uint32 status;
+
+   status = SD_ReqHandleData(data_adrs, rxbuffer,num_blk, KAL_FALSE,KAL_FALSE);
+   if (status==ERR_DAT_CRCERR)
+   {
+ 	    status=SD_TuneRead(data_adrs,rxbuffer,num_blk,KAL_FALSE);
+   }
+   return status;
+}
+#endif
+
+
+
+/*************************************************************************
+* FUNCTION
+*  SD_WriteSingleBlock
+*
+* DESCRIPTION
+*	write a single block
+*
+* PARAMETERS
+*	address: starting address to write
+*	txbuffer: as name
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*	block length is set by Set_Block_Length
+*
+*************************************************************************/
+#ifdef DRV_MSDC_SLIM
+//__attribute__ ((section ("EXT_BOOTLOADER_CODE"))) SDC_CMD_STATUS SD_WriteSingleBlock(kal_uint32 address, kal_uint32* txbuffer) // slim
+SDC_CMD_STATUS SD_WriteSingleBlock(kal_uint32 address, kal_uint32* txbuffer)
+{
+    return SD_WriteMultiBlock(address, txbuffer, 1); // slim
+}
+#else
+//__attribute__ ((section ("EXT_BOOTLOADER_CODE"))) SDC_CMD_STATUS SD_WriteSingleBlock(kal_uint32 address, kal_uint32* txbuffer)
+SDC_CMD_STATUS SD_WriteSingleBlock(kal_uint32 address, kal_uint32* txbuffer)
+{
+    return SD_WriteMultiBlock(address, txbuffer, 1);
+}
+#endif
+
+void SD_Sleep4Wait(kal_int32 sleep_tick)
+{
+   
+}
+/*************************************************************************
+* FUNCTION
+*	SD_WriteMultiBlock
+*
+* DESCRIPTION
+*	write num blocks starting at address
+*
+* PARAMETERS
+*	address: starting address to write
+*	txbuffer: as name
+*	num: number of blocks to write
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*	block length is set by Set_Block_Length
+*
+*************************************************************************/
+//#ifndef DRV_MSDC_SLIM
+//__attribute__ ((section ("EXT_BOOTLOADER_CODE"))) SDC_CMD_STATUS SD_WriteMultiBlock(kal_uint32 address, kal_uint32* txbuffer, kal_uint32 num)
+SDC_CMD_STATUS SD_WriteMultiBlock(kal_uint32 address, kal_uint32* txbuffer, kal_uint32 num_blk)
+{
+    SDC_CMD_STATUS status;
+    
+    if (gSD->mWPEnabled)
+        return ERR_WRITE_PROTECT;
+    if ((status=SD_ReqHandleData(address, txbuffer, num_blk, KAL_TRUE,KAL_FALSE))!=NO_ERROR)
+    {        
+		if (status ==ERR_DAT_CRCERR)
+		{
+			status=SD_TuneWrite(address,txbuffer,num_blk,KAL_FALSE);
+		}
+		else if (status == ERR_DAT_TIMEOUT)
+		{
+			status=SD_HandleWriteTMO(address,txbuffer,num_blk,KAL_FALSE);
+		}
+    }
+    
+        return status;
+}
+
+SDC_CMD_STATUS SD_GpdWriteMultiBlock(kal_uint32 address ,kal_uint32 num_blk,void *gpd_data)
+{
+    SDC_CMD_STATUS status;
+
+    gMSDC_Handle->f_tuning = 0;
+    
+    if (gSD->mWPEnabled)
+        return ERR_WRITE_PROTECT;
+    if ((status=SD_ReqHandleData(address, gpd_data, num_blk, KAL_TRUE,KAL_TRUE))!=NO_ERROR)
+    {
+        gMSDC_Handle->f_tuning = 1;
+        
+		if (status ==ERR_DAT_CRCERR)
+		{
+			status=SD_TuneWrite(address,gpd_data,num_blk,KAL_TRUE);
+		}
+		else if (status == ERR_DAT_TIMEOUT)
+		{
+			status=SD_HandleWriteTMO(address,gpd_data,num_blk,KAL_TRUE);
+		}
+    }    
+    return status;
+}
+
+SDC_CMD_STATUS SD_GpdReadMultiBlock(kal_uint32 address ,kal_uint32 num_blk,void *gpd_data )
+{
+    kal_uint32 status;
+    
+    gMSDC_Handle->f_tuning = 0;
+    status = SD_ReqHandleData(address, gpd_data,num_blk, KAL_FALSE,KAL_TRUE);
+    
+    if (status==ERR_DAT_CRCERR)
+    {
+        gMSDC_Handle->f_tuning = 1;
+        status=SD_TuneRead(address,gpd_data,num_blk,KAL_TRUE);
+    }
+    return status;
+}
+
+
+//#else
+//__attribute__ ((section ("EXT_BOOTLOADER_CODE"))) SDC_CMD_STATUS SD_WriteMultiBlock(kal_uint32 address, kal_uint32* txbuffer, kal_uint32 num) // slim
+//SDC_CMD_STATUS SD_WriteMultiBlock(kal_uint32 address, kal_uint32* txbuffer, kal_uint32 num) // slim
+//{
+    
+
+//}
+//#endif
+
+
+/*************************************************************************
+* FUNCTION
+*	SD_SetBusWidth
+*
+* DESCRIPTION
+*	ACMD6: set the data width 00 for 1 bit, 10 for 4 bits
+*
+* PARAMETERS
+*	width: indicate the bus width
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*	Not every card support 4-bits bus
+*	only for SD
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_SetBusWidth(SD_BITWIDTH width)
+{
+    SDC_CMD_STATUS status;
+    MSDC_DEBUG("[SD][%s %d]send ACMD6 ,change bus width to %d\r\n",__FUNCTION__,__LINE__,width);
+
+    // check if card support 4 bits bus
+    if ((width == BIT_4W) && !(gSD->mSCR.bus_width & 0x04))
+        return ERR_NOT_SUPPORT_4BITS;
+
+    // send APP_CMD
+    if ((status = SD_Cmd55(gSD->mRCA)) != NO_ERROR)
+        return status;
+
+    // send cmd6
+    if ((status = SD_SendCmd(SDC_CMD_ACMD6, width,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+        return status;
+
+    //read R1
+    if ((status = SD_CheckStatus()) != NO_ERROR)
+        return status;
+
+   
+        // set the controler  bus width
+	MSDC_SetBusWidth(width);
+    gSD->bus_width = width;
+    return NO_ERROR;
+}
+
+/*************************************************************************
+* FUNCTION
+*	SD_ReadSCR
+*
+* DESCRIPTION
+*	ACMD51: read the SD Configuration Register(8bytes block read)
+*
+* PARAMETERS
+*	scr: used for store SCR
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*	Make sure the size of SCR is 8 bytes
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_ReadSCR(kal_uint32* scr)
+{
+    SDC_CMD_STATUS status;
+    kal_uint32 blklen;
+
+    ASSERT((kal_uint32)scr % 4  == 0);
+
+    MSDC_DEBUG("[SD][%s %d]send cmd55\r\n",__FUNCTION__,__LINE__);
+
+    // send APP_CMD
+    if ((status = SD_Cmd55(gSD->mRCA)) != NO_ERROR)
+        return status;
+        
+    // set block number 
+    blklen=gSD->mBKLength;
+    gSD->mBKLength = 8;
+    MSDC_WriteReg32(SDC_BLK_NUM,1);
+    MSDC_DEBUG("[SD][%s %d]send acmd51\r\n",__FUNCTION__,__LINE__);
+
+    // set to pio mode and clear fifo
+    BitFieldWrite32((kal_uint32 *)MSDC_CFG, 1, MSDC_CFG_PIO);
+    gMSDC_Handle->dma_xfer=0;
+    MSDC_CLR_FIFO();
+    
+    // send command
+    if ((status = SD_SendCmd(SDC_CMD_ACMD51, SDC_NO_ARG,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+        return status;
+
+    // read R1
+    if ((status = SD_CheckStatus()) != NO_ERROR)
+        return status;
+
+    // read data(8bytes)
+    status=SD_WaitDatRdyOrTo(scr,8,KAL_FALSE);
+    if (status !=NO_ERROR) 
+        return status;
+    MSDC_DEBUG("[SD][%s %d]scr=%x %x\r\n",__FUNCTION__,__LINE__,*scr,*(scr+1));	
+	
+    SD_AnalysisSCR(scr);
+    MSDC_CLR_FIFO();
+    	
+    gSD->mBKLength = blklen;
+
+    return NO_ERROR;
+
+}
+
+static kal_uint32 unstuff_sd_status(kal_uint32 *raw_sd_status, kal_uint32 start, kal_uint32 size)
+{
+    kal_uint32 __mask = (1 << (size)) - 1;
+    int __off = 63 - ((start) / 8);
+    int __shft;
+    kal_uint8 *raw = (kal_uint8 *)raw_sd_status;
+    kal_uint32 __res = 0;
+
+    if ((start & 7) + 1 >= size)
+    {
+        __shft = ((start & 7) + 1) - size;
+        __res = raw[__off] >> __shft;
+    }
+    else if (size <= 32)
+    {
+        size -= ((start & 7) + 1);
+        __shft = size;
+        __res = raw[__off] << __shft;
+        while (size)
+        {
+            __off++;
+            if (size >= 8)
+            {
+                size -= 8;
+                __res |= raw[__off] << size;
+            }
+            else
+            {
+                __mask = (1 << (size)) - 1;
+                __res |= (raw[__off] >> (8 - size)) & __mask;
+                size = 0;
+            }
+        }
+    }
+    return __res & __mask;
+}
+#define UNSTUFF_SD_STATUS(r,s,sz)    unstuff_sd_status(r,s,sz)
+
+/*************************************************************************
+* FUNCTION
+*	SD_ReadSDStatus
+*
+* DESCRIPTION
+*	ACMD13: read the SD Status Register(64bytes block read)
+*
+* PARAMETERS
+*	sd_status: used for store SD Status
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*	Make sure the size of SD Status is 64 bytes
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_ReadSDStatus(kal_uint32* sd_status)
+{
+    SDC_CMD_STATUS status;
+    kal_uint32 blklen;
+
+    ASSERT((kal_uint32)sd_status % 4  == 0);
+
+    MSDC_DEBUG("[SD][%s %d]send cmd55\r\n",__FUNCTION__,__LINE__);
+
+    // send APP_CMD
+    if ((status = SD_Cmd55(gSD->mRCA)) != NO_ERROR)
+        return status;
+        
+    // set block number 
+    blklen=gSD->mBKLength;
+    gSD->mBKLength = 64;
+    MSDC_WriteReg32(SDC_BLK_NUM,1);
+    MSDC_DEBUG("[SD][%s %d]send acmd13\r\n",__FUNCTION__,__LINE__);
+
+    // set to pio mode and clear fifo
+    BitFieldWrite32((kal_uint32 *)MSDC_CFG, 1, MSDC_CFG_PIO);
+    gMSDC_Handle->dma_xfer=0;
+    
+    // send command
+    if ((status = SD_SendCmd(SDC_CMD_ACMD13, SDC_NO_ARG,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+        return status;
+
+    // read R1
+    if ((status = SD_CheckStatus()) != NO_ERROR)
+        return status;
+
+    // read data(8bytes)
+    status=SD_WaitDatRdyOrTo(sd_status,64,KAL_FALSE);
+    gSD->mBKLength = blklen;
+
+    if (status !=NO_ERROR) 
+        return status;
+    MSDC_DEBUG("[SD][%s %d]sd_status=%x %x\r\n",__FUNCTION__,__LINE__,*sd_status,*(sd_status+1));	
+	
+    gSD->mSDSts.dat_bus_width = UNSTUFF_SD_STATUS(sd_status, 511, 2);
+    gSD->mSDSts.secured_mode = UNSTUFF_SD_STATUS(sd_status, 509, 1);
+    gSD->mSDSts.sd_card_type = UNSTUFF_SD_STATUS(sd_status, 495, 16);
+    gSD->mSDSts.size_of_prot_area = UNSTUFF_SD_STATUS(sd_status, 479, 32);
+    gSD->mSDSts.speed_class = UNSTUFF_SD_STATUS(sd_status, 447, 8);
+    gSD->mSDSts.perf_move = UNSTUFF_SD_STATUS(sd_status, 439, 8);
+    gSD->mSDSts.au_size = UNSTUFF_SD_STATUS(sd_status, 431, 4);
+    gSD->mSDSts.erase_size = UNSTUFF_SD_STATUS(sd_status, 423, 16);
+    gSD->mSDSts.erase_timeout = UNSTUFF_SD_STATUS(sd_status, 407, 6);
+    gSD->mSDSts.erase_offset = UNSTUFF_SD_STATUS(sd_status, 401, 2);
+    gSD->mSDSts.uhs_speed_grade = UNSTUFF_SD_STATUS(sd_status, 399, 4);
+    gSD->mSDSts.uhs_au_size = UNSTUFF_SD_STATUS(sd_status, 395, 4);
+
+    /* If it is a SD ROM Card, set the WP flag */
+    if (gSD->mSDSts.sd_card_type == 0x0001) {
+        gSD->mWPEnabled = KAL_TRUE;
+        MSDC_CRIT("[SD]It is a ROM Card!\r\n");
+    }
+
+    return NO_ERROR;
+
+}
+
+
+/*************************************************************************
+* FUNCTION
+*	SD_SetPreEraseBlk
+*
+* DESCRIPTION
+*	ACMD23: set the number of write blocksto be pre-erased before writing
+*	used for faster multiple Block Write
+*
+* PARAMETERS
+*	num: used for storing number of blocks during multi-block operation
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_SetPreEraseBlk(kal_uint32 num)
+{
+    SDC_CMD_STATUS status;
+
+    //[22:0] number of blocks
+    num &= 0x003FFF;
+
+    // send APP_CMD
+    if ((status = SD_Cmd55(gSD->mRCA)) != NO_ERROR)
+        return status;
+
+    // send CMD23
+    if ((status = SD_SendCmd(SDC_CMD_ACMD23, num,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+        return status;
+
+    //read R1
+    if ((status = SD_CheckStatus()) != NO_ERROR)
+        return status;
+
+    return NO_ERROR;
+
+}
+
+/*************************************************************************
+* FUNCTION
+*	SD_EraseCmdClass
+*
+* DESCRIPTION
+*	groups of erase commands including CMD32 ~CMD38
+*
+* PARAMETERS
+*	cmd: indicate which command to execute
+*	address: starting address wiht write protection
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*	CMD34~CMD37 are only for MMC
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_EraseCmdClass(kal_uint32 cmd , kal_uint32 address)
+{
+   SDC_CMD_STATUS status;
+    kal_uint32 sdcard_status;
+    kal_set_eg_events(gMSDC_Handle->MSDC_Events, 0, KAL_AND);
+
+    if (cmd != SDC_CMD_CMD38)
+    {
+        if ((status = SD_SendCmd(cmd, address,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+            return status;
+    }
+    else if ((status = SD_SendCmd(cmd, SDC_NO_ARG,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+        return status;
+
+    //read R1
+    if ((status = SD_CheckStatus()) != NO_ERROR)
+        return status;
+
+
+    if (cmd == SDC_CMD_CMD38)
+    {
+
+        if ((status = SD_WaitCardNotBusy(MSDC_DATA_TIMEOUT)) != NO_ERROR)
+            return status;
+
+        do
+        {
+            if ((status = SD_GetStatus(gSD->mRCA, (kal_uint32*)&sdcard_status)) != NO_ERROR)
+                return status;
+
+            if (gMSDC_Handle->mIsPresent == KAL_FALSE)
+                return ERR_INVALID_CARD;
+        }
+        while (R1_CURRENT_STATE(sdcard_status) != TRAN_STA);
+    }
+
+    return NO_ERROR;
+}
+/*************************************************************************
+* FUNCTION
+*	SD_Switch_MMC40
+*
+* DESCRIPTION
+*	CMD6: set the command set or write to the EXT_CSD (for MMC4.0)
+*
+* PARAMETERS
+*	access: access mode
+*	index: index to EXT_CSD
+*  value: value to write to EXT_CSD
+*	set:	selected command set
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_Switch_MMC40(kal_uint8 access, kal_uint8 index, kal_uint8 value, kal_uint8 set)
+{
+    SDC_CMD_STATUS status = NO_ERROR;
+    kal_uint32 arg = 0;
+    kal_uint32 resp = 0;
+    kal_bool retry = KAL_FALSE;
+//    kal_uint8 *pData = NULL;
+
+switch_start:
+
+    arg = (access << 24) | (index << 16) | (value << 8) | set;
+
+    // send command
+    if ((status = SD_SendCmd(SDC_CMD_CMD6_MMC, arg,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+    {
+        goto ERR_Exit;
+    }
+
+#ifndef DRV_LSD
+
+    //read R1b
+    if ((status = SD_WaitCardNotBusy(MSDC_DATA_TIMEOUT)) != NO_ERROR)
+        goto ERR_Exit;
+
+#endif
+
+    SD_GetStatus(gSD->mRCA, (kal_uint32*)&status);
+
+    //read R1
+    if ((status = SD_CheckStatus()) != NO_ERROR)
+        goto ERR_Exit;
+
+    resp=MSDC_Reg32(SDC_RESP0);
+
+    if ((resp & MMC_SWITCH_ERROR) != 0)
+    {
+        if (retry == KAL_FALSE)
+        {
+#ifdef MSDC_TRACE_LEVEL2
+            MD_TRC_MSDC_INFORM_R0(resp, __LINE__);
+#endif
+            retry = KAL_TRUE;
+            goto switch_start;
+        }
+        else
+            return ERR_MMC_SWITCH_ERROR;
+    }
+
+    return NO_ERROR;
+
+ERR_Exit:
+    return status;
+}
+
+/*************************************************************************
+* FUNCTION
+*	SD_SendEXTCSD_MMC40
+*
+* DESCRIPTION
+*	CMD8: read the content of EXT_CSD register
+*
+* PARAMETERS
+*	kal: access mode
+*	index: index to EXT_CSD
+*  value: value to write to EXT_CSD
+*	set:	selected command set
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*
+*************************************************************************/
+#if 0
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#ifdef DRV_LSD
+/* under construction !*/
+#endif
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#else
+SDC_CMD_STATUS SD_SendEXTCSD_MMC40(kal_uint32* rxbuffer)
+{
+	SDC_CMD_STATUS status;
+	kal_uint32 blklen;
+	//    SDC_CMD_STATUS status1;
+	//    kal_bool retry = KAL_FALSE;
+	//kal_uint32 idx = 0;
+
+	//start:
+	blklen=gSD->mBKLength;
+    gSD->mBKLength = 512;
+    MSDC_WriteReg32(SDC_BLK_NUM,1);
+	 //set to pio mode and clear fifo
+	BitFieldWrite32((kal_uint32 *)MSDC_CFG, 1, MSDC_CFG_PIO);
+	gMSDC_Handle->dma_xfer=0;
+	MSDC_CLR_FIFO();
+
+	// read the block of 512 bytes (make sure the rxbuffer is 4 byte aligned)
+	if ((status = SD_SendCmd(SDC_CMD_CMD8_MMC40, SDC_NO_ARG,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+	    goto ERR_Exit;
+
+	//read R1
+	if ((status = SD_CheckStatus()) != NO_ERROR)
+	    goto ERR_Exit;
+
+	//idx = 0;
+	/*move data from FIFO to buffer*/
+	if ((status = SD_WaitDatRdyOrTo(rxbuffer,512,KAL_FALSE))!=NO_ERROR)
+	{
+		goto ERR_Exit; 
+	}
+
+    kal_mem_cpy(MSDC_eCSD, rxbuffer, 512);
+    gSD->mCSD.ext_csd = (T_EXT_CSD_MMC40 *)MSDC_eCSD;//rxbuffer;
+    gSD->mBKLength=blklen;
+    return NO_ERROR;
+
+ERR_Exit:
+    
+    MSDC_FatalErrorHandle();
+    return status;
+}
+#endif
+/*************************************************************************
+* FUNCTION
+*  SD_CheckTimeoutWithSleep
+*
+* DESCRIPTION
+*	check timeout or not and sleep 1 tick if has been waited more than 10 ms
+*
+* PARAMETERS
+*	start_time: the time start to wait, get with drv_get_current_time
+*     duration_ms: the timeout limitation
+*
+* RETURNS
+*	kal_bool, timeout:KAL_TRUE; not timeout:KAL_FALSE;
+*
+* GLOBALS AFFECTED
+*	gMSDC_Handle->is_timeout
+*
+* NOTE:
+*     This function should be called in the wait loop to prevent block other tasks.
+*
+*************************************************************************/
+kal_bool SD_CheckTimeoutWithSleep(kal_int32 start_time,
+                         kal_int32 duration_ms)
+{
+    kal_int32 elapsed_time = drv_get_duration_ms(start_time);    
+    //check timeout or not
+    if(elapsed_time > duration_ms)
+    {
+        gMSDC_Handle->is_timeout = KAL_TRUE;        
+        return KAL_TRUE;
+    }
+    gMSDC_Handle->is_timeout = KAL_FALSE;
+
+    if(elapsed_time < 10)
+    {
+        return KAL_FALSE;
+    }
+    else if ((KAL_FALSE == kal_query_systemInit())
+#ifdef  __TST_WRITE_TO_FILE__/*error recording: considering error recording additionally*/
+                && (KAL_FALSE == INT_QueryExceptionStatus())
+#endif
+                && (KAL_FALSE == kal_if_hisr())
+                && (KAL_FALSE == kal_if_lisr()))
+        {
+            kal_sleep_task(1);
+        }
+    return KAL_FALSE;
+
+}
+
+/*************************************************************************
+* FUNCTION
+*	SD_Switch_SD11
+*
+* DESCRIPTION
+*	CMD6: switch command to query and select the specific functions. (SD1.1 or later)
+* PARAMETERS
+*	arg: argument
+*	resp: buffer to contain the ther 64 bytes status information
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_Switch_SD11(kal_uint32 arg, T_SWITCH_STATUS* info)
+{
+	SDC_CMD_STATUS status = NO_ERROR;
+	kal_uint32 blklen;
+    gSD->mBKNum=1;
+    blklen=gSD->mBKLength;
+	gSD->mBKLength = SD_CMD6_RESP_LEN;
+	MSDC_WriteReg32(SDC_BLK_NUM,1);
+	//set to pio mode and clear fifo
+	BitFieldWrite32((kal_uint32 *)MSDC_CFG, 1, MSDC_CFG_PIO);
+	gMSDC_Handle->dma_xfer=0;
+	MSDC_CLR_FIFO();
+
+    if ((status = SD_SendCmd(SDC_CMD_CMD6_SD11, arg,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+        return status;
+
+    if ((status = SD_CheckStatus()) != NO_ERROR)
+        return status;
+	
+    status=SD_WaitDatRdyOrTo((kal_uint32 *)info,SD_CMD6_RESP_LEN,KAL_FALSE);
+    gSD->mBKLength=blklen;
+    return status;
+}
+
+/*************************************************************************
+* FUNCTION
+*	SD_Switch_SD11
+*
+* DESCRIPTION
+*	Enable the high speed interface to support up to 50M Hz clock
+*
+* PARAMETERS
+*	arg: argument
+*	resp: buffer to contain the ther 64 bytes status information
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*
+* NOTE
+*
+*************************************************************************/
+
+#ifndef DRV_MSDC_CORRECT_CMD6
+SDC_CMD_STATUS SD_SelectHighSpeed_SD11(void)
+{
+	SDC_CMD_STATUS status;
+    T_SWITCH_STATUS *p = (T_SWITCH_STATUS*)MSDC_Sector;
+	MSDC_DEBUG("[SD][%s %d]send cmd6 \r\n",__FUNCTION__,__LINE__);
+
+    if ((status = SD_Switch_SD11(SD_CMD6_QUERY_HIGH_SPEED, p)) != NO_ERROR)
+        return status;
+
+    if (p->max_current == 0)
+        return ERR_SD_HS_FAIL;
+
+    if ((p->group1_info & (1 << SD_FUNC_HIGH_SPEED)) &&
+        (p->group1_result == SD_FUNC_HIGH_SPEED))
+    {
+        if ((status = SD_Switch_SD11(SD_CMD6_SELECT_HIGH_SPEED, p)) != NO_ERROR)
+            return status;
+
+        if (p->max_current == 0)
+            return ERR_SD_HS_FAIL;
+
+        if (p->group1_result == SD_FUNC_HIGH_SPEED)
+            gSD->flags |= SD_FLAG_HS_SUPPORT;
+    }
+    else
+        return ERR_SD_HS_FAIL;
+
+
+    return NO_ERROR;
+}
+#else
+typedef struct
+{
+    kal_uint16 max_current;
+    kal_uint16 group1_info;
+    kal_uint16 group1_status;
+    kal_uint8  group1_result;
+    kal_uint8  structure_version;
+}T_Group1SwitchStatus;
+/*************************************************************************
+* FUNCTION
+*	SD_ParseGroup1FunctionStatus
+*
+* DESCRIPTION
+*	Parse the Group1 functons' information form the data returned by CMD6
+*
+* PARAMETERS
+*	arg: 
+*		T_Group1SwitchStatus* sf_status :  information of group1 function
+*		kal_uint8* crude_info			: crude data returned by CMD6
+*	resp:
+*
+* RETURNS
+*	void
+*
+* GLOBALS AFFECTED
+*	 None
+* NOTE
+*
+*************************************************************************/
+void SD_ParseGroup1FunctionStatus(T_Group1SwitchStatus* sf_status, kal_uint8* crude_info)
+{
+    sf_status->max_current = (((*(kal_uint8 *)crude_info) << 8)
+        | (*(kal_uint8 *)(crude_info + 1)));
+    sf_status->group1_info = (((*(kal_uint8 *)(crude_info + 12)) << 8)
+        | (*(kal_uint8 *)(crude_info + 13)));
+    sf_status->group1_result = ((*(kal_uint8 *)(crude_info + 16)) & 0xf);
+    sf_status->structure_version = (*(kal_uint8 *)(crude_info + 17));
+    sf_status->group1_status = (((*(kal_uint8 *)(crude_info + 28)) << 8)
+        | (*(kal_uint8 *)(crude_info + 29)));    
+}
+/*************************************************************************
+* FUNCTION
+*	SD_QuerySwithHighSpeed
+*
+* DESCRIPTION
+*	Send CMD6 with query or swith and check the response data.
+*
+* PARAMETERS
+*	arg: kal_uint32 arg
+*	resp:
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*	MSDC_Sector
+* NOTE
+*
+*************************************************************************/
+SDC_CMD_STATUS SD_QuerySwithHighSpeed(kal_uint32 arg)
+{
+	T_Group1SwitchStatus sf_status;
+	SDC_CMD_STATUS  	 cmd_status;
+	if ((cmd_status = SD_Switch_SD11(arg, (T_SWITCH_STATUS*)MSDC_Sector)) != NO_ERROR)
+       return cmd_status;
+    SD_ParseGroup1FunctionStatus(&sf_status,(kal_uint8*)MSDC_Sector);
+	if (0 == sf_status.max_current)
+    	return ERR_HIGH_SPEED_CONSUMPTION;
+	if ((SD_FUNC_HIGH_SPEED == sf_status.group1_result)\
+		&& (0==(sf_status.group1_status & (1 << SD_FUNC_HIGH_SPEED))))
+    	return NO_ERROR;//the high speed function can be switched
+	if ((0xF == sf_status.group1_result) || (!(sf_status.group1_info & (1 << SD_FUNC_HIGH_SPEED))))
+		return ERR_HIGH_SPEED_NOT_SUPPORT;//not support	
+	if (sf_status.group1_status & (1 << SD_FUNC_HIGH_SPEED))//busy      
+        return ERR_HIGH_SPEED_BUSY;
+    return ERR_HIGH_SPEED_COMMON_ERROR;
+}
+/*************************************************************************
+* FUNCTION
+*	SD_SelectHighSpeed_SD11
+*
+* DESCRIPTION
+*	Select high speed mode for the SD card that supports CMD6
+*
+* PARAMETERS
+*	arg: void
+*	resp:
+*
+* RETURNS
+*	SDC_CMD_STATUS
+*
+* GLOBALS AFFECTED
+*	gSD->flags
+* NOTE
+*
+*************************************************************************/
+
+SDC_CMD_STATUS SD_SelectHighSpeed_SD11(void)
+{
+    SDC_CMD_STATUS high_speed_status;
+	kal_int32      t1;
+	t1 = drv_get_current_time();
+	do 
+	{
+    	high_speed_status = SD_QuerySwithHighSpeed(SD_CMD6_QUERY_HIGH_SPEED);//query
+    	dbg_print("query high_speed_status: %x\r\n",high_speed_status);
+		if (NO_ERROR == high_speed_status)
+		{
+			high_speed_status = SD_QuerySwithHighSpeed(SD_CMD6_SELECT_HIGH_SPEED);//switch
+			dbg_print("switch high_speed_status: %x\r\n",high_speed_status);
+			if (NO_ERROR == high_speed_status)
+			{
+				gSD->flags |= SD_FLAG_HS_SUPPORT;
+				return NO_ERROR;
+			}
+			if (ERR_HIGH_SPEED_BUSY != high_speed_status)
+				break;			
+		}
+		if (ERR_HIGH_SPEED_BUSY != high_speed_status)
+            break;
+        if (drv_get_duration_ms(t1)>500)
+            return ERR_HIGH_SPEED_TIMEOUT;
+		//if(SD_CheckTimeoutWithSleep(t1,500))
+        //    return ERR_HIGH_SPEED_TIMEOUT;//timeout
+	}while(1);	
+	return high_speed_status;
+}
+
+#endif
+
+void parse_Cmd6FunctionStatus(T_SWITCH_STATUS *new_status,kal_uint8 * cur_Status)
+{
+    new_status->max_current=((*(kal_uint8*)cur_Status)<<8)\
+        | (*(kal_uint8 *)(cur_Status+1));
+    new_status->ver=(*(kal_uint8 *)(cur_Status+17));
+    new_status->group1_info=((*(kal_uint8 *)(cur_Status+12))<<8)\
+        | (*(kal_uint8 *)(cur_Status+13));
+    new_status->group1_result=(*(kal_uint8*)(cur_Status+16))&0xf;
+    new_status->group1_busy=((*(kal_uint8*)(cur_Status+28))<<8)\
+        | (*(kal_uint8 *)(cur_Status+29));
+    
+    new_status->group2_info=((*(kal_uint8 *)(cur_Status+10))<<8)\
+        | (*(kal_uint8 *)(cur_Status+11));
+    new_status->group2_result=((*(kal_uint8*)(cur_Status+16))>>4)&0xf;
+    new_status->group2_busy=((*(kal_uint8*)(cur_Status+26))<<8)\
+        | (*(kal_uint8 *)(cur_Status+27));
+
+    new_status->group3_info=((*(kal_uint8 *)(cur_Status+8))<<8)\
+        | (*(kal_uint8 *)(cur_Status+9));
+    new_status->group3_result=(*(kal_uint8*)(cur_Status+15))&0xf;
+    new_status->group3_busy=((*(kal_uint8*)(cur_Status+24))<<8)\
+        | (*(kal_uint8 *)(cur_Status+25));
+
+    new_status->group4_info=((*(kal_uint8 *)(cur_Status+6))<<8)\
+        | (*(kal_uint8 *)(cur_Status+7));
+    new_status->group4_result=((*(kal_uint8*)(cur_Status+15))>>4)&0xf;
+    new_status->group4_busy=((*(kal_uint8*)(cur_Status+22))<<8)\
+        | (*(kal_uint8 *)(cur_Status+23));
+
+     new_status->group5_info=((*(kal_uint8 *)(cur_Status+4))<<8)\
+        | (*(kal_uint8 *)(cur_Status+5));
+    new_status->group5_result=(*(kal_uint8*)(cur_Status+14))&0xf;
+    new_status->group5_busy=((*(kal_uint8*)(cur_Status+20))<<8)\
+        | (*(kal_uint8 *)(cur_Status+21));
+
+    new_status->group6_info=((*(kal_uint8 *)(cur_Status+2))<<8)\
+        | (*(kal_uint8 *)(cur_Status+3));
+    new_status->group6_result=((*(kal_uint8*)(cur_Status+14))>>4)&0xf;
+    new_status->group6_busy=((*(kal_uint8*)(cur_Status+18))<<8)\
+        | (*(kal_uint8 *)(cur_Status+19));
+    /*
+    dbg_print("new_status->group1_info :%x\r\n",new_status->group1_info);
+    dbg_print("new_status->group1_result:%x\r\n",new_status->group1_result);
+    dbg_print("new_status->group1_busy:%x\r\n",new_status->group1_busy);
+
+    dbg_print("new_status->group2_info :%x\r\n",new_status->group2_info);
+    dbg_print("new_status->group2_result:%x\r\n",new_status->group2_result);
+    dbg_print("new_status->group2_busy:%x\r\n",new_status->group2_busy);
+
+    dbg_print("new_status->group3_info :%x\r\n",new_status->group3_info);
+    dbg_print("new_status->group3_result:%x\r\n",new_status->group3_result);
+    dbg_print("new_status->group3_busy:%x\r\n",new_status->group3_busy);
+
+    dbg_print("new_status->group4_info :%x\r\n",new_status->group4_info);
+    dbg_print("new_status->group4_result:%x\r\n",new_status->group4_result);
+    dbg_print("new_status->group4_busy:%x\r\n",new_status->group4_busy);
+
+    dbg_print("new_status->group5_info :%x\r\n",new_status->group5_info);
+    dbg_print("new_status->group5_result:%x\r\n",new_status->group5_result);
+    dbg_print("new_status->group5_busy:%x\r\n",new_status->group5_busy);
+
+    dbg_print("new_status->group6_info :%x\r\n",new_status->group6_info);
+    dbg_print("new_status->group6_result:%x\r\n",new_status->group6_result);
+    dbg_print("new_status->group6_busy:%x\r\n",new_status->group6_busy);
+    dbg_print("new_status->max_current:%x\r\n",new_status->max_current);
+    dbg_print("new_status->ver:%x\r\n",new_status->ver);
+    */
+    
+}
+
+SDC_CMD_STATUS SD_CheckSwitch(void)
+{
+    //read the function support by current card
+    kal_uint32 status;
+    T_SWITCH_STATUS funcStatus;
+
+    char *uhs_mode[] = {"SDR12", "SDR25", "SDR50", "SDR104", "DDR50"};
+    char *speed_mode[] = {"DS", "HS"};
+    char *drv_strength[] = {"TYPE_A", "TYPE_B", "TYPE_C", "TYPE_D"};
+    char *cur_limit[] = {"200mA", "400mA", "600mA", "800mA"};
+    
+    if ((status = SD_Switch_SD11(SD_CMD6_QUERY_SUPPORT_FUNCTION, (T_SWITCH_STATUS*)MSDC_Sector)) != NO_ERROR)
+       return status;
+    parse_Cmd6FunctionStatus(&funcStatus,(kal_uint8*)MSDC_Sector);
+    gSD->card_support.function1=funcStatus.group1_info;
+    gSD->card_support.function2=funcStatus.group2_info;
+    gSD->card_support.function3=funcStatus.group3_info;
+    gSD->card_support.function4=funcStatus.group4_info;
+    #if defined(MSDC_CONFIG_SD30_SUPPORT)
+    if (gMSDC_Handle->mMSDC_type==SD30_CARD)
+    {
+        //for SD3.0
+        /*set bus speed mode*/
+        if(gSD->card_support.function1&gMSDC_Handle->host_support.function1&FUN1_SDR104)
+            gSD->function_set.function1=FUN1_SET_SDR104;
+        else if(gSD->card_support.function1&gMSDC_Handle->host_support.function1&FUN1_DDR50)
+            gSD->function_set.function1=FUN1_SET_DDR50;
+        else if(gSD->card_support.function1&gMSDC_Handle->host_support.function1&FUN1_SDR50)
+            gSD->function_set.function1=FUN1_SET_SDR50;
+        else if(gSD->card_support.function1&gMSDC_Handle->host_support.function1&FUN1_SDR25_HS)
+            gSD->function_set.function1=FUN1_SET_SDR25_HS;
+        else 
+            gSD->function_set.function1=FUN1_SET_SDR12_DS;
+        /*set command system*/
+        gSD->function_set.function2=FUN2_SET_DEFAULT;
+        /*set driver strength */
+        if (gSD->card_support.function3&gMSDC_Handle->host_support.function3&FUN3_TYPE_A)
+            gSD->function_set.function3=FUN3_SET_TYPE_A;
+        else if(gSD->card_support.function3&gMSDC_Handle->host_support.function3&FUN3_TYPE_B)
+            gSD->function_set.function3=FUN3_SET_TYPE_B;
+        else if(gSD->card_support.function3&gMSDC_Handle->host_support.function3&FUN3_TYPE_C)
+            gSD->function_set.function3=FUN3_SET_TYPE_C;
+        else if(gSD->card_support.function3&gMSDC_Handle->host_support.function3&FUN3_TYPE_D)
+            gSD->function_set.function3=FUN3_SET_TYPE_D;
+        else
+            gSD->function_set.function3=FUN3_SET_TYPE_A;
+        /*set current limit*/
+        if (gSD->function_set.function1==FUN1_SET_SDR104||gSD->function_set.function1==FUN1_SET_DDR50
+            ||gSD->function_set.function1==FUN1_SET_SDR50)
+        {
+            if(gSD->card_support.function4&gMSDC_Handle->host_support.function4&FUN4_800MA)
+                gSD->function_set.function4=FUN4_SET_800MA;
+            else if (gSD->card_support.function4&gMSDC_Handle->host_support.function4&FUN4_600MA)
+                gSD->function_set.function4=FUN4_SET_600MA;
+            else if (gSD->card_support.function4&gMSDC_Handle->host_support.function4&FUN4_400MA)
+                gSD->function_set.function4=FUN4_SET_400MA;
+            else
+                gSD->function_set.function4=FUN4_SET_200MA;
+        }
+        else
+        {
+            gSD->function_set.function4=FUN4_SET_200MA;
+        }
+
+        MSDC_CRIT("[SD][%s]Switch to %s speed mode! \r\n", __FUNCTION__,
+            uhs_mode[gSD->function_set.function1]);
+        MSDC_CRIT("[SD][%s]Switch to %s drive strength! \r\n", __FUNCTION__,
+            drv_strength[gSD->function_set.function3]);
+        MSDC_CRIT("[SD][%s]Switch to %s current limit! \r\n", __FUNCTION__,
+            cur_limit[gSD->function_set.function4]);
+    }
+    else
+   #endif
+    {
+        //for 2.0 HS DS card
+        if(gSD->card_support.function1&gMSDC_Handle->host_support.function1&FUN1_SDR25_HS)
+            gSD->function_set.function1=FUN1_SET_SDR25_HS;
+        else 
+            gSD->function_set.function1=FUN1_SET_SDR12_DS;
+
+        MSDC_CRIT("[SD][%s]Switch to %s speed mode! \r\n", __FUNCTION__,
+            speed_mode[gSD->function_set.function1]);
+    }
+    return NO_ERROR;
+    
+}
+
+SDC_CMD_STATUS SD_QuerySwith(kal_uint32 cmd6_arg)
+{
+    
+	SDC_CMD_STATUS  	 cmd_status;
+    T_SWITCH_STATUS  card_support;
+	if ((cmd_status = SD_Switch_SD11(cmd6_arg, (T_SWITCH_STATUS*)MSDC_Sector)) != NO_ERROR)
+       return cmd_status;
+    parse_Cmd6FunctionStatus(&card_support,(kal_uint8*)MSDC_Sector);
+    /*
+    dbg_print("card_support.group1_info :%x\r\n",card_support.group1_info);
+    dbg_print("card_support.group1_result:%x\r\n",card_support.group1_result);
+    dbg_print("card_support.group1_busy:%x\r\n",card_support.group1_busy);
+
+    dbg_print("card_support.group2_info :%x\r\n",card_support.group2_info);
+    dbg_print("card_support.group2_result:%x\r\n",card_support.group2_result);
+    dbg_print("card_support.group2_busy:%x\r\n",card_support.group2_busy);
+
+    dbg_print("card_support.group3_info :%x\r\n",card_support.group3_info);
+    dbg_print("card_support.group3_result:%x\r\n",card_support.group3_result);
+    dbg_print("card_support.group3_busy:%x\r\n",card_support.group3_busy);
+
+    dbg_print("card_support.group4_info :%x\r\n",card_support.group4_info);
+    dbg_print("card_support.group4_result:%x\r\n",card_support.group4_result);
+    dbg_print("card_support.group4_busy:%x\r\n",card_support.group4_busy);
+
+    dbg_print("card_support.group5_info :%x\r\n",card_support.group5_info);
+    dbg_print("card_support.group5_result:%x\r\n",card_support.group5_result);
+    dbg_print("card_support.group5_busy:%x\r\n",card_support.group5_busy);
+
+    dbg_print("card_support.group6_info :%x\r\n",card_support.group6_info);
+    dbg_print("card_support.group6_result:%x\r\n",card_support.group6_result);
+    dbg_print("card_support.group6_busy:%x\r\n",card_support.group6_busy);
+    dbg_print("card_support.max_current:%x\r\n",card_support.max_current);
+    dbg_print("card_support.ver:%x\r\n",card_support.ver);
+    */
+    if (0 == card_support.max_current)
+    	return ERR_HIGH_SPEED_CONSUMPTION;
+    #if defined(MSDC_CONFIG_SD30_SUPPORT)
+    if (gMSDC_Handle->mMSDC_type==SD30_CARD)
+    {
+        if ((gSD->function_set.function1==card_support.group1_result)\
+            &&(0==(card_support.group1_busy &(1<<(gSD->function_set.function1)))))
+        {
+
+            if ((gSD->function_set.function3==card_support.group3_result)\
+            &&(0==(card_support.group3_busy &(1<<(gSD->function_set.function3)))))
+            {
+
+                if ((gSD->function_set.function4==card_support.group4_result)\
+                &&(0==(card_support.group4_busy &(1<<(gSD->function_set.function4)))))
+                {
+
+                    return NO_ERROR;
+                }
+            }
+        }
+        dbg_print("gSD->function_set.function1=%x card_support.group1_result=%x\r\n",gSD->function_set.function1,card_support.group1_result);
+        dbg_print("gSD->function_set.function3=%x card_support.group3_result=%x\r\n",gSD->function_set.function3,card_support.group3_result);
+        dbg_print("gSD->function_set.function4=%x card_support.group4_result=%x\r\n",gSD->function_set.function4,card_support.group4_result);
+        dbg_print("busy1 %x busy3 %x busy4 %x\r\n",(card_support.group1_busy &(1<<(gSD->function_set.function1)))\
+            ,(card_support.group3_busy &(1<<(gSD->function_set.function3)))\
+            ,(card_support.group4_busy &(1<<(gSD->function_set.function4))));
+        if ((0xF == card_support.group1_result)\
+            || (!(card_support.group1_info & (1<<(gSD->function_set.function1)))))
+		    return ERR_SPEED_MODE_UNSUPPORT;//not support	
+		if ((0xF == card_support.group3_result)\
+            || (!(card_support.group3_info & (1<<(gSD->function_set.function3)))))
+		    return ERR_DRIVER_TYPE_UNSUPPORT;//not support	
+		if ((0xF == card_support.group4_result)\
+            || (!(card_support.group4_info & (1<<(gSD->function_set.function4)))))
+		    return ERR_CURRENT_LIMIT_UNSUPPORT;//not support	
+
+            
+	    if (card_support.group1_busy & (1 << (gSD->function_set.function1)))//busy      
+            return ERR_SWITCH_BUSY;
+        if (card_support.group3_busy & (1 << (gSD->function_set.function3)))//busy      
+            return ERR_SWITCH_BUSY;
+        if (card_support.group4_busy & (1 << (gSD->function_set.function4)))//busy      
+            return ERR_SWITCH_BUSY;
+    }
+    else
+    #endif
+    {
+        if ((gSD->function_set.function1==card_support.group1_result)\
+            &&(0==(card_support.group1_busy &(1<<(gSD->function_set.function1)))))
+            return NO_ERROR;
+        if ((0xF == card_support.group1_result)\
+            || (!(card_support.group1_info & (1<<(gSD->function_set.function1)))))
+		    return ERR_HIGH_SPEED_NOT_SUPPORT;//not support	
+	    if (card_support.group1_busy & (1 << (gSD->function_set.function1)))//busy      
+            return ERR_HIGH_SPEED_BUSY;
+    }
+    
+    return ERR_HIGH_SPEED_COMMON_ERROR;
+}
+
+SDC_CMD_STATUS SD_SwitchSpeedMode(void)
+{
+    kal_uint32 status,set_function;
+    kal_int32      t1;
+
+    if (gSD->mSCR.spec_ver<SCR_SEC_VER_1)
+    {
+        gSD->function_set.function1=0;
+        return NO_ERROR;
+    }
+    if (!(gSD->mCSD.ccc&CCC_SWITCH))
+    {
+        gSD->function_set.function1=0;
+        return NO_ERROR;
+    }
+        
+	t1 = drv_get_current_time();
+    if ((status =SD_CheckSwitch()) != NO_ERROR)
+        return status;
+    #if defined(MSDC_CONFIG_SD30_SUPPORT)
+    if (gMSDC_Handle->mMSDC_type==SD30_CARD)
+    {
+        set_function=0x00ff0000|gSD->function_set.function1|(gSD->function_set.function3<<8)|(gSD->function_set.function4<<12);
+    }
+    else
+    #endif
+    {
+        set_function=0x00fffff0|gSD->function_set.function1;
+    }
+	do 
+	{   
+    	status = SD_QuerySwith(SD_CMD6_QUERY_SWITCH|set_function);//query
+		if (NO_ERROR == status)
+		{
+			status = SD_QuerySwith(SD_CMD6_SELECT_SWITCH|set_function);//switch
+			if (NO_ERROR == status)
+			{
+			    if (gMSDC_Handle->mMSDC_type==SD30_CARD)
+                {         
+                    gSD->flags |= SD_FLAG_UHS_ENABLED;        
+                }
+                else if (gSD->function_set.function1==1)
+                {
+                    gSD->flags |= SD_FLAG_HS_ENABLED;
+                }
+				
+				return NO_ERROR;
+			}
+			if (ERR_SWITCH_BUSY != status)
+				break;			
+		}
+		if (ERR_SWITCH_BUSY != status)
+            break;
+        if (drv_get_duration_ms(t1)>500)
+            return ERR_SWITCH_TIMEOUT;
+	}while(1);	
+    return status;
+}
+SDC_CMD_STATUS SD_GoInactive(kal_uint16 rca)
+{
+     SDC_CMD_STATUS status;
+
+    if ((status = SD_SendCmd(SDC_CMD_CMD15, (kal_uint32)rca << 16,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+        return status;
+
+    return NO_ERROR;
+}
+
+SDC_CMD_STATUS SD_ReadStream_MMC(kal_uint32 address, kal_uint32* rxbuffer, kal_uint32 bytes)
+{
+    
+    return 0;	
+} 
+
+
+// write data stream from card only for MMC
+SDC_CMD_STATUS SD_WriteStream_MMC(kal_uint32 address, kal_uint32* txbuffer, kal_uint32 bytes)
+{
+     return 0;
+}
+
+//program CSD, transfer CSD through data line
+SDC_CMD_STATUS SD_ProgramCSD(kal_uint32 Csd[4])
+{
+    SDC_CMD_STATUS status;
+    kal_uint32 blklen;
+    //set block length to 16 , num to 1
+    
+    gSD->mBKNum=1;
+    blklen=gSD->mBKLength;
+	gSD->mBKLength = 16;
+	MSDC_WriteReg32(SDC_BLK_NUM,1);
+	//set to pio mode and clear fifo
+	BitFieldWrite32((kal_uint32 *)MSDC_CFG, 1, MSDC_CFG_PIO);
+	gMSDC_Handle->dma_xfer=0;
+	MSDC_CLR_FIFO();
+
+
+    if ((status = SD_SendCmd(SDC_CMD_CMD27, 0,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+        return status;
+
+    //read R1
+    if ((status = SD_CheckStatus()) != NO_ERROR)
+    {
+        //SD_WaitDatRdyOrTo();
+        return status;
+    }
+    //send CSD 128 bits
+    status=SD_WaitDatRdyOrTo(Csd,16,KAL_TRUE);
+    //set block length back to 512
+    BitFieldWrite32((kal_uint32*)SDC_CMD, 512, SDC_CMD_BLKLEN);
+    gSD->mBKLength=blklen;
+    return status;
+}
+
+
+//set write protect
+SDC_CMD_STATUS SD_SetWriteProtect(kal_uint32 address)
+{
+    SDC_CMD_STATUS status;
+
+    if ((status = SD_SendCmd(SDC_CMD_CMD28, address,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+        return status;
+
+    if ((status = SD_CheckStatus()) != NO_ERROR)
+        return status;
+
+    //wait until data line is ready
+    status =SD_WaitCardNotBusy(MSDC_DATA_TIMEOUT);
+    return status;
+}
+
+//clear write protect
+SDC_CMD_STATUS SD_ClrWriteProtect(kal_uint32 address)
+{
+     SDC_CMD_STATUS status;
+
+    if ((status = SD_SendCmd(SDC_CMD_CMD29, address,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+        return status;
+
+    if ((status = SD_CheckStatus()) != NO_ERROR)
+        return status;
+
+    status=SD_WaitCardNotBusy(MSDC_DATA_TIMEOUT);
+    return status;
+}
+
+// send write protect(single block read)
+SDC_CMD_STATUS SD_SendWriteProtect(kal_uint32 address, kal_uint32* WPBits32)
+{
+    SDC_CMD_STATUS status;
+    kal_uint32	tmp,blklen;
+
+    
+    BitFieldWrite32((kal_uint32*)SDC_CMD, 4, SDC_CMD_BLKLEN);
+    blklen=gSD->mBKLength;
+    gSD->mBKLength=4;
+    MSDC_WriteReg32(SDC_BLK_NUM,1);
+    MSDC_CLR_FIFO();
+
+    if ((status = SD_SendCmd(SDC_CMD_CMD30, address,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+        return status;
+
+    if ((status = SD_CheckStatus()) != NO_ERROR)
+        return status;
+
+    //read 32 write protection bits
+    tmp=MSDC_FIFO_READ32();
+    MSDC_InvertN((kal_uint8*)WPBits32, (kal_uint8*)&tmp, 4);
+    // configure the controller to the original block length
+    BitFieldWrite32((kal_uint32*)SDC_CMD, 512, SDC_CMD_BLKLEN);
+    gSD->mBKLength=blklen;
+
+    return NO_ERROR;
+}
+
+// CMD39: Fast IO-used to write and read 8 bit register
+SDC_CMD_STATUS SD_FastIO_MMC(kal_uint16 rca, kal_bool isWrite, kal_uint8 reg_adrs, kal_uint8 data)
+{
+     SDC_CMD_STATUS status;
+    kal_uint32 arg = 0;
+
+    arg = rca << 16;
+    arg |= isWrite << 15;
+    arg |= reg_adrs << 8;
+    arg |= data;
+
+    if ((status = SD_SendCmd(SDC_CMD_CMD39_MMC, arg,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+        return status;
+
+    if ((status = SD_CheckStatus()) != NO_ERROR)
+        return status;
+
+    return NO_ERROR;
+}
+
+
+// Sets the system into interrupt mode (MMC)
+SDC_CMD_STATUS SD_GoIRQ_MMC(void)
+{
+     SDC_CMD_STATUS status;
+
+    if ((status = SD_SendCmd(SDC_CMD_CMD40_MMC, SDC_NO_ARG,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+        return status;
+
+    status = *(kal_uint32*)SDC_RESP0;
+#ifdef MSDC_TRACE_LEVEL2
+    MD_TRC_MSDC_INFORM_R0(status, __LINE__);
+#endif
+
+    return NO_ERROR;
+}
+
+// Used to set/reset password ,lock/unlock the card and force erase total card.
+// similiar to a signle block write structure.(CMD42)
+// max password length = 16
+SDC_CMD_STATUS SD_LockUnlock(SD_LOCK_OP op, kal_char* Oldpwd, kal_char* Newpwd, kal_uint8 Oldlen, kal_uint8 Newlen)
+{
+     SDC_CMD_STATUS status;
+    kal_uint8 lockbk[SDC_MAX_LOCKBK];
+    kal_uint32 blklen, *ptr = (kal_uint32*)lockbk, count;
+
+    if (Oldlen > 16 || Newlen > 16)
+        return ERR_ERRORS;
+
+    /* save the original block length*/
+    blklen = gSD->mBKLength;
+
+    kal_mem_set(lockbk, 0, SDC_MAX_LOCKBK);
+
+    switch (op)
+    {
+        case SET_PWD:
+            lockbk[0] = 0x01;
+            break;
+
+        case CLR_PWD:
+            lockbk[0] = 0x02;
+            break;
+
+        case LOCK_CARD:
+            lockbk[0] = 0x04;
+            break;
+
+        case UNLOCK_CARD:
+            lockbk[0] = 0x00;
+            break;
+
+        case ERASE:
+            lockbk[0] = 0x08;
+            break;
+    }
+
+    lockbk[1] = Oldlen + Newlen;
+    kal_mem_cpy(&lockbk[2], Oldpwd, Oldlen);
+    kal_mem_cpy(&lockbk[2 + Oldlen], Newpwd, Newlen);
+
+    /* set block length */
+    if (op != ERASE)
+    {
+        SD_SetBlength(2 + lockbk[1]);
+        count = ((lockbk[1] + 2) % sizeof(kal_uint32)) ? ((lockbk[1] + 2) / sizeof(kal_uint32) + 1) :
+                ((lockbk[1] + 2) / sizeof(kal_uint32));
+        gSD->mBKNum=1;
+        blklen=gSD->mBKLength;
+    	gSD->mBKLength = 2 + lockbk[1];
+    	MSDC_WriteReg32(SDC_BLK_NUM,1);
+    	//set to pio mode and clear fifo
+    	BitFieldWrite32((kal_uint32 *)MSDC_CFG, 1, MSDC_CFG_PIO);
+    	gMSDC_Handle->dma_xfer=0;
+    	MSDC_CLR_FIFO();
+    }
+    else
+    {
+        SD_SetBlength(1);
+        gSD->mBKNum=1;
+        blklen=gSD->mBKLength;
+	    gSD->mBKLength = 1;
+	    MSDC_WriteReg32(SDC_BLK_NUM,1);
+	    //set to pio mode and clear fifo
+	    BitFieldWrite32((kal_uint32 *)MSDC_CFG, 1, MSDC_CFG_PIO);
+	    gMSDC_Handle->dma_xfer=0;
+	    MSDC_CLR_FIFO();
+        count = 1;
+    }
+    MSDC_WriteReg32(SDC_BLK_NUM,1);
+    /* send command */
+    if ((status = SD_SendCmd(SDC_CMD_CMD42, SDC_NO_ARG,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+        return status;
+
+    /* read R1b */
+    SD_CheckStatus();
+    /* clear FIFO */
+    MSDC_CLR_FIFO();
+   
+	
+#ifndef DRV_LSD
+	status=SD_WaitDatRdyOrTo(ptr,count,KAL_TRUE);
+    
+#endif
+		
+    /* wait util card has finished programming */
+    SD_WaitCardNotBusy(MSDC_DATA_TIMEOUT);
+    // restore the block length back
+     if (status != NO_ERROR)
+     {
+     	 return gMSDC_Handle->error;
+     }
+	 
+    // restore the block length back
+	 SD_SetBlength(blklen);
+    gSD->mBKLength=blklen;
+    /* check status*/
+    SD_GetStatus(gSD->mRCA, &status);
+	
+    if (status & R1_LOCK_UNLOCK_FAILED_24)
+        return ERR_LOCK_UNLOCK_FAILED;
+
+    if ((op == LOCK_CARD) && !(status & R1_CARD_IS_LOCKED_25))
+        return ERR_LOCK_UNLOCK_FAILED;
+
+    if ((op == UNLOCK_CARD) && (status & R1_CARD_IS_LOCKED_25))
+        return ERR_LOCK_UNLOCK_FAILED;
+
+    return NO_ERROR;
+}
+
+// ACMD13: read SD status(512bits = 64bytes single block read)
+SDC_CMD_STATUS SD_GetSDStatus(kal_uint32* sd_status)
+{
+     SDC_CMD_STATUS status;
+    kal_uint32 blklen;
+
+    
+    //if ((status = SD_SetBlength(64)) != NO_ERROR)
+    //    return status;
+
+    // send APP_CMD
+    if ((status = SD_Cmd55(gSD->mRCA)) != NO_ERROR)
+        return status;
+    // save the orignial block length
+    blklen=gSD->mBKLength;
+    gSD->mBKLength = 64;
+    MSDC_WriteReg32(SDC_BLK_NUM,1);
+    MSDC_DEBUG("[SD][%s %d]send acmd13\r\n",__FUNCTION__,__LINE__);
+    
+    //set to pio mode and clear fifo
+    BitFieldWrite32((kal_uint32 *)MSDC_CFG, 1, MSDC_CFG_PIO);
+    gMSDC_Handle->dma_xfer=0;
+    MSDC_CLR_FIFO();
+    // send ACMD13
+    if ((status = SD_SendCmd(SDC_CMD_ACMD13, SDC_NO_ARG,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+        return status;
+
+    //read R1
+    if ((status = SD_CheckStatus()) != NO_ERROR)
+        return status;
+    
+    // read sd status(64bytes = 4x16)
+    status=SD_WaitDatRdyOrTo(sd_status,64,KAL_FALSE);
+	if (status !=NO_ERROR) 
+	{
+		return status;
+    }
+    gSD->mBKLength=blklen;
+    return NO_ERROR;
+}
+//ACMD22: get the number of written write blocks(4bytes single block read)
+SDC_CMD_STATUS SD_GetNumWrittenBlk(kal_uint32* num)
+{
+     SDC_CMD_STATUS status;
+    kal_uint32 blklen, tmp;
+
+    // send APP_CMD
+    if ((status = SD_Cmd55(gSD->mRCA)) != NO_ERROR)
+        return status;
+    
+    blklen=gSD->mBKLength;
+    gSD->mBKLength = 4;
+    MSDC_WriteReg32(SDC_BLK_NUM,1);
+    MSDC_DEBUG("[SD][%s %d]send acmd13\r\n",__FUNCTION__,__LINE__);
+    
+    //set to pio mode and clear fifo
+    BitFieldWrite32((kal_uint32 *)MSDC_CFG, 1, MSDC_CFG_PIO);
+    gMSDC_Handle->dma_xfer=0;
+    MSDC_CLR_FIFO();
+    
+    // send CMD22
+    if ((status = SD_SendCmd(SDC_CMD_ACMD22, SDC_NO_ARG,MSDC_CMD_TIMEOUT)) != NO_ERROR)
+        return status;
+
+    //read R1
+    if ((status = SD_CheckStatus()) != NO_ERROR)
+        return status;
+
+    // read the number of written write blocks(4bytes)
+
+    if ((status=SD_WaitDatRdyOrTo(&tmp,4,KAL_FALSE))!=NO_ERROR)
+		return status;
+   
+    MSDC_InvertN((kal_uint8*)num, (kal_uint8*)&tmp, 4);
+
+    // resotre block length
+    gSD->mBKLength=blklen;
+    return NO_ERROR;
+}
+
+#ifdef DRV_MSDC_HW_CONTENTION
+extern kal_semid dclMsdcArb;
+#endif
+
+void SD_startFastFormat(void)
+{
+	#if defined(__AUDIO_DSP_LOWPOWER__)
+    AUDMA_LOCK(AUDMA_ID_MSDC);
+	#endif
+
+#ifdef DRV_MSDC_HW_CONTENTION
+    kal_uint32 retAddr;
+
+#if defined(__RVCT__)
+    /* RVCT doesn't support inline assemlber; bypass temporarily */
+    retAddr = 0;
+#else   /* __RVCT__ */
+    /* get the return address */
+    __asm
+    {
+        MOV retAddr, lr
+    }
+#endif  /* __RVCT__ */
+
+
+    if (NULL == dclMsdcArb)
+        ASSERT(0);
+
+    if (kal_query_systemInit() == KAL_FALSE)
+    {
+        /*must gain resource here before calling writeSectors*/
+        kal_take_sem(dclMsdcArb, 1);
+        SD_setArbRetAddr(retAddr);
+        SD_setArbThdId((kal_uint32)kal_get_current_thread_ID());
+    }
+
+#endif
+
+
+#ifdef DRV_LSD
+    LSD_startFastFormat();
+#elif defined(__DRV_MSDC_FAST_FORMAT__)
+    gMSDC_Handle->MSDC_fastFormat = KAL_TRUE;
+#endif
+}
+
+void SD_closeFastFormat(void)
+{
+	#ifdef DRV_LSD
+	LSD_closeFastFormat();
+	#elif defined(__DRV_MSDC_FAST_FORMAT__)
+	gMSDC_Handle->MSDC_fastFormat = KAL_FALSE;
+	#endif
+
+	#ifdef DRV_MSDC_HW_CONTENTION
+
+	if (kal_query_systemInit() == KAL_FALSE)
+	{
+	    /*when the semaphore is returned, we set thdId to zero, but not retAddr, we can know that it is released from here*/
+	    SD_setArbThdId(NULL);
+	    kal_give_sem(dclMsdcArb);
+	}
+
+	#endif
+
+	#if defined(__AUDIO_DSP_LOWPOWER__)
+	AUDMA_UNLOCK(AUDMA_ID_MSDC);
+	#endif
+
+}
+
+
+//__attribute__ ((section ("EXT_BOOTLOADER_CODE")))SDC_CMD_STATUS SD_FlushSectors(kal_uint32 startSector, kal_uint32 sectorNum)
+SDC_CMD_STATUS SD_FlushSectors(kal_uint32 startSector, kal_uint32 sectorNum)
+{
+     SDC_CMD_STATUS status;
+    kal_uint32 sectorMult,maxBlk;
+
+    if (gSD->flags & SD_FLAG_HCS_SUPPORT)
+        sectorMult = 1;
+    else
+        sectorMult = SECTOR_SIZE;
+    maxBlk=gSD->mCSD.capacity /512;
+    if(0 == sectorNum || sectorNum > maxBlk || startSector > maxBlk){
+		//ASSERT(0);
+		status = STATUS_INVALID_CTRL_DATA;
+		return status;
+	}
+
+	/*check that ending block should be smaller than maximum block number*/
+	if((startSector + sectorNum - 1) > maxBlk){
+		//ASSERT(0);
+		status = STATUS_INVALID_CTRL_DATA;
+		return status;
+	}
+    MSDC_PDNControl(KAL_FALSE);
+
+    // there are differences between SD and MMC
+    // tag erase start(CMD32)
+    if ((status = SD_EraseCmdClass(SDC_CMD_CMD32, sectorMult * startSector)) != NO_ERROR)
+    {
+        goto ErrorExit;
+    }
+
+    // tag erase end(CMD33)
+    if ((status = SD_EraseCmdClass(SDC_CMD_CMD33, sectorMult * (startSector + sectorNum - 1))) != NO_ERROR)
+    {
+        goto ErrorExit;
+    }
+
+    // erase...(CMD38)
+    if ((status = SD_EraseCmdClass(SDC_CMD_CMD38, 0)) != NO_ERROR)
+    {
+        goto ErrorExit;
+    }
+
+ErrorExit:
+    MSDC_PDNControl(KAL_TRUE);
+    return status;
+}
+
+#ifdef IC_MODULE_TEST
+
+kal_bool MSDC_ModuleTest_Report(void)
+{
+     
+	 SDC_CMD_STATUS status;
+	 
+	 if (gMSDC_Handle->mIsInitialized == KAL_FALSE)
+		 return KAL_FALSE;
+ 
+	 MSDC_PDNControl(KAL_FALSE);
+ 
+	 gMSDC_Handle->mIsInitialized = KAL_TRUE;
+	 gMSDC_Handle->trySingleLine = KAL_TRUE;
+ 
+	 status = SD_Initialize();
+ 
+	 if (status == NO_ERROR)
+		 return KAL_TRUE;
+	 else
+		 return KAL_FALSE;
+ 
+}
+#endif
+
+#else
+#ifdef DRV_LSD
+T_SDC_HANDLE	gSD_blk[SD_NUM];
+T_SDC_HANDLE	*gSD = gSD_blk;
+#endif
+#endif //  defined(__MSDC_SD_MMC__)
+
+#ifdef MSDC_DEBUG
+
+#define TST_ADRS	512*12
+kal_uint32 SD_MMC_Test(void)
+{
+
+	 return 0;
+
+}
+#endif	// FPGA_DEBUG
+
+#endif//!defined(__UBL__) || defined(__CARD_DOWNLOAD__) || defined(__EMMC_BOOTING__)
+
+#else //DRV_MSDC_OFF
+#include "kal_public_api.h" //MSBB change #include "kal_release.h"
+#include "kal_general_types.h"
+//#include "btif_sw.h"
+#include "kal_public_api.h"
+#include "kal_internal_api.h"
+#include "kal_public_defs.h"
+
+//#include "gpt_sw.h"
+#include "drv_comm.h"
+#include "reg_base.h"
+#include "msdc_def.h"
+#include "sd_def.h"
+#include "upll_ctrl.h"
+//#include	"Drv_trc.h"
+#ifdef DCL_MSDC_INTERFACE
+#include "dcl.h"
+void SD_dummyAPI(void) {}
+SDC_CMD_STATUS SD_SetBlength(kal_uint32 BKLength) {}
+SDDriver_t sd_driver_MTK1 =
+{
+    (DCL_SINGLE_BLK_RD)SD_dummyAPI,
+    (DCL_MUL_BLK_RD)SD_dummyAPI,
+    (DCL_SINGLE_BLK_WR)SD_dummyAPI,
+    (DCL_MUL_BLK_WR)SD_dummyAPI,
+    (DCL_SD_INITITALIZE)SD_dummyAPI,
+    (DCL_SET_PRE_ERASE_CNT)SD_dummyAPI,
+    (DCL_SD_SET_CALLBACK)SD_dummyAPI,
+    (DCL_SET_READ_TEST_FLAG)SD_dummyAPI,
+    (DCL_SD_READ_TEST)SD_dummyAPI,
+    (DCL_SD_SET_UPLL_CLOCK_TEST)SD_dummyAPI,
+    (DCL_SD_ERASE_BLK)SD_dummyAPI,
+    (DCL_GPD_MUL_BLK_RD)SD_dummyAPI,
+    (DCL_GPD_MUL_BLK_WR)SD_dummyAPI,
+};
+#endif //DCL_MSDC_INTERFACE
+
+void SD_startFastFormat(void) {}
+void SD_closeFastFormat(void) {}
+T_SDC_HANDLE	gSD_blk[SD_NUM];
+T_SDC_HANDLE	*gSD = gSD_blk;
+
+#if defined( __MSDC_BASIC_LOAD__) || defined( __MEUT__)
+kal_uint32 msdc_ReadTestFlag;
+#endif
+
+#endif //DRV_MSDC_OFF
+
+