📄 mlayer.c
字号:
ml_mapinfo->mappagecou_hi=0;
ml_mapinfo->mappagecou_lo=0;
for (cou=0; cou<MAX_NUM_OF_DIF_MAP; cou++) {
ST_MAPBLOCK *map=&ml_mapblocks[cou];
t_ba lba=map->start_frag;
lba*=MAX_FRAGSIZE;
ml_createmap(map,0);
if (ml_get_log2phy(lba)==BLK_NA) return 1;
if (ml_save_map()) return 1;
}
ml_state=ML_CLOSE;
return 0;
}
/****************************************************************************
*
* ml_findlog
*
* Searching for a log block (check if logical block is logged)
* it sets ml_curlog to a log block or set it to NULL
*
* INPUTS
*
* lba - logical block address
*
* RETURNS
*
* 1 - if found
* 0 - not found
*
***************************************************************************/
static t_bit ml_findlog(t_ba lba) {
ST_LOG *log=ml_log;
long a;
for (a=0; a<MAX_LOG_BLOCK; a++,log++) {
if (log->lba==lba) {
ml_curlog=log;
return 1;
}
}
ml_curlog=0;
return 0;
}
/****************************************************************************
*
* ml_dostatic
*
* does static wear leveling, its read logical block, updates static wear
* info, and if static request is coming, then copy the block
*
***************************************************************************/
static void ml_dostatic() { //把空闲block中wear最大的block与逻辑block中wear最小的block交换
unsigned long wear; //实现擦写均衡
t_ba pba;
ml_lbastatic++;
if (ml_lbastatic>=ml_data_blk_count) ml_lbastatic=0;
pba=ml_get_log2phy(ml_lbastatic);
if (pba==BLK_NA) return; //nothing to do
if (!ll_read(pba,0,ml_buffer)) {; //get original
wear=GET_SPARE_AREA(ml_buffer)->wear;
if (wear<WEAR_NA) wear_updatestaticinfo(ml_lbastatic,wear);
else wear_updatestaticinfo(ml_lbastatic,0);
}
else wear_updatestaticinfo(ml_lbastatic,0);
if (wear_check_static()) {
t_po po;
t_ba d_pba,lba;
t_ba s_pba;
unsigned char index=gl_wear_allocstruct.free_index;
if (index==INDEX_NA) return;
d_pba=gl_freetable[index];
if (wll_erase(101,d_pba)) {
d_pba=bb_setasbb(d_pba); //get a reserved block
if (d_pba==BLK_NA) { //if reserved not available
gl_freetable[index] |= FT_BAD; //signal it as BAD
}
else {
wear_updatedynamicinfo(index,0); //set new reserved block wear
gl_freetable[index] = d_pba; //put f_pba back into FLTable as FREE
}
return;
}
#ifdef _WINDOWS
cnt_increase(CNT_TSTATIC);
#endif
lba=gl_wear_allocstruct.static_logblock;
s_pba=ml_get_log2phy(lba);
if (s_pba==BLK_NA) return; //nothing to do
for (po=0; po<MAX_PAGE_PER_BLOCK; po++) {
int ret=ll_read(s_pba,po,ml_buffer);
if (!po) {
ST_SPARE *sptr=GET_SPARE_AREA(ml_buffer);
sptr->wear=gl_wear_allocstruct.free_wear;
sptr->block_type=BLK_TYPE_DAT;
sptr->bad_tag=0xff;
}
else if (ret) continue;
if (wll_write(10,d_pba,po,ml_buffer)) return; //we can stop static swap
}
ml_set_log2phy(lba,d_pba);
wear_updatestaticinfo(lba,gl_wear_allocstruct.free_wear);
gl_freetable[index]=s_pba;
wear_updatedynamicinfo(index,gl_wear_allocstruct.static_wear);
ml_save_map();
}
}
/****************************************************************************
*
* ml_alloclog
*
* alloc log block and initiate it
*
* INPUTS
*
* log - pointer where to alloc to
* lba - which logical block is connected to log block
*
* RETURNS
*
* 0 - if success
* other if any error
*
***************************************************************************/
static t_bit ml_alloclog(ST_LOG *log,t_ba lba) {
unsigned char index=ml_alloc();
t_ba pba;
if (index==INDEX_NA) return 1;
pba=gl_freetable[index];;
log->index=index;
log->lastppo=0;
log->lba=lba;
log->pba=pba;
log->wear=gl_wear_allocstruct.free_wear;
log->switchable=1;
gl_freetable[index]=(t_ba)(pba | FT_LOG);
wear_updatedynamicinfo(index,log->wear); //locked now
ml_logblocknum++;
memset(log->ppo,INDEX_NA,sizeof(log->ppo));
ml_save_map_need=1;
return 0;
}
/****************************************************************************
*
* ml_open
*
* Opening the chanel for read or write from a specified sector
*
* INPUTS
*
* sector - start of sector for read or write
* secnum - number of sector will be read or written
* mode - ML_READ open for read, ML_WRITE open for write
*
* RETURNS
*
* 0 - if success
* other if any error
*
***************************************************************************/
//全局变量赋值
t_bit ml_open(unsigned long sector, unsigned long secnum, unsigned char mode) {
if (ml_state==ML_INIT) return 1;
ml_state=ML_CLOSE;
ml_seccou=secnum;
ml_lba=(t_ba)(sector/MAX_PAGE_PER_BLOCK);
ml_lpo=(t_po)(sector%MAX_PAGE_PER_BLOCK);
if (ml_lba>=ml_data_blk_count) return 1;
if (ml_lpo>=MAX_PAGE_PER_BLOCK) return 1;
if (mode==ML_READ) ml_state=ML_PENDING_READ;
else if (mode==ML_WRITE) ml_state=ML_PENDING_WRITE;
else return 1;
return 0;
}
/****************************************************************************
*
* ml_domerge
*
* does log block and logical block merge
*
* INPUTS
*
* log - log block pointer (it contains logical block number also)
*
* RETURNS
*
* 0 - if success
* other if any error
*
***************************************************************************/
static t_bit ml_domerge(ST_LOG *log) {
unsigned long wear=WEAR_NA;
unsigned char po,lpo,index;
t_ba pba;
t_ba orig_pba;
ml_dostatic();
ml_save_map_need=1;
//非常精彩
if (log->lastppo==MAX_PAGE_PER_BLOCK && log->switchable) { // check if switchable
orig_pba=ml_get_log2phy(log->lba);
if (orig_pba==BLK_NA) return 1; // fatal
ml_set_log2phy(log->lba,log->pba); //put log block to original
wear_updatestaticinfo(log->lba,log->wear);
if (!ll_read(orig_pba,0,ml_buffer)) {//get original
wear=GET_SPARE_AREA(ml_buffer)->wear;
}
else wear=0;
gl_freetable[log->index]=orig_pba; //release original
if (wear<WEAR_NA) wear_updatedynamicinfo(log->index,wear);
else wear_updatedynamicinfo(log->index,0);
ml_curlog->lba=BLK_NA;
ml_logblocknum--;
return 0;
}
again: //缺陷:可能一直在写同一个坏的块,从而陷入死循环
index=ml_alloc();
if (index==INDEX_NA) return 1;
pba=gl_freetable[index];
orig_pba=ml_get_log2phy(log->lba);
if (orig_pba==BLK_NA) return 1; //fatal
for (po=0; po<MAX_PAGE_PER_BLOCK; po++) {
lpo=log->ppo[po];
if (lpo==INDEX_NA) {
// if (po &&
ll_read(orig_pba,po,ml_buffer);
//) continue; //get original
if (!po) wear=GET_SPARE_AREA(ml_buffer)->wear;
}
else {
// if (po &&
ll_read(log->pba,lpo,ml_buffer);
//) continue; //get logged
}
if (!po) {
ST_SPARE *sptr=GET_SPARE_AREA(ml_buffer);
sptr->wear=gl_wear_allocstruct.free_wear;
sptr->block_type=BLK_TYPE_DAT;
sptr->bad_tag=0xff;
}
if (wll_write(20,pba,po,ml_buffer)) goto again;
// if(po == 20) goto again; //测试代码
}
if (wear==WEAR_NA) {
if (!ll_read(orig_pba,0,ml_buffer)) {
wear=GET_SPARE_AREA(ml_buffer)->wear;//get original
}
else {
wear=0;
}
}
gl_freetable[index]=orig_pba; //release original
if (wear<WEAR_NA) wear_updatedynamicinfo(index,wear);
else wear_updatedynamicinfo(index,0);
gl_freetable[log->index]&=~FT_LOG; //release old log block
wear_updatedynamicinfo(log->index,WEAR_NA);
ml_set_log2phy(log->lba,pba); //put new block to original
wear_updatestaticinfo(log->lba,gl_wear_allocstruct.free_wear);
ml_curlog->lba=BLK_NA;
ml_logblocknum--;
return 0;
}
/****************************************************************************
*
* ml_releaselog
*
* releasing a log block for a new logical block
*
* INPUTS
*
* lba - logical block address for new log block
*
* RETURNS
*
* 0 - if success
* other if any error
*
***************************************************************************/
static t_bit ml_releaselog(t_ba lba) {
if (ml_logblocknum < MAX_LOG_BLOCK) {
if (ml_findlog(BLK_NA)) { //find a free
return ml_alloclog(ml_curlog,lba);
}
}
{
ST_LOG *log=&ml_log[ml_logmerge++];
if (ml_logmerge>=MAX_LOG_BLOCK) ml_logmerge=0;
ml_curlog=log;
if (ml_domerge(log)) return 1;
return ml_alloclog(log,lba);
}
}
/****************************************************************************
*
* ml_write
*
* Writing sector data
*
* INPUTS
*
* data - data pointer for an array which length is sector size
*
* RETURNS
*
* 0 - if success
* other if any error
*
***************************************************************************/
t_bit ml_write(unsigned char *datap) {
#ifdef _WINDOWS
cnt_increase(CNT_TWRITES);
#endif
if (ml_state==ML_PENDING_WRITE) {
if (!ml_findlog(ml_lba)) {
if (ml_releaselog(ml_lba)) return 1;
}
ml_state=ML_WRITE;
}
if (ml_state==ML_WRITE) {
if (!ml_seccou--) {
ml_state=ML_ABORT;
return 1;
}
if (ml_lpo>=MAX_PAGE_PER_BLOCK) {
ml_lba++;
if (ml_lba>=ml_data_blk_count) {
ml_state=ML_CLOSE;
return 1;
}
if (!ml_findlog(ml_lba)) {
if (ml_releaselog(ml_lba)) return 1;
}
ml_lpo=0;
}
if (ml_curlog->lastppo>=MAX_PAGE_PER_BLOCK) {
if (ml_domerge(ml_curlog)) return 1;
if (ml_alloclog(ml_curlog,ml_lba)) return 1; //allocate a new log block
}
memcpy (ml_buffer,datap,MAX_DATA_SIZE);
{
ST_SPARE *sptr=GET_SPARE_AREA(ml_buffer);
if (!ml_curlog->lastppo) {
sptr->wear=ml_curlog->wear;
sptr->block_type=BLK_TYPE_DAT;
sptr->bad_tag=0xff;
}
sptr->u.log.lba=ml_lba;
sptr->u.log.lpo=ml_lpo;
}
if (ml_lpo!=ml_curlog->lastppo) ml_curlog->switchable=0; //not switchable from this point
ml_curlog->ppo[ml_lpo++]=ml_curlog->lastppo;
wll_write(40,ml_curlog->pba,ml_curlog->lastppo++,ml_buffer); //致命缺陷:写错误处理不足
if (ml_save_map_need) ml_save_map();
return 0;
}
return 1;
}
/****************************************************************************
*
* ml_read
*
* read sector data
*
* INPUTS
*
* data - where to read a given sector
*
* RETURNS
*
* 0 - if success
* other if any error
*
***************************************************************************/
t_bit ml_read(unsigned char *datap) {
if (ml_state==ML_PENDING_READ) {
ml_pba=ml_get_log2phy(ml_lba);
if (ml_pba==BLK_NA) return 1;
ml_findlog(ml_lba);
ml_state=ML_READ;
}
if (ml_state==ML_READ) {
int ret;
if (!ml_seccou--) {
ml_state=ML_ABORT;
return 1;
}
if (ml_lpo>=MAX_PAGE_PER_BLOCK) {
ml_lba++;
if (ml_lba>=ml_data_blk_count) {
ml_state=ML_CLOSE;
return 1;
}
ml_pba=ml_get_log2phy(ml_lba);
if (ml_pba==BLK_NA) return 1;
ml_findlog(ml_lba);
ml_lpo=0;
}
if (ml_curlog) { //对于log,页内也存在映射
t_po po=ml_curlog->ppo[ml_lpo];
if (po==INDEX_NA) ret=ll_read(ml_pba,ml_lpo,ml_buffer);
else ret=ll_read(ml_curlog->pba,po,ml_buffer);
}
else {
ret=ll_read(ml_pba,ml_lpo,ml_buffer);
}
memcpy (datap,ml_buffer,MAX_DATA_SIZE);
ml_lpo++;
if (ret==LL_OK) return 0;
else if (ret==LL_ERASED) return 0; //erased
return 1;
}
return 1;
}
/****************************************************************************
*
* ml_close
*
* closing sector reading or writing
*
* RETURNS
*
* 0 - if success
* other if any error
*
***************************************************************************/
t_bit ml_close() {
t_bit ret=0;
if (ml_state==ML_INIT) return 1;
if (ml_seccou) ret=1;
if (ml_state==ML_ABORT) ret=1;
ml_state=ML_CLOSE;
return ret;
}
/****************************************************************************
*
* End of mlayer.c
*
***************************************************************************/
#endif //_MLAYER_C_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -