forked from Imagelibrary/rtems
2002-02-28 Joel Sherrill <joel@OARcorp.com>
* 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.
This commit is contained in:
14
c/src/exec/libblock/.cvsignore
Normal file
14
c/src/exec/libblock/.cvsignore
Normal file
@@ -0,0 +1,14 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
config.cache
|
||||
config.guess
|
||||
config.log
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
depcomp
|
||||
install-sh
|
||||
missing
|
||||
mkinstalldirs
|
||||
25
c/src/exec/libblock/ChangeLog
Normal file
25
c/src/exec/libblock/ChangeLog
Normal file
@@ -0,0 +1,25 @@
|
||||
2002-02-28 Joel Sherrill <joel@OARcorp.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2001-11-29 Victor V. Vengerov <vvv@oktet.ru>
|
||||
* AVL trees implementation added.
|
||||
|
||||
2001-11-16 Victor V. Vengerov <vvv@oktet.ru>
|
||||
* include/rtems/bdbuf.h, src/bdbuf.c(rtems_bdbuf_syncdev): New.
|
||||
|
||||
2001-11-07 Victor V. Vengerov <vvv@oktet.ru>
|
||||
|
||||
* ChangeLog: New file.
|
||||
* src/, include/, include/rtems/: New directories.
|
||||
* README, configure.ac, Makefile.am, src/Makefile.am,
|
||||
include/Makefile.am: New files.
|
||||
* include/rtems/bdbuf.h include/rtems/blkdev.h
|
||||
include/rtems/diskdevs.h include/rtems/ramdisk.h
|
||||
src/bdbuf.c src/blkdev.c src/diskdevs.c src/ramdisk.c: New files.
|
||||
13
c/src/exec/libblock/Makefile.am
Normal file
13
c/src/exec/libblock/Makefile.am
Normal file
@@ -0,0 +1,13 @@
|
||||
##
|
||||
## $Id$
|
||||
##
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign 1.4
|
||||
ACLOCAL_AMFLAGS = -I ../../../aclocal
|
||||
|
||||
SUBDIRS = include src
|
||||
|
||||
EXTRA_DIST = README
|
||||
|
||||
include $(top_srcdir)/../../../automake/subdirs.am
|
||||
include $(top_srcdir)/../../../automake/local.am
|
||||
14
c/src/exec/libblock/README
Normal file
14
c/src/exec/libblock/README
Normal file
@@ -0,0 +1,14 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
This directory contains the block device (HDD, CDROMs, etc) support code.
|
||||
It includes:
|
||||
- block device driver interface
|
||||
- generic open/close/read/write/ioctl primitives for block device drivers
|
||||
- disk I/O buffering
|
||||
- logical disk support
|
||||
- RAM disk block device driver
|
||||
|
||||
Victor V. Vengerov, <vvv@oktet.ru>
|
||||
November, 7 2001
|
||||
32
c/src/exec/libblock/configure.ac
Normal file
32
c/src/exec/libblock/configure.ac
Normal file
@@ -0,0 +1,32 @@
|
||||
## Process this file with autoconf to produce a configure script.
|
||||
##
|
||||
## $Id$
|
||||
|
||||
AC_PREREQ(2.52)
|
||||
AC_INIT
|
||||
AC_CONFIG_SRCDIR([src/bdbuf.c])
|
||||
RTEMS_TOP(../../..)
|
||||
AC_CONFIG_AUX_DIR(../../..)
|
||||
|
||||
RTEMS_CANONICAL_TARGET_CPU
|
||||
RTEMS_CANONICAL_HOST
|
||||
|
||||
AM_INIT_AUTOMAKE(rtems-c-src-libblock,$RTEMS_VERSION,no)
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
RTEMS_ENV_RTEMSBSP
|
||||
RTEMS_CHECK_CPU
|
||||
RTEMS_CHECK_CUSTOM_BSP(RTEMS_BSP)
|
||||
RTEMS_PROG_CC_FOR_TARGET
|
||||
RTEMS_ENABLE_BARE
|
||||
|
||||
RTEMS_CANONICALIZE_TOOLS
|
||||
|
||||
RTEMS_PROJECT_ROOT
|
||||
|
||||
# Explicitly list all Makefiles here
|
||||
AC_CONFIG_FILES([Makefile
|
||||
include/Makefile
|
||||
src/Makefile
|
||||
])
|
||||
AC_OUTPUT
|
||||
2
c/src/exec/libblock/include/.cvsignore
Normal file
2
c/src/exec/libblock/include/.cvsignore
Normal file
@@ -0,0 +1,2 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
23
c/src/exec/libblock/include/Makefile.am
Normal file
23
c/src/exec/libblock/include/Makefile.am
Normal file
@@ -0,0 +1,23 @@
|
||||
##
|
||||
## $Id$
|
||||
##
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign 1.5
|
||||
|
||||
include_rtemsdir = $(includedir)/rtems
|
||||
|
||||
$(PROJECT_INCLUDE)/%.h: %.h
|
||||
$(INSTALL_DATA) $< $@
|
||||
|
||||
$(PROJECT_INCLUDE)/rtems:
|
||||
@$(mkinstalldirs) $@
|
||||
|
||||
include_rtems_HEADERS = \
|
||||
rtems/bdbuf.h rtems/blkdev.h rtems/diskdevs.h rtems/ramdisk.h
|
||||
|
||||
PREINSTALL_FILES = $(PROJECT_INCLUDE)/rtems \
|
||||
$(include_rtems_HEADERS:%=$(PROJECT_INCLUDE)/%)
|
||||
|
||||
all-local: $(PREINSTALL_FILES)
|
||||
|
||||
include $(top_srcdir)/../../../automake/local.am
|
||||
2
c/src/exec/libblock/include/rtems/.cvsignore
Normal file
2
c/src/exec/libblock/include/rtems/.cvsignore
Normal file
@@ -0,0 +1,2 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
282
c/src/exec/libblock/include/rtems/bdbuf.h
Normal file
282
c/src/exec/libblock/include/rtems/bdbuf.h
Normal file
@@ -0,0 +1,282 @@
|
||||
/* bdbuf.h -- block device buffer management
|
||||
*
|
||||
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||
* Author: Victor V. Vengerov <vvv@oktet.ru>
|
||||
*
|
||||
* @(#) $Id$
|
||||
*/
|
||||
|
||||
#ifndef __RTEMS_LIBBLOCK_BDBUF_H__
|
||||
#define __RTEMS_LIBBLOCK_BDBUF_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <chain.h>
|
||||
|
||||
#include "rtems/blkdev.h"
|
||||
#include "rtems/diskdevs.h"
|
||||
|
||||
|
||||
/*
|
||||
* To manage buffers we using Buffer Descriptors.
|
||||
* To speed-up buffer lookup descriptors are organized in AVL-Tree.
|
||||
* The fields 'dev' and 'block' are search key.
|
||||
*/
|
||||
|
||||
/* Buffer descriptors
|
||||
* Descriptors organized in AVL-tree to speedup buffer lookup.
|
||||
* dev and block fields are search key in AVL-tree.
|
||||
* Modified buffers, free buffers and used buffers linked in 'mod', 'free' and
|
||||
* 'lru' chains appropriately.
|
||||
*/
|
||||
|
||||
typedef struct bdbuf_buffer {
|
||||
Chain_Node link; /* Link in the lru, mod or free chains */
|
||||
|
||||
#ifdef BINARY_TREE
|
||||
struct bdbuf_avl_node {
|
||||
struct bdbuf_buffer *left; /* link to the left sub-tree */
|
||||
struct bdbuf_buffer *right; /* link to the right sub-tree */
|
||||
|
||||
int bf; /* AVL tree node balance factor */
|
||||
} avl; /* AVL-tree links */
|
||||
#else /* AVL TREE */
|
||||
struct bdbuf_avl_node {
|
||||
char cache; /* Cache */
|
||||
|
||||
struct bdbuf_buffer* link[2]; /* Left and Right Kids */
|
||||
|
||||
char bal; /* The balance of the sub-tree */
|
||||
} avl;
|
||||
#endif
|
||||
dev_t dev; /* device number */
|
||||
blkdev_bnum block; /* block number on the device */
|
||||
|
||||
char *buffer; /* Pointer to the buffer memory area */
|
||||
rtems_status_code status; /* Last I/O operation completion status */
|
||||
int error; /* If status != RTEMS_SUCCESSFUL, this field contains
|
||||
errno value which can be used by user later */
|
||||
boolean modified:1; /* =1 if buffer was modified */
|
||||
boolean in_progress:1; /* =1 if exchange with disk is in progress;
|
||||
need to wait on semaphore */
|
||||
boolean actual:1; /* Buffer contains actual data */
|
||||
int use_count; /* Usage counter; incremented when somebody use
|
||||
this buffer; decremented when buffer released
|
||||
without modification or when buffer is flushed
|
||||
by swapout task */
|
||||
|
||||
rtems_bdpool_id pool; /* Identifier of buffer pool to which this buffer
|
||||
belongs */
|
||||
CORE_mutex_Control transfer_sema;
|
||||
/* Transfer operation semaphore */
|
||||
} bdbuf_buffer;
|
||||
|
||||
|
||||
|
||||
/* bdbuf_config structure describes block configuration (size,
|
||||
* amount, memory location) for buffering layer
|
||||
*/
|
||||
typedef struct rtems_bdbuf_config {
|
||||
int size; /* Size of block */
|
||||
int num; /* Number of blocks of appropriate size */
|
||||
char *mem_area; /* Pointer to the blocks location or NULL, in this
|
||||
case memory for blocks will be allocated by
|
||||
Buffering Layer with the help of RTEMS partition
|
||||
manager */
|
||||
} rtems_bdbuf_config;
|
||||
|
||||
extern rtems_bdbuf_config rtems_bdbuf_configuration[];
|
||||
extern int rtems_bdbuf_configuration_size;
|
||||
|
||||
/* rtems_bdbuf_init --
|
||||
* Prepare buffering layer to work - initialize buffer descritors
|
||||
* and (if it is neccessary) buffers. Buffers will be allocated accoriding
|
||||
* to the configuration table, each entry describes kind of block and
|
||||
* amount requested. After initialization all blocks is placed into
|
||||
* free elements lists.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* conf_table - pointer to the buffers configuration table
|
||||
* size - number of entries in configuration table
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
|
||||
* or error code if error is occured)
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_init(rtems_bdbuf_config *conf_table, int size);
|
||||
|
||||
|
||||
/* rtems_bdbuf_get --
|
||||
* Obtain block buffer. If specified block already cached (i.e. there's
|
||||
* block in the _modified_, or _recently_used_), return address
|
||||
* of appropriate buffer descriptor and increment reference counter to 1.
|
||||
* If block is not cached, allocate new buffer and return it. Data
|
||||
* shouldn't be read to the buffer from media; buffer may contains
|
||||
* arbitrary data. This primitive may be blocked if there are no free
|
||||
* buffer descriptors available and there are no unused non-modified
|
||||
* (or synchronized with media) buffers available.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* device - device number (constructed of major and minor device number)
|
||||
* block - linear media block number
|
||||
* bd - address of variable to store pointer to the buffer descriptor
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
|
||||
* or error code if error is occured)
|
||||
*
|
||||
* SIDE EFFECTS:
|
||||
* bufget_sema semaphore obtained by this primitive.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_get(dev_t device, blkdev_bnum block, bdbuf_buffer **bdb_ptr);
|
||||
|
||||
/* rtems_bdbuf_read --
|
||||
* (Similar to the rtems_bdbuf_get, except reading data from media)
|
||||
* Obtain block buffer. If specified block already cached, return address
|
||||
* of appropriate buffer and increment reference counter to 1. If block is
|
||||
* not cached, allocate new buffer and read data to it from the media.
|
||||
* This primitive may be blocked on waiting until data to be read from
|
||||
* media, if there are no free buffer descriptors available and there are
|
||||
* no unused non-modified (or synchronized with media) buffers available.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* device - device number (consists of major and minor device number)
|
||||
* block - linear media block number
|
||||
* bd - address of variable to store pointer to the buffer descriptor
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
|
||||
* or error code if error is occured)
|
||||
*
|
||||
* SIDE EFFECTS:
|
||||
* bufget_sema and transfer_sema semaphores obtained by this primitive.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_read(dev_t device, blkdev_bnum block, bdbuf_buffer **bdb_ptr);
|
||||
|
||||
/* rtems_bdbuf_release --
|
||||
* Release buffer allocated before. This primitive decrease the
|
||||
* usage counter. If it is zero, further destiny of buffer depends on
|
||||
* 'modified' status. If buffer was modified, it is placed to the end of
|
||||
* mod list and flush task waken up. If buffer was not modified,
|
||||
* it is placed to the end of lru list, and bufget_sema released, allowing
|
||||
* to reuse this buffer.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* bd_buf - pointer to the bdbuf_buffer structure previously obtained using
|
||||
* get/read primitive.
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
|
||||
* or error code if error is occured)
|
||||
*
|
||||
* SIDE EFFECTS:
|
||||
* flush_sema and bufget_sema semaphores may be released by this primitive.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_release(bdbuf_buffer *bd_buf);
|
||||
|
||||
/* rtems_bdbuf_release_modified --
|
||||
* Release buffer allocated before, assuming that it is _modified_ by
|
||||
* it's owner. This primitive decrease usage counter for buffer, mark
|
||||
* buffer descriptor as modified. If usage counter is 0, insert it at
|
||||
* end of mod chain and release flush_sema semaphore to activate the
|
||||
* flush task.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* bd_buf - pointer to the bdbuf_buffer structure previously obtained using
|
||||
* get/read primitive.
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
|
||||
* or error code if error is occured)
|
||||
*
|
||||
* SIDE EFFECTS:
|
||||
* flush_sema semaphore may be released by this primitive.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_release_modified(bdbuf_buffer *bd_buf);
|
||||
|
||||
/* rtems_bdbuf_sync --
|
||||
* Wait until specified buffer synchronized with disk. Invoked on exchanges
|
||||
* critical for data consistency on the media. This primitive mark owned
|
||||
* block as modified, decrease usage counter. If usage counter is 0,
|
||||
* block inserted to the mod chain and flush_sema semaphore released.
|
||||
* Finally, primitives blocked on transfer_sema semaphore.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* bd_buf - pointer to the bdbuf_buffer structure previously obtained using
|
||||
* get/read primitive.
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
|
||||
* or error code if error is occured)
|
||||
*
|
||||
* SIDE EFFECTS:
|
||||
* Primitive may be blocked on transfer_sema semaphore.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_sync(bdbuf_buffer *bd_buf);
|
||||
|
||||
/* rtems_bdbuf_syncdev --
|
||||
* Synchronize with disk all buffers containing the blocks belonging to
|
||||
* specified device.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - block device number
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
|
||||
* or error code if error is occured)
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_syncdev(dev_t dev);
|
||||
|
||||
/* rtems_bdbuf_find_pool --
|
||||
* Find first appropriate buffer pool. This primitive returns the index
|
||||
* of first buffer pool which block size is greater than or equal to
|
||||
* specified size.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* block_size - requested block size
|
||||
* pool - placeholder for result
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code: RTEMS_SUCCESSFUL if operation completed successfully,
|
||||
* RTEMS_INVALID_SIZE if specified block size is invalid (not a power
|
||||
* of 2), RTEMS_NOT_DEFINED if buffer pool for this or greater block size
|
||||
* is not configured.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_find_pool(int block_size, rtems_bdpool_id *pool);
|
||||
|
||||
/* rtems_bdbuf_get_pool_info --
|
||||
* Obtain characteristics of buffer pool with specified number.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* pool - buffer pool number
|
||||
* block_size - block size for which buffer pool is configured returned
|
||||
* there
|
||||
* blocks - number of buffers in buffer pool returned there
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code: RTEMS_SUCCESSFUL if operation completed successfully,
|
||||
* RTEMS_INVALID_NUMBER if appropriate buffer pool is not configured.
|
||||
*
|
||||
* NOTE:
|
||||
* Buffer pools enumerated contiguously starting from 0.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_get_pool_info(rtems_bdpool_id pool, int *block_size, int *blocks);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
147
c/src/exec/libblock/include/rtems/blkdev.h
Normal file
147
c/src/exec/libblock/include/rtems/blkdev.h
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* blkdev.h - block device driver interface definitions
|
||||
*
|
||||
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||
* Author: Victor V. Vengerov <vvv@oktet.ru>
|
||||
*
|
||||
* @(#) $Id$
|
||||
*/
|
||||
|
||||
#ifndef __RTEMS_LIBBLOCK_BLKDEV_H__
|
||||
#define __RTEMS_LIBBLOCK_BLKDEV_H__
|
||||
|
||||
#include <rtems.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Interface with device drivers
|
||||
* Block device looks, initialized and behaves like traditional RTEMS device
|
||||
* driver. Heart of the block device driver is in BIOREQUEST ioctl. This call
|
||||
* puts I/O request to the block device queue, in priority order, for
|
||||
* asynchronous processing. When driver executes request, req_done
|
||||
* function invoked, so callee knows about it. Look for details below.
|
||||
*/
|
||||
|
||||
|
||||
/* Block device block number datatype */
|
||||
typedef rtems_unsigned32 blkdev_bnum;
|
||||
|
||||
/* Block device request type */
|
||||
typedef enum blkdev_request_op {
|
||||
BLKDEV_REQ_READ, /* Read operation */
|
||||
BLKDEV_REQ_WRITE /* Write operation */
|
||||
} blkdev_request_op;
|
||||
|
||||
/* Type for block device request done callback function.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* arg - argument supplied in blkdev_request
|
||||
* status - rtems status code for this operation
|
||||
* errno - errno value to be passed to the user when
|
||||
* status != RTEMS_SUCCESSFUL
|
||||
*/
|
||||
typedef void (* blkdev_request_cb)(void *arg,
|
||||
rtems_status_code status,
|
||||
int error);
|
||||
|
||||
/* blkdev_sg_buffer
|
||||
* Block device scatter/gather buffer structure
|
||||
*/
|
||||
typedef struct blkdev_sg_buffer {
|
||||
rtems_unsigned32 length; /* Buffer length */
|
||||
void *buffer; /* Buffer pointer */
|
||||
} blkdev_sg_buffer;
|
||||
|
||||
/* blkdev_request (Block Device Request) structure is
|
||||
* used to read/write a number of blocks from/to device.
|
||||
*/
|
||||
typedef struct blkdev_request {
|
||||
blkdev_request_op req; /* Block device operation (read or write) */
|
||||
blkdev_request_cb req_done; /* Callback function */
|
||||
void *done_arg; /* Argument to be passed to callback function*/
|
||||
blkdev_bnum start; /* Start block number */
|
||||
rtems_unsigned32 count; /* Number of blocks to be exchanged */
|
||||
rtems_unsigned32 bufnum; /* Number of buffers provided */
|
||||
|
||||
blkdev_sg_buffer bufs[0];/* List of scatter/gather buffers */
|
||||
} blkdev_request;
|
||||
|
||||
/* Block device IOCTL request codes */
|
||||
#define BLKIO_REQUEST _IOWR('B', 1, blkdev_request)
|
||||
#define BLKIO_GETBLKSIZE _IO('B', 2)
|
||||
#define BLKIO_GETSIZE _IO('B', 3)
|
||||
#define BLKIO_SYNCDEV _IO('B', 4)
|
||||
|
||||
/* Device driver interface conventions suppose that driver may
|
||||
* contain initialize/open/close/read/write/ioctl entry points. These
|
||||
* primitives (except initialize) can be implemented in generic fashion,
|
||||
* based upon supplied block device driver ioctl handler. Every block
|
||||
* device driver should provide initialize entry point, which is register
|
||||
* all block devices and appropriate ioctl handlers.
|
||||
*/
|
||||
|
||||
#define GENERIC_BLOCK_DEVICE_DRIVER_ENTRIES \
|
||||
rtems_blkdev_generic_open, rtems_blkdev_generic_close, \
|
||||
rtems_blkdev_generic_read, rtems_blkdev_generic_write, \
|
||||
rtems_blkdev_generic_ioctl
|
||||
|
||||
/* blkdev_generic_read --
|
||||
* Generic block device read primitive. Implemented using block device
|
||||
* buffer management primitives.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_read(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
);
|
||||
|
||||
/* blkdev_generic_write --
|
||||
* Generic block device driver write primitive. Implemented using block
|
||||
* device buffer management primitives.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_write(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
);
|
||||
|
||||
/* blkdev_generic_open --
|
||||
* Generic block device open primitive.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_open(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
);
|
||||
|
||||
/* blkdev_generic_close --
|
||||
* Generic block device close primitive.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_close(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
);
|
||||
|
||||
/* blkdev_generic_ioctl --
|
||||
* Generic block device ioctl primitive.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_ioctl(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
206
c/src/exec/libblock/include/rtems/diskdevs.h
Normal file
206
c/src/exec/libblock/include/rtems/diskdevs.h
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* logdisk.h - Physical and logical block devices (disks) support
|
||||
*
|
||||
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||
* Author: Victor V. Vengerov <vvv@oktet.ru>
|
||||
*
|
||||
* @(#) $Id$
|
||||
*/
|
||||
|
||||
#ifndef __RTEMS_LIBBLOCK_LOGDISK_H__
|
||||
#define __RTEMS_LIBBLOCK_LOGDISK_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "rtems/blkdev.h"
|
||||
|
||||
/* Buffer pool identifier */
|
||||
typedef int rtems_bdpool_id;
|
||||
|
||||
/* Block device ioctl handler */
|
||||
typedef int (* block_device_ioctl) (dev_t dev, int req, void *argp);
|
||||
|
||||
/* disk_device: Entry of this type created for every disk device (both for
|
||||
* logical and physical disks).
|
||||
* Array of arrays of pointers to disk_device structures maintained. First
|
||||
* table indexed by major number and second table indexed by minor number.
|
||||
* Such data organization allow quick lookup using data structure of
|
||||
* moderated size.
|
||||
*/
|
||||
typedef struct disk_device {
|
||||
dev_t dev; /* Device ID (major + minor) */
|
||||
struct disk_device *phys_dev; /* Physical device ID (the same
|
||||
as dev if this entry specifies
|
||||
the physical device) */
|
||||
char *name; /* Disk device name */
|
||||
int uses; /* Use counter. Device couldn't be
|
||||
removed if it is in use. */
|
||||
int start; /* Starting block number (0 for
|
||||
physical devices, block offset
|
||||
on the related physical device
|
||||
for logical device) */
|
||||
int size; /* Size of physical or logical disk
|
||||
in disk blocks */
|
||||
int block_size; /* Size of device block (minimum
|
||||
transfer unit) in bytes
|
||||
(must be power of 2) */
|
||||
int block_size_log2; /* log2 of block_size */
|
||||
rtems_bdpool_id pool; /* Buffer pool assigned to this
|
||||
device */
|
||||
block_device_ioctl ioctl; /* ioctl handler for this block
|
||||
device */
|
||||
} disk_device;
|
||||
|
||||
/* rtems_disk_create_phys --
|
||||
* Create physical disk entry. This function usually invoked from
|
||||
* block device driver initialization code when physical device
|
||||
* detected in the system. Device driver should provide ioctl handler
|
||||
* to allow block device access operations. This primitive will register
|
||||
* device in rtems (invoke rtems_io_register_name).
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device identifier (major, minor numbers)
|
||||
* block_size - size of disk block (minimum data transfer unit); must be
|
||||
* power of 2
|
||||
* disk_size - number of blocks on device
|
||||
* handler - IOCTL handler (function providing basic block input/output
|
||||
* request handling BIOREQUEST and other device management
|
||||
* operations)
|
||||
* name - character name of device (e.g. /dev/hda)
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if information about new physical disk added, or
|
||||
* error code if error occured (device already registered, wrong block
|
||||
* size value, no memory available).
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_create_phys(dev_t dev, int block_size, int disk_size,
|
||||
block_device_ioctl handler,
|
||||
char *name);
|
||||
|
||||
/* rtems_disk_create_log --
|
||||
* Create logical disk entry. Logical disk is contiguous area on physical
|
||||
* disk. Disk may be splitted to several logical disks in several ways:
|
||||
* manually or using information stored in blocks on physical disk
|
||||
* (DOS-like partition table, BSD disk label, etc). This function usually
|
||||
* invoked from application when application-specific splitting are in use,
|
||||
* or from generic code which handle different logical disk organizations.
|
||||
* This primitive will register device in rtems (invoke
|
||||
* rtems_io_register_name).
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - logical device identifier (major, minor numbers)
|
||||
* phys - physical device (block device which holds this logical disk)
|
||||
* identifier
|
||||
* start - starting block number on the physical device
|
||||
* size - logical disk size in blocks
|
||||
* name - logical disk name
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if logical device successfully added, or error code
|
||||
* if error occured (device already registered, no physical device
|
||||
* exists, logical disk is out of physical disk boundaries, no memory
|
||||
* available).
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_create_log(dev_t dev, dev_t phys, int start, int size, char *name);
|
||||
|
||||
/* rtems_disk_delete --
|
||||
* Delete physical or logical disk device. Device may be deleted if its
|
||||
* use counter (and use counters of all logical devices - if it is
|
||||
* physical device) equal to 0. When physical device deleted,
|
||||
* all logical devices deleted inherently. Appropriate devices removed
|
||||
* from "/dev" filesystem.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device identifier (major, minor numbers)
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if block device successfully deleted, or error code
|
||||
* if error occured (device is not defined, device is in use).
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_delete(dev_t dev);
|
||||
|
||||
/* rtems_disk_lookup --
|
||||
* Find block device descriptor by its device identifier. This function
|
||||
* increment usage counter to 1. User should release disk_device structure
|
||||
* by invoking rtems_disk_release primitive.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device identifier (major, minor numbers)
|
||||
*
|
||||
* RETURNS:
|
||||
* pointer to the block device descriptor, or NULL if no such device
|
||||
* exists.
|
||||
*/
|
||||
disk_device *
|
||||
rtems_disk_lookup(dev_t dev);
|
||||
|
||||
/* rtems_disk_release --
|
||||
* Release disk_device structure (decrement usage counter to 1).
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dd - pointer to disk device structure
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL
|
||||
*
|
||||
* NOTE:
|
||||
* It should be implemented as inline function.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_release(disk_device *dd);
|
||||
|
||||
/* rtems_disk_next --
|
||||
* Disk device enumerator. Looking for device having device number larger
|
||||
* than dev and return disk device descriptor for it. If there are no
|
||||
* such device, NULL value returned.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device number (use -1 to start search)
|
||||
*
|
||||
* RETURNS:
|
||||
* Pointer to the disk descriptor for next disk device, or NULL if all
|
||||
* devices enumerated. */
|
||||
disk_device *
|
||||
rtems_disk_next(dev_t dev);
|
||||
|
||||
/* rtems_diskio_initialize --
|
||||
* Initialization of disk device library (initialize all data structures,
|
||||
* etc.)
|
||||
*
|
||||
* PARAMETERS:
|
||||
* none
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if library initialized, or error code if error
|
||||
* occured.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_io_initialize(void);
|
||||
|
||||
/* rtems_diskio_done --
|
||||
* Release all resources allocated for disk device interface.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* none
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if all resources released, or error code if error
|
||||
* occured.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_io_done(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
52
c/src/exec/libblock/include/rtems/ramdisk.h
Normal file
52
c/src/exec/libblock/include/rtems/ramdisk.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* ramdisk.c -- RAM disk block device implementation
|
||||
*
|
||||
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||
* Author: Victor V. Vengerov <vvv@oktet.ru>
|
||||
*
|
||||
* @(#) $Id$
|
||||
*/
|
||||
|
||||
#ifndef __RTEMS_LIBBLOCK_RAMDISK_H__
|
||||
#define __RTEMS_LIBBLOCK_RAMDISK_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <rtems.h>
|
||||
|
||||
#include "rtems/blkdev.h"
|
||||
|
||||
/* RAM disk configuration table entry */
|
||||
typedef struct rtems_ramdisk_config {
|
||||
int block_size; /* RAM disk block size */
|
||||
int block_num; /* Number of blocks on this RAM disk */
|
||||
void *location; /* RAM disk permanent location (out of RTEMS controlled
|
||||
memory), or NULL if RAM disk memory should be
|
||||
allocated dynamically */
|
||||
} rtems_ramdisk_config;
|
||||
|
||||
/* If application want to use RAM disk, it should specify configuration of
|
||||
* available RAM disks.
|
||||
* The following is definitions for RAM disk configuration table
|
||||
*/
|
||||
extern rtems_ramdisk_config rtems_ramdisk_configuration[];
|
||||
extern int rtems_ramdisk_configuration_size;
|
||||
|
||||
/* ramdisk_initialize --
|
||||
* RAM disk driver initialization entry point.
|
||||
*/
|
||||
rtems_device_driver
|
||||
ramdisk_initialize(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *arg);
|
||||
|
||||
#define RAMDISK_DRIVER_TABLE_ENTRY \
|
||||
{ ramdisk_initialize, GENERIC_BLOCK_DEVICE_DRIVER_ENTRIES }
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
2
c/src/exec/libblock/src/.cvsignore
Normal file
2
c/src/exec/libblock/src/.cvsignore
Normal file
@@ -0,0 +1,2 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
33
c/src/exec/libblock/src/Makefile.am
Normal file
33
c/src/exec/libblock/src/Makefile.am
Normal file
@@ -0,0 +1,33 @@
|
||||
##
|
||||
## $Id$
|
||||
##
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign 1.5
|
||||
|
||||
LIBNAME = libblock
|
||||
LIB = ${ARCH}/${LIBNAME}.a
|
||||
|
||||
C_FILES = bdbuf.c blkdev.c diskdevs.c ramdisk.c
|
||||
|
||||
C_O_FILES = $(C_FILES:%.c=${ARCH}/%.o)
|
||||
|
||||
SRCS = $(C_FILES)
|
||||
OBJS = $(C_O_FILES)
|
||||
|
||||
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
|
||||
include $(top_srcdir)/../../../automake/compile.am
|
||||
include $(top_srcdir)/../../../automake/lib.am
|
||||
|
||||
AM_CFLAGS += $(LIBC_DEFINES)
|
||||
|
||||
TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a
|
||||
|
||||
$(LIB): ${OBJS}
|
||||
$(make-library)
|
||||
|
||||
$(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a: $(LIB)
|
||||
$(INSTALL_DATA) $< $@
|
||||
|
||||
all-local: ${ARCH} $(PREINSTALL_FILES) $(TMPINSTALL_FILES)
|
||||
|
||||
include $(top_srcdir)/../../../automake/local.am
|
||||
1876
c/src/exec/libblock/src/bdbuf.c
Normal file
1876
c/src/exec/libblock/src/bdbuf.c
Normal file
File diff suppressed because it is too large
Load Diff
243
c/src/exec/libblock/src/blkdev.c
Normal file
243
c/src/exec/libblock/src/blkdev.c
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* blkdev.h - block device driver generic support
|
||||
*
|
||||
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||
* Author: Victor V. Vengerov <vvv@oktet.ru>
|
||||
*
|
||||
* @(#) $Id$
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "rtems/diskdevs.h"
|
||||
#include "rtems/bdbuf.h"
|
||||
|
||||
/* rtems_blkdev_generic_read --
|
||||
* Generic block device read primitive. Implemented using block device
|
||||
* buffer management primitives.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_read(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg)
|
||||
{
|
||||
rtems_libio_rw_args_t *args = arg;
|
||||
int block_size_log2;
|
||||
int block_size;
|
||||
char *buf;
|
||||
unsigned int count;
|
||||
unsigned int block;
|
||||
unsigned int blkofs;
|
||||
dev_t dev;
|
||||
disk_device *dd;
|
||||
|
||||
dev = rtems_filesystem_make_dev_t(major, minor);
|
||||
dd = rtems_disk_lookup(dev);
|
||||
if (dd == NULL)
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
|
||||
block_size_log2 = dd->block_size_log2;
|
||||
block_size = dd->block_size;
|
||||
|
||||
buf = args->buffer;
|
||||
count = args->count;
|
||||
args->bytes_moved = 0;
|
||||
|
||||
block = args->offset >> block_size_log2;
|
||||
blkofs = args->offset & (block_size - 1);
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
bdbuf_buffer *diskbuf;
|
||||
int copy;
|
||||
rtems_status_code rc;
|
||||
|
||||
rc = rtems_bdbuf_read(dev, block, &diskbuf);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
return rc;
|
||||
copy = block_size - blkofs;
|
||||
if (copy > count)
|
||||
copy = count;
|
||||
memcpy(buf, (char *)diskbuf->buffer + blkofs, copy);
|
||||
rc = rtems_bdbuf_release(diskbuf);
|
||||
args->bytes_moved += copy;
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
return rc;
|
||||
count -= copy;
|
||||
buf += copy;
|
||||
blkofs = 0;
|
||||
block++;
|
||||
}
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/* rtems_blkdev_generic_write --
|
||||
* Generic block device write primitive. Implemented using block device
|
||||
* buffer management primitives.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_write(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg)
|
||||
{
|
||||
rtems_libio_rw_args_t *args = arg;
|
||||
int block_size_log2;
|
||||
int block_size;
|
||||
char *buf;
|
||||
unsigned int count;
|
||||
unsigned int block;
|
||||
unsigned int blkofs;
|
||||
dev_t dev;
|
||||
rtems_status_code rc;
|
||||
disk_device *dd;
|
||||
|
||||
dev = rtems_filesystem_make_dev_t(major, minor);
|
||||
dd = rtems_disk_lookup(dev);
|
||||
if (dd == NULL)
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
|
||||
block_size_log2 = dd->block_size_log2;
|
||||
block_size = dd->block_size;
|
||||
|
||||
buf = args->buffer;
|
||||
count = args->count;
|
||||
args->bytes_moved = 0;
|
||||
|
||||
block = args->offset >> block_size_log2;
|
||||
blkofs = args->offset & (block_size - 1);
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
bdbuf_buffer *diskbuf;
|
||||
int copy;
|
||||
|
||||
if ((blkofs == 0) && (count > block_size))
|
||||
rc = rtems_bdbuf_get(dev, block, &diskbuf);
|
||||
else
|
||||
rc = rtems_bdbuf_read(dev, block, &diskbuf);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
return rc;
|
||||
|
||||
copy = block_size - blkofs;
|
||||
if (copy > count)
|
||||
copy = count;
|
||||
memcpy((char *)diskbuf->buffer + blkofs, buf, copy);
|
||||
args->bytes_moved += copy;
|
||||
|
||||
rc = rtems_bdbuf_release_modified(diskbuf);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
return rc;
|
||||
|
||||
count -= copy;
|
||||
buf += copy;
|
||||
blkofs = 0;
|
||||
block++;
|
||||
}
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/* blkdev_generic_open --
|
||||
* Generic block device open primitive.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_open(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg)
|
||||
{
|
||||
dev_t dev;
|
||||
disk_device *dd;
|
||||
|
||||
dev = rtems_filesystem_make_dev_t(major, minor);
|
||||
dd = rtems_disk_lookup(dev);
|
||||
if (dd == NULL)
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
|
||||
dd->uses++;
|
||||
|
||||
rtems_disk_release(dd);
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
|
||||
/* blkdev_generic_close --
|
||||
* Generic block device close primitive.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_close(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg)
|
||||
{
|
||||
dev_t dev;
|
||||
disk_device *dd;
|
||||
|
||||
dev = rtems_filesystem_make_dev_t(major, minor);
|
||||
dd = rtems_disk_lookup(dev);
|
||||
if (dd == NULL)
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
|
||||
dd->uses--;
|
||||
|
||||
rtems_disk_release(dd);
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/* blkdev_generic_ioctl --
|
||||
* Generic block device ioctl primitive.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_ioctl(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg)
|
||||
{
|
||||
rtems_libio_ioctl_args_t *args = arg;
|
||||
dev_t dev;
|
||||
disk_device *dd;
|
||||
int rc;
|
||||
|
||||
dev = rtems_filesystem_make_dev_t(major, minor);
|
||||
dd = rtems_disk_lookup(dev);
|
||||
if (dd == NULL)
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
|
||||
switch (args->command)
|
||||
{
|
||||
case BLKIO_GETBLKSIZE:
|
||||
args->ioctl_return = dd->block_size;
|
||||
break;
|
||||
|
||||
case BLKIO_GETSIZE:
|
||||
args->ioctl_return = dd->size;
|
||||
break;
|
||||
|
||||
case BLKIO_SYNCDEV:
|
||||
rc = rtems_bdbuf_syncdev(dd->dev);
|
||||
args->ioctl_return = (rc == RTEMS_SUCCESSFUL ? 0 : -1);
|
||||
break;
|
||||
|
||||
case BLKIO_REQUEST:
|
||||
{
|
||||
blkdev_request *req = args->buffer;
|
||||
req->start += dd->start;
|
||||
args->ioctl_return = dd->ioctl(dd->phys_dev->dev, args->command,
|
||||
req);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
args->ioctl_return = dd->ioctl(dd->phys_dev->dev, args->command,
|
||||
args->buffer);
|
||||
break;
|
||||
}
|
||||
rtems_disk_release(dd);
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
631
c/src/exec/libblock/src/diskdevs.c
Normal file
631
c/src/exec/libblock/src/diskdevs.c
Normal file
@@ -0,0 +1,631 @@
|
||||
/*
|
||||
* diskdevs.c - Physical and logical block devices (disks) support
|
||||
*
|
||||
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||
* Author: Victor V. Vengerov <vvv@oktet.ru>
|
||||
*
|
||||
* @(#) $Id$
|
||||
*/
|
||||
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "rtems/diskdevs.h"
|
||||
#include "rtems/bdbuf.h"
|
||||
|
||||
#define DISKTAB_INITIAL_SIZE 32
|
||||
|
||||
/* Table of disk devices having the same major number */
|
||||
struct disk_device_table {
|
||||
disk_device **minor; /* minor-indexed disk device table */
|
||||
int size; /* Number of entries in the table */
|
||||
};
|
||||
|
||||
/* Pointer to [major].minor[minor] indexed array of disk devices */
|
||||
static struct disk_device_table *disktab;
|
||||
|
||||
/* Number of allocated entries in disktab table */
|
||||
static int disktab_size;
|
||||
|
||||
/* Mutual exclusion semaphore for disk devices table */
|
||||
static rtems_id diskdevs_mutex;
|
||||
|
||||
/* Flag meaning that disk I/O, buffering etc. already has been initialized. */
|
||||
static boolean disk_io_initialized = FALSE;
|
||||
|
||||
/* diskdevs data structures protection flag.
|
||||
* Normally, only table lookup operations performed. It is quite fast, so
|
||||
* it is possible to done lookups when interrupts are disabled, avoiding
|
||||
* obtaining the semaphore. This flags sets immediately after entering in
|
||||
* mutex-protected section and cleared before leaving this section in
|
||||
* "big" primitives like add/delete new device etc. Lookup function first
|
||||
* disable interrupts and check this flag. If it is set, lookup function
|
||||
* will be blocked on semaphore and lookup operation will be performed in
|
||||
* semaphore-protected code. If it is not set (very-very frequent case),
|
||||
* we can do lookup safely, enable interrupts and return result.
|
||||
*/
|
||||
static volatile rtems_boolean diskdevs_protected;
|
||||
|
||||
/* create_disk_entry --
|
||||
* Return pointer to the disk_entry structure for the specified device, or
|
||||
* create one if it is not exists.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device id (major, minor)
|
||||
*
|
||||
* RETURNS:
|
||||
* pointer to the disk device descirptor entry, or NULL if no memory
|
||||
* available for its creation.
|
||||
*/
|
||||
static disk_device *
|
||||
create_disk_entry(dev_t dev)
|
||||
{
|
||||
rtems_device_major_number major;
|
||||
rtems_device_minor_number minor;
|
||||
struct disk_device **d;
|
||||
|
||||
rtems_filesystem_split_dev_t (dev, major, minor);
|
||||
|
||||
if (major >= disktab_size)
|
||||
{
|
||||
struct disk_device_table *p;
|
||||
int newsize;
|
||||
int i;
|
||||
newsize = disktab_size * 2;
|
||||
if (major >= newsize)
|
||||
newsize = major + 1;
|
||||
p = realloc(disktab, sizeof(struct disk_device_table) * newsize);
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
p += disktab_size;
|
||||
for (i = disktab_size; i < newsize; i++, p++)
|
||||
{
|
||||
p->minor = NULL;
|
||||
p->size = 0;
|
||||
}
|
||||
disktab_size = newsize;
|
||||
}
|
||||
|
||||
if ((disktab[major].minor == NULL) ||
|
||||
(minor >= disktab[major].size))
|
||||
{
|
||||
int newsize;
|
||||
disk_device **p;
|
||||
int i;
|
||||
int s = disktab[major].size;
|
||||
|
||||
if (s == 0)
|
||||
newsize = DISKTAB_INITIAL_SIZE;
|
||||
else
|
||||
newsize = s * 2;
|
||||
if (minor >= newsize)
|
||||
newsize = minor + 1;
|
||||
|
||||
p = realloc(disktab[major].minor, sizeof(disk_device *) * newsize);
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
disktab[major].minor = p;
|
||||
p += s;
|
||||
for (i = s; i < newsize; i++, p++)
|
||||
*p = NULL;
|
||||
disktab[major].size = newsize;
|
||||
}
|
||||
|
||||
d = disktab[major].minor + minor;
|
||||
if (*d == NULL)
|
||||
{
|
||||
*d = calloc(1, sizeof(disk_device));
|
||||
}
|
||||
return *d;
|
||||
}
|
||||
|
||||
/* get_disk_entry --
|
||||
* Get disk device descriptor by device number.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - block device number
|
||||
*
|
||||
* RETURNS:
|
||||
* Pointer to the disk device descriptor corresponding to the specified
|
||||
* device number, or NULL if disk device with such number not exists.
|
||||
*/
|
||||
static inline disk_device *
|
||||
get_disk_entry(dev_t dev)
|
||||
{
|
||||
rtems_device_major_number major;
|
||||
rtems_device_minor_number minor;
|
||||
struct disk_device_table *dtab;
|
||||
|
||||
rtems_filesystem_split_dev_t (dev, major, minor);
|
||||
|
||||
if ((major >= disktab_size) || (disktab == NULL))
|
||||
return NULL;
|
||||
|
||||
dtab = disktab + major;
|
||||
|
||||
if ((minor >= dtab->size) || (dtab->minor == NULL))
|
||||
return NULL;
|
||||
|
||||
return dtab->minor[minor];
|
||||
}
|
||||
|
||||
/* create_disk --
|
||||
* Check that disk entry for specified device number is not defined
|
||||
* and create it.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device identifier (major, minor numbers)
|
||||
* name - character name of device (e.g. /dev/hda)
|
||||
* disdev - placeholder for pointer to created disk descriptor
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if disk entry successfully created, or
|
||||
* error code if error occured (device already registered,
|
||||
* no memory available).
|
||||
*/
|
||||
static rtems_status_code
|
||||
create_disk(dev_t dev, char *name, disk_device **diskdev)
|
||||
{
|
||||
disk_device *dd;
|
||||
char *n;
|
||||
|
||||
dd = get_disk_entry(dev);
|
||||
if (dd != NULL)
|
||||
{
|
||||
return RTEMS_RESOURCE_IN_USE;
|
||||
}
|
||||
|
||||
if (name == NULL)
|
||||
{
|
||||
n = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
int nlen = strlen(name) + 1;
|
||||
n = malloc(nlen);
|
||||
if (n == NULL)
|
||||
return RTEMS_NO_MEMORY;
|
||||
strncpy(n, name, nlen);
|
||||
}
|
||||
|
||||
dd = create_disk_entry(dev);
|
||||
if (dd == NULL)
|
||||
{
|
||||
free(n);
|
||||
return RTEMS_NO_MEMORY;
|
||||
}
|
||||
|
||||
dd->dev = dev;
|
||||
dd->name = n;
|
||||
|
||||
*diskdev = dd;
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/* rtems_disk_create_phys --
|
||||
* Create physical disk entry. This function usually invoked from
|
||||
* block device driver initialization code when physical device
|
||||
* detected in the system. Device driver should provide ioctl handler
|
||||
* to allow block device access operations. This primitive will register
|
||||
* device in rtems (invoke rtems_io_register_name).
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device identifier (major, minor numbers)
|
||||
* block_size - size of disk block (minimum data transfer unit); must be
|
||||
* power of 2
|
||||
* disk_size - number of blocks on device
|
||||
* handler - IOCTL handler (function providing basic block input/output
|
||||
* request handling BIOREQUEST and other device management
|
||||
* operations)
|
||||
* name - character name of device (e.g. /dev/hda)
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if information about new physical disk added, or
|
||||
* error code if error occured (device already registered, wrong block
|
||||
* size value, no memory available).
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_create_phys(dev_t dev, int block_size, int disk_size,
|
||||
block_device_ioctl handler,
|
||||
char *name)
|
||||
{
|
||||
int bs_log2;
|
||||
int i;
|
||||
disk_device *dd;
|
||||
rtems_status_code rc;
|
||||
rtems_bdpool_id pool;
|
||||
rtems_device_major_number major;
|
||||
rtems_device_minor_number minor;
|
||||
|
||||
rtems_filesystem_split_dev_t (dev, major, minor);
|
||||
|
||||
|
||||
for (bs_log2 = 0, i = block_size; (i & 1) == 0; i >>= 1, bs_log2++);
|
||||
if ((bs_log2 < 9) || (i != 1)) /* block size < 512 or not power of 2 */
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
|
||||
rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
return rc;
|
||||
diskdevs_protected = TRUE;
|
||||
|
||||
rc = rtems_bdbuf_find_pool(block_size, &pool);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
diskdevs_protected = FALSE;
|
||||
rtems_semaphore_release(diskdevs_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = create_disk(dev, name, &dd);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
diskdevs_protected = FALSE;
|
||||
rtems_semaphore_release(diskdevs_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
dd->phys_dev = dd;
|
||||
dd->uses = 0;
|
||||
dd->start = 0;
|
||||
dd->size = disk_size;
|
||||
dd->block_size = block_size;
|
||||
dd->block_size_log2 = bs_log2;
|
||||
dd->ioctl = handler;
|
||||
dd->pool = pool;
|
||||
|
||||
rc = rtems_io_register_name(name, major, minor);
|
||||
|
||||
diskdevs_protected = FALSE;
|
||||
rtems_semaphore_release(diskdevs_mutex);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* rtems_disk_create_log --
|
||||
* Create logical disk entry. Logical disk is contiguous area on physical
|
||||
* disk. Disk may be splitted to several logical disks in several ways:
|
||||
* manually or using information stored in blocks on physical disk
|
||||
* (DOS-like partition table, BSD disk label, etc). This function usually
|
||||
* invoked from application when application-specific splitting are in use,
|
||||
* or from generic code which handle different logical disk organizations.
|
||||
* This primitive will register device in rtems (invoke
|
||||
* rtems_io_register_name).
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - logical device identifier (major, minor numbers)
|
||||
* phys - physical device (block device which holds this logical disk)
|
||||
* identifier
|
||||
* start - starting block number on the physical device
|
||||
* size - logical disk size in blocks
|
||||
* name - logical disk name
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if logical device successfully added, or error code
|
||||
* if error occured (device already registered, no physical device
|
||||
* exists, logical disk is out of physical disk boundaries, no memory
|
||||
* available).
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_create_log(dev_t dev, dev_t phys, int start, int size, char *name)
|
||||
{
|
||||
disk_device *dd;
|
||||
disk_device *pdd;
|
||||
rtems_status_code rc;
|
||||
rtems_device_major_number major;
|
||||
rtems_device_minor_number minor;
|
||||
|
||||
rtems_filesystem_split_dev_t (dev, major, minor);
|
||||
|
||||
rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
return rc;
|
||||
diskdevs_protected = TRUE;
|
||||
|
||||
pdd = get_disk_entry(phys);
|
||||
if (pdd == NULL)
|
||||
{
|
||||
diskdevs_protected = FALSE;
|
||||
rtems_semaphore_release(diskdevs_mutex);
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
}
|
||||
|
||||
rc = create_disk(dev, name, &dd);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
diskdevs_protected = FALSE;
|
||||
rtems_semaphore_release(diskdevs_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
dd->phys_dev = pdd;
|
||||
dd->uses = 0;
|
||||
dd->start = start;
|
||||
dd->size = size;
|
||||
dd->block_size = pdd->block_size;
|
||||
dd->block_size_log2 = pdd->block_size_log2;
|
||||
dd->ioctl = pdd->ioctl;
|
||||
|
||||
rc = rtems_io_register_name(name, major, minor);
|
||||
|
||||
diskdevs_protected = FALSE;
|
||||
rc = rtems_semaphore_release(diskdevs_mutex);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* rtems_disk_delete --
|
||||
* Delete physical or logical disk device. Device may be deleted if its
|
||||
* use counter (and use counters of all logical devices - if it is
|
||||
* physical device) equal to 0. When physical device deleted,
|
||||
* all logical devices deleted inherently. Appropriate devices removed
|
||||
* from "/dev" filesystem.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device identifier (major, minor numbers)
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if block device successfully deleted, or error code
|
||||
* if error occured (device is not defined, device is in use).
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_delete(dev_t dev)
|
||||
{
|
||||
rtems_status_code rc;
|
||||
int used;
|
||||
rtems_device_major_number maj;
|
||||
rtems_device_minor_number min;
|
||||
|
||||
rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
return rc;
|
||||
diskdevs_protected = TRUE;
|
||||
|
||||
/* Check if this device is in use -- calculate usage counter */
|
||||
used = 0;
|
||||
for (maj = 0; maj < disktab_size; maj++)
|
||||
{
|
||||
struct disk_device_table *dtab = disktab + maj;
|
||||
if (dtab != NULL)
|
||||
{
|
||||
for (min = 0; min < dtab->size; min++)
|
||||
{
|
||||
disk_device *dd = dtab->minor[min];
|
||||
if ((dd != NULL) && (dd->phys_dev->dev == dev))
|
||||
used += dd->uses;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (used != 0)
|
||||
{
|
||||
diskdevs_protected = FALSE;
|
||||
rtems_semaphore_release(diskdevs_mutex);
|
||||
return RTEMS_RESOURCE_IN_USE;
|
||||
}
|
||||
|
||||
/* Delete this device and all of its logical devices */
|
||||
for (maj = 0; maj < disktab_size; maj++)
|
||||
{
|
||||
struct disk_device_table *dtab = disktab +maj;
|
||||
if (dtab != NULL)
|
||||
{
|
||||
for (min = 0; min < dtab->size; min++)
|
||||
{
|
||||
disk_device *dd = dtab->minor[min];
|
||||
if ((dd != NULL) && (dd->phys_dev->dev == dev))
|
||||
{
|
||||
unlink(dd->name);
|
||||
free(dd->name);
|
||||
free(dd);
|
||||
dtab->minor[min] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
diskdevs_protected = FALSE;
|
||||
rc = rtems_semaphore_release(diskdevs_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* rtems_disk_lookup --
|
||||
* Find block device descriptor by its device identifier.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device identifier (major, minor numbers)
|
||||
*
|
||||
* RETURNS:
|
||||
* pointer to the block device descriptor, or NULL if no such device
|
||||
* exists.
|
||||
*/
|
||||
disk_device *
|
||||
rtems_disk_lookup(dev_t dev)
|
||||
{
|
||||
rtems_interrupt_level level;
|
||||
disk_device *dd;
|
||||
rtems_status_code rc;
|
||||
|
||||
rtems_interrupt_disable(level);
|
||||
if (diskdevs_protected)
|
||||
{
|
||||
rtems_interrupt_enable(level);
|
||||
rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT,
|
||||
RTEMS_NO_TIMEOUT);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
return NULL;
|
||||
diskdevs_protected = TRUE;
|
||||
dd = get_disk_entry(dev);
|
||||
dd->uses++;
|
||||
diskdevs_protected = FALSE;
|
||||
rtems_semaphore_release(diskdevs_mutex);
|
||||
return dd;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Frequent and quickest case */
|
||||
dd = get_disk_entry(dev);
|
||||
dd->uses++;
|
||||
rtems_interrupt_enable(level);
|
||||
return dd;
|
||||
}
|
||||
}
|
||||
|
||||
/* rtems_disk_release --
|
||||
* Release disk_device structure (decrement usage counter to 1).
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dd - pointer to disk device structure
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_release(disk_device *dd)
|
||||
{
|
||||
rtems_interrupt_level level;
|
||||
rtems_interrupt_disable(level);
|
||||
dd->uses--;
|
||||
rtems_interrupt_enable(level);
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/* rtems_disk_next --
|
||||
* Disk device enumerator. Looking for device having device number larger
|
||||
* than dev and return disk device descriptor for it. If there are no
|
||||
* such device, NULL value returned.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device number (use -1 to start search)
|
||||
*
|
||||
* RETURNS:
|
||||
* Pointer to the disk descriptor for next disk device, or NULL if all
|
||||
* devices enumerated.
|
||||
*/
|
||||
disk_device *
|
||||
rtems_disk_next(dev_t dev)
|
||||
{
|
||||
rtems_device_major_number major;
|
||||
rtems_device_minor_number minor;
|
||||
struct disk_device_table *dtab;
|
||||
|
||||
dev++;
|
||||
rtems_filesystem_split_dev_t (dev, major, minor);
|
||||
|
||||
if (major >= disktab_size)
|
||||
return NULL;
|
||||
|
||||
dtab = disktab + major;
|
||||
while (TRUE)
|
||||
{
|
||||
if ((dtab == NULL) || (minor > dtab->size))
|
||||
{
|
||||
major++; minor = 0;
|
||||
if (major >= disktab_size)
|
||||
return NULL;
|
||||
dtab = disktab + major;
|
||||
}
|
||||
else if (dtab->minor[minor] == NULL)
|
||||
{
|
||||
minor++;
|
||||
}
|
||||
else
|
||||
return dtab->minor[minor];
|
||||
}
|
||||
}
|
||||
|
||||
/* rtems_disk_initialize --
|
||||
* Initialization of disk device library (initialize all data structures,
|
||||
* etc.)
|
||||
*
|
||||
* PARAMETERS:
|
||||
* none
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if library initialized, or error code if error
|
||||
* occured.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_io_initialize(void)
|
||||
{
|
||||
rtems_status_code rc;
|
||||
|
||||
if (disk_io_initialized)
|
||||
return RTEMS_SUCCESSFUL;
|
||||
|
||||
disktab_size = DISKTAB_INITIAL_SIZE;
|
||||
disktab = calloc(disktab_size, sizeof(struct disk_device_table));
|
||||
if (disktab == NULL)
|
||||
return RTEMS_NO_MEMORY;
|
||||
|
||||
diskdevs_protected = FALSE;
|
||||
rc = rtems_semaphore_create(
|
||||
rtems_build_name('D', 'D', 'E', 'V'), 1,
|
||||
RTEMS_FIFO | RTEMS_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY |
|
||||
RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL, 0, &diskdevs_mutex);
|
||||
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
free(disktab);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = rtems_bdbuf_init(rtems_bdbuf_configuration,
|
||||
rtems_bdbuf_configuration_size);
|
||||
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
rtems_semaphore_delete(diskdevs_mutex);
|
||||
free(disktab);
|
||||
return rc;
|
||||
}
|
||||
|
||||
disk_io_initialized = 1;
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/* rtems_disk_io_done --
|
||||
* Release all resources allocated for disk device interface.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* none
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if all resources released, or error code if error
|
||||
* occured.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_io_done(void)
|
||||
{
|
||||
rtems_device_major_number maj;
|
||||
rtems_device_minor_number min;
|
||||
rtems_status_code rc;
|
||||
|
||||
/* Free data structures */
|
||||
for (maj = 0; maj < disktab_size; maj++)
|
||||
{
|
||||
struct disk_device_table *dtab = disktab + maj;
|
||||
if (dtab != NULL)
|
||||
{
|
||||
for (min = 0; min < dtab->size; min++)
|
||||
{
|
||||
disk_device *dd = dtab->minor[min];
|
||||
unlink(dd->name);
|
||||
free(dd->name);
|
||||
free(dd);
|
||||
}
|
||||
free(dtab);
|
||||
}
|
||||
}
|
||||
free(disktab);
|
||||
|
||||
rc = rtems_semaphore_release(diskdevs_mutex);
|
||||
|
||||
/* XXX bdbuf should be released too! */
|
||||
disk_io_initialized = 0;
|
||||
return rc;
|
||||
}
|
||||
224
c/src/exec/libblock/src/ramdisk.c
Normal file
224
c/src/exec/libblock/src/ramdisk.c
Normal file
@@ -0,0 +1,224 @@
|
||||
/* 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;
|
||||
}
|
||||
14
c/src/libblock/.cvsignore
Normal file
14
c/src/libblock/.cvsignore
Normal file
@@ -0,0 +1,14 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
config.cache
|
||||
config.guess
|
||||
config.log
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
depcomp
|
||||
install-sh
|
||||
missing
|
||||
mkinstalldirs
|
||||
25
c/src/libblock/ChangeLog
Normal file
25
c/src/libblock/ChangeLog
Normal file
@@ -0,0 +1,25 @@
|
||||
2002-02-28 Joel Sherrill <joel@OARcorp.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2001-11-29 Victor V. Vengerov <vvv@oktet.ru>
|
||||
* AVL trees implementation added.
|
||||
|
||||
2001-11-16 Victor V. Vengerov <vvv@oktet.ru>
|
||||
* include/rtems/bdbuf.h, src/bdbuf.c(rtems_bdbuf_syncdev): New.
|
||||
|
||||
2001-11-07 Victor V. Vengerov <vvv@oktet.ru>
|
||||
|
||||
* ChangeLog: New file.
|
||||
* src/, include/, include/rtems/: New directories.
|
||||
* README, configure.ac, Makefile.am, src/Makefile.am,
|
||||
include/Makefile.am: New files.
|
||||
* include/rtems/bdbuf.h include/rtems/blkdev.h
|
||||
include/rtems/diskdevs.h include/rtems/ramdisk.h
|
||||
src/bdbuf.c src/blkdev.c src/diskdevs.c src/ramdisk.c: New files.
|
||||
13
c/src/libblock/Makefile.am
Normal file
13
c/src/libblock/Makefile.am
Normal file
@@ -0,0 +1,13 @@
|
||||
##
|
||||
## $Id$
|
||||
##
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign 1.4
|
||||
ACLOCAL_AMFLAGS = -I ../../../aclocal
|
||||
|
||||
SUBDIRS = include src
|
||||
|
||||
EXTRA_DIST = README
|
||||
|
||||
include $(top_srcdir)/../../../automake/subdirs.am
|
||||
include $(top_srcdir)/../../../automake/local.am
|
||||
14
c/src/libblock/README
Normal file
14
c/src/libblock/README
Normal file
@@ -0,0 +1,14 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
This directory contains the block device (HDD, CDROMs, etc) support code.
|
||||
It includes:
|
||||
- block device driver interface
|
||||
- generic open/close/read/write/ioctl primitives for block device drivers
|
||||
- disk I/O buffering
|
||||
- logical disk support
|
||||
- RAM disk block device driver
|
||||
|
||||
Victor V. Vengerov, <vvv@oktet.ru>
|
||||
November, 7 2001
|
||||
32
c/src/libblock/configure.ac
Normal file
32
c/src/libblock/configure.ac
Normal file
@@ -0,0 +1,32 @@
|
||||
## Process this file with autoconf to produce a configure script.
|
||||
##
|
||||
## $Id$
|
||||
|
||||
AC_PREREQ(2.52)
|
||||
AC_INIT
|
||||
AC_CONFIG_SRCDIR([src/bdbuf.c])
|
||||
RTEMS_TOP(../../..)
|
||||
AC_CONFIG_AUX_DIR(../../..)
|
||||
|
||||
RTEMS_CANONICAL_TARGET_CPU
|
||||
RTEMS_CANONICAL_HOST
|
||||
|
||||
AM_INIT_AUTOMAKE(rtems-c-src-libblock,$RTEMS_VERSION,no)
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
RTEMS_ENV_RTEMSBSP
|
||||
RTEMS_CHECK_CPU
|
||||
RTEMS_CHECK_CUSTOM_BSP(RTEMS_BSP)
|
||||
RTEMS_PROG_CC_FOR_TARGET
|
||||
RTEMS_ENABLE_BARE
|
||||
|
||||
RTEMS_CANONICALIZE_TOOLS
|
||||
|
||||
RTEMS_PROJECT_ROOT
|
||||
|
||||
# Explicitly list all Makefiles here
|
||||
AC_CONFIG_FILES([Makefile
|
||||
include/Makefile
|
||||
src/Makefile
|
||||
])
|
||||
AC_OUTPUT
|
||||
2
c/src/libblock/include/.cvsignore
Normal file
2
c/src/libblock/include/.cvsignore
Normal file
@@ -0,0 +1,2 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
23
c/src/libblock/include/Makefile.am
Normal file
23
c/src/libblock/include/Makefile.am
Normal file
@@ -0,0 +1,23 @@
|
||||
##
|
||||
## $Id$
|
||||
##
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign 1.5
|
||||
|
||||
include_rtemsdir = $(includedir)/rtems
|
||||
|
||||
$(PROJECT_INCLUDE)/%.h: %.h
|
||||
$(INSTALL_DATA) $< $@
|
||||
|
||||
$(PROJECT_INCLUDE)/rtems:
|
||||
@$(mkinstalldirs) $@
|
||||
|
||||
include_rtems_HEADERS = \
|
||||
rtems/bdbuf.h rtems/blkdev.h rtems/diskdevs.h rtems/ramdisk.h
|
||||
|
||||
PREINSTALL_FILES = $(PROJECT_INCLUDE)/rtems \
|
||||
$(include_rtems_HEADERS:%=$(PROJECT_INCLUDE)/%)
|
||||
|
||||
all-local: $(PREINSTALL_FILES)
|
||||
|
||||
include $(top_srcdir)/../../../automake/local.am
|
||||
2
c/src/libblock/include/rtems/.cvsignore
Normal file
2
c/src/libblock/include/rtems/.cvsignore
Normal file
@@ -0,0 +1,2 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
282
c/src/libblock/include/rtems/bdbuf.h
Normal file
282
c/src/libblock/include/rtems/bdbuf.h
Normal file
@@ -0,0 +1,282 @@
|
||||
/* bdbuf.h -- block device buffer management
|
||||
*
|
||||
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||
* Author: Victor V. Vengerov <vvv@oktet.ru>
|
||||
*
|
||||
* @(#) $Id$
|
||||
*/
|
||||
|
||||
#ifndef __RTEMS_LIBBLOCK_BDBUF_H__
|
||||
#define __RTEMS_LIBBLOCK_BDBUF_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <chain.h>
|
||||
|
||||
#include "rtems/blkdev.h"
|
||||
#include "rtems/diskdevs.h"
|
||||
|
||||
|
||||
/*
|
||||
* To manage buffers we using Buffer Descriptors.
|
||||
* To speed-up buffer lookup descriptors are organized in AVL-Tree.
|
||||
* The fields 'dev' and 'block' are search key.
|
||||
*/
|
||||
|
||||
/* Buffer descriptors
|
||||
* Descriptors organized in AVL-tree to speedup buffer lookup.
|
||||
* dev and block fields are search key in AVL-tree.
|
||||
* Modified buffers, free buffers and used buffers linked in 'mod', 'free' and
|
||||
* 'lru' chains appropriately.
|
||||
*/
|
||||
|
||||
typedef struct bdbuf_buffer {
|
||||
Chain_Node link; /* Link in the lru, mod or free chains */
|
||||
|
||||
#ifdef BINARY_TREE
|
||||
struct bdbuf_avl_node {
|
||||
struct bdbuf_buffer *left; /* link to the left sub-tree */
|
||||
struct bdbuf_buffer *right; /* link to the right sub-tree */
|
||||
|
||||
int bf; /* AVL tree node balance factor */
|
||||
} avl; /* AVL-tree links */
|
||||
#else /* AVL TREE */
|
||||
struct bdbuf_avl_node {
|
||||
char cache; /* Cache */
|
||||
|
||||
struct bdbuf_buffer* link[2]; /* Left and Right Kids */
|
||||
|
||||
char bal; /* The balance of the sub-tree */
|
||||
} avl;
|
||||
#endif
|
||||
dev_t dev; /* device number */
|
||||
blkdev_bnum block; /* block number on the device */
|
||||
|
||||
char *buffer; /* Pointer to the buffer memory area */
|
||||
rtems_status_code status; /* Last I/O operation completion status */
|
||||
int error; /* If status != RTEMS_SUCCESSFUL, this field contains
|
||||
errno value which can be used by user later */
|
||||
boolean modified:1; /* =1 if buffer was modified */
|
||||
boolean in_progress:1; /* =1 if exchange with disk is in progress;
|
||||
need to wait on semaphore */
|
||||
boolean actual:1; /* Buffer contains actual data */
|
||||
int use_count; /* Usage counter; incremented when somebody use
|
||||
this buffer; decremented when buffer released
|
||||
without modification or when buffer is flushed
|
||||
by swapout task */
|
||||
|
||||
rtems_bdpool_id pool; /* Identifier of buffer pool to which this buffer
|
||||
belongs */
|
||||
CORE_mutex_Control transfer_sema;
|
||||
/* Transfer operation semaphore */
|
||||
} bdbuf_buffer;
|
||||
|
||||
|
||||
|
||||
/* bdbuf_config structure describes block configuration (size,
|
||||
* amount, memory location) for buffering layer
|
||||
*/
|
||||
typedef struct rtems_bdbuf_config {
|
||||
int size; /* Size of block */
|
||||
int num; /* Number of blocks of appropriate size */
|
||||
char *mem_area; /* Pointer to the blocks location or NULL, in this
|
||||
case memory for blocks will be allocated by
|
||||
Buffering Layer with the help of RTEMS partition
|
||||
manager */
|
||||
} rtems_bdbuf_config;
|
||||
|
||||
extern rtems_bdbuf_config rtems_bdbuf_configuration[];
|
||||
extern int rtems_bdbuf_configuration_size;
|
||||
|
||||
/* rtems_bdbuf_init --
|
||||
* Prepare buffering layer to work - initialize buffer descritors
|
||||
* and (if it is neccessary) buffers. Buffers will be allocated accoriding
|
||||
* to the configuration table, each entry describes kind of block and
|
||||
* amount requested. After initialization all blocks is placed into
|
||||
* free elements lists.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* conf_table - pointer to the buffers configuration table
|
||||
* size - number of entries in configuration table
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
|
||||
* or error code if error is occured)
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_init(rtems_bdbuf_config *conf_table, int size);
|
||||
|
||||
|
||||
/* rtems_bdbuf_get --
|
||||
* Obtain block buffer. If specified block already cached (i.e. there's
|
||||
* block in the _modified_, or _recently_used_), return address
|
||||
* of appropriate buffer descriptor and increment reference counter to 1.
|
||||
* If block is not cached, allocate new buffer and return it. Data
|
||||
* shouldn't be read to the buffer from media; buffer may contains
|
||||
* arbitrary data. This primitive may be blocked if there are no free
|
||||
* buffer descriptors available and there are no unused non-modified
|
||||
* (or synchronized with media) buffers available.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* device - device number (constructed of major and minor device number)
|
||||
* block - linear media block number
|
||||
* bd - address of variable to store pointer to the buffer descriptor
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
|
||||
* or error code if error is occured)
|
||||
*
|
||||
* SIDE EFFECTS:
|
||||
* bufget_sema semaphore obtained by this primitive.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_get(dev_t device, blkdev_bnum block, bdbuf_buffer **bdb_ptr);
|
||||
|
||||
/* rtems_bdbuf_read --
|
||||
* (Similar to the rtems_bdbuf_get, except reading data from media)
|
||||
* Obtain block buffer. If specified block already cached, return address
|
||||
* of appropriate buffer and increment reference counter to 1. If block is
|
||||
* not cached, allocate new buffer and read data to it from the media.
|
||||
* This primitive may be blocked on waiting until data to be read from
|
||||
* media, if there are no free buffer descriptors available and there are
|
||||
* no unused non-modified (or synchronized with media) buffers available.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* device - device number (consists of major and minor device number)
|
||||
* block - linear media block number
|
||||
* bd - address of variable to store pointer to the buffer descriptor
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
|
||||
* or error code if error is occured)
|
||||
*
|
||||
* SIDE EFFECTS:
|
||||
* bufget_sema and transfer_sema semaphores obtained by this primitive.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_read(dev_t device, blkdev_bnum block, bdbuf_buffer **bdb_ptr);
|
||||
|
||||
/* rtems_bdbuf_release --
|
||||
* Release buffer allocated before. This primitive decrease the
|
||||
* usage counter. If it is zero, further destiny of buffer depends on
|
||||
* 'modified' status. If buffer was modified, it is placed to the end of
|
||||
* mod list and flush task waken up. If buffer was not modified,
|
||||
* it is placed to the end of lru list, and bufget_sema released, allowing
|
||||
* to reuse this buffer.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* bd_buf - pointer to the bdbuf_buffer structure previously obtained using
|
||||
* get/read primitive.
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
|
||||
* or error code if error is occured)
|
||||
*
|
||||
* SIDE EFFECTS:
|
||||
* flush_sema and bufget_sema semaphores may be released by this primitive.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_release(bdbuf_buffer *bd_buf);
|
||||
|
||||
/* rtems_bdbuf_release_modified --
|
||||
* Release buffer allocated before, assuming that it is _modified_ by
|
||||
* it's owner. This primitive decrease usage counter for buffer, mark
|
||||
* buffer descriptor as modified. If usage counter is 0, insert it at
|
||||
* end of mod chain and release flush_sema semaphore to activate the
|
||||
* flush task.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* bd_buf - pointer to the bdbuf_buffer structure previously obtained using
|
||||
* get/read primitive.
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
|
||||
* or error code if error is occured)
|
||||
*
|
||||
* SIDE EFFECTS:
|
||||
* flush_sema semaphore may be released by this primitive.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_release_modified(bdbuf_buffer *bd_buf);
|
||||
|
||||
/* rtems_bdbuf_sync --
|
||||
* Wait until specified buffer synchronized with disk. Invoked on exchanges
|
||||
* critical for data consistency on the media. This primitive mark owned
|
||||
* block as modified, decrease usage counter. If usage counter is 0,
|
||||
* block inserted to the mod chain and flush_sema semaphore released.
|
||||
* Finally, primitives blocked on transfer_sema semaphore.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* bd_buf - pointer to the bdbuf_buffer structure previously obtained using
|
||||
* get/read primitive.
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
|
||||
* or error code if error is occured)
|
||||
*
|
||||
* SIDE EFFECTS:
|
||||
* Primitive may be blocked on transfer_sema semaphore.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_sync(bdbuf_buffer *bd_buf);
|
||||
|
||||
/* rtems_bdbuf_syncdev --
|
||||
* Synchronize with disk all buffers containing the blocks belonging to
|
||||
* specified device.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - block device number
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
|
||||
* or error code if error is occured)
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_syncdev(dev_t dev);
|
||||
|
||||
/* rtems_bdbuf_find_pool --
|
||||
* Find first appropriate buffer pool. This primitive returns the index
|
||||
* of first buffer pool which block size is greater than or equal to
|
||||
* specified size.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* block_size - requested block size
|
||||
* pool - placeholder for result
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code: RTEMS_SUCCESSFUL if operation completed successfully,
|
||||
* RTEMS_INVALID_SIZE if specified block size is invalid (not a power
|
||||
* of 2), RTEMS_NOT_DEFINED if buffer pool for this or greater block size
|
||||
* is not configured.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_find_pool(int block_size, rtems_bdpool_id *pool);
|
||||
|
||||
/* rtems_bdbuf_get_pool_info --
|
||||
* Obtain characteristics of buffer pool with specified number.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* pool - buffer pool number
|
||||
* block_size - block size for which buffer pool is configured returned
|
||||
* there
|
||||
* blocks - number of buffers in buffer pool returned there
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code: RTEMS_SUCCESSFUL if operation completed successfully,
|
||||
* RTEMS_INVALID_NUMBER if appropriate buffer pool is not configured.
|
||||
*
|
||||
* NOTE:
|
||||
* Buffer pools enumerated contiguously starting from 0.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_get_pool_info(rtems_bdpool_id pool, int *block_size, int *blocks);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
147
c/src/libblock/include/rtems/blkdev.h
Normal file
147
c/src/libblock/include/rtems/blkdev.h
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* blkdev.h - block device driver interface definitions
|
||||
*
|
||||
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||
* Author: Victor V. Vengerov <vvv@oktet.ru>
|
||||
*
|
||||
* @(#) $Id$
|
||||
*/
|
||||
|
||||
#ifndef __RTEMS_LIBBLOCK_BLKDEV_H__
|
||||
#define __RTEMS_LIBBLOCK_BLKDEV_H__
|
||||
|
||||
#include <rtems.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Interface with device drivers
|
||||
* Block device looks, initialized and behaves like traditional RTEMS device
|
||||
* driver. Heart of the block device driver is in BIOREQUEST ioctl. This call
|
||||
* puts I/O request to the block device queue, in priority order, for
|
||||
* asynchronous processing. When driver executes request, req_done
|
||||
* function invoked, so callee knows about it. Look for details below.
|
||||
*/
|
||||
|
||||
|
||||
/* Block device block number datatype */
|
||||
typedef rtems_unsigned32 blkdev_bnum;
|
||||
|
||||
/* Block device request type */
|
||||
typedef enum blkdev_request_op {
|
||||
BLKDEV_REQ_READ, /* Read operation */
|
||||
BLKDEV_REQ_WRITE /* Write operation */
|
||||
} blkdev_request_op;
|
||||
|
||||
/* Type for block device request done callback function.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* arg - argument supplied in blkdev_request
|
||||
* status - rtems status code for this operation
|
||||
* errno - errno value to be passed to the user when
|
||||
* status != RTEMS_SUCCESSFUL
|
||||
*/
|
||||
typedef void (* blkdev_request_cb)(void *arg,
|
||||
rtems_status_code status,
|
||||
int error);
|
||||
|
||||
/* blkdev_sg_buffer
|
||||
* Block device scatter/gather buffer structure
|
||||
*/
|
||||
typedef struct blkdev_sg_buffer {
|
||||
rtems_unsigned32 length; /* Buffer length */
|
||||
void *buffer; /* Buffer pointer */
|
||||
} blkdev_sg_buffer;
|
||||
|
||||
/* blkdev_request (Block Device Request) structure is
|
||||
* used to read/write a number of blocks from/to device.
|
||||
*/
|
||||
typedef struct blkdev_request {
|
||||
blkdev_request_op req; /* Block device operation (read or write) */
|
||||
blkdev_request_cb req_done; /* Callback function */
|
||||
void *done_arg; /* Argument to be passed to callback function*/
|
||||
blkdev_bnum start; /* Start block number */
|
||||
rtems_unsigned32 count; /* Number of blocks to be exchanged */
|
||||
rtems_unsigned32 bufnum; /* Number of buffers provided */
|
||||
|
||||
blkdev_sg_buffer bufs[0];/* List of scatter/gather buffers */
|
||||
} blkdev_request;
|
||||
|
||||
/* Block device IOCTL request codes */
|
||||
#define BLKIO_REQUEST _IOWR('B', 1, blkdev_request)
|
||||
#define BLKIO_GETBLKSIZE _IO('B', 2)
|
||||
#define BLKIO_GETSIZE _IO('B', 3)
|
||||
#define BLKIO_SYNCDEV _IO('B', 4)
|
||||
|
||||
/* Device driver interface conventions suppose that driver may
|
||||
* contain initialize/open/close/read/write/ioctl entry points. These
|
||||
* primitives (except initialize) can be implemented in generic fashion,
|
||||
* based upon supplied block device driver ioctl handler. Every block
|
||||
* device driver should provide initialize entry point, which is register
|
||||
* all block devices and appropriate ioctl handlers.
|
||||
*/
|
||||
|
||||
#define GENERIC_BLOCK_DEVICE_DRIVER_ENTRIES \
|
||||
rtems_blkdev_generic_open, rtems_blkdev_generic_close, \
|
||||
rtems_blkdev_generic_read, rtems_blkdev_generic_write, \
|
||||
rtems_blkdev_generic_ioctl
|
||||
|
||||
/* blkdev_generic_read --
|
||||
* Generic block device read primitive. Implemented using block device
|
||||
* buffer management primitives.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_read(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
);
|
||||
|
||||
/* blkdev_generic_write --
|
||||
* Generic block device driver write primitive. Implemented using block
|
||||
* device buffer management primitives.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_write(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
);
|
||||
|
||||
/* blkdev_generic_open --
|
||||
* Generic block device open primitive.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_open(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
);
|
||||
|
||||
/* blkdev_generic_close --
|
||||
* Generic block device close primitive.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_close(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
);
|
||||
|
||||
/* blkdev_generic_ioctl --
|
||||
* Generic block device ioctl primitive.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_ioctl(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
206
c/src/libblock/include/rtems/diskdevs.h
Normal file
206
c/src/libblock/include/rtems/diskdevs.h
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* logdisk.h - Physical and logical block devices (disks) support
|
||||
*
|
||||
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||
* Author: Victor V. Vengerov <vvv@oktet.ru>
|
||||
*
|
||||
* @(#) $Id$
|
||||
*/
|
||||
|
||||
#ifndef __RTEMS_LIBBLOCK_LOGDISK_H__
|
||||
#define __RTEMS_LIBBLOCK_LOGDISK_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "rtems/blkdev.h"
|
||||
|
||||
/* Buffer pool identifier */
|
||||
typedef int rtems_bdpool_id;
|
||||
|
||||
/* Block device ioctl handler */
|
||||
typedef int (* block_device_ioctl) (dev_t dev, int req, void *argp);
|
||||
|
||||
/* disk_device: Entry of this type created for every disk device (both for
|
||||
* logical and physical disks).
|
||||
* Array of arrays of pointers to disk_device structures maintained. First
|
||||
* table indexed by major number and second table indexed by minor number.
|
||||
* Such data organization allow quick lookup using data structure of
|
||||
* moderated size.
|
||||
*/
|
||||
typedef struct disk_device {
|
||||
dev_t dev; /* Device ID (major + minor) */
|
||||
struct disk_device *phys_dev; /* Physical device ID (the same
|
||||
as dev if this entry specifies
|
||||
the physical device) */
|
||||
char *name; /* Disk device name */
|
||||
int uses; /* Use counter. Device couldn't be
|
||||
removed if it is in use. */
|
||||
int start; /* Starting block number (0 for
|
||||
physical devices, block offset
|
||||
on the related physical device
|
||||
for logical device) */
|
||||
int size; /* Size of physical or logical disk
|
||||
in disk blocks */
|
||||
int block_size; /* Size of device block (minimum
|
||||
transfer unit) in bytes
|
||||
(must be power of 2) */
|
||||
int block_size_log2; /* log2 of block_size */
|
||||
rtems_bdpool_id pool; /* Buffer pool assigned to this
|
||||
device */
|
||||
block_device_ioctl ioctl; /* ioctl handler for this block
|
||||
device */
|
||||
} disk_device;
|
||||
|
||||
/* rtems_disk_create_phys --
|
||||
* Create physical disk entry. This function usually invoked from
|
||||
* block device driver initialization code when physical device
|
||||
* detected in the system. Device driver should provide ioctl handler
|
||||
* to allow block device access operations. This primitive will register
|
||||
* device in rtems (invoke rtems_io_register_name).
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device identifier (major, minor numbers)
|
||||
* block_size - size of disk block (minimum data transfer unit); must be
|
||||
* power of 2
|
||||
* disk_size - number of blocks on device
|
||||
* handler - IOCTL handler (function providing basic block input/output
|
||||
* request handling BIOREQUEST and other device management
|
||||
* operations)
|
||||
* name - character name of device (e.g. /dev/hda)
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if information about new physical disk added, or
|
||||
* error code if error occured (device already registered, wrong block
|
||||
* size value, no memory available).
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_create_phys(dev_t dev, int block_size, int disk_size,
|
||||
block_device_ioctl handler,
|
||||
char *name);
|
||||
|
||||
/* rtems_disk_create_log --
|
||||
* Create logical disk entry. Logical disk is contiguous area on physical
|
||||
* disk. Disk may be splitted to several logical disks in several ways:
|
||||
* manually or using information stored in blocks on physical disk
|
||||
* (DOS-like partition table, BSD disk label, etc). This function usually
|
||||
* invoked from application when application-specific splitting are in use,
|
||||
* or from generic code which handle different logical disk organizations.
|
||||
* This primitive will register device in rtems (invoke
|
||||
* rtems_io_register_name).
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - logical device identifier (major, minor numbers)
|
||||
* phys - physical device (block device which holds this logical disk)
|
||||
* identifier
|
||||
* start - starting block number on the physical device
|
||||
* size - logical disk size in blocks
|
||||
* name - logical disk name
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if logical device successfully added, or error code
|
||||
* if error occured (device already registered, no physical device
|
||||
* exists, logical disk is out of physical disk boundaries, no memory
|
||||
* available).
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_create_log(dev_t dev, dev_t phys, int start, int size, char *name);
|
||||
|
||||
/* rtems_disk_delete --
|
||||
* Delete physical or logical disk device. Device may be deleted if its
|
||||
* use counter (and use counters of all logical devices - if it is
|
||||
* physical device) equal to 0. When physical device deleted,
|
||||
* all logical devices deleted inherently. Appropriate devices removed
|
||||
* from "/dev" filesystem.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device identifier (major, minor numbers)
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if block device successfully deleted, or error code
|
||||
* if error occured (device is not defined, device is in use).
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_delete(dev_t dev);
|
||||
|
||||
/* rtems_disk_lookup --
|
||||
* Find block device descriptor by its device identifier. This function
|
||||
* increment usage counter to 1. User should release disk_device structure
|
||||
* by invoking rtems_disk_release primitive.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device identifier (major, minor numbers)
|
||||
*
|
||||
* RETURNS:
|
||||
* pointer to the block device descriptor, or NULL if no such device
|
||||
* exists.
|
||||
*/
|
||||
disk_device *
|
||||
rtems_disk_lookup(dev_t dev);
|
||||
|
||||
/* rtems_disk_release --
|
||||
* Release disk_device structure (decrement usage counter to 1).
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dd - pointer to disk device structure
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL
|
||||
*
|
||||
* NOTE:
|
||||
* It should be implemented as inline function.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_release(disk_device *dd);
|
||||
|
||||
/* rtems_disk_next --
|
||||
* Disk device enumerator. Looking for device having device number larger
|
||||
* than dev and return disk device descriptor for it. If there are no
|
||||
* such device, NULL value returned.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device number (use -1 to start search)
|
||||
*
|
||||
* RETURNS:
|
||||
* Pointer to the disk descriptor for next disk device, or NULL if all
|
||||
* devices enumerated. */
|
||||
disk_device *
|
||||
rtems_disk_next(dev_t dev);
|
||||
|
||||
/* rtems_diskio_initialize --
|
||||
* Initialization of disk device library (initialize all data structures,
|
||||
* etc.)
|
||||
*
|
||||
* PARAMETERS:
|
||||
* none
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if library initialized, or error code if error
|
||||
* occured.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_io_initialize(void);
|
||||
|
||||
/* rtems_diskio_done --
|
||||
* Release all resources allocated for disk device interface.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* none
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if all resources released, or error code if error
|
||||
* occured.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_io_done(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
52
c/src/libblock/include/rtems/ramdisk.h
Normal file
52
c/src/libblock/include/rtems/ramdisk.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* ramdisk.c -- RAM disk block device implementation
|
||||
*
|
||||
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||
* Author: Victor V. Vengerov <vvv@oktet.ru>
|
||||
*
|
||||
* @(#) $Id$
|
||||
*/
|
||||
|
||||
#ifndef __RTEMS_LIBBLOCK_RAMDISK_H__
|
||||
#define __RTEMS_LIBBLOCK_RAMDISK_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <rtems.h>
|
||||
|
||||
#include "rtems/blkdev.h"
|
||||
|
||||
/* RAM disk configuration table entry */
|
||||
typedef struct rtems_ramdisk_config {
|
||||
int block_size; /* RAM disk block size */
|
||||
int block_num; /* Number of blocks on this RAM disk */
|
||||
void *location; /* RAM disk permanent location (out of RTEMS controlled
|
||||
memory), or NULL if RAM disk memory should be
|
||||
allocated dynamically */
|
||||
} rtems_ramdisk_config;
|
||||
|
||||
/* If application want to use RAM disk, it should specify configuration of
|
||||
* available RAM disks.
|
||||
* The following is definitions for RAM disk configuration table
|
||||
*/
|
||||
extern rtems_ramdisk_config rtems_ramdisk_configuration[];
|
||||
extern int rtems_ramdisk_configuration_size;
|
||||
|
||||
/* ramdisk_initialize --
|
||||
* RAM disk driver initialization entry point.
|
||||
*/
|
||||
rtems_device_driver
|
||||
ramdisk_initialize(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *arg);
|
||||
|
||||
#define RAMDISK_DRIVER_TABLE_ENTRY \
|
||||
{ ramdisk_initialize, GENERIC_BLOCK_DEVICE_DRIVER_ENTRIES }
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
2
c/src/libblock/src/.cvsignore
Normal file
2
c/src/libblock/src/.cvsignore
Normal file
@@ -0,0 +1,2 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
33
c/src/libblock/src/Makefile.am
Normal file
33
c/src/libblock/src/Makefile.am
Normal file
@@ -0,0 +1,33 @@
|
||||
##
|
||||
## $Id$
|
||||
##
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign 1.5
|
||||
|
||||
LIBNAME = libblock
|
||||
LIB = ${ARCH}/${LIBNAME}.a
|
||||
|
||||
C_FILES = bdbuf.c blkdev.c diskdevs.c ramdisk.c
|
||||
|
||||
C_O_FILES = $(C_FILES:%.c=${ARCH}/%.o)
|
||||
|
||||
SRCS = $(C_FILES)
|
||||
OBJS = $(C_O_FILES)
|
||||
|
||||
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
|
||||
include $(top_srcdir)/../../../automake/compile.am
|
||||
include $(top_srcdir)/../../../automake/lib.am
|
||||
|
||||
AM_CFLAGS += $(LIBC_DEFINES)
|
||||
|
||||
TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a
|
||||
|
||||
$(LIB): ${OBJS}
|
||||
$(make-library)
|
||||
|
||||
$(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a: $(LIB)
|
||||
$(INSTALL_DATA) $< $@
|
||||
|
||||
all-local: ${ARCH} $(PREINSTALL_FILES) $(TMPINSTALL_FILES)
|
||||
|
||||
include $(top_srcdir)/../../../automake/local.am
|
||||
1876
c/src/libblock/src/bdbuf.c
Normal file
1876
c/src/libblock/src/bdbuf.c
Normal file
File diff suppressed because it is too large
Load Diff
243
c/src/libblock/src/blkdev.c
Normal file
243
c/src/libblock/src/blkdev.c
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* blkdev.h - block device driver generic support
|
||||
*
|
||||
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||
* Author: Victor V. Vengerov <vvv@oktet.ru>
|
||||
*
|
||||
* @(#) $Id$
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "rtems/diskdevs.h"
|
||||
#include "rtems/bdbuf.h"
|
||||
|
||||
/* rtems_blkdev_generic_read --
|
||||
* Generic block device read primitive. Implemented using block device
|
||||
* buffer management primitives.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_read(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg)
|
||||
{
|
||||
rtems_libio_rw_args_t *args = arg;
|
||||
int block_size_log2;
|
||||
int block_size;
|
||||
char *buf;
|
||||
unsigned int count;
|
||||
unsigned int block;
|
||||
unsigned int blkofs;
|
||||
dev_t dev;
|
||||
disk_device *dd;
|
||||
|
||||
dev = rtems_filesystem_make_dev_t(major, minor);
|
||||
dd = rtems_disk_lookup(dev);
|
||||
if (dd == NULL)
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
|
||||
block_size_log2 = dd->block_size_log2;
|
||||
block_size = dd->block_size;
|
||||
|
||||
buf = args->buffer;
|
||||
count = args->count;
|
||||
args->bytes_moved = 0;
|
||||
|
||||
block = args->offset >> block_size_log2;
|
||||
blkofs = args->offset & (block_size - 1);
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
bdbuf_buffer *diskbuf;
|
||||
int copy;
|
||||
rtems_status_code rc;
|
||||
|
||||
rc = rtems_bdbuf_read(dev, block, &diskbuf);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
return rc;
|
||||
copy = block_size - blkofs;
|
||||
if (copy > count)
|
||||
copy = count;
|
||||
memcpy(buf, (char *)diskbuf->buffer + blkofs, copy);
|
||||
rc = rtems_bdbuf_release(diskbuf);
|
||||
args->bytes_moved += copy;
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
return rc;
|
||||
count -= copy;
|
||||
buf += copy;
|
||||
blkofs = 0;
|
||||
block++;
|
||||
}
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/* rtems_blkdev_generic_write --
|
||||
* Generic block device write primitive. Implemented using block device
|
||||
* buffer management primitives.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_write(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg)
|
||||
{
|
||||
rtems_libio_rw_args_t *args = arg;
|
||||
int block_size_log2;
|
||||
int block_size;
|
||||
char *buf;
|
||||
unsigned int count;
|
||||
unsigned int block;
|
||||
unsigned int blkofs;
|
||||
dev_t dev;
|
||||
rtems_status_code rc;
|
||||
disk_device *dd;
|
||||
|
||||
dev = rtems_filesystem_make_dev_t(major, minor);
|
||||
dd = rtems_disk_lookup(dev);
|
||||
if (dd == NULL)
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
|
||||
block_size_log2 = dd->block_size_log2;
|
||||
block_size = dd->block_size;
|
||||
|
||||
buf = args->buffer;
|
||||
count = args->count;
|
||||
args->bytes_moved = 0;
|
||||
|
||||
block = args->offset >> block_size_log2;
|
||||
blkofs = args->offset & (block_size - 1);
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
bdbuf_buffer *diskbuf;
|
||||
int copy;
|
||||
|
||||
if ((blkofs == 0) && (count > block_size))
|
||||
rc = rtems_bdbuf_get(dev, block, &diskbuf);
|
||||
else
|
||||
rc = rtems_bdbuf_read(dev, block, &diskbuf);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
return rc;
|
||||
|
||||
copy = block_size - blkofs;
|
||||
if (copy > count)
|
||||
copy = count;
|
||||
memcpy((char *)diskbuf->buffer + blkofs, buf, copy);
|
||||
args->bytes_moved += copy;
|
||||
|
||||
rc = rtems_bdbuf_release_modified(diskbuf);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
return rc;
|
||||
|
||||
count -= copy;
|
||||
buf += copy;
|
||||
blkofs = 0;
|
||||
block++;
|
||||
}
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/* blkdev_generic_open --
|
||||
* Generic block device open primitive.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_open(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg)
|
||||
{
|
||||
dev_t dev;
|
||||
disk_device *dd;
|
||||
|
||||
dev = rtems_filesystem_make_dev_t(major, minor);
|
||||
dd = rtems_disk_lookup(dev);
|
||||
if (dd == NULL)
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
|
||||
dd->uses++;
|
||||
|
||||
rtems_disk_release(dd);
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
|
||||
/* blkdev_generic_close --
|
||||
* Generic block device close primitive.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_close(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg)
|
||||
{
|
||||
dev_t dev;
|
||||
disk_device *dd;
|
||||
|
||||
dev = rtems_filesystem_make_dev_t(major, minor);
|
||||
dd = rtems_disk_lookup(dev);
|
||||
if (dd == NULL)
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
|
||||
dd->uses--;
|
||||
|
||||
rtems_disk_release(dd);
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/* blkdev_generic_ioctl --
|
||||
* Generic block device ioctl primitive.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_ioctl(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg)
|
||||
{
|
||||
rtems_libio_ioctl_args_t *args = arg;
|
||||
dev_t dev;
|
||||
disk_device *dd;
|
||||
int rc;
|
||||
|
||||
dev = rtems_filesystem_make_dev_t(major, minor);
|
||||
dd = rtems_disk_lookup(dev);
|
||||
if (dd == NULL)
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
|
||||
switch (args->command)
|
||||
{
|
||||
case BLKIO_GETBLKSIZE:
|
||||
args->ioctl_return = dd->block_size;
|
||||
break;
|
||||
|
||||
case BLKIO_GETSIZE:
|
||||
args->ioctl_return = dd->size;
|
||||
break;
|
||||
|
||||
case BLKIO_SYNCDEV:
|
||||
rc = rtems_bdbuf_syncdev(dd->dev);
|
||||
args->ioctl_return = (rc == RTEMS_SUCCESSFUL ? 0 : -1);
|
||||
break;
|
||||
|
||||
case BLKIO_REQUEST:
|
||||
{
|
||||
blkdev_request *req = args->buffer;
|
||||
req->start += dd->start;
|
||||
args->ioctl_return = dd->ioctl(dd->phys_dev->dev, args->command,
|
||||
req);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
args->ioctl_return = dd->ioctl(dd->phys_dev->dev, args->command,
|
||||
args->buffer);
|
||||
break;
|
||||
}
|
||||
rtems_disk_release(dd);
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
631
c/src/libblock/src/diskdevs.c
Normal file
631
c/src/libblock/src/diskdevs.c
Normal file
@@ -0,0 +1,631 @@
|
||||
/*
|
||||
* diskdevs.c - Physical and logical block devices (disks) support
|
||||
*
|
||||
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||
* Author: Victor V. Vengerov <vvv@oktet.ru>
|
||||
*
|
||||
* @(#) $Id$
|
||||
*/
|
||||
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "rtems/diskdevs.h"
|
||||
#include "rtems/bdbuf.h"
|
||||
|
||||
#define DISKTAB_INITIAL_SIZE 32
|
||||
|
||||
/* Table of disk devices having the same major number */
|
||||
struct disk_device_table {
|
||||
disk_device **minor; /* minor-indexed disk device table */
|
||||
int size; /* Number of entries in the table */
|
||||
};
|
||||
|
||||
/* Pointer to [major].minor[minor] indexed array of disk devices */
|
||||
static struct disk_device_table *disktab;
|
||||
|
||||
/* Number of allocated entries in disktab table */
|
||||
static int disktab_size;
|
||||
|
||||
/* Mutual exclusion semaphore for disk devices table */
|
||||
static rtems_id diskdevs_mutex;
|
||||
|
||||
/* Flag meaning that disk I/O, buffering etc. already has been initialized. */
|
||||
static boolean disk_io_initialized = FALSE;
|
||||
|
||||
/* diskdevs data structures protection flag.
|
||||
* Normally, only table lookup operations performed. It is quite fast, so
|
||||
* it is possible to done lookups when interrupts are disabled, avoiding
|
||||
* obtaining the semaphore. This flags sets immediately after entering in
|
||||
* mutex-protected section and cleared before leaving this section in
|
||||
* "big" primitives like add/delete new device etc. Lookup function first
|
||||
* disable interrupts and check this flag. If it is set, lookup function
|
||||
* will be blocked on semaphore and lookup operation will be performed in
|
||||
* semaphore-protected code. If it is not set (very-very frequent case),
|
||||
* we can do lookup safely, enable interrupts and return result.
|
||||
*/
|
||||
static volatile rtems_boolean diskdevs_protected;
|
||||
|
||||
/* create_disk_entry --
|
||||
* Return pointer to the disk_entry structure for the specified device, or
|
||||
* create one if it is not exists.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device id (major, minor)
|
||||
*
|
||||
* RETURNS:
|
||||
* pointer to the disk device descirptor entry, or NULL if no memory
|
||||
* available for its creation.
|
||||
*/
|
||||
static disk_device *
|
||||
create_disk_entry(dev_t dev)
|
||||
{
|
||||
rtems_device_major_number major;
|
||||
rtems_device_minor_number minor;
|
||||
struct disk_device **d;
|
||||
|
||||
rtems_filesystem_split_dev_t (dev, major, minor);
|
||||
|
||||
if (major >= disktab_size)
|
||||
{
|
||||
struct disk_device_table *p;
|
||||
int newsize;
|
||||
int i;
|
||||
newsize = disktab_size * 2;
|
||||
if (major >= newsize)
|
||||
newsize = major + 1;
|
||||
p = realloc(disktab, sizeof(struct disk_device_table) * newsize);
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
p += disktab_size;
|
||||
for (i = disktab_size; i < newsize; i++, p++)
|
||||
{
|
||||
p->minor = NULL;
|
||||
p->size = 0;
|
||||
}
|
||||
disktab_size = newsize;
|
||||
}
|
||||
|
||||
if ((disktab[major].minor == NULL) ||
|
||||
(minor >= disktab[major].size))
|
||||
{
|
||||
int newsize;
|
||||
disk_device **p;
|
||||
int i;
|
||||
int s = disktab[major].size;
|
||||
|
||||
if (s == 0)
|
||||
newsize = DISKTAB_INITIAL_SIZE;
|
||||
else
|
||||
newsize = s * 2;
|
||||
if (minor >= newsize)
|
||||
newsize = minor + 1;
|
||||
|
||||
p = realloc(disktab[major].minor, sizeof(disk_device *) * newsize);
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
disktab[major].minor = p;
|
||||
p += s;
|
||||
for (i = s; i < newsize; i++, p++)
|
||||
*p = NULL;
|
||||
disktab[major].size = newsize;
|
||||
}
|
||||
|
||||
d = disktab[major].minor + minor;
|
||||
if (*d == NULL)
|
||||
{
|
||||
*d = calloc(1, sizeof(disk_device));
|
||||
}
|
||||
return *d;
|
||||
}
|
||||
|
||||
/* get_disk_entry --
|
||||
* Get disk device descriptor by device number.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - block device number
|
||||
*
|
||||
* RETURNS:
|
||||
* Pointer to the disk device descriptor corresponding to the specified
|
||||
* device number, or NULL if disk device with such number not exists.
|
||||
*/
|
||||
static inline disk_device *
|
||||
get_disk_entry(dev_t dev)
|
||||
{
|
||||
rtems_device_major_number major;
|
||||
rtems_device_minor_number minor;
|
||||
struct disk_device_table *dtab;
|
||||
|
||||
rtems_filesystem_split_dev_t (dev, major, minor);
|
||||
|
||||
if ((major >= disktab_size) || (disktab == NULL))
|
||||
return NULL;
|
||||
|
||||
dtab = disktab + major;
|
||||
|
||||
if ((minor >= dtab->size) || (dtab->minor == NULL))
|
||||
return NULL;
|
||||
|
||||
return dtab->minor[minor];
|
||||
}
|
||||
|
||||
/* create_disk --
|
||||
* Check that disk entry for specified device number is not defined
|
||||
* and create it.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device identifier (major, minor numbers)
|
||||
* name - character name of device (e.g. /dev/hda)
|
||||
* disdev - placeholder for pointer to created disk descriptor
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if disk entry successfully created, or
|
||||
* error code if error occured (device already registered,
|
||||
* no memory available).
|
||||
*/
|
||||
static rtems_status_code
|
||||
create_disk(dev_t dev, char *name, disk_device **diskdev)
|
||||
{
|
||||
disk_device *dd;
|
||||
char *n;
|
||||
|
||||
dd = get_disk_entry(dev);
|
||||
if (dd != NULL)
|
||||
{
|
||||
return RTEMS_RESOURCE_IN_USE;
|
||||
}
|
||||
|
||||
if (name == NULL)
|
||||
{
|
||||
n = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
int nlen = strlen(name) + 1;
|
||||
n = malloc(nlen);
|
||||
if (n == NULL)
|
||||
return RTEMS_NO_MEMORY;
|
||||
strncpy(n, name, nlen);
|
||||
}
|
||||
|
||||
dd = create_disk_entry(dev);
|
||||
if (dd == NULL)
|
||||
{
|
||||
free(n);
|
||||
return RTEMS_NO_MEMORY;
|
||||
}
|
||||
|
||||
dd->dev = dev;
|
||||
dd->name = n;
|
||||
|
||||
*diskdev = dd;
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/* rtems_disk_create_phys --
|
||||
* Create physical disk entry. This function usually invoked from
|
||||
* block device driver initialization code when physical device
|
||||
* detected in the system. Device driver should provide ioctl handler
|
||||
* to allow block device access operations. This primitive will register
|
||||
* device in rtems (invoke rtems_io_register_name).
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device identifier (major, minor numbers)
|
||||
* block_size - size of disk block (minimum data transfer unit); must be
|
||||
* power of 2
|
||||
* disk_size - number of blocks on device
|
||||
* handler - IOCTL handler (function providing basic block input/output
|
||||
* request handling BIOREQUEST and other device management
|
||||
* operations)
|
||||
* name - character name of device (e.g. /dev/hda)
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if information about new physical disk added, or
|
||||
* error code if error occured (device already registered, wrong block
|
||||
* size value, no memory available).
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_create_phys(dev_t dev, int block_size, int disk_size,
|
||||
block_device_ioctl handler,
|
||||
char *name)
|
||||
{
|
||||
int bs_log2;
|
||||
int i;
|
||||
disk_device *dd;
|
||||
rtems_status_code rc;
|
||||
rtems_bdpool_id pool;
|
||||
rtems_device_major_number major;
|
||||
rtems_device_minor_number minor;
|
||||
|
||||
rtems_filesystem_split_dev_t (dev, major, minor);
|
||||
|
||||
|
||||
for (bs_log2 = 0, i = block_size; (i & 1) == 0; i >>= 1, bs_log2++);
|
||||
if ((bs_log2 < 9) || (i != 1)) /* block size < 512 or not power of 2 */
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
|
||||
rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
return rc;
|
||||
diskdevs_protected = TRUE;
|
||||
|
||||
rc = rtems_bdbuf_find_pool(block_size, &pool);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
diskdevs_protected = FALSE;
|
||||
rtems_semaphore_release(diskdevs_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = create_disk(dev, name, &dd);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
diskdevs_protected = FALSE;
|
||||
rtems_semaphore_release(diskdevs_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
dd->phys_dev = dd;
|
||||
dd->uses = 0;
|
||||
dd->start = 0;
|
||||
dd->size = disk_size;
|
||||
dd->block_size = block_size;
|
||||
dd->block_size_log2 = bs_log2;
|
||||
dd->ioctl = handler;
|
||||
dd->pool = pool;
|
||||
|
||||
rc = rtems_io_register_name(name, major, minor);
|
||||
|
||||
diskdevs_protected = FALSE;
|
||||
rtems_semaphore_release(diskdevs_mutex);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* rtems_disk_create_log --
|
||||
* Create logical disk entry. Logical disk is contiguous area on physical
|
||||
* disk. Disk may be splitted to several logical disks in several ways:
|
||||
* manually or using information stored in blocks on physical disk
|
||||
* (DOS-like partition table, BSD disk label, etc). This function usually
|
||||
* invoked from application when application-specific splitting are in use,
|
||||
* or from generic code which handle different logical disk organizations.
|
||||
* This primitive will register device in rtems (invoke
|
||||
* rtems_io_register_name).
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - logical device identifier (major, minor numbers)
|
||||
* phys - physical device (block device which holds this logical disk)
|
||||
* identifier
|
||||
* start - starting block number on the physical device
|
||||
* size - logical disk size in blocks
|
||||
* name - logical disk name
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if logical device successfully added, or error code
|
||||
* if error occured (device already registered, no physical device
|
||||
* exists, logical disk is out of physical disk boundaries, no memory
|
||||
* available).
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_create_log(dev_t dev, dev_t phys, int start, int size, char *name)
|
||||
{
|
||||
disk_device *dd;
|
||||
disk_device *pdd;
|
||||
rtems_status_code rc;
|
||||
rtems_device_major_number major;
|
||||
rtems_device_minor_number minor;
|
||||
|
||||
rtems_filesystem_split_dev_t (dev, major, minor);
|
||||
|
||||
rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
return rc;
|
||||
diskdevs_protected = TRUE;
|
||||
|
||||
pdd = get_disk_entry(phys);
|
||||
if (pdd == NULL)
|
||||
{
|
||||
diskdevs_protected = FALSE;
|
||||
rtems_semaphore_release(diskdevs_mutex);
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
}
|
||||
|
||||
rc = create_disk(dev, name, &dd);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
diskdevs_protected = FALSE;
|
||||
rtems_semaphore_release(diskdevs_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
dd->phys_dev = pdd;
|
||||
dd->uses = 0;
|
||||
dd->start = start;
|
||||
dd->size = size;
|
||||
dd->block_size = pdd->block_size;
|
||||
dd->block_size_log2 = pdd->block_size_log2;
|
||||
dd->ioctl = pdd->ioctl;
|
||||
|
||||
rc = rtems_io_register_name(name, major, minor);
|
||||
|
||||
diskdevs_protected = FALSE;
|
||||
rc = rtems_semaphore_release(diskdevs_mutex);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* rtems_disk_delete --
|
||||
* Delete physical or logical disk device. Device may be deleted if its
|
||||
* use counter (and use counters of all logical devices - if it is
|
||||
* physical device) equal to 0. When physical device deleted,
|
||||
* all logical devices deleted inherently. Appropriate devices removed
|
||||
* from "/dev" filesystem.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device identifier (major, minor numbers)
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if block device successfully deleted, or error code
|
||||
* if error occured (device is not defined, device is in use).
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_delete(dev_t dev)
|
||||
{
|
||||
rtems_status_code rc;
|
||||
int used;
|
||||
rtems_device_major_number maj;
|
||||
rtems_device_minor_number min;
|
||||
|
||||
rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
return rc;
|
||||
diskdevs_protected = TRUE;
|
||||
|
||||
/* Check if this device is in use -- calculate usage counter */
|
||||
used = 0;
|
||||
for (maj = 0; maj < disktab_size; maj++)
|
||||
{
|
||||
struct disk_device_table *dtab = disktab + maj;
|
||||
if (dtab != NULL)
|
||||
{
|
||||
for (min = 0; min < dtab->size; min++)
|
||||
{
|
||||
disk_device *dd = dtab->minor[min];
|
||||
if ((dd != NULL) && (dd->phys_dev->dev == dev))
|
||||
used += dd->uses;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (used != 0)
|
||||
{
|
||||
diskdevs_protected = FALSE;
|
||||
rtems_semaphore_release(diskdevs_mutex);
|
||||
return RTEMS_RESOURCE_IN_USE;
|
||||
}
|
||||
|
||||
/* Delete this device and all of its logical devices */
|
||||
for (maj = 0; maj < disktab_size; maj++)
|
||||
{
|
||||
struct disk_device_table *dtab = disktab +maj;
|
||||
if (dtab != NULL)
|
||||
{
|
||||
for (min = 0; min < dtab->size; min++)
|
||||
{
|
||||
disk_device *dd = dtab->minor[min];
|
||||
if ((dd != NULL) && (dd->phys_dev->dev == dev))
|
||||
{
|
||||
unlink(dd->name);
|
||||
free(dd->name);
|
||||
free(dd);
|
||||
dtab->minor[min] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
diskdevs_protected = FALSE;
|
||||
rc = rtems_semaphore_release(diskdevs_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* rtems_disk_lookup --
|
||||
* Find block device descriptor by its device identifier.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device identifier (major, minor numbers)
|
||||
*
|
||||
* RETURNS:
|
||||
* pointer to the block device descriptor, or NULL if no such device
|
||||
* exists.
|
||||
*/
|
||||
disk_device *
|
||||
rtems_disk_lookup(dev_t dev)
|
||||
{
|
||||
rtems_interrupt_level level;
|
||||
disk_device *dd;
|
||||
rtems_status_code rc;
|
||||
|
||||
rtems_interrupt_disable(level);
|
||||
if (diskdevs_protected)
|
||||
{
|
||||
rtems_interrupt_enable(level);
|
||||
rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT,
|
||||
RTEMS_NO_TIMEOUT);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
return NULL;
|
||||
diskdevs_protected = TRUE;
|
||||
dd = get_disk_entry(dev);
|
||||
dd->uses++;
|
||||
diskdevs_protected = FALSE;
|
||||
rtems_semaphore_release(diskdevs_mutex);
|
||||
return dd;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Frequent and quickest case */
|
||||
dd = get_disk_entry(dev);
|
||||
dd->uses++;
|
||||
rtems_interrupt_enable(level);
|
||||
return dd;
|
||||
}
|
||||
}
|
||||
|
||||
/* rtems_disk_release --
|
||||
* Release disk_device structure (decrement usage counter to 1).
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dd - pointer to disk device structure
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_release(disk_device *dd)
|
||||
{
|
||||
rtems_interrupt_level level;
|
||||
rtems_interrupt_disable(level);
|
||||
dd->uses--;
|
||||
rtems_interrupt_enable(level);
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/* rtems_disk_next --
|
||||
* Disk device enumerator. Looking for device having device number larger
|
||||
* than dev and return disk device descriptor for it. If there are no
|
||||
* such device, NULL value returned.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device number (use -1 to start search)
|
||||
*
|
||||
* RETURNS:
|
||||
* Pointer to the disk descriptor for next disk device, or NULL if all
|
||||
* devices enumerated.
|
||||
*/
|
||||
disk_device *
|
||||
rtems_disk_next(dev_t dev)
|
||||
{
|
||||
rtems_device_major_number major;
|
||||
rtems_device_minor_number minor;
|
||||
struct disk_device_table *dtab;
|
||||
|
||||
dev++;
|
||||
rtems_filesystem_split_dev_t (dev, major, minor);
|
||||
|
||||
if (major >= disktab_size)
|
||||
return NULL;
|
||||
|
||||
dtab = disktab + major;
|
||||
while (TRUE)
|
||||
{
|
||||
if ((dtab == NULL) || (minor > dtab->size))
|
||||
{
|
||||
major++; minor = 0;
|
||||
if (major >= disktab_size)
|
||||
return NULL;
|
||||
dtab = disktab + major;
|
||||
}
|
||||
else if (dtab->minor[minor] == NULL)
|
||||
{
|
||||
minor++;
|
||||
}
|
||||
else
|
||||
return dtab->minor[minor];
|
||||
}
|
||||
}
|
||||
|
||||
/* rtems_disk_initialize --
|
||||
* Initialization of disk device library (initialize all data structures,
|
||||
* etc.)
|
||||
*
|
||||
* PARAMETERS:
|
||||
* none
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if library initialized, or error code if error
|
||||
* occured.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_io_initialize(void)
|
||||
{
|
||||
rtems_status_code rc;
|
||||
|
||||
if (disk_io_initialized)
|
||||
return RTEMS_SUCCESSFUL;
|
||||
|
||||
disktab_size = DISKTAB_INITIAL_SIZE;
|
||||
disktab = calloc(disktab_size, sizeof(struct disk_device_table));
|
||||
if (disktab == NULL)
|
||||
return RTEMS_NO_MEMORY;
|
||||
|
||||
diskdevs_protected = FALSE;
|
||||
rc = rtems_semaphore_create(
|
||||
rtems_build_name('D', 'D', 'E', 'V'), 1,
|
||||
RTEMS_FIFO | RTEMS_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY |
|
||||
RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL, 0, &diskdevs_mutex);
|
||||
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
free(disktab);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = rtems_bdbuf_init(rtems_bdbuf_configuration,
|
||||
rtems_bdbuf_configuration_size);
|
||||
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
rtems_semaphore_delete(diskdevs_mutex);
|
||||
free(disktab);
|
||||
return rc;
|
||||
}
|
||||
|
||||
disk_io_initialized = 1;
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/* rtems_disk_io_done --
|
||||
* Release all resources allocated for disk device interface.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* none
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if all resources released, or error code if error
|
||||
* occured.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_io_done(void)
|
||||
{
|
||||
rtems_device_major_number maj;
|
||||
rtems_device_minor_number min;
|
||||
rtems_status_code rc;
|
||||
|
||||
/* Free data structures */
|
||||
for (maj = 0; maj < disktab_size; maj++)
|
||||
{
|
||||
struct disk_device_table *dtab = disktab + maj;
|
||||
if (dtab != NULL)
|
||||
{
|
||||
for (min = 0; min < dtab->size; min++)
|
||||
{
|
||||
disk_device *dd = dtab->minor[min];
|
||||
unlink(dd->name);
|
||||
free(dd->name);
|
||||
free(dd);
|
||||
}
|
||||
free(dtab);
|
||||
}
|
||||
}
|
||||
free(disktab);
|
||||
|
||||
rc = rtems_semaphore_release(diskdevs_mutex);
|
||||
|
||||
/* XXX bdbuf should be released too! */
|
||||
disk_io_initialized = 0;
|
||||
return rc;
|
||||
}
|
||||
224
c/src/libblock/src/ramdisk.c
Normal file
224
c/src/libblock/src/ramdisk.c
Normal file
@@ -0,0 +1,224 @@
|
||||
/* 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;
|
||||
}
|
||||
14
cpukit/libblock/.cvsignore
Normal file
14
cpukit/libblock/.cvsignore
Normal file
@@ -0,0 +1,14 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
config.cache
|
||||
config.guess
|
||||
config.log
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
depcomp
|
||||
install-sh
|
||||
missing
|
||||
mkinstalldirs
|
||||
25
cpukit/libblock/ChangeLog
Normal file
25
cpukit/libblock/ChangeLog
Normal file
@@ -0,0 +1,25 @@
|
||||
2002-02-28 Joel Sherrill <joel@OARcorp.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2001-11-29 Victor V. Vengerov <vvv@oktet.ru>
|
||||
* AVL trees implementation added.
|
||||
|
||||
2001-11-16 Victor V. Vengerov <vvv@oktet.ru>
|
||||
* include/rtems/bdbuf.h, src/bdbuf.c(rtems_bdbuf_syncdev): New.
|
||||
|
||||
2001-11-07 Victor V. Vengerov <vvv@oktet.ru>
|
||||
|
||||
* ChangeLog: New file.
|
||||
* src/, include/, include/rtems/: New directories.
|
||||
* README, configure.ac, Makefile.am, src/Makefile.am,
|
||||
include/Makefile.am: New files.
|
||||
* include/rtems/bdbuf.h include/rtems/blkdev.h
|
||||
include/rtems/diskdevs.h include/rtems/ramdisk.h
|
||||
src/bdbuf.c src/blkdev.c src/diskdevs.c src/ramdisk.c: New files.
|
||||
13
cpukit/libblock/Makefile.am
Normal file
13
cpukit/libblock/Makefile.am
Normal file
@@ -0,0 +1,13 @@
|
||||
##
|
||||
## $Id$
|
||||
##
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign 1.4
|
||||
ACLOCAL_AMFLAGS = -I ../../../aclocal
|
||||
|
||||
SUBDIRS = include src
|
||||
|
||||
EXTRA_DIST = README
|
||||
|
||||
include $(top_srcdir)/../../../automake/subdirs.am
|
||||
include $(top_srcdir)/../../../automake/local.am
|
||||
14
cpukit/libblock/README
Normal file
14
cpukit/libblock/README
Normal file
@@ -0,0 +1,14 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
This directory contains the block device (HDD, CDROMs, etc) support code.
|
||||
It includes:
|
||||
- block device driver interface
|
||||
- generic open/close/read/write/ioctl primitives for block device drivers
|
||||
- disk I/O buffering
|
||||
- logical disk support
|
||||
- RAM disk block device driver
|
||||
|
||||
Victor V. Vengerov, <vvv@oktet.ru>
|
||||
November, 7 2001
|
||||
32
cpukit/libblock/configure.ac
Normal file
32
cpukit/libblock/configure.ac
Normal file
@@ -0,0 +1,32 @@
|
||||
## Process this file with autoconf to produce a configure script.
|
||||
##
|
||||
## $Id$
|
||||
|
||||
AC_PREREQ(2.52)
|
||||
AC_INIT
|
||||
AC_CONFIG_SRCDIR([src/bdbuf.c])
|
||||
RTEMS_TOP(../../..)
|
||||
AC_CONFIG_AUX_DIR(../../..)
|
||||
|
||||
RTEMS_CANONICAL_TARGET_CPU
|
||||
RTEMS_CANONICAL_HOST
|
||||
|
||||
AM_INIT_AUTOMAKE(rtems-c-src-libblock,$RTEMS_VERSION,no)
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
RTEMS_ENV_RTEMSBSP
|
||||
RTEMS_CHECK_CPU
|
||||
RTEMS_CHECK_CUSTOM_BSP(RTEMS_BSP)
|
||||
RTEMS_PROG_CC_FOR_TARGET
|
||||
RTEMS_ENABLE_BARE
|
||||
|
||||
RTEMS_CANONICALIZE_TOOLS
|
||||
|
||||
RTEMS_PROJECT_ROOT
|
||||
|
||||
# Explicitly list all Makefiles here
|
||||
AC_CONFIG_FILES([Makefile
|
||||
include/Makefile
|
||||
src/Makefile
|
||||
])
|
||||
AC_OUTPUT
|
||||
2
cpukit/libblock/include/.cvsignore
Normal file
2
cpukit/libblock/include/.cvsignore
Normal file
@@ -0,0 +1,2 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
2
cpukit/libblock/include/rtems/.cvsignore
Normal file
2
cpukit/libblock/include/rtems/.cvsignore
Normal file
@@ -0,0 +1,2 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
282
cpukit/libblock/include/rtems/bdbuf.h
Normal file
282
cpukit/libblock/include/rtems/bdbuf.h
Normal file
@@ -0,0 +1,282 @@
|
||||
/* bdbuf.h -- block device buffer management
|
||||
*
|
||||
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||
* Author: Victor V. Vengerov <vvv@oktet.ru>
|
||||
*
|
||||
* @(#) $Id$
|
||||
*/
|
||||
|
||||
#ifndef __RTEMS_LIBBLOCK_BDBUF_H__
|
||||
#define __RTEMS_LIBBLOCK_BDBUF_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <chain.h>
|
||||
|
||||
#include "rtems/blkdev.h"
|
||||
#include "rtems/diskdevs.h"
|
||||
|
||||
|
||||
/*
|
||||
* To manage buffers we using Buffer Descriptors.
|
||||
* To speed-up buffer lookup descriptors are organized in AVL-Tree.
|
||||
* The fields 'dev' and 'block' are search key.
|
||||
*/
|
||||
|
||||
/* Buffer descriptors
|
||||
* Descriptors organized in AVL-tree to speedup buffer lookup.
|
||||
* dev and block fields are search key in AVL-tree.
|
||||
* Modified buffers, free buffers and used buffers linked in 'mod', 'free' and
|
||||
* 'lru' chains appropriately.
|
||||
*/
|
||||
|
||||
typedef struct bdbuf_buffer {
|
||||
Chain_Node link; /* Link in the lru, mod or free chains */
|
||||
|
||||
#ifdef BINARY_TREE
|
||||
struct bdbuf_avl_node {
|
||||
struct bdbuf_buffer *left; /* link to the left sub-tree */
|
||||
struct bdbuf_buffer *right; /* link to the right sub-tree */
|
||||
|
||||
int bf; /* AVL tree node balance factor */
|
||||
} avl; /* AVL-tree links */
|
||||
#else /* AVL TREE */
|
||||
struct bdbuf_avl_node {
|
||||
char cache; /* Cache */
|
||||
|
||||
struct bdbuf_buffer* link[2]; /* Left and Right Kids */
|
||||
|
||||
char bal; /* The balance of the sub-tree */
|
||||
} avl;
|
||||
#endif
|
||||
dev_t dev; /* device number */
|
||||
blkdev_bnum block; /* block number on the device */
|
||||
|
||||
char *buffer; /* Pointer to the buffer memory area */
|
||||
rtems_status_code status; /* Last I/O operation completion status */
|
||||
int error; /* If status != RTEMS_SUCCESSFUL, this field contains
|
||||
errno value which can be used by user later */
|
||||
boolean modified:1; /* =1 if buffer was modified */
|
||||
boolean in_progress:1; /* =1 if exchange with disk is in progress;
|
||||
need to wait on semaphore */
|
||||
boolean actual:1; /* Buffer contains actual data */
|
||||
int use_count; /* Usage counter; incremented when somebody use
|
||||
this buffer; decremented when buffer released
|
||||
without modification or when buffer is flushed
|
||||
by swapout task */
|
||||
|
||||
rtems_bdpool_id pool; /* Identifier of buffer pool to which this buffer
|
||||
belongs */
|
||||
CORE_mutex_Control transfer_sema;
|
||||
/* Transfer operation semaphore */
|
||||
} bdbuf_buffer;
|
||||
|
||||
|
||||
|
||||
/* bdbuf_config structure describes block configuration (size,
|
||||
* amount, memory location) for buffering layer
|
||||
*/
|
||||
typedef struct rtems_bdbuf_config {
|
||||
int size; /* Size of block */
|
||||
int num; /* Number of blocks of appropriate size */
|
||||
char *mem_area; /* Pointer to the blocks location or NULL, in this
|
||||
case memory for blocks will be allocated by
|
||||
Buffering Layer with the help of RTEMS partition
|
||||
manager */
|
||||
} rtems_bdbuf_config;
|
||||
|
||||
extern rtems_bdbuf_config rtems_bdbuf_configuration[];
|
||||
extern int rtems_bdbuf_configuration_size;
|
||||
|
||||
/* rtems_bdbuf_init --
|
||||
* Prepare buffering layer to work - initialize buffer descritors
|
||||
* and (if it is neccessary) buffers. Buffers will be allocated accoriding
|
||||
* to the configuration table, each entry describes kind of block and
|
||||
* amount requested. After initialization all blocks is placed into
|
||||
* free elements lists.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* conf_table - pointer to the buffers configuration table
|
||||
* size - number of entries in configuration table
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
|
||||
* or error code if error is occured)
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_init(rtems_bdbuf_config *conf_table, int size);
|
||||
|
||||
|
||||
/* rtems_bdbuf_get --
|
||||
* Obtain block buffer. If specified block already cached (i.e. there's
|
||||
* block in the _modified_, or _recently_used_), return address
|
||||
* of appropriate buffer descriptor and increment reference counter to 1.
|
||||
* If block is not cached, allocate new buffer and return it. Data
|
||||
* shouldn't be read to the buffer from media; buffer may contains
|
||||
* arbitrary data. This primitive may be blocked if there are no free
|
||||
* buffer descriptors available and there are no unused non-modified
|
||||
* (or synchronized with media) buffers available.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* device - device number (constructed of major and minor device number)
|
||||
* block - linear media block number
|
||||
* bd - address of variable to store pointer to the buffer descriptor
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
|
||||
* or error code if error is occured)
|
||||
*
|
||||
* SIDE EFFECTS:
|
||||
* bufget_sema semaphore obtained by this primitive.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_get(dev_t device, blkdev_bnum block, bdbuf_buffer **bdb_ptr);
|
||||
|
||||
/* rtems_bdbuf_read --
|
||||
* (Similar to the rtems_bdbuf_get, except reading data from media)
|
||||
* Obtain block buffer. If specified block already cached, return address
|
||||
* of appropriate buffer and increment reference counter to 1. If block is
|
||||
* not cached, allocate new buffer and read data to it from the media.
|
||||
* This primitive may be blocked on waiting until data to be read from
|
||||
* media, if there are no free buffer descriptors available and there are
|
||||
* no unused non-modified (or synchronized with media) buffers available.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* device - device number (consists of major and minor device number)
|
||||
* block - linear media block number
|
||||
* bd - address of variable to store pointer to the buffer descriptor
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
|
||||
* or error code if error is occured)
|
||||
*
|
||||
* SIDE EFFECTS:
|
||||
* bufget_sema and transfer_sema semaphores obtained by this primitive.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_read(dev_t device, blkdev_bnum block, bdbuf_buffer **bdb_ptr);
|
||||
|
||||
/* rtems_bdbuf_release --
|
||||
* Release buffer allocated before. This primitive decrease the
|
||||
* usage counter. If it is zero, further destiny of buffer depends on
|
||||
* 'modified' status. If buffer was modified, it is placed to the end of
|
||||
* mod list and flush task waken up. If buffer was not modified,
|
||||
* it is placed to the end of lru list, and bufget_sema released, allowing
|
||||
* to reuse this buffer.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* bd_buf - pointer to the bdbuf_buffer structure previously obtained using
|
||||
* get/read primitive.
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
|
||||
* or error code if error is occured)
|
||||
*
|
||||
* SIDE EFFECTS:
|
||||
* flush_sema and bufget_sema semaphores may be released by this primitive.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_release(bdbuf_buffer *bd_buf);
|
||||
|
||||
/* rtems_bdbuf_release_modified --
|
||||
* Release buffer allocated before, assuming that it is _modified_ by
|
||||
* it's owner. This primitive decrease usage counter for buffer, mark
|
||||
* buffer descriptor as modified. If usage counter is 0, insert it at
|
||||
* end of mod chain and release flush_sema semaphore to activate the
|
||||
* flush task.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* bd_buf - pointer to the bdbuf_buffer structure previously obtained using
|
||||
* get/read primitive.
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
|
||||
* or error code if error is occured)
|
||||
*
|
||||
* SIDE EFFECTS:
|
||||
* flush_sema semaphore may be released by this primitive.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_release_modified(bdbuf_buffer *bd_buf);
|
||||
|
||||
/* rtems_bdbuf_sync --
|
||||
* Wait until specified buffer synchronized with disk. Invoked on exchanges
|
||||
* critical for data consistency on the media. This primitive mark owned
|
||||
* block as modified, decrease usage counter. If usage counter is 0,
|
||||
* block inserted to the mod chain and flush_sema semaphore released.
|
||||
* Finally, primitives blocked on transfer_sema semaphore.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* bd_buf - pointer to the bdbuf_buffer structure previously obtained using
|
||||
* get/read primitive.
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
|
||||
* or error code if error is occured)
|
||||
*
|
||||
* SIDE EFFECTS:
|
||||
* Primitive may be blocked on transfer_sema semaphore.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_sync(bdbuf_buffer *bd_buf);
|
||||
|
||||
/* rtems_bdbuf_syncdev --
|
||||
* Synchronize with disk all buffers containing the blocks belonging to
|
||||
* specified device.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - block device number
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
|
||||
* or error code if error is occured)
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_syncdev(dev_t dev);
|
||||
|
||||
/* rtems_bdbuf_find_pool --
|
||||
* Find first appropriate buffer pool. This primitive returns the index
|
||||
* of first buffer pool which block size is greater than or equal to
|
||||
* specified size.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* block_size - requested block size
|
||||
* pool - placeholder for result
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code: RTEMS_SUCCESSFUL if operation completed successfully,
|
||||
* RTEMS_INVALID_SIZE if specified block size is invalid (not a power
|
||||
* of 2), RTEMS_NOT_DEFINED if buffer pool for this or greater block size
|
||||
* is not configured.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_find_pool(int block_size, rtems_bdpool_id *pool);
|
||||
|
||||
/* rtems_bdbuf_get_pool_info --
|
||||
* Obtain characteristics of buffer pool with specified number.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* pool - buffer pool number
|
||||
* block_size - block size for which buffer pool is configured returned
|
||||
* there
|
||||
* blocks - number of buffers in buffer pool returned there
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS status code: RTEMS_SUCCESSFUL if operation completed successfully,
|
||||
* RTEMS_INVALID_NUMBER if appropriate buffer pool is not configured.
|
||||
*
|
||||
* NOTE:
|
||||
* Buffer pools enumerated contiguously starting from 0.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_get_pool_info(rtems_bdpool_id pool, int *block_size, int *blocks);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
147
cpukit/libblock/include/rtems/blkdev.h
Normal file
147
cpukit/libblock/include/rtems/blkdev.h
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* blkdev.h - block device driver interface definitions
|
||||
*
|
||||
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||
* Author: Victor V. Vengerov <vvv@oktet.ru>
|
||||
*
|
||||
* @(#) $Id$
|
||||
*/
|
||||
|
||||
#ifndef __RTEMS_LIBBLOCK_BLKDEV_H__
|
||||
#define __RTEMS_LIBBLOCK_BLKDEV_H__
|
||||
|
||||
#include <rtems.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Interface with device drivers
|
||||
* Block device looks, initialized and behaves like traditional RTEMS device
|
||||
* driver. Heart of the block device driver is in BIOREQUEST ioctl. This call
|
||||
* puts I/O request to the block device queue, in priority order, for
|
||||
* asynchronous processing. When driver executes request, req_done
|
||||
* function invoked, so callee knows about it. Look for details below.
|
||||
*/
|
||||
|
||||
|
||||
/* Block device block number datatype */
|
||||
typedef rtems_unsigned32 blkdev_bnum;
|
||||
|
||||
/* Block device request type */
|
||||
typedef enum blkdev_request_op {
|
||||
BLKDEV_REQ_READ, /* Read operation */
|
||||
BLKDEV_REQ_WRITE /* Write operation */
|
||||
} blkdev_request_op;
|
||||
|
||||
/* Type for block device request done callback function.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* arg - argument supplied in blkdev_request
|
||||
* status - rtems status code for this operation
|
||||
* errno - errno value to be passed to the user when
|
||||
* status != RTEMS_SUCCESSFUL
|
||||
*/
|
||||
typedef void (* blkdev_request_cb)(void *arg,
|
||||
rtems_status_code status,
|
||||
int error);
|
||||
|
||||
/* blkdev_sg_buffer
|
||||
* Block device scatter/gather buffer structure
|
||||
*/
|
||||
typedef struct blkdev_sg_buffer {
|
||||
rtems_unsigned32 length; /* Buffer length */
|
||||
void *buffer; /* Buffer pointer */
|
||||
} blkdev_sg_buffer;
|
||||
|
||||
/* blkdev_request (Block Device Request) structure is
|
||||
* used to read/write a number of blocks from/to device.
|
||||
*/
|
||||
typedef struct blkdev_request {
|
||||
blkdev_request_op req; /* Block device operation (read or write) */
|
||||
blkdev_request_cb req_done; /* Callback function */
|
||||
void *done_arg; /* Argument to be passed to callback function*/
|
||||
blkdev_bnum start; /* Start block number */
|
||||
rtems_unsigned32 count; /* Number of blocks to be exchanged */
|
||||
rtems_unsigned32 bufnum; /* Number of buffers provided */
|
||||
|
||||
blkdev_sg_buffer bufs[0];/* List of scatter/gather buffers */
|
||||
} blkdev_request;
|
||||
|
||||
/* Block device IOCTL request codes */
|
||||
#define BLKIO_REQUEST _IOWR('B', 1, blkdev_request)
|
||||
#define BLKIO_GETBLKSIZE _IO('B', 2)
|
||||
#define BLKIO_GETSIZE _IO('B', 3)
|
||||
#define BLKIO_SYNCDEV _IO('B', 4)
|
||||
|
||||
/* Device driver interface conventions suppose that driver may
|
||||
* contain initialize/open/close/read/write/ioctl entry points. These
|
||||
* primitives (except initialize) can be implemented in generic fashion,
|
||||
* based upon supplied block device driver ioctl handler. Every block
|
||||
* device driver should provide initialize entry point, which is register
|
||||
* all block devices and appropriate ioctl handlers.
|
||||
*/
|
||||
|
||||
#define GENERIC_BLOCK_DEVICE_DRIVER_ENTRIES \
|
||||
rtems_blkdev_generic_open, rtems_blkdev_generic_close, \
|
||||
rtems_blkdev_generic_read, rtems_blkdev_generic_write, \
|
||||
rtems_blkdev_generic_ioctl
|
||||
|
||||
/* blkdev_generic_read --
|
||||
* Generic block device read primitive. Implemented using block device
|
||||
* buffer management primitives.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_read(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
);
|
||||
|
||||
/* blkdev_generic_write --
|
||||
* Generic block device driver write primitive. Implemented using block
|
||||
* device buffer management primitives.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_write(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
);
|
||||
|
||||
/* blkdev_generic_open --
|
||||
* Generic block device open primitive.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_open(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
);
|
||||
|
||||
/* blkdev_generic_close --
|
||||
* Generic block device close primitive.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_close(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
);
|
||||
|
||||
/* blkdev_generic_ioctl --
|
||||
* Generic block device ioctl primitive.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_ioctl(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
206
cpukit/libblock/include/rtems/diskdevs.h
Normal file
206
cpukit/libblock/include/rtems/diskdevs.h
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* logdisk.h - Physical and logical block devices (disks) support
|
||||
*
|
||||
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||
* Author: Victor V. Vengerov <vvv@oktet.ru>
|
||||
*
|
||||
* @(#) $Id$
|
||||
*/
|
||||
|
||||
#ifndef __RTEMS_LIBBLOCK_LOGDISK_H__
|
||||
#define __RTEMS_LIBBLOCK_LOGDISK_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "rtems/blkdev.h"
|
||||
|
||||
/* Buffer pool identifier */
|
||||
typedef int rtems_bdpool_id;
|
||||
|
||||
/* Block device ioctl handler */
|
||||
typedef int (* block_device_ioctl) (dev_t dev, int req, void *argp);
|
||||
|
||||
/* disk_device: Entry of this type created for every disk device (both for
|
||||
* logical and physical disks).
|
||||
* Array of arrays of pointers to disk_device structures maintained. First
|
||||
* table indexed by major number and second table indexed by minor number.
|
||||
* Such data organization allow quick lookup using data structure of
|
||||
* moderated size.
|
||||
*/
|
||||
typedef struct disk_device {
|
||||
dev_t dev; /* Device ID (major + minor) */
|
||||
struct disk_device *phys_dev; /* Physical device ID (the same
|
||||
as dev if this entry specifies
|
||||
the physical device) */
|
||||
char *name; /* Disk device name */
|
||||
int uses; /* Use counter. Device couldn't be
|
||||
removed if it is in use. */
|
||||
int start; /* Starting block number (0 for
|
||||
physical devices, block offset
|
||||
on the related physical device
|
||||
for logical device) */
|
||||
int size; /* Size of physical or logical disk
|
||||
in disk blocks */
|
||||
int block_size; /* Size of device block (minimum
|
||||
transfer unit) in bytes
|
||||
(must be power of 2) */
|
||||
int block_size_log2; /* log2 of block_size */
|
||||
rtems_bdpool_id pool; /* Buffer pool assigned to this
|
||||
device */
|
||||
block_device_ioctl ioctl; /* ioctl handler for this block
|
||||
device */
|
||||
} disk_device;
|
||||
|
||||
/* rtems_disk_create_phys --
|
||||
* Create physical disk entry. This function usually invoked from
|
||||
* block device driver initialization code when physical device
|
||||
* detected in the system. Device driver should provide ioctl handler
|
||||
* to allow block device access operations. This primitive will register
|
||||
* device in rtems (invoke rtems_io_register_name).
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device identifier (major, minor numbers)
|
||||
* block_size - size of disk block (minimum data transfer unit); must be
|
||||
* power of 2
|
||||
* disk_size - number of blocks on device
|
||||
* handler - IOCTL handler (function providing basic block input/output
|
||||
* request handling BIOREQUEST and other device management
|
||||
* operations)
|
||||
* name - character name of device (e.g. /dev/hda)
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if information about new physical disk added, or
|
||||
* error code if error occured (device already registered, wrong block
|
||||
* size value, no memory available).
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_create_phys(dev_t dev, int block_size, int disk_size,
|
||||
block_device_ioctl handler,
|
||||
char *name);
|
||||
|
||||
/* rtems_disk_create_log --
|
||||
* Create logical disk entry. Logical disk is contiguous area on physical
|
||||
* disk. Disk may be splitted to several logical disks in several ways:
|
||||
* manually or using information stored in blocks on physical disk
|
||||
* (DOS-like partition table, BSD disk label, etc). This function usually
|
||||
* invoked from application when application-specific splitting are in use,
|
||||
* or from generic code which handle different logical disk organizations.
|
||||
* This primitive will register device in rtems (invoke
|
||||
* rtems_io_register_name).
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - logical device identifier (major, minor numbers)
|
||||
* phys - physical device (block device which holds this logical disk)
|
||||
* identifier
|
||||
* start - starting block number on the physical device
|
||||
* size - logical disk size in blocks
|
||||
* name - logical disk name
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if logical device successfully added, or error code
|
||||
* if error occured (device already registered, no physical device
|
||||
* exists, logical disk is out of physical disk boundaries, no memory
|
||||
* available).
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_create_log(dev_t dev, dev_t phys, int start, int size, char *name);
|
||||
|
||||
/* rtems_disk_delete --
|
||||
* Delete physical or logical disk device. Device may be deleted if its
|
||||
* use counter (and use counters of all logical devices - if it is
|
||||
* physical device) equal to 0. When physical device deleted,
|
||||
* all logical devices deleted inherently. Appropriate devices removed
|
||||
* from "/dev" filesystem.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device identifier (major, minor numbers)
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if block device successfully deleted, or error code
|
||||
* if error occured (device is not defined, device is in use).
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_delete(dev_t dev);
|
||||
|
||||
/* rtems_disk_lookup --
|
||||
* Find block device descriptor by its device identifier. This function
|
||||
* increment usage counter to 1. User should release disk_device structure
|
||||
* by invoking rtems_disk_release primitive.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device identifier (major, minor numbers)
|
||||
*
|
||||
* RETURNS:
|
||||
* pointer to the block device descriptor, or NULL if no such device
|
||||
* exists.
|
||||
*/
|
||||
disk_device *
|
||||
rtems_disk_lookup(dev_t dev);
|
||||
|
||||
/* rtems_disk_release --
|
||||
* Release disk_device structure (decrement usage counter to 1).
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dd - pointer to disk device structure
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL
|
||||
*
|
||||
* NOTE:
|
||||
* It should be implemented as inline function.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_release(disk_device *dd);
|
||||
|
||||
/* rtems_disk_next --
|
||||
* Disk device enumerator. Looking for device having device number larger
|
||||
* than dev and return disk device descriptor for it. If there are no
|
||||
* such device, NULL value returned.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device number (use -1 to start search)
|
||||
*
|
||||
* RETURNS:
|
||||
* Pointer to the disk descriptor for next disk device, or NULL if all
|
||||
* devices enumerated. */
|
||||
disk_device *
|
||||
rtems_disk_next(dev_t dev);
|
||||
|
||||
/* rtems_diskio_initialize --
|
||||
* Initialization of disk device library (initialize all data structures,
|
||||
* etc.)
|
||||
*
|
||||
* PARAMETERS:
|
||||
* none
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if library initialized, or error code if error
|
||||
* occured.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_io_initialize(void);
|
||||
|
||||
/* rtems_diskio_done --
|
||||
* Release all resources allocated for disk device interface.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* none
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if all resources released, or error code if error
|
||||
* occured.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_io_done(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
52
cpukit/libblock/include/rtems/ramdisk.h
Normal file
52
cpukit/libblock/include/rtems/ramdisk.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* ramdisk.c -- RAM disk block device implementation
|
||||
*
|
||||
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||
* Author: Victor V. Vengerov <vvv@oktet.ru>
|
||||
*
|
||||
* @(#) $Id$
|
||||
*/
|
||||
|
||||
#ifndef __RTEMS_LIBBLOCK_RAMDISK_H__
|
||||
#define __RTEMS_LIBBLOCK_RAMDISK_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <rtems.h>
|
||||
|
||||
#include "rtems/blkdev.h"
|
||||
|
||||
/* RAM disk configuration table entry */
|
||||
typedef struct rtems_ramdisk_config {
|
||||
int block_size; /* RAM disk block size */
|
||||
int block_num; /* Number of blocks on this RAM disk */
|
||||
void *location; /* RAM disk permanent location (out of RTEMS controlled
|
||||
memory), or NULL if RAM disk memory should be
|
||||
allocated dynamically */
|
||||
} rtems_ramdisk_config;
|
||||
|
||||
/* If application want to use RAM disk, it should specify configuration of
|
||||
* available RAM disks.
|
||||
* The following is definitions for RAM disk configuration table
|
||||
*/
|
||||
extern rtems_ramdisk_config rtems_ramdisk_configuration[];
|
||||
extern int rtems_ramdisk_configuration_size;
|
||||
|
||||
/* ramdisk_initialize --
|
||||
* RAM disk driver initialization entry point.
|
||||
*/
|
||||
rtems_device_driver
|
||||
ramdisk_initialize(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *arg);
|
||||
|
||||
#define RAMDISK_DRIVER_TABLE_ENTRY \
|
||||
{ ramdisk_initialize, GENERIC_BLOCK_DEVICE_DRIVER_ENTRIES }
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
2
cpukit/libblock/src/.cvsignore
Normal file
2
cpukit/libblock/src/.cvsignore
Normal file
@@ -0,0 +1,2 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
33
cpukit/libblock/src/Makefile.am
Normal file
33
cpukit/libblock/src/Makefile.am
Normal file
@@ -0,0 +1,33 @@
|
||||
##
|
||||
## $Id$
|
||||
##
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign 1.5
|
||||
|
||||
LIBNAME = libblock
|
||||
LIB = ${ARCH}/${LIBNAME}.a
|
||||
|
||||
C_FILES = bdbuf.c blkdev.c diskdevs.c ramdisk.c
|
||||
|
||||
C_O_FILES = $(C_FILES:%.c=${ARCH}/%.o)
|
||||
|
||||
SRCS = $(C_FILES)
|
||||
OBJS = $(C_O_FILES)
|
||||
|
||||
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
|
||||
include $(top_srcdir)/../../../automake/compile.am
|
||||
include $(top_srcdir)/../../../automake/lib.am
|
||||
|
||||
AM_CFLAGS += $(LIBC_DEFINES)
|
||||
|
||||
TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a
|
||||
|
||||
$(LIB): ${OBJS}
|
||||
$(make-library)
|
||||
|
||||
$(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a: $(LIB)
|
||||
$(INSTALL_DATA) $< $@
|
||||
|
||||
all-local: ${ARCH} $(PREINSTALL_FILES) $(TMPINSTALL_FILES)
|
||||
|
||||
include $(top_srcdir)/../../../automake/local.am
|
||||
1876
cpukit/libblock/src/bdbuf.c
Normal file
1876
cpukit/libblock/src/bdbuf.c
Normal file
File diff suppressed because it is too large
Load Diff
243
cpukit/libblock/src/blkdev.c
Normal file
243
cpukit/libblock/src/blkdev.c
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* blkdev.h - block device driver generic support
|
||||
*
|
||||
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||
* Author: Victor V. Vengerov <vvv@oktet.ru>
|
||||
*
|
||||
* @(#) $Id$
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "rtems/diskdevs.h"
|
||||
#include "rtems/bdbuf.h"
|
||||
|
||||
/* rtems_blkdev_generic_read --
|
||||
* Generic block device read primitive. Implemented using block device
|
||||
* buffer management primitives.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_read(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg)
|
||||
{
|
||||
rtems_libio_rw_args_t *args = arg;
|
||||
int block_size_log2;
|
||||
int block_size;
|
||||
char *buf;
|
||||
unsigned int count;
|
||||
unsigned int block;
|
||||
unsigned int blkofs;
|
||||
dev_t dev;
|
||||
disk_device *dd;
|
||||
|
||||
dev = rtems_filesystem_make_dev_t(major, minor);
|
||||
dd = rtems_disk_lookup(dev);
|
||||
if (dd == NULL)
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
|
||||
block_size_log2 = dd->block_size_log2;
|
||||
block_size = dd->block_size;
|
||||
|
||||
buf = args->buffer;
|
||||
count = args->count;
|
||||
args->bytes_moved = 0;
|
||||
|
||||
block = args->offset >> block_size_log2;
|
||||
blkofs = args->offset & (block_size - 1);
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
bdbuf_buffer *diskbuf;
|
||||
int copy;
|
||||
rtems_status_code rc;
|
||||
|
||||
rc = rtems_bdbuf_read(dev, block, &diskbuf);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
return rc;
|
||||
copy = block_size - blkofs;
|
||||
if (copy > count)
|
||||
copy = count;
|
||||
memcpy(buf, (char *)diskbuf->buffer + blkofs, copy);
|
||||
rc = rtems_bdbuf_release(diskbuf);
|
||||
args->bytes_moved += copy;
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
return rc;
|
||||
count -= copy;
|
||||
buf += copy;
|
||||
blkofs = 0;
|
||||
block++;
|
||||
}
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/* rtems_blkdev_generic_write --
|
||||
* Generic block device write primitive. Implemented using block device
|
||||
* buffer management primitives.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_write(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg)
|
||||
{
|
||||
rtems_libio_rw_args_t *args = arg;
|
||||
int block_size_log2;
|
||||
int block_size;
|
||||
char *buf;
|
||||
unsigned int count;
|
||||
unsigned int block;
|
||||
unsigned int blkofs;
|
||||
dev_t dev;
|
||||
rtems_status_code rc;
|
||||
disk_device *dd;
|
||||
|
||||
dev = rtems_filesystem_make_dev_t(major, minor);
|
||||
dd = rtems_disk_lookup(dev);
|
||||
if (dd == NULL)
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
|
||||
block_size_log2 = dd->block_size_log2;
|
||||
block_size = dd->block_size;
|
||||
|
||||
buf = args->buffer;
|
||||
count = args->count;
|
||||
args->bytes_moved = 0;
|
||||
|
||||
block = args->offset >> block_size_log2;
|
||||
blkofs = args->offset & (block_size - 1);
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
bdbuf_buffer *diskbuf;
|
||||
int copy;
|
||||
|
||||
if ((blkofs == 0) && (count > block_size))
|
||||
rc = rtems_bdbuf_get(dev, block, &diskbuf);
|
||||
else
|
||||
rc = rtems_bdbuf_read(dev, block, &diskbuf);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
return rc;
|
||||
|
||||
copy = block_size - blkofs;
|
||||
if (copy > count)
|
||||
copy = count;
|
||||
memcpy((char *)diskbuf->buffer + blkofs, buf, copy);
|
||||
args->bytes_moved += copy;
|
||||
|
||||
rc = rtems_bdbuf_release_modified(diskbuf);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
return rc;
|
||||
|
||||
count -= copy;
|
||||
buf += copy;
|
||||
blkofs = 0;
|
||||
block++;
|
||||
}
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/* blkdev_generic_open --
|
||||
* Generic block device open primitive.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_open(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg)
|
||||
{
|
||||
dev_t dev;
|
||||
disk_device *dd;
|
||||
|
||||
dev = rtems_filesystem_make_dev_t(major, minor);
|
||||
dd = rtems_disk_lookup(dev);
|
||||
if (dd == NULL)
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
|
||||
dd->uses++;
|
||||
|
||||
rtems_disk_release(dd);
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
|
||||
/* blkdev_generic_close --
|
||||
* Generic block device close primitive.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_close(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg)
|
||||
{
|
||||
dev_t dev;
|
||||
disk_device *dd;
|
||||
|
||||
dev = rtems_filesystem_make_dev_t(major, minor);
|
||||
dd = rtems_disk_lookup(dev);
|
||||
if (dd == NULL)
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
|
||||
dd->uses--;
|
||||
|
||||
rtems_disk_release(dd);
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/* blkdev_generic_ioctl --
|
||||
* Generic block device ioctl primitive.
|
||||
*/
|
||||
rtems_device_driver
|
||||
rtems_blkdev_generic_ioctl(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg)
|
||||
{
|
||||
rtems_libio_ioctl_args_t *args = arg;
|
||||
dev_t dev;
|
||||
disk_device *dd;
|
||||
int rc;
|
||||
|
||||
dev = rtems_filesystem_make_dev_t(major, minor);
|
||||
dd = rtems_disk_lookup(dev);
|
||||
if (dd == NULL)
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
|
||||
switch (args->command)
|
||||
{
|
||||
case BLKIO_GETBLKSIZE:
|
||||
args->ioctl_return = dd->block_size;
|
||||
break;
|
||||
|
||||
case BLKIO_GETSIZE:
|
||||
args->ioctl_return = dd->size;
|
||||
break;
|
||||
|
||||
case BLKIO_SYNCDEV:
|
||||
rc = rtems_bdbuf_syncdev(dd->dev);
|
||||
args->ioctl_return = (rc == RTEMS_SUCCESSFUL ? 0 : -1);
|
||||
break;
|
||||
|
||||
case BLKIO_REQUEST:
|
||||
{
|
||||
blkdev_request *req = args->buffer;
|
||||
req->start += dd->start;
|
||||
args->ioctl_return = dd->ioctl(dd->phys_dev->dev, args->command,
|
||||
req);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
args->ioctl_return = dd->ioctl(dd->phys_dev->dev, args->command,
|
||||
args->buffer);
|
||||
break;
|
||||
}
|
||||
rtems_disk_release(dd);
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
631
cpukit/libblock/src/diskdevs.c
Normal file
631
cpukit/libblock/src/diskdevs.c
Normal file
@@ -0,0 +1,631 @@
|
||||
/*
|
||||
* diskdevs.c - Physical and logical block devices (disks) support
|
||||
*
|
||||
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
|
||||
* Author: Victor V. Vengerov <vvv@oktet.ru>
|
||||
*
|
||||
* @(#) $Id$
|
||||
*/
|
||||
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "rtems/diskdevs.h"
|
||||
#include "rtems/bdbuf.h"
|
||||
|
||||
#define DISKTAB_INITIAL_SIZE 32
|
||||
|
||||
/* Table of disk devices having the same major number */
|
||||
struct disk_device_table {
|
||||
disk_device **minor; /* minor-indexed disk device table */
|
||||
int size; /* Number of entries in the table */
|
||||
};
|
||||
|
||||
/* Pointer to [major].minor[minor] indexed array of disk devices */
|
||||
static struct disk_device_table *disktab;
|
||||
|
||||
/* Number of allocated entries in disktab table */
|
||||
static int disktab_size;
|
||||
|
||||
/* Mutual exclusion semaphore for disk devices table */
|
||||
static rtems_id diskdevs_mutex;
|
||||
|
||||
/* Flag meaning that disk I/O, buffering etc. already has been initialized. */
|
||||
static boolean disk_io_initialized = FALSE;
|
||||
|
||||
/* diskdevs data structures protection flag.
|
||||
* Normally, only table lookup operations performed. It is quite fast, so
|
||||
* it is possible to done lookups when interrupts are disabled, avoiding
|
||||
* obtaining the semaphore. This flags sets immediately after entering in
|
||||
* mutex-protected section and cleared before leaving this section in
|
||||
* "big" primitives like add/delete new device etc. Lookup function first
|
||||
* disable interrupts and check this flag. If it is set, lookup function
|
||||
* will be blocked on semaphore and lookup operation will be performed in
|
||||
* semaphore-protected code. If it is not set (very-very frequent case),
|
||||
* we can do lookup safely, enable interrupts and return result.
|
||||
*/
|
||||
static volatile rtems_boolean diskdevs_protected;
|
||||
|
||||
/* create_disk_entry --
|
||||
* Return pointer to the disk_entry structure for the specified device, or
|
||||
* create one if it is not exists.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device id (major, minor)
|
||||
*
|
||||
* RETURNS:
|
||||
* pointer to the disk device descirptor entry, or NULL if no memory
|
||||
* available for its creation.
|
||||
*/
|
||||
static disk_device *
|
||||
create_disk_entry(dev_t dev)
|
||||
{
|
||||
rtems_device_major_number major;
|
||||
rtems_device_minor_number minor;
|
||||
struct disk_device **d;
|
||||
|
||||
rtems_filesystem_split_dev_t (dev, major, minor);
|
||||
|
||||
if (major >= disktab_size)
|
||||
{
|
||||
struct disk_device_table *p;
|
||||
int newsize;
|
||||
int i;
|
||||
newsize = disktab_size * 2;
|
||||
if (major >= newsize)
|
||||
newsize = major + 1;
|
||||
p = realloc(disktab, sizeof(struct disk_device_table) * newsize);
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
p += disktab_size;
|
||||
for (i = disktab_size; i < newsize; i++, p++)
|
||||
{
|
||||
p->minor = NULL;
|
||||
p->size = 0;
|
||||
}
|
||||
disktab_size = newsize;
|
||||
}
|
||||
|
||||
if ((disktab[major].minor == NULL) ||
|
||||
(minor >= disktab[major].size))
|
||||
{
|
||||
int newsize;
|
||||
disk_device **p;
|
||||
int i;
|
||||
int s = disktab[major].size;
|
||||
|
||||
if (s == 0)
|
||||
newsize = DISKTAB_INITIAL_SIZE;
|
||||
else
|
||||
newsize = s * 2;
|
||||
if (minor >= newsize)
|
||||
newsize = minor + 1;
|
||||
|
||||
p = realloc(disktab[major].minor, sizeof(disk_device *) * newsize);
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
disktab[major].minor = p;
|
||||
p += s;
|
||||
for (i = s; i < newsize; i++, p++)
|
||||
*p = NULL;
|
||||
disktab[major].size = newsize;
|
||||
}
|
||||
|
||||
d = disktab[major].minor + minor;
|
||||
if (*d == NULL)
|
||||
{
|
||||
*d = calloc(1, sizeof(disk_device));
|
||||
}
|
||||
return *d;
|
||||
}
|
||||
|
||||
/* get_disk_entry --
|
||||
* Get disk device descriptor by device number.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - block device number
|
||||
*
|
||||
* RETURNS:
|
||||
* Pointer to the disk device descriptor corresponding to the specified
|
||||
* device number, or NULL if disk device with such number not exists.
|
||||
*/
|
||||
static inline disk_device *
|
||||
get_disk_entry(dev_t dev)
|
||||
{
|
||||
rtems_device_major_number major;
|
||||
rtems_device_minor_number minor;
|
||||
struct disk_device_table *dtab;
|
||||
|
||||
rtems_filesystem_split_dev_t (dev, major, minor);
|
||||
|
||||
if ((major >= disktab_size) || (disktab == NULL))
|
||||
return NULL;
|
||||
|
||||
dtab = disktab + major;
|
||||
|
||||
if ((minor >= dtab->size) || (dtab->minor == NULL))
|
||||
return NULL;
|
||||
|
||||
return dtab->minor[minor];
|
||||
}
|
||||
|
||||
/* create_disk --
|
||||
* Check that disk entry for specified device number is not defined
|
||||
* and create it.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device identifier (major, minor numbers)
|
||||
* name - character name of device (e.g. /dev/hda)
|
||||
* disdev - placeholder for pointer to created disk descriptor
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if disk entry successfully created, or
|
||||
* error code if error occured (device already registered,
|
||||
* no memory available).
|
||||
*/
|
||||
static rtems_status_code
|
||||
create_disk(dev_t dev, char *name, disk_device **diskdev)
|
||||
{
|
||||
disk_device *dd;
|
||||
char *n;
|
||||
|
||||
dd = get_disk_entry(dev);
|
||||
if (dd != NULL)
|
||||
{
|
||||
return RTEMS_RESOURCE_IN_USE;
|
||||
}
|
||||
|
||||
if (name == NULL)
|
||||
{
|
||||
n = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
int nlen = strlen(name) + 1;
|
||||
n = malloc(nlen);
|
||||
if (n == NULL)
|
||||
return RTEMS_NO_MEMORY;
|
||||
strncpy(n, name, nlen);
|
||||
}
|
||||
|
||||
dd = create_disk_entry(dev);
|
||||
if (dd == NULL)
|
||||
{
|
||||
free(n);
|
||||
return RTEMS_NO_MEMORY;
|
||||
}
|
||||
|
||||
dd->dev = dev;
|
||||
dd->name = n;
|
||||
|
||||
*diskdev = dd;
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/* rtems_disk_create_phys --
|
||||
* Create physical disk entry. This function usually invoked from
|
||||
* block device driver initialization code when physical device
|
||||
* detected in the system. Device driver should provide ioctl handler
|
||||
* to allow block device access operations. This primitive will register
|
||||
* device in rtems (invoke rtems_io_register_name).
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device identifier (major, minor numbers)
|
||||
* block_size - size of disk block (minimum data transfer unit); must be
|
||||
* power of 2
|
||||
* disk_size - number of blocks on device
|
||||
* handler - IOCTL handler (function providing basic block input/output
|
||||
* request handling BIOREQUEST and other device management
|
||||
* operations)
|
||||
* name - character name of device (e.g. /dev/hda)
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if information about new physical disk added, or
|
||||
* error code if error occured (device already registered, wrong block
|
||||
* size value, no memory available).
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_create_phys(dev_t dev, int block_size, int disk_size,
|
||||
block_device_ioctl handler,
|
||||
char *name)
|
||||
{
|
||||
int bs_log2;
|
||||
int i;
|
||||
disk_device *dd;
|
||||
rtems_status_code rc;
|
||||
rtems_bdpool_id pool;
|
||||
rtems_device_major_number major;
|
||||
rtems_device_minor_number minor;
|
||||
|
||||
rtems_filesystem_split_dev_t (dev, major, minor);
|
||||
|
||||
|
||||
for (bs_log2 = 0, i = block_size; (i & 1) == 0; i >>= 1, bs_log2++);
|
||||
if ((bs_log2 < 9) || (i != 1)) /* block size < 512 or not power of 2 */
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
|
||||
rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
return rc;
|
||||
diskdevs_protected = TRUE;
|
||||
|
||||
rc = rtems_bdbuf_find_pool(block_size, &pool);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
diskdevs_protected = FALSE;
|
||||
rtems_semaphore_release(diskdevs_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = create_disk(dev, name, &dd);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
diskdevs_protected = FALSE;
|
||||
rtems_semaphore_release(diskdevs_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
dd->phys_dev = dd;
|
||||
dd->uses = 0;
|
||||
dd->start = 0;
|
||||
dd->size = disk_size;
|
||||
dd->block_size = block_size;
|
||||
dd->block_size_log2 = bs_log2;
|
||||
dd->ioctl = handler;
|
||||
dd->pool = pool;
|
||||
|
||||
rc = rtems_io_register_name(name, major, minor);
|
||||
|
||||
diskdevs_protected = FALSE;
|
||||
rtems_semaphore_release(diskdevs_mutex);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* rtems_disk_create_log --
|
||||
* Create logical disk entry. Logical disk is contiguous area on physical
|
||||
* disk. Disk may be splitted to several logical disks in several ways:
|
||||
* manually or using information stored in blocks on physical disk
|
||||
* (DOS-like partition table, BSD disk label, etc). This function usually
|
||||
* invoked from application when application-specific splitting are in use,
|
||||
* or from generic code which handle different logical disk organizations.
|
||||
* This primitive will register device in rtems (invoke
|
||||
* rtems_io_register_name).
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - logical device identifier (major, minor numbers)
|
||||
* phys - physical device (block device which holds this logical disk)
|
||||
* identifier
|
||||
* start - starting block number on the physical device
|
||||
* size - logical disk size in blocks
|
||||
* name - logical disk name
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if logical device successfully added, or error code
|
||||
* if error occured (device already registered, no physical device
|
||||
* exists, logical disk is out of physical disk boundaries, no memory
|
||||
* available).
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_create_log(dev_t dev, dev_t phys, int start, int size, char *name)
|
||||
{
|
||||
disk_device *dd;
|
||||
disk_device *pdd;
|
||||
rtems_status_code rc;
|
||||
rtems_device_major_number major;
|
||||
rtems_device_minor_number minor;
|
||||
|
||||
rtems_filesystem_split_dev_t (dev, major, minor);
|
||||
|
||||
rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
return rc;
|
||||
diskdevs_protected = TRUE;
|
||||
|
||||
pdd = get_disk_entry(phys);
|
||||
if (pdd == NULL)
|
||||
{
|
||||
diskdevs_protected = FALSE;
|
||||
rtems_semaphore_release(diskdevs_mutex);
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
}
|
||||
|
||||
rc = create_disk(dev, name, &dd);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
diskdevs_protected = FALSE;
|
||||
rtems_semaphore_release(diskdevs_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
dd->phys_dev = pdd;
|
||||
dd->uses = 0;
|
||||
dd->start = start;
|
||||
dd->size = size;
|
||||
dd->block_size = pdd->block_size;
|
||||
dd->block_size_log2 = pdd->block_size_log2;
|
||||
dd->ioctl = pdd->ioctl;
|
||||
|
||||
rc = rtems_io_register_name(name, major, minor);
|
||||
|
||||
diskdevs_protected = FALSE;
|
||||
rc = rtems_semaphore_release(diskdevs_mutex);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* rtems_disk_delete --
|
||||
* Delete physical or logical disk device. Device may be deleted if its
|
||||
* use counter (and use counters of all logical devices - if it is
|
||||
* physical device) equal to 0. When physical device deleted,
|
||||
* all logical devices deleted inherently. Appropriate devices removed
|
||||
* from "/dev" filesystem.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device identifier (major, minor numbers)
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if block device successfully deleted, or error code
|
||||
* if error occured (device is not defined, device is in use).
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_delete(dev_t dev)
|
||||
{
|
||||
rtems_status_code rc;
|
||||
int used;
|
||||
rtems_device_major_number maj;
|
||||
rtems_device_minor_number min;
|
||||
|
||||
rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
return rc;
|
||||
diskdevs_protected = TRUE;
|
||||
|
||||
/* Check if this device is in use -- calculate usage counter */
|
||||
used = 0;
|
||||
for (maj = 0; maj < disktab_size; maj++)
|
||||
{
|
||||
struct disk_device_table *dtab = disktab + maj;
|
||||
if (dtab != NULL)
|
||||
{
|
||||
for (min = 0; min < dtab->size; min++)
|
||||
{
|
||||
disk_device *dd = dtab->minor[min];
|
||||
if ((dd != NULL) && (dd->phys_dev->dev == dev))
|
||||
used += dd->uses;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (used != 0)
|
||||
{
|
||||
diskdevs_protected = FALSE;
|
||||
rtems_semaphore_release(diskdevs_mutex);
|
||||
return RTEMS_RESOURCE_IN_USE;
|
||||
}
|
||||
|
||||
/* Delete this device and all of its logical devices */
|
||||
for (maj = 0; maj < disktab_size; maj++)
|
||||
{
|
||||
struct disk_device_table *dtab = disktab +maj;
|
||||
if (dtab != NULL)
|
||||
{
|
||||
for (min = 0; min < dtab->size; min++)
|
||||
{
|
||||
disk_device *dd = dtab->minor[min];
|
||||
if ((dd != NULL) && (dd->phys_dev->dev == dev))
|
||||
{
|
||||
unlink(dd->name);
|
||||
free(dd->name);
|
||||
free(dd);
|
||||
dtab->minor[min] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
diskdevs_protected = FALSE;
|
||||
rc = rtems_semaphore_release(diskdevs_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* rtems_disk_lookup --
|
||||
* Find block device descriptor by its device identifier.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device identifier (major, minor numbers)
|
||||
*
|
||||
* RETURNS:
|
||||
* pointer to the block device descriptor, or NULL if no such device
|
||||
* exists.
|
||||
*/
|
||||
disk_device *
|
||||
rtems_disk_lookup(dev_t dev)
|
||||
{
|
||||
rtems_interrupt_level level;
|
||||
disk_device *dd;
|
||||
rtems_status_code rc;
|
||||
|
||||
rtems_interrupt_disable(level);
|
||||
if (diskdevs_protected)
|
||||
{
|
||||
rtems_interrupt_enable(level);
|
||||
rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT,
|
||||
RTEMS_NO_TIMEOUT);
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
return NULL;
|
||||
diskdevs_protected = TRUE;
|
||||
dd = get_disk_entry(dev);
|
||||
dd->uses++;
|
||||
diskdevs_protected = FALSE;
|
||||
rtems_semaphore_release(diskdevs_mutex);
|
||||
return dd;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Frequent and quickest case */
|
||||
dd = get_disk_entry(dev);
|
||||
dd->uses++;
|
||||
rtems_interrupt_enable(level);
|
||||
return dd;
|
||||
}
|
||||
}
|
||||
|
||||
/* rtems_disk_release --
|
||||
* Release disk_device structure (decrement usage counter to 1).
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dd - pointer to disk device structure
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_release(disk_device *dd)
|
||||
{
|
||||
rtems_interrupt_level level;
|
||||
rtems_interrupt_disable(level);
|
||||
dd->uses--;
|
||||
rtems_interrupt_enable(level);
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/* rtems_disk_next --
|
||||
* Disk device enumerator. Looking for device having device number larger
|
||||
* than dev and return disk device descriptor for it. If there are no
|
||||
* such device, NULL value returned.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* dev - device number (use -1 to start search)
|
||||
*
|
||||
* RETURNS:
|
||||
* Pointer to the disk descriptor for next disk device, or NULL if all
|
||||
* devices enumerated.
|
||||
*/
|
||||
disk_device *
|
||||
rtems_disk_next(dev_t dev)
|
||||
{
|
||||
rtems_device_major_number major;
|
||||
rtems_device_minor_number minor;
|
||||
struct disk_device_table *dtab;
|
||||
|
||||
dev++;
|
||||
rtems_filesystem_split_dev_t (dev, major, minor);
|
||||
|
||||
if (major >= disktab_size)
|
||||
return NULL;
|
||||
|
||||
dtab = disktab + major;
|
||||
while (TRUE)
|
||||
{
|
||||
if ((dtab == NULL) || (minor > dtab->size))
|
||||
{
|
||||
major++; minor = 0;
|
||||
if (major >= disktab_size)
|
||||
return NULL;
|
||||
dtab = disktab + major;
|
||||
}
|
||||
else if (dtab->minor[minor] == NULL)
|
||||
{
|
||||
minor++;
|
||||
}
|
||||
else
|
||||
return dtab->minor[minor];
|
||||
}
|
||||
}
|
||||
|
||||
/* rtems_disk_initialize --
|
||||
* Initialization of disk device library (initialize all data structures,
|
||||
* etc.)
|
||||
*
|
||||
* PARAMETERS:
|
||||
* none
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if library initialized, or error code if error
|
||||
* occured.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_io_initialize(void)
|
||||
{
|
||||
rtems_status_code rc;
|
||||
|
||||
if (disk_io_initialized)
|
||||
return RTEMS_SUCCESSFUL;
|
||||
|
||||
disktab_size = DISKTAB_INITIAL_SIZE;
|
||||
disktab = calloc(disktab_size, sizeof(struct disk_device_table));
|
||||
if (disktab == NULL)
|
||||
return RTEMS_NO_MEMORY;
|
||||
|
||||
diskdevs_protected = FALSE;
|
||||
rc = rtems_semaphore_create(
|
||||
rtems_build_name('D', 'D', 'E', 'V'), 1,
|
||||
RTEMS_FIFO | RTEMS_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY |
|
||||
RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL, 0, &diskdevs_mutex);
|
||||
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
free(disktab);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = rtems_bdbuf_init(rtems_bdbuf_configuration,
|
||||
rtems_bdbuf_configuration_size);
|
||||
|
||||
if (rc != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
rtems_semaphore_delete(diskdevs_mutex);
|
||||
free(disktab);
|
||||
return rc;
|
||||
}
|
||||
|
||||
disk_io_initialized = 1;
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/* rtems_disk_io_done --
|
||||
* Release all resources allocated for disk device interface.
|
||||
*
|
||||
* PARAMETERS:
|
||||
* none
|
||||
*
|
||||
* RETURNS:
|
||||
* RTEMS_SUCCESSFUL if all resources released, or error code if error
|
||||
* occured.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_disk_io_done(void)
|
||||
{
|
||||
rtems_device_major_number maj;
|
||||
rtems_device_minor_number min;
|
||||
rtems_status_code rc;
|
||||
|
||||
/* Free data structures */
|
||||
for (maj = 0; maj < disktab_size; maj++)
|
||||
{
|
||||
struct disk_device_table *dtab = disktab + maj;
|
||||
if (dtab != NULL)
|
||||
{
|
||||
for (min = 0; min < dtab->size; min++)
|
||||
{
|
||||
disk_device *dd = dtab->minor[min];
|
||||
unlink(dd->name);
|
||||
free(dd->name);
|
||||
free(dd);
|
||||
}
|
||||
free(dtab);
|
||||
}
|
||||
}
|
||||
free(disktab);
|
||||
|
||||
rc = rtems_semaphore_release(diskdevs_mutex);
|
||||
|
||||
/* XXX bdbuf should be released too! */
|
||||
disk_io_initialized = 0;
|
||||
return rc;
|
||||
}
|
||||
224
cpukit/libblock/src/ramdisk.c
Normal file
224
cpukit/libblock/src/ramdisk.c
Normal file
@@ -0,0 +1,224 @@
|
||||
/* 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;
|
||||
}
|
||||
Reference in New Issue
Block a user