/*
 * Copyright (C) 2013 Henrik Nordstrom <henrik@henriknordstrom.net>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <blk.h>
#include <dm.h>
#include <fdtdec.h>
#include <part.h>
#include <os.h>
#include <malloc.h>
#include <sandboxblockdev.h>
#include <asm/errno.h>
#include <dm/device-internal.h>

DECLARE_GLOBAL_DATA_PTR;

#ifndef CONFIG_BLK
static struct host_block_dev host_devices[CONFIG_HOST_MAX_DEVICES];

static struct host_block_dev *find_host_device(int dev)
{
	if (dev >= 0 && dev < CONFIG_HOST_MAX_DEVICES)
		return &host_devices[dev];

	return NULL;
}
#endif

#ifdef CONFIG_BLK
static unsigned long host_block_read(struct udevice *dev,
				     unsigned long start, lbaint_t blkcnt,
				     void *buffer)
{
	struct host_block_dev *host_dev = dev_get_priv(dev);
	struct blk_desc *block_dev = dev_get_uclass_platdata(dev);

#else
static unsigned long host_block_read(struct blk_desc *block_dev,
				     unsigned long start, lbaint_t blkcnt,
				     void *buffer)
{
	int dev = block_dev->devnum;
	struct host_block_dev *host_dev = find_host_device(dev);

	if (!host_dev)
		return -1;
#endif

	if (os_lseek(host_dev->fd, start * block_dev->blksz, OS_SEEK_SET) ==
			-1) {
		printf("ERROR: Invalid block %lx\n", start);
		return -1;
	}
	ssize_t len = os_read(host_dev->fd, buffer, blkcnt * block_dev->blksz);
	if (len >= 0)
		return len / block_dev->blksz;
	return -1;
}

#ifdef CONFIG_BLK
static unsigned long host_block_write(struct udevice *dev,
				      unsigned long start, lbaint_t blkcnt,
				      const void *buffer)
{
	struct host_block_dev *host_dev = dev_get_priv(dev);
	struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
#else
static unsigned long host_block_write(struct blk_desc *block_dev,
				      unsigned long start, lbaint_t blkcnt,
				      const void *buffer)
{
	int dev = block_dev->devnum;
	struct host_block_dev *host_dev = find_host_device(dev);
#endif

	if (os_lseek(host_dev->fd, start * block_dev->blksz, OS_SEEK_SET) ==
			-1) {
		printf("ERROR: Invalid block %lx\n", start);
		return -1;
	}
	ssize_t len = os_write(host_dev->fd, buffer, blkcnt * block_dev->blksz);
	if (len >= 0)
		return len / block_dev->blksz;
	return -1;
}

#ifdef CONFIG_BLK
int host_dev_bind(int devnum, char *filename)
{
	struct host_block_dev *host_dev;
	struct udevice *dev;
	char dev_name[20], *str, *fname;
	int ret, fd;

	/* Remove and unbind the old device, if any */
	ret = blk_get_device(IF_TYPE_HOST, devnum, &dev);
	if (ret == 0) {
		ret = device_remove(dev);
		if (ret)
			return ret;
		ret = device_unbind(dev);
		if (ret)
			return ret;
	} else if (ret != -ENODEV) {
		return ret;
	}

	if (!filename)
		return 0;

	snprintf(dev_name, sizeof(dev_name), "host%d", devnum);
	str = strdup(dev_name);
	if (!str)
		return -ENOMEM;
	fname = strdup(filename);
	if (!fname) {
		free(str);
		return -ENOMEM;
	}

	fd = os_open(filename, OS_O_RDWR);
	if (fd == -1) {
		printf("Failed to access host backing file '%s'\n", filename);
		ret = -ENOENT;
		goto err;
	}
	ret = blk_create_device(gd->dm_root, "sandbox_host_blk", str,
				IF_TYPE_HOST, devnum, 512,
				os_lseek(fd, 0, OS_SEEK_END), &dev);
	if (ret)
		goto err_file;
	ret = device_probe(dev);
	if (ret) {
		device_unbind(dev);
		goto err_file;
	}

	host_dev = dev_get_priv(dev);
	host_dev->fd = fd;
	host_dev->filename = fname;

	return blk_prepare_device(dev);
err_file:
	os_close(fd);
err:
	free(fname);
	free(str);
	return ret;
}
#else
int host_dev_bind(int dev, char *filename)
{
	struct host_block_dev *host_dev = find_host_device(dev);

	if (!host_dev)
		return -1;
	if (host_dev->blk_dev.priv) {
		os_close(host_dev->fd);
		host_dev->blk_dev.priv = NULL;
	}
	if (host_dev->filename)
		free(host_dev->filename);
	if (filename && *filename) {
		host_dev->filename = strdup(filename);
	} else {
		host_dev->filename = NULL;
		return 0;
	}

	host_dev->fd = os_open(host_dev->filename, OS_O_RDWR);
	if (host_dev->fd == -1) {
		printf("Failed to access host backing file '%s'\n",
		       host_dev->filename);
		return 1;
	}

	struct blk_desc *blk_dev = &host_dev->blk_dev;
	blk_dev->if_type = IF_TYPE_HOST;
	blk_dev->priv = host_dev;
	blk_dev->blksz = 512;
	blk_dev->lba = os_lseek(host_dev->fd, 0, OS_SEEK_END) / blk_dev->blksz;
	blk_dev->block_read = host_block_read;
	blk_dev->block_write = host_block_write;
	blk_dev->devnum = dev;
	blk_dev->part_type = PART_TYPE_UNKNOWN;
	part_init(blk_dev);

	return 0;
}
#endif

int host_get_dev_err(int devnum, struct blk_desc **blk_devp)
{
#ifdef CONFIG_BLK
	struct udevice *dev;
	int ret;

	ret = blk_get_device(IF_TYPE_HOST, devnum, &dev);
	if (ret)
		return ret;
	*blk_devp = dev_get_uclass_platdata(dev);
#else
	struct host_block_dev *host_dev = find_host_device(devnum);

	if (!host_dev)
		return -ENODEV;

	if (!host_dev->blk_dev.priv)
		return -ENOENT;

	*blk_devp = &host_dev->blk_dev;
#endif

	return 0;
}

#ifdef CONFIG_BLK
static const struct blk_ops sandbox_host_blk_ops = {
	.read	= host_block_read,
	.write	= host_block_write,
};

U_BOOT_DRIVER(sandbox_host_blk) = {
	.name		= "sandbox_host_blk",
	.id		= UCLASS_BLK,
	.ops		= &sandbox_host_blk_ops,
	.priv_auto_alloc_size	= sizeof(struct host_block_dev),
};
#else
U_BOOT_LEGACY_BLK(sandbox_host) = {
	.if_typename	= "host",
	.if_type	= IF_TYPE_HOST,
	.max_devs	= CONFIG_HOST_MAX_DEVICES,
	.get_dev	= host_get_dev_err,
};
#endif
