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

📄 saftl.c

📁 M-System DOC(Disk on a Chip) Flash芯片的诊断工具, 可以从Flash芯片中获取特定的数据信息, 用于判断芯片当前的状态.
💻 C
📖 第 1 页 / 共 5 页
字号:
       {
          DBG_PRINT_ERR(FLZONE_TL,"Debug: Too many blocks in the quick mount area.\r\n");
          return FALSE;
       }
    }

    /* Check quick mount validity and load general information sector */
    if(fCheckOnly == FALSE)
    {
       flashPtr->args.startSector = ((FLDword)(volPrmPtr->firstQuickMountUnit + wIdx)) <<
                                    volPrmPtr->sectorsInUnitBits;
    }
    else
    {
       flashPtr->args.startSector = ((FLDword)(volPrmPtr->firstQuickMountUnit + wIdx)) <<
                                    (flashPtr->erasableBlockSizeBits-FL_SECTOR_SIZE_BITS);
       if((volPrmPtr->flash->flashTechnology & FL_SUPPORT_MLC) &&
          (volPrmPtr->MTDFlags               & MTD_REL_MODE )    )
       {
          flashPtr->args.startSector <<= 1;
       }
    }
    flashPtr->args.noOfSectors = 1;
    flashPtr->args.readMainBuf = (fCheckOnly == TRUE) ? saftlBuffer :
                                 volPrmPtr->foldingBuffer;
    flashPtr->args.opFlags     = MTD_DATA | volPrmPtr->MTDFlags;
    status                     = flashPtr->flashRead(flashPtr);
    if(status != flOK)
       return FALSE;

    info = (CNANDQuickMountInfo FAR1 *)flashPtr->args.readMainBuf;

    if(info->endianValidation  != SAFTL_ENDIAN_VALIDATION_MARK)
    {
       DBG_PRINT_WRN(FLZONE_TL,"Quick mount data is invalid.\r\n");
       DBG_PRINT_WRN_PRM(FLZONE_TL,(FLTXT("Mark is 0x%lx instead of 0x%lx.\r\n"),(FLDword)info->endianValidation,(FLDword)SAFTL_ENDIAN_VALIDATION_MARK));
       return FALSE;     
    }
    if(info->quickMountVersion != SAFTL_QUICK_MOUNT_VERSION)
    {
       DBG_PRINT_WRN(FLZONE_TL,"Quick mount data is not compatible with current TrueFFS version.\r\n");
       DBG_PRINT_WRN_PRM(FLZONE_TL,(FLTXT("TrueFFS quick mount version is 0x%lx while the version on the flash is 0x%lx.\r\n"),(FLDword)SAFTL_QUICK_MOUNT_VERSION,(FLDword)info->endianValidation));
       return FALSE;
    }

    if(fCheckOnly == TRUE)
       return TRUE;

    if(info->noOfCachedUnits != volPrmPtr->noOfCachedUnits)
    {
       DBG_PRINT_WRN(FLZONE_TL,"Quick mount data was not loaded , because the number of cached units does not fit the number currently allocated.\r\n");
       DBG_PRINT_WRN_PRM(FLZONE_TL,(FLTXT("There are %u allocated units while there are %u stored units.\r\n"),volPrmPtr->noOfCachedUnits,(FLWord)info->noOfCachedUnits ));
       return FALSE;     
    }

    /* Store current volPrmPtr record */
    tffscpy(bSavedCnandPtr,volPrmPtr,sizeof(Cnand));

    /* Load volume information from the quick mount data */
    volPrmPtr->neededFreeUnits    = (FLByte)info->neededFreeUnits;
    volPrmPtr->freeUnits          = (FLWord)info->freeUnits;
    volPrmPtr->roverUnit          = (FLWord)info->roverUnit;
    volPrmPtr->bootUnits          = (FLWord)info->bootUnits;
    volPrmPtr->multiUnitListHead  = (FLWord)info->multiUnitListHead;
    volPrmPtr->multiUnitListTail  = (FLWord)info->multiUnitListTail;
    volPrmPtr->singleUnitListHead = (FLWord)info->singleUnitListHead;
    volPrmPtr->singleUnitListTail = (FLWord)info->singleUnitListTail;
    volPrmPtr->freeCacheUnitList  = (FLWord)info->freeCacheUnitList;
    volPrmPtr->wearLevel.alarm    = (FLWord)info->alarm;
    volPrmPtr->wearLevel.currUnit = (FLWord)info->currUnit;
    volPrmPtr->eraseSum           = info->eraseSum;
    volPrmPtr->noOfUsedUnits      = (FLWord)info->noOfUsedUnits;
