From 40fd050890e08eb6d064aaf074cf3a8b75d1251e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 29 Feb 2016 15:25:57 -0700 Subject: dm: sandbox: Add driver-model block-device support for sandbox Update the host driver to support driver model for block devices. A future commit will remove the old code, but for now it is useful to be able to use it both with and without CONFIG_BLK. Signed-off-by: Simon Glass Tested-by: Stephen Warren --- drivers/block/sandbox.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 117 insertions(+), 1 deletion(-) (limited to 'drivers/block/sandbox.c') diff --git a/drivers/block/sandbox.c b/drivers/block/sandbox.c index dde9d6845f..6d41508d5c 100644 --- a/drivers/block/sandbox.c +++ b/drivers/block/sandbox.c @@ -4,14 +4,20 @@ * SPDX-License-Identifier: GPL-2.0+ */ -#include #include +#include +#include +#include #include #include #include #include #include +#include +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) @@ -21,7 +27,17 @@ static struct host_block_dev *find_host_device(int 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) @@ -31,6 +47,7 @@ static unsigned long host_block_read(struct blk_desc *block_dev, if (!host_dev) return -1; +#endif if (os_lseek(host_dev->fd, start * block_dev->blksz, OS_SEEK_SET) == -1) { @@ -43,12 +60,21 @@ static unsigned long host_block_read(struct blk_desc *block_dev, 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) { @@ -61,6 +87,70 @@ static unsigned long host_block_write(struct blk_desc *block_dev, 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); @@ -100,9 +190,19 @@ int host_dev_bind(int dev, char *filename) 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) @@ -112,6 +212,8 @@ int host_get_dev_err(int devnum, struct blk_desc **blk_devp) return -ENOENT; *blk_devp = &host_dev->blk_dev; +#endif + return 0; } @@ -124,3 +226,17 @@ struct blk_desc *host_get_dev(int dev) return blk_dev; } + +#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), +}; +#endif -- cgit v1.2.1