source: rtems/cpukit/libblock/src/blkdev.c @ 4f3cbd9

4.115
Last change on this file since 4f3cbd9 was 4f3cbd9, checked in by Sebastian Huber <sebastian.huber@…>, on 02/28/12 at 12:03:15

libblock: New IO control RTEMS_BLKIO_GETDISKDEV

  • Property mode set to 100644
File size: 6.8 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup rtems_blkdev
5 *
6 * Block device management.
7 */
8
9/*
10 * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
11 * Author: Victor V. Vengerov <vvv@oktet.ru>
12 *
13 * @(#) $Id$
14 */
15
16#if HAVE_CONFIG_H
17#include "config.h"
18#endif
19
20#include <errno.h>
21#include <string.h>
22
23#include <rtems.h>
24#include <rtems/libio.h>
25#include <sys/ioctl.h>
26
27#include "rtems/diskdevs.h"
28#include "rtems/bdbuf.h"
29
30/* rtems_blkdev_generic_read --
31 *     Generic block device read primitive. Implemented using block device
32 *     buffer management primitives.
33 */
34rtems_device_driver
35rtems_blkdev_generic_read(
36    rtems_device_major_number major __attribute__((unused)),
37    rtems_device_minor_number minor __attribute__((unused)),
38    void                    * arg)
39{
40    rtems_status_code rc = RTEMS_SUCCESSFUL;
41    rtems_libio_rw_args_t *args = arg;
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);
49    dev_t dev = dd->dev;
50
51    args->bytes_moved = 0;
52
53    while (count > 0)
54    {
55        rtems_bdbuf_buffer *diskbuf;
56        uint32_t            copy;
57
58        rc = rtems_bdbuf_read(dev, block, &diskbuf);
59        if (rc != RTEMS_SUCCESSFUL)
60            break;
61        copy = block_size - blkofs;
62        if (copy > count)
63            copy = count;
64        memcpy(buf, (char *)diskbuf->buffer + blkofs, copy);
65        rc = rtems_bdbuf_release(diskbuf);
66        args->bytes_moved += copy;
67        if (rc != RTEMS_SUCCESSFUL)
68            break;
69        count -= copy;
70        buf += copy;
71        blkofs = 0;
72        block++;
73    }
74
75    return rc;
76}
77
78/* rtems_blkdev_generic_write --
79 *     Generic block device write primitive. Implemented using block device
80 *     buffer management primitives.
81 */
82rtems_device_driver
83rtems_blkdev_generic_write(
84    rtems_device_major_number major __attribute__((unused)),
85    rtems_device_minor_number minor __attribute__((unused)),
86    void                    * arg)
87{
88    rtems_status_code rc = RTEMS_SUCCESSFUL;
89    rtems_libio_rw_args_t *args = arg;
90    rtems_libio_t *iop = args->iop;
91    rtems_disk_device *dd = iop->data1;
92    uint32_t block_size = dd->block_size;
93    char *buf = args->buffer;
94    uint32_t count = args->count;
95    rtems_blkdev_bnum block = (rtems_blkdev_bnum) (args->offset / block_size);
96    uint32_t blkofs = (uint32_t) (args->offset % block_size);
97    dev_t dev = dd->dev;
98
99    args->bytes_moved = 0;
100
101    while (count > 0)
102    {
103        rtems_bdbuf_buffer *diskbuf;
104        uint32_t            copy;
105
106        if ((blkofs == 0) && (count >= block_size))
107            rc = rtems_bdbuf_get(dev, block, &diskbuf);
108        else
109            rc = rtems_bdbuf_read(dev, block, &diskbuf);
110        if (rc != RTEMS_SUCCESSFUL)
111            break;
112
113        copy = block_size - blkofs;
114        if (copy > count)
115            copy = count;
116        memcpy((char *)diskbuf->buffer + blkofs, buf, copy);
117        args->bytes_moved += copy;
118
119        rc = rtems_bdbuf_release_modified(diskbuf);
120        if (rc != RTEMS_SUCCESSFUL)
121            break;
122
123        count -= copy;
124        buf += copy;
125        blkofs = 0;
126        block++;
127    }
128
129    return rc;
130}
131
132/* blkdev_generic_open --
133 *     Generic block device open primitive.
134 */
135rtems_device_driver
136rtems_blkdev_generic_open(
137    rtems_device_major_number major,
138    rtems_device_minor_number minor,
139    void                    * arg)
140{
141  rtems_libio_open_close_args_t *oc = arg;
142  rtems_libio_t *iop = oc->iop;
143  dev_t dev = rtems_filesystem_make_dev_t(major, minor);
144  rtems_disk_device *dd = rtems_disk_obtain(dev);
145
146  iop->data1 = dd;
147
148  if (dd != NULL)
149    return RTEMS_SUCCESSFUL;
150  else
151    return RTEMS_UNSATISFIED;
152}
153
154
155/* blkdev_generic_close --
156 *     Generic block device close primitive.
157 */
158rtems_device_driver
159rtems_blkdev_generic_close(
160    rtems_device_major_number major __attribute__((unused)),
161    rtems_device_minor_number minor __attribute__((unused)),
162    void                    * arg)
163{
164  rtems_libio_open_close_args_t *oc = arg;
165  rtems_libio_t *iop = oc->iop;
166  rtems_disk_device *dd = iop->data1;
167
168  rtems_disk_release(dd);
169
170  return RTEMS_SUCCESSFUL;
171}
172
173/* blkdev_generic_ioctl --
174 *     Generic block device ioctl primitive.
175 */
176rtems_device_driver
177rtems_blkdev_generic_ioctl(
178    rtems_device_major_number major __attribute__((unused)),
179    rtems_device_minor_number minor __attribute__((unused)),
180    void                    * arg)
181{
182    rtems_libio_ioctl_args_t *args = arg;
183    rtems_libio_t *iop = args->iop;
184    rtems_disk_device *dd = iop->data1;
185    int rc;
186
187    switch (args->command)
188    {
189        case RTEMS_BLKIO_GETMEDIABLKSIZE:
190            *((uint32_t *) args->buffer) = dd->media_block_size;
191            args->ioctl_return = 0;
192            break;
193
194        case RTEMS_BLKIO_GETBLKSIZE:
195            *((uint32_t *) args->buffer) = dd->block_size;
196            args->ioctl_return = 0;
197            break;
198
199        case RTEMS_BLKIO_SETBLKSIZE:
200            dd->block_size = *((uint32_t *) args->buffer);
201            args->ioctl_return = 0;
202            break;
203
204        case RTEMS_BLKIO_GETSIZE:
205            *((rtems_blkdev_bnum *) args->buffer) = dd->size;
206            args->ioctl_return = 0;
207            break;
208
209        case RTEMS_BLKIO_SYNCDEV:
210            rc = rtems_bdbuf_syncdev(dd->dev);
211            args->ioctl_return = (uint32_t) (rc == RTEMS_SUCCESSFUL ? 0 : -1);
212            break;
213
214        case RTEMS_BLKIO_GETDISKDEV:
215            *((rtems_disk_device **) args->buffer) = dd;
216            args->ioctl_return = 0;
217            break;
218
219        case RTEMS_BLKIO_REQUEST:
220            /*
221             * It is not allowed to directly access the driver circumventing
222             * the cache.
223             */
224            args->ioctl_return = (uint32_t) -1;
225            break;
226
227        default:
228            args->ioctl_return = (uint32_t) dd->ioctl(dd->phys_dev,
229                                                      args->command,
230                                                      args->buffer);
231            break;
232    }
233
234    return RTEMS_SUCCESSFUL;
235}
236
237int
238rtems_blkdev_ioctl(rtems_disk_device *dd, uint32_t req, void *argp)
239{
240    size_t            *arg_size = argp;
241    int                rc = 0;
242
243    switch (req)
244    {
245        case RTEMS_BLKIO_GETMEDIABLKSIZE:
246            *arg_size = dd->media_block_size;
247            break;
248
249        case RTEMS_BLKIO_GETBLKSIZE:
250            *arg_size = dd->block_size;
251            break;
252
253        case RTEMS_BLKIO_SETBLKSIZE:
254            dd->block_size = *arg_size;
255            break;
256
257        case RTEMS_BLKIO_GETSIZE:
258            *arg_size = dd->size;
259            break;
260
261        default:
262            errno = EINVAL;
263            rc = -1;
264            break;
265    }
266
267    return rc;
268}
Note: See TracBrowser for help on using the repository browser.