source: rtems/cpukit/libblock/src/blkdev.c @ b5b07cad

4.104.11
Last change on this file since b5b07cad was b5b07cad, checked in by Thomas Doerfler <Thomas.Doerfler@…>, on Oct 29, 2009 at 12:50:01 PM
  • - Reorderd AVL node fields to save space
  • Fixed printf() formats. New structure for waiters synchronization. Added BDBUF_INVALID_DEV define. New error handling in rtems_bdbuf_init().
  • Release disk in case of an error.
  • Property mode set to 100644
File size: 6.7 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,
37    rtems_device_minor_number minor,
38    void                    * arg)
39{
40    rtems_status_code rc = RTEMS_SUCCESSFUL;
41    rtems_libio_rw_args_t *args = arg;
42    uint32_t block_size;
43    char *buf;
44    uint32_t count;
45    rtems_blkdev_bnum block;
46    uint32_t blkofs;
47    dev_t dev;
48    rtems_disk_device *dd;
49
50    dev = rtems_filesystem_make_dev_t(major, minor);
51    dd = rtems_disk_obtain(dev);
52    if (dd == NULL)
53        return RTEMS_INVALID_NUMBER;
54
55    block_size = dd->block_size;
56
57    buf = args->buffer;
58    count = args->count;
59    args->bytes_moved = 0;
60
61    block = (rtems_blkdev_bnum) (args->offset / block_size);
62    blkofs = (uint32_t) (args->offset % block_size);
63
64    while (count > 0)
65    {
66        rtems_bdbuf_buffer *diskbuf;
67        uint32_t            copy;
68
69        rc = rtems_bdbuf_read(dev, block, &diskbuf);
70        if (rc != RTEMS_SUCCESSFUL)
71            break;
72        copy = block_size - blkofs;
73        if (copy > count)
74            copy = count;
75        memcpy(buf, (char *)diskbuf->buffer + blkofs, copy);
76        rc = rtems_bdbuf_release(diskbuf);
77        args->bytes_moved += copy;
78        if (rc != RTEMS_SUCCESSFUL)
79            break;
80        count -= copy;
81        buf += copy;
82        blkofs = 0;
83        block++;
84    }
85
86    rtems_disk_release(dd);
87
88    return rc;
89}
90
91/* rtems_blkdev_generic_write --
92 *     Generic block device write primitive. Implemented using block device
93 *     buffer management primitives.
94 */
95rtems_device_driver
96rtems_blkdev_generic_write(
97    rtems_device_major_number major,
98    rtems_device_minor_number minor,
99    void                    * arg)
100{
101    rtems_status_code rc = RTEMS_SUCCESSFUL;
102    rtems_libio_rw_args_t *args = arg;
103    uint32_t block_size;
104    char *buf;
105    uint32_t count;
106    rtems_blkdev_bnum block;
107    uint32_t blkofs;
108    dev_t dev;
109    rtems_disk_device *dd;
110
111    dev = rtems_filesystem_make_dev_t(major, minor);
112    dd = rtems_disk_obtain(dev);
113    if (dd == NULL)
114        return RTEMS_INVALID_NUMBER;
115
116    block_size = dd->block_size;
117
118    buf = args->buffer;
119    count = args->count;
120    args->bytes_moved = 0;
121
122    block = (rtems_blkdev_bnum) (args->offset / block_size);
123    blkofs = (uint32_t) (args->offset % block_size);
124
125    while (count > 0)
126    {
127        rtems_bdbuf_buffer *diskbuf;
128        uint32_t            copy;
129
130        if ((blkofs == 0) && (count >= block_size))
131            rc = rtems_bdbuf_get(dev, block, &diskbuf);
132        else
133            rc = rtems_bdbuf_read(dev, block, &diskbuf);
134        if (rc != RTEMS_SUCCESSFUL)
135            break;
136
137        copy = block_size - blkofs;
138        if (copy > count)
139            copy = count;
140        memcpy((char *)diskbuf->buffer + blkofs, buf, copy);
141        args->bytes_moved += copy;
142
143        rc = rtems_bdbuf_release_modified(diskbuf);
144        if (rc != RTEMS_SUCCESSFUL)
145            break;
146
147        count -= copy;
148        buf += copy;
149        blkofs = 0;
150        block++;
151    }
152
153    rtems_disk_release(dd);
154
155    return rc;
156}
157
158/* blkdev_generic_open --
159 *     Generic block device open primitive.
160 */
161rtems_device_driver
162rtems_blkdev_generic_open(
163    rtems_device_major_number major,
164    rtems_device_minor_number minor,
165    void                    * arg __attribute__((unused)))
166{
167    dev_t dev;
168    rtems_disk_device *dd;
169
170    dev = rtems_filesystem_make_dev_t(major, minor);
171    dd = rtems_disk_obtain(dev);
172    if (dd == NULL)
173        return RTEMS_INVALID_NUMBER;
174
175    dd->uses++;
176
177    rtems_disk_release(dd);
178
179    return RTEMS_SUCCESSFUL;
180}
181
182
183/* blkdev_generic_close --
184 *     Generic block device close primitive.
185 */
186rtems_device_driver
187rtems_blkdev_generic_close(
188    rtems_device_major_number major,
189    rtems_device_minor_number minor,
190    void                    * arg __attribute__((unused)))
191{
192    dev_t dev;
193    rtems_disk_device *dd;
194
195    dev = rtems_filesystem_make_dev_t(major, minor);
196    dd = rtems_disk_obtain(dev);
197    if (dd == NULL)
198        return RTEMS_INVALID_NUMBER;
199
200    dd->uses--;
201
202    rtems_disk_release(dd);
203
204    return RTEMS_SUCCESSFUL;
205}
206
207/* blkdev_generic_ioctl --
208 *     Generic block device ioctl primitive.
209 */
210rtems_device_driver
211rtems_blkdev_generic_ioctl(
212    rtems_device_major_number major,
213    rtems_device_minor_number minor,
214    void                    * arg)
215{
216    rtems_libio_ioctl_args_t *args = arg;
217    dev_t dev;
218    rtems_disk_device *dd;
219    int rc;
220
221    dev = rtems_filesystem_make_dev_t(major, minor);
222    dd = rtems_disk_obtain(dev);
223    if (dd == NULL)
224        return RTEMS_INVALID_NUMBER;
225
226    switch (args->command)
227    {
228        case RTEMS_BLKIO_GETMEDIABLKSIZE:
229            args->ioctl_return = dd->media_block_size;
230            break;
231
232        case RTEMS_BLKIO_GETBLKSIZE:
233            args->ioctl_return = dd->block_size;
234            break;
235
236        case RTEMS_BLKIO_SETBLKSIZE:
237            dd->block_size = *((size_t*) args->buffer);
238            break;
239
240        case RTEMS_BLKIO_GETSIZE:
241            args->ioctl_return = dd->size;
242            break;
243
244        case RTEMS_BLKIO_SYNCDEV:
245            rc = rtems_bdbuf_syncdev(dd->dev);
246            args->ioctl_return = (uint32_t) (rc == RTEMS_SUCCESSFUL ? 0 : -1);
247            break;
248
249        case RTEMS_BLKIO_REQUEST:
250        {
251            rtems_blkdev_request *req = args->buffer;
252            args->ioctl_return = (uint32_t) dd->ioctl(dd, args->command, req);
253            break;
254        }
255
256        default:
257            args->ioctl_return = (uint32_t) dd->ioctl(dd, args->command,
258                                                      args->buffer);
259            break;
260    }
261    rtems_disk_release(dd);
262
263    return RTEMS_SUCCESSFUL;
264}
265
266int
267rtems_blkdev_ioctl(rtems_disk_device *dd, uint32_t req, void *argp)
268{
269    size_t            *arg_size = argp;
270    int                rc = 0;
271   
272    switch (req)
273    {
274        case RTEMS_BLKIO_GETMEDIABLKSIZE:
275            *arg_size = dd->media_block_size;
276            break;
277
278        case RTEMS_BLKIO_GETBLKSIZE:
279            *arg_size = dd->block_size;
280            break;
281
282        case RTEMS_BLKIO_SETBLKSIZE:
283            dd->block_size = *arg_size;
284            break;
285
286        case RTEMS_BLKIO_GETSIZE:
287            *arg_size = dd->size;
288            break;
289
290        default:
291            errno = EINVAL;
292            rc = -1;
293            break;
294    }
295
296    return rc;
297}
Note: See TracBrowser for help on using the repository browser.