⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iobuf.c

📁 一个操作系统源代码 用于嵌入式设备 在Vc++环境下仿真 成功移植到多款处理器上
💻 C
字号:
/*
 *  asixos/fs/iobuf.c
 *
 *  Copyright (C) 2002 Asic Center
 *	
 *	2002-07-24	Created by Pessia
 *  2002-07-25	Pass MONO-MODULE-SIMULATION
 *	2002-08-18	In read_block(), when 'head' is NULL, 
 *				do not check write-buffer.
 *	2002-08-21	Fix a bug about not doing check write-buffer
 *				when 'head' is NULL.
 */

/*
 * 'iobuf.c' is the file of I/O buffer manager for AsixOS filesystem.
 * It contains read/write functions(write_block, read_block, sync_link,
 * sync_area) which needn't check input-parameter.
 */

#include <stdio.h>//for simulation
#include <stdlib.h>//for simulation
#include <string.h>

#include <filesys\fs.h>
#include "iobuf.h"


 /*
 * Function Prototype
 */
int write_block( DLIST_S *head, unsigned int blkid, unsigned short start, 
				unsigned short size, unsigned char *data, unsigned char mode );
int sync_link( DLIST_S *head );
int sync_area( DLIST_S *head );
int read_block( DLIST_S *head, unsigned int blkid, unsigned short start, 
				unsigned short size, unsigned char *data );
static int clip_region( unsigned int x1, unsigned int sizex1,
						unsigned int a, unsigned int sizea,
						unsigned int *start, unsigned short *size );


/* 
 * write_block :
 *	function:	put block's data into buffer in which new blocks are 
 *				waiting to be written into device.
 *	parameter:
 *		head :	head of 'file' link which this block belongs to
 *		blkid:	ID of block to be written
 *		start:	new data's offset address in this block
 *		size :	data size
 *		data :	pointer to data
 *		mode :	mode of writing
 *	return value:
 *		FS_ERROR:	fail
 *		FS_OK:		success
 */
int write_block( DLIST_S *head, unsigned int blkid, unsigned short start, 
				unsigned short size, unsigned char *data, unsigned char mode )
{
	register BUF_BLK_S *p;
	register AREA_S *q;
	register unsigned char *t;
	
	p = (BUF_BLK_S *)FS_MALLOC(sizeof(BUF_BLK_S));
	t = (unsigned char *)FS_MALLOC(sizeof(unsigned char)*size);
	if ( p==NULL || t==NULL ){
		/* 
		 * !!!! In real environment, we should try to 
		 * free some other places to get memory. 
		 */
		PRINT_ERROR("Fail to malloc BUF_BLK_S\n");
		return FS_ERROR;
	}
	
	/* Fill this block */
	p->blkid = blkid;
	p->start = start;
	p->size = size;
	p->data = t;
	memcpy( t, (const void *)data, sizeof(unsigned char)*size);
	
	/*
	 * In real environment, we should stop BUFFER-REFRESH timer here.
	 */
	
	/* Find pointer to area by block ID */
	q = find_area(blkid);
	
	/* Add this new block into area link */
	list_add_tail(&p->area, get_area_buf_listhead(q));
	inc_newblock_num(q);
	
	/*
	 * If this block should be immediately written,
	 * we should write all new block in this area.
	 */
	if ( mode==IMMEDIATE_WRITE ){
		/* Init 'p->link', otherwise, it will go wrong
		 * in sync_area. */
		INIT_LIST_HEAD( &p->link );
		sync_area( get_area_buf_listhead(q) );
		return FS_OK;
	}
	
	/* Pessia 02-8-27 13:46
	 * If 'head' is NULL, this block will not be added 
	 * in its 'file' link.
	 */
	if ( head!= NULL ){
		/* Add this block into special link('file' link) */
		list_add_tail(&p->link, head);
	}
	else	// longn_qi 2002/11/20 added
	{
		INIT_LIST_HEAD( &p->link );
	}
	
	/*
	 * If area's buffer is full enough, 
	 * we should write all new block in this area.
	 */
	if ( AREA_BUF_FULL(q) ){
		sync_area( get_area_buf_listhead(q) );
	}
	
	/*
	 * In real environment, we should start BUFFER-REFRESH timer here.
	 */
	
	return FS_OK;
}

