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

📄 mlayer.c

📁 一个nand flash管理的算法(匈牙利算法)
💻 C
📖 第 1 页 / 共 3 页
字号:
#ifndef _MLAYER_C_
#define _MLAYER_C_

/****************************************************************************
 *
 *            Copyright (c) 2005 by HCC Embedded 
 *
 * This software is copyrighted by and is the sole property of 
 * HCC.  All rights, title, ownership, or other interests
 * in the software remain the property of HCC.  This
 * software may only be used in accordance with the corresponding
 * license agreement.  Any unauthorized use, duplication, transmission,  
 * distribution, or disclosure of this software is expressly forbidden.
 *
 * This Copyright notice may not be removed or modified without prior
 * written consent of HCC.
 *
 * HCC reserves the right to modify this software without notice.
 *
 * HCC Embedded
 * Budapest 1132
 * Victor Hugo Utca 11-15
 * Hungary
 *
 * Tel:  +36 (1) 450 1302
 * Fax:  +36 (1) 450 1303
 * http: www.hcc-embedded.com
 * email: info@hcc-embedded.com
 *
 ***************************************************************************/

#include "llayer.h"
#include "mlayer.h"
#include "fil_wear.h"
#include "fil_bad.h"
#include "prgmacro.h"
#include "string.h"
#include "mdebug.h"


/****************************************************************************
 *
 *	global Variables
 *
 ***************************************************************************/


/****************************************************************************
 *
 *	static Variables
 *
 ***************************************************************************/

ST_MAPBLOCK *gl_stepback;

unsigned char gl_buffer[MAX_PAGE_SIZE];
unsigned char gl_buffer2[MAX_PAGE_SIZE];
unsigned char gl_state;
unsigned char gl_save_map_need;
unsigned long gl_seccou;

t_ba gl_lba;
t_po gl_lpo;

ST_MLAYER mlayers[MLAYER_SETS];
ST_MLAYER *gl_mlayer;

/****************************************************************************
 *
 * ml_chk_frag
 *
 * function checks if requested fragment is in the cache area
 * and set ppba pointer its start address if found
 *
 * RETURNS
 *
 * 1 - if cached
 * 0 - if not
 *
 ***************************************************************************/

static t_bit ml_chk_frag(unsigned char frag) {
unsigned char idx; 

	for (idx=0; idx<MAX_CACHEFRAG; idx++) {
		if (gl_mlayer->frag.indexes[idx]==frag) {
			gl_mlayer->frag.ppba=gl_mlayer->frag.ppbas[idx];
			return 1;
		}
	}
	return 0;
}

/****************************************************************************
 *
 * ml_get_log2phy
 *
 * convert logical address to physical
 *
 * INPUTS
 *
 * lba - logical block address
 *
 * RETURNS
 *
 * physical address or BLK_NA if address is invalid
 *
 ***************************************************************************/

static t_ba ml_get_log2phy(t_ba lba) {
unsigned short index; 
unsigned char *buff;
	if (lba>=(MAX_BLOCK-MAX_FREE_BLOCK)) return BLK_NA;

	gl_mlayer->frag.current=(unsigned char)(lba/MAX_FRAGSIZE);
	index=(unsigned short)(lba%MAX_FRAGSIZE);

	if (ml_chk_frag(gl_mlayer->frag.current)) return gl_mlayer->frag.ppba[index];

	gl_mlayer->frag.pos++;
	if (gl_mlayer->frag.pos>=MAX_CACHEFRAG) gl_mlayer->frag.pos=0;

	buff=gl_mlayer->fragbuff+MAX_PAGE_SIZE*((unsigned short)(gl_mlayer->frag.pos));

	if (ll_read((t_ba)(gl_mlayer->start_pba+gl_mlayer->mapdir[gl_mlayer->frag.current].pba),gl_mlayer->mapdir[gl_mlayer->frag.current].ppo,buff)) {
		gl_mlayer->frag.indexes[gl_mlayer->frag.pos]=INDEX_NA;
		return BLK_NA;
	}

	if (gl_mlayer->mapdir[gl_mlayer->frag.current].index) gl_mlayer->frag.ppbas[gl_mlayer->frag.pos]=(t_ba *)buff;
	else gl_mlayer->frag.ppbas[gl_mlayer->frag.pos]=(t_ba *)(buff+MAX_DATA_SIZE/2);

	gl_mlayer->frag.ppba=gl_mlayer->frag.ppbas[gl_mlayer->frag.pos];
	gl_mlayer->frag.indexes[gl_mlayer->frag.pos]=gl_mlayer->frag.current;

	return gl_mlayer->frag.ppba[index];
}

