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

📄 mlayer.c

📁 一个nand flash管理的算法(匈牙利算法)
💻 C
📖 第 1 页 / 共 3 页
字号:
	return 0;
}

/****************************************************************************
 *
 * ml_save_map
 *
 * Save map informations (fragments, free table modification)
 *
 * RETURNS
 *
 * 0 - if success
 * other if any error
 *
 ***************************************************************************/

static t_bit ml_save_map() {
ST_MAPBLOCK  *map=get_mapblock(ml_frag.current);
ST_SPARE *sptr;
char domap=0;
unsigned char cou;

	DEBPR0("ml_save_map\n")

	if (!map) return 1; //fatal

	for (;;) {
again:
		if (map->ppo==MAX_PAGE_PER_BLOCK || domap) {

			unsigned char index = ml_alloc();
			if (index==INDEX_NA) return 1; //fatal

			map->pba=gl_freetable[index];
			map->ppo=0;
			wear_updatedynamicinfo(index,gl_wear_allocstruct.free_wear);

			map->ref_count++;   //以ref_count来区分最新的map block

			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_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_freetable[index]|=FT_MAP;

			DEBPR3("map_pba %d flt %04x domap %d\n",map->pba,gl_freetable[index],domap)
		}

		if (bb_flush()) return 1; //fatal

		sptr=GET_SPARE_AREA(ml_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=ml_frag.current;
	
		for (cou=0; cou<MAX_MAP_BLK; cou++) {
			ml_mapinfo->index[cou]=map->index[cou]; //copy history
		}

		ml_mapinfo->last_pba=map->last_pba;
		ml_mapinfo->last_ppo=map->last_ppo;

		ml_mapinfo->mappagecou_lo++;
		if (!ml_mapinfo->mappagecou_lo)	ml_mapinfo->mappagecou_hi++; /* 64bit counter */

		if (!ml_chk_frag(ml_frag.current)) {
			return 1; //fatal
		}

		if (!wll_writedouble(30,map->pba,map->ppo,(unsigned char*)ml_frag.ppba,(unsigned char*)gl_freetable)) {

			if (!domap) {
				map->last_pba=map->pba;
				map->last_ppo=map->ppo;

				ml_mapdir[ml_frag.current].pba=map->pba;
				ml_mapdir[ml_frag.current].ppo=map->ppo;
				ml_mapdir[ml_frag.current].index=1;

				map->ppo++;
			}
			else {
				unsigned char frag;
				unsigned char *sou,*dest;

				map->ppo++;
	
				sptr=GET_SPARE_AREA(ml_buffer);

				for (frag=0;frag<MAX_FRAG_PER_BLK;) {
	
					dest=ml_buffer;
					if (ml_chk_frag((unsigned char)(frag+map->start_frag))) {
						memcpy(dest,ml_frag.ppba,MAX_DATA_SIZE/2);
					}
					else {
						if (!ll_read(map->mapdir[frag].pba,map->mapdir[frag].ppo,ml_buffer2)) {
							sou=ml_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,ml_frag.ppba,MAX_DATA_SIZE/2);
					}
					else {
						if (!ll_read(map->mapdir[frag].pba,map->mapdir[frag].ppo,ml_buffer2)) {
							sou=ml_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,map->pba,map->ppo,ml_buffer)) goto again;

					map->ppo++;
				}
	
				ml_createmap(map,1);

				map->last_pba=map->pba;
				map->last_ppo=0;  //because of domap!

			}

			wear_releasedynamiclock();
			ml_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=0;	//summary of wears
unsigned long wear_count=0;	//counting number of wears 
unsigned long wear_average=0;
unsigned char idx;
unsigned char cou;
t_ba pba,lba;
t_po po,lastpo;
ST_SPARE *sptr;
ST_LOG *log;

	DEBPR0("ml_init\n");

	if (ml_lowinit()) return 1;

	sptr=GET_SPARE_AREA(ml_buffer);

//search last map blk
	for (pba=0; pba<MAX_BLOCK; pba++) {

		wear_count++; //increase counts

		if (!ll_read(pba,0,ml_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
								  ); 
			}
		}
	}

	ml_stepback=0;

	for (cou=0; cou<MAX_NUM_OF_DIF_MAP; cou++) {
		ST_MAPBLOCK *map=&ml_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(map->pba,(unsigned char)(MAX_PAGE_PER_BLOCK-po-1),ml_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(map->pba,po,ml_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(map->pba,map->ppo,ml_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: ml_buildmap at idx %d\n",idx);
				return 1; //fatal
			}
		}
	}


	{
//finding last fltable
		ST_MAPBLOCK *mapcur=ml_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(map->last_pba,map->last_ppo,ml_basebuff)) return 1; //fatal

		ml_mapinfo->mappagecou_lo=ml_max_mappagecou_lo;
		ml_mapinfo->mappagecou_hi=ml_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
	ml_logblocknum=0;
	log=ml_log;
	for (idx=0; idx<MAX_FREE_BLOCK; idx++) {
		if ((gl_freetable[idx]&(FT_MAP|FT_LOG))==FT_LOG) {
			pba=(t_ba)(gl_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(pba,(unsigned char)(MAX_PAGE_PER_BLOCK-po-1),ml_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(pba,po,ml_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++;
				ml_logblocknum++;
			}
			else {
				gl_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_freetable[idx]&FT_BAD)!=FT_BAD) {
		 	pba=(t_ba)(gl_freetable[idx]&FT_ADDRMASK);
			if (ll_read(pba,0,ml_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(pba,0,ml_buffer)) {
            wear_updatestaticinfo(lba, 0);  
        } else {
            wear_updatestaticinfo(lba, sptr->wear);  /* only data block could be updated */
        }
        ml_data_blk_count++;
	}

	if (ml_stepback) {
		t_ba lba=ml_stepback->start_frag;

		lba*=MAX_FRAGSIZE;

		ml_stepback->ppo=MAX_PAGE_PER_BLOCK;
		ml_stepback->indexcou=MAX_MAP_BLK; //force map merge

		if (ml_get_log2phy(lba)==BLK_NA) return 1;
		if (ml_save_map()) return 1;
	}

	ml_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(ml_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,map->pba,map->ppo,ml_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 ml_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(ml_buffer);

	if (ml_lowinit()) return 1;

	for (index=0,pba=0;index<MAX_FREE_BLOCK+MAX_RESERVED_BLOCK; pba++,index++) {
		int ret=ll_read(pba,0,ml_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(pba)) {
				sptr->bad_tag=0; //signalling bad block
				ll_write(pba,0,ml_buffer);
				DEBPR2("Bad Block found (erased) pba %d [%4x]",pba,pba);
				continue; //cannot be erased so bad block
			}
		}

		if (index<MAX_FREE_BLOCK) {
			gl_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=&ml_mapblocks[cou];

		index = ml_alloc();
		if (index==INDEX_NA) return 1; //fatal
		map->pba=gl_freetable[index];
		map->ppo=0;
		gl_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 (ml_mapinfo,0xff,sizeof(ST_MAPINFO));

//create MAP dir from remaining blocks
	ppba=(t_ba *)ml_fragbuff;
	fidx=0;
	frag=0;
	lbacou=0;

	for (;pba<MAX_BLOCK;pba++) {
		int ret=ll_read(pba,0,ml_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(pba)) {
				sptr->bad_tag=0; //signalling bad block
				ll_write(pba,0,ml_buffer);
				DEBPR2("Bad Block found (erased) pba %d [%4x]",pba,pba);
				continue; //cannot be erased so bad block
			}
		}

		ml_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;
		}
	}

⌨️ 快捷键说明

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