From e51bd967cda1989d606b5b6178ed6d2c8d151707 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Thu, 28 Feb 2002 20:39:54 +0000 Subject: 2002-02-28 Joel Sherrill * Submitted by Victor V. Vengerov and merged into the RTEMS source. * ChangeLog, Makefile.am, README, configure.ac, include/Makefile.am, include/rtems/bdbuf.h, include/rtems/blkdev.h, include/rtems/diskdevs.h, include/rtems/ramdisk.h, include/rtems/.cvsignore, include/.cvsignore, src/Makefile.am, src/bdbuf.c, src/blkdev.c, src/diskdevs.c, src/ramdisk.c, src/.cvsignore, .cvsignore: New files. --- c/src/exec/libblock/src/blkdev.c | 243 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 243 insertions(+) create mode 100644 c/src/exec/libblock/src/blkdev.c (limited to 'c/src/exec/libblock/src/blkdev.c') diff --git a/c/src/exec/libblock/src/blkdev.c b/c/src/exec/libblock/src/blkdev.c new file mode 100644 index 0000000000..1004ec4de3 --- /dev/null +++ b/c/src/exec/libblock/src/blkdev.c @@ -0,0 +1,243 @@ +/* + * blkdev.h - block device driver generic support + * + * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia + * Author: Victor V. Vengerov + * + * @(#) $Id$ + */ + +#include +#include +#include + +#include "rtems/diskdevs.h" +#include "rtems/bdbuf.h" + +/* rtems_blkdev_generic_read -- + * Generic block device read primitive. Implemented using block device + * buffer management primitives. + */ +rtems_device_driver +rtems_blkdev_generic_read( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg) +{ + rtems_libio_rw_args_t *args = arg; + int block_size_log2; + int block_size; + char *buf; + unsigned int count; + unsigned int block; + unsigned int blkofs; + dev_t dev; + disk_device *dd; + + dev = rtems_filesystem_make_dev_t(major, minor); + dd = rtems_disk_lookup(dev); + if (dd == NULL) + return RTEMS_INVALID_NUMBER; + + block_size_log2 = dd->block_size_log2; + block_size = dd->block_size; + + buf = args->buffer; + count = args->count; + args->bytes_moved = 0; + + block = args->offset >> block_size_log2; + blkofs = args->offset & (block_size - 1); + + while (count > 0) + { + bdbuf_buffer *diskbuf; + int copy; + rtems_status_code rc; + + rc = rtems_bdbuf_read(dev, block, &diskbuf); + if (rc != RTEMS_SUCCESSFUL) + return rc; + copy = block_size - blkofs; + if (copy > count) + copy = count; + memcpy(buf, (char *)diskbuf->buffer + blkofs, copy); + rc = rtems_bdbuf_release(diskbuf); + args->bytes_moved += copy; + if (rc != RTEMS_SUCCESSFUL) + return rc; + count -= copy; + buf += copy; + blkofs = 0; + block++; + } + return RTEMS_SUCCESSFUL; +} + +/* rtems_blkdev_generic_write -- + * Generic block device write primitive. Implemented using block device + * buffer management primitives. + */ +rtems_device_driver +rtems_blkdev_generic_write( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg) +{ + rtems_libio_rw_args_t *args = arg; + int block_size_log2; + int block_size; + char *buf; + unsigned int count; + unsigned int block; + unsigned int blkofs; + dev_t dev; + rtems_status_code rc; + disk_device *dd; + + dev = rtems_filesystem_make_dev_t(major, minor); + dd = rtems_disk_lookup(dev); + if (dd == NULL) + return RTEMS_INVALID_NUMBER; + + block_size_log2 = dd->block_size_log2; + block_size = dd->block_size; + + buf = args->buffer; + count = args->count; + args->bytes_moved = 0; + + block = args->offset >> block_size_log2; + blkofs = args->offset & (block_size - 1); + + while (count > 0) + { + bdbuf_buffer *diskbuf; + int copy; + + if ((blkofs == 0) && (count > block_size)) + rc = rtems_bdbuf_get(dev, block, &diskbuf); + else + rc = rtems_bdbuf_read(dev, block, &diskbuf); + if (rc != RTEMS_SUCCESSFUL) + return rc; + + copy = block_size - blkofs; + if (copy > count) + copy = count; + memcpy((char *)diskbuf->buffer + blkofs, buf, copy); + args->bytes_moved += copy; + + rc = rtems_bdbuf_release_modified(diskbuf); + if (rc != RTEMS_SUCCESSFUL) + return rc; + + count -= copy; + buf += copy; + blkofs = 0; + block++; + } + return RTEMS_SUCCESSFUL; +} + +/* blkdev_generic_open -- + * Generic block device open primitive. + */ +rtems_device_driver +rtems_blkdev_generic_open( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg) +{ + dev_t dev; + disk_device *dd; + + dev = rtems_filesystem_make_dev_t(major, minor); + dd = rtems_disk_lookup(dev); + if (dd == NULL) + return RTEMS_INVALID_NUMBER; + + dd->uses++; + + rtems_disk_release(dd); + + return RTEMS_SUCCESSFUL; +} + + +/* blkdev_generic_close -- + * Generic block device close primitive. + */ +rtems_device_driver +rtems_blkdev_generic_close( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg) +{ + dev_t dev; + disk_device *dd; + + dev = rtems_filesystem_make_dev_t(major, minor); + dd = rtems_disk_lookup(dev); + if (dd == NULL) + return RTEMS_INVALID_NUMBER; + + dd->uses--; + + rtems_disk_release(dd); + + return RTEMS_SUCCESSFUL; +} + +/* blkdev_generic_ioctl -- + * Generic block device ioctl primitive. + */ +rtems_device_driver +rtems_blkdev_generic_ioctl( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg) +{ + rtems_libio_ioctl_args_t *args = arg; + dev_t dev; + disk_device *dd; + int rc; + + dev = rtems_filesystem_make_dev_t(major, minor); + dd = rtems_disk_lookup(dev); + if (dd == NULL) + return RTEMS_INVALID_NUMBER; + + switch (args->command) + { + case BLKIO_GETBLKSIZE: + args->ioctl_return = dd->block_size; + break; + + case BLKIO_GETSIZE: + args->ioctl_return = dd->size; + break; + + case BLKIO_SYNCDEV: + rc = rtems_bdbuf_syncdev(dd->dev); + args->ioctl_return = (rc == RTEMS_SUCCESSFUL ? 0 : -1); + break; + + case BLKIO_REQUEST: + { + blkdev_request *req = args->buffer; + req->start += dd->start; + args->ioctl_return = dd->ioctl(dd->phys_dev->dev, args->command, + req); + break; + } + + default: + args->ioctl_return = dd->ioctl(dd->phys_dev->dev, args->command, + args->buffer); + break; + } + rtems_disk_release(dd); + + return RTEMS_SUCCESSFUL; +} -- cgit v1.2.3