📄 mlayer.c
字号:
return 0;
}
/****************************************************************************
*
* ml_findlog
*
* Searching for a log block (check if logical block is logged)
* it sets gl_mlayer->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=gl_mlayer->log;
long a;
for (a=0; a<MAX_LOG_BLOCK; a++,log++) {
if (log->lba==lba) {
gl_mlayer->curlog=log;
return 1;
}
}
gl_mlayer->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() {
unsigned long wear;
t_ba pba;
gl_mlayer->lbastatic++;
if (gl_mlayer->lbastatic>=gl_mlayer->data_blk_count) gl_mlayer->lbastatic=0;
pba=ml_get_log2phy(gl_mlayer->lbastatic);
if (pba==BLK_NA) return; //nothing to do
if (!ll_read((t_ba)(gl_mlayer->start_pba+pba),0,gl_buffer)) {; //get original
wear=GET_SPARE_AREA(gl_buffer)->wear;
if (wear<WEAR_NA) wear_updatestaticinfo(gl_mlayer->lbastatic,wear);
else wear_updatestaticinfo(gl_mlayer->lbastatic,0);
}
else wear_updatestaticinfo(gl_mlayer->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_mlayer->freetable[index];
if (wll_erase(101,(t_ba)(gl_mlayer->start_pba+d_pba))) {
d_pba=bb_setasbb(d_pba); //get a reserved block
if (d_pba==BLK_NA) { //if reserved not available
gl_mlayer->freetable[index] |= FT_BAD; //signal it as BAD
}
else {
wear_updatedynamicinfo(index,0); //set new reserved block wear
gl_mlayer->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((t_ba)(gl_mlayer->start_pba+s_pba),po,gl_buffer);
if (!po) {
ST_SPARE *sptr=GET_SPARE_AREA(gl_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,(t_ba)(gl_mlayer->start_pba+d_pba),po,gl_buffer)) return; //we can stop static swap
}
ml_set_log2phy(lba,d_pba);
wear_updatestaticinfo(lba,gl_wear_allocstruct.free_wear);
gl_mlayer->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;
t_ba pba;
index=ml_alloc();
if (index==INDEX_NA) return 1;
pba=gl_mlayer->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_mlayer->freetable[index]=(t_ba)(pba | FT_LOG);
wear_updatedynamicinfo(index,log->wear); //locked now
gl_mlayer->logblocknum++;
memset(log->ppo,INDEX_NA,sizeof(log->ppo));
gl_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) {
unsigned char mlcou;
t_ba lba;
if (gl_state==ML_INIT) return 1;
lba=(t_ba)(sector/MAX_PAGE_PER_BLOCK);
for (mlcou=0; mlcou<MLAYER_SETS; mlcou++) {
gl_mlayer=&mlayers[mlcou];
if (lba<gl_mlayer->data_blk_count) goto ok;
lba=(t_ba)(lba-gl_mlayer->data_blk_count);
}
return 1; //not found
ok:
gl_state=ML_CLOSE;
gl_seccou=secnum;
gl_lba=lba;
gl_lpo=(t_po)(sector%MAX_PAGE_PER_BLOCK);
if (gl_lba>=gl_mlayer->data_blk_count) return 1;
if (gl_lpo>=MAX_PAGE_PER_BLOCK) return 1;
if (mode==ML_READ) gl_state=ML_PENDING_READ;
else if (mode==ML_WRITE) gl_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;
gl_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((t_ba)(gl_mlayer->start_pba+orig_pba),0,gl_buffer)) {//get original
wear=GET_SPARE_AREA(gl_buffer)->wear;
}
else wear=0;
gl_mlayer->freetable[log->index]=orig_pba; //release original
if (wear<WEAR_NA) wear_updatedynamicinfo(log->index,wear);
else wear_updatedynamicinfo(log->index,0);
gl_mlayer->curlog->lba=BLK_NA;
gl_mlayer->logblocknum--;
return 0;
}
again:
index=ml_alloc();
if (index==INDEX_NA) return 1;
pba=gl_mlayer->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((t_ba)(gl_mlayer->start_pba+orig_pba),po,gl_buffer);
//) continue; //get original
if (!po) wear=GET_SPARE_AREA(gl_buffer)->wear;
}
else {
// if (po &&
ll_read((t_ba)(gl_mlayer->start_pba+log->pba),lpo,gl_buffer);
//) continue; //get logged
}
if (!po) {
ST_SPARE *sptr=GET_SPARE_AREA(gl_buffer);
sptr->wear=gl_wear_allocstruct.free_wear;
sptr->block_type=BLK_TYPE_DAT;
sptr->bad_tag=0xff;
}
if (wll_write(20,(t_ba)(gl_mlayer->start_pba+pba),po,gl_buffer)) goto again;
}
if (wear==WEAR_NA) {
if (!ll_read((t_ba)(gl_mlayer->start_pba+orig_pba),0,gl_buffer)) {
wear=GET_SPARE_AREA(gl_buffer)->wear;//get original
}
else {
wear=0;
}
}
gl_mlayer->freetable[index]=orig_pba; //release original
if (wear<WEAR_NA) wear_updatedynamicinfo(index,wear);
else wear_updatedynamicinfo(index,0);
gl_mlayer->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);
gl_mlayer->curlog->lba=BLK_NA;
gl_mlayer->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 (gl_mlayer->logblocknum < MAX_LOG_BLOCK) {
if (ml_findlog(BLK_NA)) { //find a free
return ml_alloclog(gl_mlayer->curlog,lba);
}
}
{
ST_LOG *log=&gl_mlayer->log[gl_mlayer->logmerge++];
if (gl_mlayer->logmerge>=MAX_LOG_BLOCK) gl_mlayer->logmerge=0;
gl_mlayer->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 (gl_state==ML_PENDING_WRITE) {
if (!ml_findlog(gl_lba)) {
if (ml_releaselog(gl_lba)) return 1;
}
gl_state=ML_WRITE;
}
if (gl_state==ML_WRITE) {
if (!gl_seccou--) {
gl_state=ML_ABORT;
return 1;
}
if (gl_lpo>=MAX_PAGE_PER_BLOCK) {
gl_lba++;
if (gl_lba>=gl_mlayer->data_blk_count) {
if (gl_mlayer->laynum+1<MLAYER_SETS) {
gl_mlayer++;
gl_lba=0;
}
else {
gl_state=ML_CLOSE;
return 1;
}
}
if (!ml_findlog(gl_lba)) {
if (ml_releaselog(gl_lba)) return 1;
}
gl_lpo=0;
}
if (gl_mlayer->curlog->lastppo>=MAX_PAGE_PER_BLOCK) {
if (ml_domerge(gl_mlayer->curlog)) return 1;
if (ml_alloclog(gl_mlayer->curlog,gl_lba)) return 1; //allocate a new log block
}
memcpy (gl_buffer,datap,MAX_DATA_SIZE);
{
ST_SPARE *sptr=GET_SPARE_AREA(gl_buffer);
if (!gl_mlayer->curlog->lastppo) {
sptr->wear=gl_mlayer->curlog->wear;
sptr->block_type=BLK_TYPE_DAT;
sptr->bad_tag=0xff;
}
sptr->u.log.lba=gl_lba;
sptr->u.log.lpo=gl_lpo;
}
if (gl_lpo!=gl_mlayer->curlog->lastppo) gl_mlayer->curlog->switchable=0; //not switchable from this point
gl_mlayer->curlog->ppo[gl_lpo++]=gl_mlayer->curlog->lastppo;
wll_write(40,(t_ba)(gl_mlayer->start_pba+gl_mlayer->curlog->pba),gl_mlayer->curlog->lastppo++,gl_buffer);
if (gl_save_map_need) {
ml_save_map();
ml_dostatic();
}
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 (gl_state==ML_PENDING_READ) {
gl_mlayer->pba=ml_get_log2phy(gl_lba);
if (gl_mlayer->pba==BLK_NA) return 1;
ml_findlog(gl_lba);
gl_state=ML_READ;
}
if (gl_state==ML_READ) {
int ret;
if (!gl_seccou--) {
gl_state=ML_ABORT;
return 1;
}
if (gl_lpo>=MAX_PAGE_PER_BLOCK) {
gl_lba++;
if (gl_lba>=gl_mlayer->data_blk_count) {
if (gl_mlayer->laynum+1<MLAYER_SETS) {
gl_mlayer++; //goto next set
gl_lba=0;
}
else {
gl_state=ML_CLOSE;
return 1;
}
}
gl_mlayer->pba=ml_get_log2phy(gl_lba);
if (gl_mlayer->pba==BLK_NA) return 1;
ml_findlog(gl_lba);
gl_lpo=0;
}
if (gl_mlayer->curlog) {
t_po po=gl_mlayer->curlog->ppo[gl_lpo];
if (po==INDEX_NA) ret=ll_read((t_ba)(gl_mlayer->start_pba+gl_mlayer->pba),gl_lpo,gl_buffer);
else ret=ll_read((t_ba)(gl_mlayer->start_pba+gl_mlayer->curlog->pba),po,gl_buffer);
}
else {
ret=ll_read((t_ba)(gl_mlayer->start_pba+gl_mlayer->pba),gl_lpo,gl_buffer);
}
memcpy (datap,gl_buffer,MAX_DATA_SIZE);
gl_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 (gl_state==ML_INIT) return 1;
if (gl_seccou) ret=1;
if (gl_state==ML_ABORT) ret=1;
gl_state=ML_CLOSE;
return ret;
}
/****************************************************************************
*
* End of emlayer.c
*
***************************************************************************/
#endif //_MLAYER_C_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -