// 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:
// e32\drivers\medlfs\flash_media.cpp
//
//
#include <drivers/flash_media.h>
#include "variantmediadef.h"
_LIT(KPddName, "Media.Flash");
_LIT(KFlashThreadName,"FlashThread");
const TInt KFlashThreadPriority=24; // same as file server
GLDEF_C TDfcQue FlashDfcQ;
class DPhysicalDeviceMediaFlash : public DPhysicalDevice
{
public:
DPhysicalDeviceMediaFlash();
virtual TInt Install();
virtual void GetCaps(TDes8& aDes) const;
virtual TInt Create(DBase*& aChannel, TInt aMediaId, const TDesC8* anInfo, const TVersion& aVer);
virtual TInt Validate(TInt aDeviceType, const TDesC8* anInfo, const TVersion& aVer);
virtual TInt Info(TInt aFunction, TAny* a1);
};
DPhysicalDeviceMediaFlash::DPhysicalDeviceMediaFlash()
//
// Constructor
//
{
iUnitsMask=0x2;
iVersion=TVersion(KMediaDriverInterfaceMajorVersion,KMediaDriverInterfaceMinorVersion,KMediaDriverInterfaceBuildVersion);
}
TInt DPhysicalDeviceMediaFlash::Install()
//
// Install the media drives PDD.
//
{
return SetName(&KPddName);
}
void DPhysicalDeviceMediaFlash::GetCaps(TDes8& /*aDes*/) const
//
// Return the media drivers capabilities.
//
{
}
TInt DPhysicalDeviceMediaFlash::Create(DBase*& aChannel, TInt aMediaId, const TDesC8* /* anInfo */,const TVersion &aVer)
//
// Create an LFFS media driver.
//
{
if (!Kern::QueryVersionSupported(iVersion,aVer))
return KErrNotSupported;
DMediaDriverFlash *pD=DMediaDriverFlash::New(aMediaId);
aChannel=pD;
TInt r=KErrNoMemory;
if (pD)
r=pD->DoCreate(aMediaId);
if (r==KErrNone)
pD->OpenMediaDriverComplete(KErrNone);
return r;
}
TInt DPhysicalDeviceMediaFlash::Validate(TInt aDeviceType, const TDesC8* /*anInfo*/, const TVersion& aVer)
{
if (!Kern::QueryVersionSupported(iVersion,aVer))
return KErrNotSupported;
if (aDeviceType!=MEDIA_DEVICE_LFFS)
return KErrNotSupported;
return KErrNone;
}
TInt DPhysicalDeviceMediaFlash::Info(TInt aFunction, TAny*)
//
// Return the priority of this media driver
//
{
if (aFunction==EPriority)
return KMediaDriverPriorityNormal;
return KErrNotSupported;
}
/**
@internalComponent
*/
DMediaDriverFlash::DMediaDriverFlash(TInt aMediaId)
//
// Constructor.
//
: DMediaDriver(aMediaId)
{}
/**
@internalComponent
*/
TInt DMediaDriverFlash::DoCreate(TInt /*aMediaId*/)
//
// Create the media driver.
//
{
TInt r=Initialise(); // interrogate FLASH etc.
if (r==KErrNone)
{
TUint32 size=TotalSize();
SetTotalSizeInBytes(size);
}
return r;
}
/**
A function called by the local media subsystem to deal with a request;
this is implemented by the generic layer of the LFFS media driver.
The implementation delegates the handling of reading, writing and erasing
to the specific layer's DoRead(), DoWrite() and DoErase() functions
respectively.
@param aRequest An object that encapsulates information about the request.
@return A value indicating the result:
KErrNone, if the request has been sucessfully initiated;
KErrNotSupported, if the request cannot be handled by the device;
KMediaDriverDeferRequest, if the request cannot be handled
immediately because of an outstanding request (this request will be
deferred until the outstanding request has completed);
otherwise one of the other system-wide error codes.
@see DMediaDriverFlash::DoRead()
@see DMediaDriverFlash::DoWrite()
@see DMediaDriverFlash::DoErase()
*/
TInt DMediaDriverFlash::Request(TLocDrvRequest& m)
{
TInt r=KErrNotSupported;
TInt id=m.Id();
__KTRACE_OPT(KLOCDRV,Kern::Printf(">DMediaDriverFlash::Request %d",id));
if (id==DLocalDrive::ECaps)
{
TLocalDriveCapsV2& c=*(TLocalDriveCapsV2*)m.RemoteDes();
r=Caps(c);
c.iSize=m.Drive()->iPartitionLen;
c.iPartitionType=m.Drive()->iPartitionType;
return r;
}
switch (id)
{
case DLocalDrive::ERead:
if (iReadReq)
return KMediaDriverDeferRequest; // read already in progress so defer this one
iReadReq=&m;
r=DoRead();
if (r!=KErrNone)
iReadReq=NULL;
break;
case DLocalDrive::EWrite:
if (iWriteReq)
return KMediaDriverDeferRequest; // write already in progress so defer this one
iWriteReq=&m;
r=DoWrite();
if (r!=KErrNone)
iWriteReq=NULL;
break;
case DLocalDrive::EFormat:
if (iEraseReq)
return KMediaDriverDeferRequest; // erase already in progress so defer this one
iEraseReq=&m;
r=DoErase();
if (r!=KErrNone)
iEraseReq=NULL;
break;
case DLocalDrive::EEnlarge:
case DLocalDrive::EReduce:
default:
r=KErrNotSupported;
break;
}
__KTRACE_OPT(KLOCDRV,Kern::Printf("<DMediaDriverFlash::Request %d",r));
if (r<0)
DMediaDriver::Complete(m,r);
return r;
}
/**
A function called by the local media subsystem to inform the driver
that the device should power down.
The default implementation does nothing.
*/
void DMediaDriverFlash::NotifyPowerDown()
{
// no action required
}
/**
A function called by the local media subsystem to inform the driver
that the device is to be immediately powered down.
The default implementation does nothing.
*/
void DMediaDriverFlash::NotifyEmergencyPowerDown()
{
// no action required
}
/**
Called by the specific layer of the LFFS media driver to inform
the generic layer that a request is complete.
@param aRequest The type of the request that is complete. This is one of
the TRequest enum values:
EReqRead, EReqWrite or EReqErase as appropriate.
@param aResult KErrNone, if the request has been completed successfully,
otherwise one if the other system-wide error codes.
@see DMediaDriverFlash::TRequest
*/
void DMediaDriverFlash::Complete(TInt aRequest, TInt aResult)
{
__KTRACE_OPT(KLOCDRV,Kern::Printf("Flash:Complete(%d,%d)",aRequest,aResult));
TLocDrvRequest* pR=iRequests[aRequest];
iRequests[aRequest]=NULL;
DMediaDriver::Complete(*pR,aResult);
}
/**
Called by the generic layer to get the capabilities of the flash device.
The default implementation is synchronous, and returns KErrCompletion.
@param aCaps On return, descriptor data contains capability information
about the flash device, in the form of a class derived from
TLocalDriveCapsV2. The size of the derived class should not exceed
KMaxLocalDriveCapsLength which is defined and used in
e32\drivers\locmedia\locmedia.cpp. If a larger sized capabilities
class is used, and this code is modified to write to member data
beyond KMaxLocalDriveCapsLength this will cause a fault.
@return KErrCompletion, if the operation has been done synchronously and is successful;
one of the other system wide error codes (not KErrNone), if
the operation has been done synchronously but UNSUCCESSFULLY;
KErrNone, if the operation is being done asynchronously.
@see TLocalDriveCapsV2
*/
TInt DMediaDriverFlash::Caps(TLocalDriveCapsV2& caps)
{
caps.iType=EMediaFlash;
caps.iBattery=EBatNotSupported;
caps.iDriveAtt=KDriveAttLocal|KDriveAttInternal;
caps.iMediaAtt=KMediaAttFormattable;
caps.iBaseAddress=(TUint8*)TInternalRamDrive::Base();
caps.iFileSystemId=KDriveFileSysLFFS;
caps.iHiddenSectors=0;
caps.iEraseBlockSize=EraseBlockSize();
__KTRACE_OPT( KLOCDRV, Kern::Printf("MLFS: ) type=%d", caps.iType) );
__KTRACE_OPT( KLOCDRV, Kern::Printf("MLFS: ) battery=%d", caps.iBattery) );
__KTRACE_OPT( KLOCDRV, Kern::Printf("MLFS: ) driveatt=0x%x", caps.iDriveAtt) );
__KTRACE_OPT( KLOCDRV, Kern::Printf("MLFS: ) mediaatt=0x%x", caps.iMediaAtt) );
__KTRACE_OPT( KLOCDRV, Kern::Printf("MLFS: ) filesystemid=0x%x", caps.iFileSystemId) );
__KTRACE_OPT( KLOCDRV, Kern::Printf("MLFS: ) eraseblocksize=0x%x", caps.iEraseBlockSize) );
return KErrCompletion; // synchronous completion
}
/**
A function called by the local media subsystem to get partition information
for the flash device.
It is called once the subsystem has been notified that the media driver
is open and has been succesfully initialised.
The function should be overriden by the specific layer of
the LFFS media driver.
The default implementation is synchronous
and sets:
- the partition count to 1, meaning that there is only the one partition.
- the partition base address to 0.
- the partition length to the total size of the flash device.
- the size of the media to the total size of the flash device.
- the partition type to KPartitionTypeEneaLFFS.
@param anInfo An object that, on successful return, contains
the partition information.
@return KErrNone, if retrieval of partition information is to be
done asynchronously;
KErrCompletion, if retrieval of partition information has been
done synchronously, and successfully;
one of the other system-wide error codes, if retrieval of partition
information has been done synchronously, but unsuccessfully.
*/
TInt DMediaDriverFlash::PartitionInfo(TPartitionInfo& aInfo)
{
aInfo.iPartitionCount = 1;
aInfo.iEntry[0].iPartitionBaseAddr = 0;
aInfo.iEntry[0].iPartitionLen = TotalSizeInBytes();
aInfo.iEntry[0].iPartitionType = KPartitionTypeEneaLFFS;
aInfo.iMediaSizeInBytes = TotalSizeInBytes();
return KErrCompletion;
}
DECLARE_EXTENSION_PDD()
{
return new DPhysicalDeviceMediaFlash;
}
static const TInt LffsDriveNumbers[LFFS_DRIVECOUNT]={LFFS_DRIVELIST};
_LIT(KFlashDriveName,LFFS_DRIVENAME);
DECLARE_STANDARD_EXTENSION()
{
__KTRACE_OPT(KBOOT,Kern::Printf("Registering FLASH drive"));
if (Kern::SuperPage().iCpuId & KCpuIdISS)
return KErrNone; // no FLASH on ARMULATOR
TInt r=Kern::DfcQInit(&FlashDfcQ,KFlashThreadPriority,&KFlashThreadName);
if (r==KErrNone)
{
DPrimaryMediaBase* pM=new DPrimaryMediaBase;
if (pM)
{
pM->iDfcQ=&FlashDfcQ;
r=LocDrv::RegisterMediaDevice(EFixedMedia1,LFFS_DRIVECOUNT,&LffsDriveNumbers[0],pM,LFFS_NUMMEDIA,KFlashDriveName);
if (r==KErrNone)
pM->iMsgQ.Receive();
}
}
__KTRACE_OPT(KBOOT,Kern::Printf("Registering FLASH drive - return %d",r));
return r;
}