start nvmemory nvmemory
authorjahyvone@4FIL49437
Thu, 27 May 2010 00:38:17 +0300
branchnvmemory
changeset 74 eb3d0111f868
parent 73 b6aa150091ee
child 80 e9514b7eeead
start nvmemory
baseport/syborg/bld.inf
baseport/syborg/bootstrap/syborg.inc
baseport/syborg/bootstrap/syborg.s
baseport/syborg/estart.txt
baseport/syborg/mednvmemory/mednvmemory.mmp
baseport/syborg/mednvmemory/syborg_mednvmemory.cpp
baseport/syborg/mednvmemory/syborg_mednvmemory.h
baseport/syborg/rom/kernel.iby
baseport/syborg/specific/syborg.h
baseport/syborg/specific/variantmediadef.h
baseport/syborg/syborg.dtb
baseport/syborg/syborg.dts
symbian-qemu-0.9.1-12/model-libraries/commoninc/platformtypes.h
symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Debug/BuildLog.htm
symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Debug/app.res
symbian-qemu-0.9.1-12/model-libraries/nvmemmory/NVMemory_HowTo.txt
symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/BuildLog.htm
symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/RCa03000
symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/mt.dep
symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/nvmemmory.dll
symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/nvmemmory.dll.intermediate.manifest
symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/nvmemmory.exp
symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/nvmemmory.lib
symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/nvmemmory.obj
symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/nvmemmory.pdb
symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/vc80.idb
symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/vc80.pdb
symbian-qemu-0.9.1-12/model-libraries/nvmemmory/app.ico
symbian-qemu-0.9.1-12/model-libraries/nvmemmory/app.rc
symbian-qemu-0.9.1-12/model-libraries/nvmemmory/nvmemmory.cpp
symbian-qemu-0.9.1-12/model-libraries/nvmemmory/nvmemmory.h
symbian-qemu-0.9.1-12/model-libraries/nvmemmory/nvmemmory.ncb
symbian-qemu-0.9.1-12/model-libraries/nvmemmory/nvmemmory.sln
symbian-qemu-0.9.1-12/model-libraries/nvmemmory/nvmemmory.suo
symbian-qemu-0.9.1-12/model-libraries/nvmemmory/nvmemmory.vcproj
symbian-qemu-0.9.1-12/model-libraries/nvmemmory/nvmemmory.vcproj.NOE.jahyvone.user
symbian-qemu-0.9.1-12/qemu-symbian-svp/plugins/qemu_arm_plugins.py
symbian-qemu-0.9.1-12/qemu-symbian-svp/plugins/syborg_nvmemorydevice.py
symbian-qemu-0.9.1-12/qemu-symbian-svp/python-plugin.c
--- a/baseport/syborg/bld.inf	Fri May 14 16:38:13 2010 +0100
+++ b/baseport/syborg/bld.inf	Thu May 27 00:38:17 2010 +0300
@@ -95,6 +95,9 @@
 webcamera/webcamera_ldd
 webcamera/webcamera_app
 
+//Non volatile memory device
+mednvmemory\mednvmemory
+
 PRJ_EXTENSIONS
 start		extension		base/config
 option		PREFIX			_syborg_
--- a/baseport/syborg/bootstrap/syborg.inc	Fri May 14 16:38:13 2010 +0100
+++ b/baseport/syborg/bootstrap/syborg.inc	Thu May 27 00:38:17 2010 +0300
@@ -52,7 +52,8 @@
 KHwBaseNand		EQU     KHwBaseRegisters + 0x0d000
 KHwBaseAudio		EQU     KHwBaseRegisters + 0x0e000
 KHwBaseWebcamera	EQU     KHwBaseRegisters + 0x0f000
-KHwBasePlatform		EQU     KHwBaseRegisters + 0x10000
+KHwNVMemoryDevice			EQU		KHwBaseRegisters + 0x10000
+KHwBasePlatform		EQU     KHwBaseRegisters + 0x11000
 
 ;-----------------------------------------------------------------------------
 ; Module linear bases
@@ -79,6 +80,7 @@
 KHwLinBaseNand		EQU	KHwLinBaseRegisters + 0x0d*KHwLinSeparation
 KHwLinBaseAudio		EQU	KHwLinBaseRegisters + 0x0e*KHwLinSeparation
 KHwLinBaseWebcameraDevice	EQU	KHwLinBaseRegisters + 0x0f*KHwLinSeparation
-KHwLinBasePlatform	EQU	KHwLinBaseRegisters + 0x10*KHwLinSeparation;
+KHwLinBaseNVMemory	EQU	KHwLinBaseRegisters + 0x10*KHwLinSeparation
+KHwLinBasePlatform	EQU	KHwLinBaseRegisters + 0x11*KHwLinSeparation
 	
 	END
--- a/baseport/syborg/bootstrap/syborg.s	Fri May 14 16:38:13 2010 +0100
+++ b/baseport/syborg/bootstrap/syborg.s	Thu May 27 00:38:17 2010 +0300
@@ -183,6 +183,7 @@
 		HW_MAPPING		KHwBaseNand,    		1,	HW_MULT_4K
 		HW_MAPPING		KHwBaseAudio,    		1,	HW_MULT_4K
 		HW_MAPPING		KHwBaseWebcamera,    		1,	HW_MULT_4K
+		HW_MAPPING		KHwNVMemoryDevice,		1,	HW_MULT_4K
 		HW_MAPPING		KHwBasePlatform,    		8,	HW_MULT_4K
 	
 		DCD     0   ; terminator