/* 
 * sync_link :
 *	function:	put all new blocks in the 'file' link into device
 *	parameter:
 *		head :	head of 'file' link to be written
 *	return value:
 *		FS_OK:		success
 */
int sync_link( DLIST_S *head ){
	register DLIST_S *p;
	register AREA_S *q;
	register BUF_BLK_S *blk;
	
	special_list_for_each(p, head){
		/* Get pointer to buffer-block */
		blk = list_entry(p, BUF_BLK_S, link );
		/* Find which area this block belongs to */
		q = find_area(blk->blkid);
		/* Write all new blocks in this area */
		sync_area( get_area_buf_listhead(q) );
	}
	
	return FS_OK;
}

/* 
 * sync_link :
 *	function:	put all new blocks in the area link into device
 *	parameter:
 *		head :	head of area link to be written
 *	return value:
 *		FS_OK:		success
 */
int sync_area( DLIST_S *head ){
	register DLIST_S *p;
	register AREA_S *q;
	register BUF_BLK_S *blk;
	unsigned int blkaddr;
	static unsigned char phybuf[MAX_AREA_SIZE];
	
	/* If area link is null, just return */
	if ( list_empty(head) ){
		return FS_OK;
	}
	
	/* Clear buffer */
	memset( phybuf, 0, MAX_AREA_SIZE*sizeof(unsigned char) );
	
	/* Get pointer to area */
	q = get_area_pointer(head);
	
	/* Read data from device into buffer*/
	(READ_DEV(q))(phybuf, AREA_START_ADDR(q), AREA_SIZE(q));
	
	special_list_for_each(p, head){
		/* Get pointer to buffer-block */
		blk = list_entry(p, BUF_BLK_S, area );
		
		/* Delete this block from special link('file' link) */
		list_del(&blk->link);
		
		/* Put data of this block into buffer */
		blkaddr = blk->blkid+blk->start;
		memcpy( (unsigned char*)(phybuf+(blkaddr-AREA_START_ADDR(q))),
				(unsigned char*)blk->data, blk->size);
		
		/* Modify according physical block's status */
		modify_block_status( phybuf, blkaddr, 0 );
		
		/* Delete this block from area link */
		list_del(&blk->area);
		dec_newblock_num(q);
		
		/* Free this block */
		FS_FREE(blk->data);
		FS_FREE(blk);
	}
	
	/* Write data into device */
	(WRITE_DEV(q))((unsigned char*)phybuf, 
					(unsigned int)AREA_START_ADDR(q) , AREA_SIZE(q));
	
	return FS_OK;
}

/*
 * clip_region :
 *	function:	get same part of main and sub regions
 *	parameter:
 *		x1,sizex1 :	main region
 *		a,sizea   :	sub region
 *		start,size:	same region
 *	return value:
 *		FS_ERROR:	no same region
 *		FS_OK:		success
 */
static int clip_region( unsigned int x1, unsigned int sizex1,
						unsigned int a, unsigned int sizea,
						unsigned int *start, unsigned short *size )
{
	register unsigned int x2,b,end;
	
	x2 = x1 + sizex1 - 1;
	b = a + sizea - 1;
	
	if ( a>x2 )
		return FS_ERROR;
		
	else if ( a<x1 ){
		*start = x1;
		
		if ( b<x1 )
			return FS_ERROR;
		else
			goto CHECK_B;
			
	}else{
		*start = a;
		
	CHECK_B:
		if ( b<x2 )
			end = b;
		else
			end = x2;
	}
	
	*size = (unsigned short)(end - *start + 1);
	return FS_OK;	
}

/* 
 * read_block :
 *	function:	read data to user
 *	parameter:
 *		head :	head of 'file' link which this block belongs to
 *		blkid:	ID of block to be read
 *		start:	data's offset address in this block
 *		size :	data size
 *		data :	pointer to data buffer
 *	return value:
 *		FS_ERROR:	fail
 *		FS_OK:		success
 */
