From e51bd967cda1989d606b5b6178ed6d2c8d151707 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Thu, 28 Feb 2002 20:39:54 +0000 Subject: 2002-02-28 Joel Sherrill * Submitted by Victor V. Vengerov 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. --- c/src/exec/libblock/include/rtems/.cvsignore | 2 + c/src/exec/libblock/include/rtems/bdbuf.h | 282 +++++++++++++++++++++++++++ c/src/exec/libblock/include/rtems/blkdev.h | 147 ++++++++++++++ c/src/exec/libblock/include/rtems/diskdevs.h | 206 +++++++++++++++++++ c/src/exec/libblock/include/rtems/ramdisk.h | 52 +++++ 5 files changed, 689 insertions(+) create mode 100644 c/src/exec/libblock/include/rtems/.cvsignore create mode 100644 c/src/exec/libblock/include/rtems/bdbuf.h create mode 100644 c/src/exec/libblock/include/rtems/blkdev.h create mode 100644 c/src/exec/libblock/include/rtems/diskdevs.h create mode 100644 c/src/exec/libblock/include/rtems/ramdisk.h (limited to 'c/src/exec/libblock/include/rtems') diff --git a/c/src/exec/libblock/include/rtems/.cvsignore b/c/src/exec/libblock/include/rtems/.cvsignore new file mode 100644 index 0000000000..282522db03 --- /dev/null +++ b/c/src/exec/libblock/include/rtems/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/c/src/exec/libblock/include/rtems/bdbuf.h b/c/src/exec/libblock/include/rtems/bdbuf.h new file mode 100644 index 0000000000..270b69598b --- /dev/null +++ b/c/src/exec/libblock/include/rtems/bdbuf.h @@ -0,0 +1,282 @@ +/* bdbuf.h -- block device buffer management + * + * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia + * Author: Victor V. Vengerov + * + * @(#) $Id$ + */ + +#ifndef __RTEMS_LIBBLOCK_BDBUF_H__ +#define __RTEMS_LIBBLOCK_BDBUF_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#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 diff --git a/c/src/exec/libblock/include/rtems/blkdev.h b/c/src/exec/libblock/include/rtems/blkdev.h new file mode 100644 index 0000000000..ca3b5ba5e2 --- /dev/null +++ b/c/src/exec/libblock/include/rtems/blkdev.h @@ -0,0 +1,147 @@ +/* + * blkdev.h - block device driver interface definitions + * + * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia + * Author: Victor V. Vengerov + * + * @(#) $Id$ + */ + +#ifndef __RTEMS_LIBBLOCK_BLKDEV_H__ +#define __RTEMS_LIBBLOCK_BLKDEV_H__ + +#include +#include + +#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 diff --git a/c/src/exec/libblock/include/rtems/diskdevs.h b/c/src/exec/libblock/include/rtems/diskdevs.h new file mode 100644 index 0000000000..fab3231e62 --- /dev/null +++ b/c/src/exec/libblock/include/rtems/diskdevs.h @@ -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 + * + * @(#) $Id$ + */ + +#ifndef __RTEMS_LIBBLOCK_LOGDISK_H__ +#define __RTEMS_LIBBLOCK_LOGDISK_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#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 diff --git a/c/src/exec/libblock/include/rtems/ramdisk.h b/c/src/exec/libblock/include/rtems/ramdisk.h new file mode 100644 index 0000000000..b9e8c238b8 --- /dev/null +++ b/c/src/exec/libblock/include/rtems/ramdisk.h @@ -0,0 +1,52 @@ +/* ramdisk.c -- RAM disk block device implementation + * + * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia + * Author: Victor V. Vengerov + * + * @(#) $Id$ + */ + +#ifndef __RTEMS_LIBBLOCK_RAMDISK_H__ +#define __RTEMS_LIBBLOCK_RAMDISK_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#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 -- cgit v1.2.3