#ifndef TL_NO_STATISTICS 
    volPrmPtr->sectorsRead        = info->sectorsRead;
    volPrmPtr->sectorsWritten     = info->sectorsWritten;
    volPrmPtr->sectorsDeleted     = info->sectorsDeleted;
    volPrmPtr->parasiteWritesFromOldest = info->parasiteWritesFromOldest;
    volPrmPtr->parasiteWritesFromOldest = info->parasiteWritesFromOldest;
    volPrmPtr->unitsFoldedFromOldest    = info->unitsFoldedFromOldest;
    volPrmPtr->unitsFoldedFromNewest    = info->unitsFoldedFromNewest;
#endif /* FL_NO_STATISTICS */    

    flashPtr->args.startSector++; /* Skip first sector */

    /* Load unit cache   */
    status = loadQuickMountToBuffer(volPrmPtr, (FLByte FAR1 *)volPrmPtr->CT ,
                                    volPrmPtr->noOfCachedUnits * sizeof(CNANDCache));
    /* Load sector cache */
    if(status == flOK)
       status = loadQuickMountToBuffer(volPrmPtr, (FLByte FAR1 *)volPrmPtr->sectors ,
                                       (volPrmPtr->noOfCachedUnits << volPrmPtr->sectorsInUnitBits)
                                       * sizeof(FLWord));
    /* Load VUT table    */
    if(status == flOK)
       status = loadQuickMountToBuffer(volPrmPtr, (FLByte FAR1 *)volPrmPtr->VUT ,
                                       volPrmPtr->noOfVirtualUnits * sizeof(FLWord));
    /* Load CLT table    */
    if(status == flOK)
       status = loadQuickMountToBuffer(volPrmPtr, (FLByte FAR1 *)volPrmPtr->CLT ,
                                       volPrmPtr->noOfUnits * sizeof(FLByte));
    /* Load LUT table    */
    if(status == flOK)
       status = loadQuickMountToBuffer(volPrmPtr, (FLByte FAR1 *)volPrmPtr->LUT ,
                                       volPrmPtr->noOfUnits * sizeof(FLWord));
    if(status != flOK)
    {
       /* RE-store volPrmPtr record */
       tffscpy(volPrmPtr,bSavedCnandPtr,sizeof(Cnand));
       DBG_PRINT_WRN(FLZONE_TL,"Failed getting quick mount information.\r\n");
       DBG_PRINT_WRN_PRM(FLZONE_TL,(FLTXT("With status status %d.\r\n"),status));
       return FALSE;
    }   
    
    volPrmPtr->fIsQuickMountValid = TRUE; /* Prevent re-writing of the quick mount */
    return TRUE;
    
}


#ifndef FL_READ_ONLY

