1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/userlibandfileserver/fileserver/sfat/sl_fatcache.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1122 @@
1.4 +// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// f32\sfat32\sl_fatcache.cpp
1.18 +// FAT12 and FAT16 cache implementation
1.19 +//
1.20 +//
1.21 +
1.22 +/**
1.23 + @file
1.24 +*/
1.25 +
1.26 +
1.27 +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1.28 +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1.29 +//!!
1.30 +//!! WARNING!! DO NOT edit this file !! '\sfat' component is obsolete and is not being used. '\sfat32'replaces it
1.31 +//!!
1.32 +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1.33 +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1.34 +
1.35 +#include "sl_std.h"
1.36 +#include "sl_fatcache.h"
1.37 +
1.38 +
1.39 +//#################################################################################################################################
1.40 +// CFatCacheBase implementation
1.41 +// Base class for all types of FAT cache
1.42 +//#################################################################################################################################
1.43 +
1.44 +CFatCacheBase::~CFatCacheBase()
1.45 + {
1.46 + Close(ETrue); //-- deallocate cache's memory discarding any dirty data
1.47 + }
1.48 +
1.49 +CFatCacheBase::CFatCacheBase()
1.50 + {
1.51 + iCurrentFatNo = KInvalidFatNo;
1.52 + SetDirty(EFalse);
1.53 + }
1.54 +
1.55 +
1.56 +/**
1.57 + FAT cache initialisation.
1.58 +
1.59 + @param aOwner pointer to the owning FAT mount
1.60 +*/
1.61 +void CFatCacheBase::InitialiseL(CFatMountCB* aOwner)
1.62 + {
1.63 + ASSERT(aOwner);
1.64 +
1.65 + Close(ETrue); //-- deallocate cache's memory discarding any dirty data
1.66 +
1.67 + //-- populate parameters from the owning mount
1.68 + iFatType = aOwner->FatType();
1.69 + __ASSERT_ALWAYS((iFatType == EFat12 || iFatType == EFat16 || iFatType == EFat32), User::Leave(KErrCorrupt));
1.70 +
1.71 + ipDrive = &aOwner->DriveInterface();
1.72 + iFatStartPos = aOwner->FirstFatSector() << aOwner->SectorSizeLog2();
1.73 + iFatSize = aOwner->FatSizeInBytes();
1.74 + iNumFATs = (TUint16)aOwner->NumberOfFats();
1.75 + iFatSecSzLog2 = (TUint16)aOwner->SectorSizeLog2();
1.76 + iFatClustSzLog2 = (TUint16)aOwner->ClusterSizeLog2();
1.77 +
1.78 + __ASSERT_ALWAYS(iNumFATs >=1, User::Leave(KErrCorrupt));
1.79 +
1.80 + __PRINT3(_L("#-CFatCacheBase::InitialiseL() FatStart:%u, FatSz:%d, drv:%d"),iFatStartPos, iFatSize, aOwner->DriveNumber());
1.81 + }
1.82 +
1.83 +//-----------------------------------------------------------------------------
1.84 +/**
1.85 + This method shall be called to check if we are allowed to invalidate dirty cache, i.e. discard non-flushed data.
1.86 + The behaviour is hardcoded (see KAllowInvalidateDirtyCache constant)
1.87 +
1.88 + @return ETrue if invalidating dirty cache is allowed. Otherwise panics the current thread
1.89 +*/
1.90 +TBool CFatCacheBase::CheckInvalidatingDirtyCache() const
1.91 + {
1.92 +
1.93 + //-- If not EFalse, invalidating dirty cache (pages) is allowed. This shall be OK, because
1.94 + //-- invalidating the cache is required only after direct media writes to the FAT by RawWrite, which can corrupt it anyway.
1.95 + TBool KAllowInvalidateDirtyCache = ETrue;
1.96 +
1.97 + if(!IsDirty())
1.98 + return KAllowInvalidateDirtyCache;
1.99 +
1.100 + __PRINT(_L("#-CFatCacheBase::Invalidating dirty cache !"));
1.101 +
1.102 + if(!KAllowInvalidateDirtyCache)
1.103 + {
1.104 + __ASSERT_ALWAYS(0, Fault(EFatCache_DiscardingDirtyData));
1.105 + }
1.106 +
1.107 + return KAllowInvalidateDirtyCache;
1.108 + }
1.109 +
1.110 +//-----------------------------------------------------------------------------
1.111 +
1.112 +/**
1.113 + Read portion of raw data from 1st FAT copy.
1.114 +
1.115 + @param aPos media position in the _FIRST_ FAT to start reading with
1.116 + @param aLen number of bytes to read
1.117 + @param aData data descriptor
1.118 +
1.119 + @return standard error code.
1.120 +*/
1.121 +TInt CFatCacheBase::ReadFatData(TUint32 aPos, TUint32 aLen, TDes8& aData) const
1.122 + {
1.123 + //__PRINT2(_L("#-CFatCacheNew::ReadFatData() pos:%u, Len:%d"), aPos, aLen);
1.124 +
1.125 + //-- this method can pick up data corresponding to invalid FAT entries, like FAT[0], FAT[1] and
1.126 + //-- the last portion beyond FAT because of read granularity. This isn't a problem, because the data there
1.127 + //-- won't be written on disk.
1.128 + ASSERT(aPos >= FatStartPos());
1.129 +
1.130 + return ipDrive->ReadNonCritical(aPos, aLen, aData);
1.131 + }
1.132 +
1.133 +//-----------------------------------------------------------------------------
1.134 +
1.135 +/**
1.136 + Writes data to the FAT table, which number is set in iCurrentFatNo member variable.
1.137 + @param aPos data media position in the _FIRST_ FAT copy
1.138 + @param aData data descriptor
1.139 + @return standard error code.
1.140 +*/
1.141 +TInt CFatCacheBase::WriteFatData(TUint32 aPos, const TDesC8& aData) const
1.142 + {
1.143 + //__PRINT3(_L("#-CFatCacheBase::WriteFatData() pos:%u, Len:%d, FAT:%d"), aPos, aData.Length(), iCurrentFatNo);
1.144 +
1.145 +#ifdef _DEBUG
1.146 + //-- 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
1.147 + //-- calculate correct data position in FAT
1.148 + TInt reserved_Entries_Offset=0;
1.149 + switch(iFatType)
1.150 + {
1.151 + case EFat32: reserved_Entries_Offset = KFatFirstSearchCluster*sizeof(TFat32Entry); break; //-- FAT32
1.152 + case EFat16: reserved_Entries_Offset = KFatFirstSearchCluster*sizeof(TFat16Entry); break; //-- FAT16
1.153 + case EFat12: reserved_Entries_Offset = 3; break; //-- FAT12
1.154 + default: ASSERT(0); break;
1.155 + }
1.156 + ASSERT(aPos >= FatStartPos()+reserved_Entries_Offset);
1.157 + ASSERT((aPos+aData.Length()) <= FatStartPos()+FatSize());
1.158 + ASSERT(iCurrentFatNo < iNumFATs);
1.159 +#endif
1.160 +
1.161 + //-- goto the required FAT copy. iCurrentFatNo shall contain FAT number we are writing to.
1.162 + aPos+=iCurrentFatNo*FatSize();
1.163 +
1.164 + return ipDrive->WriteCritical(aPos, aData);
1.165 + }
1.166 +
1.167 +//-----------------------------------------------------------------------------
1.168 +/**
1.169 + get a pointer to the CFatBitCache interface.
1.170 + @return NULL because it is not present here
1.171 +*/
1.172 +CFatBitCache* CFatCacheBase::BitCacheInterface()
1.173 + {
1.174 + return NULL;
1.175 + }
1.176 +
1.177 +
1.178 +//#################################################################################################################################
1.179 +// CFatPagedCacheBase implementation
1.180 +// Base class for all paged FAT caches
1.181 +//#################################################################################################################################
1.182 +
1.183 +CFatPagedCacheBase::CFatPagedCacheBase()
1.184 + :CFatCacheBase()
1.185 + {
1.186 + }
1.187 +
1.188 +
1.189 +//#################################################################################################################################
1.190 +// CFatCachePageBase implementation
1.191 +// Base class for FAT cache pages (FAT16 fixed and FAT32 LRU)
1.192 +//#################################################################################################################################
1.193 +
1.194 +CFatCachePageBase::CFatCachePageBase(CFatPagedCacheBase& aCache)
1.195 + :iCache(aCache)
1.196 + {
1.197 + ASSERT(IsPowerOf2(aCache.PageSize()));
1.198 + iStartIndexInFAT = KMaxTUint;
1.199 +
1.200 + //-- calculate number of FAT entries in the page, it depends on FAT type
1.201 + switch(aCache.FatType())
1.202 + {
1.203 + case EFat32:
1.204 + iFatEntriesInPage = PageSize() >> KFat32EntrySzLog2;
1.205 + break;
1.206 +
1.207 + case EFat16:
1.208 + iFatEntriesInPage = PageSize() >> KFat16EntrySzLog2;
1.209 + break;
1.210 +
1.211 + default:
1.212 + ASSERT(0);
1.213 + Fault(EFatCache_BadFatType);
1.214 + break;
1.215 +
1.216 + };
1.217 +
1.218 + SetState(EInvalid);
1.219 + }
1.220 +
1.221 +CFatCachePageBase::~CFatCachePageBase()
1.222 + {
1.223 + iData.Close();
1.224 + }
1.225 +
1.226 +//-----------------------------------------------------------------------------
1.227 +/**
1.228 + Mark the page as "invalid". I.e containing inalid data.
1.229 + On the first read/write access to such page it will be re-read from the media
1.230 +
1.231 + @param aIgnoreDirtyData if ETrue, it is allowed to ignore the fact that the page contains dirty (not flushed) data.
1.232 +*/
1.233 +void CFatCachePageBase::Invalidate(TBool aIgnoreDirtyData /*= EFalse*/)
1.234 + {
1.235 + if(!aIgnoreDirtyData && IsDirty())
1.236 + {
1.237 + __PRINT1(_L("#-CFatCachePageBase::Invalidate() dirty page! FAT idx:%d"), iStartIndexInFAT);
1.238 + __ASSERT_ALWAYS(0, Fault(EFatCache_DiscardingDirtyData));
1.239 + }
1.240 +
1.241 + iDirtySectors.Clear(); //-- clear dirty sectors bitmap
1.242 + SetState(EInvalid);
1.243 + }
1.244 +
1.245 +//-----------------------------------------------------------------------------
1.246 +/**
1.247 + Flush all dirty page sectors to the media and mark the page as "clean" if required.
1.248 + If the page is "clean" i.e doesn't contain changed data, does nothing.
1.249 +
1.250 + @param aKeepDirty if ETrue, the "dirty" flag isn't reset after page flushing.
1.251 +*/
1.252 +void CFatCachePageBase::FlushL(TBool aKeepDirty)
1.253 + {
1.254 + if(!IsDirty())
1.255 + return;
1.256 +
1.257 + if(!IsValid())
1.258 + {
1.259 + __PRINT1(_L("#-CFatCachePageBase::FlushL() Invalid page! FAT idx:%d"), iStartIndexInFAT);
1.260 + ASSERT(0);
1.261 + User::Leave(KErrCorrupt);
1.262 + return;
1.263 + }
1.264 +
1.265 + //__PRINT1(_L("#-CFatCachePageBase::FlushL() FAT idx:%d"), iStartIndexInFAT);
1.266 +
1.267 + //-- write dirty FAT sectors to the media one by one.
1.268 + //-- merging adjacent dirty subsectors into larger clusters and writing them at once looks like a good idea, but
1.269 + //-- in reality it showed FAT performance degradation, at least on MMC/SD media.
1.270 +
1.271 + const TInt MaxSectors = iCache.SectorsInPage();
1.272 +
1.273 + for(TInt i=0; i<MaxSectors; ++i)
1.274 + {
1.275 + if(iDirtySectors[i])
1.276 + {
1.277 + DoWriteSectorL(i);
1.278 + }
1.279 + }
1.280 +
1.281 + //-- All data flushed; mark page as clean if it isn't required not to do.
1.282 + if(!aKeepDirty)
1.283 + SetClean();
1.284 +
1.285 + }
1.286 +
1.287 +
1.288 +//#################################################################################################################################
1.289 +// CFat16FixedCache implementation
1.290 +// Fixed cache (caches all FAT16) but organised as an array of pages
1.291 +//#################################################################################################################################
1.292 +
1.293 +CFat16FixedCache::CFat16FixedCache()
1.294 + :CFatPagedCacheBase(),iPages(1) //-- array granularity is 1
1.295 + {
1.296 + }
1.297 +
1.298 +//-----------------------------------------------------------------------------
1.299 +/**
1.300 + FAT16 fixed cache factory function.
1.301 + @param aOwner pointer to the owning FAT mount
1.302 + @param aFatSize size of the FAT table in bytes
1.303 + @param aRdGranularityLog2 Log2(read granularity)
1.304 + @param aWrGranularityLog2 Log2(write granularity)
1.305 +
1.306 + @return pointer to the constructed object.
1.307 +*/
1.308 +CFat16FixedCache* CFat16FixedCache::NewL(CFatMountCB* aOwner, TUint32 aFatSize, TUint32 aRdGranularityLog2, TUint32 aWrGranularityLog2)
1.309 + {
1.310 + __PRINT(_L("#-CFat16FixedCache::NewL()"));
1.311 +
1.312 + CFat16FixedCache* pSelf = NULL;
1.313 + pSelf = new (ELeave) CFat16FixedCache;
1.314 +
1.315 + CleanupStack::PushL(pSelf);
1.316 + pSelf->InitialiseL(aOwner, aFatSize, aRdGranularityLog2, aWrGranularityLog2);
1.317 + CleanupStack::Pop();
1.318 +
1.319 + return pSelf;
1.320 + }
1.321 +
1.322 +//-----------------------------------------------------------------------------
1.323 +/**
1.324 + FAT16 fixed cache initialisation.
1.325 + @param aOwner pointer to the owning FAT mount
1.326 + @param aFatSize size of the FAT table in bytes
1.327 + @param aRdGranularityLog2 Log2(read granularity)
1.328 + @param aWrGranularityLog2 Log2(write granularity)
1.329 +*/
1.330 +void CFat16FixedCache::InitialiseL(CFatMountCB* aOwner, TUint32 aFatSize, TUint32 aRdGranularityLog2, TUint32 aWrGranularityLog2)
1.331 + {
1.332 + const TUint32 ReadGranularity = Pow2(aRdGranularityLog2);
1.333 + const TUint32 WriteGranularity = Pow2(aWrGranularityLog2);
1.334 +
1.335 + __PRINT3(_L("#-CFat16FixedCache::InitialiseL FatSz:%u, RdGr:%d, WrGr:%d"),aFatSize, ReadGranularity, WriteGranularity);
1.336 + (void)ReadGranularity;
1.337 + (void)WriteGranularity;
1.338 +
1.339 + TBool bParamsValid = (aRdGranularityLog2 >= aWrGranularityLog2) && (aWrGranularityLog2 >= KDefSectorSzLog2);
1.340 + __ASSERT_ALWAYS(bParamsValid, Fault(EFatCache_BadGranularity));
1.341 +
1.342 + CFatPagedCacheBase::InitialiseL(aOwner);
1.343 +
1.344 + ASSERT(FatType() == EFat16);
1.345 +
1.346 + //-- See FAT specs, and round up the limit to the FAT sector boundary
1.347 + const TUint32 KMaxFat16Size = ((65524*sizeof(TFat16Entry)+FAT_SectorSz()-1) >> FAT_SectorSzLog2()) << FAT_SectorSzLog2();
1.348 + const TUint32 KMinFat16Size = 4086*sizeof(TFat16Entry); //-- See FAT specs
1.349 +
1.350 + bParamsValid = aFatSize >= KMinFat16Size && aFatSize <= KMaxFat16Size;
1.351 + __ASSERT_ALWAYS(bParamsValid, User::Leave(KErrCorrupt));
1.352 +
1.353 + //-- cache page size is (2^aRdGranularityLog2) bytes and consists of 2^(aRdGranularityLog2-aWrGranularity) sectors.
1.354 + iPageSizeLog2 = aRdGranularityLog2;
1.355 + iSectorSizeLog2 = aWrGranularityLog2; //-- Log2(number of sectors in cache page)
1.356 +
1.357 + __ASSERT_ALWAYS(SectorsInPage() < KMaxSectorsInPage, Fault(EFatCache_BadGranularity));
1.358 +
1.359 + const TUint numPages = (aFatSize+(PageSize()-1)) >> iPageSizeLog2;
1.360 + __PRINT1(_L("#-CFat16FixedCache Num Pages:%d"), numPages);
1.361 +
1.362 + //-- prepare pointer array for pages. NULL entry in the array means that the page at this index isn't allocated.
1.363 + for(TUint i=0; i<numPages; ++i)
1.364 + iPages.Append(NULL);
1.365 +
1.366 + }
1.367 +
1.368 +
1.369 +//-----------------------------------------------------------------------------
1.370 +/**
1.371 + Close the cache and deallocate its memory.
1.372 + @param aDiscardDirtyData if ETrue, will ignore dirty data. If EFalse, will panic on atempt to close dirty cache.
1.373 +*/
1.374 +void CFat16FixedCache::Close(TBool aDiscardDirtyData)
1.375 + {
1.376 + __PRINT1(_L("#-CFat16FixedCache::Close(%d)"), aDiscardDirtyData);
1.377 +
1.378 + TInt cnt = iPages.Count();
1.379 + while(cnt--)
1.380 + {//-- delete pages
1.381 + CFat16FixedCachePage *pPage = iPages[cnt];
1.382 + if(pPage && (pPage->IsDirty()))
1.383 + {//-- trying to destroy the cache that has dirty pages
1.384 + __PRINT1(_L("#-CFat16FixedCache::Close() The page is dirty! Start idx:%d"), pPage->StartFatIndex());
1.385 + if(!aDiscardDirtyData)
1.386 + {
1.387 + __ASSERT_ALWAYS(0, Fault(EFatCache_DiscardingDirtyData));
1.388 + }
1.389 + //-- ignore this fact if requested.
1.390 + }
1.391 +
1.392 + delete pPage;
1.393 + }
1.394 +
1.395 + iPages.Close();
1.396 + SetDirty(EFalse);
1.397 + }
1.398 +
1.399 +//-----------------------------------------------------------------------------
1.400 +/**
1.401 + Read FAT entry from the cache.
1.402 +
1.403 + @param aIndex FAT entry index to read
1.404 + @return FAT entry value at the index "aIndex"
1.405 +*/
1.406 +TUint32 CFat16FixedCache::ReadEntryL(TUint32 aIndex)
1.407 + {
1.408 + //__PRINT1(_L("#-CFat16FixedCache::ReadEntryL() FAT idx:%d"), aIndex);
1.409 + ASSERT(aIndex >= KFatFirstSearchCluster && aIndex < (FatSize() >> KFat16EntrySzLog2));
1.410 +
1.411 + //-- calculate page index in the array
1.412 + const TInt pgIdx = aIndex >> (PageSizeLog2()-KFat16EntrySzLog2);
1.413 + CFat16FixedCachePage *pPage = iPages[pgIdx];
1.414 +
1.415 + TUint32 entry = KMaxTUint;
1.416 +
1.417 + if(!pPage)
1.418 + {//-- page at this position isn't allocated yet
1.419 + pPage = CFat16FixedCachePage::NewL(*this);
1.420 + iPages[pgIdx] = pPage;
1.421 +
1.422 + //-- read the page from media
1.423 + entry = pPage->ReadFromMediaL(aIndex);
1.424 + }
1.425 + else
1.426 + {//-- get cached entry from the page
1.427 + TBool bRes = pPage->ReadCachedEntryL(aIndex, entry);
1.428 + ASSERT(bRes);
1.429 + (void)bRes;
1.430 + }
1.431 +
1.432 + return entry;
1.433 + }
1.434 +
1.435 +//-----------------------------------------------------------------------------
1.436 +/**
1.437 + Write FAT entry to the cache.
1.438 + Appropriate FAT cache sector will be marked as "dirty" and will be eventually flushed to the media.
1.439 +
1.440 + @param aIndex FAT entry index
1.441 + @param aEntry FAT entry value
1.442 +*/
1.443 +void CFat16FixedCache::WriteEntryL(TUint32 aIndex, TUint32 aEntry)
1.444 + {
1.445 + //__PRINT2(_L("#-CFat16FixedCache::WriteEntryL() FAT idx:%d, val:%d"), aIndex, aEntry);
1.446 +
1.447 + ASSERT(aIndex >= KFatFirstSearchCluster && aIndex < (FatSize() >> KFat16EntrySzLog2));
1.448 +
1.449 + SetDirty(ETrue);
1.450 +
1.451 + //-- calculate page index in the array
1.452 + const TInt pgIdx = aIndex >> (PageSizeLog2()-KFat16EntrySzLog2);
1.453 + CFat16FixedCachePage *pPage = iPages[pgIdx];
1.454 +
1.455 + if(!pPage)
1.456 + {//-- page at this position isn't allocated yet
1.457 + pPage = CFat16FixedCachePage::NewL(*this);
1.458 + iPages[pgIdx] = pPage;
1.459 +
1.460 + //-- read the page from media
1.461 + pPage->ReadFromMediaL(aIndex);
1.462 + }
1.463 +
1.464 + //-- overwrite entry in cache
1.465 + TBool bRes = pPage->WriteCachedEntryL(aIndex, aEntry);
1.466 + ASSERT(bRes);
1.467 + (void)bRes;
1.468 + }
1.469 +
1.470 +/**
1.471 + A debug method that asserts that the cache is really clean
1.472 +*/
1.473 +void CFat16FixedCache::AssertCacheReallyClean() const
1.474 + {
1.475 +#ifdef _DEBUG
1.476 + for(TUint i=0; i<NumPages(); ++i)
1.477 + {
1.478 + CFat16FixedCachePage* pPage = iPages[i];
1.479 + if(pPage && pPage->IsDirty())
1.480 + {
1.481 + __PRINT(_L("#-CFat16FixedCache::AssertCacheReallyClean()"));
1.482 + ASSERT(0);
1.483 + }
1.484 + }
1.485 +#endif
1.486 + }
1.487 +
1.488 +
1.489 +//-----------------------------------------------------------------------------
1.490 +/**
1.491 + Flushes all dirty data to the media.
1.492 +*/
1.493 +void CFat16FixedCache::FlushL()
1.494 + {
1.495 + if(!IsDirty())
1.496 + {
1.497 + AssertCacheReallyClean();
1.498 + return;
1.499 + }
1.500 +
1.501 +
1.502 + //-- flush dirty data to all copies of FAT
1.503 + for(iCurrentFatNo=0; iCurrentFatNo < NumFATs(); ++iCurrentFatNo)
1.504 + {
1.505 + const TInt nPages = NumPages();
1.506 + for(TInt i=0; i<nPages; ++i)
1.507 + {
1.508 + const TBool keepDirty = iCurrentFatNo < (NumFATs() - 1);
1.509 +
1.510 + CFat16FixedCachePage* pPage = iPages[i];
1.511 + if(pPage)
1.512 + pPage->FlushL(keepDirty);
1.513 + }
1.514 +
1.515 + }
1.516 +
1.517 + iCurrentFatNo = KInvalidFatNo;
1.518 + SetDirty(EFalse);
1.519 + }
1.520 +
1.521 +//-----------------------------------------------------------------------------
1.522 +/**
1.523 + Invalidate whole cache. All pages will be marked as invalid and will be re-read from the media on first access to them.
1.524 + @return always KErrNone
1.525 +*/
1.526 +TInt CFat16FixedCache::Invalidate()
1.527 + {
1.528 + __PRINT(_L("#-CFat16FixedCache::Invalidate()"));
1.529 + const TBool bIgnoreDirtyData = CheckInvalidatingDirtyCache();
1.530 +
1.531 + //-- iterate through the array of pages marking invalidating every page
1.532 + TInt cnt = iPages.Count();
1.533 + while(cnt--)
1.534 + {//-- delete pages
1.535 + CFat16FixedCachePage *pPage = iPages[cnt];
1.536 + if(pPage)
1.537 + pPage->Invalidate(bIgnoreDirtyData);
1.538 + }
1.539 +
1.540 +
1.541 + SetDirty(EFalse);
1.542 +
1.543 + return KErrNone;
1.544 + }
1.545 +
1.546 +//-----------------------------------------------------------------------------
1.547 +/**
1.548 + Invalidate FAT cache pages that contain FAT entries from aStartIndex to (aStartIndex+aNumEntries)
1.549 + These pages will be marked as invalid and will be re-read from the media on first access to them.
1.550 +
1.551 + @param aStartIndex FAT start index of the region being invalidated
1.552 + @param aNumEntries number of entries to invalidate
1.553 + @return always KErrNone
1.554 +*/
1.555 +TInt CFat16FixedCache::InvalidateRegion(TUint32 aStartIndex, TUint32 aNumEntries)
1.556 + {
1.557 + __PRINT2(_L("#-CFat16FixedCache::InvalidateRegion() startIndex:%d, entries:%d"),aStartIndex, aNumEntries);
1.558 + ASSERT(aStartIndex >= KFatFirstSearchCluster && aStartIndex < (FatSize() >> KFat16EntrySzLog2));
1.559 +
1.560 + if(!aNumEntries)
1.561 + {
1.562 + ASSERT(0);
1.563 + return KErrNone;
1.564 + }
1.565 +
1.566 + const TBool bIgnoreDirtyData = CheckInvalidatingDirtyCache();
1.567 + const TUint startPgIdx = aStartIndex >> (PageSizeLog2()-KFat16EntrySzLog2);
1.568 + const TUint nPagesToInv = 1+(aNumEntries >> (PageSizeLog2()-KFat16EntrySzLog2));
1.569 +
1.570 + TUint i;
1.571 + //-- invalidate pages that contain [aStartIndex ... aStartIndex+aNumEntries] entries
1.572 + for(i=0; i<nPagesToInv; ++i)
1.573 + {
1.574 + const TUint pageIdx = i+startPgIdx;
1.575 + if(pageIdx >= NumPages())
1.576 + break;
1.577 +
1.578 + CFat16FixedCachePage* pPage = iPages[pageIdx];
1.579 + if(pPage)
1.580 + pPage->Invalidate(bIgnoreDirtyData);
1.581 + }
1.582 +
1.583 + SetDirty(EFalse);
1.584 +
1.585 + //-- check if the cache still has dirty pages
1.586 + for(i=0; i<NumPages(); ++i)
1.587 + {
1.588 + CFat16FixedCachePage* pPage = iPages[i];
1.589 + if(pPage && pPage->IsDirty())
1.590 + {
1.591 + SetDirty(ETrue);
1.592 + break;
1.593 + }
1.594 + }
1.595 +
1.596 + return KErrNone;
1.597 + }
1.598 +
1.599 +//#################################################################################################################################
1.600 +// CFat16FixedCachePage implementation
1.601 +// Page for the FAT16 fixed cache
1.602 +//#################################################################################################################################
1.603 +
1.604 +//-----------------------------------------------------------------------------
1.605 +
1.606 +CFat16FixedCachePage::CFat16FixedCachePage(CFatPagedCacheBase& aCache)
1.607 + :CFatCachePageBase(aCache)
1.608 + {
1.609 + ASSERT(IsPowerOf2(EntriesInPage()));
1.610 + }
1.611 +
1.612 +
1.613 +/**
1.614 + Factory function.
1.615 + @param aCache reference to the owning cache.
1.616 + @return pointer to the constructed object or NULL on error
1.617 +*/
1.618 +CFat16FixedCachePage* CFat16FixedCachePage::NewL(CFatPagedCacheBase& aCache)
1.619 + {
1.620 + CFat16FixedCachePage* pSelf = NULL;
1.621 + pSelf = new (ELeave) CFat16FixedCachePage(aCache);
1.622 +
1.623 + CleanupStack::PushL(pSelf);
1.624 +
1.625 + pSelf->iData.CreateMaxL(aCache.PageSize()); //-- allocate memory for the page
1.626 +
1.627 + CleanupStack::Pop();
1.628 +
1.629 + return pSelf;
1.630 + }
1.631 +
1.632 +
1.633 +//-----------------------------------------------------------------------------
1.634 +/**
1.635 + Read FAT16 entry from the cache.
1.636 +
1.637 + 1. If page's data are valid, just extracts data from the page buffer.
1.638 + 2. If page's data are invalid firstly reads data from the media and goto 1
1.639 +
1.640 + @param aFatIndex entry's absolute FAT index (from the FAT start)
1.641 + @param aResult on sucess there will be FAT16 entry value
1.642 + @return ETrue, because FAT16 cache pages never get eviched.
1.643 +*/
1.644 +TBool CFat16FixedCachePage::ReadCachedEntryL (TUint32 aFatIndex, TUint32& aResult)
1.645 + {
1.646 + if(IsValid())
1.647 + {//-- read entry directly from page buffer, the cached data are valid
1.648 + aResult = (*GetEntryPtr(aFatIndex)) & KFat16EntryMask;
1.649 + }
1.650 + else
1.651 + {//-- aFatIndex belongs to this page, but the page is invalid and needs to be read from the media
1.652 + //__PRINT(_L("#-CFat16FixedCachePage::ReadCachedEntry() The page is invalid, reading from the media"));
1.653 + aResult = ReadFromMediaL(aFatIndex);
1.654 + }
1.655 +
1.656 + return ETrue;
1.657 + }
1.658 +
1.659 +//-----------------------------------------------------------------------------
1.660 +
1.661 +/**
1.662 + Writes FAT cache page sector to the media (to all copies of the FAT)
1.663 + @param aSector sector number winthin this page
1.664 +*/
1.665 +void CFat16FixedCachePage::DoWriteSectorL(TUint32 aSector)
1.666 + {
1.667 + //__PRINT1(_L("#-CFat16FixedCachePage::DoWriteSectorL() startSec:%d, cnt:%d"), aSector);
1.668 +
1.669 + ASSERT(aSector < iCache.SectorsInPage());
1.670 +
1.671 + TInt offset = 0;
1.672 +
1.673 + if(iStartIndexInFAT == 0 && aSector == 0)
1.674 + {//-- this is the very beginning of FAT16. We must skip FAT[0] & FAT[1] entries and do not write them to media.
1.675 + offset = KFatFirstSearchCluster << KFat16EntrySzLog2;
1.676 + }
1.677 +
1.678 + const TUint8* pData = iData.Ptr()+offset+(aSector << iCache.SectorSizeLog2());
1.679 +
1.680 + TUint32 dataLen = (1 << iCache.SectorSizeLog2()) - offset;
1.681 +
1.682 + const TUint32 mediaPosStart = iCache.FatStartPos() + (iStartIndexInFAT << KFat16EntrySzLog2) + (aSector << iCache.SectorSizeLog2()) + offset;
1.683 + const TUint32 mediaPosEnd = mediaPosStart + dataLen;
1.684 +
1.685 + //-- check if we are going to write beyond FAT. It can happen if the write granularity is bigger that the sector size.
1.686 + const TUint32 posFatEnd = iCache.FatStartPos() + iCache.FatSize();
1.687 + if(mediaPosEnd > posFatEnd)
1.688 + {//-- correct the leength of the data to write.
1.689 + dataLen -= (mediaPosEnd-posFatEnd);
1.690 + }
1.691 +
1.692 + TPtrC8 ptrData(pData, dataLen); //-- source data descriptor
1.693 +
1.694 + TInt nRes = iCache.WriteFatData(mediaPosStart, ptrData);
1.695 +
1.696 + if(nRes != KErrNone)
1.697 + {
1.698 + __PRINT1(_L("#-CFat16FixedCachePage::DoWriteSectorsL() failed! code:%d"), nRes);
1.699 + User::Leave(nRes);
1.700 + }
1.701 +
1.702 + }
1.703 +
1.704 +//-----------------------------------------------------------------------------
1.705 +/**
1.706 + Write FAT16 entry at aFatIndex to the cache. Note that the data are not written to the media, only to the cache page.
1.707 + Corresponding page sector is marked as dirty and will be flushed on FlushL() call later.
1.708 +
1.709 + 1. If page's data are valid, copies data to the page buffer and marks sector as dirty.
1.710 + 2. If page's data are invalid, firstly reads data from the media and goto 1
1.711 +
1.712 + @param aFatIndex entry's absolute FAT index (from the FAT start)
1.713 + @param aFatEntry FAT16 entry value
1.714 + @return ETrue because FAT16 cache pages never get eviched.
1.715 +*/
1.716 +TBool CFat16FixedCachePage::WriteCachedEntryL(TUint32 aFatIndex, TUint32 aFatEntry)
1.717 + {
1.718 +
1.719 + ASSERT(IsEntryCached(aFatIndex));
1.720 +
1.721 + if(!IsValid())
1.722 + {//-- we are trying to write data to the page that has invalid data. //-- read the data from the media first.
1.723 + ReadFromMediaL(aFatIndex);
1.724 + }
1.725 +
1.726 + TFat16Entry* pEntry = GetEntryPtr(aFatIndex);
1.727 +
1.728 + const TFat16Entry orgEntry = *pEntry;
1.729 + *pEntry = (TFat16Entry)((orgEntry & ~KFat16EntryMask) | (aFatEntry & KFat16EntryMask));
1.730 +
1.731 + //-- mark corresponding sector of the cache page as dirty
1.732 + const TUint entryIndexInPage = aFatIndex & (EntriesInPage()-1); //-- number of entries in page is always a power of 2
1.733 + const TUint dirtySectorNum = entryIndexInPage >> (iCache.SectorSizeLog2() - KFat16EntrySzLog2);
1.734 +
1.735 + ASSERT(dirtySectorNum < iCache.SectorsInPage());
1.736 +
1.737 + iDirtySectors.SetBit(dirtySectorNum);
1.738 + SetState(EDirty); //-- mark page as dirty.
1.739 +
1.740 + return ETrue;
1.741 + }
1.742 +
1.743 +//-----------------------------------------------------------------------------
1.744 +
1.745 +/**
1.746 + Get a pointer to the FAT16 entry in the page buffer.
1.747 + The page 's data shall be valid and the entry shall belong to this page.
1.748 +
1.749 + @param aFatIndex absolute FAT index (from the FAT start) of the entry
1.750 + @return pointer to the FAT16 entry in the page buffer.
1.751 +*/
1.752 +TFat16Entry* CFat16FixedCachePage::GetEntryPtr(TUint32 aFatIndex) const
1.753 + {
1.754 + ASSERT(IsValid() && IsEntryCached(aFatIndex));
1.755 +
1.756 + const TUint KEntryIndexInPage = aFatIndex & (EntriesInPage()-1); //-- number of entries in page is always a power of 2
1.757 + TFat16Entry* pEntry = ((TFat16Entry*)iData.Ptr()) + KEntryIndexInPage;
1.758 +
1.759 + return pEntry;
1.760 + }
1.761 +
1.762 +//-----------------------------------------------------------------------------
1.763 +/**
1.764 + Read the FAT16 cache page from the media and returns required FAT16 entry.
1.765 +
1.766 + @param aFatIndex entry's absolute FAT index (from the FAT start)
1.767 + @return entry value at aFatIndex.
1.768 +*/
1.769 +TUint32 CFat16FixedCachePage::ReadFromMediaL(TUint32 aFatIndex)
1.770 + {
1.771 + //__PRINT1(_L("#-CFat16FixedCachePage::ReadFromMediaL() FAT idx:%d"), aFatIndex);
1.772 + const TUint KFat16EntriesInPageLog2 = iCache.PageSizeLog2()-KFat16EntrySzLog2; //-- number of FAT16 entries in page is always a power of 2
1.773 +
1.774 + //-- find out index in FAT this page starts from
1.775 + iStartIndexInFAT = (aFatIndex >> KFat16EntriesInPageLog2) << KFat16EntriesInPageLog2;
1.776 + SetState(EInvalid); //-- mark the page as invalid just in case if the read fails.
1.777 +
1.778 + //-- read page from the media
1.779 + const TUint32 pageStartPos = iCache.FatStartPos() + (iStartIndexInFAT << KFat16EntrySzLog2);
1.780 +
1.781 + TInt nRes = iCache.ReadFatData(pageStartPos, iCache.PageSize(), iData);
1.782 + if(nRes != KErrNone)
1.783 + {
1.784 + __PRINT1(_L("#-CFat16FixedCachePage::ReadFromMediaL() failed! code:%d"), nRes);
1.785 + User::Leave(nRes);
1.786 + }
1.787 +
1.788 + SetClean(); //-- mark this page as clean
1.789 +
1.790 + const TFat16Entry entry = (TFat16Entry)((*GetEntryPtr(aFatIndex)) & KFat16EntryMask);
1.791 +
1.792 + return entry;
1.793 + }
1.794 +
1.795 +
1.796 +//-----------------------------------------------------------------------------
1.797 +
1.798 +//#################################################################################################################################
1.799 +// CFat12Cache implementation
1.800 +// FAT12 non-paged fixed cache. This cache consists from only 1 page, logically divided up to 32 sectors (write granularity unit)
1.801 +//#################################################################################################################################
1.802 +
1.803 +CFat12Cache::CFat12Cache()
1.804 + :CFatCacheBase()
1.805 + {
1.806 + }
1.807 +
1.808 +//-----------------------------------------------------------------------------
1.809 +/**
1.810 + FAT12 fixed cache factory function.
1.811 + @param aOwner pointer to the owning FAT mount
1.812 + @param aFatSize size of the FAT table in bytes
1.813 +
1.814 + @return pointer to the constructed object.
1.815 +*/
1.816 +CFat12Cache* CFat12Cache::NewL(CFatMountCB* aOwner, TUint32 aFatSize)
1.817 + {
1.818 + __PRINT(_L("#-CFat12Cache::NewL()"));
1.819 + CFat12Cache* pSelf = NULL;
1.820 + pSelf = new (ELeave) CFat12Cache;
1.821 +
1.822 + CleanupStack::PushL(pSelf);
1.823 + pSelf->InitialiseL(aOwner, aFatSize);
1.824 + CleanupStack::Pop();
1.825 +
1.826 + return pSelf;
1.827 + }
1.828 +
1.829 +//-----------------------------------------------------------------------------
1.830 +/**
1.831 + FAT16 fixed cache initialisation.
1.832 + @param aOwner pointer to the owning FAT mount
1.833 + @param aFatSize size of the FAT table in bytes
1.834 +*/
1.835 +void CFat12Cache::InitialiseL(CFatMountCB* aOwner, TUint32 aFatSize)
1.836 + {
1.837 + __PRINT1(_L("#-CFat12Cache::InitialiseL FatSz:%u"),aFatSize);
1.838 +
1.839 + CFatCacheBase::InitialiseL(aOwner);
1.840 + ASSERT(FatType() == EFat12);
1.841 +
1.842 + //-- 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
1.843 + const TUint32 KMaxFat12Size = ( ((TUint32)(4084*1.5+FAT_SectorSz()-1)) >> FAT_SectorSzLog2()) << FAT_SectorSzLog2();
1.844 + const TUint32 KMinFat12Size = FAT_SectorSz(); //-- 1 FAT sector
1.845 + __ASSERT_ALWAYS(aFatSize >= KMinFat12Size && aFatSize <= KMaxFat12Size, User::Leave(KErrCorrupt));
1.846 + (void)KMaxFat12Size;
1.847 + (void)KMinFat12Size;
1.848 +
1.849 + //-- as soon as FAT12 max size is 4084 entries or 6126 bytes, the cache is contiguous and divided
1.850 + //-- to logical sectors (write granularity).
1.851 +
1.852 + //-- calculate number write cache sector in the cache
1.853 + iSectorsInCache = (aFatSize + (FAT_SectorSz()-1)) >> FAT_SectorSzLog2();
1.854 + __ASSERT_ALWAYS(NumSectors() <= KMaxSectorsInCache, Fault(EFatCache_BadGranularity));
1.855 +
1.856 + //-- round up cache size to write granularity (sector size)
1.857 + const TUint32 cacheSize = NumSectors() << FAT_SectorSzLog2();
1.858 +
1.859 + //-- create buffer for the whole FAT12
1.860 + iData.CreateMaxL(cacheSize);
1.861 +
1.862 + //-- this will read whole FAT into the cache
1.863 + User::LeaveIfError(Invalidate());
1.864 + }
1.865 +
1.866 +//-----------------------------------------------------------------------------
1.867 +/**
1.868 + Close the cache and deallocate its memory.
1.869 + @param aDiscardDirtyData if ETrue, will ignore dirty data. If EFalse, will panic on atempt to close dirty cache.
1.870 +*/
1.871 +void CFat12Cache::Close(TBool aDiscardDirtyData)
1.872 + {
1.873 + __PRINT1(_L("#-CFat12Cache::Close(%d)"), aDiscardDirtyData);
1.874 +
1.875 + for(TUint32 i=0; i<NumSectors(); ++i)
1.876 + {
1.877 + if(iDirtySectors[i])
1.878 + {//-- trying to destroy the cache that has dirty sectors
1.879 + __PRINT1(_L("#-CFat12Cache::Close() The cache is dirty! cache sector:%d"), i);
1.880 + if(!aDiscardDirtyData)
1.881 + {
1.882 + __ASSERT_ALWAYS(0, Fault(EFatCache_DiscardingDirtyData));
1.883 + }
1.884 + //-- ignore this fact if requested.
1.885 + }
1.886 + }
1.887 +
1.888 + iData.Close();
1.889 + SetDirty(EFalse);
1.890 + }
1.891 +
1.892 +//-----------------------------------------------------------------------------
1.893 +/**
1.894 + Read FAT entry from the cache.
1.895 +
1.896 + @param aIndex FAT entry index to read
1.897 + @return FAT entry value at the index "aIndex"
1.898 +*/
1.899 +TUint32 CFat12Cache::ReadEntryL(TUint32 aIndex)
1.900 + {
1.901 + //__PRINT1(_L("#-CFat12Cache::ReadEntryL() FAT idx:%d"), aIndex);
1.902 + ASSERT(aIndex >= KFatFirstSearchCluster && aIndex < (FatSize() + FatSize()/2)); //-- FAT12 entry is 1.5 bytes long
1.903 +
1.904 + TUint32 entry;
1.905 +
1.906 + if(aIndex & 0x01)
1.907 + {//-- odd index
1.908 + --aIndex;
1.909 + const TUint32 byteIdx = 1 + aIndex + (aIndex >> 1); //-- byteIdx = 1+(aIndex-1)*1.5
1.910 + Mem::Copy(&entry, iData.Ptr()+byteIdx, 2);
1.911 + entry >>= 4;
1.912 + }
1.913 + else
1.914 + {//-- even index
1.915 + const TUint32 byteIdx = aIndex + (aIndex >> 1); //-- byteIdx = aIndex*1.5
1.916 + Mem::Copy(&entry, iData.Ptr()+byteIdx, 2);
1.917 + }
1.918 +
1.919 + entry &= KFat12EntryMask;
1.920 +
1.921 + return entry;
1.922 + }
1.923 +
1.924 +//-----------------------------------------------------------------------------
1.925 +/**
1.926 + Write FAT entry to the cache.
1.927 + Appropriate FAT cache sector will be marked as "dirty" and will be eventually flushed to the media.
1.928 +
1.929 + @param aIndex FAT entry index
1.930 + @param aEntry FAT entry value
1.931 +*/
1.932 +void CFat12Cache::WriteEntryL(TUint32 aIndex, TUint32 aEntry)
1.933 + {
1.934 + //__PRINT2(_L("#-CFat12Cache::WriteEntryL() FAT idx:%d, entry:%u"), aIndex, aEntry);
1.935 + ASSERT(aIndex >= KFatFirstSearchCluster && aIndex < (FatSize() + FatSize()/2)); //-- FAT12 entry is 1.5 bytes long
1.936 +
1.937 + aEntry &= KFat12EntryMask;
1.938 +
1.939 + TUint32 byteIdx = 0;
1.940 + TUint8 tmp;
1.941 +
1.942 + if(aIndex & 0x01)
1.943 + {//-- odd index
1.944 + --aIndex;
1.945 + byteIdx = 1 + aIndex + (aIndex >> 1); //-- byteIdx = 1+(aIndex-1)*1.5
1.946 + tmp = (TUint8)(iData[byteIdx] & 0x0F); //-- we modifying a higher nibble
1.947 + tmp |= (TUint8) ((aEntry & 0x0F)<<4);
1.948 + iData[byteIdx] = tmp;
1.949 +
1.950 + iData[byteIdx+1] = (TUint8)(aEntry >> 4);
1.951 + }
1.952 + else
1.953 + {//-- even index
1.954 + byteIdx = aIndex + (aIndex >> 1); //-- byteIdx = aIndex*1.5
1.955 + iData[byteIdx] = (TUint8)aEntry;
1.956 +
1.957 + const TUint32 nextIdx = byteIdx+1;
1.958 + tmp = (TUint8)(iData[nextIdx] & 0xF0); //-- we modifying a lower nibble
1.959 + tmp |= (TUint8)((aEntry >> 8) & 0x0F);
1.960 + iData[nextIdx] = tmp;
1.961 +
1.962 + }
1.963 +
1.964 + //-- mark changed sectors dirty. We modified 2 bytes at [byteIdx] and [byteIdx+1]
1.965 + iDirtySectors.SetBit(byteIdx >> FAT_SectorSzLog2());
1.966 + iDirtySectors.SetBit((byteIdx+1) >> FAT_SectorSzLog2());
1.967 +
1.968 + SetDirty(ETrue);
1.969 + }
1.970 +
1.971 +//-----------------------------------------------------------------------------
1.972 +/**
1.973 + A debug method that asserts that the cache is really clean
1.974 +*/
1.975 +void CFat12Cache::AssertCacheReallyClean() const
1.976 + {
1.977 +#ifdef _DEBUG
1.978 + if(iDirtySectors.HasBitsSet())
1.979 + {
1.980 + __PRINT(_L("#-CFat12Cache::AssertCacheReallyClean()"));
1.981 + ASSERT(0);
1.982 + }
1.983 +
1.984 +#endif
1.985 + }
1.986 +
1.987 +//-----------------------------------------------------------------------------
1.988 +/**
1.989 + Flushes all dirty data to the media.
1.990 + Walks through all sectors in this cache and flushes dirty ones.
1.991 +*/
1.992 +void CFat12Cache::FlushL()
1.993 + {
1.994 + if(!IsDirty())
1.995 + {
1.996 + AssertCacheReallyClean();
1.997 + return;
1.998 + }
1.999 +
1.1000 + //-- write all dirty sectors to the media (into all copies of FAT)
1.1001 + for(iCurrentFatNo=0; iCurrentFatNo < NumFATs(); ++iCurrentFatNo)
1.1002 + {
1.1003 + for(TUint secNo=0; secNo<NumSectors(); ++secNo)
1.1004 + {
1.1005 + if(iDirtySectors[secNo])
1.1006 + {//-- this sector is dirty, write it to the media
1.1007 +
1.1008 + TInt offset = 0;
1.1009 + if(secNo == 0)
1.1010 + {//-- this is a first sector in FAT. We must skip FAT[0] & FAT[1] entries and do not write them to the media.
1.1011 + offset = 3; //-- 2 FAT12 entries
1.1012 + }
1.1013 +
1.1014 + const TUint32 secPos = secNo << FAT_SectorSzLog2(); //-- relative sector position in FAT
1.1015 + const TUint8* pData = iData.Ptr()+offset+secPos; //-- pointer to the data in cache buffer
1.1016 + const TUint32 len = FAT_SectorSz() - offset;
1.1017 + TPtrC8 ptrData(pData, len); //-- source data descriptor
1.1018 + const TUint32 mediaPos = FatStartPos() + secPos + offset;
1.1019 +
1.1020 + TInt nRes = WriteFatData(mediaPos, ptrData);
1.1021 +
1.1022 + if(nRes != KErrNone)
1.1023 + {
1.1024 + __PRINT1(_L("#-CFat12Cache::FlushL() failed! code:%d"), nRes);
1.1025 + User::Leave(nRes);
1.1026 + }
1.1027 +
1.1028 + }//if(iDirtySectors[secNo])
1.1029 + }
1.1030 +
1.1031 + }
1.1032 +
1.1033 + iCurrentFatNo = KInvalidFatNo;
1.1034 +
1.1035 + //-- mark the cache as clean
1.1036 + iDirtySectors.Clear();
1.1037 + SetDirty(EFalse);
1.1038 +
1.1039 + }
1.1040 +
1.1041 +//-----------------------------------------------------------------------------
1.1042 +/**
1.1043 + Invalidates whole cache. Because FAT12 is tiny, just re-reads data from the media to the cache
1.1044 + @return Media read result code.
1.1045 +*/
1.1046 +TInt CFat12Cache::Invalidate()
1.1047 + {
1.1048 + __PRINT(_L("#-CFat12Cache::Invalidate()"));
1.1049 + CheckInvalidatingDirtyCache();
1.1050 +
1.1051 + //-- read whole cache from the media
1.1052 + const TUint32 posStart = FatStartPos();
1.1053 + const TUint32 len = NumSectors() << FAT_SectorSzLog2();
1.1054 +
1.1055 + TInt nRes = ReadFatData(posStart, len, iData);
1.1056 + if(nRes != KErrNone)
1.1057 + return nRes;
1.1058 +
1.1059 + //-- mark the cache as clean
1.1060 + SetDirty(EFalse);
1.1061 + iDirtySectors.Clear();
1.1062 +
1.1063 + return KErrNone;
1.1064 + }
1.1065 +
1.1066 +//-----------------------------------------------------------------------------
1.1067 +/**
1.1068 + Invalidate wholes cache. Because FAT12 is tiny, just re-reads data from the media to the cache
1.1069 + @param aStartIndex ignored
1.1070 + @param aNumEntries ignored
1.1071 + @return Media read result code.
1.1072 +*/
1.1073 +TInt CFat12Cache::InvalidateRegion(TUint32 aStartIndex, TUint32 aNumEntries)
1.1074 + {
1.1075 + __PRINT2(_L("#-CFat12Cache::InvalidateRegion() startIndex:%d, entries:%d"),aStartIndex, aNumEntries);
1.1076 + ASSERT(aStartIndex >= KFatFirstSearchCluster && aStartIndex < (FatSize() + FatSize()/2)); //-- FAT12 entry is 1.5 bytes long
1.1077 + (void)aStartIndex;
1.1078 + (void)aNumEntries;
1.1079 +
1.1080 + //-- just re-read all FAT12, it is just 6K max and isn't worth calculating invalid sectors
1.1081 + return Invalidate();
1.1082 + }
1.1083 +
1.1084 +
1.1085 +
1.1086 +
1.1087 +
1.1088 +
1.1089 +
1.1090 +
1.1091 +
1.1092 +
1.1093 +
1.1094 +
1.1095 +
1.1096 +
1.1097 +
1.1098 +
1.1099 +
1.1100 +
1.1101 +
1.1102 +
1.1103 +
1.1104 +
1.1105 +
1.1106 +
1.1107 +
1.1108 +
1.1109 +
1.1110 +
1.1111 +
1.1112 +
1.1113 +
1.1114 +
1.1115 +
1.1116 +
1.1117 +
1.1118 +
1.1119 +
1.1120 +
1.1121 +
1.1122 +
1.1123 +
1.1124 +
1.1125 +