/****************************************************************************
 *
 * ml_set_log2phy
 *
 * set logical block's physical address, 1st gl_mlayer->get_log2phy function has to
 * be called to get the fragments into the cached area and ppba must be set
 *
 * INPUTS
 *
 * lba - logical block address
 * pba - physical block address
 *
 * RETURNS
 *
 * 0 - if success
 * other if any error
 *
 ***************************************************************************/

static t_bit ml_set_log2phy(t_ba lba,t_ba pba) {
unsigned short index; 
	if (lba>=(MAX_BLOCK-MAX_FREE_BLOCK)) return 1;

	index=(unsigned short)(lba%MAX_FRAGSIZE);
	gl_mlayer->frag.ppba[index]=pba;

	return 0;
}


/****************************************************************************
 *
 * ml_createmap
 *
 * Creates complete mapdir information for a given block address
 *
 * INPUTS
 *
 * map - which map is used to 
 * ppo - physical page offset, where to start this information
 *
 ***************************************************************************/

static void ml_createmap(ST_MAPBLOCK  *map,unsigned char ppo) {
unsigned char frag;
	for (frag=0; frag<MAX_FRAG_PER_BLK;) {
		map->mapdir[frag].pba=map->pba;
		map->mapdir[frag].ppo=ppo;
		map->mapdir[frag].index=1;
		frag++;

		map->mapdir[frag].pba=map->pba;
		map->mapdir[frag].ppo=ppo;
		map->mapdir[frag].index=0;
		frag++;
		ppo++;
	}
}

/****************************************************************************
 *
 * ml_lowinit
 *
 * low level initialization, this must be called from gl_mlayer->init and gl_mlayer->format
 *
 * RETURN
 *
 * 0 - if ok
 * other if error
 *
 ***************************************************************************/

static t_bit ml_lowinit() {
int a;
	DEBOPEN;

	wear_init();

	gl_mlayer->curlog=0;
	gl_mlayer->logblocknum=0;
	gl_mlayer->logmerge=0;

	memset (gl_mlayer->log,0xff,sizeof(gl_mlayer->log)); //reset all entries

	gl_mlayer->freetable=(t_ba *)(gl_mlayer->basebuff+MAX_DATA_SIZE/2);
	gl_mlayer->mapinfo = (ST_MAPINFO *)(&gl_mlayer->freetable[MAX_FREE_BLOCK]);

	gl_mlayer->frag.pos=0;
	memset(gl_mlayer->frag.indexes,INDEX_NA,sizeof(gl_mlayer->frag.indexes));
	gl_mlayer->frag.current=INDEX_NA;

	for (a=0; a<MAX_NUM_OF_DIF_MAP; a++) {
		ST_MAPBLOCK *map=&gl_mlayer->mapblocks[a];

		map->last_pba=BLK_NA;
		map->last_ppo=INDEX_NA;

		map->block_type=(unsigned char)(BLK_TYPE_MAP_00+a);
		map->mapdir=&gl_mlayer->mapdir[a*MAX_FRAG_PER_BLK];
		map->pba=BLK_NA;
		map->ppo=INDEX_NA;
		map->ref_count=0;
		map->start_frag=(unsigned char)(a*MAX_FRAG_PER_BLK);
		map->end_frag=(unsigned char)(map->start_frag+MAX_FRAG_PER_BLK);

		map->indexcou=0;
		memset(map->index,INDEX_NA,MAX_MAP_BLK);
	}

	gl_mlayer->max_mappagecou_lo=0;
	gl_mlayer->max_mappagecou_hi=0;
	
	gl_mlayer->badblock=&gl_mlayer->mapinfo->badblock;

	gl_mlayer->badblock->index=INDEX_NA;
	gl_mlayer->badblock->pba=BLK_NA;
	gl_mlayer->badblock->ppo=INDEX_NA;

	bb_init(MAX_RESERVED_BLOCK); //here the BB page is not loaded!!! 
	//We should call this function again later if we have the MAP-PAGE

	gl_save_map_need=0;

	memset(gl_mlayer->mapdir,0xff,sizeof(gl_mlayer->mapdir));
	gl_mlayer->data_blk_count=0;

	return 0;
}									   

