Convert Kernelhwsrv package from SFL to EPL
kernel\eka\compsupp is subject to the ARM EABI LICENSE
userlibandfileserver\fatfilenameconversionplugins\unicodeTables is subject to the Unicode license
kernel\eka\kernel\zlib is subject to the zlib license
// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// f32\sfat\sl_disk.cpp
//
//
#include "sl_disk.h"
#include "sl_cache.h"
#include "sl_dir_cache.h"
/**
@file
*/
//################################################################################################################################
//# CRawDisk implementation
//################################################################################################################################
/**
Factory function. Constructs objects of the classes derived from CRawDisk.
@param aOwner reference to the onwning FAT Mount class
@param aLocDrvCaps local drive capabilities from the media driver
@return pointer to the constructed object. May be NULL on error.
*/
CRawDisk* CRawDisk::NewL(CFatMountCB& aOwner, const TLocalDriveCaps& aLocDrvCaps)
{
__PRINT1(_L("CRawDisk::NewL() drv:%d"), aOwner.DriveNumber());
if(aLocDrvCaps.iMediaAtt & KMediaAttVariableSize)
{//-- this is the RAM drive "attribute"
ASSERT((aLocDrvCaps.iDriveAtt & (KDriveAttInternal|KDriveAttLocal)) && aLocDrvCaps.iType == EMediaRam);
if(!aLocDrvCaps.iBaseAddress)
{
ASSERT(0);
return NULL;
}
return CRamDisk::NewL(aOwner);
}
//-- create CAtaDisk by default
return CAtaDisk::NewL(aOwner);
}
CRawDisk::CRawDisk(CFatMountCB& aOwner)
{
iFatMount = &aOwner;
}
/**
Default implementation. Initialises and re-initialises the object.
*/
void CRawDisk::InitializeL()
{
ASSERT(iFatMount);
}
TInt CRawDisk::GetLastErrorInfo(TDes8& /*aErrorInfo*/) const
{
return KErrNotSupported;
}
//################################################################################################################################
//## CAtaDisk class implementation
//################################################################################################################################
CAtaDisk::CAtaDisk(CFatMountCB& aFatMount)
:CRawDisk(aFatMount), iDrive(aFatMount.DriveInterface())
{
}
CAtaDisk::~CAtaDisk()
{
delete ipDirCache;
delete iUidCache;
}
//-------------------------------------------------------------------------------------
/**
CAtaDisk factory method.
@param aFatMount reference to the owner.
@return pointer to the constructed object.
*/
CAtaDisk* CAtaDisk::NewL(CFatMountCB& aFatMount)
{
__PRINT1(_L("CAtaDisk::NewL() drv:%d"), aFatMount.DriveNumber());
CAtaDisk* pSelf = new (ELeave) CAtaDisk(aFatMount);
CleanupStack::PushL(pSelf);
pSelf->ConstructL();
pSelf->InitializeL();
CleanupStack::Pop();
return pSelf;
}
//-------------------------------------------------------------------------------------
/** 2nd stage constructor */
void CAtaDisk::ConstructL()
{
//=========================== create data WT cache that is primarily used for caching exacutable modules' UIDs
const TUint32 KUidCachePageSzLog2 = 9; //-- 512 bytes in page
const TUint32 KUidCachePages = 64; //-- 64 pages; total cache size is 32K
iUidCache = CMediaWTCache::NewL(iDrive, KUidCachePages, KUidCachePageSzLog2);
//=========================== create directory cache
//-- Get dir. cache parameters from config. They may be set in estart.txt for a specified drive.
const TUint32 KDirCacheSize = iFatMount->FatConfig().DirCacheSize(); //- Total directory cache size, bytes.
const TUint32 KMaxDirCachePageSzLog2 = iFatMount->FatConfig().DirCacheMaxPageSizeLog2(); //- Log2 of the Max. dir. cache page.
__PRINT2(_L("CAtaDisk::ConstructL() Dir Cache config:%d,%d"),KDirCacheSize,KMaxDirCachePageSzLog2);
ASSERT(KDirCacheSize >= K1KiloByte && KDirCacheSize <= K1MegaByte);
ASSERT((KMaxDirCachePageSzLog2 >= KDefSectorSzLog2) && (Pow2(KMaxDirCachePageSzLog2) <= KDirCacheSize));
//-- calculate the size and number of pages for the dir. cache.
//-- if the mount's cluster size is less than max. page size from config, the page size will be cluster size.
//-- 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.
//-- The number of pages depends on total cache size and page size.
const TUint clustSizeLog2 = iFatMount->ClusterSizeLog2(); //-- current FAT cluster size Log2
const TUint32 pageSzLog2 = (clustSizeLog2 <= KMaxDirCachePageSzLog2) ? clustSizeLog2 : KMaxDirCachePageSzLog2;
const TUint32 numPages = KDirCacheSize / (Pow2(pageSzLog2));
ASSERT(!ipDirCache);
#ifdef USE_DP_DIR_CACHE
//=========================== create Demand Paging type of the directory cache
// initialize cache memory manager as all file systems have mounted by now
if(CCacheMemoryManagerFactory::CacheMemoryManager())
{
// Note: the configuration data of min and max cache size are aligned with the memory size it
// occupies in kernel as we are using demand paging subsystem for dynamic cache size support.
// Therefore, they are refered as 'Mem Size' in following calculation.
// However, 'Data Size' refers to the logical size of a page, i.e. the actual data size each page
// contains.
// The constraints we have to consider when setting up the dynamic cache:
// 1. each page's data size is aligned with cluster size, unless cluster size is bigger than
// the default maximum page size allowed (typically 32 KB).
// 2. if page's data size is smaller than segment size (typically 4 KB), i.e. the unit size of
// demand paging subsystem's page management, we will still use up the whole segment for
// that page.
// 3. the default min and max cache's memory size is pre-defined in fat_config.cpp file.
// (see KDef_DynamicDirCacheMin & KDef_DynamicDirCacheMax).
// calculate page data size (logical view of page size)
const TUint32 DefMaxCachePageLog2 = iFatMount->FatConfig().DynamicDirCacheMaxPageSizeLog2();
const TUint32 PageDataSizeLog2 = clustSizeLog2 < DefMaxCachePageLog2 ? clustSizeLog2 : DefMaxCachePageLog2;
// calculate page number, based on memory size we have reserved
const TUint32 SegmentSizeLog2 = CCacheMemoryManagerFactory::CacheMemoryManager()->SegmentSizeInBytesLog2();
const TUint32 PageMemSizeLog2 = PageDataSizeLog2 < SegmentSizeLog2 ? SegmentSizeLog2 : PageDataSizeLog2;
TUint32 CacheSizeMinInPages = iFatMount->FatConfig().DynamicDirCacheSizeMin() >> PageMemSizeLog2;
TUint32 CacheSizeMaxInPages = iFatMount->FatConfig().DynamicDirCacheSizeMax() >> PageMemSizeLog2;
// cache memory client is connected via name
TBuf<0x20> clientName = _L("CACHE_MEM_CLIENT:");
clientName.Append('A'+iFatMount->DriveNumber());
TRAPD(err, ipDirCache = CDynamicDirCache::NewL(iDrive, CacheSizeMinInPages, CacheSizeMaxInPages, PageDataSizeLog2, clientName));
if (err == KErrNone)
{
__PRINT4(_L("CDynamicDirCache::NewL(drv:%C, minPageNum:%u, maxPageNum:%u, pageDataSize:%u)\n"), 'A'+iFatMount->DriveNumber(), CacheSizeMinInPages, CacheSizeMaxInPages, 1<<PageDataSizeLog2);
return;
}
}
#endif // USE_DP_DIR_CACHE
//=========================== create legacy type of the directory cache
ASSERT(!ipDirCache);
ipDirCache = CMediaWTCache::NewL(iDrive, numPages, pageSzLog2);
__PRINT3(_L("CDirCache::NewL(drive: %C, NumPages=%d, PageSize=%u)"), 'A'+iFatMount->DriveNumber(), numPages, 1<<pageSzLog2);
}
//-------------------------------------------------------------------------------------
/**
Initialises and re-initialises the object.
*/
void CAtaDisk::InitializeL()
{
CRawDisk::InitializeL();
//-- there is a little issue here. after formatting FAT mounts's cluster size can change.
//-- dir. cache page size depends on the cluster size. This method doesn't change the dir. cache page size.
//-- At present it is done in CFatMountCB::InitializeL() that deletes this object and then reconstructs it again.
//-- invalidate directory cache here
ipDirCache->InvalidateCache();
TInt64 cacheBasePos;
if(iFatMount->FatType() == EFat32)
{
//-- this is FAT32, all directories including Root are files and aligned to the cluster heap boundary
//-- set dir. cache base position to the cluster heap boundary
const TUint32 offsetMask = (1 << iFatMount->ClusterSizeLog2() )-1;
cacheBasePos = (iFatMount->ClusterBasePosition() & offsetMask);
}
else
{
//-- this is FAT12/16. Root directory is a separate volume object and has no alignment.
//-- set cache base position to its beginning.
cacheBasePos = iFatMount->StartOfRootDirInBytes();
}
ipDirCache->SetCacheBasePos(cacheBasePos);
}
//-------------------------------------------------------------------------------------
/**
Read data from the media through LRU data cache cache.
@param aPos absolute media position
@param aLength how many bytes to read
@param aDes data descriptor
@leave on error
*/
void CAtaDisk::ReadCachedL(TInt64 aPos,TInt aLength,TDes8& aDes) const
{
__PRINT3(_L("CAtaDisk::ReadL() pos:%u:%u, len:%u"), I64HIGH(aPos), I64LOW(aPos), aLength);
iUidCache->ReadL(aPos, aLength, aDes);
}
//-------------------------------------------------------------------------------------
/**
Write data to the media through LRU data cache
@param aPos absolute media position
@param aDes data descriptor
@leave on error
*/
void CAtaDisk::WriteCachedL(TInt64 aPos, const TDesC8& aDes)
{
__PRINT3(_L("CAtaDisk::WriteL() pos:%u:%u, len:%u"), I64HIGH(aPos), I64LOW(aPos), aDes.Size());
iUidCache->WriteL(aPos, aDes);
}
//-------------------------------------------------------------------------------------
/**
Read data from the media directly without any caches.
Mostly used by file IO
@param aPos absolute media position
@param aLength how many bytes to read
@param aTrg Pointer to the data descriptor, i.e. (const TAny*)(&TDes8)
@param aMessage Refrence to server message from request
@param anOffset Offset into read data to write
@leave on error
*/
void CAtaDisk::ReadL(TInt64 aPos,TInt aLength,const TAny* aTrg,const RMessagePtr2 &aMessage,TInt anOffset) const
{
__PRINT4(_L("CAtaDisk::ReadL() pos:%u:%u, len:%u, offset:%u"), I64HIGH(aPos), I64LOW(aPos), aLength, anOffset);
User::LeaveIfError(iDrive.ReadNonCritical(aPos,aLength,aTrg,aMessage,anOffset));
}
//-------------------------------------------------------------------------------------
/**
Write data to the media directly without any cached.
Mostly used by file IO
This method shall invalidate some data caches to keep them in synch with the media.
@param aPos Media position in bytes
@param aLength Length in bytes of write
@param aTrg Pointer to the data descriptor, i.e. (const TAny*)(&TDes8)
@param aMessage Refrence to server message from request, contains data
@param anOffset Offset into write data to use in write
@leave on error
*/
void CAtaDisk::WriteL(TInt64 aPos,TInt aLength,const TAny* aSrc,const RMessagePtr2 &aMessage,TInt anOffset)
{
__PRINT4(_L("CAtaDisk::WriteL() pos:%u:%u, len:%u, offset:%u"), I64HIGH(aPos), I64LOW(aPos), aLength, anOffset);
//-- write data to the media directly
User::LeaveIfError(iDrive.WriteNonCritical(aPos,aLength,aSrc,aMessage,anOffset));
//-- 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
//-- the executable module and therefore belongs to one cache page only.
//-- 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
iUidCache->InvalidateCachePage(aPos);
//-- 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
iFatMount->FAT().InvalidateCacheL(aPos,aLength);
}
//-------------------------------------------------------------------------------------
/** Get information for last disk error */
TInt CAtaDisk::GetLastErrorInfo(TDes8& aErrorInfo) const
{
return iDrive.GetLastErrorInfo(aErrorInfo);
}
//-------------------------------------------------------------------------------------
/** Invalidate whole UID cache */
void CAtaDisk::InvalidateUidCache()
{
ASSERT(iUidCache);
iUidCache->InvalidateCache();
}
/**
Invalidate the UID cache page that has aPos cached.
This method doesn't pay attention to the length of the block being invalidated because
UID lives in the very beginning of the exe module and always fits into a single page
*/
void CAtaDisk::InvalidateUidCachePage(TUint64 aPos)
{
ASSERT(iUidCache);
iUidCache->InvalidateCachePage(aPos);
}
//################################################################################################################################
//## CRamDisk class implementation
//################################################################################################################################
/**
CRamDisk factory method.
@param aFatMount reference to the owner.
@return pointer to the constructed object.
*/
CRamDisk* CRamDisk::NewL(CFatMountCB& aFatMount)
{
__PRINT1(_L("CRamDisk::NewL() drv:%d"), aFatMount.DriveNumber());
CRamDisk* pSelf = new(ELeave)CRamDisk(aFatMount);
CleanupStack::PushL(pSelf);
pSelf->InitializeL();
CleanupStack::Pop();
return pSelf;
}
CRamDisk::CRamDisk(CFatMountCB& aFatMount)
:CRawDisk(aFatMount)
{
}
//-------------------------------------------------------------------------------------
/**
Initialises and re-initialises the object.
*/
void CRamDisk::InitializeL()
{
CRawDisk::InitializeL();
//-- set the RAM disk base
TLocalDriveCapsV2 caps;
TPckg<TLocalDriveCapsV2> capsPckg(caps);
User::LeaveIfError(iFatMount->LocalDrive()->Caps(capsPckg));
ASSERT(caps.iMediaAtt & KMediaAttVariableSize);
//-- set RAM disk base
iRamDiskBase = caps.iBaseAddress;
ASSERT(iRamDiskBase);
}
/** @return the start address of the Ram Drive in low memory */
TUint8* CRamDisk::RamDiskBase() const
{
return iRamDiskBase;
}
//-------------------------------------------------------------------------------------
//
// Read aLength of data from the disk
//
void CRamDisk::ReadCachedL(TInt64 aPos,TInt aLength,TDes8& aDes) const
{
__PRINT3(_L("CRamDisk::ReadL Base 0x%x Pos 0x%x, Len %d"),RamDiskBase(),I64LOW(aPos),aLength);
__ASSERT_ALWAYS((aPos+aLength<=I64INT(iFatMount->Size())) && (aLength>=0),User::Leave(KErrCorrupt));
Mem::Copy((TUint8*)aDes.Ptr(),RamDiskBase()+I64LOW(aPos),aLength);
aDes.SetLength(aLength);
}
//-------------------------------------------------------------------------------------
//
// Write aLength of data to the disk
//
void CRamDisk::WriteCachedL(TInt64 aPos,const TDesC8& aDes)
{
__PRINT3(_L("CRamDisk::WriteL Base 0x%x Pos 0x%x, Len %d"),RamDiskBase(),aPos,aDes.Length());
__ASSERT_ALWAYS(aPos+aDes.Length()<=I64INT(iFatMount->Size()),User::Leave(KErrCorrupt));
Mem::Copy(RamDiskBase()+I64LOW(aPos),(TUint8*)aDes.Ptr(),aDes.Length());
}
//-------------------------------------------------------------------------------------
//
// Read from ramDrive into thread relative descriptor
//
void CRamDisk::ReadL(TInt64 aPos,TInt aLength,const TAny* /*aTrg*/,const RMessagePtr2 &aMessage,TInt anOffset) const
{
__PRINT2(_L("CRamDisk::ReadL TAny* Pos 0x%x, Len %d"),aPos,aLength);
__ASSERT_ALWAYS((aPos+aLength<=I64INT(iFatMount->Size())) && (aLength>=0),User::Leave(KErrCorrupt));
TUint8* pos=RamDiskBase()+I64LOW(aPos);
TPtrC8 buf(pos,aLength);
aMessage.WriteL(0,buf,anOffset);
}
//-------------------------------------------------------------------------------------
//
// Write from thread relative descriptor into ramDrive
//
void CRamDisk::WriteL(TInt64 aPos,TInt aLength,const TAny* /*aSrc*/,const RMessagePtr2 &aMessage,TInt anOffset)
{
__PRINT2(_L("CRamDisk::WriteL TAny* Pos 0x%x, Len %d"),aPos,aLength);
__ASSERT_ALWAYS(aPos+aLength<=I64INT(iFatMount->Size()),User::Leave(KErrCorrupt));
TUint8* pos=RamDiskBase()+I64LOW(aPos);
TPtr8 buf(pos,aLength);
aMessage.ReadL(0,buf,anOffset);
}