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