[57aa979] | 1 | /** |
---|
| 2 | * @file |
---|
| 3 | * |
---|
[4670d91] | 4 | * @ingroup rtems_blkdev |
---|
[cfe8f7a] | 5 | * |
---|
| 6 | * @brief Block Device Management |
---|
[57aa979] | 7 | */ |
---|
[18daff9] | 8 | |
---|
[8b96149] | 9 | /* |
---|
[e51bd96] | 10 | * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia |
---|
| 11 | * Author: Victor V. Vengerov <vvv@oktet.ru> |
---|
| 12 | */ |
---|
| 13 | |
---|
[80cf60e] | 14 | #ifdef HAVE_CONFIG_H |
---|
[006fa1ef] | 15 | #include "config.h" |
---|
| 16 | #endif |
---|
| 17 | |
---|
[945884fe] | 18 | #include <errno.h> |
---|
[228587bb] | 19 | #include <string.h> |
---|
| 20 | |
---|
[e51bd96] | 21 | #include <rtems.h> |
---|
| 22 | #include <rtems/libio.h> |
---|
| 23 | #include <sys/ioctl.h> |
---|
| 24 | |
---|
| 25 | #include "rtems/diskdevs.h" |
---|
| 26 | #include "rtems/bdbuf.h" |
---|
| 27 | |
---|
[0b038bd4] | 28 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" |
---|
| 29 | |
---|
[e51bd96] | 30 | /* rtems_blkdev_generic_read -- |
---|
| 31 | * Generic block device read primitive. Implemented using block device |
---|
| 32 | * buffer management primitives. |
---|
| 33 | */ |
---|
| 34 | rtems_device_driver |
---|
| 35 | rtems_blkdev_generic_read( |
---|
[f97536d] | 36 | rtems_device_major_number major RTEMS_UNUSED, |
---|
| 37 | rtems_device_minor_number minor RTEMS_UNUSED, |
---|
[e51bd96] | 38 | void * arg) |
---|
| 39 | { |
---|
[b5b07cad] | 40 | rtems_status_code rc = RTEMS_SUCCESSFUL; |
---|
[e51bd96] | 41 | rtems_libio_rw_args_t *args = arg; |
---|
[bdac0eed] | 42 | rtems_libio_t *iop = args->iop; |
---|
| 43 | rtems_disk_device *dd = iop->data1; |
---|
| 44 | uint32_t block_size = dd->block_size; |
---|
| 45 | char *buf = args->buffer; |
---|
| 46 | uint32_t count = args->count; |
---|
| 47 | rtems_blkdev_bnum block = (rtems_blkdev_bnum) (args->offset / block_size); |
---|
| 48 | uint32_t blkofs = (uint32_t) (args->offset % block_size); |
---|
[048dcd2b] | 49 | |
---|
[bdac0eed] | 50 | args->bytes_moved = 0; |
---|
[048dcd2b] | 51 | |
---|
[e51bd96] | 52 | while (count > 0) |
---|
| 53 | { |
---|
[3899a537] | 54 | rtems_bdbuf_buffer *diskbuf; |
---|
[cec5c069] | 55 | uint32_t copy; |
---|
[048dcd2b] | 56 | |
---|
[796967c] | 57 | rc = rtems_bdbuf_read(dd, block, &diskbuf); |
---|
[e51bd96] | 58 | if (rc != RTEMS_SUCCESSFUL) |
---|
[b5b07cad] | 59 | break; |
---|
[e51bd96] | 60 | copy = block_size - blkofs; |
---|
| 61 | if (copy > count) |
---|
| 62 | copy = count; |
---|
| 63 | memcpy(buf, (char *)diskbuf->buffer + blkofs, copy); |
---|
| 64 | rc = rtems_bdbuf_release(diskbuf); |
---|
| 65 | args->bytes_moved += copy; |
---|
| 66 | if (rc != RTEMS_SUCCESSFUL) |
---|
[b5b07cad] | 67 | break; |
---|
[e51bd96] | 68 | count -= copy; |
---|
| 69 | buf += copy; |
---|
| 70 | blkofs = 0; |
---|
| 71 | block++; |
---|
| 72 | } |
---|
[b5b07cad] | 73 | |
---|
| 74 | return rc; |
---|
[e51bd96] | 75 | } |
---|
| 76 | |
---|
| 77 | /* rtems_blkdev_generic_write -- |
---|
| 78 | * Generic block device write primitive. Implemented using block device |
---|
[8b96149] | 79 | * buffer management primitives. |
---|
[e51bd96] | 80 | */ |
---|
| 81 | rtems_device_driver |
---|
| 82 | rtems_blkdev_generic_write( |
---|
[f97536d] | 83 | rtems_device_major_number major RTEMS_UNUSED, |
---|
| 84 | rtems_device_minor_number minor RTEMS_UNUSED, |
---|
[e51bd96] | 85 | void * arg) |
---|
| 86 | { |
---|
[b5b07cad] | 87 | rtems_status_code rc = RTEMS_SUCCESSFUL; |
---|
[e51bd96] | 88 | rtems_libio_rw_args_t *args = arg; |
---|
[bdac0eed] | 89 | rtems_libio_t *iop = args->iop; |
---|
| 90 | rtems_disk_device *dd = iop->data1; |
---|
| 91 | uint32_t block_size = dd->block_size; |
---|
| 92 | char *buf = args->buffer; |
---|
| 93 | uint32_t count = args->count; |
---|
| 94 | rtems_blkdev_bnum block = (rtems_blkdev_bnum) (args->offset / block_size); |
---|
| 95 | uint32_t blkofs = (uint32_t) (args->offset % block_size); |
---|
[048dcd2b] | 96 | |
---|
[bdac0eed] | 97 | args->bytes_moved = 0; |
---|
[048dcd2b] | 98 | |
---|
[e51bd96] | 99 | while (count > 0) |
---|
| 100 | { |
---|
[3899a537] | 101 | rtems_bdbuf_buffer *diskbuf; |
---|
[cec5c069] | 102 | uint32_t copy; |
---|
[048dcd2b] | 103 | |
---|
[635652e] | 104 | if ((blkofs == 0) && (count >= block_size)) |
---|
[796967c] | 105 | rc = rtems_bdbuf_get(dd, block, &diskbuf); |
---|
[e51bd96] | 106 | else |
---|
[796967c] | 107 | rc = rtems_bdbuf_read(dd, block, &diskbuf); |
---|
[e51bd96] | 108 | if (rc != RTEMS_SUCCESSFUL) |
---|
[b5b07cad] | 109 | break; |
---|
[048dcd2b] | 110 | |
---|
[e51bd96] | 111 | copy = block_size - blkofs; |
---|
| 112 | if (copy > count) |
---|
| 113 | copy = count; |
---|
| 114 | memcpy((char *)diskbuf->buffer + blkofs, buf, copy); |
---|
| 115 | args->bytes_moved += copy; |
---|
[048dcd2b] | 116 | |
---|
[e51bd96] | 117 | rc = rtems_bdbuf_release_modified(diskbuf); |
---|
| 118 | if (rc != RTEMS_SUCCESSFUL) |
---|
[b5b07cad] | 119 | break; |
---|
[048dcd2b] | 120 | |
---|
[e51bd96] | 121 | count -= copy; |
---|
| 122 | buf += copy; |
---|
| 123 | blkofs = 0; |
---|
| 124 | block++; |
---|
| 125 | } |
---|
[b5b07cad] | 126 | |
---|
| 127 | return rc; |
---|
[e51bd96] | 128 | } |
---|
| 129 | |
---|
| 130 | /* blkdev_generic_open -- |
---|
| 131 | * Generic block device open primitive. |
---|
| 132 | */ |
---|
| 133 | rtems_device_driver |
---|
| 134 | rtems_blkdev_generic_open( |
---|
| 135 | rtems_device_major_number major, |
---|
| 136 | rtems_device_minor_number minor, |
---|
[bdac0eed] | 137 | void * arg) |
---|
[e51bd96] | 138 | { |
---|
[bdac0eed] | 139 | rtems_libio_open_close_args_t *oc = arg; |
---|
| 140 | rtems_libio_t *iop = oc->iop; |
---|
| 141 | dev_t dev = rtems_filesystem_make_dev_t(major, minor); |
---|
| 142 | rtems_disk_device *dd = rtems_disk_obtain(dev); |
---|
[048dcd2b] | 143 | |
---|
[bdac0eed] | 144 | iop->data1 = dd; |
---|
[048dcd2b] | 145 | |
---|
[bdac0eed] | 146 | if (dd != NULL) |
---|
[e51bd96] | 147 | return RTEMS_SUCCESSFUL; |
---|
[bdac0eed] | 148 | else |
---|
| 149 | return RTEMS_UNSATISFIED; |
---|
[e51bd96] | 150 | } |
---|
| 151 | |
---|
| 152 | |
---|
| 153 | /* blkdev_generic_close -- |
---|
| 154 | * Generic block device close primitive. |
---|
| 155 | */ |
---|
| 156 | rtems_device_driver |
---|
| 157 | rtems_blkdev_generic_close( |
---|
[f97536d] | 158 | rtems_device_major_number major RTEMS_UNUSED, |
---|
| 159 | rtems_device_minor_number minor RTEMS_UNUSED, |
---|
[bdac0eed] | 160 | void * arg) |
---|
[e51bd96] | 161 | { |
---|
[bdac0eed] | 162 | rtems_libio_open_close_args_t *oc = arg; |
---|
| 163 | rtems_libio_t *iop = oc->iop; |
---|
| 164 | rtems_disk_device *dd = iop->data1; |
---|
[048dcd2b] | 165 | |
---|
[bdac0eed] | 166 | rtems_disk_release(dd); |
---|
[048dcd2b] | 167 | |
---|
[bdac0eed] | 168 | return RTEMS_SUCCESSFUL; |
---|
[e51bd96] | 169 | } |
---|
| 170 | |
---|
| 171 | /* blkdev_generic_ioctl -- |
---|
| 172 | * Generic block device ioctl primitive. |
---|
| 173 | */ |
---|
| 174 | rtems_device_driver |
---|
| 175 | rtems_blkdev_generic_ioctl( |
---|
[f97536d] | 176 | rtems_device_major_number major RTEMS_UNUSED, |
---|
| 177 | rtems_device_minor_number minor RTEMS_UNUSED, |
---|
[e51bd96] | 178 | void * arg) |
---|
| 179 | { |
---|
| 180 | rtems_libio_ioctl_args_t *args = arg; |
---|
[bdac0eed] | 181 | rtems_libio_t *iop = args->iop; |
---|
| 182 | rtems_disk_device *dd = iop->data1; |
---|
[048dcd2b] | 183 | |
---|
[291c9264] | 184 | if (args->command != RTEMS_BLKIO_REQUEST) |
---|
[e51bd96] | 185 | { |
---|
[5b045eb] | 186 | args->ioctl_return = dd->ioctl(dd, |
---|
[291c9264] | 187 | args->command, |
---|
| 188 | args->buffer); |
---|
[e51bd96] | 189 | } |
---|
[291c9264] | 190 | else |
---|
[945884fe] | 191 | { |
---|
[291c9264] | 192 | /* |
---|
| 193 | * It is not allowed to directly access the driver circumventing the |
---|
| 194 | * cache. |
---|
| 195 | */ |
---|
[5b045eb] | 196 | args->ioctl_return = -1; |
---|
[945884fe] | 197 | } |
---|
| 198 | |
---|
[291c9264] | 199 | return RTEMS_SUCCESSFUL; |
---|
[945884fe] | 200 | } |
---|