userlibandfileserver/fileserver/sfat32/sl_fatcache.cpp
changeset 15 4122176ea935
child 87 2f92ad2dc5db
equal deleted inserted replaced
0:a41df078684a 15:4122176ea935
       
     1 // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // f32\sfat32\sl_fatcache.cpp
       
    15 // FAT12 and FAT16 cache implementation
       
    16 // 
       
    17 //
       
    18 
       
    19 /**
       
    20  @file
       
    21 */
       
    22 
       
    23 #include "sl_std.h"
       
    24 #include "sl_fatcache.h"
       
    25 
       
    26 
       
    27 //#################################################################################################################################
       
    28 //  CFatCacheBase implementation
       
    29 //  Base class for all types of FAT cache
       
    30 //#################################################################################################################################
       
    31 
       
    32 CFatCacheBase::~CFatCacheBase()
       
    33     {
       
    34     Close(ETrue); //-- deallocate cache's memory discarding any dirty data
       
    35     }
       
    36 
       
    37 CFatCacheBase::CFatCacheBase()
       
    38     {
       
    39     iCurrentFatNo = KInvalidFatNo;
       
    40     SetDirty(EFalse);
       
    41     }
       
    42 
       
    43 
       
    44 /**
       
    45     FAT cache initialisation.
       
    46 
       
    47     @param  aOwner pointer to the owning FAT mount
       
    48 */
       
    49 void CFatCacheBase::InitialiseL(CFatMountCB* aOwner)
       
    50     {
       
    51     ASSERT(aOwner);
       
    52     
       
    53     Close(ETrue); //-- deallocate cache's memory discarding any dirty data
       
    54     
       
    55     //-- populate parameters from the owning mount
       
    56     iFatType = aOwner->FatType();
       
    57     __ASSERT_ALWAYS((iFatType == EFat12 || iFatType == EFat16 || iFatType == EFat32), User::Leave(KErrCorrupt));  
       
    58     
       
    59     ipDrive = &aOwner->DriveInterface();
       
    60     iFatStartPos = aOwner->FirstFatSector() << aOwner->SectorSizeLog2(); 
       
    61     iFatSize = aOwner->FatSizeInBytes();
       
    62     iNumFATs = (TUint16)aOwner->NumberOfFats();
       
    63     iFatSecSzLog2   = (TUint16)aOwner->SectorSizeLog2(); 
       
    64     iFatClustSzLog2 = (TUint16)aOwner->ClusterSizeLog2();
       
    65 
       
    66     __ASSERT_ALWAYS(iNumFATs >=1, User::Leave(KErrCorrupt));
       
    67 
       
    68     __PRINT3(_L("#-CFatCacheBase::InitialiseL() FatStart:%u, FatSz:%d, drv:%d"),iFatStartPos, iFatSize, aOwner->DriveNumber());
       
    69     }
       
    70 
       
    71 //-----------------------------------------------------------------------------
       
    72 /**
       
    73     This method shall be called to check if we are allowed to invalidate dirty cache, i.e. discard non-flushed data.
       
    74     The behaviour is hardcoded (see KAllowInvalidateDirtyCache constant)
       
    75 
       
    76     @return ETrue if invalidating dirty cache is allowed. Otherwise panics the current thread
       
    77 */
       
    78 TBool CFatCacheBase::CheckInvalidatingDirtyCache() const
       
    79     {
       
    80     
       
    81     //-- If not EFalse, invalidating dirty cache (pages) is allowed. This shall be OK, because
       
    82     //-- invalidating the cache is required only after direct media writes to the FAT by RawWrite, which can corrupt it anyway. 
       
    83     TBool KAllowInvalidateDirtyCache = ETrue;
       
    84     
       
    85     if(!IsDirty())
       
    86         return KAllowInvalidateDirtyCache;        
       
    87 
       
    88     __PRINT(_L("#-CFatCacheBase::Invalidating dirty cache !"));
       
    89     
       
    90     if(!KAllowInvalidateDirtyCache)
       
    91         {
       
    92         __ASSERT_ALWAYS(0, Fault(EFatCache_DiscardingDirtyData));
       
    93         }
       
    94 
       
    95     return KAllowInvalidateDirtyCache;        
       
    96     }
       
    97 
       
    98 //-----------------------------------------------------------------------------
       
    99 
       
   100 /**
       
   101     Read portion of raw data from 1st FAT copy.
       
   102     
       
   103     @param  aPos   media position in the _FIRST_ FAT to start reading with
       
   104     @param  aLen   number of bytes to read
       
   105     @param  aData  data descriptor
       
   106 
       
   107     @return standard error code.
       
   108 */
       
   109 TInt CFatCacheBase::ReadFatData(TUint32 aPos, TUint32 aLen, TDes8& aData) const
       
   110     {
       
   111     //__PRINT2(_L("#-CFatCacheNew::ReadFatData() pos:%u, Len:%d"), aPos, aLen);
       
   112 
       
   113     //-- this method can pick up data corresponding to invalid FAT entries, like FAT[0], FAT[1] and
       
   114     //-- the last portion beyond FAT because of read granularity. This isn't a problem, because the data there
       
   115     //-- won't be written on disk.
       
   116     ASSERT(aPos >= FatStartPos()); 
       
   117 
       
   118     return ipDrive->ReadNonCritical(aPos, aLen, aData);
       
   119     }
       
   120 
       
   121 //-----------------------------------------------------------------------------
       
   122 
       
   123 /** 
       
   124     Writes data to the FAT table, which number is set in iCurrentFatNo member variable. 
       
   125     @param  aPos   data media position in the _FIRST_ FAT copy
       
   126     @param  aData  data descriptor
       
   127     @return standard error code.
       
   128 */
       
   129 TInt CFatCacheBase::WriteFatData(TUint32 aPos, const TDesC8& aData) const
       
   130     {
       
   131     //__PRINT3(_L("#-CFatCacheBase::WriteFatData() pos:%u, Len:%d, FAT:%d"), aPos, aData.Length(), iCurrentFatNo);
       
   132 
       
   133 #ifdef _DEBUG    
       
   134     //-- FAT[0] and FAT[1] entries are reserved and we must not write data there. It's up to the caller of this method to
       
   135     //-- calculate correct data position in FAT
       
   136     TInt reserved_Entries_Offset=0;
       
   137     switch(iFatType)
       
   138         {
       
   139         case EFat32: reserved_Entries_Offset = KFatFirstSearchCluster*sizeof(TFat32Entry); break;  //-- FAT32  
       
   140         case EFat16: reserved_Entries_Offset = KFatFirstSearchCluster*sizeof(TFat16Entry); break;  //-- FAT16  
       
   141         case EFat12: reserved_Entries_Offset = 3;   break;                                         //-- FAT12
       
   142         default: ASSERT(0); break;
       
   143         }
       
   144     ASSERT(aPos >= FatStartPos()+reserved_Entries_Offset);
       
   145     ASSERT((aPos+aData.Length()) <= FatStartPos()+FatSize());
       
   146     ASSERT(iCurrentFatNo < iNumFATs);
       
   147 #endif    
       
   148 
       
   149     //-- goto the required FAT copy. iCurrentFatNo shall contain FAT number we are writing to.
       
   150     aPos+=iCurrentFatNo*FatSize(); 
       
   151 
       
   152     return ipDrive->WriteCritical(aPos, aData);
       
   153     }
       
   154 
       
   155 //-----------------------------------------------------------------------------
       
   156 /** 
       
   157     get a pointer to the CFatBitCache interface. 
       
   158     @return NULL because it is not present here 
       
   159 */
       
   160 CFatBitCache* CFatCacheBase::BitCacheInterface() 
       
   161     {
       
   162     return NULL;
       
   163     }
       
   164     
       
   165 
       
   166 //#################################################################################################################################
       
   167 //  CFatPagedCacheBase implementation
       
   168 //  Base class for all paged FAT caches
       
   169 //#################################################################################################################################
       
   170 
       
   171 CFatPagedCacheBase::CFatPagedCacheBase()
       
   172                :CFatCacheBase() 
       
   173     {
       
   174     }
       
   175 
       
   176 
       
   177 //#################################################################################################################################
       
   178 //  CFatCachePageBase implementation
       
   179 //  Base class for FAT cache pages (FAT16 fixed and FAT32 LRU)
       
   180 //#################################################################################################################################
       
   181 
       
   182 CFatCachePageBase::CFatCachePageBase(CFatPagedCacheBase& aCache)
       
   183                   :iCache(aCache)
       
   184     {
       
   185     ASSERT(IsPowerOf2(aCache.PageSize()));
       
   186     iStartIndexInFAT = KMaxTUint;
       
   187 
       
   188     //-- calculate number of FAT entries in the page, it depends on FAT type
       
   189     switch(aCache.FatType())
       
   190         {
       
   191         case EFat32:
       
   192             iFatEntriesInPage = PageSize() >> KFat32EntrySzLog2;
       
   193         break;
       
   194     
       
   195         case EFat16:
       
   196             iFatEntriesInPage = PageSize() >> KFat16EntrySzLog2;
       
   197         break;
       
   198     
       
   199         default:
       
   200             ASSERT(0);
       
   201             Fault(EFatCache_BadFatType);
       
   202         break;
       
   203 
       
   204         };
       
   205 
       
   206     SetState(EInvalid); 
       
   207     }
       
   208 
       
   209 CFatCachePageBase::~CFatCachePageBase()
       
   210     {
       
   211     iData.Close();
       
   212     }
       
   213 
       
   214 //-----------------------------------------------------------------------------
       
   215 /**
       
   216     Mark the page as "invalid". I.e containing inalid data.
       
   217     On the first read/write access to such page it will be re-read from the media
       
   218 
       
   219     @param aIgnoreDirtyData if ETrue, it is allowed to ignore the fact that the page contains dirty (not flushed) data.
       
   220 */
       
   221 void CFatCachePageBase::Invalidate(TBool aIgnoreDirtyData /*= EFalse*/)
       
   222     {
       
   223     if(!aIgnoreDirtyData && IsDirty())
       
   224         {
       
   225         __PRINT1(_L("#-CFatCachePageBase::Invalidate() dirty page! FAT idx:%d"), iStartIndexInFAT);
       
   226         __ASSERT_ALWAYS(0, Fault(EFatCache_DiscardingDirtyData));
       
   227         }
       
   228 
       
   229     iDirtySectors.Clear(); //-- clear dirty sectors bitmap
       
   230     SetState(EInvalid);
       
   231     }
       
   232 
       
   233 //-----------------------------------------------------------------------------
       
   234 /**
       
   235     Flush all dirty page sectors to the media and mark the page as "clean" if required.
       
   236     If the page is "clean" i.e doesn't contain changed data, does nothing.
       
   237 
       
   238     @param  aKeepDirty  if ETrue, the "dirty" flag isn't reset after page flushing.
       
   239 */
       
   240 void CFatCachePageBase::FlushL(TBool aKeepDirty)
       
   241     {
       
   242     if(!IsDirty())
       
   243         return;
       
   244 
       
   245     if(!IsValid())
       
   246         {
       
   247         __PRINT1(_L("#-CFatCachePageBase::FlushL() Invalid page! FAT idx:%d"), iStartIndexInFAT);
       
   248         ASSERT(0);
       
   249         User::Leave(KErrCorrupt);
       
   250         return;
       
   251         }
       
   252 
       
   253     //__PRINT1(_L("#-CFatCachePageBase::FlushL() FAT idx:%d"), iStartIndexInFAT);
       
   254 
       
   255     //-- write dirty FAT sectors  to the media one by one. 
       
   256     //-- merging adjacent dirty subsectors into larger clusters and writing them at once looks like a good idea, but
       
   257     //-- in reality it showed FAT performance degradation, at least on MMC/SD media.
       
   258     
       
   259     const TInt MaxSectors = iCache.SectorsInPage();
       
   260     
       
   261     for(TInt i=0; i<MaxSectors; ++i)
       
   262         {
       
   263         if(iDirtySectors[i])
       
   264             {
       
   265             DoWriteSectorL(i);
       
   266             }
       
   267         }
       
   268 
       
   269     //-- All data flushed; mark page as clean if it isn't required not to do.
       
   270     if(!aKeepDirty)
       
   271         SetClean(); 
       
   272 
       
   273     }
       
   274 
       
   275 
       
   276 //#################################################################################################################################
       
   277 //  CFat16FixedCache implementation
       
   278 //  Fixed cache (caches all FAT16) but organised as an array of pages
       
   279 //#################################################################################################################################
       
   280 
       
   281 CFat16FixedCache::CFat16FixedCache()
       
   282                  :CFatPagedCacheBase(),iPages(1) //-- array granularity is 1
       
   283     {
       
   284     }
       
   285 
       
   286 //-----------------------------------------------------------------------------
       
   287 /**
       
   288     FAT16 fixed cache factory function.
       
   289     @param  aOwner              pointer to the owning FAT mount
       
   290     @param  aFatSize            size of the FAT table in bytes
       
   291     @param  aRdGranularityLog2  Log2(read granularity)
       
   292     @param  aWrGranularityLog2  Log2(write granularity)
       
   293 
       
   294     @return pointer to the constructed object.
       
   295 */
       
   296 CFat16FixedCache* CFat16FixedCache::NewL(CFatMountCB* aOwner, TUint32 aFatSize, TUint32 aRdGranularityLog2, TUint32 aWrGranularityLog2)
       
   297     {
       
   298     __PRINT(_L("#-CFat16FixedCache::NewL()"));
       
   299 
       
   300     CFat16FixedCache* pSelf = NULL;
       
   301     pSelf = new (ELeave) CFat16FixedCache;
       
   302 
       
   303     CleanupStack::PushL(pSelf);
       
   304     pSelf->InitialiseL(aOwner, aFatSize, aRdGranularityLog2, aWrGranularityLog2);
       
   305     CleanupStack::Pop();
       
   306     
       
   307     return pSelf;
       
   308     }
       
   309 
       
   310 //-----------------------------------------------------------------------------
       
   311 /**
       
   312     FAT16 fixed cache initialisation.
       
   313     @param  aOwner              pointer to the owning FAT mount
       
   314     @param  aFatSize            size of the FAT table in bytes
       
   315     @param  aRdGranularityLog2  Log2(read granularity)
       
   316     @param  aWrGranularityLog2  Log2(write granularity)
       
   317 */
       
   318 void CFat16FixedCache::InitialiseL(CFatMountCB* aOwner, TUint32 aFatSize, TUint32 aRdGranularityLog2, TUint32 aWrGranularityLog2)
       
   319     {
       
   320     const TUint32 ReadGranularity = Pow2(aRdGranularityLog2);
       
   321     const TUint32 WriteGranularity = Pow2(aWrGranularityLog2);
       
   322 
       
   323     __PRINT3(_L("#-CFat16FixedCache::InitialiseL FatSz:%u, RdGr:%d, WrGr:%d"),aFatSize, ReadGranularity, WriteGranularity);
       
   324     (void)ReadGranularity;
       
   325     (void)WriteGranularity;
       
   326 
       
   327     TBool bParamsValid = (aRdGranularityLog2 >= aWrGranularityLog2) && (aWrGranularityLog2 >= KDefSectorSzLog2);
       
   328     __ASSERT_ALWAYS(bParamsValid, Fault(EFatCache_BadGranularity));
       
   329 
       
   330     CFatPagedCacheBase::InitialiseL(aOwner);
       
   331     
       
   332     ASSERT(FatType() == EFat16);
       
   333 
       
   334     //-- See FAT specs, and round up the limit to the FAT sector boundary
       
   335     const TUint32 KMaxFat16Size = ((65524*sizeof(TFat16Entry)+FAT_SectorSz()-1) >> FAT_SectorSzLog2()) << FAT_SectorSzLog2(); 
       
   336     const TUint32 KMinFat16Size = 4086*sizeof(TFat16Entry);  //-- See FAT specs
       
   337     
       
   338     bParamsValid = aFatSize >= KMinFat16Size && aFatSize <= KMaxFat16Size;
       
   339 	__ASSERT_ALWAYS(bParamsValid, User::Leave(KErrCorrupt));
       
   340 
       
   341     //-- cache page size is (2^aRdGranularityLog2) bytes and consists of 2^(aRdGranularityLog2-aWrGranularity) sectors.
       
   342     iPageSizeLog2 = aRdGranularityLog2;
       
   343     iSectorSizeLog2 = aWrGranularityLog2; //-- Log2(number of sectors in cache page)
       
   344     
       
   345     __ASSERT_ALWAYS(SectorsInPage() < KMaxSectorsInPage, Fault(EFatCache_BadGranularity));
       
   346 
       
   347     const TUint numPages = (aFatSize+(PageSize()-1)) >> iPageSizeLog2;
       
   348     __PRINT1(_L("#-CFat16FixedCache Num Pages:%d"), numPages);
       
   349 
       
   350     //-- prepare pointer array for pages. NULL entry in the array means that the page at this index isn't allocated.
       
   351     for(TUint i=0; i<numPages; ++i)
       
   352         iPages.Append(NULL);
       
   353     
       
   354     }
       
   355 
       
   356 
       
   357 //-----------------------------------------------------------------------------
       
   358 /**
       
   359     Close the cache and deallocate its memory.
       
   360     @param  aDiscardDirtyData if ETrue, will ignore dirty data. If EFalse, will panic on atempt to close dirty cache.  
       
   361 */
       
   362 void CFat16FixedCache::Close(TBool aDiscardDirtyData)
       
   363     {
       
   364     __PRINT1(_L("#-CFat16FixedCache::Close(%d)"), aDiscardDirtyData);
       
   365 
       
   366     TInt cnt = iPages.Count();
       
   367     while(cnt--)
       
   368         {//-- delete pages
       
   369         CFat16FixedCachePage *pPage = iPages[cnt];
       
   370         if(pPage && (pPage->IsDirty()))
       
   371             {//-- trying to destroy the cache that has dirty pages
       
   372             __PRINT1(_L("#-CFat16FixedCache::Close() The page is dirty! Start idx:%d"), pPage->StartFatIndex());
       
   373             if(!aDiscardDirtyData)
       
   374                 {
       
   375                 __ASSERT_ALWAYS(0, Fault(EFatCache_DiscardingDirtyData));
       
   376                 }
       
   377             //-- ignore this fact if requested.
       
   378             }
       
   379         
       
   380         delete pPage;
       
   381         }
       
   382 
       
   383     iPages.Close();
       
   384     SetDirty(EFalse);
       
   385     }
       
   386 
       
   387 //-----------------------------------------------------------------------------
       
   388 /**
       
   389     Read FAT entry from the cache. 
       
   390 
       
   391     @param  aIndex FAT entry index to read
       
   392     @return FAT entry value at the index "aIndex" 
       
   393 */
       
   394 TUint32 CFat16FixedCache::ReadEntryL(TUint32 aIndex)
       
   395     {
       
   396     //__PRINT1(_L("#-CFat16FixedCache::ReadEntryL() FAT idx:%d"), aIndex);
       
   397     ASSERT(aIndex >= KFatFirstSearchCluster &&  aIndex < (FatSize() >> KFat16EntrySzLog2));
       
   398 
       
   399     //-- calculate page index in the array
       
   400     const TInt pgIdx = aIndex >> (PageSizeLog2()-KFat16EntrySzLog2);
       
   401     CFat16FixedCachePage *pPage = iPages[pgIdx];
       
   402     
       
   403     TUint32 entry = KMaxTUint;
       
   404 
       
   405     if(!pPage)
       
   406         {//-- page at this position isn't allocated yet
       
   407         pPage = CFat16FixedCachePage::NewL(*this);
       
   408         iPages[pgIdx] = pPage;
       
   409         
       
   410         //-- read the page from media
       
   411         entry = pPage->ReadFromMediaL(aIndex);
       
   412         }
       
   413     else
       
   414         {//-- get cached entry from the page
       
   415         TBool bRes = pPage->ReadCachedEntryL(aIndex, entry);
       
   416         ASSERT(bRes);
       
   417         (void)bRes;
       
   418         }
       
   419 
       
   420     return entry;
       
   421     }
       
   422 
       
   423 //-----------------------------------------------------------------------------
       
   424 /**
       
   425     Write FAT entry to the cache. 
       
   426     Appropriate FAT cache sector will be marked as "dirty" and will be eventually flushed to the media.
       
   427 
       
   428     @param  aIndex FAT entry index
       
   429     @param  aEntry FAT entry value
       
   430 */
       
   431 void CFat16FixedCache::WriteEntryL(TUint32 aIndex, TUint32 aEntry)
       
   432     {
       
   433     //__PRINT2(_L("#-CFat16FixedCache::WriteEntryL() FAT idx:%d, val:%d"), aIndex, aEntry);
       
   434 
       
   435     ASSERT(aIndex >= KFatFirstSearchCluster &&  aIndex < (FatSize() >> KFat16EntrySzLog2));
       
   436 
       
   437     SetDirty(ETrue);
       
   438 
       
   439     //-- calculate page index in the array
       
   440     const TInt pgIdx = aIndex >> (PageSizeLog2()-KFat16EntrySzLog2);
       
   441     CFat16FixedCachePage *pPage = iPages[pgIdx];
       
   442 
       
   443     if(!pPage)
       
   444         {//-- page at this position isn't allocated yet
       
   445         pPage = CFat16FixedCachePage::NewL(*this);
       
   446         iPages[pgIdx] = pPage;
       
   447         
       
   448         //-- read the page from media
       
   449         pPage->ReadFromMediaL(aIndex);
       
   450         }
       
   451 
       
   452     //-- overwrite entry in cache
       
   453     TBool bRes = pPage->WriteCachedEntryL(aIndex, aEntry);
       
   454     ASSERT(bRes);
       
   455     (void)bRes;
       
   456     }
       
   457 
       
   458 /**
       
   459     A debug method that asserts that the cache is really clean
       
   460 */
       
   461 void CFat16FixedCache::AssertCacheReallyClean() const
       
   462     {
       
   463 #ifdef _DEBUG 
       
   464         for(TUint i=0; i<NumPages(); ++i)
       
   465         {
       
   466             CFat16FixedCachePage* pPage = iPages[i];
       
   467             if(pPage && pPage->IsDirty())
       
   468                 {
       
   469                 __PRINT(_L("#-CFat16FixedCache::AssertCacheReallyClean()"));
       
   470                 ASSERT(0);
       
   471                 }
       
   472         }
       
   473 #endif   
       
   474     }
       
   475 
       
   476 
       
   477 //-----------------------------------------------------------------------------
       
   478 /**
       
   479     Flushes all dirty data to the media.
       
   480 */
       
   481 void CFat16FixedCache::FlushL()
       
   482     {
       
   483     if(!IsDirty())
       
   484         {
       
   485         AssertCacheReallyClean();
       
   486         return;
       
   487         }
       
   488 
       
   489 
       
   490     //-- flush dirty data to all copies of FAT
       
   491     for(iCurrentFatNo=0; iCurrentFatNo < NumFATs(); ++iCurrentFatNo)
       
   492         {
       
   493         const TInt nPages = NumPages();
       
   494         for(TInt i=0; i<nPages; ++i)
       
   495             {
       
   496             const TBool keepDirty = iCurrentFatNo < (NumFATs() - 1);
       
   497 
       
   498             CFat16FixedCachePage* pPage = iPages[i];
       
   499             if(pPage)
       
   500                 pPage->FlushL(keepDirty);
       
   501             }
       
   502        
       
   503         }
       
   504    
       
   505     iCurrentFatNo = KInvalidFatNo;
       
   506     SetDirty(EFalse);
       
   507     }
       
   508 
       
   509 //-----------------------------------------------------------------------------
       
   510 /**
       
   511     Invalidate whole cache. All pages will be marked as invalid and will be re-read from the media on first access to them.
       
   512     @return always KErrNone
       
   513 */
       
   514 TInt CFat16FixedCache::Invalidate()
       
   515     {
       
   516     __PRINT(_L("#-CFat16FixedCache::Invalidate()"));
       
   517     const TBool bIgnoreDirtyData = CheckInvalidatingDirtyCache();
       
   518 
       
   519     //-- iterate through the array of pages marking invalidating every page
       
   520     TInt cnt = iPages.Count();
       
   521     while(cnt--)
       
   522         {//-- delete pages
       
   523         CFat16FixedCachePage *pPage = iPages[cnt];
       
   524         if(pPage)
       
   525             pPage->Invalidate(bIgnoreDirtyData);
       
   526         }
       
   527 
       
   528 
       
   529     SetDirty(EFalse);
       
   530 
       
   531     return KErrNone;
       
   532     }
       
   533 
       
   534 //-----------------------------------------------------------------------------
       
   535 /**
       
   536     Invalidate FAT cache pages that contain FAT entries from aStartIndex to (aStartIndex+aNumEntries)
       
   537     These pages will be marked as invalid and will be re-read from the media on first access to them.
       
   538     
       
   539     @param  aStartIndex FAT start index of the region being invalidated
       
   540     @param  aNumEntries number of entries to invalidate
       
   541     @return always KErrNone
       
   542 */
       
   543 TInt CFat16FixedCache::InvalidateRegion(TUint32 aStartIndex, TUint32 aNumEntries)
       
   544     {
       
   545     __PRINT2(_L("#-CFat16FixedCache::InvalidateRegion() startIndex:%d, entries:%d"),aStartIndex, aNumEntries);
       
   546     ASSERT(aStartIndex >= KFatFirstSearchCluster &&  aStartIndex < (FatSize() >> KFat16EntrySzLog2));
       
   547 
       
   548     if(!aNumEntries)
       
   549         {
       
   550         ASSERT(0);
       
   551         return KErrNone;
       
   552         }
       
   553 
       
   554     const TBool bIgnoreDirtyData = CheckInvalidatingDirtyCache();
       
   555     const TUint startPgIdx  = aStartIndex >> (PageSizeLog2()-KFat16EntrySzLog2);
       
   556     const TUint nPagesToInv = 1+(aNumEntries >> (PageSizeLog2()-KFat16EntrySzLog2));
       
   557 
       
   558     TUint i;
       
   559     //-- invalidate pages that contain [aStartIndex ... aStartIndex+aNumEntries] entries
       
   560     for(i=0; i<nPagesToInv; ++i)
       
   561         {
       
   562         const TUint pageIdx = i+startPgIdx;
       
   563         if(pageIdx >= NumPages())
       
   564             break;
       
   565         
       
   566         CFat16FixedCachePage* pPage = iPages[pageIdx];
       
   567         if(pPage)
       
   568             pPage->Invalidate(bIgnoreDirtyData);
       
   569         } 
       
   570 
       
   571     SetDirty(EFalse);
       
   572    
       
   573     //-- check if the cache still has dirty pages
       
   574     for(i=0; i<NumPages(); ++i)
       
   575         {
       
   576         CFat16FixedCachePage* pPage = iPages[i];
       
   577         if(pPage && pPage->IsDirty()) 
       
   578             {
       
   579             SetDirty(ETrue);
       
   580             break;
       
   581             }      
       
   582         }
       
   583 
       
   584     return KErrNone;
       
   585     }
       
   586 
       
   587 //#################################################################################################################################
       
   588 //  CFat16FixedCachePage implementation
       
   589 //  Page for the FAT16 fixed cache
       
   590 //#################################################################################################################################
       
   591 
       
   592 //-----------------------------------------------------------------------------
       
   593 
       
   594 CFat16FixedCachePage::CFat16FixedCachePage(CFatPagedCacheBase& aCache)
       
   595                      :CFatCachePageBase(aCache)
       
   596     {
       
   597     ASSERT(IsPowerOf2(EntriesInPage()));
       
   598     }
       
   599 
       
   600 
       
   601 /**
       
   602     Factory function.
       
   603     @param aCache reference to the owning cache.
       
   604     @return pointer to the constructed object or NULL on error
       
   605 */
       
   606 CFat16FixedCachePage* CFat16FixedCachePage::NewL(CFatPagedCacheBase& aCache)
       
   607     {
       
   608     CFat16FixedCachePage* pSelf = NULL;
       
   609     pSelf = new (ELeave) CFat16FixedCachePage(aCache);
       
   610 
       
   611     CleanupStack::PushL(pSelf);
       
   612     
       
   613     pSelf->iData.CreateMaxL(aCache.PageSize()); //-- allocate memory for the page
       
   614    
       
   615     CleanupStack::Pop();
       
   616 
       
   617     return pSelf;
       
   618     }
       
   619 
       
   620 
       
   621 //-----------------------------------------------------------------------------
       
   622 /**
       
   623     Read FAT16 entry from the cache. 
       
   624     
       
   625     1. If page's data are valid, just extracts data from the page buffer.
       
   626     2. If page's data are invalid firstly reads data from the media and goto 1
       
   627     
       
   628     @param  aFatIndex entry's absolute FAT index (from the FAT start)
       
   629     @param  aResult on sucess there will be FAT16 entry value
       
   630     @return ETrue, because FAT16 cache pages never get eviched.
       
   631 */
       
   632 TBool CFat16FixedCachePage::ReadCachedEntryL (TUint32 aFatIndex, TUint32& aResult)
       
   633     {
       
   634     if(IsValid())
       
   635         {//-- read entry directly from page buffer, the cached data are valid
       
   636         aResult = (*GetEntryPtr(aFatIndex)) & KFat16EntryMask;
       
   637         }
       
   638     else
       
   639         {//-- aFatIndex belongs to this page, but the page is invalid and needs to be read from the media
       
   640         //__PRINT(_L("#-CFat16FixedCachePage::ReadCachedEntry() The page is invalid, reading from the media"));
       
   641         aResult = ReadFromMediaL(aFatIndex);
       
   642         }
       
   643 
       
   644     return ETrue;
       
   645     }
       
   646 
       
   647 //-----------------------------------------------------------------------------
       
   648 
       
   649 /**
       
   650     Writes FAT cache page sector to the media (to all copies of the FAT)
       
   651     @param  aSector sector number winthin this page
       
   652 */
       
   653 void CFat16FixedCachePage::DoWriteSectorL(TUint32 aSector)
       
   654     {
       
   655     //__PRINT1(_L("#-CFat16FixedCachePage::DoWriteSectorL() startSec:%d, cnt:%d"), aSector);
       
   656 
       
   657     ASSERT(aSector < iCache.SectorsInPage());
       
   658 
       
   659     TInt offset = 0;
       
   660 
       
   661     if(iStartIndexInFAT == 0 && aSector == 0)
       
   662         {//-- this is the very beginning of FAT16. We must skip FAT[0] & FAT[1] entries and do not write them to media.    
       
   663         offset = KFatFirstSearchCluster << KFat16EntrySzLog2; 
       
   664         }    
       
   665     
       
   666     const TUint8* pData = iData.Ptr()+offset+(aSector << iCache.SectorSizeLog2());
       
   667     
       
   668     TUint32 dataLen = (1 << iCache.SectorSizeLog2()) - offset;
       
   669 
       
   670     const TUint32 mediaPosStart = iCache.FatStartPos() + (iStartIndexInFAT << KFat16EntrySzLog2) + (aSector << iCache.SectorSizeLog2()) + offset; 
       
   671     const TUint32 mediaPosEnd = mediaPosStart + dataLen; 
       
   672 
       
   673     //-- check if we are going to write beyond FAT. It can happen if the write granularity is bigger that the sector size.
       
   674     const TUint32 posFatEnd = iCache.FatStartPos() + iCache.FatSize();
       
   675     if(mediaPosEnd > posFatEnd)
       
   676         {//-- correct the leength of the data to write.
       
   677         dataLen -= (mediaPosEnd-posFatEnd);
       
   678         }
       
   679 
       
   680     TPtrC8 ptrData(pData, dataLen); //-- source data descriptor 
       
   681 
       
   682     TInt nRes = iCache.WriteFatData(mediaPosStart, ptrData);
       
   683     
       
   684     if(nRes != KErrNone)
       
   685         {
       
   686         __PRINT1(_L("#-CFat16FixedCachePage::DoWriteSectorsL() failed! code:%d"), nRes);
       
   687         User::Leave(nRes);
       
   688         }
       
   689 
       
   690     }
       
   691 
       
   692 //-----------------------------------------------------------------------------
       
   693 /**
       
   694     Write FAT16 entry at aFatIndex to the cache. Note that the data are not written to the media, only to the cache page.
       
   695     Corresponding page sector is marked as dirty and will be flushed on FlushL() call later.
       
   696 
       
   697     1. If page's data are valid, copies data to the page buffer and marks sector as dirty.
       
   698     2. If page's data are invalid, firstly reads data from the media and goto 1
       
   699 
       
   700     @param  aFatIndex entry's absolute FAT index (from the FAT start)
       
   701     @param  aFatEntry FAT16 entry value
       
   702     @return ETrue because FAT16 cache pages never get eviched.
       
   703 */
       
   704 TBool CFat16FixedCachePage::WriteCachedEntryL(TUint32 aFatIndex, TUint32 aFatEntry)
       
   705     {
       
   706     
       
   707     ASSERT(IsEntryCached(aFatIndex));
       
   708 
       
   709     if(!IsValid())
       
   710         {//-- we are trying to write data to the page that has invalid data. //-- read the data from the media first.
       
   711         ReadFromMediaL(aFatIndex);
       
   712         }
       
   713 
       
   714     TFat16Entry* pEntry = GetEntryPtr(aFatIndex);
       
   715     
       
   716     const TFat16Entry orgEntry = *pEntry;
       
   717     *pEntry = (TFat16Entry)((orgEntry & ~KFat16EntryMask) | (aFatEntry & KFat16EntryMask));
       
   718     
       
   719     //-- mark corresponding sector of the cache page as dirty
       
   720     const TUint entryIndexInPage = aFatIndex & (EntriesInPage()-1); //-- number of entries in page is always a power of 2
       
   721     const TUint dirtySectorNum   = entryIndexInPage >> (iCache.SectorSizeLog2() - KFat16EntrySzLog2);
       
   722 
       
   723     ASSERT(dirtySectorNum < iCache.SectorsInPage());
       
   724 
       
   725     iDirtySectors.SetBit(dirtySectorNum);
       
   726     SetState(EDirty); //-- mark page as dirty.
       
   727 
       
   728     return ETrue;
       
   729     }
       
   730 
       
   731 //-----------------------------------------------------------------------------
       
   732 
       
   733 /**
       
   734     Get a pointer to the FAT16 entry in the page buffer.
       
   735     The page 's data shall be valid and the entry shall belong to this page.
       
   736     
       
   737     @param aFatIndex absolute FAT index (from the FAT start) of the entry
       
   738     @return pointer to the FAT16 entry in the page buffer.
       
   739 */
       
   740 TFat16Entry* CFat16FixedCachePage::GetEntryPtr(TUint32 aFatIndex) const
       
   741     {
       
   742     ASSERT(IsValid() && IsEntryCached(aFatIndex));
       
   743 
       
   744     const TUint KEntryIndexInPage = aFatIndex & (EntriesInPage()-1); //-- number of entries in page is always a power of 2
       
   745     TFat16Entry* pEntry = ((TFat16Entry*)iData.Ptr()) + KEntryIndexInPage;
       
   746 
       
   747     return  pEntry;
       
   748     }
       
   749 
       
   750 //-----------------------------------------------------------------------------
       
   751 /**
       
   752     Read the FAT16 cache page from the media and returns required FAT16 entry.    
       
   753 
       
   754     @param  aFatIndex entry's absolute FAT index (from the FAT start)
       
   755     @return entry value at aFatIndex.
       
   756 */
       
   757 TUint32 CFat16FixedCachePage::ReadFromMediaL(TUint32 aFatIndex)
       
   758     {
       
   759     //__PRINT1(_L("#-CFat16FixedCachePage::ReadFromMediaL() FAT idx:%d"), aFatIndex);
       
   760     const TUint KFat16EntriesInPageLog2 = iCache.PageSizeLog2()-KFat16EntrySzLog2; //-- number of FAT16 entries in page is always a power of 2
       
   761 
       
   762     //-- find out index in FAT this page starts from
       
   763     iStartIndexInFAT = (aFatIndex >> KFat16EntriesInPageLog2) << KFat16EntriesInPageLog2;
       
   764     SetState(EInvalid); //-- mark the page as invalid just in case if the read fails.
       
   765 
       
   766     //-- read page from the media
       
   767     const TUint32 pageStartPos = iCache.FatStartPos() + (iStartIndexInFAT << KFat16EntrySzLog2);
       
   768     
       
   769     TInt nRes = iCache.ReadFatData(pageStartPos, iCache.PageSize(), iData);
       
   770     if(nRes != KErrNone)
       
   771         {
       
   772         __PRINT1(_L("#-CFat16FixedCachePage::ReadFromMediaL() failed! code:%d"), nRes);
       
   773         User::Leave(nRes);
       
   774         }
       
   775 
       
   776     SetClean(); //-- mark this page as clean
       
   777 
       
   778     const TFat16Entry entry = (TFat16Entry)((*GetEntryPtr(aFatIndex)) & KFat16EntryMask);
       
   779 
       
   780     return entry;
       
   781     }
       
   782 
       
   783 
       
   784 //-----------------------------------------------------------------------------
       
   785 
       
   786 //#################################################################################################################################
       
   787 //  CFat12Cache implementation
       
   788 //  FAT12 non-paged fixed cache. This cache consists from only 1 page, logically divided up to 32 sectors (write granularity unit)
       
   789 //#################################################################################################################################
       
   790 
       
   791 CFat12Cache::CFat12Cache()
       
   792             :CFatCacheBase()
       
   793     {
       
   794     }
       
   795 
       
   796 //-----------------------------------------------------------------------------
       
   797 /**
       
   798     FAT12 fixed cache factory function.
       
   799     @param  aOwner              pointer to the owning FAT mount
       
   800     @param  aFatSize            size of the FAT table in bytes
       
   801 
       
   802     @return pointer to the constructed object.
       
   803 */
       
   804 CFat12Cache* CFat12Cache::NewL(CFatMountCB* aOwner, TUint32 aFatSize)
       
   805     {
       
   806     __PRINT(_L("#-CFat12Cache::NewL()"));
       
   807     CFat12Cache* pSelf = NULL;
       
   808     pSelf = new (ELeave) CFat12Cache;
       
   809 
       
   810     CleanupStack::PushL(pSelf);
       
   811     pSelf->InitialiseL(aOwner, aFatSize);
       
   812     CleanupStack::Pop();
       
   813     
       
   814     return pSelf;
       
   815     }
       
   816 
       
   817 //-----------------------------------------------------------------------------
       
   818 /**
       
   819     FAT16 fixed cache initialisation.
       
   820     @param  aOwner              pointer to the owning FAT mount
       
   821     @param  aFatSize            size of the FAT table in bytes
       
   822 */
       
   823 void CFat12Cache::InitialiseL(CFatMountCB* aOwner, TUint32 aFatSize)
       
   824     {
       
   825     __PRINT1(_L("#-CFat12Cache::InitialiseL FatSz:%u"),aFatSize);
       
   826 
       
   827     CFatCacheBase::InitialiseL(aOwner);
       
   828     ASSERT(FatType() == EFat12);
       
   829 
       
   830     //-- see FAT specs; 4084 is a max. number of clusters, fat12 entry is 1.5 bytes; but we need to round up FAT12 size to the sector size
       
   831     const TUint32 KMaxFat12Size = ( ((TUint32)(4084*1.5+FAT_SectorSz()-1)) >> FAT_SectorSzLog2()) << FAT_SectorSzLog2();
       
   832     const TUint32 KMinFat12Size = FAT_SectorSz();  //-- 1 FAT sector
       
   833 	__ASSERT_ALWAYS(aFatSize >= KMinFat12Size && aFatSize <= KMaxFat12Size, User::Leave(KErrCorrupt));
       
   834     (void)KMaxFat12Size;
       
   835     (void)KMinFat12Size;
       
   836 
       
   837     //-- as soon as FAT12 max size is 4084 entries or 6126 bytes, the cache is contiguous and divided 
       
   838     //-- to logical sectors (write granularity). 
       
   839 
       
   840     //-- calculate number write cache sector in the cache
       
   841     iSectorsInCache = (aFatSize + (FAT_SectorSz()-1)) >> FAT_SectorSzLog2();
       
   842     __ASSERT_ALWAYS(NumSectors() <= KMaxSectorsInCache, Fault(EFatCache_BadGranularity));
       
   843 
       
   844     //-- round up cache size to write granularity (sector size)
       
   845     const TUint32 cacheSize = NumSectors() << FAT_SectorSzLog2();
       
   846     
       
   847     //-- create buffer for the whole FAT12
       
   848     iData.CreateMaxL(cacheSize);
       
   849 
       
   850     //-- this will read whole FAT into the cache 
       
   851     User::LeaveIfError(Invalidate()); 
       
   852     }
       
   853 
       
   854 //-----------------------------------------------------------------------------
       
   855 /**
       
   856     Close the cache and deallocate its memory.
       
   857     @param  aDiscardDirtyData if ETrue, will ignore dirty data. If EFalse, will panic on atempt to close dirty cache.  
       
   858 */
       
   859 void CFat12Cache::Close(TBool aDiscardDirtyData)
       
   860     {
       
   861     __PRINT1(_L("#-CFat12Cache::Close(%d)"), aDiscardDirtyData);    
       
   862     
       
   863     for(TUint32 i=0; i<NumSectors(); ++i)
       
   864         {
       
   865         if(iDirtySectors[i])
       
   866             {//-- trying to destroy the cache that has dirty sectors
       
   867             __PRINT1(_L("#-CFat12Cache::Close() The cache is dirty! cache sector:%d"), i);
       
   868             if(!aDiscardDirtyData)
       
   869                 {
       
   870                 __ASSERT_ALWAYS(0, Fault(EFatCache_DiscardingDirtyData));
       
   871                 }
       
   872             //-- ignore this fact if requested.
       
   873             }
       
   874         }
       
   875 
       
   876     iData.Close();
       
   877     SetDirty(EFalse);
       
   878     }
       
   879 
       
   880 //-----------------------------------------------------------------------------
       
   881 /**
       
   882     Read FAT entry from the cache. 
       
   883 
       
   884     @param  aIndex FAT entry index to read
       
   885     @return FAT entry value at the index "aIndex" 
       
   886 */
       
   887 TUint32 CFat12Cache::ReadEntryL(TUint32 aIndex)
       
   888     {
       
   889     //__PRINT1(_L("#-CFat12Cache::ReadEntryL() FAT idx:%d"), aIndex);
       
   890     ASSERT(aIndex >= KFatFirstSearchCluster &&  aIndex <  (FatSize() + FatSize()/2)); //-- FAT12 entry is 1.5 bytes long
       
   891 
       
   892     TUint32 entry;
       
   893 
       
   894     if(aIndex & 0x01)
       
   895         {//-- odd index
       
   896         --aIndex;
       
   897         const TUint32 byteIdx = 1 + aIndex + (aIndex >> 1); //-- byteIdx = 1+(aIndex-1)*1.5
       
   898         Mem::Copy(&entry, iData.Ptr()+byteIdx, 2); 
       
   899         entry >>= 4;   
       
   900         }
       
   901     else
       
   902         {//-- even index
       
   903         const TUint32 byteIdx = aIndex + (aIndex >> 1); //-- byteIdx = aIndex*1.5
       
   904         Mem::Copy(&entry, iData.Ptr()+byteIdx, 2);
       
   905         }
       
   906 
       
   907     entry &= KFat12EntryMask; 
       
   908 
       
   909     return entry;
       
   910     }
       
   911 
       
   912 //-----------------------------------------------------------------------------
       
   913 /**
       
   914     Write FAT entry to the cache. 
       
   915     Appropriate FAT cache sector will be marked as "dirty" and will be eventually flushed to the media.
       
   916 
       
   917     @param  aIndex FAT entry index
       
   918     @param  aEntry FAT entry value
       
   919 */
       
   920 void CFat12Cache::WriteEntryL(TUint32 aIndex, TUint32 aEntry)
       
   921     {
       
   922     //__PRINT2(_L("#-CFat12Cache::WriteEntryL() FAT idx:%d, entry:%u"), aIndex, aEntry);
       
   923     ASSERT(aIndex >= KFatFirstSearchCluster &&  aIndex <  (FatSize() + FatSize()/2)); //-- FAT12 entry is 1.5 bytes long
       
   924 
       
   925     aEntry &= KFat12EntryMask; 
       
   926  
       
   927     TUint32 byteIdx = 0;
       
   928     TUint8 tmp;
       
   929 
       
   930     if(aIndex & 0x01)
       
   931         {//-- odd index
       
   932         --aIndex;
       
   933         byteIdx = 1 + aIndex + (aIndex >> 1); //-- byteIdx = 1+(aIndex-1)*1.5
       
   934         tmp = (TUint8)(iData[byteIdx] & 0x0F); //-- we modifying a higher nibble 
       
   935         tmp |= (TUint8) ((aEntry & 0x0F)<<4);
       
   936         iData[byteIdx] = tmp;
       
   937 
       
   938         iData[byteIdx+1] = (TUint8)(aEntry >> 4);  
       
   939         }
       
   940     else
       
   941         {//-- even index
       
   942         byteIdx = aIndex + (aIndex >> 1); //-- byteIdx = aIndex*1.5
       
   943         iData[byteIdx] = (TUint8)aEntry;  
       
   944 
       
   945         const TUint32 nextIdx = byteIdx+1;
       
   946         tmp = (TUint8)(iData[nextIdx] & 0xF0); //-- we modifying a lower nibble 
       
   947         tmp |= (TUint8)((aEntry >> 8) & 0x0F);
       
   948         iData[nextIdx] = tmp;
       
   949 
       
   950         }
       
   951 
       
   952     //-- mark changed sectors dirty. We modified 2 bytes at [byteIdx] and [byteIdx+1]
       
   953     iDirtySectors.SetBit(byteIdx >> FAT_SectorSzLog2());
       
   954     iDirtySectors.SetBit((byteIdx+1) >> FAT_SectorSzLog2());
       
   955 
       
   956     SetDirty(ETrue);
       
   957     }
       
   958 
       
   959 //-----------------------------------------------------------------------------
       
   960 /**
       
   961     A debug method that asserts that the cache is really clean
       
   962 */
       
   963 void CFat12Cache::AssertCacheReallyClean() const
       
   964     {
       
   965 #ifdef _DEBUG 
       
   966     if(iDirtySectors.HasBitsSet())
       
   967         {
       
   968         __PRINT(_L("#-CFat12Cache::AssertCacheReallyClean()"));
       
   969         ASSERT(0);
       
   970         }
       
   971 
       
   972 #endif   
       
   973     }
       
   974 
       
   975 //-----------------------------------------------------------------------------
       
   976 /**
       
   977     Flushes all dirty data to the media.
       
   978     Walks through all sectors in this cache and flushes dirty ones.
       
   979 */
       
   980 void CFat12Cache::FlushL()
       
   981     {
       
   982     if(!IsDirty())
       
   983         {
       
   984         AssertCacheReallyClean();
       
   985         return;
       
   986         }
       
   987 
       
   988     //-- write all dirty sectors to the media (into all copies of FAT)
       
   989     for(iCurrentFatNo=0; iCurrentFatNo < NumFATs(); ++iCurrentFatNo)
       
   990         {
       
   991         for(TUint secNo=0; secNo<NumSectors(); ++secNo)
       
   992             {
       
   993             if(iDirtySectors[secNo])
       
   994                 {//-- this sector is dirty, write it to the media
       
   995 
       
   996                 TInt offset = 0;
       
   997                 if(secNo == 0)
       
   998                     {//-- this is a first sector in FAT. We must skip FAT[0] & FAT[1] entries and do not write them to the media.    
       
   999                     offset = 3; //-- 2 FAT12 entries
       
  1000                     }
       
  1001 
       
  1002                 const TUint32 secPos = secNo << FAT_SectorSzLog2(); //-- relative sector position in FAT
       
  1003                 const TUint8* pData = iData.Ptr()+offset+secPos;    //-- pointer to the data in cache buffer
       
  1004                 const TUint32 len = FAT_SectorSz() - offset;          
       
  1005                 TPtrC8 ptrData(pData, len);                         //-- source data descriptor 
       
  1006                 const TUint32 mediaPos = FatStartPos() + secPos + offset;
       
  1007                 
       
  1008                 TInt nRes = WriteFatData(mediaPos, ptrData);
       
  1009 
       
  1010                 if(nRes != KErrNone)
       
  1011                     {
       
  1012                     __PRINT1(_L("#-CFat12Cache::FlushL() failed! code:%d"), nRes);
       
  1013                     User::Leave(nRes);
       
  1014                     }
       
  1015 
       
  1016                 }//if(iDirtySectors[secNo])
       
  1017             }
       
  1018 
       
  1019         }
       
  1020 
       
  1021     iCurrentFatNo = KInvalidFatNo;
       
  1022 
       
  1023     //-- mark the cache as clean
       
  1024     iDirtySectors.Clear();
       
  1025     SetDirty(EFalse);
       
  1026     
       
  1027     }
       
  1028 
       
  1029 //-----------------------------------------------------------------------------
       
  1030 /**
       
  1031     Invalidates whole cache. Because FAT12 is tiny, just re-reads data from the media to the cache
       
  1032     @return Media read result code.
       
  1033 */
       
  1034 TInt CFat12Cache::Invalidate()
       
  1035     {
       
  1036     __PRINT(_L("#-CFat12Cache::Invalidate()"));
       
  1037     CheckInvalidatingDirtyCache();
       
  1038     
       
  1039     //-- read whole cache from the media
       
  1040     const TUint32 posStart = FatStartPos();
       
  1041     const TUint32 len      = NumSectors() << FAT_SectorSzLog2();
       
  1042      
       
  1043     TInt nRes = ReadFatData(posStart, len, iData);
       
  1044     if(nRes != KErrNone)
       
  1045         return nRes;
       
  1046 
       
  1047     //-- mark the cache as clean
       
  1048     SetDirty(EFalse);
       
  1049     iDirtySectors.Clear();
       
  1050 
       
  1051     return KErrNone;
       
  1052     }
       
  1053 
       
  1054 //-----------------------------------------------------------------------------
       
  1055 /**
       
  1056     Invalidate wholes cache. Because FAT12 is tiny, just re-reads data from the media to the cache
       
  1057     @param  aStartIndex ignored
       
  1058     @param  aNumEntries ignored
       
  1059     @return Media read result code.
       
  1060 */
       
  1061 TInt CFat12Cache::InvalidateRegion(TUint32 aStartIndex, TUint32 aNumEntries)
       
  1062     {
       
  1063     __PRINT2(_L("#-CFat12Cache::InvalidateRegion() startIndex:%d, entries:%d"),aStartIndex, aNumEntries);
       
  1064     ASSERT(aStartIndex >= KFatFirstSearchCluster &&  aStartIndex <  (FatSize() + FatSize()/2)); //-- FAT12 entry is 1.5 bytes long
       
  1065     (void)aStartIndex;
       
  1066     (void)aNumEntries;
       
  1067 
       
  1068     //-- just re-read all FAT12, it is just 6K max and isn't worth calculating invalid sectors
       
  1069     return Invalidate();
       
  1070     }
       
  1071 
       
  1072 
       
  1073 
       
  1074 
       
  1075 
       
  1076 
       
  1077 
       
  1078 
       
  1079 
       
  1080 
       
  1081 
       
  1082 
       
  1083 
       
  1084 
       
  1085 
       
  1086 
       
  1087 
       
  1088 
       
  1089 
       
  1090 
       
  1091 
       
  1092 
       
  1093 
       
  1094 
       
  1095 
       
  1096 
       
  1097 
       
  1098 
       
  1099 
       
  1100 
       
  1101 
       
  1102 
       
  1103 
       
  1104 
       
  1105 
       
  1106 
       
  1107 
       
  1108 
       
  1109 
       
  1110 
       
  1111 
       
  1112 
       
  1113