--- a/baseport/syborg/estart.txt	Fri May 14 16:38:13 2010 +0100
+++ b/baseport/syborg/estart.txt	Thu May 27 00:38:17 2010 +0300
@@ -1,1 +1,7 @@
-C: 0  ELOCAL FAT  0       FS_FORMAT_COLD,FS_SYNC_DRIVE # IRAM
+#
+# QEMU SYBORG ESTART.TXT
+#
+
+D:  0  ELOCAL  FAT   0       FS_FORMAT_COLD,FS_SYNC_DRIVE       # IRAM
+C:  1  ELOCAL  FAT   0       FS_FORMAT_CORRUPT,FS_NOT_RUGGED    # NVMEM
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/baseport/syborg/mednvmemory/mednvmemory.mmp	Thu May 27 00:38:17 2010 +0300
@@ -0,0 +1,48 @@
+/*
+* Copyright (c) 2010 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:
+*
+*/
+
+#include <variant.mmh>
+#include "kernel/kern_ext.mmh"
+
+TARGET			VariantTarget(mednvmemory,pdd)
+TARGETTYPE		pdd
+//TARGETTYPE		kext
+ROMTARGET		nvmemory.dll
+
+SYMBIAN_BASE_SYSTEMINCLUDE(drivers)
+SYSTEMINCLUDE	AsspNKernIncludePath
+
+SOURCEPATH		.
+SOURCE			syborg_mednvmemory.cpp
+
+//LIBRARY			ekern.lib
+LIBRARY			PlatformLib
+LIBRARY			elocd.lib
+
+//NOEXPORTLIBRARY
+
+//DEFFILE			../e32/~/empty.def
+//DEFFILE			./~/exkey.def
+
+//NOSTRICTDEF
+
+epocallowdlldata
+
+UID				0x100039cf 0x100000db
+VENDORID        0x70000001
+
+CAPABILITY		all
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/baseport/syborg/mednvmemory/syborg_mednvmemory.cpp	Thu May 27 00:38:17 2010 +0300
@@ -0,0 +1,773 @@
+/*
+* Copyright (c) 2010 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 - contribution.
+*
+* Contributors:
+*
+* Description: Minimalistic non volatile memory driver
+*
+*/
+
+
+#include "locmedia.h"
+#include "platform.h"
+#include "variantmediadef.h"
+#include "syborg_mednvmemory.h"
+#include "syborg.h"
+
+_LIT(KNVMemPddName, "Media.MEDNVMEMORY");
+_LIT(KNVMemDriveName,NVMEM1_DRIVENAME);
+
+class DPhysicalDeviceMediaNVMemory : public DPhysicalDevice
+	{
+public:
+	DPhysicalDeviceMediaNVMemory();
+public:
+	// Implementing the interface
+	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);
+	};
+								
+class DMediaDriverNVMemory : public DMediaDriver
+	{
+public:
+	DMediaDriverNVMemory(TInt aMediaId);
+public:
+	// Implementing the interface
+	virtual TInt Request(TLocDrvRequest& aRequest);
+	virtual void Disconnect(DLocalDrive* aLocalDrive, TThreadMessage* aMsg);
+	virtual TInt PartitionInfo(TPartitionInfo &anInfo);
+	virtual void NotifyPowerDown();
+	virtual void NotifyEmergencyPowerDown();
+public:
+	void CompleteRequest(TInt aReason);
+	TInt DoCreate(TInt aMediaId);
+	TInt Caps(TLocDrvRequest& aRequest);
+	TInt Read();
+	TInt Write();
+	TInt Format();
+	static void TransactionLaunchDfc(TAny* aMediaDriver);
+	void DoTransactionLaunchDfc();
+	static void SessionEndDfc(TAny* aMediaDriver);
+	void DoSessionEndDfc();
+	TUint32 GetNVMemSize( void );
+
+public:
+	TUint32 iLatestTransferSectorCount;
+	TDfc iSessionEndDfc;
+
+private:
+	TInt ContinueTransaction( TUint32 aTransactionSectorOffset, TUint32 aTransactionSectorCount, TUint32 aDirection );
+	static void Isr(TAny* aPtr);
+
+private:
+	TLocDrvRequest* iCurrentRequest;				// Current Request
+	Int64 iTotalLength;
+	Int64 iProsessedLength;
+	Int64 iPos;
+	TPhysAddr iTransferBufferPhys;
+	TUint8* iTransferBufferLin;
+	TUint32 iHead;
+	TUint32 iTail;
+	TUint32 iSplitted;
+	TUint32 iAlignmentOverhead;
+	TBool iReadModifyWrite;
+	TDfc iTransactionLaunchDfc;
+	};
+
+DPhysicalDeviceMediaNVMemory::DPhysicalDeviceMediaNVMemory()
+//
+// Constructor
+//
+	{
+	__DEBUG_PRINT(">DPhysicalDeviceMediaNVMemory::DPhysicalDeviceMediaNVMemory");
+	iUnitsMask=0x1;
+	iVersion=TVersion(KMediaDriverInterfaceMajorVersion,KMediaDriverInterfaceMinorVersion,KMediaDriverInterfaceBuildVersion);
+	}
+
+TInt DPhysicalDeviceMediaNVMemory::Install()
+//
+// Install the Internal NVMem PDD.
+//
+	{
+	__DEBUG_PRINT("DPhysicalDeviceMediaNVMemory::Install()");
+	return SetName(&KNVMemPddName);
+	}
+
+void DPhysicalDeviceMediaNVMemory::GetCaps(TDes8& /*aDes*/) const
+//
+// Return the media drivers capabilities.
+//
+	{
+	__DEBUG_PRINT("DPhysicalDeviceMediaNVMemory::GetCaps()");
+	}
+
+TInt DPhysicalDeviceMediaNVMemory::Create(DBase*& aChannel, TInt aMediaId, const TDesC8* /* anInfo */,const TVersion &aVer)
+//
+// Create an Internal Ram media driver.
+//
+	{
+	__DEBUG_PRINT("DPhysicalDeviceMediaNVMemory::Create()");
+	if (!Kern::QueryVersionSupported(iVersion,aVer))
+		return KErrNotSupported;
+	TInt r=KErrNoMemory;
+	DMediaDriverNVMemory* pD=new DMediaDriverNVMemory(aMediaId);
+	aChannel=pD;
+	if (pD)
+		{
+		r=pD->DoCreate(aMediaId);
+		}
+	if( r==KErrNone )
+		{
+		pD->OpenMediaDriverComplete(KErrNone);
+		}
+
+	return r;
+	}
+
+TInt DPhysicalDeviceMediaNVMemory::Validate(TInt aDeviceType, const TDesC8* /*anInfo*/, const TVersion& aVer)
+	{
+	__DEBUG_PRINT("DPhysicalDeviceMediaNVMemory::Validate()");
+	if (!Kern::QueryVersionSupported(iVersion,aVer))
+		return KErrNotSupported;
+	if (aDeviceType!=EFixedMedia1)
+		return KErrNotSupported;
+	return KErrNone;
+	}
+
+TInt DPhysicalDeviceMediaNVMemory::Info(TInt aFunction, TAny*)
+//
+// Return the priority of this media driver
+//
+	{
+	__DEBUG_PRINT("DPhysicalDeviceMediaNVMemory::Info()");
+	if (aFunction==EPriority)
+		return KMediaDriverPriorityNormal;
+	return KErrNotSupported;
+	}
+
+DMediaDriverNVMemory::DMediaDriverNVMemory(TInt aMediaId)
+//
+// Constructor.
+//
+	:	DMediaDriver(aMediaId),
+		iSessionEndDfc(DMediaDriverNVMemory::SessionEndDfc, this, 1),
+		iTransferBufferPhys(0),
+		iTransactionLaunchDfc(DMediaDriverNVMemory::TransactionLaunchDfc, this, KMaxDfcPriority)
+	{
+	__DEBUG_PRINT("DMediaDriverNVMemory::DMediaDriverNVMemory()");
+	}
+
+TInt DMediaDriverNVMemory::DoCreate(TInt /*aMediaId*/)
+//
+// Create the media driver.
+//
+	{
+	__DEBUG_PRINT(">DMediaDriverNVMemory::DoCreate");
+	TInt r = KErrNone; 
+	// Inform our size
+	Int64 size=GetNVMemSize()<<KDiskSectorShift;
+	if( size<=0 )
+		{
+		Kern::Fault("DMediaDriverNVMemory zero size nv memory array", 0);
+		}
+	SetTotalSizeInBytes(size);
+	// Some dfc initialization
+	if( r==KErrNone )
+		{
+		iSessionEndDfc.SetDfcQ( this->iPrimaryMedia->iDfcQ );
+		iTransactionLaunchDfc.SetDfcQ( this->iPrimaryMedia->iDfcQ );
+		}
+	// Create our piece of physically contiguous transfer buffer. 
+	r = Epoc::AllocPhysicalRam( KNVMemTransferBufferSize, iTransferBufferPhys );
+	if( r != KErrNone )
+		{
+		Kern::Fault("DMediaDriverNVMemory Allocate Ram %d",r);
+		}
+
+    DPlatChunkHw* bufChunk = NULL;
+
+    // Create HW Memory Chunk
+    r = DPlatChunkHw::New( bufChunk, iTransferBufferPhys, KNVMemTransferBufferSize, EMapAttrUserRw | EMapAttrFullyBlocking );
+
+    if( r != KErrNone )
+        {
+        // Check Physical Memory
+        if( iTransferBufferPhys )
+			{
+            // Free Physical Memory
+            Epoc::FreePhysicalRam( iTransferBufferPhys, KNVMemTransferBufferSize );
+			}
+		Kern::Fault("DMediaDriverNVMemory error in creating transfer buffer", r);
+        }
+
+    // Set Main Buffer Pointer
+    iTransferBufferLin = reinterpret_cast<TUint8*>(bufChunk->LinearAddress());
+
+  	// Inform "hardware" about the shared memory
+  	WriteReg( KHwNVMemoryDevice, R_NVMEM_SHARED_MEMORY_BASE, iTransferBufferPhys );
+  	WriteReg( KHwNVMemoryDevice, R_NVMEM_SHARED_MEMORY_SIZE, KNVMemTransferBufferSize );
+  	WriteReg( KHwNVMemoryDevice, R_NVMEM_ENABLE, 1 );
+
+	// Set up interrupt service
+  	r = Interrupt::Bind( EIntNVMemoryDevice, Isr, this );
+  	Interrupt::Enable( EIntNVMemoryDevice );
+
+
+	__DEBUG_PRINT("<DMediaDriverNVMemory::DoCreate %d", r);
+	return(r);
+	}
+
+TInt DMediaDriverNVMemory::Request(TLocDrvRequest& m)
+	{
+	TInt request=m.Id();
+	__DEBUG_PRINT(">DMediaDriverNVMemory::Request %d",request);
+	TInt r=KErrNone;
+	
+	// Requests that can be handled synchronously
+	if( request == DLocalDrive::ECaps ) 
+		{
+		r=Caps(m);
+		return r;
+		}
+
+	// All other requests must be deferred if a request is currently in progress
+	if (iCurrentRequest)
+		{
+		// a request is already in progress, so hold on to this one
+		r = KMediaDriverDeferRequest;
+		}
+	else
+		{
+
+		iCurrentRequest=&m;
+		iProsessedLength = 0;
+		iHead = 0;
+		iTail = 0;
+		iSplitted = 0;
+		iAlignmentOverhead = 0;
+
+		iPos = m.Pos();
+		iTotalLength = m.Length();
+
+
+		__DEBUG_PRINT(">DMediaDriverNVMemory::Request pos:0x%lx len:0x%lx", iPos, iTotalLength);
+		if( iTotalLength<0 || iPos<0 )
+			{
+			Kern::Fault("DMediaDriverNVMemory::Request: illegal access!", 0);
+			}
+		// Handle unaligned operations
+		iHead = iPos % KDiskSectorSize;
+		TUint32 tailAlignment = ((iHead + iTotalLength) % KDiskSectorSize);
+		if( tailAlignment )
+			{
+			iTail = KDiskSectorSize - tailAlignment;
+			}
+
+		iSplitted = (iTotalLength + iHead + iTail) / KNVMemTransferBufferSize;
+
+		__DEBUG_PRINT(">DMediaDriverNVMemory::Request head: %d tail: %d splitted: %d\n", iHead, iTail, iSplitted );
+		__DEBUG_PRINT(">DMediaDriverNVMemory::Request partitionlen: %lx", iCurrentRequest->Drive()->iPartitionLen );
+
+		if( (iTotalLength + iPos) > iCurrentRequest->Drive()->iPartitionLen )
+			{
+			Kern::Fault("DMediaDriverNVMemory::Request: Access over partition boundary!", 0);
+			}
+		if( iTotalLength > KMaxTInt32 )
+			{
+			Kern::Fault("DMediaDriverNVMemory::Request: Access length overflow!", 0);
+			}
+		switch (request)
+			{
+			case DLocalDrive::ERead:
+			case DLocalDrive::EWrite:
+			case DLocalDrive::EFormat:
+				__DEBUG_PRINT("DMediaDriverNVMemory::Request iTransactionLaunchDfc.Enque()>");
+				iTransactionLaunchDfc.Enque();
+				__DEBUG_PRINT("DMediaDriverNVMemory::Request iTransactionLaunchDfc.Enque()<");
+			break;
+			case DLocalDrive::EEnlarge:
+			case DLocalDrive::EReduce:
+			default:
+				r=KErrNotSupported;
+			break;
+			}
+		}
+
+	__DEBUG_PRINT("<DMediaDriverNVMemory::Request %d",r);
+	return r;
+	}
+
+void DMediaDriverNVMemory::CompleteRequest(TInt aReason)
+//
+// completes the request which is being currently processed
+//
+	{
+	__DEBUG_PRINT("DMediaDriverNVMemory::CompleteRequest() reason: %d", aReason);
+	TLocDrvRequest* pR=iCurrentRequest;
+	if (pR)
+		{
+		iCurrentRequest=NULL;
+		DMediaDriver::Complete(*pR,aReason);
+		}
+	}
+
+void DMediaDriverNVMemory::Disconnect( DLocalDrive* aLocalDrive, TThreadMessage* aMsg )
+	{
+	__DEBUG_PRINT(">DMediaDriverNVMemory::Disconnect()");
+	// Complete using the default implementation
+	DMediaDriver::Disconnect(aLocalDrive, aMsg);
+	__DEBUG_PRINT("<DMediaDriverNVMemory::Disconnect()");
+	}
+
+void DMediaDriverNVMemory::NotifyPowerDown()
+	{
+	__DEBUG_PRINT("DMediaDriverNVMemory::NotifyPowerDown()");
+	// no action required
+	}
+
+void DMediaDriverNVMemory::NotifyEmergencyPowerDown()
+	{
+	__DEBUG_PRINT("DMediaDriverNVMemory::NotifyEmergencyPowerDown()");
+	// no action required
+	}
+
+TInt DMediaDriverNVMemory::Caps(TLocDrvRequest& m)
+	{
+	__DEBUG_PRINT("DMediaDriverNVMemory::Caps()");
+	TLocalDriveCapsV6& caps=*(TLocalDriveCapsV6*)m.RemoteDes();
+	caps.iType=EMediaHardDisk;
+	caps.iConnectionBusType=EConnectionBusInternal;
+	caps.iDriveAtt=KDriveAttLocal|KDriveAttInternal;
+	caps.iMediaAtt=KMediaAttFormattable;
+	caps.iFileSystemId=KDriveFileSysFAT;
+	caps.iPartitionType=KPartitionTypeFAT16;
+	caps.iSize=m.Drive()->iPartitionLen;
+	caps.iHiddenSectors=0;
+	caps.iEraseBlockSize = KNVMemTransferBufferSize; 
+	caps.iBlockSize=KDiskSectorSize;
+	caps.iMaxBytesPerFormat = KNVMemTransferBufferSize;
+
+	return KErrCompletion;									
+	}
+
+TInt DMediaDriverNVMemory::Read()
+	{
+	__DEBUG_PRINT(">DMediaDriverNVMemory::Read() pos: %lx, size: %lx", iPos, iTotalLength);
+	// Set our sector offset
+	TUint32 transactionSectorOffset = (TUint32)(iPos / KDiskSectorSize); 
+	TUint32 transactionLength = 0;
+	TUint32 transactionDirection = NVMEM_TRANSACTION_READ;
+	// Do we have an operation longer than our shared memory?
+	if( iSplitted > 0 )
+		{
+		transactionLength = KNVMemTransferBufferSize;
+		}
+	else
+		{
+		// Do the whole operation in one go since we have enough room in our memory
+		transactionLength = I64LOW(iTotalLength);
+		// Read the "broken" tail sector
+		if( iTail )
+			{
+			transactionLength += iTail;
+			iAlignmentOverhead += iTail;
+			}
+		}
+	// Read the "broken" head sector
+	if( iHead > 0 )
+		{
+		transactionLength += iHead;
+		iAlignmentOverhead += iHead;
+		}
+
+	// We should be ok to continue
+	ContinueTransaction( transactionSectorOffset, transactionLength/KDiskSectorSize, transactionDirection );
+	__DEBUG_PRINT("<DMediaDriverNVMemory::Read()");
+	return KErrNone;
+	}
+
+TInt DMediaDriverNVMemory::Write()
+	{
+	__DEBUG_PRINT("DMediaDriverNVMemory::Write() pos: 0x%lx, size: 0x%lx", iPos, iTotalLength);
+	TInt r = KErrNone;
+	// Set our sector offset
+	TUint32 transactionSectorOffset = (TUint32)(iPos / KDiskSectorSize); 
+	TUint32 transactionLength = 0;
+	TUint32 transactionDirection = NVMEM_TRANSACTION_WRITE;
+	// Do we have an operation longer than our shared memory?
+	if( iSplitted > 0 )
+		{
+		transactionLength = KNVMemTransferBufferSize;
+		}
+	else
+		{
+		// Do the whole operation in one go since we have enough room in our memory
+		transactionLength = I64LOW(iTotalLength);
+		if( iTail )
+			{
+			iReadModifyWrite = ETrue;
+			// Read the "broken" tail sector
+			transactionLength += iTail;
+			iAlignmentOverhead += iTail;
+			}
+		}
+	// Is there a need to read modify write the "broken" head sector of the operation
+	if( iHead > 0 )
+		{
+		iReadModifyWrite = ETrue;
+		// If splitted operation we only need the broken sector
+		if( iSplitted > 0 )
+			{
+			transactionLength = KDiskSectorSize;
+			iAlignmentOverhead += iHead;
+			}
+		else
+			{
+			// Read the "broken" head sector in addition to everything else
+			transactionLength += iHead;
+			iAlignmentOverhead += iHead;
+			}
+		}
+	
+	// Was there a need to read-modify before writing
+	if( iReadModifyWrite )
+		{
+		transactionDirection = NVMEM_TRANSACTION_READ;
+		}
+	else
+		{
+		// Handle format here
+		if( iCurrentRequest->Id() == DLocalDrive::EFormat )
+			{
+			// Not much handling just flow through since we have filled the shared memory with zeroes already
+			}
+		else
+			{
+			// Read from client
+			TPtr8 targetDescriptor(iTransferBufferLin, transactionLength);
+			r = iCurrentRequest->ReadRemote(&targetDescriptor,0);
+			}
+		}
+	
+	// We should be ok to continue
+	ContinueTransaction( transactionSectorOffset, transactionLength/KDiskSectorSize, transactionDirection );
+
+	return r;
+	}
+
+
+TInt DMediaDriverNVMemory::Format()
+	{
+	__DEBUG_PRINT("DMediaDriverNVMemory::Format() pos: 0x%lx, size: 0x%lx", iPos, iTotalLength);
+	memset( iTransferBufferLin, 0x00, KNVMemTransferBufferSize );
+	// Stop the nonsense here. Write operations should be used for partial sector data removal operations
+	if( iHead > 0 || iTail > 0 )
+		{
+		Kern::Fault("DMediaDriverNVMemory::Format: alignment violation!", 0);
+		}
+	Write();
+//	DoTransaction( m, NVMEM_TRANSACTION_WRITE );
+	return KErrNone;
+	}
+
+TInt DMediaDriverNVMemory::ContinueTransaction( TUint32 aTransactionSectorOffset, TUint32 aTransactionSectorCount, TUint32 aTransactionDirection )
+	{
+	__DEBUG_PRINT("DMediaDriverNVMemory::ContinueTransaction() sectoroffset: %d, sectorcount: %d, direction: %d", aTransactionSectorOffset, aTransactionSectorCount, aTransactionDirection);
+	if( aTransactionDirection != NVMEM_TRANSACTION_UNDEFINED )
+		{
+	  	WriteReg( KHwNVMemoryDevice, R_NVMEM_TRANSACTION_OFFSET, aTransactionSectorOffset );
+	  	WriteReg( KHwNVMemoryDevice, R_NVMEM_TRANSACTION_SIZE, aTransactionSectorCount );
+	  	WriteReg( KHwNVMemoryDevice, R_NVMEM_TRANSACTION_DIRECTION, aTransactionDirection );
+	  	WriteReg( KHwNVMemoryDevice, R_NVMEM_TRANSACTION_EXECUTE, aTransactionDirection );
+		}
+	else
+		{
+		Kern::Fault("DMediaDriverNVMemory::ContinueTransaction: Undefined transaction!", 0);
+		}
+	return KErrNone;
+	}
+
+
+TInt DMediaDriverNVMemory::PartitionInfo(TPartitionInfo& anInfo)
+//
+// Return partition information on the media.
+//
+	{
+	__DEBUG_PRINT("DMediaDriverNVMemory::PartitionInfo()");
+	anInfo.iPartitionCount=1;
+	anInfo.iEntry[0].iPartitionBaseAddr=0;
+	anInfo.iEntry[0].iPartitionLen=anInfo.iMediaSizeInBytes=TotalSizeInBytes();
+	anInfo.iEntry[0].iPartitionType=KPartitionTypeFAT16;
+	return KErrCompletion;
+	}
+
+void DMediaDriverNVMemory::TransactionLaunchDfc(TAny* aMediaDriver)
+	{
+	static_cast<DMediaDriverNVMemory*>(aMediaDriver)->DoTransactionLaunchDfc();
+	}
+
+void DMediaDriverNVMemory::DoTransactionLaunchDfc()
+	{
+	__DEBUG_PRINT(">DMediaDriverNVMemory::DoTransactionLaunchDfc()");
+	TInt request = iCurrentRequest->Id();
+	TInt r(KErrNone);
+	switch (request)
+		{
+		case DLocalDrive::ERead:
+			r=Read();
+		break;
+		case DLocalDrive::EWrite:
+			r=Write();
+		break;
+		case DLocalDrive::EFormat:
+			r=Format();
+		break;
+		case DLocalDrive::EEnlarge:
+		case DLocalDrive::EReduce:
+		default:
+			r=KErrNotSupported;
+		break;
+		}
+	if( r != KErrNone )
+		{
+		// TODO some proper error handling here
+		}
+	__DEBUG_PRINT("<MediaDriverNVMemory::DoTransactionLaunchDfc %d",r);
+	}
+
+void DMediaDriverNVMemory::SessionEndDfc(TAny* aMediaDriver)
+	{
+	static_cast<DMediaDriverNVMemory*>(aMediaDriver)->DoSessionEndDfc();
+	}
+
+void DMediaDriverNVMemory::DoSessionEndDfc()
+	{
+	__DEBUG_PRINT(">DMediaDriverNVMemory::DoSessionEndDfc()");
+	TInt r = KErrNone;
+	// Check that we have a request in process
+	if( iCurrentRequest )
+		{
+		// Transaction variables
+		TUint32 transactionSectorOffset(0);
+		TUint32 transactionLength(0);
+		TUint32 transactionDirection( NVMEM_TRANSACTION_UNDEFINED );
+		// How much did we actually transfer? 
+		TUint32 latestTransferSize = (iLatestTransferSectorCount * KDiskSectorSize);
+		__DEBUG_PRINT("DMediaDriverNVMemory::DoSessionEndDfc() latestTransferSize: %d", latestTransferSize );
+		// Subtract alignment overhead
+		latestTransferSize = latestTransferSize - iAlignmentOverhead;
+		// For decision whether the buffer is ready for operation already
+		TBool bufferReady(EFalse);
+		// For decision whether we have finished the latest request
+		TBool sessionComplete(EFalse);
+
+		// Was there a read-modify-write (RWM) for which we need to do some buffer manipulation before proceeding?
+		// Note that in case of format we triggered to alignment violation in earlier method already and can not enter to following 
+		// condition when there is a format operation going on
+		if( iReadModifyWrite )
+			{
+			bufferReady = ETrue;
+			iReadModifyWrite = EFalse;
+			// Was it a splitted operation for which we only need to take care of the broken head sector.
+			if( iSplitted > 0 )
+				{
+				// We have a sector here here filled with data from mass memory. Modify with client data.
+				__DEBUG_PRINT("DMediaDriverNVMemory::DoSessionEndDfc() readremote splitted: %d head: %d", latestTransferSize, iHead );
+				TPtr8 targetDescriptor(&iTransferBufferLin[iHead], KNVMemTransferBufferSize - iHead);
+				r = iCurrentRequest->ReadRemote(&targetDescriptor,0);
+				}
+			// Else we need to take care of both head and tail
+			else
+				{
+				// We have a piece of data read from mass memory. Modify with client data.
+				__DEBUG_PRINT("DMediaDriverNVMemory::DoSessionEndDfc() readremote: %d head: %d", I64LOW(iTotalLength - iProsessedLength), iHead );
+				TPtr8 targetDescriptor(&iTransferBufferLin[iHead], I64LOW(iTotalLength - iProsessedLength));
+				r = iCurrentRequest->ReadRemote(&targetDescriptor,0);
+//				latestTransferSize -= (KDiskSectorSize - iTail);
+				iTail = 0;
+				}
+			}
+		else
+			{
+			// Overhead is processed when we enter here
+			iAlignmentOverhead = 0;
+			// Update position
+			iPos += latestTransferSize;
+			// Save the information on how many bytes we transferred already
+			iProsessedLength += latestTransferSize; 
+			// Update the splitted information. We don't take head into account here anymore since it is already taken care of
+			iSplitted = (iTotalLength - iProsessedLength + iTail) / KNVMemTransferBufferSize;
+			// Check if we have done already
+			if( iProsessedLength >= iTotalLength )
+				{
+				// If this was the final transfer for this request let's take tail into account as well (if not taken already)
+				// iProsessedLength -= iTail;
+				// latestTransferSize -= iTail;
+				if( iProsessedLength > iTotalLength )
+					{
+					Kern::Fault("DMediaDriverNVMemory: Illegal transfer operation!", 0);
+					}
+				sessionComplete = ETrue;
+				}
+			}
+
+		TInt request = iCurrentRequest->Id();
+
+		// Set our sector offset
+		transactionSectorOffset = (TUint32)(iPos / KDiskSectorSize); 
+		
+		if( bufferReady )
+			{
+			// Write as much as we read in RMW operation
+			transactionLength = (iLatestTransferSectorCount * KDiskSectorSize);
+			}
+		else
+			{
+			// Do we have an operation longer than our shared memory?
+			if( iSplitted > 0 )
+				{
+				transactionLength = KNVMemTransferBufferSize;
+				}
+			else
+				{
+				// Do the whole operation in one go since we have enough room in our memory
+				transactionLength = I64LOW(iTotalLength - iProsessedLength);
+				// Read the "broken" tail sector
+				if( iTail > 0 && request == DLocalDrive::EWrite )
+					{
+					iReadModifyWrite = ETrue;
+					// Read the "broken" tail sector
+					transactionLength += iTail;
+	   				iAlignmentOverhead = iTail;
+	   				}
+				}
+			}
+		
+		// Was there a need to read-modify before writing
+		if( iReadModifyWrite )
+			{
+			transactionDirection = NVMEM_TRANSACTION_READ;
+			}
+		else
+			{
+			if( request == DLocalDrive::ERead )
+				{
+				transactionDirection = NVMEM_TRANSACTION_READ;
+				// Write to client
+				__DEBUG_PRINT("DMediaDriverNVMemory::DoSessionEndDfc() WriteRemote: %d head: %d", latestTransferSize, iHead );
+				TPtrC8 sourceDescriptor(&iTransferBufferLin[iHead], latestTransferSize);
+				r = iCurrentRequest->WriteRemote( &sourceDescriptor, 0 );
+				}
+			// Head is processed
+			iHead = 0;
+			if( request == DLocalDrive::EWrite && !sessionComplete )
+				{
+				transactionDirection = NVMEM_TRANSACTION_WRITE;
+				if( bufferReady )
+					{
+					// Actually no need for any actions here
+					}
+				else
+					{
+					// Prepare a buffer for transfer
+					__DEBUG_PRINT("DMediaDriverNVMemory::DoSessionEndDfc() ReadRemote: %d head: %d", latestTransferSize, iHead );
+					TPtr8 targetDescriptor(iTransferBufferLin, transactionLength);
+					r = iCurrentRequest->ReadRemote(&targetDescriptor,0);
+					}
+				}
+			if( request == DLocalDrive::EFormat )
+				{
+				transactionDirection = NVMEM_TRANSACTION_WRITE;
+				}
+			}
+		if( sessionComplete )
+			{
+			CompleteRequest( r );
+			}
+		else
+			{
+			ContinueTransaction( transactionSectorOffset, transactionLength/KDiskSectorSize, transactionDirection );
+			}
+		}
+	else
+		{
+		// Let's just flow through for now
+		}
+
+	__DEBUG_PRINT("<DMediaDriverNVMemory::DoSessionEndDfc()" );
+	}
+
+
+TUint32  DMediaDriverNVMemory::GetNVMemSize( void )
+	{
+	__DEBUG_PRINT("DMediaDriverNVMemory::GetNVMemSize()");
+	TUint32 sizeInSectors = ReadReg( KHwNVMemoryDevice, R_NVMEM_NV_MEMORY_SIZE );
+	return sizeInSectors; 
+	}
+
+void DMediaDriverNVMemory::Isr(TAny* aPtr)
+	{
+	__DEBUG_PRINT(">DMediaDriverNVMemory::Isr");
+
+    DMediaDriverNVMemory* nvMem = reinterpret_cast<DMediaDriverNVMemory*>(aPtr);
+
+	// Save the amount of transferred sectors. This clears the interrupt from HW as well
+	nvMem->iLatestTransferSectorCount = ReadReg( KHwNVMemoryDevice, R_NVMEM_STATUS );
+
+	// Clear from framework
+	Interrupt::Clear( EIntNVMemoryDevice );
+
+	nvMem->iSessionEndDfc.Add();
+	}
+
+
+DECLARE_EXTENSION_PDD()
+	{
+	__DEBUG_PRINT(">MediaDriverNVMemory create device");
+	return new DPhysicalDeviceMediaNVMemory;
+	}
+
+static const TInt NVMemDriveNumbers[NVMEM1_DRIVECOUNT]={NVMEM1_DRIVELIST};	
+
+DECLARE_STANDARD_EXTENSION()
+	{
+	__DEBUG_PRINT("Registering NVMEM drive");
+	TInt r=KErrNoMemory;
+
+	DPrimaryMediaBase* pM=new DPrimaryMediaBase;
+
+	TDynamicDfcQue* NVMemoryDfcQ;
+	 
+	r = Kern::DynamicDfcQCreate( NVMemoryDfcQ, KNVMemDfcThreadPriority, KNVMemDriveName );
+
+	if( r == KErrNone )
+		{
+		pM->iDfcQ = NVMemoryDfcQ;
+		}
+	else
+		{
+		__DEBUG_PRINT("NVMEM DFCQ initialization failed");
+		}
+
+	if (pM)
+		{
+		r=LocDrv::RegisterMediaDevice(EFixedMedia1,NVMEM1_DRIVECOUNT,&NVMemDriveNumbers[0],pM,NVMEM1_NUMMEDIA,KNVMemDriveName);
+		}
+
+	pM->iMsgQ.Receive();
+
+	__DEBUG_PRINT("Registering NVMEM drive - return %d",r);
+
+	return r;
+	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/baseport/syborg/mednvmemory/syborg_mednvmemory.h	Thu May 27 00:38:17 2010 +0300
@@ -0,0 +1,60 @@
+/*
+* Copyright (c) 2010 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: Minimalistic non volatile memory driver
+*
+*/
+
+#ifndef _SYBORG_MEDNVMEMORY_H
+#define _SYBORG_MEDNVMEMORY_H
+
+#include <kpower.h>
+#include <e32keys.h>
+#include <system.h>
+
+//#define DEBUG_MEDNVMEMORY
+#ifdef DEBUG_MEDNVMEMORY
+#define __DEBUG_PRINT(format...)    Kern::Printf(format)
+#else
+#define __DEBUG_PRINT(format...)    __KTRACE_OPT(KLOCDRV,Kern::Printf(format))
+#endif
+
+#define R_NVMEM_ID                                0x0000
+#define R_NVMEM_TRANSACTION_OFFSET                0x0004
+#define R_NVMEM_TRANSACTION_SIZE                  0x0008
+#define R_NVMEM_TRANSACTION_DIRECTION             0x000c
+#define R_NVMEM_TRANSACTION_EXECUTE               0x0010
+#define R_NVMEM_SHARED_MEMORY_BASE                0x0014
+#define R_NVMEM_NV_MEMORY_SIZE                    0x0018
+#define R_NVMEM_SHARED_MEMORY_SIZE                0x001c
+#define R_NVMEM_STATUS                            0x0020
+#define R_NVMEM_ENABLE                            0x0024
+#define R_NVMEM_LASTREG                           0x0028  // not a register, address of last register
+
+#define NVMEM_TRANSACTION_UNDEFINED 0
+#define NVMEM_TRANSACTION_READ 1
+#define NVMEM_TRANSACTION_WRITE 2
+
+// 512 Byte sectors
+const TInt KDiskSectorShift	= 9;
+const TInt KDiskSectorSize	= 0x200;
+
+// Dfc thread priority 
+const TInt KNVMemDfcThreadPriority = 24;
+
+// Transfer buffer size 256kBytes 
+const TInt KNVMemTransferBufferSize = 0x40000;
+// Transfer buffer size in sectors
+const TInt KNVMemTransferBufferSectorCount = KNVMemTransferBufferSize/KDiskSectorSize;
+
+#endif
--- a/baseport/syborg/rom/kernel.iby	Fri May 14 16:38:13 2010 +0100
+++ b/baseport/syborg/rom/kernel.iby	Thu May 27 00:38:17 2010 +0300
@@ -68,6 +68,9 @@
 device[VARID]=		\epoc32\release\##KMAIN##\##BUILD##\_##VARIANT##_ewebcamera.LDD    	\sys\bin\ewebcamera.LDD
 file=			\epoc32\release\##KMAIN##\##BUILD##\webcamera_app.exe			\sys\bin\webcamera_app.exe
 
+/* Generic nonvolatile memory */
+extension[VARID]=	\epoc32\release\##KMAIN##\##BUILD##\_##VARIANT##_MEDNVMEMORY.PDD	    	\sys\bin\MEDNVMEMORY.PDD
+
 // Estart
 data=               	\epoc32\rom\syborg\ESTART.TXT					    \sys\data\ESTART.TXT
 
--- a/baseport/syborg/specific/syborg.h	Fri May 14 16:38:13 2010 +0100
+++ b/baseport/syborg/specific/syborg.h	Thu May 27 00:38:17 2010 +0300
@@ -53,7 +53,8 @@
 const TUint KHwSVPNandDevice			= KHwBasePeripherals + 0x0d*KHwLinSeparation;
 const TUint KHwSVPAudioDevice			= KHwBasePeripherals + 0x0e*KHwLinSeparation;
 const TUint KHwSVPWebcameraDevice		= KHwBasePeripherals + 0x0f*KHwLinSeparation;
-const TUint KHwSVPPlatformDevice		= KHwBasePeripherals + 0x10*KHwLinSeparation;
+const TUint KHwNVMemoryDevice			= KHwBasePeripherals + 0x10*KHwLinSeparation;
+const TUint KHwSVPPlatformDevice		= KHwBasePeripherals + 0x11*KHwLinSeparation;
 	
 enum TSyborgInterruptId
 {
@@ -68,7 +69,8 @@
   EIntSerial2 = 7,
   EIntSerial3 = 8,
   EIntNet0 = 9,
-  EIntAudio0 = 10
+  EIntAudio0 = 10,
+  EIntNVMemoryDevice = 12
 };
 
 // Timer Mode
--- a/baseport/syborg/specific/variantmediadef.h	Fri May 14 16:38:13 2010 +0100
+++ b/baseport/syborg/specific/variantmediadef.h	Thu May 27 00:38:17 2010 +0300
@@ -20,8 +20,14 @@
 
 // Variant parameters for IRAM Media Driver (MEDINT.PDD)
 #define IRAM_DRIVECOUNT 1
-#define IRAM_DRIVELIST  0       // C:
+#define IRAM_DRIVELIST  0       // D:
 #define IRAM_NUMMEDIA   1	
 #define IRAM_DRIVENAME "IRam"
 
+// Variant parameters for non volatile memory Media Driver (MEDNVMEMORY.PDD)
+#define NVMEM1_DRIVECOUNT		1
+#define NVMEM1_DRIVELIST		1 // C:
+#define NVMEM1_NUMMEDIA         1	
+#define NVMEM1_DRIVENAME "NVMem"
+
 #endif  // __VARIANTMEDIADEF_H__
Binary file baseport/syborg/syborg.dtb has changed
--- a/baseport/syborg/syborg.dts	Fri May 14 16:38:13 2010 +0100
+++ b/baseport/syborg/syborg.dts	Thu May 27 00:38:17 2010 +0300
@@ -121,9 +121,18 @@
             interrupts = <b>;
             interrupt-parent = <&intc>;
         };
