forked from Imagelibrary/rtems
* Submitted by Victor V. Vengerov <vvv@oktet.ru> and merged into the RTEMS source. * ChangeLog, Makefile.am, README, configure.ac, include/Makefile.am, include/rtems/bdbuf.h, include/rtems/blkdev.h, include/rtems/diskdevs.h, include/rtems/ramdisk.h, include/rtems/.cvsignore, include/.cvsignore, src/Makefile.am, src/bdbuf.c, src/blkdev.c, src/diskdevs.c, src/ramdisk.c, src/.cvsignore, .cvsignore: New files.
225 lines
5.9 KiB
C
225 lines
5.9 KiB
C
/* ramdisk.c -- RAM disk block device implementation
|
|
*
|
|
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
|
* Author: Victor V. Vengerov <vvv@oktet.ru>
|
|
*
|
|
* @(#) $Id$
|
|
*/
|
|
|
|
#include <rtems.h>
|
|
#include <rtems/libio.h>
|
|
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
#include "rtems/blkdev.h"
|
|
#include "rtems/diskdevs.h"
|
|
#include "rtems/ramdisk.h"
|
|
|
|
#define RAMDISK_DEVICE_BASE_NAME "/dev/ramdisk"
|
|
|
|
/* Internal RAM disk descriptor */
|
|
struct ramdisk {
|
|
int block_size; /* RAM disk block size */
|
|
int block_num; /* Number of blocks on this RAM disk */
|
|
void *area; /* RAM disk memory area */
|
|
rtems_boolean initialized;/* RAM disk is initialized */
|
|
rtems_boolean malloced; /* != 0, if memory allocated by malloc for this
|
|
RAM disk */
|
|
};
|
|
|
|
static struct ramdisk *ramdisk;
|
|
static int nramdisks;
|
|
|
|
/* ramdisk_read --
|
|
* RAM disk READ request handler. This primitive copies data from RAM
|
|
* disk to supplied buffer and invoke the callout function to inform
|
|
* upper layer that reading is completed.
|
|
*
|
|
* PARAMETERS:
|
|
* req - pointer to the READ block device request info
|
|
*
|
|
* RETURNS:
|
|
* ioctl return value
|
|
*/
|
|
static int
|
|
ramdisk_read(struct ramdisk *rd, blkdev_request *req)
|
|
{
|
|
char *from;
|
|
rtems_unsigned32 i;
|
|
blkdev_sg_buffer *sg;
|
|
rtems_unsigned32 remains;
|
|
|
|
from = (char *)rd->area + (req->start * rd->block_size);
|
|
remains = rd->block_size * req->count;
|
|
sg = req->bufs;
|
|
for (i = 0; (remains > 0) && (i < req->bufnum); i++, sg++)
|
|
{
|
|
int count = sg->length;
|
|
if (count > remains)
|
|
count = remains;
|
|
memcpy(sg->buffer, from, count);
|
|
remains -= count;
|
|
}
|
|
req->req_done(req->done_arg, RTEMS_SUCCESSFUL, 0);
|
|
return 0;
|
|
}
|
|
|
|
/* ramdisk_write --
|
|
* RAM disk WRITE request handler. This primitive copies data from
|
|
* supplied buffer to RAM disk and invoke the callout function to inform
|
|
* upper layer that writing is completed.
|
|
*
|
|
* PARAMETERS:
|
|
* req - pointer to the WRITE block device request info
|
|
*
|
|
* RETURNS:
|
|
* ioctl return value
|
|
*/
|
|
static int
|
|
ramdisk_write(struct ramdisk *rd, blkdev_request *req)
|
|
{
|
|
char *to;
|
|
rtems_unsigned32 i;
|
|
blkdev_sg_buffer *sg;
|
|
rtems_unsigned32 remains;
|
|
|
|
to = (char *)rd->area + (req->start * rd->block_size);
|
|
remains = rd->block_size * req->count;
|
|
sg = req->bufs;
|
|
for (i = 0; (remains > 0) && (i < req->bufnum); i++, sg++)
|
|
{
|
|
int count = sg->length;
|
|
if (count > remains)
|
|
count = remains;
|
|
memcpy(to, sg->buffer, count);
|
|
remains -= count;
|
|
}
|
|
req->req_done(req->done_arg, RTEMS_SUCCESSFUL, 0);
|
|
return 0;
|
|
}
|
|
|
|
/* ramdisk_ioctl --
|
|
* IOCTL handler for RAM disk device.
|
|
*
|
|
* PARAMETERS:
|
|
* dev - device number (major, minor number)
|
|
* req - IOCTL request code
|
|
* argp - IOCTL argument
|
|
*
|
|
* RETURNS:
|
|
* IOCTL return value
|
|
*/
|
|
static int
|
|
ramdisk_ioctl(dev_t dev, int req, void *argp)
|
|
{
|
|
switch (req)
|
|
{
|
|
case BLKIO_REQUEST:
|
|
{
|
|
rtems_device_minor_number minor;
|
|
blkdev_request *r = argp;
|
|
struct ramdisk *rd;
|
|
|
|
minor = rtems_filesystem_dev_minor_t(dev);
|
|
if ((minor >= nramdisks) || !ramdisk[minor].initialized)
|
|
{
|
|
errno = ENODEV;
|
|
return -1;
|
|
}
|
|
|
|
rd = ramdisk + minor;
|
|
|
|
switch (r->req)
|
|
{
|
|
case BLKDEV_REQ_READ:
|
|
return ramdisk_read(rd, r);
|
|
|
|
case BLKDEV_REQ_WRITE:
|
|
return ramdisk_write(rd, r);
|
|
|
|
default:
|
|
errno = EBADRQC;
|
|
return -1;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
errno = EBADRQC;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* ramdisk_initialize --
|
|
* RAM disk device driver initialization. Run through RAM disk
|
|
* configuration information and configure appropriate RAM disks.
|
|
*
|
|
* PARAMETERS:
|
|
* major - RAM disk major device number
|
|
* minor - minor device number, not applicable
|
|
* arg - initialization argument, not applicable
|
|
*
|
|
* RETURNS:
|
|
* none
|
|
*/
|
|
rtems_device_driver
|
|
ramdisk_initialize(
|
|
rtems_device_major_number major,
|
|
rtems_device_minor_number minor,
|
|
void *arg)
|
|
{
|
|
rtems_device_minor_number i;
|
|
rtems_ramdisk_config *c = rtems_ramdisk_configuration;
|
|
struct ramdisk *r;
|
|
rtems_status_code rc;
|
|
|
|
rc = rtems_disk_io_initialize();
|
|
if (rc != RTEMS_SUCCESSFUL)
|
|
return rc;
|
|
|
|
r = ramdisk = calloc(rtems_ramdisk_configuration_size,
|
|
sizeof(struct ramdisk));
|
|
|
|
for (i = 0; i < rtems_ramdisk_configuration_size; i++, c++, r++)
|
|
{
|
|
dev_t dev = rtems_filesystem_make_dev_t(major, i);
|
|
char name[sizeof(RAMDISK_DEVICE_BASE_NAME "0123456789")];
|
|
snprintf(name, sizeof(name), RAMDISK_DEVICE_BASE_NAME "%d", i);
|
|
r->block_size = c->block_size;
|
|
r->block_num = c->block_num;
|
|
if (c->location == NULL)
|
|
{
|
|
r->malloced = TRUE;
|
|
r->area = malloc(r->block_size * r->block_num);
|
|
if (r->area == NULL) /* No enough memory for this disk */
|
|
{
|
|
r->initialized = FALSE;
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
r->initialized = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
r->malloced = FALSE;
|
|
r->initialized = TRUE;
|
|
r->area = c->location;
|
|
}
|
|
rc = rtems_disk_create_phys(dev, c->block_size, c->block_num,
|
|
ramdisk_ioctl, name);
|
|
if (rc != RTEMS_SUCCESSFUL)
|
|
{
|
|
if (r->malloced)
|
|
{
|
|
free(r->area);
|
|
}
|
|
r->initialized = FALSE;
|
|
}
|
|
}
|
|
nramdisks = rtems_ramdisk_configuration_size;
|
|
return RTEMS_SUCCESSFUL;
|
|
}
|