source: rtems/cpukit/libblock/src/ramdisk.c @ e03c37a

4.104.114.9
Last change on this file since e03c37a was e03c37a, checked in by Ralf Corsepius <ralf.corsepius@…>, on Aug 25, 2008 at 3:07:58 PM

s/rtems_boolean/bool/g.

  • Property mode set to 100644
File size: 7.4 KB
Line 
1/* ramdisk.c -- RAM disk block device implementation
2 *
3 * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
4 * Author: Victor V. Vengerov <vvv@oktet.ru>
5 *
6 * @(#) $Id$
7 */
8
9#if HAVE_CONFIG_H
10#include "config.h"
11#endif
12
13#include <rtems.h>
14#include <rtems/libio.h>
15#include <errno.h>
16#include <stdlib.h>
17#include <stdio.h>
18#include <string.h>
19#include <inttypes.h>
20
21#include "rtems/blkdev.h"
22#include "rtems/diskdevs.h"
23#include "rtems/ramdisk.h"
24
25/**
26 * Control tracing. It can be compiled out of the code for small
27 * footprint targets. Leave in by default.
28 */
29#if !defined (RTEMS_RAMDISK_TRACE)
30#define RTEMS_RAMDISK_TRACE 0
31#endif
32
33#define RAMDISK_DEVICE_BASE_NAME "/dev/ramdisk"
34
35/* Internal RAM disk descriptor */
36struct ramdisk {
37    int           block_size; /* RAM disk block size */
38    int           block_num;  /* Number of blocks on this RAM disk */
39    void         *area;       /* RAM disk memory area */
40    bool          initialized;/* RAM disk is initialized */
41    bool          malloced;   /* != 0, if memory allocated by malloc for this
42                                 RAM disk */
43#if RTEMS_RAMDISK_TRACE
44    int           info_level; /* Trace level */
45#endif
46};
47
48static struct ramdisk *ramdisk;
49static uint32_t        nramdisks;
50
51#if RTEMS_RAMDISK_TRACE
52/**
53 * Print a message to the ramdisk output and flush it.
54 *
55 * @param rd The ramdisk control structure.
56 * @param format The format string. See printf for details.
57 * @param ... The arguments for the format text.
58 * @return int The number of bytes written to the output.
59 */
60static int
61rtems_ramdisk_printf (struct ramdisk *rd, const char *format, ...)
62{
63  int ret = 0;
64  if (rd->info_level >= 1)
65  {
66    va_list args;
67    va_start (args, format);
68    fprintf (stdout, "ramdisk:");
69    ret =  vfprintf (stdout, format, args);
70    fprintf (stdout, "\n");
71    fflush (stdout);
72  }
73  return ret;
74}
75#endif
76
77/* ramdisk_read --
78 *     RAM disk READ request handler. This primitive copies data from RAM
79 *     disk to supplied buffer and invoke the callout function to inform
80 *     upper layer that reading is completed.
81 *
82 * PARAMETERS:
83 *     req - pointer to the READ block device request info
84 *
85 * RETURNS:
86 *     ioctl return value
87 */
88static int
89ramdisk_read(struct ramdisk *rd, rtems_blkdev_request *req)
90{
91    char *from;
92    uint32_t   i;
93    rtems_blkdev_sg_buffer *sg;
94    uint32_t   remains;
95
96#if RTEMS_RAMDISK_TRACE
97    rtems_ramdisk_printf (rd, "ramdisk read: start=%d, blocks=%d remains=%d",
98                          req->bufs[0].block, req->bufnum,
99                          rd->block_size * req->count);
100#endif
101
102    remains = rd->block_size * req->bufnum;
103    sg = req->bufs;
104    for (i = 0; (remains > 0) && (i < req->bufnum); i++, sg++)
105    {
106        uint32_t count = sg->length;
107        from = ((char *)rd->area + (sg->block * rd->block_size));
108        if (count > remains)
109            count = remains;
110        memcpy(sg->buffer, from, count);
111        remains -= count;
112        from += count;
113    }
114    req->req_done(req->done_arg, RTEMS_SUCCESSFUL, 0);
115    return 0;
116}
117
118/* ramdisk_write --
119 *     RAM disk WRITE request handler. This primitive copies data from
120 *     supplied buffer to RAM disk and invoke the callout function to inform
121 *     upper layer that writing is completed.
122 *
123 * PARAMETERS:
124 *     req - pointer to the WRITE block device request info
125 *
126 * RETURNS:
127 *     ioctl return value
128 */
129static int
130ramdisk_write(struct ramdisk *rd, rtems_blkdev_request *req)
131{
132    char *to;
133    uint32_t   i;
134    rtems_blkdev_sg_buffer *sg;
135    uint32_t   remains;
136
137#if RTEMS_RAMDISK_TRACE
138    rtems_ramdisk_printf (rd, "ramdisk write: start=%d, blocks=%d remains=%d",
139                          req->bufs[0].block, req->bufnum,
140                          rd->block_size * req->bufnum);
141#endif
142    remains = rd->block_size * req->bufnum;
143    sg = req->bufs;
144    for (i = 0; (remains > 0) && (i < req->bufnum); i++, sg++)
145    {
146        uint32_t count = sg->length;
147        to = ((char *)rd->area + (sg->block * rd->block_size));
148        if (count > remains)
149            count = remains;
150        memcpy(to, sg->buffer, count);
151        remains -= count;
152        to += count;
153    }
154    req->req_done(req->done_arg, RTEMS_SUCCESSFUL, 0);
155    return 0;
156}
157
158/* ramdisk_ioctl --
159 *     IOCTL handler for RAM disk device.
160 *
161 * PARAMETERS:
162 *      dev  - device number (major, minor number)
163 *      req  - IOCTL request code
164 *      argp - IOCTL argument
165 *
166 * RETURNS:
167 *     IOCTL return value
168 */
169static int
170ramdisk_ioctl(dev_t dev, uint32_t req, void *argp)
171{
172    switch (req)
173    {
174        case RTEMS_BLKIO_REQUEST:
175        {
176            rtems_device_minor_number minor;
177            rtems_blkdev_request *r = argp;
178            struct ramdisk *rd;
179
180            minor = rtems_filesystem_dev_minor_t(dev);
181            if ((minor >= nramdisks) || !ramdisk[minor].initialized)
182            {
183                errno = ENODEV;
184                return -1;
185            }
186
187            rd = ramdisk + minor;
188
189            switch (r->req)
190            {
191                case RTEMS_BLKDEV_REQ_READ:
192                    return ramdisk_read(rd, r);
193
194                case RTEMS_BLKDEV_REQ_WRITE:
195                    return ramdisk_write(rd, r);
196
197                default:
198                    errno = EBADRQC;
199                    return -1;
200            }
201            break;
202        }
203
204        default:
205            errno = EBADRQC;
206            return -1;
207    }
208}
209
210/* ramdisk_initialize --
211 *     RAM disk device driver initialization. Run through RAM disk
212 *     configuration information and configure appropriate RAM disks.
213 *
214 * PARAMETERS:
215 *     major - RAM disk major device number
216 *     minor - minor device number, not applicable
217 *     arg   - initialization argument, not applicable
218 *
219 * RETURNS:
220 *     none
221 */
222rtems_device_driver
223ramdisk_initialize(
224    rtems_device_major_number major,
225    rtems_device_minor_number minor,
226    void *arg)
227{
228    rtems_device_minor_number i;
229    rtems_ramdisk_config *c = rtems_ramdisk_configuration;
230    struct ramdisk *r;
231    rtems_status_code rc;
232
233    rc = rtems_disk_io_initialize();
234    if (rc != RTEMS_SUCCESSFUL)
235        return rc;
236
237    r = ramdisk = calloc(rtems_ramdisk_configuration_size,
238                         sizeof(struct ramdisk));
239#if RTEMS_RAMDISK_TRACE
240    r->info_level = 1;
241#endif   
242    for (i = 0; i < rtems_ramdisk_configuration_size; i++, c++, r++)
243    {
244        dev_t dev = rtems_filesystem_make_dev_t(major, i);
245        char name[sizeof(RAMDISK_DEVICE_BASE_NAME "0123456789")];
246        snprintf(name, sizeof(name), RAMDISK_DEVICE_BASE_NAME "%" PRIu32, i);
247        r->block_size = c->block_size;
248        r->block_num = c->block_num;
249        if (c->location == NULL)
250        {
251            r->malloced = TRUE;
252            r->area = malloc(r->block_size * r->block_num);
253            if (r->area == NULL) /* No enough memory for this disk */
254            {
255                r->initialized = FALSE;
256                continue;
257            }
258            else
259            {
260                r->initialized = TRUE;
261            }
262        }
263        else
264        {
265            r->malloced = FALSE;
266            r->initialized = TRUE;
267            r->area = c->location;
268        }
269        rc = rtems_disk_create_phys(dev, c->block_size, c->block_num,
270                                    ramdisk_ioctl, name);
271        if (rc != RTEMS_SUCCESSFUL)
272        {
273            if (r->malloced)
274            {
275                free(r->area);
276            }
277            r->initialized = FALSE;
278        }
279    }
280    nramdisks = rtems_ramdisk_configuration_size;
281    return RTEMS_SUCCESSFUL;
282}
Note: See TracBrowser for help on using the repository browser.