+        nvmemorydevice@0 {
+            compatible = "syborg,nvmemorydevice";
+            drive_size = <4000000>;
+            sector_size = <200>;
+            drive_image_name = "syborg_system.img";
+            reg = <c0010000>;
+            interrupts = <c>;
+            interrupt-parent = <&intc>;
+        };
         platform@0 {
             compatible = "syborg,platform";
-            reg = <c0010000>;
+            reg = <c0011000>;
         };
     };
 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/symbian-qemu-0.9.1-12/model-libraries/commoninc/platformtypes.h	Thu May 27 00:38:17 2010 +0300
@@ -0,0 +1,19 @@
+#ifndef PLATFORMTYPES_H
+#define PLATFORMTYPES_H
+
+// TODO: We should have a proper type definition file created common for standalone model libraries
+typedef signed __int8         int8_t;
+typedef signed __int16        int16_t;
+typedef signed __int32        int32_t;
+typedef signed __int64        int64_t;
+typedef unsigned __int8     uint8_t;
+typedef unsigned __int8     u_int8_t;
+typedef unsigned __int16    uint16_t;
+typedef unsigned __int16    u_int16_t;
+typedef unsigned __int32    uint32_t;
+typedef unsigned __int32    u_int32_t;
+typedef unsigned __int64    uint64_t;
+typedef unsigned __int64    u_int64_t;
+typedef unsigned char byte_t;
+
+#endif // PLATFORMTYPES_H
Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Debug/BuildLog.htm has changed
Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Debug/app.res has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/symbian-qemu-0.9.1-12/model-libraries/nvmemmory/NVMemory_HowTo.txt	Thu May 27 00:38:17 2010 +0300
@@ -0,0 +1,73 @@
+========================================================================
+    NVMEMORY.DLL - A simple non volatile sector addressed memory device
+                - An example of a portable high abstraction model architecture. 
+                    This DLL is created to serve in multiple different modeling 
+                    environments and tools. Model portability should be taken into 
+                    account when further developing and maintaining this device.
+========================================================================
+
+========================================================================
+    USAGE       nvmemory.dll
+                Example usage provided by syborg_nvmemorydevice.py    
+    
+                1 - Create an instance of SyborgNVMemory class. 
+                    This can be performed either by instantiating the C++ class directly 
+                    by calling the constructor "new SyborgNVMemory( a_sectorsize );".
+                    Or by using the C API to create an instance "nvmem_create( sector_size )".
+                    As you can see you need to set the sector size for your device when you create it.
+                    
+                    In fact each of the API functions are provided in form of both C and C++ API functions.
+                    From this on only the C API is explained.
+                    
+                2 - Reset the device by calling "nvmem_reset( self.obj )". 
+                    This function clears any information stored by the device instance except the sector size.
+                    
+                    Note that for the C API you always need to specify the object which you wish to command.
+                    
+                3 - Create handle to your image file by calling "nvmem_open( self.obj, imagepath )". 
+                    Image is opened in binary mode. Store the handle.
+                    
+                    Note that you need to have an image stored to a path on your PC before you can call this function. 
+                    You must provide the image name and path when calling.
+                    
+                    Note also that there is a service provided by this DLL which can create an image for you. 
+                    NVMEMORY_API int32_t nvmem_create_image( SyborgNVMemory* a_syborg_nvmemory, char* a_memoryarrayname, uint32_t a_sectorcount, uint32_t a_sectorsize = NVMEM_DEFAULT_SECTORSIZE_IN_BYTES );
+                    nvmem_create_image function probably needs further development. You may also create image in your wrapper as done in example usage file.
+                    
+                    You may get your memory device size by calling nvmem_get_sector_count( self.obj, nvmemhandle ). 
+                    nvmemhandle is the handle you got when calling nvmem_open. 
+                    nvmem_get_sector_count is handy in cases where you have provided a readymade image for the device. 
+                    In this case you don't need to go and hardcode the image size each time in your wrapper.
+                
+                4 - Initialize callback. Provide a callback function for the device by calling "nvmem_set_callback( self.obj, nvmem_callback )". 
+                    Where the callback is a function pointer of a type "int (*i_NVMemCallBack)(int);". 
+                    Callback is called by DLL when read and write operations are finished. Parameter is the amount of sectors succesfully read or written.
+                    
+                5 - Start using your device.
+                    nvmem_read(  self.obj, nvmemory_sharedmemory_host_address, nvmemhandle, transaction_offset, transaction_size )
+                    nvmem_write(  self.obj, nvmemory_sharedmemory_host_address, nvmemhandle, transaction_offset, transaction_size )
+                    
+                See syborg_nvmemorydevice.py to learn more about device usage. 
+                    
+========================================================================
+
+
+========================================================================
+    DYNAMIC LINK LIBRARY : nvmemmory Project Overview
+========================================================================
+
+Summary of what you will find in each of the files that
+make up your nvmemmory application.
+
+nvmemmory.vcproj
+    This is the main project file for VC++ projects generated using an Application Wizard. 
+    It contains information about the version of Visual C++ that generated the file, and 
+    information about the platforms, configurations, and project features selected with the
+    Application Wizard.
+
+nvmemmory.cpp
+    This is the main DLL source file.
+
+nvmemmory.h
+    This file contains a class declaration.
+
Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/BuildLog.htm has changed
Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/RCa03000 has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/mt.dep	Thu May 27 00:38:17 2010 +0300
@@ -0,0 +1,1 @@
+Manifest resource last updated at 14:11:35.93 on 26.05.2010 
Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/nvmemmory.dll has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/nvmemmory.dll.intermediate.manifest	Thu May 27 00:38:17 2010 +0300
@@ -0,0 +1,8 @@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+  <dependency>
+    <dependentAssembly>
+      <assemblyIdentity type='win32' name='Microsoft.VC80.CRT' version='8.0.50727.762' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
+    </dependentAssembly>
+  </dependency>
+</assembly>
Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/nvmemmory.exp has changed
Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/nvmemmory.lib has changed
Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/nvmemmory.obj has changed
Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/nvmemmory.pdb has changed
Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/vc80.idb has changed
Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/vc80.pdb has changed
Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/app.ico has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/symbian-qemu-0.9.1-12/model-libraries/nvmemmory/app.rc	Thu May 27 00:38:17 2010 +0300
@@ -0,0 +1,63 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon placed first or with lowest ID value becomes application icon
+
+LANGUAGE 9, 1
+#pragma code_page(1252)
+1           ICON         "app.ico"
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE  
+BEGIN
+    "resource.h\0"
+    "\0"
+END
+
+2 TEXTINCLUDE  
+BEGIN
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE  
+BEGIN
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/symbian-qemu-0.9.1-12/model-libraries/nvmemmory/nvmemmory.cpp	Thu May 27 00:38:17 2010 +0300
@@ -0,0 +1,267 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "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: 
+*
+* Simple non volatile memory device. nvmemmory.cpp
+*
+*/
+
+extern "C" 
+    {
+#include <stdio.h>
+    }
+#include "nvmemmory.h"
+
+SyborgNVMemory::SyborgNVMemory( uint32_t a_sectorsize ):
+    iNVMemSectorSizeInBytes( a_sectorsize )
+    {
+    for( int32_t index = 0; index < NVMEM_MAX_STREAMHANDLES; index += 1 ) 
+        {
+        i_filestream[index] = NULL;
+        }
+    }
+
+SyborgNVMemory::~SyborgNVMemory()
+    {
+    NVMemReset();
+    }
+
+int32_t SyborgNVMemory::NVMemReset( )
+    {
+    /*Initialize the file array*/
+    for( int32_t index = 0; index < NVMEM_MAX_STREAMHANDLES; index += 1 ) 
+        {
+        if( i_filestream[index] != NULL )
+            {
+            fclose( i_filestream[index] );
+            i_filestream[index] = NULL;
+            }
+        }
+    return 0;
+    }
+
+int32_t SyborgNVMemory::NVMemCreateImage( char* a_memoryarrayname, uint32_t a_sectorcount, uint32_t a_sectorsize )
+    {
+    /* Create a temporary MByte buffer array for image creation purpose */
+    const uint32_t tempbufsize = 1024 * 1024;
+    uint8_t tempbuf[ tempbufsize ];
+    uint32_t index = 0;
+    FILE *filestream = NULL;
+    char mode1[4] = {"rb"};
+    char mode2[4] = {"wb"};
+    int32_t ret = NVMEM_ERROR_CREATE;
+    uint32_t temparraysectorcount = tempbufsize / a_sectorsize;
+    iNVMemSectorSizeInBytes = a_sectorsize;
+            
+    /* Try to open the specified file. If it exists we do not create a new one */
+    filestream = fopen( a_memoryarrayname, &mode1[0] );
+    if( filestream == NULL )
+        {
+        /* Fill MBR with zeroes */
+        for( index = 0; index < iNVMemSectorSizeInBytes; index += 1 )
+            {
+            tempbuf[index] = 0;
+            }
+        /* Open a temporary file handle. Create the file*/
+        filestream = fopen( a_memoryarrayname, &mode2[0] );
+
+        if( ret != NULL )
+            {
+            ret = NVMEM_OK;
+            for( index = 0; (index < a_sectorcount) && (ret == NVMEM_OK); index += temparraysectorcount )
+                {
+                /* Print one array of zeroes to our temporary buffer */
+                if( fwrite( tempbuf, iNVMemSectorSizeInBytes, temparraysectorcount, filestream ) < 0 )
+                    {
+                    ret = NVMEM_ERROR_FWRITE;
+                    }
+                }
+            fclose( filestream );
+            }
+        else
+            {
+            ret = NVMEM_ERROR_FOPEN;
+            }
+        }
+    return ret;
+    }
+
+int32_t SyborgNVMemory::NVMemOpen( char* a_memoryarrayname )
+    {
+    char mode[4] = {"rb+"};
+    int32_t handle = NVMEM_ERROR_OUT_OF_FREE_STREAMHANDLES;
+    /* Search for a free handle position and assign if found */
+    int32_t index = 0;
+    for( ; index < NVMEM_MAX_STREAMHANDLES; index += 1 ) 
+        {
+        if( i_filestream[index] == NULL )
+            {
+            i_filestream[index] = fopen( a_memoryarrayname, &mode[0] );
+            if( i_filestream[index] != NULL )
+                {
+                handle = index;
+                printf("handle created: %d\n", index);
+                }
+            else
+                {
+                handle = NVMEM_ERROR_FOPEN;
+                }
+            break;
+            }
+        }
+    return handle;
+    }
+
+int32_t SyborgNVMemory::NVMemClose( int32_t a_memoryarrayhandle )
+    {
+    int32_t result = NVMEM_ERROR_FCLOSE;
+    if( fclose( i_filestream[a_memoryarrayhandle] ) == 0 )
+        {
+        result = NVMEM_OK;
+        }
+    return result;
+    }
+
+int32_t SyborgNVMemory::NVMemFlush( int32_t a_memoryarrayhandle )
+    {
+    int32_t result = NVMEM_ERROR_FFLUSH;
+    if( fflush( i_filestream[a_memoryarrayhandle] ) == 0 )
+        {
+        result = NVMEM_OK;
+        }
+    return result;
+    }
+
+void SyborgNVMemory::NVMemRead( uint32_t *a_client_targetmemoryaddr, int32_t a_memoryarrayhandle, uint32_t a_memoryarraysectoroffset, uint32_t a_sectorcount )
+    {
+    //printf("SyborgNVMemory::NVMemRead: sectorpos:%d sectorcount:%d hostaddr: 0x%08x handle: %d\n", a_memoryarraysectoroffset, a_sectorcount, a_client_targetmemoryaddr, a_memoryarrayhandle );
+    uint32_t items_read = 0;
+    long streamoffset = a_memoryarraysectoroffset * iNVMemSectorSizeInBytes;
+    int32_t result = fseek( i_filestream[a_memoryarrayhandle], streamoffset, SEEK_SET );
+    if( result == 0 )   
+        {
+        items_read = fread( a_client_targetmemoryaddr, iNVMemSectorSizeInBytes, a_sectorcount, i_filestream[a_memoryarrayhandle] );
+        /*Check that everything is read*/
+        if( items_read != a_sectorcount )
+            {
+            result = NVMEM_ERROR_FREAD;
+            }
+        else
+            {
+            result = items_read;
+            }
+        }
+    else /*error*/
+        {
+        result = NVMEM_ERROR_FSEEK;
+        }
+    i_NVMemCallBack( result );
+    }
+
+void SyborgNVMemory::NVMemWrite( uint32_t *a_client_sourcememoryaddr, int32_t a_memoryarrayhandle, uint32_t a_memoryarraysectoroffset, uint32_t a_sectorcount )
+    {
+    //printf("SyborgNVMemory::NVMemWrite: sectorpos:%d sectorcount:%d hostaddr: 0x%08x\n", a_memoryarraysectoroffset, a_sectorcount, a_client_sourcememoryaddr );
+    uint32_t items_written = 0;
+    long streamoffset = a_memoryarraysectoroffset * iNVMemSectorSizeInBytes;
+    int32_t result = fseek( i_filestream[a_memoryarrayhandle], streamoffset, SEEK_SET );
+    if( result == 0 )   
+        {
+        items_written = fwrite( a_client_sourcememoryaddr, iNVMemSectorSizeInBytes, a_sectorcount, i_filestream[a_memoryarrayhandle] );
+        /*Check that everything is written*/
+        if( items_written != a_sectorcount )
+            {
+            result = NVMEM_ERROR_FWRITE;
+            }
+        else
+            {
+            result = items_written;
+            }
+        }
+    else /*error*/
+        {
+        result = NVMEM_ERROR_FSEEK;
+        }
+    i_NVMemCallBack( result );
+    }
+
+uint32_t SyborgNVMemory::NVMemGetSectorCount( int32_t a_memoryarrayhandle )
+    {
+    long byte_size = 0;
+    uint32_t sector_count = 0;
+    printf("use handle: %d\n", a_memoryarrayhandle);
+    fseek( i_filestream[a_memoryarrayhandle], 0, SEEK_END );
+    byte_size = ftell( i_filestream[a_memoryarrayhandle] );
+    sector_count = byte_size / iNVMemSectorSizeInBytes;
+    return sector_count;
+    }
+
+int32_t  SyborgNVMemory::NVMemSetCallback( int (*aNVMemCallBack) (int) )
+    {
+    i_NVMemCallBack = aNVMemCallBack;
+    return 0;
+    }
+
+
+extern "C"
+    {
+    NVMEMORY_API SyborgNVMemory * nvmem_create( uint32_t a_sectorsize )
+        {
+        return new SyborgNVMemory( a_sectorsize );
+        }
+
+    NVMEMORY_API int32_t nvmem_reset( SyborgNVMemory* a_syborg_nvmemory ) 
+        {
+        return a_syborg_nvmemory->NVMemReset();
+        }
+
+    NVMEMORY_API int32_t nvmem_create_image( SyborgNVMemory* a_syborg_nvmemory, char* a_memoryarrayname, uint32_t a_sectorcount, uint32_t a_sectorsize )
+        {
+        return a_syborg_nvmemory->NVMemCreateImage( a_memoryarrayname, a_sectorcount, a_sectorsize );
+        }
+
+    NVMEMORY_API int32_t nvmem_open( SyborgNVMemory* a_syborg_nvmemory, char* a_memoryarrayname ) 
+        {
+        return a_syborg_nvmemory->NVMemOpen( a_memoryarrayname );
+        }
+
+    NVMEMORY_API int32_t nvmem_close( SyborgNVMemory* a_syborg_nvmemory, int32_t a_memoryarrayhandle ) 
+        {
+        return a_syborg_nvmemory->NVMemClose( a_memoryarrayhandle );
+        }
+
+    NVMEMORY_API int32_t nvmem_flush( SyborgNVMemory* a_syborg_nvmemory, int32_t a_memoryarrayhandle ) 
+        {
+        return a_syborg_nvmemory->NVMemFlush( a_memoryarrayhandle );
+        }
+
+    NVMEMORY_API void nvmem_read( SyborgNVMemory* a_syborg_nvmemory, uint32_t *a_client_targetmemoryaddr, int32_t a_memoryarrayhandle, uint32_t a_memoryarraysectoroffset, uint32_t a_sectorcount ) 
+        {
+        a_syborg_nvmemory->NVMemRead( a_client_targetmemoryaddr, a_memoryarrayhandle, a_memoryarraysectoroffset, a_sectorcount );
+        }
+
+    NVMEMORY_API void nvmem_write( SyborgNVMemory* a_syborg_nvmemory, uint32_t *a_client_sourcememoryaddr, int32_t a_memoryarrayhandle, uint32_t a_memoryarraysectoroffset, uint32_t a_sectorcount ) 
+        {
+        a_syborg_nvmemory->NVMemWrite( a_client_sourcememoryaddr, a_memoryarrayhandle, a_memoryarraysectoroffset, a_sectorcount );
+        }
+
+    NVMEMORY_API uint32_t nvmem_get_sector_count( SyborgNVMemory* a_syborg_nvmemory, int32_t a_memoryarrayhandle )
+        {
+        return a_syborg_nvmemory->NVMemGetSectorCount( a_memoryarrayhandle );
+        }
+    
+    NVMEMORY_API int32_t nvmem_set_callback( SyborgNVMemory* a_syborg_nvmemory, int (*aGraphicsCallBack) (int) )
+        {
+        return a_syborg_nvmemory->NVMemSetCallback( aGraphicsCallBack );
+        }
+    }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/symbian-qemu-0.9.1-12/model-libraries/nvmemmory/nvmemmory.h	Thu May 27 00:38:17 2010 +0300
@@ -0,0 +1,255 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "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: 
+*
+* Simple non volatile memory device. nvmemmory.h
+*
+*/
+
+#ifndef _NVMEMORY_H
+#define _NVMEMORY_H
+
+#pragma once
+
+/*! \brief 
+NVMEMORY.DLL 
+- A simple non volatile sector addressed memory device
+- An example of a portable high abstraction model architecture. 
+  This DLL is created to serve in multiple different modeling 
+  environments and tools. Model portability should be taken into 
+  account when further developing and maintaining this device.
+
+USAGE       
+nvmemory.dll Example usage provided by syborg_nvmemorydevice.py.
+1 - Create an instance of SyborgNVMemory class. 
+    This can be performed either by instantiating the C++ class directly 
+    by calling the constructor "new SyborgNVMemory( a_sectorsize );".
+    Or by using the C API to create an instance "nvmem_create( sector_size )".
+    As you can see you need to set the sector size for your device when you create it.
+    
+    In fact each of the API functions are provided in form of both C and C++ API functions.
+    From this on only the C API is explained.
+
+2 - Reset the device by calling "nvmem_reset( self.obj )". 
+    This function clears any information stored by the device instance except the sector size.
+    Note that for the C API you always need to specify the object which you wish to command.
+
+3 - Create handle to your image file by calling "nvmem_open( self.obj, imagepath )".
+    Image is opened in binary mode. Store the handle.
+    
+    Note that you need to have an image stored to a path on your PC before you can call this function. 
+    You must provide the image name and path when calling.
+    
+    Note also that there is a service provided by this DLL which can create an image for you.
+    NVMEMORY_API int32_t nvmem_create_image( SyborgNVMemory* a_syborg_nvmemory, char* a_memoryarrayname, uint32_t a_sectorcount, uint32_t a_sectorsize = NVMEM_DEFAULT_SECTORSIZE_IN_BYTES );
+    nvmem_create_image function probably needs further development. You may also create image in your wrapper as done in example usage file.
+    
+    You may get your memory device size by calling nvmem_get_sector_count( self.obj, nvmemhandle ).
+    nvmemhandle is the handle you got when calling nvmem_open.
+    nvmem_get_sector_count is handy in cases where you have provided a readymade image for the device.
+    In this case you don't need to go and hardcode the image size each time in your wrapper.
+    
+4 - Initialize callback. Provide a callback function for the device by calling "nvmem_set_callback( self.obj, nvmem_callback )".
+    Where the callback is a function pointer of a type "int (*i_NVMemCallBack)(int);".
+    Callback is called by DLL when read and write operations are finished. Parameter is the amount of sectors succesfully read or written.
+    
+5 - Start using your device.
+    nvmem_read(  self.obj, nvmemory_sharedmemory_host_address, nvmemhandle, transaction_offset, transaction_size )
+    nvmem_write(  self.obj, nvmemory_sharedmemory_host_address, nvmemhandle, transaction_offset, transaction_size )
+    
+    See syborg_nvmemorydevice.py to learn more about device usage. 
+*/
+
+#include "platformtypes.h"
+
+#ifdef WIN32
+#ifdef NVMEMORY_EXPORTS
+#define NVMEMORY_API __declspec(dllexport)
+#else
+#define NVMEMORY_API __declspec(dllimport)
+#endif
+#else
+#define NVMEMORY_API
+#endif
+
+class NVMEMORY_API SyborgNVMemory;
+
+extern "C"
+    {
+    const int32_t NVMEM_DEFAULT_SECTORSIZE_IN_BYTES = 512;
+    const int32_t NVMEM_MAX_STREAMHANDLES = 16;
+
+    /*Nvmemory error codes*/
+    const int32_t NVMEM_OK =                                 0;
+    const int32_t NVMEM_ERROR_OUT_OF_FREE_STREAMHANDLES =   -1;
+    const int32_t NVMEM_ERROR_FOPEN =                       -2;
+    const int32_t NVMEM_ERROR_FCLOSE =                      -3;
+    const int32_t NVMEM_ERROR_FFLUSH =                      -4;
+    const int32_t NVMEM_ERROR_FSEEK =                       -5;
+    const int32_t NVMEM_ERROR_FREAD =                       -6;
+    const int32_t NVMEM_ERROR_FWRITE =                      -7;
+    const int32_t NVMEM_ERROR_SETVBUF =                     -8;
+    const int32_t NVMEM_ERROR_CREATE =                      -9;
+    const int32_t NVMEM_ERROR_FPRINTF =                     -10;
+
+    /**
+    * Reset the device
+    *
+    * @param a_syborg_nvmemory an object of class SyborgNVMemory.
+    * @return TODO an error if fails
+    */
+    NVMEMORY_API int32_t nvmem_reset( SyborgNVMemory* a_syborg_nvmemory );
+    
+    /**
+    * Create a non volatile memory array object.
+    *
+    * @param a_sectorsize Size for the sector.
+    * @return An object of class SyborgNVMemory.
+    */
+    NVMEMORY_API SyborgNVMemory * nvmem_create( uint32_t a_sectorsize = NVMEM_DEFAULT_SECTORSIZE_IN_BYTES);
+
+    /**
+    * Create a non volatile memory array. A raw image will be created to host filesystem which will 
+    * act as a non volatile memory device in client point of view.
+    *
+    * @param a_syborg_nvmemory an object of class SyborgNVMemory.
+    * @param a_memoryarrayname Name for the image to be created.
+    * @param a_sectorcount Image size in sectors.
+    * @param a_sectorsize size for the sector.
+    * @return An error code.
+    */
+    NVMEMORY_API int32_t nvmem_create_image( SyborgNVMemory* a_syborg_nvmemory, char* a_memoryarrayname, uint32_t a_sectorcount, uint32_t a_sectorsize = NVMEM_DEFAULT_SECTORSIZE_IN_BYTES );
+    
+    /**
+    * Create handle to an image
+    *
+    * @param a_syborg_nvmemory an object of class SyborgNVMemory.
+    * @param a_memoryarrayname Name and path for the image to be opened.
+    * @return Handle to a non volatile memory array.
+    */
+    NVMEMORY_API int32_t nvmem_open( SyborgNVMemory* a_syborg_nvmemory, char* a_memoryarrayname );
+
+    /**
+    * Close handle to a non volatile memory array
+    *
+    * @param a_syborg_nvmemory an object of class SyborgNVMemory.
+    * @param a_memoryarrayhandle Handle to be closed.
+    * @return Error code.
+    */
+    NVMEMORY_API int32_t nvmem_close( SyborgNVMemory* a_syborg_nvmemory, int32_t a_memoryarrayhandle );
+    
+    /**
+    * Flush possible cached content of a non volatile memory array
+    *
+    * @param a_syborg_nvmemory an object of class SyborgNVMemory.
+    * @param a_memoryarrayhandle Handle pointing to stream which is flushed to a file.
+    * @return Error code.
+    */
+    NVMEMORY_API int32_t nvmem_flush( SyborgNVMemory* a_syborg_nvmemory, int32_t a_memoryarrayhandle );
+
+    /**
+    * Read from a non volatile memory array to a guest os application memory space
+    *
+    * @param a_syborg_nvmemory an object of class SyborgNVMemory.
+    * @param a_client_targetmemoryaddr Host OS address pointing to a place to where the data read should be returned.
+    * @param a_memoryarrayhandle Handle to the device image.
+    * @param a_memoryarrayoffset Sector offset to a position from where the data is to be read.
+    * @param a_sectorcount Amount of sectors to be read.
+    * @return Error code.
+    */
+    NVMEMORY_API void nvmem_read( SyborgNVMemory* a_syborg_nvmemory, uint32_t *a_client_targetmemoryaddr, int32_t a_memoryarrayhandle, uint32_t a_memoryarrayoffset, uint32_t a_sectorcount );
+
+    /**
+    * Write to a non volatile memory array from a guest os application memory space
+    *
+    * @param a_syborg_nvmemory an object of class SyborgNVMemory.
+    * @param a_client_sourcememoryaddr Host OS address pointing to a place to where to get the data for write operation.
+    * @param a_memoryarrayhandle Handle to the device image.
+    * @param a_memoryarrayoffset Sector offset to a position to where the data is to be written.
+    * @param a_sectorcount Amount of sectors to be written.
+    * @return Error code.
+    */
+    NVMEMORY_API void nvmem_write( SyborgNVMemory* a_syborg_nvmemory, uint32_t *a_client_sourcememoryaddr, int32_t a_memoryarrayhandle, uint32_t a_memoryarrayoffset, uint32_t a_sectorcount );
+
+    /**
+    * Get the size of a non volatile memory array
+    *
+    * @param a_syborg_nvmemory an object of class SyborgNVMemory.
+    * @param a_memoryarrayhandle Handle to the device image.
+    * @return Total amount of sectors of the device.
+    */
+    NVMEMORY_API uint32_t nvmem_get_sector_count( SyborgNVMemory* a_syborg_nvmemory, int32_t a_memoryarrayhandle );
+
+    /**
+    * Store callback
+    *
+    * @param a_syborg_nvmemory an object of class SyborgNVMemory.
+    * @param aGraphicsCallBack pointer to a callback function.
+    * @return TODO an error if fails.
+    */
+    NVMEMORY_API int32_t nvmem_set_callback( SyborgNVMemory* a_syborg_nvmemory, int (*aGraphicsCallBack) (int) );
+    }
+
+class NVMEMORY_API SyborgNVMemory
+    {
+    public:
+
+        SyborgNVMemory( uint32_t a_sectorsize = NVMEM_DEFAULT_SECTORSIZE_IN_BYTES );
+        ~SyborgNVMemory( );
+
+        /**
+        * Reset the device
+        */
+        int32_t NVMemReset( );
+        /**
+        * Create a non volatile memory array. A raw image will be created to host filesystem which will 
+        * act as a non volatile memory device in client point of view.
+        */
+        int32_t NVMemCreateImage( char* a_memoryarrayname, uint32_t a_sectorcount, uint32_t a_sectorsize = NVMEM_DEFAULT_SECTORSIZE_IN_BYTES );
+        /**
+        * Return handle to a non volatile memory array
+        */
+        int32_t NVMemOpen( char* a_memoryarrayname );
+        /**
+        * Close handle to a non volatile memory array
+        */
+        int32_t NVMemClose( int32_t a_memoryarrayhandle );
+        /**
+        * Flush possible cached content of a non volatile memory array
+        */
+        int32_t NVMemFlush( int32_t a_memoryarrayhandle );
+        /**
+        * Read from a non volatile memory array to a guest os application memory space
+        */
+        void NVMemRead( uint32_t *a_client_targetmemoryaddr, int32_t a_memoryarrayhandle, uint32_t a_memoryarrayoffset, uint32_t a_sectorcount );
+        /**
+        * Write to a non volatile memory array from a guest os application memory space
+        */
+        void NVMemWrite( uint32_t *a_client_sourcememoryaddr, int32_t a_memoryarrayhandle, uint32_t a_memoryarrayoffset, uint32_t a_sectorcount );
+        /**
+        * Get the size of a non volatile memory array
+        */
+        uint32_t NVMemGetSectorCount( int32_t a_memoryarrayhandle );
+        /**
+        * Store callback
+        */
+        int32_t NVMemSetCallback( int (*aNVMemCallBack) (int) );
+
+    private:
+        FILE *i_filestream[NVMEM_MAX_STREAMHANDLES];
+        uint32_t iNVMemSectorSizeInBytes;
+        int (*i_NVMemCallBack)(int); 
+    };
+
+#endif // _NVMEMORY_H
Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/nvmemmory.ncb has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/symbian-qemu-0.9.1-12/model-libraries/nvmemmory/nvmemmory.sln	Thu May 27 00:38:17 2010 +0300
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual C++ Express 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nvmemmory", "nvmemmory.vcproj", "{F42A5A5B-9267-46F9-89C5-9D83F96A6B36}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{F42A5A5B-9267-46F9-89C5-9D83F96A6B36}.Debug|Win32.ActiveCfg = Debug|Win32
+		{F42A5A5B-9267-46F9-89C5-9D83F96A6B36}.Debug|Win32.Build.0 = Debug|Win32
+		{F42A5A5B-9267-46F9-89C5-9D83F96A6B36}.Release|Win32.ActiveCfg = Release|Win32
+		{F42A5A5B-9267-46F9-89C5-9D83F96A6B36}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/nvmemmory.suo has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/symbian-qemu-0.9.1-12/model-libraries/nvmemmory/nvmemmory.vcproj	Thu May 27 00:38:17 2010 +0300
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="nvmemmory"
+	ProjectGUID="{F42A5A5B-9267-46F9-89C5-9D83F96A6B36}"
+	RootNamespace="nvmemmory"
+	Keyword="ManagedCProj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="1"
+			ManagedExtensions="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="C:\modelling\display\PlatsimUtil\PlatsimUtil\inc\public"
+				PreprocessorDefinitions="WIN32;_DEBUG;NVMEMORY_EXPORTS;WINDOWS_LEAN_AND_MEAN"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="$(NoInherit)"
+				OutputFile="$(OutDir)\$(ProjectName).dll"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				AssemblyDebug="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="2"
+			CharacterSet="1"
+			ManagedExtensions="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="$(SolutionDir)..\commoninc"
+				PreprocessorDefinitions="WIN32;NDEBUG;NVMEMORY_EXPORTS;WINDOWS_LEAN_AND_MEAN"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="$(NoInherit)"
+				OutputFile="$(OutDir)\$(ProjectName).dll"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+		<AssemblyReference
+			RelativePath="System.dll"
+			AssemblyName="System, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
+		/>
+		<AssemblyReference
+			RelativePath="System.Data.dll"
+			AssemblyName="System.Data, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=x86"
+		/>
+		<AssemblyReference
+			RelativePath="System.XML.dll"
+			AssemblyName="System.Xml, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
+		/>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\nvmemmory.cpp"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\nvmemmory.h"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/symbian-qemu-0.9.1-12/model-libraries/nvmemmory/nvmemmory.vcproj.NOE.jahyvone.user	Thu May 27 00:38:17 2010 +0300
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioUserFile
+	ProjectType="Visual C++"
+	Version="8.00"
+	ShowAllFiles="false"
+	>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			>
+			<DebugSettings
+				Command=""
+				WorkingDirectory=""
+				CommandArguments=""
+				Attach="false"
+				DebuggerType="3"
+				Remote="1"
+				RemoteMachine="4FIL49437"
+				RemoteCommand=""
+				HttpUrl=""
+				PDBPath=""
+				SQLDebugging=""
+				Environment=""
+				EnvironmentMerge="true"
+				DebuggerFlavor=""
+				MPIRunCommand=""
+				MPIRunArguments=""
+				MPIRunWorkingDirectory=""
+				ApplicationCommand=""
+				ApplicationArguments=""
+				ShimCommand=""
+				MPIAcceptMode=""
+				MPIAcceptFilter=""
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			>
+			<DebugSettings
+				Command=""
+				WorkingDirectory=""
+				CommandArguments=""
+				Attach="false"
+				DebuggerType="3"
+				Remote="1"
+				RemoteMachine="4FIL49437"
+				RemoteCommand=""
+				HttpUrl=""
+				PDBPath=""
+				SQLDebugging=""
+				Environment=""
+				EnvironmentMerge="true"
+				DebuggerFlavor=""
+				MPIRunCommand=""
+				MPIRunArguments=""
+				MPIRunWorkingDirectory=""
+				ApplicationCommand=""
+				ApplicationArguments=""
+				ShimCommand=""
+				MPIAcceptMode=""
+				MPIAcceptFilter=""
+			/>
+		</Configuration>
+	</Configurations>
+</VisualStudioUserFile>
--- a/symbian-qemu-0.9.1-12/qemu-symbian-svp/plugins/qemu_arm_plugins.py	Fri May 14 16:38:13 2010 +0100
+++ b/symbian-qemu-0.9.1-12/qemu-symbian-svp/plugins/qemu_arm_plugins.py	Thu May 27 00:38:17 2010 +0300
@@ -6,3 +6,4 @@
 import syborg_keyboard
 import syborg_pointer
 import syborg_usbtest