/*----------------------------------------------------------------------*/
/*               s t o r e Q u i c k M o u n t B u f f e r              */
/*                                                                      */
/* Store a RAM table to the quick mount area.                           */
/*                                                                      */
/* Notes                                                                */
/*  The routine uses both saftlBuffer + all of volPrmPtr->foldingBuffer */
/*                                                                      */
/* Parameters:                                                          */
/*    volPrmPtr       : Pointer identifying drive                       */
/*    volPrmPtr->flash->args.startSector  : Flash address to write to   */
/*    volPrmPtr->flash->args.writeMainBuf : Location in internal buffer */
/*    bufPtr          : Pointer to read the data to                     */
/*    endBufPtr       : Pointer to end of internal buffer (minus 512)   */
/*    dwSize          : Size to write in bytes                          */
/*                                                                      */
/* Returns:                                                             */
/*       flOK if the data was successfully loaded.                      */
/*       Any other value for failure.                                   */
/*----------------------------------------------------------------------*/

static FLStatus storeQuickMountBuffer(Cnand * volPrmPtr,
                                      FLByte FAR1 * bufPtr,
                                      FLByte FAR1 * endBufPtr,
                                      FLDword dwSize)
{   
   FLFlash * flashPtr         = volPrmPtr->flash;
   FLDword dwEndAddress       = flashPtr->args.startSector + 
                                ((dwSize+FL_SECTOR_MASK)>>FL_SECTOR_SIZE_BITS);
   FLDword dwUnitSectorMask   = (1L << volPrmPtr->sectorsInUnitBits) - 1; 
   FLDword dwUnitOffset;
   FLDword dwNoneFullSector   = (dwSize & FL_SECTOR_MASK) ? dwEndAddress - 1 : 
                                SAFTL_INVALID_SECTOR_NO;
   FLByte bNoOfSkippedUnits   = 0;

   while(flashPtr->args.startSector < dwEndAddress)
   {
      /* Copy the data to intenal buffer and pad with 0's if neccesary */
      if(flashPtr->args.startSector == dwNoneFullSector)
      {
         tffsset((void FAR1 *)flashPtr->args.writeMainBuf,00,FL_SECTOR_SIZE);
         tffscpy((void FAR1 *)flashPtr->args.writeMainBuf,bufPtr,(dwSize & FL_SECTOR_MASK));
      }
      else /* A full 512 bytes of data - can be read directly to the buffer */
      {
         tffscpy((void FAR1 *)flashPtr->args.writeMainBuf,bufPtr,FL_SECTOR_SIZE);
         bufPtr                      = BYTE_ADD_FAR(bufPtr,FL_SECTOR_SIZE); 
      }

      /* Check if internal buffer is full - need to write */
      if(flashPtr->args.writeMainBuf != endBufPtr)
      {
         /* Buffer is not full yet , copy the data and continue */
         flashPtr->args.writeMainBuf = BYTE_ADD_FAR(flashPtr->args.writeMainBuf,FL_SECTOR_SIZE);
         flashPtr->args.startSector++;
      }
      else /* The intenal buffer is full - write the data */
      {
         /* Write to the begining of the page */
         flashPtr->args.startSector -= (volPrmPtr->foldingBufferSize >> FL_SECTOR_SIZE_BITS) - 1;
         flashPtr->args.writeMainBuf = volPrmPtr->foldingBuffer;

         /* Make sure it is on a good unit */
         if((flashPtr->args.startSector & dwUnitSectorMask) == 0)
         {
            /* Find next good block */
            dwUnitOffset = (flashPtr->args.startSector >> volPrmPtr->sectorsInUnitBits) - 
                           volPrmPtr->firstQuickMountUnit; 
            while ((saftlBuffer[dwUnitOffset] != BBT_GOOD_UNIT) ||
                   (bNoOfSkippedUnits != 0                    )    )
            {
               switch(saftlBuffer[dwUnitOffset])
               {
                  case BBT_UNAVAIL_UNIT:
                     bNoOfSkippedUnits = flashPtr->args.noOfSkippedUnits;
                     /* No break */
                  case BBT_BAD_UNIT:
                     break;

                  default: /* BBT_GOOD_UNIT */
                     bNoOfSkippedUnits--;
                     break;
               }
               if(dwUnitOffset >= FL_SECTOR_SIZE)
                  return flGeneralFailure;
               dwEndAddress     += volPrmPtr->sectorsInUnit;
               dwNoneFullSector += volPrmPtr->sectorsInUnit;
               dwUnitOffset++;
            }
            flashPtr->args.startSector = (dwUnitOffset + (FLDword)volPrmPtr->firstQuickMountUnit)
                                         << volPrmPtr->sectorsInUnitBits;  
         }
         checkStatus(flashPtr->flashWrite(flashPtr))
         flashPtr->args.startSector += volPrmPtr->foldingBufferSize >> FL_SECTOR_SIZE_BITS;
      }  /* End if - internal buffer is full */
   } /* End loop over give buffer */
   return flOK;
}



