int simple_sd_ioctl_rw(struct msdc_ioctl* msdc_ctl)
{
	if(msdc_ctl->total_size > 512)
		return simple_sd_ioctl_multi_rw(msdc_ctl);
	else
		return simple_sd_ioctl_single_rw(msdc_ctl);
}
int simple_sd_ioctl_rw(struct msdc_ioctl *msdc_ctl)
{
	if((msdc_ctl->total_size > 512) && (msdc_ctl->total_size <= MAX_REQ_SZ))
		return simple_sd_ioctl_multi_rw(msdc_ctl);
	else
		return simple_sd_ioctl_single_rw(msdc_ctl);
}
static long simple_sd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    struct msdc_ioctl *msdc_ctl = (struct msdc_ioctl *)arg;
	int ret;
	if(msdc_ctl == NULL){
		switch(cmd){
			//#ifdef MTK_SD_REINIT_SUPPORT
			case MSDC_REINIT_SDCARD:
				ret = sd_ioctl_reinit(msdc_ctl);
				break;
			//#endif
        	default:
            printk("mt_sd_ioctl:this opcode value is illegal!!\n");
            return -EINVAL;
			}
		return ret;		
	}
	else{	
    switch (msdc_ctl->opcode){
        case MSDC_SINGLE_READ_WRITE:
            msdc_ctl->result = simple_sd_ioctl_single_rw(msdc_ctl);
            break;
        case MSDC_MULTIPLE_READ_WRITE:
            msdc_ctl->result = simple_sd_ioctl_multi_rw(msdc_ctl);
            break;
        case MSDC_GET_CID:
            msdc_ctl->result = simple_sd_ioctl_get_cid(msdc_ctl);
            break;
        case MSDC_GET_CSD:
            msdc_ctl->result = simple_sd_ioctl_get_csd(msdc_ctl);
            break;
        case MSDC_GET_EXCSD:
            msdc_ctl->result = simple_sd_ioctl_get_excsd(msdc_ctl);
            break;
        case MSDC_DRIVING_SETTING:
            printk("in ioctl to change driving\n");
            if (1 == msdc_ctl->iswrite){
                msdc_ctl->result = simple_sd_ioctl_set_driving(msdc_ctl);
            } else {
                msdc_ctl->result = simple_sd_ioctl_get_driving(msdc_ctl);
            }
            break;
        case MSDC_ERASE_PARTITION:
            msdc_ctl->result = simple_mmc_erase_partition_wrap(msdc_ctl);
            break;
		case MSDC_SD30_MODE_SWITCH:
			msdc_ctl->result = simple_sd_ioctl_sd30_mode_switch(msdc_ctl);
			break;
        default:
            printk("simple_sd_ioctl:this opcode value is illegal!!\n");
            return -EINVAL;
    }

    return msdc_ctl->result;
}
}
int emmc_dump_read(unsigned char* buf, unsigned int len, unsigned int offset,unsigned int slot)
{
    /* maybe delete in furture */
    struct msdc_ioctl     msdc_ctl;
    unsigned int i;
    unsigned int l_user_begin_num = 0;
    unsigned int l_dest_num = 0;
    unsigned long long l_start_offset = 0;
    unsigned int ret = SD_FALSE;

    if ((0 != slot) || (0 != offset % 512) || (0 != len % 512)) {
        /* emmc always in slot0 */
        printk("debug: slot is not use for emmc!\n");
        return ret;
    }

    /* find the offset in emmc */
    for (i = 0; i < PART_NUM; i++) {
    //for (i = 0; i < 1; i++) {
        if ('m' == *(PartInfo[i].name) && 'b' == *(PartInfo[i].name + 1) &&
                'r' == *(PartInfo[i].name + 2)){
            l_user_begin_num = i;
        }

        if ('e' == *(PartInfo[i].name) && 'x' == *(PartInfo[i].name + 1) &&
                'p' == *(PartInfo[i].name + 2) && 'd' == *(PartInfo[i].name + 3) &&
                'b' == *(PartInfo[i].name + 4)){
            l_dest_num = i;
        }
    }

#if DEBUG_MMC_IOCTL
    printk("l_user_begin_num = %d l_dest_num = %d\n",l_user_begin_num,l_dest_num);
#endif

    if (l_user_begin_num >= PART_NUM && l_dest_num >= PART_NUM) {
        printk("not find in scatter file error!\n");
        return ret;
    }

    if (PartInfo[l_dest_num].size < (len + offset)) {
        printk("read operation oversize!\n");
        return ret;
    }

#if DEBUG_MMC_IOCTL
    printk("read start address=0x%llx\n", PartInfo[l_dest_num].start_address - PartInfo[l_user_begin_num].start_address);
#endif 
    l_start_offset = offset + PartInfo[l_dest_num].start_address - PartInfo[l_user_begin_num].start_address;

    msdc_ctl.partition = 0;
    msdc_ctl.iswrite = 0;
    msdc_ctl.host_num = slot;
    msdc_ctl.opcode = MSDC_CARD_DUNM_FUNC;
    msdc_ctl.total_size = 512;
    msdc_ctl.trans_type = 0;
    for (i = 0; i < (len/512); i++) {
        /* code */
        msdc_ctl.address = (l_start_offset >> 9) + i; //blk address
        msdc_ctl.buffer =(u32*)(buf + i * 512);

#if DEBUG_MMC_IOCTL
        printk("l_start_offset = 0x%x\n", msdc_ctl.address);
#endif        
        msdc_ctl.result = simple_sd_ioctl_single_rw(&msdc_ctl);
    }
    
#if DEBUG_MMC_IOCTL
    printk("read data:");
    for (i = 0; i < 32; i++) {
        printk("0x%x", buf[i]);
        if (0 == (i+1)%32)
            printk("\n");
    }
#endif
    return SD_TRUE;
}
static long simple_sd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    struct msdc_ioctl msdc_ctl;
    int ret;

    if((struct msdc_ioctl*)arg == NULL){
        switch(cmd){
            case MSDC_REINIT_SDCARD:
                ret = sd_ioctl_reinit((struct msdc_ioctl*)arg);
                break;

            case MSDC_CD_PIN_EN_SDCARD:
                ret = sd_ioctl_cd_pin_en((struct msdc_ioctl*)arg);
                break;

            default:
			pr_err("mt_sd_ioctl:this opcode value is illegal!!\n");
			return -EINVAL;
		}
		return ret;
    }
    else{
        if (copy_from_user(&msdc_ctl, (struct msdc_ioctl*)arg, sizeof(struct msdc_ioctl))){
            return -EFAULT;
        }

        switch (msdc_ctl.opcode){
            case MSDC_SINGLE_READ_WRITE:
                msdc_ctl.result = simple_sd_ioctl_single_rw(&msdc_ctl);
                break;
            case MSDC_MULTIPLE_READ_WRITE:
                msdc_ctl.result = simple_sd_ioctl_multi_rw(&msdc_ctl);
                break;
            case MSDC_GET_CID:
                msdc_ctl.result = simple_sd_ioctl_get_cid(&msdc_ctl);
                break;
            case MSDC_GET_CSD:
                msdc_ctl.result = simple_sd_ioctl_get_csd(&msdc_ctl);
                break;
            case MSDC_GET_EXCSD:
                msdc_ctl.result = simple_sd_ioctl_get_excsd(&msdc_ctl);
                break;
            case MSDC_DRIVING_SETTING:
			pr_debug("in ioctl to change driving\n");
                if (1 == msdc_ctl.iswrite){
                    msdc_ctl.result = simple_sd_ioctl_set_driving(&msdc_ctl);
                } else {
                    msdc_ctl.result = simple_sd_ioctl_get_driving(&msdc_ctl);
                }
                break;
            case MSDC_ERASE_PARTITION:
                msdc_ctl.result = simple_mmc_erase_partition_wrap(&msdc_ctl);
                break;
            case MSDC_SD30_MODE_SWITCH:
                msdc_ctl.result = simple_sd_ioctl_sd30_mode_switch(&msdc_ctl);
                break;
            default:
			pr_err("simple_sd_ioctl:this opcode value is illegal!!\n");
			return -EINVAL;
		}
        if (copy_to_user((struct msdc_ioctl*)arg, &msdc_ctl, sizeof(struct msdc_ioctl))) {
            return -EFAULT;
        }

        return msdc_ctl.result;
	}
}