source: rtems/cpukit/libblock/src/ramdisk.c @ 945884fe

4.104.11
Last change on this file since 945884fe was 945884fe, checked in by Chris Johns <chrisj@…>, on Aug 6, 2009 at 3:58:09 AM

2009-08-06 Chris Johns <chrisj@…>

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