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

4.104.115
Last change on this file since b5b07cad was b5b07cad, checked in by Thomas Doerfler <Thomas.Doerfler@…>, on 10/29/09 at 12:50:01
  • - 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
RevLine 
[57aa979]1/**
2 * @file
3 *
[4670d91]4 * @ingroup rtems_blkdev
5 *
[57aa979]6 * Block device management.
7 */
8 
[8b96149]9/*
[e51bd96]10 * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
11 * Author: Victor V. Vengerov <vvv@oktet.ru>
12 *
13 * @(#) $Id$
14 */
15
[006fa1ef]16#if HAVE_CONFIG_H
17#include "config.h"
18#endif
19
[945884fe]20#include <errno.h>
[228587bb]21#include <string.h>
22
[e51bd96]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{
[b5b07cad]40    rtems_status_code rc = RTEMS_SUCCESSFUL;
[e51bd96]41    rtems_libio_rw_args_t *args = arg;
[b5b07cad]42    uint32_t block_size;
43    char *buf;
44    uint32_t count;
45    rtems_blkdev_bnum block;
46    uint32_t blkofs;
[e51bd96]47    dev_t dev;
[3899a537]48    rtems_disk_device *dd;
[048dcd2b]49
[e51bd96]50    dev = rtems_filesystem_make_dev_t(major, minor);
[3899a537]51    dd = rtems_disk_obtain(dev);
[e51bd96]52    if (dd == NULL)
53        return RTEMS_INVALID_NUMBER;
[048dcd2b]54
[e51bd96]55    block_size = dd->block_size;
[048dcd2b]56
[e51bd96]57    buf = args->buffer;
58    count = args->count;
59    args->bytes_moved = 0;
[048dcd2b]60
[b5b07cad]61    block = (rtems_blkdev_bnum) (args->offset / block_size);
62    blkofs = (uint32_t) (args->offset % block_size);
[048dcd2b]63
[e51bd96]64    while (count > 0)
65    {
[3899a537]66        rtems_bdbuf_buffer *diskbuf;
[cec5c069]67        uint32_t            copy;
[048dcd2b]68
[e51bd96]69        rc = rtems_bdbuf_read(dev, block, &diskbuf);
70        if (rc != RTEMS_SUCCESSFUL)
[b5b07cad]71            break;
[e51bd96]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)
[b5b07cad]79            break;
[e51bd96]80        count -= copy;
81        buf += copy;
82        blkofs = 0;
83        block++;
84    }
[b5b07cad]85
86    rtems_disk_release(dd);
87
88    return rc;
[e51bd96]89}
90
91/* rtems_blkdev_generic_write --
92 *     Generic block device write primitive. Implemented using block device
[8b96149]93 *     buffer management primitives.
[e51bd96]94 */
95rtems_device_driver
96rtems_blkdev_generic_write(
97    rtems_device_major_number major,
98    rtems_device_minor_number minor,
99    void                    * arg)
100{
[b5b07cad]101    rtems_status_code rc = RTEMS_SUCCESSFUL;
[e51bd96]102    rtems_libio_rw_args_t *args = arg;
[b5b07cad]103    uint32_t block_size;
104    char *buf;
105    uint32_t count;
106    rtems_blkdev_bnum block;
107    uint32_t blkofs;
[e51bd96]108    dev_t dev;
[3899a537]109    rtems_disk_device *dd;
[048dcd2b]110
[e51bd96]111    dev = rtems_filesystem_make_dev_t(major, minor);
[3899a537]112    dd = rtems_disk_obtain(dev);
[e51bd96]113    if (dd == NULL)
114        return RTEMS_INVALID_NUMBER;
[048dcd2b]115
[e51bd96]116    block_size = dd->block_size;
[048dcd2b]117
[e51bd96]118    buf = args->buffer;
119    count = args->count;
120    args->bytes_moved = 0;
[048dcd2b]121
[b5b07cad]122    block = (rtems_blkdev_bnum) (args->offset / block_size);
123    blkofs = (uint32_t) (args->offset % block_size);
[048dcd2b]124
[e51bd96]125    while (count > 0)
126    {
[3899a537]127        rtems_bdbuf_buffer *diskbuf;
[cec5c069]128        uint32_t            copy;
[048dcd2b]129
[635652e]130        if ((blkofs == 0) && (count >= block_size))
[e51bd96]131            rc = rtems_bdbuf_get(dev, block, &diskbuf);
132        else
133            rc = rtems_bdbuf_read(dev, block, &diskbuf);
134        if (rc != RTEMS_SUCCESSFUL)
[b5b07cad]135            break;
[048dcd2b]136
[e51bd96]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;
[048dcd2b]142
[e51bd96]143        rc = rtems_bdbuf_release_modified(diskbuf);
144        if (rc != RTEMS_SUCCESSFUL)
[b5b07cad]145            break;
[048dcd2b]146
[e51bd96]147        count -= copy;
148        buf += copy;
149        blkofs = 0;
150        block++;
151    }
[b5b07cad]152
153    rtems_disk_release(dd);
154
155    return rc;
[e51bd96]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,
[31e2698]165    void                    * arg __attribute__((unused)))
[e51bd96]166{
167    dev_t dev;
[3899a537]168    rtems_disk_device *dd;
[048dcd2b]169
[e51bd96]170    dev = rtems_filesystem_make_dev_t(major, minor);
[3899a537]171    dd = rtems_disk_obtain(dev);
[e51bd96]172    if (dd == NULL)
173        return RTEMS_INVALID_NUMBER;
[048dcd2b]174
[e51bd96]175    dd->uses++;
[048dcd2b]176
[e51bd96]177    rtems_disk_release(dd);
[048dcd2b]178
[e51bd96]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,
[31e2698]190    void                    * arg __attribute__((unused)))
[e51bd96]191{
192    dev_t dev;
[3899a537]193    rtems_disk_device *dd;
[048dcd2b]194
[e51bd96]195    dev = rtems_filesystem_make_dev_t(major, minor);
[3899a537]196    dd = rtems_disk_obtain(dev);
[e51bd96]197    if (dd == NULL)
198        return RTEMS_INVALID_NUMBER;
[048dcd2b]199
[e51bd96]200    dd->uses--;
[048dcd2b]201
[e51bd96]202    rtems_disk_release(dd);
[048dcd2b]203
[e51bd96]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;
[3899a537]218    rtems_disk_device *dd;
[e51bd96]219    int rc;
[048dcd2b]220
[e51bd96]221    dev = rtems_filesystem_make_dev_t(major, minor);
[3899a537]222    dd = rtems_disk_obtain(dev);
[e51bd96]223    if (dd == NULL)
224        return RTEMS_INVALID_NUMBER;
[048dcd2b]225
[e51bd96]226    switch (args->command)
227    {
[945884fe]228        case RTEMS_BLKIO_GETMEDIABLKSIZE:
229            args->ioctl_return = dd->media_block_size;
230            break;
231
[3899a537]232        case RTEMS_BLKIO_GETBLKSIZE:
[e51bd96]233            args->ioctl_return = dd->block_size;
234            break;
[048dcd2b]235
[945884fe]236        case RTEMS_BLKIO_SETBLKSIZE:
237            dd->block_size = *((size_t*) args->buffer);
238            break;
239
[3899a537]240        case RTEMS_BLKIO_GETSIZE:
[e51bd96]241            args->ioctl_return = dd->size;
242            break;
243
[3899a537]244        case RTEMS_BLKIO_SYNCDEV:
[e51bd96]245            rc = rtems_bdbuf_syncdev(dd->dev);
[b96e09c]246            args->ioctl_return = (uint32_t) (rc == RTEMS_SUCCESSFUL ? 0 : -1);
[e51bd96]247            break;
[048dcd2b]248
[3899a537]249        case RTEMS_BLKIO_REQUEST:
[e51bd96]250        {
[3899a537]251            rtems_blkdev_request *req = args->buffer;
[b96e09c]252            args->ioctl_return = (uint32_t) dd->ioctl(dd, args->command, req);
[e51bd96]253            break;
254        }
[048dcd2b]255
[e51bd96]256        default:
[b96e09c]257            args->ioctl_return = (uint32_t) dd->ioctl(dd, args->command,
258                                                      args->buffer);
[e51bd96]259            break;
260    }
261    rtems_disk_release(dd);
[048dcd2b]262
[e51bd96]263    return RTEMS_SUCCESSFUL;
264}
[945884fe]265
266int
[b96e09c]267rtems_blkdev_ioctl(rtems_disk_device *dd, uint32_t req, void *argp)
[945884fe]268{
269    size_t            *arg_size = argp;
[eb649786]270    int                rc = 0;
[945884fe]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;
[eb649786]292            rc = -1;
[945884fe]293            break;
294    }
295
[eb649786]296    return rc;
[945884fe]297}
Note: See TracBrowser for help on using the repository browser.