source: rtems/cpukit/libblock/src/blkdev.c @ 635652e

4.104.114.84.9
Last change on this file since 635652e was 635652e, checked in by Joel Sherrill <joel.sherrill@…>, on Jan 27, 2003 at 3:13:12 PM

2003-01-27 Eugeny S. Mints <Eugeny.Mints@…>

  • src/blkdev.c: Per PR331 fix bug which is tripped by writing 512 byte blocks to 512 byte aligned positions.
  • Property mode set to 100644
File size: 5.9 KB
Line 
1/*
2 * blkdev.h - block device driver generic support
3 *
4 * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
5 * Author: Victor V. Vengerov <vvv@oktet.ru>
6 *
7 * @(#) $Id$
8 */
9
10#include <string.h>
11
12#include <rtems.h>
13#include <rtems/libio.h>
14#include <sys/ioctl.h>
15
16#include "rtems/diskdevs.h"
17#include "rtems/bdbuf.h"
18
19/* rtems_blkdev_generic_read --
20 *     Generic block device read primitive. Implemented using block device
21 *     buffer management primitives.
22 */
23rtems_device_driver
24rtems_blkdev_generic_read(
25    rtems_device_major_number major,
26    rtems_device_minor_number minor,
27    void                    * arg)
28{
29    rtems_libio_rw_args_t *args = arg;
30    int block_size_log2;
31    int block_size;
32    char *buf;
33    unsigned int count;
34    unsigned int block;
35    unsigned int blkofs;
36    dev_t dev;
37    disk_device *dd;
38   
39    dev = rtems_filesystem_make_dev_t(major, minor);
40    dd = rtems_disk_lookup(dev);
41    if (dd == NULL)
42        return RTEMS_INVALID_NUMBER;
43   
44    block_size_log2 = dd->block_size_log2;
45    block_size = dd->block_size;
46   
47    buf = args->buffer;
48    count = args->count;
49    args->bytes_moved = 0;
50   
51    block = args->offset >> block_size_log2;
52    blkofs = args->offset & (block_size - 1);
53   
54    while (count > 0)
55    {
56        bdbuf_buffer *diskbuf;
57        int copy;
58        rtems_status_code rc;
59       
60        rc = rtems_bdbuf_read(dev, block, &diskbuf);
61        if (rc != RTEMS_SUCCESSFUL)
62            return rc;
63        copy = block_size - blkofs;
64        if (copy > count)
65            copy = count;
66        memcpy(buf, (char *)diskbuf->buffer + blkofs, copy);
67        rc = rtems_bdbuf_release(diskbuf);
68        args->bytes_moved += copy;
69        if (rc != RTEMS_SUCCESSFUL)
70            return rc;
71        count -= copy;
72        buf += copy;
73        blkofs = 0;
74        block++;
75    }
76    return RTEMS_SUCCESSFUL;
77}
78
79/* rtems_blkdev_generic_write --
80 *     Generic block device write primitive. Implemented using block device
81 *     buffer management primitives.
82 */
83rtems_device_driver
84rtems_blkdev_generic_write(
85    rtems_device_major_number major,
86    rtems_device_minor_number minor,
87    void                    * arg)
88{
89    rtems_libio_rw_args_t *args = arg;
90    int block_size_log2;
91    int block_size;
92    char *buf;
93    unsigned int count;
94    unsigned int block;
95    unsigned int blkofs;
96    dev_t dev;
97    rtems_status_code rc;
98    disk_device *dd;
99   
100    dev = rtems_filesystem_make_dev_t(major, minor);
101    dd = rtems_disk_lookup(dev);
102    if (dd == NULL)
103        return RTEMS_INVALID_NUMBER;
104   
105    block_size_log2 = dd->block_size_log2;
106    block_size = dd->block_size;
107   
108    buf = args->buffer;
109    count = args->count;
110    args->bytes_moved = 0;
111   
112    block = args->offset >> block_size_log2;
113    blkofs = args->offset & (block_size - 1);
114   
115    while (count > 0)
116    {
117        bdbuf_buffer *diskbuf;
118        int copy;
119       
120        if ((blkofs == 0) && (count >= block_size))
121            rc = rtems_bdbuf_get(dev, block, &diskbuf);
122        else
123            rc = rtems_bdbuf_read(dev, block, &diskbuf);
124        if (rc != RTEMS_SUCCESSFUL)
125            return rc;
126           
127        copy = block_size - blkofs;
128        if (copy > count)
129            copy = count;
130        memcpy((char *)diskbuf->buffer + blkofs, buf, copy);
131        args->bytes_moved += copy;
132       
133        rc = rtems_bdbuf_release_modified(diskbuf);
134        if (rc != RTEMS_SUCCESSFUL)
135            return rc;
136       
137        count -= copy;
138        buf += copy;
139        blkofs = 0;
140        block++;
141    }
142    return RTEMS_SUCCESSFUL;
143}
144
145/* blkdev_generic_open --
146 *     Generic block device open primitive.
147 */
148rtems_device_driver
149rtems_blkdev_generic_open(
150    rtems_device_major_number major,
151    rtems_device_minor_number minor,
152    void                    * arg)
153{
154    dev_t dev;
155    disk_device *dd;
156   
157    dev = rtems_filesystem_make_dev_t(major, minor);
158    dd = rtems_disk_lookup(dev);
159    if (dd == NULL)
160        return RTEMS_INVALID_NUMBER;
161       
162    dd->uses++;
163   
164    rtems_disk_release(dd);
165   
166    return RTEMS_SUCCESSFUL;
167}
168
169
170/* blkdev_generic_close --
171 *     Generic block device close primitive.
172 */
173rtems_device_driver
174rtems_blkdev_generic_close(
175    rtems_device_major_number major,
176    rtems_device_minor_number minor,
177    void                    * arg)
178{
179    dev_t dev;
180    disk_device *dd;
181   
182    dev = rtems_filesystem_make_dev_t(major, minor);
183    dd = rtems_disk_lookup(dev);
184    if (dd == NULL)
185        return RTEMS_INVALID_NUMBER;
186       
187    dd->uses--;
188   
189    rtems_disk_release(dd);
190   
191    return RTEMS_SUCCESSFUL;
192}
193
194/* blkdev_generic_ioctl --
195 *     Generic block device ioctl primitive.
196 */
197rtems_device_driver
198rtems_blkdev_generic_ioctl(
199    rtems_device_major_number major,
200    rtems_device_minor_number minor,
201    void                    * arg)
202{
203    rtems_libio_ioctl_args_t *args = arg;
204    dev_t dev;
205    disk_device *dd;
206    int rc;
207   
208    dev = rtems_filesystem_make_dev_t(major, minor);
209    dd = rtems_disk_lookup(dev);
210    if (dd == NULL)
211        return RTEMS_INVALID_NUMBER;
212   
213    switch (args->command)
214    {
215        case BLKIO_GETBLKSIZE:
216            args->ioctl_return = dd->block_size;
217            break;
218       
219        case BLKIO_GETSIZE:
220            args->ioctl_return = dd->size;
221            break;
222
223        case BLKIO_SYNCDEV:
224            rc = rtems_bdbuf_syncdev(dd->dev);
225            args->ioctl_return = (rc == RTEMS_SUCCESSFUL ? 0 : -1);
226            break;
227           
228        case BLKIO_REQUEST:
229        {
230            blkdev_request *req = args->buffer;
231            req->start += dd->start;
232            args->ioctl_return = dd->ioctl(dd->phys_dev->dev, args->command, 
233                                           req);
234            break;
235        }
236       
237        default:
238            args->ioctl_return = dd->ioctl(dd->phys_dev->dev, args->command, 
239                                           args->buffer);
240            break;
241    }
242    rtems_disk_release(dd);
243   
244    return RTEMS_SUCCESSFUL;
245}
Note: See TracBrowser for help on using the repository browser.