int read_block( DLIST_S *head, unsigned int blkid, unsigned short start, 
				unsigned short size, unsigned char *data )
{
	register DLIST_S *p;
	register AREA_S *q;
	register BUF_BLK_S *blk;
	unsigned int blkstart, blkend;
	unsigned int clipstart, clipend, clipoffset;
	unsigned short clipsize;
	unsigned int rbuf_start, data_start;
	unsigned short datanum = size;
	
	static unsigned char phybuf[BLOCKSIZE];//right code!!!
	//static unsigned char phybuf[2048];//test code!!!
	
	blkstart = blkid + start;
	blkend = blkstart + size -1;
	data_start = blkstart;
	datanum = size;
	
	/* Clear buffer */
	memset( phybuf, 0, BLOCKSIZE*sizeof(unsigned char) );
	
	/* Find pointer to area by block ID */
	q = find_area(blkid);
	
	/*
	 * If read-buffer is needed in this area, we should 
	 * check the buffer to find whether it has needed-data.
	 * If yes, copy it.
	 * NOTE: Here, we assume that : 
	 *			read-buffer size >= 0.5 * BLOCKSIZE
	 */
	if ( AREA_READ_BUFFER_SIZE(q) ){
	READ_FROM_BUFFER:
		if ( !clip_region(	AREA_READ_BUFFER_START(q), 
							AREA_READ_BUFFER_SIZE(q),
							data_start, datanum,
							&clipstart, &clipsize) )
		{
			/* Copy data */
			memcpy( (unsigned char *)(phybuf+(clipstart-blkid)), 
					(unsigned char *)
					(AREA_READ_BUFFER(q)+(clipstart-AREA_READ_BUFFER_START(q))), 
					clipsize );
			
			/*
			 * data_start : start address of remained data to be read
			 * data_num   : the number of remained data
			 */
			/* Read left data if have */
			if ( data_start < clipstart ){
				goto REFRESH_READ_BUFFER;
			}else{
			/* Read right data if have */
				clipend = clipstart+clipsize-1;
				if ( clipend < blkend ){
					data_start = clipend+1;
					datanum -= clipsize;
					goto REFRESH_READ_BUFFER;
				}
			}
			
			/* Pessia(2002-8-18)
			 * When 'head' is NULL, do not check write-buffer.
			 * Pessia(2002-8-21) moved this check-up from 
			 * 'CHECK_WRITE_BUFFER'.
			 */
			if ( head == NULL )
				return FS_OK;
			else
				goto CHECK_WRITE_BUFFER;

		}else{
		REFRESH_READ_BUFFER:
			/* Calculate next read-buffer start address */
			rbuf_start = get_rbuf_startaddr(data_start,q);
			AREA_READ_BUFFER_START(q) = rbuf_start;
			/* Refresh area read-buffer */
			(READ_DEV(q))((unsigned char *)AREA_READ_BUFFER(q), 
						rbuf_start, AREA_READ_BUFFER_SIZE(q));
			
			goto READ_FROM_BUFFER;
		}
	}
	
	/* Pessia 2002-8-21 19:36
	 * NO READ BUFFER:
	 * When 'head' is NULL, or there are no new blocks in write-buffer, 
	 * we read data directly from device 
	 */
	if ( head == NULL ){
JUST_READ_DIRECTLY:		
		(READ_DEV(q))(data, blkstart, (unsigned int)size);
		return FS_OK;
	}else{
		if ( list_empty(head) )
			goto JUST_READ_DIRECTLY;
	}
	
	/* Read data from device into buffer*/
	(READ_DEV(q))((unsigned char *)(phybuf+start), blkstart, (unsigned int)size);

CHECK_WRITE_BUFFER:
	/*
	 * Check new blocks in the 'file' link to find whether
	 * there are some data needed. If found, copy them.
	 */
	list_for_each(p, head){
		/* Get pointer to buffer-block */
		blk = list_entry(p, BUF_BLK_S, link );
		
		/* Check block id */
		if ( blk->blkid != blkid )
			continue;
			
		/* Check whether has new data. If yes, copy it */
		if ( !clip_region((blk->blkid+blk->start), blk->size,
						  blkstart, size,
						 &clipstart, &clipsize) )
		{
			clipoffset = clipstart - blk->blkid;
			memcpy( (unsigned char *)(phybuf+clipoffset),
					(unsigned char *)(blk->data+(clipoffset-blk->start)), 
					clipsize );
		}
	}
	/* Copy data to user */
	memcpy( data, (unsigned char *)(phybuf+start), size );
	return FS_OK;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -