# HG changeset patch # User jahyvone@4FIL49437 # Date 1274909897 -10800 # Node ID eb3d0111f8684d99f43b7e0f541c2fca3f99f1c5 # Parent b6aa150091ee2c8afae935616935cd3506a59368 start nvmemory diff -r b6aa150091ee -r eb3d0111f868 baseport/syborg/bld.inf --- 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_ diff -r b6aa150091ee -r eb3d0111f868 baseport/syborg/bootstrap/syborg.inc --- 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 diff -r b6aa150091ee -r eb3d0111f868 baseport/syborg/bootstrap/syborg.s --- 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 diff -r b6aa150091ee -r eb3d0111f868 baseport/syborg/estart.txt --- 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 + diff -r b6aa150091ee -r eb3d0111f868 baseport/syborg/mednvmemory/mednvmemory.mmp --- /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 +#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 diff -r b6aa150091ee -r eb3d0111f868 baseport/syborg/mednvmemory/syborg_mednvmemory.cpp --- /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()<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(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::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::Disconnect()"); + // Complete using the default implementation + DMediaDriver::Disconnect(aLocalDrive, aMsg); + __DEBUG_PRINT("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(" 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(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("(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::Isr"); + + DMediaDriverNVMemory* nvMem = reinterpret_cast(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; + } diff -r b6aa150091ee -r eb3d0111f868 baseport/syborg/mednvmemory/syborg_mednvmemory.h --- /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 +#include +#include + +//#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 diff -r b6aa150091ee -r eb3d0111f868 baseport/syborg/rom/kernel.iby --- 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 diff -r b6aa150091ee -r eb3d0111f868 baseport/syborg/specific/syborg.h --- 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 diff -r b6aa150091ee -r eb3d0111f868 baseport/syborg/specific/variantmediadef.h --- 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__ diff -r b6aa150091ee -r eb3d0111f868 baseport/syborg/syborg.dtb Binary file baseport/syborg/syborg.dtb has changed diff -r b6aa150091ee -r eb3d0111f868 baseport/syborg/syborg.dts --- 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 = ; interrupt-parent = <&intc>; }; + nvmemorydevice@0 { + compatible = "syborg,nvmemorydevice"; + drive_size = <4000000>; + sector_size = <200>; + drive_image_name = "syborg_system.img"; + reg = ; + interrupts = ; + interrupt-parent = <&intc>; + }; platform@0 { compatible = "syborg,platform"; - reg = ; + reg = ; }; }; }; diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/model-libraries/commoninc/platformtypes.h --- /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 diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Debug/BuildLog.htm Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Debug/BuildLog.htm has changed diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Debug/app.res Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Debug/app.res has changed diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/model-libraries/nvmemmory/NVMemory_HowTo.txt --- /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. + diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/BuildLog.htm Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/BuildLog.htm has changed diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/RCa03000 Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/RCa03000 has changed diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/mt.dep --- /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 diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/nvmemmory.dll Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/nvmemmory.dll has changed diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/nvmemmory.dll.intermediate.manifest --- /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 @@ + + + + + + + + diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/nvmemmory.exp Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/nvmemmory.exp has changed diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/nvmemmory.lib Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/nvmemmory.lib has changed diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/nvmemmory.obj Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/nvmemmory.obj has changed diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/nvmemmory.pdb Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/nvmemmory.pdb has changed diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/vc80.idb Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/vc80.idb has changed diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/vc80.pdb Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/Release/vc80.pdb has changed diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/model-libraries/nvmemmory/app.ico Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/app.ico has changed diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/model-libraries/nvmemmory/app.rc --- /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 + diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/model-libraries/nvmemmory/nvmemmory.cpp --- /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 + } +#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 ); + } + } diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/model-libraries/nvmemmory/nvmemmory.h --- /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 diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/model-libraries/nvmemmory/nvmemmory.ncb Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/nvmemmory.ncb has changed diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/model-libraries/nvmemmory/nvmemmory.sln --- /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 diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/model-libraries/nvmemmory/nvmemmory.suo Binary file symbian-qemu-0.9.1-12/model-libraries/nvmemmory/nvmemmory.suo has changed diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/model-libraries/nvmemmory/nvmemmory.vcproj --- /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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/model-libraries/nvmemmory/nvmemmory.vcproj.NOE.jahyvone.user --- /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 @@ + + + + + + + + + + + diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/qemu-symbian-svp/plugins/qemu_arm_plugins.py --- 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 diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/qemu-symbian-svp/plugins/syborg_nvmemorydevice.py --- /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) diff -r b6aa150091ee -r eb3d0111f868 symbian-qemu-0.9.1-12/qemu-symbian-svp/python-plugin.c --- 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\")"