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);
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
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;
}
}
Ejemplo n.º 4
0
static int simple_sd_ioctl_single_rw(struct msdc_ioctl *msdc_ctl)
{
	char l_buf[512];
	struct scatterlist msdc_sg;
	struct mmc_data msdc_data;
	struct mmc_command msdc_cmd;
	struct mmc_request msdc_mrq;
	struct msdc_host *host_ctl;
	int  ret = 0;
    if(!msdc_ctl)
        return -EINVAL;
    if(msdc_ctl->total_size <= 0)
        return -EINVAL;

	host_ctl = mtk_msdc_host[msdc_ctl->host_num];
	BUG_ON(!host_ctl);
	BUG_ON(!host_ctl->mmc);
	BUG_ON(!host_ctl->mmc->card);

#ifdef MTK_MSDC_USE_CACHE
	if (msdc_ctl->iswrite && mmc_card_mmc(host_ctl->mmc->card)
		&& (host_ctl->mmc->card->ext_csd.cache_ctrl & 0x1))
		return simple_sd_ioctl_multi_rw(msdc_ctl);
#endif

	mmc_claim_host(host_ctl->mmc);

#if DEBUG_MMC_IOCTL
	pr_debug("user want access %d partition\n", msdc_ctl->partition);
#endif

	ret = mmc_send_ext_csd(host_ctl->mmc->card, l_buf);
	if (ret) {
		pr_debug("mmc_send_ext_csd error, single rw\n");
		goto single_end;
	}
#ifdef CONFIG_MTK_EMMC_SUPPORT
	switch (msdc_ctl->partition) {
	case EMMC_PART_BOOT1:
		if (0x1 != (l_buf[179] & 0x7)) {
			/* change to access boot partition 1 */
			l_buf[179] &= ~0x7;
			l_buf[179] |= 0x1;
			mmc_switch(host_ctl->mmc->card, 0, 179, l_buf[179], 1000);
		}
		break;
	case EMMC_PART_BOOT2:
		if (0x2 != (l_buf[179] & 0x7)) {
			/* change to access boot partition 2 */
			l_buf[179] &= ~0x7;
			l_buf[179] |= 0x2;
			mmc_switch(host_ctl->mmc->card, 0, 179, l_buf[179], 1000);
		}
		break;
	default:
		/* make sure access partition is user data area */
		if (0 != (l_buf[179] & 0x7)) {
			/* set back to access user area */
			l_buf[179] &= ~0x7;
			l_buf[179] |= 0x0;
			mmc_switch(host_ctl->mmc->card, 0, 179, l_buf[179], 1000);
		}
		break;
	}
#endif
	if (msdc_ctl->total_size > 512) {
		msdc_ctl->result = -1;
		goto single_end;
	}
#if DEBUG_MMC_IOCTL
	pr_debug("start MSDC_SINGLE_READ_WRITE !!\n");
#endif
	memset(&msdc_data, 0, sizeof(struct mmc_data));
	memset(&msdc_mrq, 0, sizeof(struct mmc_request));
	memset(&msdc_cmd, 0, sizeof(struct mmc_command));

	msdc_mrq.cmd = &msdc_cmd;
	msdc_mrq.data = &msdc_data;

	if (msdc_ctl->trans_type)
		dma_force[host_ctl->id] = FORCE_IN_DMA;
	else
		dma_force[host_ctl->id] = FORCE_IN_PIO;

	if (msdc_ctl->iswrite) {
		msdc_data.flags = MMC_DATA_WRITE;
		msdc_cmd.opcode = MMC_WRITE_BLOCK;
		msdc_data.blocks = msdc_ctl->total_size / 512;
		if (MSDC_CARD_DUNM_FUNC != msdc_ctl->opcode) {
			if (copy_from_user(sg_msdc_multi_buffer, msdc_ctl->buffer, 512)) {
				dma_force[host_ctl->id] = FORCE_NOTHING;
				ret = -EFAULT;
				goto single_end;
			}
		} else {
			/* called from other kernel module */
			memcpy(sg_msdc_multi_buffer, msdc_ctl->buffer, 512);
		}
	} else {
		msdc_data.flags = MMC_DATA_READ;
		msdc_cmd.opcode = MMC_READ_SINGLE_BLOCK;
		msdc_data.blocks = msdc_ctl->total_size / 512;

		memset(sg_msdc_multi_buffer, 0, 512);
	}

	msdc_cmd.arg = msdc_ctl->address;

	if (!mmc_card_blockaddr(host_ctl->mmc->card)) {
		pr_debug("the device is used byte address!\n");
		msdc_cmd.arg <<= 9;
	}

	msdc_cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;

	msdc_data.stop = NULL;
	msdc_data.blksz = 512;
	msdc_data.sg = &msdc_sg;
	msdc_data.sg_len = 1;

#if DEBUG_MMC_IOCTL
	pr_debug("single block: ueser buf address is 0x%p!\n", msdc_ctl->buffer);
#endif
	sg_init_one(&msdc_sg, sg_msdc_multi_buffer, msdc_ctl->total_size);
	mmc_set_data_timeout(&msdc_data, host_ctl->mmc->card);

	mmc_wait_for_req(host_ctl->mmc, &msdc_mrq);

	if (!msdc_ctl->iswrite) {
		if (MSDC_CARD_DUNM_FUNC != msdc_ctl->opcode) {
			if (copy_to_user(msdc_ctl->buffer, sg_msdc_multi_buffer, 512)) {
				dma_force[host_ctl->id] = FORCE_NOTHING;
				ret = -EFAULT;
				goto single_end;
			}
		} else {
			/* called from other kernel module */
			memcpy(msdc_ctl->buffer, sg_msdc_multi_buffer, 512);
		}
	}

    /* clear the global buffer of R/W IOCTL */
    memset(sg_msdc_multi_buffer, 0 , 512);

	if (msdc_ctl->partition) {
		ret = mmc_send_ext_csd(host_ctl->mmc->card, l_buf);
		if (ret) {
			pr_debug("mmc_send_ext_csd error, single rw2\n");
			goto single_end;
		}

		if (l_buf[179] & 0x7) {
			/* set back to access user area */
			l_buf[179] &= ~0x7;
			l_buf[179] |= 0x0;
			mmc_switch(host_ctl->mmc->card, 0, 179, l_buf[179], 1000);
		}
	}

single_end:
	mmc_release_host(host_ctl->mmc);
	if (ret)
		msdc_ctl->result = ret;

	if (msdc_cmd.error)
		msdc_ctl->result = msdc_cmd.error;

	if (msdc_data.error)
		msdc_ctl->result = msdc_data.error;
	else
		msdc_ctl->result = 0;

	dma_force[host_ctl->id] = FORCE_NOTHING;
	return msdc_ctl->result;
}
Ejemplo n.º 5
0
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;
	}
}