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

📄 inftl.c

📁 DOC文件系统驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:

#endif /* FL_READ_ONLY */


/*----------------------------------------------------------------------*/
/*                       g e t U n i t D a t a                          */
/*                                                                      */
/* Get virtual unit No. and replacement unit no. of a unit.             */
/*                                                                      */
/* Parameters:                                                          */
/*      vol              : Pointer identifying drive                    */
/*      unitNo           : Physical unit number                         */
/*      virtualUnitNo    : Returns the virtual unit no.                 */
/*      prevUnitNo       : Returns the previous unit no.                */
/*      ANAC             : Returns the Accumulating Number Along Chain. */
/*      NAC              : Returns the Number Along Chain value.        */
/*      validFields      : Returns a bit map of the valid fields.       */
/*                                                                      */
/* Returns:                                                             */
/*    flOK on success, flHWProtection on H/W read protection.           */
/*----------------------------------------------------------------------*/

static FLStatus getUnitData(Bnand vol,
        ANANDUnitNo unitNo,
        ANANDUnitNo *virtualUnitNo,
        ANANDUnitNo *prevUnitNo,
        byte *ANAC,
        byte *NAC,
        byte *validFields)
{
  ANANDUnitHeader       unitData;
  SecondANANDUnitHeader secondUnitData;
  FLStatus              status;
  byte                  parityPerField=0;
  byte                  temp;
  byte                  returnedValidField = ALL_PARITY_BITS_OK;
  byte                  curValidFields[2];
  int                   index;

#ifdef NFTL_CACHE
  /* on cache miss read ANANDUnitHeader from flash and re-fill cache */
  if ((vol.ucache != NULL)&&(vol.ucache[unitNo].virtualUnitNo != 0xDEAD) &&
      (vol.ucache[unitNo].prevUnitNo != 0xDEAD))
  {
     *virtualUnitNo = vol.ucache[unitNo].virtualUnitNo;
     *prevUnitNo = vol.ucache[unitNo].prevUnitNo;
     *ANAC = vol.ucache[unitNo].ANAC;
     *NAC = vol.ucache[unitNo].NAC;
  }
  else
#endif  /* NFTL_CACHE */
  {   /* no ANANDUnitHeader cache MUST read first header */

      *validFields       = 0; /* Set all fields to be invalid */

      /* Read first unit data */
      status = vol.flash->read(vol.flash,
                   unitBaseAddress(vol,unitNo) + UNIT_DATA_OFFSET,
                   &unitData,
                   sizeof(ANANDUnitHeader),
                   EXTRA);
      if(status != flOK)
         return status;

      *virtualUnitNo = LE2(unitData.virtualUnitNo);
      *prevUnitNo    = LE2(unitData.prevUnitNo   );
      *ANAC          = unitData.ANAC;
      *NAC           = unitData.NAC;

      for(index=0;index<2;index++)
      {
         /* If all data is 0xff assume a free unit */
         if((*virtualUnitNo     == ANAND_NO_UNIT  )&&
            (*prevUnitNo        == ANAND_NO_UNIT  )&&
            (*ANAC              == ANAND_UNIT_FREE)&&
            (*NAC               == ANAND_UNIT_FREE)&&
            (unitData.discarded == ANAND_UNIT_FREE))
         {
#ifndef FL_READ_ONLY
            if(index!=0)
            {
               /* If this is the second copy then the first was not  */
               /* erased, but since it was written first it makes no */
               /* sence. Let us erase it just in case.               */

               status = formatUnit(&vol,unitNo,UNIT_TAILER_OFFSET);
               if(status != flOK)
                  return status;
            }
#endif /* FL_READ_ONLY */
            break;
         }

         /* Not a free unit check unit data validity (discard and partity) */
         if ((onesCount((byte)(unitData.discarded^DISCARD))>1))
         {
            /* Discarded mark is more then 1 bit distance from 0xAA  */
            /* Assume erase operation was interrupted and erase unit */

            TL_DEBUG_PRINT(tl_out,"getUnitData : unit %d has an invalid discard mark\n",unitNo);
            TL_DEBUG_PRINT(tl_out,"              it might be helpful to know it was %d\n",unitData.discarded);

#ifndef FL_READ_ONLY
            status = formatUnit(&vol,unitNo,UNIT_TAILER_OFFSET);
            if(status != flOK)
               return status;
#endif /* FL_READ_ONLY */
            *virtualUnitNo = ANAND_NO_UNIT;
            *prevUnitNo    = ANAND_NO_UNIT;
            *ANAC          = ANAND_UNIT_FREE;
            *NAC           = ANAND_UNIT_FREE;
            break;
         }

         /* Discarded OK now check parity field */
         parityPerField = 0;
         temp=(byte)(((byte *)virtualUnitNo)[0]^((byte *)virtualUnitNo)[1]);
         if((onesCount(temp) & 1)==1)
            parityPerField|=VU_PARITY_BIT;
         temp=(byte)(((byte *)prevUnitNo)[0]^((byte *)prevUnitNo)[1]);
         if((onesCount(temp) & 1)==1)
            parityPerField|=PU_PARITY_BIT;
         if((onesCount(unitData.ANAC) & 1)==1)
            parityPerField|=ANAC_PARITY_BIT;
         if((onesCount(unitData.NAC) & 1)==1)
            parityPerField|=NAC_PARITY_BIT;

         /* Store valid fields using bitmap */
         curValidFields[index] = (byte)((~(parityPerField ^ unitData.parityPerField))
                         & ALL_PARITY_BITS_OK);

         if(curValidFields[index] == ALL_PARITY_BITS_OK)
         {
            /* If either copies has valid fields (all of them) use it */
            break;
         }
         else
         {
            if(index>0)
            {
               /* Use first header data if possible otherwise use second */
               returnedValidField = (byte)(curValidFields[0] | curValidFields[1]);
               TL_DEBUG_PRINT(tl_out,"getUnitData : The returned valid field indicator is %d\n",returnedValidField);
               TL_DEBUG_PRINT(tl_out,"              While %d indicates a valid unit data\n",ALL_PARITY_BITS_OK);
               if(curValidFields[0] & VU_PARITY_BIT)
                  *virtualUnitNo = LE2(unitData.virtualUnitNo);

               if(curValidFields[0] & PU_PARITY_BIT)
                  *prevUnitNo    = LE2(unitData.prevUnitNo   );

               if(curValidFields[0] & ANAC_PARITY_BIT)
                  *ANAC          = unitData.ANAC;

               if(curValidFields[0] & NAC_PARITY_BIT)
                  *NAC           = unitData.ANAC;
               break;
            }
         }

         /* Read second unit header for next iteration */
         status = vol.flash->read(vol.flash, unitBaseAddress(vol,unitNo) +
                      SECOND_HEADER_OFFSET + UNIT_DATA_OFFSET,
                      &secondUnitData,
                      sizeof(SecondANANDUnitHeader),
                      EXTRA);
         if(status != flOK)
            return status;

         *virtualUnitNo = LE2(secondUnitData.virtualUnitNo);
         *prevUnitNo    = LE2(secondUnitData.prevUnitNo   );
         *ANAC          = secondUnitData.ANAC;
         *NAC           = secondUnitData.NAC;

         TL_DEBUG_PRINT(tl_out,"getUnitData : First unit header is not OK in unit %d \n",unitNo);
         TL_DEBUG_PRINT(tl_out,"getUnitData : Virtual Unit No  = %d \n",LE2(unitData.virtualUnitNo));
         TL_DEBUG_PRINT(tl_out,"getUnitData : Previous Unit No = %d \n",LE2(unitData.prevUnitNo));
         TL_DEBUG_PRINT(tl_out,"getUnitData : ANAC             = %d \n",unitData.ANAC);
         TL_DEBUG_PRINT(tl_out,"getUnitData : NAC              = %d \n",unitData.NAC);
         TL_DEBUG_PRINT(tl_out,"getUnitData : ParityPerField   = %d \n",unitData.parityPerField);
         TL_DEBUG_PRINT(tl_out,"getUnitData : Discarded        = %d \n",unitData.discarded);

         TL_DEBUG_PRINT(tl_out,"getUnitData : Second unit header of the same unit %d is:\n",unitNo);
         TL_DEBUG_PRINT(tl_out,"getUnitData : Virtual Unit No  = %d \n",LE2(secondUnitData.virtualUnitNo));
         TL_DEBUG_PRINT(tl_out,"getUnitData : Previous Unit No = %d \n",LE2(secondUnitData.prevUnitNo));
         TL_DEBUG_PRINT(tl_out,"getUnitData : ANAC             = %d \n",secondUnitData.ANAC);
         TL_DEBUG_PRINT(tl_out,"getUnitData : NAC              = %d \n",secondUnitData.NAC);
         TL_DEBUG_PRINT(tl_out,"getUnitData : ParityPerField   = %d \n",secondUnitData.parityPerField);
      }

#ifdef NFTL_CACHE
      if ((vol.ucache != NULL) &&                     /* Cache enabled    */
          (returnedValidField == ALL_PARITY_BITS_OK)) /* All fields valid */
      {
         vol.ucache[unitNo].virtualUnitNo = *virtualUnitNo;
         vol.ucache[unitNo].prevUnitNo    = *prevUnitNo;
         vol.ucache[unitNo].ANAC          = *ANAC;
         vol.ucache[unitNo].NAC           = *NAC;
      }
#endif /* NFTL_CACHE */
   }
   *validFields = returnedValidField;
   return flOK;

}


