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

📄 mlayer.c

📁 一个nand flash管理的算法(匈牙利算法)
💻 C
📖 第 1 页 / 共 3 页
字号:
  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 + -