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

📄 mal_2k.c

📁 HID-Ukey底层源码实现(st72651芯片) windows上层驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
			SRL		Y
			RRC		X
			RRC		A	; 1st shift
			SRL		Y
			RRC		X
			RRC		A	; 2nd shift
			SRL		Y
			RRC		X
			RRC		A	; 3rd shift
			SRL		Y
			RRC		X
			RRC		A	; 4th shift
			SRL		Y
			RRC		X
			RRC		A	; 5th shift
			LD		SMC_Laddr:1, A
			LD		SMC_Laddr, X
		}	// The C line below costs too much
	
//	SMC_Laddr = (unsigned int)(MAL_Block_Address >> 5);

		Adjust_Laddr();
		SMC_Ppage = (unsigned char)MAL_Block_Address & 0x001F;
	}
	
	else { //for 2k Flash
		asm {
			LD		A, MAL_Block_Address:2
			LD		X, MAL_Block_Address:1
			LD		SMC_Laddr:1, A
			LD		SMC_Laddr, X
		}	// The C line below costs too much
	//	SMC_Laddr = (unsigned int)(MAL_Block_Address >> 8);
		Adjust_Laddr();
		SMC_Ppage512 = SMC_Ppage = (unsigned char)MAL_Block_Address & 0x00FF; //512 Byte page number for 2K
		SubBlock = (unsigned char) (SMC_Ppage % 4); //offset in the coloumn

		SMC_Ppage = SMC_Ppage / 4; //2K page number for 2K Flash
	}	


	if (SMC_Lookup_nCache0 == 0)	// Card < 64MB
		return;						// No cache management needed

	// Calculate the address of the last page: EndBlock 
	if (SMC_Cluster_Size != 64){
		asm {
			LD		A, MAL_Block_Numbers:1
			LD		X, MAL_Block_Numbers
			ADD		A, SMC_Ppage
			JRNC	sub_1
			INC		X
	sub_1:	SUB		A, #1
			JRNC	shift5
			DEC		X
	shift5:
			SRL		X
			RRC		A		; 1st shift
			SRL		X
			RRC		A		; 2nd shift
			SRL		X
			RRC		A		; 3rd shift
			SRL		X
			RRC		A		; 4th shift
			SRL		X
			RRC		A		; 5th shift
			ADD		A, SMC_Laddr:1
			LD		EndBlock:1, A
			LD		A, X
			ADC		A, SMC_Laddr
			LD		EndBlock, A
		}	// The following C line costs too much
	//	EndBlock = SMC_Laddr + ((SMC_Ppage + MAL_Block_Numbers - 1) >> 5);
	}
	else { //for 2K flash
		asm {
			LD		A, MAL_Block_Numbers:1
			LD		X, MAL_Block_Numbers
			ADD		A, SMC_Ppage
			JRNC	sub_2
			INC		X
	sub_2:	SUB		A, #1
			JRNC	shift8
			DEC		X
shift8:		LD		A, X
			ADD		A, SMC_Laddr:1
			LD		EndBlock:1, A
			CLR		A
			ADC		A, SMC_Laddr
			LD		EndBlock, A
		}	// The following C line costs a lot
	//	EndBlock = SMC_Laddr + ((SMC_Ppage512 + MAL_Block_Numbers - 1) >> 8);
	}


	if (EndBlock >= 1000) {		// The access will cross the zone boundary
		unsigned char ZoneNext;
		unsigned char ChipNext;

		ZoneNext = SMC_Zone + 1;
		ChipNext = NAND_Chip;
		if(SMC_Cluster_Size != 64) {
			if (ZoneNext >= Chip_Size[NAND_Chip]) {
				ZoneNext -= Chip_Size[NAND_Chip];
				goto com0;
		//		ChipNext++;
		//		while (Chip_Size[ChipNext] == 0)
		//			ChipNext++;			// Skip bad or not exist chips
			}
		}  
		else {
			if (ZoneNext >= (Chip_Size[NAND_Chip]/8)) {
				ZoneNext -= (Chip_Size[NAND_Chip]/8);
com0:			ChipNext++;
				while (Chip_Size[ChipNext] == 0)
					ChipNext++;			// Skip bad or not exist chips
			}
		}

		if (gZONE(NAND_Chip, SMC_Zone) == SMC_Lookup_Zone0) { // current zone hits table0
			if (gZONE(ChipNext, ZoneNext) == SMC_Lookup_Zone1)
				return;
			
			NAND_Lookup_Update1(ChipNext, ZoneNext);		// update lookup tabke 1 for ZoneNext
		}
		else if (gZONE(NAND_Chip, SMC_Zone) == SMC_Lookup_Zone1) {// current zone hits table1
			if (gZONE(ChipNext, ZoneNext) == SMC_Lookup_Zone0)
				return;

			NAND_Lookup_Update0(ChipNext, ZoneNext);		// update lookup table 0 for ZoneNext
		}
		else if (gZONE(ChipNext, ZoneNext) == SMC_Lookup_Zone0)	// next zone hits table0
			NAND_Lookup_Update1(NAND_Chip, SMC_Zone);		// update lookup table 1 for SMC_Zone
		else if (gZONE(ChipNext, ZoneNext) == SMC_Lookup_Zone1)	// next zone hits table1
			NAND_Lookup_Update0(NAND_Chip, SMC_Zone);		// updata lookup table 0 for SMC_Zone
		else {
			NAND_Lookup_Update0(NAND_Chip, SMC_Zone);		// updata lookup table 0 for SMC_Zone
			NAND_Lookup_Update1(ChipNext, ZoneNext);		// updata lookup table 1 for ZoneNext
		}
	}
	else {		// The access will not cross the zone boundary
		if (gZONE(NAND_Chip, SMC_Zone) == SMC_Lookup_Zone0
				|| gZONE(NAND_Chip, SMC_Zone) == SMC_Lookup_Zone1)
			return;
		
#if USE_CACHE0
		if (NAND_Chip == 0)		// Cache has to be for chip0 only
			if (SMC_Zone == 0 && SMC_Laddr < SMC_Lookup_nCache0) {	// Hit on cache of zone0
				if (EndBlock < SMC_Lookup_nCache0)
					return;
			}
#endif
		// Going to make the lookup table for the new zone
		if (SMC_Lookup_Count0 < SMC_Lookup_Count1)
			NAND_Lookup_Update0(NAND_Chip, SMC_Zone);
		else
			NAND_Lookup_Update1(NAND_Chip, SMC_Zone);
	}
}