/*----------------------------------------------------------------------*/
/*            s t o r e E n t i r e Q u i c k M o u n t I n f o         */
/*                                                                      */
/* Save the quick mount information from the RAM tables to the flash.   */
/*                                                                      */
/* Parameters:                                                          */
/*      volPrmPtr       : Pointer identifying drive                     */
/*                                                                      */
/* Returns:                                                             */
/*       flOK if data was written properly. Any other value for failure */
/*----------------------------------------------------------------------*/

static FLStatus storeEntireQuickMountInfo(Cnand *volPrmPtr)
{
    FLFlash             * flashPtr = volPrmPtr->flash;
    CNANDQuickMountInfo * info = (CNANDQuickMountInfo *)volPrmPtr->foldingBuffer;
    FLStatus              status;
    /* Last internal buffer location , before writing */
    FLByte FAR1         * endBufPtr = BYTE_ADD_FAR(volPrmPtr->foldingBuffer,
                                      volPrmPtr->foldingBufferSize - FL_SECTOR_SIZE);
    FLWord                wCachedUnits = volPrmPtr->noOfCachedUnits;

    if((volPrmPtr->volumeFlags & SAFTL_QUICK_MOUNT) == 0)
        return flOK;

    /* Find the first good unit of the partition */
    checkStatus(discardQuickMountInfo(volPrmPtr));
  
    /* Prepare for writing the quick mount data */    
    flashPtr->args.startSector  = 1L + ((FLDword)volPrmPtr->firstQuickMountUnit << 
                                  volPrmPtr->sectorsInUnitBits);
    flashPtr->args.noOfSectors  = volPrmPtr->foldingBufferSize >> FL_SECTOR_SIZE_BITS;
    flashPtr->args.writeMainBuf = BYTE_ADD_FAR(volPrmPtr->foldingBuffer,FL_SECTOR_SIZE); 
    flashPtr->args.extraBuf    = (FLByte FAR1 *)volPrmPtr->myHeaders; 
    flashPtr->args.opFlags     = MTD_DATA | MTD_EXTRA | volPrmPtr->MTDFlags;

    /* Build volume information sector */
    tffsset(volPrmPtr->myHeaders,0,volPrmPtr->sectorsInUnit * sizeof(CNANDSectorHeader));
    tffsset(volPrmPtr->foldingBuffer,0,FL_SECTOR_SIZE);
    info->quickMountVersion  = SAFTL_QUICK_MOUNT_VERSION;
    info->endianValidation   = SAFTL_ENDIAN_VALIDATION_MARK;
    info->noOfCachedUnits    = (FLDword) volPrmPtr->noOfCachedUnits;
    info->neededFreeUnits    = (FLDword) volPrmPtr->neededFreeUnits;
    info->freeUnits          = (FLDword) volPrmPtr->freeUnits;
    info->roverUnit          = (FLDword) volPrmPtr->roverUnit;
    info->bootUnits          = (FLDword) volPrmPtr->bootUnits;
    info->multiUnitListHead  = (FLDword) volPrmPtr->multiUnitListHead;
    info->multiUnitListTail  = (FLDword) volPrmPtr->multiUnitListTail;

⌨️ 快捷键说明

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