/*----------------------------------------------------------------------*/
/*                       g e t P r e v U n i t                          */
/*                                                                      */
/* Get next unit in chain.                                              */
/*                                                                      */
/* Parameters:                                                          */
/*      vol             : Pointer identifying drive                     */
/*      unitNo          : Physical unit number                          */
/*      virUnitNo       : The expected virtual unit number              */
/*                                                                      */
/* Returns:                                                             */
/*      Physical unit number of the unit following unitNo in the chain. */
/*      If such unit do not exist, return ANAND_NO_UNIT.                */
/*----------------------------------------------------------------------*/

static ANANDUnitNo getPrevUnit(Bnand vol, ANANDUnitNo unitNo, ANANDUnitNo virUnitNo)
{
  ANANDUnitNo virtualUnitNo, replacementUnitNo;
  byte ANAC,NAC;
  byte parityPerField;

  /* If first in chain there can be not previous unit */
  if ((vol.physicalUnits[unitNo] & FIRST_IN_CHAIN))
    return ANAND_NO_UNIT;

  getUnitData(&vol,unitNo,&virtualUnitNo,&replacementUnitNo,&ANAC,&NAC,&parityPerField);

  /* check if unit is valid */
  if((badParityResult(parityPerField)) || ( virUnitNo != virtualUnitNo ))
  {
     TL_DEBUG_PRINT(tl_out,"getPrevUnit : An invalid unit was detected on getPrevUnit - parity is %x/0xf ",parityPerField);
     TL_DEBUG_PRINT(tl_out,"given virtual unit no is %d ",virUnitNo);
     TL_DEBUG_PRINT(tl_out,"where %d was read\n",virtualUnitNo);
     SET_EXIT(INFTL_FAILED_MOUNT);
     return ANAND_BAD_CHAIN_UNIT;
  }
  return replacementUnitNo;
}


