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

📄 ssfdc.c

📁 truefs for vxworks, make fs on flash or rom
💻 C
📖 第 1 页 / 共 5 页
字号:
/* We know there is an error, Check if it is fixable (one bit error in  *//* 256 bytes of data is fixable).					*//*                                                                      *//* Parameters:                                                          *//*	diff		: The difference between the read and 		*//*			  calculated ECC.				*//*									*//* Returns:								*//*	TRUE if the error is fixable, otherwise FALSE.			*//*                                                                      *//*----------------------------------------------------------------------*/static FLBoolean isFixable (unsigned char FAR0 *diff){  int i, j;  unsigned char mask;  /* data is fixable if for each pair of bits one is 0 and one is 1 */  for (i = 0; i < 3; i++)    for (j = 0, mask = 1; j < 4; j++, mask <<= 2) {      if ((i == 2) && (j == 0))	continue;     /* the two lowest bits in the 3rd byte are always 1 */      /* xor two neighbouring bits */      if (!(((diff[i] & mask) >> (2 * j)) ^	    ((diff[i] & (mask << 1)) >> (2 * j + 1))))	return FALSE;    }  return TRUE;}/*----------------------------------------------------------------------*//*		         c h e c k A n d F i x				*//*									*//* Compare the calculated ECC and the one read from the device. 	*//* If there is a difference, try to fix the error. If both codes	*//* are the same, data is correct.					*//*                                                                      *//* Parameters:                                                          *//*	ecc1		: Calculated ECC.				*//*	ecc2		: Read ECC.					*//*      sectorToFix	: The data to fix.				*//*									*//* Returns:								*//*	TRUE if data is correct or error fixed, otherwise FALSE.	*//*                                                                      *//*----------------------------------------------------------------------*/static FLBoolean checkAndFix(unsigned char FAR0 *ecc1, unsigned char FAR0 *ecc2,			 unsigned char FAR0 *sectorToFix){  if((ecc1[0] != ecc2[0]) ||     (ecc1[1] != ecc2[1]) ||     (ecc1[2] != ecc2[2])) {  /* ECC error, try to fix */    unsigned char diff[3];    int i;    for (i = 0; i < 3; i++)      diff[i] = ecc1[i] ^ ecc2[i];    if (isFixable(diff)) {      unsigned char line = 0, column = 0, mask;      /* push the lower bits to the right */      for (i = 0, mask = 2; i < 4; i++, mask <<= 2)	line |= (diff[0] & mask) >> (i + 1);      /* push the upper bits to the left */      for (i = 0, mask = 0x80; i < 4; i++, mask >>= 2)	line |= (diff[1] & mask) << i;      /* push to the right */      for (i = 0, mask = 8; i < 3; i++, mask <<= 2)	column |= (diff[2] & mask) >> (i + 3);      sectorToFix[line] ^= 1 << column;  /* fix */      return TRUE;    }    else {    #ifdef DEBUG_PRINT      DEBUG_PRINT("Debug: ECC error in SSFDC.\n");    #endif      return FALSE;    }  }  else    return TRUE;}/*----------------------------------------------------------------------*//*		         e c c O n R e a d				*//*									*//* Use ECC\EDC for a sector of data. Do each half seperately.		*//* If there is a fixable error, fix it.					*//*                                                                      *//* Parameters:                                                          *//*	vol		: Pointer identifying drive			*//*	sectorAddress	: Physical address of the sector to check.	*//*									*//* Returns:								*//* 	FALSE if there is an error that can't be fixed, otherwise 	*//*	return TRUE.							*//*                                                                      *//*----------------------------------------------------------------------*/static FLBoolean eccOnRead(SSFDC vol, CardAddress sectorAddress){  unsigned char calcEcc[3], readEcc[3];  unsigned char FAR0 *sectorToFix = (unsigned char FAR0 *)vol.mappedSector;  createEcc(sectorToFix, calcEcc);  vol.flash.read(&vol.flash, sectorAddress + ECC1, readEcc, sizeof readEcc, EXTRA);  if (checkAndFix(calcEcc, readEcc, sectorToFix)) {    /* success in the first half go for the second half */    createEcc(sectorToFix + SECTOR_SIZE / 2, calcEcc);    vol.flash.read(&vol.flash, sectorAddress + ECC2, readEcc, sizeof readEcc, EXTRA);    if (checkAndFix(calcEcc, readEcc, sectorToFix + SECTOR_SIZE / 2))      return TRUE;  }  return FALSE;}#endif /* ECC_ON_READ *//******************* end of ECC\EDC part ********************************//*----------------------------------------------------------------------*//*		         u n i t B a s e A d d r e s s			*//*									*//* Returns the physical address of a unit.				*//*                                                                      *//* Parameters:                                                          *//*	vol		: Pointer identifying drive			*//*	unitNo		: Physical unit number				*//*                                                                      *//* Returns:                                                             *//*	physical address of unitNo					*//*----------------------------------------------------------------------*/static CardAddress unitBaseAddress(SSFDC vol, UnitNo unitNo){  return (CardAddress)unitNo << vol.unitSizeBits;}/*----------------------------------------------------------------------*//*		         v i r t u a l 2 P h y s i c a l		*//*									*//* Translate virtual sector number to physical address.			*//*                                                                      *//* Parameters:                                                          *//*	vol		: Pointer identifying drive			*//*	sectorNo	: Virtual sector number				*//*                                                                      *//* Returns:                                                             *//*	physical address of sectorNo					*//*----------------------------------------------------------------------*/static CardAddress virtual2Physical(SSFDC vol, SectorNo sectorNo){  unsigned unitOffset = (sectorNo % vol.sectorsPerUnit) << SECTOR_SIZE_BITS;  UnitNo unitNo = vol.virtualUnits[sectorNo / vol.sectorsPerUnit];  StatusArea statusArea;  /* no physical unit is assigned to this virtual sector number */  if (unitNo == NO_UNIT)    return UNASSIGNED_ADDRESS;  /* check if this sector was replaced */  vol.flash.read(&vol.flash,		 unitBaseAddress(&vol, unitNo) + unitOffset + STATUS_AREA_OFFSET,		 &statusArea, sizeof statusArea, EXTRA);  if (statusArea.sectorStatus != 0xff) {    if (vol.replacedUnit == unitNo)      if (vol.replacementSectors[sectorNo % vol.sectorsPerUnit] == SECTOR_REPLACED)	return unitBaseAddress(&vol, vol.transferUnit) + unitOffset; /* this sector was replaced */    return UNASSIGNED_ADDRESS;  /* this sector is bad or deleted */  }  return unitBaseAddress(&vol, unitNo) + unitOffset;}/*----------------------------------------------------------------------*//*		         p h y s i c a l 2 V i r t u a l		*//*									*//* Translate physical unit number to virtual unit number. Read virtual	*//* unit number from first or second address area according to the 	*//* parameter addressAreaNo.						*//*                                                                      *//* Parameters:                                                          *//*	vol		: Pointer identifying drive			*//*	unitNo		: Physical unit number				*//*	addressAreaNo	: Specify which address area to use		*//*                                                                      *//* Returns:                                                             *//*	Virtual unit number of unitNo.					*//*----------------------------------------------------------------------*/static UnitNo physical2Virtual(SSFDC vol, UnitNo unitNo, int addressAreaNo){  unsigned char addressArea[2];  UnitNo virtualUnitNo;  int offset;  offset = (addressAreaNo == OFFSET1 ? BLOCK_ADDRESS_OFFSET1 : BLOCK_ADDRESS_OFFSET2);  /* get virtual unit no. from address area */  vol.flash.read(&vol.flash, unitBaseAddress(&vol, unitNo) + offset, addressArea,		 sizeof addressArea, EXTRA);  /* trade places of byte 0 and byte 1 */  virtualUnitNo = ((UnitNo)addressArea[0] << 8) | addressArea[1];  /* virtual address is in bits 1 through 11 */  virtualUnitNo <<= 4;  virtualUnitNo >>= 5;  return virtualUnitNo;}/*----------------------------------------------------------------------*//*      	        s e c t o r s I n V o l u m e			*//*									*//* Gets the total number of sectors in the volume			*//*									*//* Parameters:                                                          *//*	vol		: Pointer identifying drive			*//*                                                                      *//* Returns:                                                             *//*	Number of sectors in the volume					*//*----------------------------------------------------------------------*/static SectorNo sectorsInVolume(SSFDC vol){  return vol.virtualSectors;}/*----------------------------------------------------------------------*//*      	        I d e n t i f y F o r m a t			*//*									*//* There are two different formats for nand devices, this function 	*//* tries to identify one of them by reading its ID string. If format is *//* identified, bootBlock holds the number of the unit where the boot 	*//* sector is. 								*//*									*//* Parameters:                                                          *//*	vol		: Pointer identifying drive			*//*	bootBlock	: Receives the number of the block where the	*//*			  boot sector is.				*//*                                                                      *//* Returns:                                                             *//*	The type of the format idetified (SSFDC, NFTL, unknown)		*//*----------------------------------------------------------------------*/static FormatType identifyFormat(SSFDC vol, UnitNo *bootBlock){  int i;  unsigned char bootRecordId[10], invalidDataFlag;  unsigned char formatPattern[10] = {FORMAT_PATTERN};  for (*bootBlock = 0; *bootBlock < vol.noOfUnits; (*bootBlock)++) {    vol.flash.read(&vol.flash, unitBaseAddress(&vol, *bootBlock),		   bootRecordId, sizeof bootRecordId, 0);    if (tffscmp(bootRecordId, "ANAND", 6) == 0)      return ANAND_FORMAT;    for (i = 0; (unsigned)i < vol.sectorsPerUnit; i++) {      vol.flash.read(&vol.flash, unitBaseAddress(&vol, *bootBlock) + (i << SECTOR_SIZE_BITS),		     bootRecordId, sizeof bootRecordId, 0);      if (tffscmp(bootRecordId, formatPattern, sizeof formatPattern) == 0) {	/* check that the data is valid */	vol.flash.read(&vol.flash,		       unitBaseAddress(&vol, *bootBlock) +		       (i << SECTOR_SIZE_BITS) + CIS_DATA_OFFSET,		       &invalidDataFlag, sizeof invalidDataFlag, EXTRA);	if (invalidDataFlag == 0xff)	  return SSFDC_FORMAT;      }    }  }  return BAD_FORMAT;}/*----------------------------------------------------------------------*//*      	        i s E r a s e d s e c t o r 			*//*									*//* Check if a sector is erased.						*//*									*//* Parameters:                                                          *//*	vol		: Pointer identifying drive			*//* 	unitNo		: The sector to check is in this unit.		*//*	offset		: Offset of the sector in the unit.		*//*                                                                      *//* Returns:                                                             *//*	TRUE if the sector is erased, otherwise FALSE			*//*----------------------------------------------------------------------*/static FLBoolean isErasedSector(SSFDC vol, UnitNo unitNo, unsigned offset){  unsigned char *buf;  StatusArea statusArea;  int i;  buf = (unsigned char *)vol.flash.map(&vol.flash,				       unitBaseAddress(&vol, unitNo) +				       offset, SECTOR_SIZE);  /* check data area */  for (i = 0; i < SECTOR_SIZE; i++)    if (buf[i] != 0xff)      return FALSE;  /* check status area */  vol.flash.read(&vol.flash,		 unitBaseAddress(&vol, unitNo) + offset + STATUS_AREA_OFFSET,		 &statusArea, sizeof statusArea, EXTRA);  if (statusArea.sectorStatus != 0xff)    return FALSE;  return TRUE;}/*----------------------------------------------------------------------*//*      	        w r i t e A n d C h e c k 			*//*									*//* Write one sector. If eccMode is TRUE, calculate and write ECC.	*//*									*//* Parameters:                                                          *//*	vol		: Pointer identifying drive			*//*	address		: Physical address of the sector to write to	*//*	fromAddress	: Buffer of data to write			*//*	eccMode		: If TRUE, calculate and write ECC		*//*                                                                      *//* Returns:                                                             *//* 	FLStatus 	: 0 on success, failed otherwise.		*//*----------------------------------------------------------------------*/static FLStatus writeAndCheck(SSFDC vol,			      CardAddress address,			      void FAR1 *fromAddress,			      int eccMode){  int sectorInUnit;  FLStatus status = vol.flash.write(&vol.flash,address,fromAddress,SECTOR_SIZE,0);  if (eccMode) {  /* calculate and write ECC */    unsigned char ecc[3];    createEcc((unsigned char FAR1 *)fromAddress, ecc);    status = vol.flash.write(&vol.flash, address + ECC1, ecc, sizeof ecc, EXTRA);    createEcc((unsigned char FAR1 *)fromAddress + SECTOR_SIZE / 2, ecc);    status = vol.flash.write(&vol.flash, address + ECC2, ecc, sizeof ecc, EXTRA);  }  if (status == flWriteFault) {   /* write failed, sector doesn't hold valid data. */    StatusArea statusArea = {0, 0xff};    vol.flash.write(&vol.flash, address + STATUS_AREA_OFFSET, &statusArea,		    sizeof statusArea,EXTRA);  }

⌨️ 快捷键说明

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