+import syborg_nvmemorydevice
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/symbian-qemu-0.9.1-12/qemu-symbian-svp/plugins/syborg_nvmemorydevice.py	Thu May 27 00:38:17 2010 +0300
@@ -0,0 +1,221 @@
+#
+# Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "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: syborg_nvmemorydevice.py
+# A simple non volatile memory device nvmemory.dll python wrapper
+# Represents a non volatile memory device register interface for quest OS in QEMU Syborg environment.
+#
+# Gets the following from devicetree (.dtb configuration file) 
+#       drive_size - the size of the non volatile memory array to be created if there is no such thing available when the system is started
+#       sector_size - the size of the sector for the memory device
+#       drive_image_name - the name of the image to be used
+#
+# Creates an empty image of specified size and name if there is not image available when the system is started
+#
+
+import ctypes
+import qemu
+import sys
+import os
+import array
+
+class syborg_nvmemorydevice(qemu.devclass):
+    # 256 MB default empty drive size if there is no readymade image available
+    DEFAULT_DRIVE_SIZE = 0x10000000
+    DEVICE_SECTOR_SIZE = 0x200
+    DRIVE_NAME = "qemudrive.img"
+    DRIVE_PATH = "nvmemory"
+    
+    # Memory device registers
+    R_NVMEM_ID                                = 0x0000
+    R_NVMEM_TRANSACTION_OFFSET                = 0x0004
+    R_NVMEM_TRANSACTION_SIZE                  = 0x0008
+    R_NVMEM_TRANSACTION_DIRECTION             = 0x000c
+    R_NVMEM_TRANSACTION_EXECUTE               = 0x0010
+    R_NVMEM_SHARED_MEMORY_BASE                = 0x0014
+    R_NVMEM_NV_MEMORY_SIZE                    = 0x0018
+    R_NVMEM_SHARED_MEMORY_SIZE                = 0x001c
+    R_NVMEM_STATUS                            = 0x0020
+    R_NVMEM_ENABLE                            = 0x0024
+    R_NVMEM_LASTREG                           = 0x0028  # not a register, address of last register
+    
+    NVMEM_TRANSACTION_READ              = 1
+    NVMEM_TRANSACTION_WRITE             = 2
+    # Variables to store the information for current transaction
+    shared_memory_base                  = 0
+    shared_memory_size                  = 0
+    transaction_offset                  = 0
+    transaction_size                    = 0
+    transaction_direction               = 0
+    # Variables to validate transaction
+    transaction_offset_set              = 0
+    transaction_size_set                = 0
+    transaction_direction_set           = 0
+    nvmemory_sector_count                = 0
+    
+    drive_size                          = 0
+    sector_size                         = 0
+    drive_image_name                    = ""
+
+    def create(self):
+        print "syborg_nvmemorydevice: create\n"
+        
+        # Get properties
+        self.drive_size = self.properties["drive_size"]
+        self.sector_size = self.properties["sector_size"]
+        self.drive_image_name = self.properties["drive_image_name"]
+        
+        print "drive size: ", self.drive_size
+        print "sector size: ", self.sector_size
+        print "drive name: ", self.drive_image_name
+
+        drive_path_and_name = self.DRIVE_PATH + "\\" + self.drive_image_name 
+        # Save working directory
+        self.working_dir = os.getcwd()
+        
+        # Open the nvmemory library
+        try:
+            self.nvmemlib = ctypes.CDLL("nvmemmory.dll")
+        except:
+            sys.exit("syborg_nvmemorydevice: nvmemmory.dll load failed")
+        
+        # Create an instance of non volatile memory handler class
+        self.obj = self.nvmemlib.nvmem_create( self.sector_size )
+        self.nvmemlib.nvmem_reset( self.obj )
+        
+        # Create drive image path
+        try:
+            print "syborg_nvmemorydevice: Check drive image path\n"
+            os.mkdir( self.DRIVE_PATH )
+        except:
+            # Here we could check why we failed - usually because the path already exists \n"
+            pass
+        try:
+            self.filehandle = os.open( drive_path_and_name, os.O_RDWR|os.O_BINARY )
+            os.close( self.filehandle )
+        except:
+            print "syborg_nvmemorydevice: drive image not found - create\n"
+            self.filehandle = open( drive_path_and_name, "wb" )
+            # Initialize file with zeroes. This may take a while
+            temparray = array.array("B", [0,0,0,0,0,0,0,0])
+            arraylength = temparray.buffer_info()[1] * temparray.itemsize
+            multiplier = self.drive_size / arraylength / 128
+            temparray = temparray * multiplier
+            arraylength = temparray.buffer_info()[1] * temparray.itemsize
+            print "array length: ", arraylength
+            index = 0
+            while index < 128:
+                temparray.tofile(self.filehandle)
+                index = index+1
+        
+        # Create path and get handle to the raw memory array
+        imagepath = self.working_dir + "\\" + drive_path_and_name
+        print "imagepath: ", imagepath
+        self.nvmemhandle = self.nvmemlib.nvmem_open( self.obj, imagepath )
+        if( self.nvmemhandle < 0 ):
+            error_msg = "syborg_nvmemorydevice: nvmem_open error: ", self.nvmemhandle
+            sys.exit( error_msg )
+        
+        # Initialize callback and get memory sector count
+        self.initialize_nvmem_callback()
+        self.nvmemory_sector_count = self.nvmemlib.nvmem_get_sector_count( self.obj, self.nvmemhandle )
+        print "syborg_nvmemorydevice: created\n"
+            
+    def updateIrq(self,new_value):
+        self.set_irq_level(0, new_value)
+
+    def nvmem_request_callback(self, result):
+        #print "graphics_request_callback: " , result
+        self.status_reg = result
+        self.updateIrq(1)
+        return 0
+        
+    def initialize_nvmem_callback(self):
+        self.CALLBACKFUNC = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int)
+        self.nvmem_callback = self.CALLBACKFUNC(self.nvmem_request_callback)
+        self.nvmemlib.nvmem_set_callback( self.obj, self.nvmem_callback )
+
+    def read_reg(self, offset):
+        offset >>= 2
+        #print "read register: 0x%x" % (offset) 
+        if offset == self.R_NVMEM_ID:
+            return 0xDEADBEEF
+        elif offset == self.R_NVMEM_TRANSACTION_OFFSET:
+            return self.transaction_offset
+        elif offset == self.R_NVMEM_TRANSACTION_SIZE:
+            return self.transaction_size
+        elif offset == self.R_NVMEM_TRANSACTION_DIRECTION:
+            return self.transaction_direction
+        elif offset == self.R_NVMEM_SHARED_MEMORY_BASE:
+            return self.shared_memory_base
+        elif offset == self.R_NVMEM_SHARED_MEMORY_SIZE:
+            return self.shared_memory_size
+        elif offset == self.R_NVMEM_NV_MEMORY_SIZE:
+            return self.nvmemory_sector_count
+        elif offset == self.R_NVMEM_STATUS:
+            self.updateIrq(0)
+            return self.status_reg
+        else:
+            reg_read_error = "syborg_nvmemorydevice: Illegal register read at: ", offset 
+            sys.exit( reg_read_error )
+
+    def write_reg(self, offset, value):
+        offset >>= 2
+        #print "write register: 0x%x value: 0x%x" % (offset, value) 
+        if offset == self.R_NVMEM_TRANSACTION_OFFSET:
+            self.transaction_offset = value
+            self.transaction_offset_set = 1
+        elif offset == self.R_NVMEM_TRANSACTION_SIZE:
+            self.transaction_size = value
+            self.transaction_size_set = 1
+        elif offset == self.R_NVMEM_TRANSACTION_DIRECTION:
+            self.transaction_direction = value
+            self.transaction_direction_set = 1
+        elif offset == self.R_NVMEM_TRANSACTION_EXECUTE:
+            if( (self.transaction_offset_set == 0) | (self.transaction_size_set == 0) | (self.transaction_direction_set == 0) ):
+                error_msg = "syborg_nvmemorydevice: Illegal transaction! All the required parameters are not set" 
+                sys.exit( error_msg )
+            elif(self.transaction_size == 0 ):
+                error_msg = "syborg_nvmemorydevice: Zero size transaction issued!" 
+                sys.exit( error_msg )
+            else:
+                if( self.transaction_direction == self.NVMEM_TRANSACTION_READ ):
+                    self.nvmemlib.nvmem_read(  self.obj, self.nvmemory_sharedmemory_host_address, self.nvmemhandle, self.transaction_offset, self.transaction_size )
+                elif( self.transaction_direction == self.NVMEM_TRANSACTION_WRITE ):
+                    self.nvmemlib.nvmem_write(  self.obj, self.nvmemory_sharedmemory_host_address, self.nvmemhandle, self.transaction_offset, self.transaction_size )
+                else:
+                    error_msg = "syborg_nvmemorydevice: Transaction direction not set!" 
+                    sys.exit( error_msg )
+                self.transaction_offset_set = 0
+                self.transaction_size_set = 0
+                self.transaction_direction_set = 0
+        elif offset == self.R_NVMEM_SHARED_MEMORY_BASE:
+            self.shared_memory_base = value
+        elif offset == self.R_NVMEM_SHARED_MEMORY_SIZE:
+            self.shared_memory_size = value
+        elif offset == self.R_NVMEM_ENABLE:
+            if( value > 0 ):
+                self.nvmemory_memregion = qemu.memregion( self.shared_memory_base, self.shared_memory_size )
+                self.nvmemory_sharedmemory_host_address = self.nvmemory_memregion.region_host_addr()
+                print"syborg_nvmemorydevice: host addr: 0x%08x" % (self.nvmemory_sharedmemory_host_address)
+        else:
+            reg_write_error = "syborg_nvmemorydevice: Illegal register write to: ", offset 
+            sys.exit( reg_write_error )
+
+    # Device class properties
+    regions = [qemu.ioregion(0x1000, readl=read_reg, writel=write_reg)]
+    irqs = 1
+    name = "syborg,nvmemorydevice"
+    properties = {"drive_size":DEFAULT_DRIVE_SIZE, "sector_size":DEVICE_SECTOR_SIZE, "drive_image_name":DRIVE_NAME}
+
+qemu.register_device(syborg_nvmemorydevice)
--- a/symbian-qemu-0.9.1-12/qemu-symbian-svp/python-plugin.c	Fri May 14 16:38:13 2010 +0100
+++ b/symbian-qemu-0.9.1-12/qemu-symbian-svp/python-plugin.c	Thu May 27 00:38:17 2010 +0300
@@ -2,6 +2,8 @@
 *
 * Contributors:
 * NTT DOCOMO, INC. -- Syborg QEMU crashes when using skin + touchscreen device