#endif	// THUMB_DRIVE

/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
				Organization of the Lookup Table

  There are two lookup tables, table0 & table1. Table0 always keep the
  information for Zone 0 and the Table1 keeps the information for the current
  working Zone.

  A lookup table is a buffer with 1024 elements. The index of this buffer is
  the logical address and the content of each element is the corresponding
  physical address.
  Assume LUT[x] is the value of xth element:
	LUT[x] < 1024	LUT[x] is the physical address of logicall address x
	LUT[x] >= 1024	(LUT[x] & 1024) is a free physical address and will be
					allocated to the logical address of x.
  NOTE: LUT[x] IS CONVERTED TO DTC ADDRESS FOR FASTING ACCESS
		LUT[x] >> 5 or LUT[x] >> 4 is the real physical cluster address

  Using the lookup table:
  The first 1000 elements of a lookup table are used for mapping the logical
  address to physical address. All the bad physical block addresses are saved
  at the end of this table. Elements start from index 1000 are available to
  use for new allocation.
	x < 1000		LUT[x] is used for mapping
	x >= 1024 - n	LUT[x] is the physical address of a bad physical cluster
					n is the number of bad blocks.
	x >= 1000 & x < 1024 -n
					LUT[x] is the free physical cluster that can be allocated
  When an existing physical cluster is over-written, the free cluster on the
  index 1000 is used. Then the old cluster is erased and put in the location
  of index 1000.

-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
//#pragma NO_ENTRY
void SMC_Convert_Lookup(unsigned short *pLUT)
{
	unsigned short	value;
	int iLUT;

	for (iLUT = 1023; iLUT >= 0; iLUT--) {
		value = *pLUT;
		if (SMC_Cluster_Size == 32)
			*pLUT = value << 5;
		else if (SMC_Cluster_Size == 64){
			if (*pLUT & 0x400) {	//to chk if it is a mapped cluster
				*pLUT = value << 6;
				*pLUT |= 0x0010;
			}
			else {
				*pLUT = value << 6;
			//	*pLUT &= 0xffef;	// last 6bits must be 0 after shift
			}
		}
		else {
			value &= ~0x0400;
			*pLUT = value << 4;
		}
		if (value & 0x2000)
			*pLUT |= 0x01;		// bad cluster
		pLUT++;
	}
}

void SMC_Paddr_To_DTC_Addr(void)
{
	Map_To_DTC_Addr256(malPaddr, SMC_Zone, SMC_Paddr, 0,Col);
}

unsigned short SMC_Get_Free()
{
#if USE_CACHE0
	if (SMC_Lookup_pTable == SMC_Lookup_pCache0)
		return SMC_Lookup_pFree0[0];
#endif

#ifndef THUMB_DRIVE
	if (SMC_4MB)
		return SMC_Lookup_pTable[500];
#endif
	return SMC_Lookup_pTable[1000];
}

/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
	Replace SMC_Laddr with SMC_Paddr and set SMC_Raddr on logical address 1000
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
void SMC_Update_Lookup()
{
#if ALLOW_OUT_RANGE
	if (Mal_Addr_Out_Range & 0x01)
		return;
#endif
	SMC_Lookup_pTable[SMC_Laddr] = SMC_Paddr;

	if (SMC_Wstate & SMC_OLD_CLUSTER) {
	//	malPaddr = Map_DTC_Addr(SMC_Zone, SMC_Raddr, 0);
//		Map_To_DTC_Addr(malPaddr, SMC_Zone, SMC_Raddr, 0);
		Map_To_DTC_Addr256(malPaddr, SMC_Zone, SMC_Raddr, 0,0);//for 2K Flash
		if (DTC_SMC_Erase() != 0x01)		// Erase the dirty cluster of malPaddr
			asm NOP;

#if USE_CACHE0
		if (SMC_Lookup_pTable == SMC_Lookup_pCache0)
			SMC_Lookup_pFree0[0] = SMC_Raddr | 0x8000;
		else
#endif

#ifndef THUMB_DRIVE
		if (SMC_4MB)
			SMC_Lookup_pTable[500] = SMC_Raddr | 0x8000;
		else {
#endif		
			if (SMC_Cluster_Size != 64)
				SMC_Lookup_pTable[1000] = SMC_Raddr | 0x8000;
			else
				SMC_Lookup_pTable[1000] = SMC_Raddr | 0x0010;//different map bit for 2K flash
#ifndef THUMB_DRIVE
		}
#endif
	}
}

/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
	Convert the SMC_Laddr to SMC_Paddr in SMC_Zone
	return TRUE if the logical Cluster of SMC_Laddr exists
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if USE_CACHE0
void SMC_Copy_Lookup_Cache0()
{
	unsigned short *pW;

	// Copy the first few lookup items of zone0
	// They are PBR, MBR, FAT & ROOT
	asm {
		LD		X, SMC_Lookup_nCache0
		SLL		X
		DEC		X
copy_cache:
		LD		A, ([SMC_Lookup_pTable.w],X)
		LD		(SMC_Lookup_pCache0,X), A
		DEC		X
		JRPL	copy_cache
	}
//	for (index = Lookup_nCache-1; index >= 0; index--)
//		SMC_Lookup_pCache0[index] = SMC_Lookup_pTable[index];

	// Copy the first few free lookup items of zone0
	asm {
		LD		A, SMC_Lookup_pTable:1
		ADD		A, #0xD0
		LD		pW:1, A
		LD		A, SMC_Lookup_pTable
		ADC		A, #0x07
		LD		pW, A
	}
//	pW = SMC_Lookup_pTable+1000;

	asm {
		LD		X, #CACHE0_FREE*2-1
copy_free0:
		LD		A, ([pW.w], X)
		LD		(SMC_Lookup_pFree0,X), A
		DEC		X
		JRPL	copy_free0
	}

//	for (index = CACHE0_FREE-1; index >= 0; index--)
//		SMC_Lookup_pFree0[index] = pW[index];
}
#endif // USE_CACHE0

#pragma DATA_SEG DEFAULT_RAM	// After here, all variable will be in non-Zero page

#ifndef THUMB_DRIVE
void SMC_Lookup_Update0(unsigned char Zone)
{
	SMC_Lookup_pTable = SMC_Lookup_Table0;
#if USE_CACHE0
	if (SMC_Lookup_Zone0 == 0)
		SMC_Copy_Lookup_Cache0();
#endif
	SMC_Lookup_Count0 = 0;
	SMC_Lookup_Zone0 = Zone;

	malRaddr = 1024;		// number of clusters in the zone
	if (SMC_4MB)
		malRaddr = 512;
	malNpage = SMC_Cluster_Size;
	if (SMC_Cluster_Size == 64) {
		Buffer_Param[0x00] = 0x00;		//flag for recognition
		Buffer_Param[0x02] = 0x00;		//first cmd for Mapzone
		Buffer_Param[0x03] = 0xe3;		//Add for mazone
	}
	else {
		Buffer_Param[0x00] = 0x01; 
		Buffer_Param[0x02] = 0x50;
		Buffer_Param[0x03] = 0xe4;
	}
//	Map_To_DTC_Addr(malPaddr, Zone, 0, 0);
	Map_To_DTC_Addr256(malPaddr, Zone, 0, 0, 2);	//for 2K Flash
	DTC_SMC_Map_Zone(SMC_Lookup_pTable);
	SMC_Convert_Lookup(SMC_Lookup_pTable);
}

