📄 mlayer.c
字号:
if (map->indexcou==MAX_MAP_BLK) {
domap=1;
}
if (domap) {
unsigned char idx;
for (idx=0; idx<MAX_MAP_BLK;idx++) {
unsigned char midx=map->index[idx];
if (midx!=INDEX_NA) {
gl_mlayer->freetable[midx]&=~FT_MAP;
wear_updatedynamicinfo(midx,WEAR_NA); //still locked
map->index[idx]=INDEX_NA;
}
}
map->indexcou=0;
}
map->index[map->indexcou++]=index;
gl_mlayer->freetable[index]|=FT_MAP;
DEBPR3("map_pba %d flt %04x domap %d\n",map->pba,gl_mlayer->freetable[index],domap)
}
if (bb_flush()) return 1; //fatal
sptr=GET_SPARE_AREA(gl_mlayer->basebuff);
if (!map->ppo) {
sptr->wear=gl_wear_allocstruct.free_wear;
sptr->u.map.ref_count=map->ref_count;
sptr->block_type=map->block_type;
sptr->bad_tag=0xff;
}
sptr->page_state=STA_MAPPAGE;
sptr->frag=gl_mlayer->frag.current;
for (cou=0; cou<MAX_MAP_BLK; cou++) {
gl_mlayer->mapinfo->index[cou]=map->index[cou]; //copy history
}
gl_mlayer->mapinfo->last_pba=map->last_pba;
gl_mlayer->mapinfo->last_ppo=map->last_ppo;
gl_mlayer->mapinfo->mappagecou_lo++;
if (!gl_mlayer->mapinfo->mappagecou_lo) gl_mlayer->mapinfo->mappagecou_hi++; /* 64bit counter */
if (!ml_chk_frag(gl_mlayer->frag.current)) {
return 1; //fatal
}
if (!wll_writedouble(30,(t_ba)(gl_mlayer->start_pba+map->pba),map->ppo,(unsigned char*)gl_mlayer->frag.ppba,(unsigned char*)gl_mlayer->freetable)) {
if (!domap) {
map->last_pba=map->pba;
map->last_ppo=map->ppo;
gl_mlayer->mapdir[gl_mlayer->frag.current].pba=map->pba;
gl_mlayer->mapdir[gl_mlayer->frag.current].ppo=map->ppo;
gl_mlayer->mapdir[gl_mlayer->frag.current].index=1;
map->ppo++;
}
else {
unsigned char frag;
unsigned char *sou,*dest;
map->ppo++;
sptr=GET_SPARE_AREA(gl_buffer);
for (frag=0;frag<MAX_FRAG_PER_BLK;) {
dest=gl_buffer;
if (ml_chk_frag((unsigned char)(frag+map->start_frag))) {
memcpy(dest,gl_mlayer->frag.ppba,MAX_DATA_SIZE/2);
}
else {
if (!ll_read((t_ba)(gl_mlayer->start_pba+map->mapdir[frag].pba),map->mapdir[frag].ppo,gl_buffer2)) {
sou=gl_buffer2;
if (!map->mapdir[frag].index) sou+=MAX_DATA_SIZE/2;
memcpy(dest,sou,MAX_DATA_SIZE/2);
}
else memset(dest,0xff,MAX_DATA_SIZE);
}
frag++;
dest+=MAX_DATA_SIZE/2;
if (ml_chk_frag((unsigned char)(frag+map->start_frag))) {
memcpy(dest,gl_mlayer->frag.ppba,MAX_DATA_SIZE/2);
}
else {
if (!ll_read((t_ba)(gl_mlayer->start_pba+map->mapdir[frag].pba),map->mapdir[frag].ppo,gl_buffer2)) {
sou=gl_buffer2;
if (!map->mapdir[frag].index) sou+=MAX_DATA_SIZE/2;
memcpy(dest,sou,MAX_DATA_SIZE/2);
}
else memset(dest,0xff,MAX_DATA_SIZE);
}
frag++;
sptr->page_state=STA_ORIGFRAG;
if (wll_write(31,(t_ba)(gl_mlayer->start_pba+map->pba),map->ppo,gl_buffer)) goto again;
map->ppo++;
}
ml_createmap(map,1);
map->last_pba=map->pba;
map->last_ppo=0; //because of domap!
}
wear_releasedynamiclock();
gl_save_map_need=0;
return 0;
}
else {
if (!map->ppo) {
domap=1;
}
else {
map->ppo++;
}
}
}
}
/****************************************************************************
*
* ml_init
*
* Initialize this layer, this function must be called at the begining
*
* RETURNS
*
* 0 - if ok
* other if any error
*
***************************************************************************/
t_bit ml_init() {
unsigned long wear_sum;
unsigned long wear_count;
unsigned long wear_average;
unsigned char idx;
unsigned char cou;
unsigned char mlcou;
t_ba pba,lba;
t_po po,lastpo;
ST_SPARE *sptr;
ST_LOG *log;
DEBPR0("ml_init\n");
gl_state=ML_INIT;
if (ll_init()) return 1;
gl_stepback=0;
for (mlcou=0; mlcou<MLAYER_SETS; mlcou++) {
gl_mlayer=&mlayers[mlcou];
gl_mlayer->start_pba=(t_ba)(MAX_BLOCK*(unsigned short)mlcou);
gl_mlayer->laynum=mlcou;
wear_sum=0; //summary of wears
wear_count=0; //counting number of wears
wear_average=0;
if (ml_lowinit()) return 1;
sptr=GET_SPARE_AREA(gl_buffer);
//search last map blk
for (pba=0; pba<MAX_BLOCK; pba++) {
wear_count++; //increase counts
if (!ll_read((t_ba)(gl_mlayer->start_pba+pba),0,gl_buffer)) {
if (sptr->wear<WEAR_NA) wear_sum+=sptr->wear; //add to summary
switch (sptr->block_type) {
case BLK_TYPE_MAP_00:
case BLK_TYPE_MAP_01:
case BLK_TYPE_MAP_02:
case BLK_TYPE_MAP_03: check_reference_count(
(unsigned char)(sptr->block_type-BLK_TYPE_MAP_00),
sptr->u.map.ref_count,pba
);
}
}
}
for (cou=0; cou<MAX_NUM_OF_DIF_MAP; cou++) {
ST_MAPBLOCK *map=&gl_mlayer->mapblocks[cou];
if (map->pba==BLK_NA) return 1; //fatal, no map blk found
//search last erased only page
lastpo=MAX_PAGE_PER_BLOCK;
for (po=0;po<MAX_PAGE_PER_BLOCK;po++) {
int ret=ll_read((t_ba)(gl_mlayer->start_pba+map->pba),(unsigned char)(MAX_PAGE_PER_BLOCK-po-1),gl_buffer);
if (ret==LL_ERASED) lastpo=(unsigned char)(MAX_PAGE_PER_BLOCK-po-1);
else break;
}
//search last po in block
map->ppo=INDEX_NA;
for (po=0;po<lastpo;po++) {
int ret=ll_read((t_ba)(gl_mlayer->start_pba+map->pba),po,gl_buffer);
if (ret==LL_OK) {
if (sptr->page_state==STA_MAPPAGE) {
map->ppo=po;
}
}
}
if (map->ppo==INDEX_NA) return 1; //fatal, no map blk found
//read it
if (ll_read((t_ba)(gl_mlayer->start_pba+map->pba),map->ppo,gl_mlayer->basebuff)) return 1; //fatal
map->last_pba=map->pba; //update last information
map->last_ppo=map->ppo;
map->ppo=lastpo;
for (idx=0; idx<MAX_MAP_BLK; idx++) {
if (ml_buildmap(map,idx)) {
DEBPR1("ERROR: gl_mlayer->buildmap at idx %d\n",idx);
return 1; //fatal
}
}
}
{
//finding last fltable
ST_MAPBLOCK *mapcur=gl_mlayer->mapblocks;
unsigned long mappagecou_lo=mapcur->mappagecou_lo;
unsigned long mappagecou_hi=mapcur->mappagecou_hi;
ST_MAPBLOCK *map=mapcur;
for (cou=1,mapcur++; cou<MAX_NUM_OF_DIF_MAP;cou++,mapcur++) {
if (mapcur->mappagecou_hi>mappagecou_hi) {
mappagecou_lo=mapcur->mappagecou_lo;
mappagecou_hi=mapcur->mappagecou_hi;
map=mapcur;
}
else if (mapcur->mappagecou_hi==mappagecou_hi && mapcur->mappagecou_lo>mappagecou_lo) {
mappagecou_lo=mapcur->mappagecou_lo;
mappagecou_hi=mapcur->mappagecou_hi;
map=mapcur;
}
}
if (ll_read((t_ba)(gl_mlayer->start_pba+map->last_pba),map->last_ppo,gl_mlayer->basebuff)) return 1; //fatal
gl_mlayer->mapinfo->mappagecou_lo=gl_mlayer->max_mappagecou_lo;
gl_mlayer->mapinfo->mappagecou_hi=gl_mlayer->max_mappagecou_hi; //write back the maximum found
}
if (bb_init(MAX_RESERVED_BLOCK)) return 1; //here the BB page is loaded!!!
//building log blocks
gl_mlayer->logblocknum=0;
log=gl_mlayer->log;
for (idx=0; idx<MAX_FREE_BLOCK; idx++) {
if ((gl_mlayer->freetable[idx]&(FT_MAP|FT_LOG))==FT_LOG) {
pba=(t_ba)(gl_mlayer->freetable[idx]&FT_ADDRMASK);
log->lastppo=MAX_PAGE_PER_BLOCK;
log->pba=pba;
log->switchable=1;
log->index=idx;
lastpo=MAX_PAGE_PER_BLOCK;
for (po=0;po<MAX_PAGE_PER_BLOCK;po++) { //searching the last page from top
int ret=ll_read((t_ba)(gl_mlayer->start_pba+pba),(unsigned char)(MAX_PAGE_PER_BLOCK-po-1),gl_buffer);
if (ret==LL_ERASED) lastpo=(unsigned char)(MAX_PAGE_PER_BLOCK-po-1);
else break;
}
log->lastppo=lastpo;
for (po=0; po<lastpo; po++) { //building log blk
int ret=ll_read((t_ba)(gl_mlayer->start_pba+pba),po,gl_buffer);
if (ret==LL_OK) {
log->ppo[sptr->u.log.lpo]=po;
log->lba=sptr->u.log.lba;
if (po!=sptr->u.log.lpo) log->switchable=0;
if (!po) log->wear=sptr->wear;
}
else log->switchable=0; //if error or hole in the log block
}
if (log->lastppo!=0) {
log++;
gl_mlayer->logblocknum++;
}
else {
gl_mlayer->freetable[idx]&=~FT_LOG; //nothing was written, so remove log block flag
log->lastppo=INDEX_NA; //reset data in not used log blk
log->pba=BLK_NA;
}
}
}
if (wear_count) wear_average=wear_sum/wear_count; //calculate current average
//fill dynamic wear info table
for (idx=0; idx<MAX_FREE_BLOCK; idx++) {
if ((gl_mlayer->freetable[idx]&FT_BAD)!=FT_BAD) {
pba=(t_ba)(gl_mlayer->freetable[idx]&FT_ADDRMASK);
if (ll_read((t_ba)(gl_mlayer->start_pba+pba),0,gl_buffer)==LL_OK) {
wear_updatedynamicinfo(idx,sptr->wear);
}
else {
wear_updatedynamicinfo(idx,wear_average);
}
}
}
wear_releasedynamiclock();
//fill static wear info
for(lba=0; lba<MAX_BLOCK; lba++) {
pba=ml_get_log2phy(lba);
if (pba==BLK_NA) break;
if (ll_read((t_ba)(gl_mlayer->start_pba+pba),0,gl_buffer)) {
wear_updatestaticinfo(lba, 0);
} else {
wear_updatestaticinfo(lba, sptr->wear); /* only data block could be updated */
}
gl_mlayer->data_blk_count++;
}
if (gl_stepback) {
t_ba lba=gl_stepback->start_frag;
lba*=MAX_FRAGSIZE;
gl_stepback->ppo=MAX_PAGE_PER_BLOCK;
gl_stepback->indexcou=MAX_MAP_BLK; //force map merge
if (ml_get_log2phy(lba)==BLK_NA) return 1;
if (ml_save_map()) return 1;
}
}
gl_state=ML_CLOSE;
return 0;
}
/****************************************************************************
*
* write_frags
*
* subfunction for formatting to write current fragments in fragbuff
*
* INPUTS
*
* frag - current frag number
*
* RETURNS
*
* 0 - if successfuly
* other if any error
*
***************************************************************************/
static t_bit write_frags(unsigned char frag) {
ST_SPARE *sptr=GET_SPARE_AREA(gl_mlayer->fragbuff);
ST_MAPBLOCK *map=get_mapblock(frag);
if (!map->ppo) {
sptr->wear=1;//gl_wear_allocstruct.free_wear;
sptr->u.map.ref_count=map->ref_count;
sptr->block_type=map->block_type;
sptr->bad_tag=0xff;
}
sptr->page_state=STA_ORIGFRAG;
if (wll_write(1,(t_ba)(gl_mlayer->start_pba+map->pba),map->ppo,gl_mlayer->fragbuff)) return 1; //fatal
map->ppo++;
return 0;
}
/****************************************************************************
*
* ml_getmaxsector
*
* retreives the maximum number of sectors can be used in the system
*
* RETURNS
*
* maximum number of sectors
*
***************************************************************************/
unsigned long ml_getmaxsector() {
return gl_mlayer->data_blk_count;
}
/****************************************************************************
*
* ml_format
*
* Formatting the layer, this function must be called once at manufacturing
*
* RETURNS
*
* 0 - if success
* other if any error
*
***************************************************************************/
t_bit ml_format() {
unsigned long lbacou;
unsigned short fidx;
unsigned char index;
unsigned char cou;
unsigned char frag;
t_ba pba;
t_ba *ppba;
ST_SPARE *sptr=GET_SPARE_AREA(gl_buffer);
unsigned char mlcou;
gl_state=ML_INIT;
if (ll_init()) return 1;
for (mlcou=0; mlcou<MLAYER_SETS; mlcou++) {
gl_mlayer=&mlayers[mlcou];
gl_mlayer->start_pba=(t_ba)(MAX_BLOCK*(unsigned short)mlcou);
gl_mlayer->laynum=mlcou;
if (ml_lowinit()) return 1;
for (index=0,pba=0;index<MAX_FREE_BLOCK+MAX_RESERVED_BLOCK; pba++,index++) {
int ret=ll_read((t_ba)(gl_mlayer->start_pba+pba),0,gl_buffer);
if (ret==LL_OK || ret==LL_ERROR) {
if (sptr->bad_tag!=0xff) {
DEBPR2("Bad Block found (badtag) pba %d [%4x]",pba,pba);
continue; //bad block
}
if (ll_erase((t_ba)(gl_mlayer->start_pba+pba))) {
sptr->bad_tag=0; //signalling bad block
ll_write((t_ba)(gl_mlayer->start_pba+pba),0,gl_buffer);
DEBPR2("Bad Block found (erased) pba %d [%4x]",pba,pba);
continue; //cannot be erased so bad block
}
}
if (index<MAX_FREE_BLOCK) {
gl_mlayer->freetable[index]=pba;
wear_updatedynamicinfo((unsigned char)index,0);
}
else {
if (bb_addreserved(pba)) {
return 1;
}
}
}
wear_releasedynamiclock();
//allocate MAP block
for (cou=0; cou<MAX_NUM_OF_DIF_MAP; cou++) {
ST_MAPBLOCK *map=&gl_mlayer->mapblocks[cou];
index = ml_alloc();
if (index==INDEX_NA) return 1; //fatal
map->pba=gl_mlayer->freetable[index];
map->ppo=0;
gl_mlayer->freetable[index]|=FT_MAP;
wear_updatedynamicinfo(index,gl_wear_allocstruct.free_wear);
map->indexcou=0;
map->index[map->indexcou++]=index;
map->ref_count=1;
}
memset (gl_mlayer->mapinfo,0xff,sizeof(ST_MAPINFO));
//create MAP dir from remaining blocks
ppba=(t_ba *)gl_mlayer->fragbuff;
fidx=0;
frag=0;
lbacou=0;
for (;pba<MAX_BLOCK;pba++) {
int ret=ll_read((t_ba)(gl_mlayer->start_pba+pba),0,gl_buffer);
lbacou++;
if (ret==LL_OK || ret==LL_ERROR) {
if (sptr->bad_tag!=0xff) {
DEBPR2("Bad Block found (badtag) pba %d [%4x]",pba,pba);
continue; //bad block
}
if (ll_erase((t_ba)(gl_mlayer->start_pba+pba))) {
sptr->bad_tag=0; //signalling bad block
ll_write((t_ba)(gl_mlayer->start_pba+pba),0,gl_buffer);
DEBPR2("Bad Block found (erased) pba %d [%4x]",pba,pba);
continue; //cannot be erased so bad block
}
}
gl_mlayer->data_blk_count++;
ppba[fidx++]=pba;
if (fidx==MAX_FRAGSIZE*2) {
if (write_frags(frag)) return 1; //fatal
fidx=0;
frag+=2;
}
}
for (;lbacou<MAX_BLOCK;lbacou++) { //fill remaining with BLK_NA
ppba[fidx++]=BLK_NA;
if (fidx==MAX_FRAGSIZE*2) {
if (write_frags(frag)) return 1; //fatal
fidx=0;
frag+=2;
}
}
gl_mlayer->mapinfo->mappagecou_hi=0;
gl_mlayer->mapinfo->mappagecou_lo=0;
for (cou=0; cou<MAX_NUM_OF_DIF_MAP; cou++) {
ST_MAPBLOCK *map=&gl_mlayer->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;
}
}
gl_state=ML_CLOSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -