subdev.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. /*
  2. * Copyright (c) 2009 Travis Geiselbrecht
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining
  5. * a copy of this software and associated documentation files
  6. * (the "Software"), to deal in the Software without restriction,
  7. * including without limitation the rights to use, copy, modify, merge,
  8. * publish, distribute, sublicense, and/or sell copies of the Software,
  9. * and to permit persons to whom the Software is furnished to do so,
  10. * subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be
  13. * included in all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  18. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  19. * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  20. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  21. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23. #include <debug.h>
  24. #include <stdlib.h>
  25. #include <lib/bio.h>
  26. #define LOCAL_TRACE 0
  27. typedef struct {
  28. // inheirit the usual bits
  29. bdev_t dev;
  30. // we're a subdevice of this
  31. bdev_t *parent;
  32. // we're this many blocks into it
  33. bnum_t offset;
  34. } subdev_t;
  35. static ssize_t subdev_read(struct bdev *_dev, void *buf, off_t offset, size_t len)
  36. {
  37. subdev_t *subdev = (subdev_t *)_dev;
  38. return bio_read(subdev->parent, buf, offset + subdev->offset * subdev->dev.block_size, len);
  39. }
  40. static ssize_t subdev_read_block(struct bdev *_dev, void *buf, bnum_t block, uint count)
  41. {
  42. subdev_t *subdev = (subdev_t *)_dev;
  43. return bio_read_block(subdev->parent, buf, block + subdev->offset, count);
  44. }
  45. static ssize_t subdev_write(struct bdev *_dev, const void *buf, off_t offset, size_t len)
  46. {
  47. subdev_t *subdev = (subdev_t *)_dev;
  48. return bio_write(subdev->parent, buf, offset + subdev->offset * subdev->dev.block_size, len);
  49. }
  50. static ssize_t subdev_write_block(struct bdev *_dev, const void *buf, bnum_t block, uint count)
  51. {
  52. subdev_t *subdev = (subdev_t *)_dev;
  53. return bio_write_block(subdev->parent, buf, block + subdev->offset, count);
  54. }
  55. static ssize_t subdev_erase(struct bdev *_dev, off_t offset, size_t len)
  56. {
  57. subdev_t *subdev = (subdev_t *)_dev;
  58. return bio_erase(subdev->parent, offset + subdev->offset * subdev->dev.block_size, len);
  59. }
  60. static void subdev_close(struct bdev *_dev)
  61. {
  62. subdev_t *subdev = (subdev_t *)_dev;
  63. bio_close(subdev->parent);
  64. subdev->parent = NULL;
  65. }
  66. status_t bio_publish_subdevice(const char *parent_dev, const char *subdev, bnum_t startblock, size_t len)
  67. {
  68. LTRACEF("parent %s, sub %s, startblock %u, len %zd\n", parent_dev, subdev, startblock, len);
  69. bdev_t *parent = bio_open(parent_dev);
  70. if (!parent)
  71. return -1;
  72. /* make sure we're able to do this */
  73. if (startblock + len > parent->block_count)
  74. return -1;
  75. subdev_t *sub = malloc(sizeof(subdev_t));
  76. bio_initialize_bdev(&sub->dev, subdev, parent->block_size, len);
  77. sub->parent = parent;
  78. sub->offset = startblock;
  79. sub->dev.read = &subdev_read;
  80. sub->dev.read_block = &subdev_read_block;
  81. sub->dev.write = &subdev_write;
  82. sub->dev.write_block = &subdev_write_block;
  83. sub->dev.erase = &subdev_erase;
  84. sub->dev.close = &subdev_close;
  85. bio_register_device(&sub->dev);
  86. return 0;
  87. }