//#pragma NO_OVERLAP
void SMC_Lookup_Update1(unsigned char Zone)
{
	SMC_Lookup_pTable = SMC_Lookup_Table1;
#if USE_CACHE0
	if (SMC_Lookup_Zone1 == 0)
		SMC_Copy_Lookup_Cache0();
#endif
	SMC_Lookup_Count1 = 0;
	SMC_Lookup_Zone1 = Zone;

	malRaddr = 1024;		// number of clusters in the zone
//	if (SMC_4MB)			// 4MB does not use LOOKUP Table 1
//		malRaddr = 512;
	malNpage = SMC_Cluster_Size; 
	if (SMC_Cluster_Size == 64) {		//For 256MB
		Buffer_Param[0x00] = 0x00;		//flag for recognition
		Buffer_Param[0x02] = 0x00;		//first cmd for Mapzone
		Buffer_Param[0x03] = 0xe3;		//Adr for mapzone
	}
	else {
		Buffer_Param[0x00] = 0x01;
		Buffer_Param[0x02] = 0x50;
		Buffer_Param[0x03] = 0xe4;
	}
//	Map_To_DTC_Addr(malPaddr, Zone, 0, 0);
	Map_To_DTC_Addr256(malPaddr, Zone, 0, 0, 2);		//for 2K Flash
	DTC_SMC_Map_Zone(SMC_Lookup_pTable);
	SMC_Convert_Lookup(SMC_Lookup_pTable);
}
#endif

static unsigned char SMC_Log2Phy()
{
#if ALLOW_OUT_RANGE
	if (Mal_Addr_Out_Range & 0x03)
		return FALSE;	// The address is out of range now
#endif

#ifdef THUMB_DRIVE
	if (gZONE(NAND_Chip, SMC_Zone) == SMC_Lookup_Zone0) {		// Hit on table0
#else
	if (SMC_Zone == SMC_Lookup_Zone0) {		// Hit on table0
#endif
		SMC_Lookup_pTable = SMC_Lookup_Table0;
		if (SMC_Lookup_Count0 != LOOKUP_THRESHOLD)
			SMC_Lookup_Count0++;	// increase the visit counter of this table
		if (SMC_Lookup_Count1 != 0)
			SMC_Lookup_Count1--;	// decrease the visit counter of another table
	}
#ifdef THUMB_DRIVE
	else if (gZONE(NAND_Chip, SMC_Zone) == SMC_Lookup_Zone1) {// Hit on table1
#else
	else if (SMC_Zone == SMC_Lookup_Zone1) {	// Hit on table1
#endif
		SMC_Lookup_pTable = SMC_Lookup_Table1;
		if (SMC_Lookup_Count1 != LOOKUP_THRESHOLD)
			SMC_Lookup_Count1++;	// increase the visit counter of this table
		if (SMC_Lookup_Count0 != 0)
			SMC_Lookup_Count0--;	// decrease the visit counter of another table
	}
	else {
		// No hit on both table
#if USE_CACHE0
		// The _SMC_Get_Logical_Addr() gurantees it is on zone0 cache
		SMC_Lookup_pTable = SMC_Lookup_pCache0;
#else
//		asm nop;	// There must be a bug if we are here
#endif
	}

	if (SMC_Cluster_Size == 64){
		SMC_Paddr = SMC_Lookup_pTable[SMC_Laddr];
		return ((SMC_Paddr & 0x10) == 0);		//for 2K Flash
	}

	SMC_Paddr = SMC_Lookup_pTable[SMC_Laddr];
	return ((SMC_Paddr & 0x8000) == 0);

//	SMC_Paddr = SMC_Lookup_pTable[SMC_Laddr];
//	return ((SMC_Paddr & 0x8000) == 0);
}

/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
	Mark and add SMC_Zone:SMC_Paddr to end of the lookup table
	SMC_Laddr is the logical cluster number.
	On return: SMC_Zone:SMC_Paddr will be the good cluster form SMC_Laddr
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
void SMC_Lookup_Map_Bad(void)
{
	unsigned int	temp;
	unsigned short*	pBad;

#if USE_CACHE0
	if (SMC_Lookup_pTable != SMC_Lookup_pCache0) {
		pBad = SMC_Lookup_pTable + 1023;		// the last item
		while (*pBad & 0x0F)
			pBad--;

		temp = *pBad;
		*pBad = SMC_Paddr | 0x0001;
	}
	else {
		// shift the free cluster array
		// SMC_Lookup_pFree0[0] = SMC_Lookup_pFree0[1];
		// SMC_Lookup_pFree0[1] = SMC_Lookup_pFree0[2];
		asm {
			CLR		X
shift_free0:
			LD		A, (SMC_Lookup_pFree0:2,X)
			LD		(SMC_Lookup_pFree0,X), A
			INC		X

⌨️ 快捷键说明

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