+* 
+* Nokia Oyj -- New memregion service added for converting guest OS addresses to host OS addresses
 *
 */
 
@@ -137,6 +139,127 @@
 
 typedef struct {
     PyObject_HEAD
+    uint32_t base;
+    uint32_t size;
+	uint32_t *host_ram_base_ptr;
+} qemu_py_memregion;
+
+static void qemu_py_memregion_dealloc(qemu_py_ioregion *self)
+	{
+    self->ob_type->tp_free((PyObject*)self);
+	}
+
+static int qemu_py_memregion_init(qemu_py_memregion *self, PyObject *args,
+                                 PyObject *kwds)
+	{
+    static char *kwlist[] = {"base","size", NULL};
+    uint32_t base;
+    uint32_t size;
+	int ret = -1;
+	int region_index = 0;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "ll", kwlist,
+                                     &base, &size ))
+		{
+        ret = -1; 
+		}
+	else
+		{
+		for( region_index = 0; region_index < devtree_ram_map_size; region_index+=1 )
+			{
+			// The created region needs to fit inside memory regions in device tree configuration
+			if( (devtree_ram_map[region_index].base <= base) && 
+				((devtree_ram_map[region_index].base + devtree_ram_map[region_index].size) >=
+				(base + size)) )
+				{
+				ret = 0;
+				self->base = base;
+				self->size = size;
+				self->host_ram_base_ptr = (uint32_t*)host_ram_addr(base);
+				break;
+				}
+			else
+				{
+				ret = -1;
+				}
+			}
+		}
+	
+    return ret;
+	}
+
+static PyObject *qemu_py_memregion_get_size(qemu_py_memregion *self,
+                                    PyObject *args, PyObject *kwds)
+	{
+	return PyLong_FromUnsignedLong(self->size);
+	}
+
+static PyObject *qemu_py_memregion_get_base(qemu_py_memregion *self,
+                                    PyObject *args, PyObject *kwds)
+	{
+	return PyLong_FromUnsignedLong(self->base);
+	}
+
+static PyObject *qemu_py_memregion_get_host_base(qemu_py_memregion *self,
+                                    PyObject *args, PyObject *kwds)
+	{
+	return PyLong_FromVoidPtr( (void*)(self->host_ram_base_ptr) );
+	}
+
+static PyMethodDef qemu_py_memregion_methods[] = {
+    {"size", (PyCFunction)qemu_py_memregion_get_size, METH_VARARGS|METH_KEYWORDS,
+     "Get memory region size"},
+    {"region_guest_addr", (PyCFunction)qemu_py_memregion_get_base, METH_VARARGS|METH_KEYWORDS,
+     "Get memory region base"},
+    {"region_host_addr", (PyCFunction)qemu_py_memregion_get_host_base, METH_VARARGS|METH_KEYWORDS,
+     "Get memory region host base address"},
+    {NULL}  /* Sentinel */
+};
+
+static PyTypeObject qemu_py_memRegionType = {
+    PyObject_HEAD_INIT(NULL)
+    0,                                      /* ob_size */
+    "qemu.memregion",                       /* tp_name */
+    sizeof(qemu_py_memregion),              /* tp_basicsize */
+    0,                                      /* tp_itemsize */
+    (destructor)qemu_py_memregion_dealloc,  /* tp_dealloc */
+    0,                                      /* tp_print */
+    0,                                      /* tp_getattr */
+    0,                                      /* tp_setattr */
+    0,                                      /* tp_compare */
+    0,                                      /* tp_repr */
+    0,                                      /* tp_as_number */
+    0,                                      /* tp_as_sequence */
+    0,                                      /* tp_as_mapping */
+    0,                                      /* tp_hash  */
+    0,                                      /* tp_call */
+    0,                                      /* tp_str */
+    0,                                      /* tp_getattro */
+    0,                                      /* tp_setattro */
+    0,                                      /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT,                     /* tp_flags */
+    "QEMU MemRegion",                       /* tp_doc */
+    0,                                      /* tp_traverse */
+    0,                                      /* tp_clear */
+    0,		                                /* tp_richcompare */
+    0,		                                /* tp_weaklistoffset */
+    0,		                                /* tp_iter */
+    0,		                                /* tp_iternext */
+    qemu_py_memregion_methods,              /* tp_methods */
+    0,                                      /* tp_members */
+    0,                                      /* tp_getset */
+    0,                                      /* tp_base */
+    0,                                      /* tp_dict */
+    0,                                      /* tp_descr_get */
+    0,                                      /* tp_descr_set */
+    0,                                      /* tp_dictoffset */
+    (initproc)qemu_py_memregion_init,       /* tp_init */
+    0,                                      /* tp_alloc */
+    0,                                      /* tp_new */
+};
+
+typedef struct {
+    PyObject_HEAD
     QEMUFile *f;
 } qemu_py_file;
 
@@ -1929,6 +2052,7 @@
     qemu_py_add_class(m, "palette", &qemu_py_paletteType);
     qemu_py_add_class(m, "ptimer", &qemu_py_ptimerType);
     qemu_py_add_class(m, "file", &qemu_py_fileType);
+    qemu_py_add_class(m, "memregion", &qemu_py_memRegionType);
 }
 
 #define PLUGIN_INIT_SCRIPT "import sys\nsys.path.insert(0, \"%s/plugins\")"