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; } }
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; }
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; } }