📄 iobuf.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 + -