/****************************************************************************
 *
 * ml_buildmap
 *
 * function for rebuilding mapdir from a given index from free block table
 *
 * INPUTS
 *
 * idx  - mapinfo index, to be built from
 *
 * RETURNS
 *
 * 0 - if ok
 * other if any error
 *
 ***************************************************************************/

static t_bit ml_buildmap(ST_MAPBLOCK *map,unsigned char idx) {
t_ba pba;
t_po ppo;
unsigned char index;
ST_SPARE *sptr=GET_SPARE_AREA(gl_buffer);
unsigned char frag;
unsigned char afrm=0;
again:
	map->index[idx]=gl_mlayer->mapinfo->index[idx];
	index=gl_mlayer->mapinfo->index[idx];

	if (index!=INDEX_NA) {
		map->indexcou=(unsigned char)(idx+1); //update indexcou
	}

	DEBPR0("ml_buildmap\n");

	if (idx==0) {
		if (index==INDEX_NA) return 1; //fatal

		map->mappagecou_hi=gl_mlayer->mapinfo->mappagecou_hi;
		map->mappagecou_lo=gl_mlayer->mapinfo->mappagecou_lo; /* get the counter, if step back then it is also ok */


		if (gl_mlayer->mapinfo->mappagecou_hi>gl_mlayer->max_mappagecou_hi) {
			gl_mlayer->max_mappagecou_lo=gl_mlayer->mapinfo->mappagecou_lo;
			gl_mlayer->max_mappagecou_hi=gl_mlayer->mapinfo->mappagecou_hi; 
		}
		else if (gl_mlayer->mapinfo->mappagecou_hi==gl_mlayer->max_mappagecou_hi && gl_mlayer->mapinfo->mappagecou_lo>gl_mlayer->max_mappagecou_lo) {
			gl_mlayer->max_mappagecou_lo=gl_mlayer->mapinfo->mappagecou_lo;
			gl_mlayer->max_mappagecou_hi=gl_mlayer->mapinfo->mappagecou_hi; 	
		}

		pba=(t_ba)(gl_mlayer->freetable[index]&FT_ADDRMASK);
		ppo=0;

		if (!ll_read((t_ba)(gl_mlayer->start_pba+pba),ppo,gl_buffer)) {
			if (sptr->page_state==STA_MAPPAGE) {
				frag=sptr->frag;
				gl_mlayer->mapdir[frag].pba=pba;
				gl_mlayer->mapdir[frag].ppo=ppo;
				gl_mlayer->mapdir[frag].index=1;
				ppo=1;
			}
			else if (sptr->page_state!=STA_ORIGFRAG) {
				DEBPR1("sptr->page_state %d\n",sptr->page_state);
				return 1; //only mappage can be here, or origfrag after format
			}
			else afrm=1; //we are after format
		}
		else return 1; //must be ok!

		for (frag=0;frag<MAX_FRAG_PER_BLK; ppo++) {
			if (!ll_read((t_ba)(gl_mlayer->start_pba+pba),ppo,gl_buffer)) {
				if (sptr->page_state==STA_ORIGFRAG) {
					map->mapdir[frag].pba=pba;
					map->mapdir[frag].ppo=ppo;
					map->mapdir[frag].index=1;
					frag++;

					map->mapdir[frag].pba=pba;
					map->mapdir[frag].ppo=ppo;
					map->mapdir[frag].index=0;
					frag++;
				}
				else {
					return 1; //only mappage can be here
				}
			}
			else {
				//broken mapdir, so step back
				if (gl_stepback) return 1; //only once is allowed
				gl_stepback=map;

				if (gl_mlayer->mapinfo->last_pba==BLK_NA || gl_mlayer->mapinfo->last_ppo==INDEX_NA) return 1; //cant

				map->pba=gl_mlayer->mapinfo->last_pba;
				map->ppo=gl_mlayer->mapinfo->last_ppo;

				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++; //set next position

				goto again;
			}
		}
	}
	else {
		if (index==INDEX_NA) return 0; //nothing to do
		pba=(t_ba)(gl_mlayer->freetable[index]&FT_ADDRMASK);
		ppo=0;
	}

	for (;ppo<MAX_PAGE_PER_BLOCK; ppo++) {
		int ret=ll_read((t_ba)(gl_mlayer->start_pba+pba),ppo,gl_buffer);
		if (ret==LL_OK) {
			if (sptr->page_state==STA_MAPPAGE) {
				frag=sptr->frag;
				gl_mlayer->mapdir[frag].pba=pba;
				gl_mlayer->mapdir[frag].ppo=ppo;
				gl_mlayer->mapdir[frag].index=1;
			}
			else {
				return 1; //only mappage can be here
			}
		}
		else if (ret==LL_ERASED) continue; //maybe flashfail happened
	}

	if (afrm) {
		//we are after format
		if (ppo<MAX_FRAG_PER_BLK/2) return 1; //flt missing after format
	}

	return 0;
}


