예제 #1
0
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 */
예제 #2
0
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 */