kernel/eka/drivers/medlfs/flash_media.cpp
changeset 0 a41df078684a
child 6 0173bcd7697c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/medlfs/flash_media.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,377 @@
+// 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;
+	}
+