userlibandfileserver/fileserver/sfat32/sl_disk.cpp
changeset 2 4122176ea935
child 6 0173bcd7697c
equal deleted inserted replaced
0:a41df078684a 2:4122176ea935
       
     1 // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // f32\sfat\sl_disk.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "sl_disk.h"
       
    19 #include "sl_cache.h"
       
    20 #include "sl_dir_cache.h"
       
    21 
       
    22 /**
       
    23 @file
       
    24 */
       
    25 
       
    26 
       
    27 //################################################################################################################################
       
    28 //#     CRawDisk implementation
       
    29 //################################################################################################################################
       
    30 
       
    31 
       
    32 /**
       
    33     Factory function. Constructs objects of the classes derived from CRawDisk.
       
    34     
       
    35     @param  aOwner      reference to the onwning FAT Mount class
       
    36     @param  aLocDrvCaps local drive capabilities from the media driver
       
    37     @return pointer to the constructed object. May be NULL on error.
       
    38 */
       
    39 CRawDisk* CRawDisk::NewL(CFatMountCB& aOwner, const TLocalDriveCaps& aLocDrvCaps)
       
    40 {
       
    41     __PRINT1(_L("CRawDisk::NewL() drv:%d"), aOwner.DriveNumber());
       
    42 
       
    43     if(aLocDrvCaps.iMediaAtt & KMediaAttVariableSize)
       
    44     {//-- this is the RAM drive "attribute"
       
    45         ASSERT((aLocDrvCaps.iDriveAtt & (KDriveAttInternal|KDriveAttLocal)) && aLocDrvCaps.iType == EMediaRam);
       
    46         if(!aLocDrvCaps.iBaseAddress)
       
    47         {
       
    48             ASSERT(0);
       
    49             return NULL;
       
    50         }
       
    51 
       
    52         return CRamDisk::NewL(aOwner);
       
    53     }
       
    54 
       
    55     //-- create CAtaDisk by default
       
    56     return CAtaDisk::NewL(aOwner);
       
    57 }
       
    58 
       
    59 
       
    60 CRawDisk::CRawDisk(CFatMountCB& aOwner)
       
    61     {
       
    62     iFatMount = &aOwner;
       
    63     }
       
    64 
       
    65 /**
       
    66     Default implementation. Initialises and re-initialises the object.
       
    67 */
       
    68 void CRawDisk::InitializeL()
       
    69     {
       
    70     ASSERT(iFatMount);
       
    71     }
       
    72 
       
    73 
       
    74 TInt CRawDisk::GetLastErrorInfo(TDes8& /*aErrorInfo*/) const
       
    75 	{
       
    76 	return KErrNotSupported;
       
    77 	}
       
    78 
       
    79 //################################################################################################################################
       
    80 //##    CAtaDisk class implementation
       
    81 //################################################################################################################################
       
    82 
       
    83 CAtaDisk::CAtaDisk(CFatMountCB& aFatMount)
       
    84          :CRawDisk(aFatMount), iDrive(aFatMount.DriveInterface())
       
    85 	{
       
    86 	}
       
    87 
       
    88 CAtaDisk::~CAtaDisk()
       
    89     {
       
    90     delete ipDirCache;
       
    91     delete iUidCache;
       
    92     
       
    93     }
       
    94 
       
    95 
       
    96 //-------------------------------------------------------------------------------------
       
    97 
       
    98 /**
       
    99     CAtaDisk factory method.
       
   100     
       
   101     @param  aFatMount reference to the owner.
       
   102     @return pointer to the constructed object.
       
   103 */
       
   104 CAtaDisk* CAtaDisk::NewL(CFatMountCB& aFatMount)
       
   105 	{
       
   106 	__PRINT1(_L("CAtaDisk::NewL() drv:%d"), aFatMount.DriveNumber());
       
   107 
       
   108     CAtaDisk* pSelf = new (ELeave) CAtaDisk(aFatMount);
       
   109     
       
   110     CleanupStack::PushL(pSelf);
       
   111     
       
   112     pSelf->ConstructL();
       
   113     pSelf->InitializeL();
       
   114     
       
   115     CleanupStack::Pop();
       
   116 
       
   117 	return pSelf;
       
   118 	}
       
   119 
       
   120 //-------------------------------------------------------------------------------------
       
   121 
       
   122 /** 2nd stage constructor */
       
   123 void CAtaDisk::ConstructL()
       
   124     {
       
   125     //===========================  create data WT cache that is primarily used for caching exacutable modules' UIDs
       
   126     const TUint32 KUidCachePageSzLog2 = 9; //-- 512 bytes in page 
       
   127     const TUint32 KUidCachePages = 64;     //-- 64 pages; total cache size is 32K 
       
   128 
       
   129     iUidCache = CMediaWTCache::NewL(iDrive, KUidCachePages, KUidCachePageSzLog2);
       
   130 
       
   131 
       
   132     //=========================== create directory cache
       
   133     
       
   134     //-- Get dir. cache parameters from config. They may be set in estart.txt for a specified drive.
       
   135     const TUint32 KDirCacheSize = iFatMount->FatConfig().DirCacheSize(); //- Total directory cache size, bytes.
       
   136     const TUint32 KMaxDirCachePageSzLog2 = iFatMount->FatConfig().DirCacheMaxPageSizeLog2(); //- Log2 of the Max. dir. cache page.
       
   137 
       
   138     __PRINT2(_L("CAtaDisk::ConstructL() Dir Cache config:%d,%d"),KDirCacheSize,KMaxDirCachePageSzLog2);
       
   139 
       
   140     ASSERT(KDirCacheSize >= K1KiloByte && KDirCacheSize <= K1MegaByte);
       
   141     ASSERT((KMaxDirCachePageSzLog2 >= KDefSectorSzLog2) && (Pow2(KMaxDirCachePageSzLog2) <= KDirCacheSize));
       
   142 
       
   143     //-- calculate the size and number of pages for the dir. cache. 
       
   144     //-- if the mount's cluster size is less than max. page size from config, the page size will be cluster size.
       
   145     //-- otherwise it will be the value from config. I.e  the minimal page size is cluster size; the maximal page size is taken from config.
       
   146     //-- The number of pages depends on total cache size and page size.
       
   147     const TUint clustSizeLog2 = iFatMount->ClusterSizeLog2(); //-- current FAT cluster size Log2
       
   148     const TUint32 pageSzLog2 = (clustSizeLog2 <= KMaxDirCachePageSzLog2) ? clustSizeLog2 : KMaxDirCachePageSzLog2;
       
   149     const TUint32 numPages = KDirCacheSize / (Pow2(pageSzLog2));
       
   150 
       
   151     ASSERT(!ipDirCache);
       
   152 
       
   153 #ifdef USE_DP_DIR_CACHE
       
   154 
       
   155     //=========================== create Demand Paging type of the directory cache
       
   156 
       
   157     // initialize cache memory manager as all file systems have mounted by now
       
   158 	if(CCacheMemoryManagerFactory::CacheMemoryManager())
       
   159 		{
       
   160 		// Note: the configuration data of min and max cache size are aligned with the memory size it
       
   161 		//	occupies in kernel as we are using demand paging subsystem for dynamic cache size support. 
       
   162 		//  Therefore, they are refered as 'Mem Size' in following calculation.
       
   163 		//  However, 'Data Size' refers to the logical size of a page, i.e. the actual data size each page
       
   164 		//  contains.
       
   165 		// The constraints we have to consider when setting up the dynamic cache:
       
   166 		// 	1. each page's data size is aligned with cluster size, unless cluster size is bigger than
       
   167 		//  	the default maximum page size allowed (typically 32 KB).
       
   168 		// 	2. if page's data size is smaller than segment size (typically 4 KB), i.e. the unit size of 
       
   169 		//     	demand paging subsystem's page management, we will still use up the whole segment for
       
   170 		// 		that page.
       
   171 		//  3. the default min and max cache's memory size is pre-defined in  fat_config.cpp file.
       
   172 		// 		(see KDef_DynamicDirCacheMin & KDef_DynamicDirCacheMax).
       
   173 
       
   174 		// calculate page data size (logical view of page size)
       
   175 	    const TUint32 DefMaxCachePageLog2 = iFatMount->FatConfig().DynamicDirCacheMaxPageSizeLog2();
       
   176 	    const TUint32 PageDataSizeLog2 = clustSizeLog2 < DefMaxCachePageLog2 ? clustSizeLog2 : DefMaxCachePageLog2;
       
   177 	    
       
   178 		// calculate page number, based on memory size we have reserved
       
   179 	    const TUint32 SegmentSizeLog2 = CCacheMemoryManagerFactory::CacheMemoryManager()->SegmentSizeInBytesLog2();
       
   180 	    const TUint32 PageMemSizeLog2 = PageDataSizeLog2 < SegmentSizeLog2 ? SegmentSizeLog2 : PageDataSizeLog2;
       
   181 	    TUint32 CacheSizeMinInPages = iFatMount->FatConfig().DynamicDirCacheSizeMin() >> PageMemSizeLog2;
       
   182 	    TUint32 CacheSizeMaxInPages = iFatMount->FatConfig().DynamicDirCacheSizeMax() >> PageMemSizeLog2;
       
   183 
       
   184 	    // cache memory client is connected via name 
       
   185 	    TBuf<0x20> clientName = _L("CACHE_MEM_CLIENT:");
       
   186 		clientName.Append('A'+iFatMount->DriveNumber());
       
   187 
       
   188 		TRAPD(err, ipDirCache = CDynamicDirCache::NewL(iDrive, CacheSizeMinInPages, CacheSizeMaxInPages, PageDataSizeLog2, clientName));
       
   189 		if (err == KErrNone)
       
   190 	    	{
       
   191 	    	__PRINT4(_L("CDynamicDirCache::NewL(drv:%C, minPageNum:%u, maxPageNum:%u, pageDataSize:%u)\n"), 'A'+iFatMount->DriveNumber(), CacheSizeMinInPages, CacheSizeMaxInPages, 1<<PageDataSizeLog2);
       
   192 	    	return;
       
   193 	    	}
       
   194 		}
       
   195 #endif // USE_DP_DIR_CACHE
       
   196 
       
   197     //=========================== create legacy type of the directory cache
       
   198     ASSERT(!ipDirCache);
       
   199 
       
   200     ipDirCache = CMediaWTCache::NewL(iDrive, numPages, pageSzLog2);
       
   201     __PRINT3(_L("CDirCache::NewL(drive: %C, NumPages=%d, PageSize=%u)"), 'A'+iFatMount->DriveNumber(), numPages, 1<<pageSzLog2);
       
   202     
       
   203     }
       
   204 
       
   205 //-------------------------------------------------------------------------------------
       
   206 
       
   207 /**
       
   208     Initialises and re-initialises the object.
       
   209 */
       
   210 void CAtaDisk::InitializeL()
       
   211 {
       
   212     CRawDisk::InitializeL();
       
   213     
       
   214     //-- there is a little issue here. after formatting FAT mounts's cluster size can change.
       
   215     //-- dir. cache page size depends on the cluster size. This method doesn't change the dir. cache page size.
       
   216     //-- At present it is done in CFatMountCB::InitializeL() that deletes this object and then reconstructs it again.
       
   217 
       
   218     //-- invalidate directory cache here
       
   219     ipDirCache->InvalidateCache();
       
   220     
       
   221     TInt64  cacheBasePos;
       
   222     
       
   223     if(iFatMount->FatType() == EFat32)
       
   224         {
       
   225         //-- this is FAT32, all directories including Root are files and aligned to the cluster heap boundary
       
   226         //-- set dir. cache base position to the cluster heap boundary
       
   227         const TUint32 offsetMask = (1 << iFatMount->ClusterSizeLog2() )-1;
       
   228         cacheBasePos = (iFatMount->ClusterBasePosition() & offsetMask);
       
   229         }
       
   230     else
       
   231         {
       
   232         //-- this is FAT12/16. Root directory is a separate volume object and has no alignment.
       
   233         //-- set cache base position to its beginning.
       
   234         cacheBasePos = iFatMount->StartOfRootDirInBytes();
       
   235         }
       
   236 
       
   237     ipDirCache->SetCacheBasePos(cacheBasePos);
       
   238     
       
   239 }
       
   240 
       
   241 //-------------------------------------------------------------------------------------
       
   242 
       
   243 /**
       
   244     Read data from the media through LRU data cache cache. 
       
   245 
       
   246     @param  aPos        absolute media position
       
   247     @param  aLength     how many bytes to read
       
   248     @param  aDes        data descriptor
       
   249 
       
   250     @leave on error
       
   251 */
       
   252 void CAtaDisk::ReadCachedL(TInt64 aPos,TInt aLength,TDes8& aDes) const
       
   253 	{
       
   254     __PRINT3(_L("CAtaDisk::ReadL() pos:%u:%u, len:%u"), I64HIGH(aPos), I64LOW(aPos), aLength);
       
   255     iUidCache->ReadL(aPos, aLength, aDes);
       
   256 	}
       
   257 
       
   258 //-------------------------------------------------------------------------------------
       
   259 
       
   260 /**
       
   261     Write data to the media through LRU data cache
       
   262 
       
   263     @param  aPos        absolute media position
       
   264     @param  aDes        data descriptor
       
   265 
       
   266     @leave on error
       
   267 */
       
   268 void CAtaDisk::WriteCachedL(TInt64 aPos, const TDesC8& aDes)
       
   269 	{
       
   270     __PRINT3(_L("CAtaDisk::WriteL() pos:%u:%u, len:%u"), I64HIGH(aPos), I64LOW(aPos), aDes.Size());
       
   271     iUidCache->WriteL(aPos, aDes);
       
   272 	}
       
   273 
       
   274 
       
   275 //-------------------------------------------------------------------------------------
       
   276 
       
   277 /**
       
   278     Read data from the media directly without any caches.
       
   279     Mostly used by file IO
       
   280 
       
   281     @param  aPos        absolute media position
       
   282     @param  aLength     how many bytes to read
       
   283 	@param  aTrg		Pointer to the data descriptor, i.e. (const TAny*)(&TDes8)
       
   284 	@param  aMessage	Refrence to server message from request
       
   285 	@param  anOffset	Offset into read data to write
       
   286 
       
   287     @leave on error
       
   288 */
       
   289 void CAtaDisk::ReadL(TInt64 aPos,TInt aLength,const TAny* aTrg,const RMessagePtr2 &aMessage,TInt anOffset) const
       
   290 	{
       
   291 
       
   292 	__PRINT4(_L("CAtaDisk::ReadL() pos:%u:%u, len:%u, offset:%u"), I64HIGH(aPos), I64LOW(aPos), aLength, anOffset);
       
   293 	User::LeaveIfError(iDrive.ReadNonCritical(aPos,aLength,aTrg,aMessage,anOffset));
       
   294 	}
       
   295 
       
   296 //-------------------------------------------------------------------------------------
       
   297 
       
   298 /**
       
   299     Write data to the media directly without any cached.
       
   300     Mostly used by file IO
       
   301 
       
   302     This method shall invalidate some data caches to keep them in synch with the media.
       
   303 
       
   304     @param aPos		Media position in bytes
       
   305     @param aLength	Length in bytes of write
       
   306 	@param aTrg		Pointer to the data descriptor, i.e. (const TAny*)(&TDes8)
       
   307 	@param aMessage	Refrence to server message from request, contains data
       
   308 	@param anOffset	Offset into write data to use in write
       
   309 
       
   310     @leave on error
       
   311 */
       
   312 void CAtaDisk::WriteL(TInt64 aPos,TInt aLength,const TAny* aSrc,const RMessagePtr2 &aMessage,TInt anOffset)
       
   313 	{
       
   314     __PRINT4(_L("CAtaDisk::WriteL() pos:%u:%u, len:%u, offset:%u"), I64HIGH(aPos), I64LOW(aPos), aLength, anOffset);
       
   315 
       
   316 	//-- write data to the media directly
       
   317     User::LeaveIfError(iDrive.WriteNonCritical(aPos,aLength,aSrc,aMessage,anOffset));
       
   318 
       
   319     //-- we need to invalidate UID cache page that corresponds to aPos (if any). This is UID caching specific. UID is stored in the first few bytes of 
       
   320     //-- the executable module and therefore belongs to one cache page only.
       
   321     //-- If someone writes to the beginning of the exe module file, corresponding UID cache page will be invalidated and re-read from the media later
       
   322     iUidCache->InvalidateCachePage(aPos); 
       
   323 
       
   324     //-- invalidate affected(if any) part of the FAT cache in the case if someone used to write data to FAT area, which usually do not happen 
       
   325     iFatMount->FAT().InvalidateCacheL(aPos,aLength);
       
   326 
       
   327 	}
       
   328 
       
   329 //-------------------------------------------------------------------------------------
       
   330 
       
   331 /** Get information for last disk error */
       
   332 TInt CAtaDisk::GetLastErrorInfo(TDes8& aErrorInfo) const
       
   333 	{
       
   334 	return iDrive.GetLastErrorInfo(aErrorInfo);
       
   335 	}
       
   336 
       
   337 
       
   338 //-------------------------------------------------------------------------------------
       
   339 /** Invalidate whole UID cache */
       
   340 void CAtaDisk::InvalidateUidCache()
       
   341 {
       
   342     ASSERT(iUidCache);
       
   343     iUidCache->InvalidateCache();
       
   344 }
       
   345 
       
   346 /** 
       
   347     Invalidate the UID cache page that has aPos cached.
       
   348     This method doesn't pay attention to the length of the block being invalidated because
       
   349     UID lives in the very beginning of the exe module and always fits into a single page
       
   350 */
       
   351 void CAtaDisk::InvalidateUidCachePage(TUint64 aPos)
       
   352 {
       
   353     ASSERT(iUidCache);
       
   354     iUidCache->InvalidateCachePage(aPos);
       
   355 }
       
   356 
       
   357 
       
   358 //################################################################################################################################
       
   359 //##    CRamDisk class implementation
       
   360 //################################################################################################################################
       
   361 
       
   362 
       
   363 /**
       
   364     CRamDisk factory method.
       
   365     
       
   366     @param  aFatMount reference to the owner.
       
   367     @return pointer to the constructed object.
       
   368 */
       
   369 CRamDisk* CRamDisk::NewL(CFatMountCB& aFatMount)
       
   370 	{
       
   371     __PRINT1(_L("CRamDisk::NewL() drv:%d"), aFatMount.DriveNumber());
       
   372 	CRamDisk* pSelf = new(ELeave)CRamDisk(aFatMount);
       
   373 
       
   374     CleanupStack::PushL(pSelf);
       
   375   
       
   376     pSelf->InitializeL();
       
   377     
       
   378     CleanupStack::Pop();
       
   379 
       
   380 	return pSelf;
       
   381 	}
       
   382 
       
   383 CRamDisk::CRamDisk(CFatMountCB& aFatMount)
       
   384 	     :CRawDisk(aFatMount)
       
   385     {
       
   386 	}
       
   387 
       
   388 //-------------------------------------------------------------------------------------
       
   389 
       
   390 /**
       
   391     Initialises and re-initialises the object.
       
   392 */
       
   393 void CRamDisk::InitializeL()
       
   394 {
       
   395     CRawDisk::InitializeL();
       
   396 
       
   397     //-- set the RAM disk base
       
   398     TLocalDriveCapsV2 caps;
       
   399     TPckg<TLocalDriveCapsV2> capsPckg(caps);
       
   400     User::LeaveIfError(iFatMount->LocalDrive()->Caps(capsPckg));
       
   401   
       
   402     ASSERT(caps.iMediaAtt & KMediaAttVariableSize);
       
   403     
       
   404     //-- set RAM disk base
       
   405     iRamDiskBase = caps.iBaseAddress; 
       
   406     ASSERT(iRamDiskBase);
       
   407 }
       
   408 
       
   409 
       
   410 
       
   411 /** @return the start address of the Ram Drive in low memory */
       
   412 TUint8* CRamDisk::RamDiskBase() const
       
   413 	{
       
   414 	return iRamDiskBase;
       
   415 	}
       
   416 
       
   417 //-------------------------------------------------------------------------------------
       
   418 //
       
   419 // Read aLength of data from the disk
       
   420 //
       
   421 void CRamDisk::ReadCachedL(TInt64 aPos,TInt aLength,TDes8& aDes) const
       
   422 	{
       
   423 	
       
   424 	__PRINT3(_L("CRamDisk::ReadL Base 0x%x Pos 0x%x, Len %d"),RamDiskBase(),I64LOW(aPos),aLength);
       
   425 	__ASSERT_ALWAYS((aPos+aLength<=I64INT(iFatMount->Size())) && (aLength>=0),User::Leave(KErrCorrupt));
       
   426 	Mem::Copy((TUint8*)aDes.Ptr(),RamDiskBase()+I64LOW(aPos),aLength);
       
   427 	aDes.SetLength(aLength);
       
   428 	}
       
   429 
       
   430 //-------------------------------------------------------------------------------------
       
   431 //
       
   432 // Write aLength of data to the disk
       
   433 //
       
   434 void CRamDisk::WriteCachedL(TInt64 aPos,const TDesC8& aDes)
       
   435 	{
       
   436 
       
   437 	__PRINT3(_L("CRamDisk::WriteL Base 0x%x Pos 0x%x, Len %d"),RamDiskBase(),aPos,aDes.Length());
       
   438 	__ASSERT_ALWAYS(aPos+aDes.Length()<=I64INT(iFatMount->Size()),User::Leave(KErrCorrupt));
       
   439 	Mem::Copy(RamDiskBase()+I64LOW(aPos),(TUint8*)aDes.Ptr(),aDes.Length());
       
   440 	}
       
   441 	
       
   442 
       
   443 //-------------------------------------------------------------------------------------
       
   444 //
       
   445 // Read from ramDrive into thread relative descriptor
       
   446 //
       
   447 void CRamDisk::ReadL(TInt64 aPos,TInt aLength,const TAny* /*aTrg*/,const RMessagePtr2 &aMessage,TInt anOffset) const
       
   448 	{
       
   449 	__PRINT2(_L("CRamDisk::ReadL TAny* Pos 0x%x, Len %d"),aPos,aLength);
       
   450 	__ASSERT_ALWAYS((aPos+aLength<=I64INT(iFatMount->Size())) && (aLength>=0),User::Leave(KErrCorrupt));
       
   451 	TUint8* pos=RamDiskBase()+I64LOW(aPos);
       
   452 	TPtrC8 buf(pos,aLength);
       
   453 	aMessage.WriteL(0,buf,anOffset);
       
   454 	}
       
   455 
       
   456 //-------------------------------------------------------------------------------------
       
   457 //
       
   458 // Write from thread relative descriptor into ramDrive
       
   459 //
       
   460 void CRamDisk::WriteL(TInt64 aPos,TInt aLength,const TAny* /*aSrc*/,const RMessagePtr2 &aMessage,TInt anOffset)
       
   461 	{
       
   462 	__PRINT2(_L("CRamDisk::WriteL TAny* Pos 0x%x, Len %d"),aPos,aLength);
       
   463 	__ASSERT_ALWAYS(aPos+aLength<=I64INT(iFatMount->Size()),User::Leave(KErrCorrupt));
       
   464 	TUint8* pos=RamDiskBase()+I64LOW(aPos);
       
   465 	TPtr8 buf(pos,aLength);
       
   466 	aMessage.ReadL(0,buf,anOffset);
       
   467 	}
       
   468 
       
   469 
       
   470 
       
   471 
       
   472 
       
   473 
       
   474 
       
   475 
       
   476 
       
   477 
       
   478 
       
   479 
       
   480 
       
   481 
       
   482 
       
   483 
       
   484 
       
   485 
       
   486 
       
   487 
       
   488 
       
   489 
       
   490 
       
   491 
       
   492 
       
   493 
       
   494