/****************************************************************************
 *
 * check_reference_count
 *
 * function check and set the latest map reference counter
 *
 * INPUTS
 *
 * mapnum - which map need to be checked
 * refcount - current reference counter
 * pba - current block physical address
 *
 ***************************************************************************/

static void check_reference_count(unsigned char mapnum,unsigned long ref_count,t_ba pba) {
ST_MAPBLOCK *map=&gl_mlayer->mapblocks[mapnum];

	if (map->pba==BLK_NA) { /* we have found the 1st map block */
		map->pba=pba;
		map->ref_count=ref_count;
	} 
	else {
		if (map->ref_count<ref_count) {
			map->pba=pba;
            map->ref_count=ref_count;
		}
	}
}

/****************************************************************************
 *
 * ml_alloc
 *
 * allocate a block from free table and erases it
 *
 * RETURNS
 *
 * index in free table or INDEX_NA if any error
 *
 ***************************************************************************/

static unsigned char ml_alloc() {
unsigned char index;

	for (;;) {	   //loop for wear alloc
		t_ba pba;

		wear_alloc();
		index=gl_wear_allocstruct.free_index;

		DEBPR1("gl_mlayer->alloc index %d\n",index);

	    if (index==INDEX_NA) {
		    return INDEX_NA; //FATAL error no free blocks are available
	    }


		pba=gl_mlayer->freetable[index];

		for (;;) { //internal loop for pba changing

			DEBPR2("gl_mlayer->alloc pba %d, %04x\n", pba,pba);

			if (wll_erase(100,(t_ba)(gl_mlayer->start_pba+pba)) == LL_OK) {
				return index; //erase is ok, so return with the index
			}

	        DEBPR1("gl_mlayer->alloc: Erase of block %d failed\n", pba);

			pba=bb_setasbb(pba); //change pba, set current as BAD
			if (pba==BLK_NA) {	 //check if success
				gl_mlayer->freetable[index] |= FT_BAD;     //signal it as locked BAD
				break; //get a new index
			}

			gl_mlayer->freetable[index] = pba; //write back new pba
			gl_wear_allocstruct.free_wear=1; //set new wear info
			wear_updatedynamicinfo(index,1); //update wear info
		}
	}

}

/****************************************************************************
 *
 * get_mapblock
 *
 * Function for retreiving the map according fragment counter
 *
 * INPUTS
 *
 * frag_num - fragment number
 *
 * RETURNS
 *
 * map pointer where the fragment is or NULL if any error
 *
 ***************************************************************************/

ST_MAPBLOCK *get_mapblock(unsigned char frag_num) {
ST_MAPBLOCK *map=gl_mlayer->mapblocks;

	if (frag_num<map->end_frag) return map;

	map++; 
	if (frag_num<map->end_frag) return map;

	map++; 
	if (frag_num<map->end_frag) return map;

	map++; 
	if (frag_num<map->end_frag) return map;

	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(gl_mlayer->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_mlayer->freetable[index];
			map->ppo=0;
			wear_updatedynamicinfo(index,gl_wear_allocstruct.free_wear);

			map->ref_count++;

⌨️ 快捷键说明

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