linux/drivers/mtd/mtdchar.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright © 1999-2010 David Woodhouse <[email protected]>
 */

#include <linux/device.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/mutex.h>
#include <linux/backing-dev.h>
#include <linux/compat.h>
#include <linux/mount.h>
#include <linux/blkpg.h>
#include <linux/magic.h>
#include <linux/major.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/map.h>

#include <linux/uaccess.h>

#include "mtdcore.h"

/*
 * Data structure to hold the pointer to the mtd device as well
 * as mode information of various use cases.
 */
struct mtd_file_info {};

static loff_t mtdchar_lseek(struct file *file, loff_t offset, int orig)
{}

static int mtdchar_open(struct inode *inode, struct file *file)
{} /* mtdchar_open */

/*====================================================================*/

static int mtdchar_close(struct inode *inode, struct file *file)
{} /* mtdchar_close */

/* Back in June 2001, dwmw2 wrote:
 *
 *   FIXME: This _really_ needs to die. In 2.5, we should lock the
 *   userspace buffer down and use it directly with readv/writev.
 *
 * The implementation below, using mtd_kmalloc_up_to, mitigates
 * allocation failures when the system is under low-memory situations
 * or if memory is highly fragmented at the cost of reducing the
 * performance of the requested transfer due to a smaller buffer size.
 *
 * A more complex but more memory-efficient implementation based on
 * get_user_pages and iovecs to cover extents of those pages is a
 * longer-term goal, as intimated by dwmw2 above. However, for the
 * write case, this requires yet more complex head and tail transfer
 * handling when those head and tail offsets and sizes are such that
 * alignment requirements are not met in the NAND subdriver.
 */

static ssize_t mtdchar_read(struct file *file, char __user *buf, size_t count,
			loff_t *ppos)
{} /* mtdchar_read */

static ssize_t mtdchar_write(struct file *file, const char __user *buf, size_t count,
			loff_t *ppos)
{} /* mtdchar_write */

/*======================================================================

    IOCTL calls for getting device parameters.

======================================================================*/

static int otp_select_filemode(struct mtd_file_info *mfi, int mode)
{}

static int mtdchar_writeoob(struct file *file, struct mtd_info *mtd,
	uint64_t start, uint32_t length, void __user *ptr,
	uint32_t __user *retp)
{}

static int mtdchar_readoob(struct file *file, struct mtd_info *mtd,
	uint64_t start, uint32_t length, void __user *ptr,
	uint32_t __user *retp)
{}

/*
 * Copies (and truncates, if necessary) OOB layout information to the
 * deprecated layout struct, nand_ecclayout_user. This is necessary only to
 * support the deprecated API ioctl ECCGETLAYOUT while allowing all new
 * functionality to use mtd_ooblayout_ops flexibly (i.e. mtd_ooblayout_ops
 * can describe any kind of OOB layout with almost zero overhead from a
 * memory usage point of view).
 */
static int shrink_ecclayout(struct mtd_info *mtd,
			    struct nand_ecclayout_user *to)
{}

static int get_oobinfo(struct mtd_info *mtd, struct nand_oobinfo *to)
{}

static int mtdchar_blkpg_ioctl(struct mtd_info *mtd,
			       struct blkpg_ioctl_arg *arg)
{}

static void adjust_oob_length(struct mtd_info *mtd, uint64_t start,
			      struct mtd_oob_ops *ops)
{}

static noinline_for_stack int
mtdchar_write_ioctl(struct mtd_info *mtd, struct mtd_write_req __user *argp)
{}

static noinline_for_stack int
mtdchar_read_ioctl(struct mtd_info *mtd, struct mtd_read_req __user *argp)
{}

static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg)
{} /* memory_ioctl */

static long mtdchar_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
{}

#ifdef CONFIG_COMPAT

struct mtd_oob_buf32 {};

#define MEMWRITEOOB32
#define MEMREADOOB32

static long mtdchar_compat_ioctl(struct file *file, unsigned int cmd,
	unsigned long arg)
{}

#endif /* CONFIG_COMPAT */

/*
 * try to determine where a shared mapping can be made
 * - only supported for NOMMU at the moment (MMU can't doesn't copy private
 *   mappings)
 */
#ifndef CONFIG_MMU
static unsigned long mtdchar_get_unmapped_area(struct file *file,
					   unsigned long addr,
					   unsigned long len,
					   unsigned long pgoff,
					   unsigned long flags)
{
	struct mtd_file_info *mfi = file->private_data;
	struct mtd_info *mtd = mfi->mtd;
	unsigned long offset;
	int ret;

	if (addr != 0)
		return (unsigned long) -EINVAL;

	if (len > mtd->size || pgoff >= (mtd->size >> PAGE_SHIFT))
		return (unsigned long) -EINVAL;

	offset = pgoff << PAGE_SHIFT;
	if (offset > mtd->size - len)
		return (unsigned long) -EINVAL;

	ret = mtd_get_unmapped_area(mtd, len, offset, flags);
	return ret == -EOPNOTSUPP ? -ENODEV : ret;
}

static unsigned mtdchar_mmap_capabilities(struct file *file)
{
	struct mtd_file_info *mfi = file->private_data;

	return mtd_mmap_capabilities(mfi->mtd);
}
#endif

/*
 * set up a mapping for shared memory segments
 */
static int mtdchar_mmap(struct file *file, struct vm_area_struct *vma)
{}

static const struct file_operations mtd_fops =;

int __init init_mtdchar(void)
{}

void __exit cleanup_mtdchar(void)
{}

MODULE_ALIAS_CHARDEV_MAJOR();