static int nve_open_ex(void) { int ret = 0; struct mtd_info *mtd; struct NVE_struct *nve; printk("nve_open_ex in\n"); //the driver is not initialized successfully, return error if (NULL == my_nve) { ret = -ENODEV; goto out; } else nve = my_nve; //print something to indicate more APP call me at the same time //just to debug if (nve->initialized > 0) { goto out; } //mtd = get_mtd_device_nm(NVE_NAME); mtd = get_mtd_device_nm("block2mtd: /dev/block/platform/omap/omap_hsmmc.1/by-name/nvme"); if (IS_ERR(mtd)) { ret = PTR_ERR(mtd); goto out; } if (MTD_ABSENT == mtd->type) { put_mtd_device(mtd); ret = -ENODEV; goto out; } nve->mtd = mtd; nve->nve_partition_count = NVE_PARTITION_COUNT; nve->nve_current_id = NVE_INVALID_NVM; printk("[NVE] nve_open_ex: nve->nve_partition_count = 0x%x.\n", nve->nve_partition_count); //the count must bigger than 3, one for updata, the other for runtime if (nve->nve_partition_count < 4){ ret = -ENODEV; goto out; } nve_findvalidNVM(nve); //check block0 ret = nve_get_NVM(nve, 0); if (!ret) { //block0 is valid, restore it to NVM ret = nve_restore(nve); } if (ret) { if (NVE_INVALID_NVM == nve->nve_current_id) { printk("[NVE] nve_open_ex: no valid NVM.\n"); ret = -ENODEV; goto out; } else { ret = 0; } } if (nve_do_index_table(nve)) { ret = -ENODEV; goto out; } nve->initialized = 1; out: printk("[NVE] nve_open_ex: out.\n"); return ret; } /* nve_open_ex */
static int nve_ioctl(struct file *file, u_int cmd, u_long arg) { int ret = 0; struct mtd_info *mtd = NULL; void __user *argp = (void __user *)arg; u_long size; struct nve_info_user info; struct NVE_struct *nve = NULL; struct NVE_index *nve_index = NULL; struct NV_header *nv = NULL; struct NVE_partition_header *nve_header = NULL; u_char *nv_data = NULL; if (NULL == my_nve) { return -EFAULT; } else nve = my_nve; mtd = nve->mtd; size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT; printk("[NVE]nve_ioctl, size = 0x%x\n", (uint32_t)size); if (cmd & IOC_IN) { if (!access_ok(VERIFY_READ, argp, size)) return -EFAULT; } if (cmd & IOC_OUT) { if (!access_ok(VERIFY_WRITE, argp, size)) return -EFAULT; } switch (cmd) { case NVEACCESSDATA: if (copy_from_user(&info, argp, sizeof(struct nve_info_user))) return -EFAULT; printk("[NVE][%s]current_id = %d,ioctl = %d.\n", __func__, nve->nve_current_id,info.nv_read); if(info.nv_read) { if (nve_do_index_table(nve)) { printk("[NVE]nve_ioctl,read nv from emmc error,nve_current_id = %d.\n",nve->nve_current_id); return -EFAULT; } } //find nv nve_header = (struct NVE_partition_header *)(nve->nve_ramdisk); if (info.nv_number >= nve_header->valid_items) { printk("[NVE]nve_ioctl, nv[%d] is not defined.\n", info.nv_number); return -EFAULT; } nve_index = nve->nve_index_table + info.nv_number; #if 0 if (strncmp(info.nv_name, nve_index->nv_name, NV_NAME_LENGTH)) { printk("[NVE]nve_ioctl, nv[%d]'s name is not correct.\n", info.nv_number); //find nv by name nve_index = nve->nve_index_table + nve_header->valid_items - 1; for (i = nve_header->valid_items; i > 0; i--) { if (strncmp(info.nv_name, nve_index->nv_name, NV_NAME_LENGTH)) { info.nv_number = i - 1; break; } nve_index--; } } #endif if (info.valid_size > NVE_NV_DATA_SIZE) info.valid_size = NVE_NV_DATA_SIZE; else if (info.valid_size == 0) info.valid_size = nve_index->nv_size; nv_data = nve->nve_ramdisk + nve_index->nv_offset + sizeof(struct NV_header); if (info.nv_read) { //read nv from ram memcpy(info.nv_data, nv_data, info.valid_size); //send back to user if (copy_to_user(argp, &info, sizeof(struct nve_info_user))) return -EFAULT; } else { //write nv to ram nv = (struct NV_header *)(nve->nve_ramdisk + nve_index->nv_offset); nv->valid_size = info.valid_size; nve_index->nv_size = info.valid_size; memset(nv_data, 0x0, NVE_NV_DATA_SIZE); memcpy(nv_data, info.nv_data, info.valid_size); //updata nve_ramdisk nve_header->nve_age++; //write NVE to nand nve_increment(nve); ret = nve_write(mtd, nve->nve_current_id * NVE_PARTITION_SIZE, NVE_PARTITION_SIZE, (u_char *)nve->nve_ramdisk); } break; default: ret = -ENOTTY; break; } return ret; } /* memory_ioctl */