#ifdef NFTL_CACHE

/*----------------------------------------------------------------------*/
/*           g e t S e c t o r F l a g s F r o m C a c h e              */
/*                                                                      */
/* Get sector flags from Sector Cache.                                  */
/*                                                                      */
/* Parameters:                                                          */
/*      vol             : Pointer identifying drive                     */
/*      address         : starting address of the sector                */
/*                                                                      */
/* Returns:                                                             */
/*      sector flags (SECTOR_USED, SECTOR_DELETED etc.)                 */
/*----------------------------------------------------------------------*/

static byte getSectorFlagsFromCache(Bnand vol, CardAddress address)
{
  return scacheTable[((vol.scache[(address - vol.firstUnitAddress) >> (SECTOR_SIZE_BITS+2)] >>
                     (((word)address >> 8) & 0x7)) & 0x3)];
}


/*----------------------------------------------------------------------*/
/*               s e t S e c t o r F l a g s C a c h e                  */
/*                                                                      */
/* Get sector flags from Sector Cache.                                  */
/*                                                                      */
/* Parameters:                                                          */
/*      vol             : Pointer identifying drive                     */
/*      address         : starting address of the sector                */
/*      sectorFlags     : one of SECTOR_USED, SECTOR_DELETED etc.       */
/*                                                                      */
/*----------------------------------------------------------------------*/

static void setSectorFlagsCache(Bnand vol, CardAddress address,
        byte sectorFlags)
{
  register byte tmp, val;

  if (vol.scache == NULL)
    return;

⌨️ 快捷键说明

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