/*
 * devfs.c - a device file system for barebox
 *
 * Copyright (c) 2011 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#include <common.h>
#include <driver.h>
#include <errno.h>
#include <malloc.h>
#include <ioctl.h>
#include <linux/err.h>
#include <linux/mtd/mtd.h>

LIST_HEAD(cdev_list);

struct cdev *cdev_by_name(const char *filename)
{
	struct cdev *cdev;

	list_for_each_entry(cdev, &cdev_list, list) {
		if (!strcmp(cdev->name, filename))
			return cdev;
	}
	return NULL;
}

struct cdev *cdev_open(const char *name, unsigned long flags)
{
	struct cdev *cdev = cdev_by_name(name);
	int ret;

	if (!cdev)
		return NULL;

	if (cdev->ops->open) {
		ret = cdev->ops->open(cdev, flags);
		if (ret)
			return NULL;
	}

	return cdev;
}

void cdev_close(struct cdev *cdev)
{
	if (cdev->ops->close)
		cdev->ops->close(cdev);
}

ssize_t cdev_read(struct cdev *cdev, void *buf, size_t count, ulong offset, ulong flags)
{
	if (!cdev->ops->read)
		return -ENOSYS;

	return cdev->ops->read(cdev, buf, count, cdev->offset +offset, flags);
}

ssize_t cdev_write(struct cdev *cdev, const void *buf, size_t count, ulong offset, ulong flags)
{
	if (!cdev->ops->write)
		return -ENOSYS;

	return cdev->ops->write(cdev, buf, count, cdev->offset + offset, flags);
}

int cdev_flush(struct cdev *cdev)
{
	if (!cdev->ops->flush)
		return 0;

	return cdev->ops->flush(cdev);
}

static int partition_ioctl(struct cdev *cdev, int request, void *buf)
{
	size_t offset;
	struct mtd_info_user *user = buf;

	switch (request) {
	case MEMSETBADBLOCK:
	case MEMGETBADBLOCK:
		offset = (off_t)buf;
		offset += cdev->offset;
		return cdev->ops->ioctl(cdev, request, (void *)offset);
	case MEMGETINFO:
		if (cdev->mtd) {
			user->type	= cdev->mtd->type;
			user->flags	= cdev->mtd->flags;
			user->size	= cdev->mtd->size;
			user->erasesize	= cdev->mtd->erasesize;
			user->oobsize	= cdev->mtd->oobsize;
			user->mtd	= cdev->mtd;
			/* The below fields are obsolete */
			user->ecctype	= -1;
			user->eccsize	= 0;
			return 0;
		}
		if (!cdev->ops->ioctl)
			return -EINVAL;
		return cdev->ops->ioctl(cdev, request, buf);
	default:
		return -EINVAL;
	}
}

int cdev_ioctl(struct cdev *cdev, int request, void *buf)
{
	if (cdev->flags & DEVFS_IS_PARTITION)
		return partition_ioctl(cdev, request, buf);

	if (!cdev->ops->ioctl)
		return -EINVAL;

	return cdev->ops->ioctl(cdev, request, buf);
}

int cdev_erase(struct cdev *cdev, size_t count, unsigned long offset)
{
	if (!cdev->ops->erase)
		return -ENOSYS;

	return cdev->ops->erase(cdev, count, cdev->offset + offset);
}

int devfs_create(struct cdev *new)
{
	struct cdev *cdev;

	cdev = cdev_by_name(new->name);
	if (cdev)
		return -EEXIST;

	list_add_tail(&new->list, &cdev_list);
	if (new->dev)
		list_add_tail(&new->devices_list, &new->dev->cdevs);

	return 0;
}

int devfs_remove(struct cdev *cdev)
{
	if (cdev->open)
		return -EBUSY;

	list_del(&cdev->list);
	if (cdev->dev)
		list_del(&cdev->devices_list);

	return 0;
}

int devfs_add_partition(const char *devname, unsigned long offset, size_t size,
		int flags, const char *name)
{
	struct cdev *cdev, *new;

	cdev = cdev_by_name(name);
	if (cdev)
		return -EEXIST;

	cdev = cdev_by_name(devname);
	if (!cdev)
		return -ENOENT;

	if (offset + size > cdev->size)
		return -EINVAL;

	new = xzalloc(sizeof (*new));
	new->name = strdup(name);
	new->ops = cdev->ops;
	new->priv = cdev->priv;
	new->size = size;
	new->offset = offset + cdev->offset;
	new->dev = cdev->dev;
	new->flags = flags | DEVFS_IS_PARTITION;

#ifdef CONFIG_PARTITION_NEED_MTD
	if (cdev->mtd) {
		new->mtd = mtd_add_partition(cdev->mtd, offset, size, flags, name);
		if (IS_ERR(new->mtd)) {
			int ret = PTR_ERR(new->mtd);
			free(new);
			return ret;
		}
	}
#endif

	devfs_create(new);

	return 0;
}

int devfs_del_partition(const char *name)
{
	struct cdev *cdev;
	int ret;

	cdev = cdev_by_name(name);
	if (!cdev)
		return -ENOENT;

	if (!(cdev->flags & DEVFS_IS_PARTITION))
		return -EINVAL;
	if (cdev->flags & DEVFS_PARTITION_FIXED)
		return -EPERM;

#ifdef CONFIG_PARTITION_NEED_MTD
	if (cdev->mtd)
		mtd_del_partition(cdev->mtd);
#endif

	ret = devfs_remove(cdev);
	if (ret)
		return ret;

	free(cdev->name);
	free(cdev);

	return 0;
}
