diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/specific/nanddev.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/specific/nanddev.cpp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,416 @@ +// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// D_MEDNAND.CPP +// +// + +#define _MEDIA_DRIVER +#include +#include +#include + +/******************************************** + * Driver definitions + ********************************************/ +const TInt KSimulatedDeviceId = 0xEC73; +const CHAR KNandFileName[] = "NANDDRV.BIN"; + +// +// Platform dependent media driver class +// +class DMediaDriverNandWin32 : public DMediaDriverNand + { +public: + DMediaDriverNandWin32(TMediaDevice aDevice); + + // replacing pure virtual - NAND device specific stuff + virtual TInt Initialise(); + virtual TInt GetDeviceId(TUint8& aDeviceId, TUint8& aManufacturerId); + virtual TInt DeviceRead(const TUint aPageAddress, TAny* aBuf, const TUint aLength); + virtual TInt DeviceWrite(const TUint aPageAddress, TAny* aBuf, const TUint aLength); + virtual TInt DeviceErase(const TUint aBlockAddress); + virtual TInt DeviceClose(); + +public: + HANDLE iFile; + HANDLE iMapping; + TUint8* iBase; + }; + +LOCAL_C TInt MapLastError() +// +// Map an NT error to an Epoc/32 error. +// + { + __PATH_NOT_YET_TESTED; + DWORD r=GetLastError(); + TInt res; + switch (r) + { + case ERROR_SHARING_VIOLATION : res=KErrAccessDenied; break; + case ERROR_LOCK_VIOLATION : res=KErrLocked; break; + case ERROR_FILE_NOT_FOUND: res=KErrNotFound; break; + case ERROR_PATH_NOT_FOUND: res=KErrPathNotFound; break; + case ERROR_ALREADY_EXISTS: + case ERROR_FILE_EXISTS: + res=KErrAlreadyExists; + break; + case ERROR_NOT_READY: res=KErrNotReady; break; + case ERROR_UNRECOGNIZED_VOLUME: + case ERROR_NOT_DOS_DISK: + res=KErrUnknown; + break; + case ERROR_UNRECOGNIZED_MEDIA: res=KErrCorrupt; break; + case ERROR_INVALID_NAME: res=KErrBadName; break; + case ERROR_NO_MORE_FILES: res=KErrEof; break; + case ERROR_DISK_FULL: res=KErrDiskFull; break; + default: res=KErrGeneral; + } + return(res); + } + +TInt DMediaDriverNandWin32::Initialise() +// +// Create the simulated NAND file if necessary and +// map it into memory. +// + { + __PATH_TESTED; + + // locate/open the file that models the flash + CHAR filename[MAX_PATH]; + strcpy(filename, Property::GetString("EmulatorMediaPath")); + if (!Emulator::CreateAllDirectories(filename)) + { + __PATH_NOT_YET_TESTED; + return Emulator::LastError(); + } + strcat(filename, KNandFileName); + iFile = CreateFileA(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL); + + if (iFile == INVALID_HANDLE_VALUE) + { + __PATH_NOT_YET_TESTED; + return Emulator::LastError(); + } + + const TUint32 flashSizeInBytes = iNumBlocks * iNumPagesPerBlock * (iNumBytesMain + iNumBytesSpare); + + SetFilePointer(iFile, flashSizeInBytes, NULL, FILE_BEGIN); + SetEndOfFile(iFile); + + iMapping = CreateFileMappingA(iFile, NULL, PAGE_READWRITE, 0, flashSizeInBytes, NULL); + if (iMapping == NULL) + { + __PATH_NOT_YET_TESTED; + return Emulator::LastError(); + } + + iBase = (TUint8*)MapViewOfFile(iMapping, FILE_MAP_WRITE, 0, 0, flashSizeInBytes); + if (iBase == NULL) + { + __PATH_NOT_YET_TESTED; + return Emulator::LastError(); + } + + return KErrNone; + } + +TInt DMediaDriverNandWin32::GetDeviceId(TUint8& aDeviceId, TUint8& aManufacturerId) + { + __PATH_TESTED; + + aManufacturerId = (KSimulatedDeviceId & 0xFF00) >> 8; + aDeviceId = (KSimulatedDeviceId & 0xFF); + return KErrNone; + } + +TInt DMediaDriverNandWin32::DeviceRead(const TUint aPageAddress, TAny* aBuf, const TUint aLength) + { + __PATH_TESTED; + + __NAND_ASSERT(aPageAddress < (iNumBlocks * iNumPagesPerBlock)); + __NAND_ASSERT( (aLength == iNumBytesMain) + || (aLength == iNumBytesMain + iNumBytesSpare) + || (aLength == iNumBytesSpare) ); + +#ifdef __TEST_MEDIA_DRIVER__ + extern TBool gNoPower; + if(gNoPower) + return KErrBadPower; +#endif + + TUint8* readPoint; + if (aLength == iNumBytesMain) + { + __PATH_TESTED; + readPoint = iBase + (aPageAddress * (iNumBytesMain + iNumBytesSpare)); + } + else if (aLength == iNumBytesSpare) + { + __PATH_TESTED; + readPoint = iBase + (aPageAddress * (iNumBytesMain + iNumBytesSpare)) + iNumBytesMain; + } + else if (aLength == (iNumBytesMain + iNumBytesSpare)) + { + __PATH_TESTED; + readPoint = iBase + (aPageAddress * (iNumBytesMain + iNumBytesSpare)); + } + else + { + __PATH_NOT_YET_TESTED; + return KErrArgument; + } + + for (TUint i = 0; i < aLength; i++) + { + ((TUint8*)aBuf)[i] = readPoint[i]; + } + +#ifdef __TEST_MEDIA_DRIVER__ + extern TBool gECCFail; + if(gECCFail) + { + //introduce a random one bit error + TUint8* p=(TUint8*)aBuf; + TUint32 key=Kern::Random() % aLength; + TUint32 shift=1<<(Kern::Random() % 8); + p[key]=(TUint8)(p[key]&shift?p[key]-shift:p[key]+shift); + gECCFail=EFalse; + } +#endif + + return KErrNone; + } + +#ifdef __TEST_MEDIA_DRIVER__ +extern "C" TUint32 gbbm_get_sphy_blknum(TUint32, TUint32); +#endif +TInt DMediaDriverNandWin32::DeviceWrite(const TUint aPageAddress, TAny* aBuf, const TUint aLength) + { + __PATH_TESTED; + + __NAND_ASSERT(aPageAddress < (iNumBlocks * iNumPagesPerBlock)); + __NAND_ASSERT( (aLength == iNumBytesMain) + || (aLength == iNumBytesMain + iNumBytesSpare) + || (aLength == iNumBytesSpare) ); + +#ifdef __TEST_MEDIA_DRIVER__ + extern TBool gNoPower; + extern TBool gPowerFail; + extern TUint32 gPowerFailAfter; + if(gNoPower) + return KErrBadPower; + if(gPowerFail) + { + if(gPowerFailAfter) + --gPowerFailAfter; + else + { + gPowerFail=EFalse; + gNoPower=ETrue; + extern TUint32 gNotificationType; + extern TUint32 KNandDbgNotifyPowerDown; + extern TInt NotifyThread(); + if(gNotificationType==KNandDbgNotifyPowerDown) + NotifyThread(); + return KErrBadPower; + } + } +#endif + + TUint8* writePoint; + + if (aLength == iNumBytesMain) + { + __PATH_TESTED; + writePoint = iBase + (aPageAddress * (iNumBytesMain + iNumBytesSpare)); + } + else if (aLength == iNumBytesSpare) + { + __PATH_TESTED; + writePoint = iBase + (aPageAddress * (iNumBytesMain + iNumBytesSpare)) + iNumBytesMain; + } + else if (aLength == (iNumBytesMain + iNumBytesSpare)) + { + __PATH_TESTED; + writePoint = iBase + (aPageAddress * (iNumBytesMain + iNumBytesSpare)); + } + else + { + __PATH_NOT_YET_TESTED; + return KErrArgument; + } + + for (TUint i = 0; i < aLength; i++) + { + writePoint[i] &= ((TUint8*)aBuf)[i]; + } + +#ifdef __TEST_MEDIA_DRIVER__ + extern TUint32 gFailAfter; + extern TUint32 gFailAfterCnt; + extern TBool gFailureType; //true-WriteFail, false-EraseFail + extern TBool gFailON; + if(gFailON && gFailureType) + { + if(gFailAfterCnt) + --gFailAfterCnt; + else + { + extern TUint32 FirstReadPUN; + extern DMediaDriverNand* gMediaDriverPtr; + if(gbbm_get_sphy_blknum(0,aPageAddress/gMediaDriverPtr->iNumPagesPerBlock)==FirstReadPUN) + { + gFailAfterCnt=gFailAfter; + //notify failure + extern TUint32 gNotificationType; + extern TUint32 KNandDbgNotifyWriteFail; + extern TInt NotifyThread(); + if(gNotificationType==KNandDbgNotifyWriteFail) + NotifyThread(); + + return KErrCorrupt; + } + } + } +#endif + + return KErrNone; + } + +TInt DMediaDriverNandWin32::DeviceErase(const TUint aBlockAddress) + { + __PATH_TESTED; + + __NAND_ASSERT(aBlockAddress < iNumBlocks); +#ifdef __TEST_MEDIA_DRIVER__ + extern TBool gNoPower; + extern TBool gPowerFail; + extern TUint32 gPowerFailAfter; + if(gNoPower) + return KErrBadPower; + if(gPowerFail) + { + if(gPowerFailAfter) + --gPowerFailAfter; + else + { + gPowerFail=EFalse; + gNoPower=ETrue; + extern TUint32 gNotificationType; + extern TUint32 KNandDbgNotifyPowerDown; + extern TInt NotifyThread(); + if(gNotificationType==KNandDbgNotifyPowerDown) + NotifyThread(); + return KErrBadPower; + } + } +#endif + + const TUint bytesPerEraseBlock = iNumPagesPerBlock * (iNumBytesMain + iNumBytesSpare); + const TUint erasePos = aBlockAddress * bytesPerEraseBlock; + + TUint8* temp = iBase + erasePos; + for (TUint i=0; i < bytesPerEraseBlock; i++) + { + temp[i]=0xFF; + } + return KErrNone; + } + +TInt DMediaDriverNandWin32::DeviceClose() + { + __PATH_NOT_YET_TESTED; + TBool bRtn=UnmapViewOfFile(iBase); + if(!bRtn) + { + __PATH_NOT_YET_TESTED; + return(MapLastError()); + } + + bRtn=CloseHandle(iMapping); + if (!bRtn) + { + __PATH_NOT_YET_TESTED; + return(MapLastError()); + } + + bRtn=CloseHandle(iFile); + if (!bRtn) + { + __PATH_NOT_YET_TESTED; + return(MapLastError()); + } + + return KErrNone; + } + +DMediaDriverNandWin32::DMediaDriverNandWin32(TMediaDevice aDevice) + : DMediaDriverNand(aDevice) + { + __PATH_TESTED; + } + +DMediaDriverNand* DMediaDriverNand::New(TMediaDevice aDevice) + { + __PATH_TESTED; + return new DMediaDriverNandWin32(aDevice); + } + +#ifdef __USE_CUSTOM_ALLOCATOR +/** + Concrete implementation of the NAND buffer allocator class + - Uses Kern::Alloc based allocation + + @internalTechnology + */ +class TNandAllocatorWins : public TNandAllocatorBase + { +public: + virtual TInt AllocateBuffers(SBufferInfo& aBufferInfo); // Initialise the allocator + }; + +/** Concrete implementation of the NAND buffer allocator class + Creates a customallocator (using Kern::Alloc) + + @param aBufferInfo A reference to a SBufferInfo containing the details of the PSL allocated buffer + @return Standard Symbian OS error code + @see TNandAllocatorBase::SCellInfo + */ +TInt TNandAllocatorWins::AllocateBuffers(SBufferInfo& aBufferInfo) + { + const TUint32 KNumBuffers = 4; + const TUint32 KMaxNumBytesSpare = 16; + const TUint32 KMaxNumBytesMain = 512; + const TUint32 KMaxNumBytesPage = KMaxNumBytesSpare + KMaxNumBytesMain; + + aBufferInfo.iBytesPerSpareArray = KMaxNumBytesSpare; + aBufferInfo.iBytesPerMainArray = KMaxNumBytesMain; + aBufferInfo.iBufferCount = KNumBuffers; + + aBufferInfo.iBufferP = reinterpret_cast(Kern::Alloc(KMaxNumBytesPage * KNumBuffers)); + + return(aBufferInfo.iBufferP ? KErrNone : KErrNoMemory); + } + +/** +Create an allocator suitable for use on this target +@internalComponent +*/ +TNandAllocatorBase* DMediaDriverNand::ExtensionInitAllocator() + { + return new TNandAllocatorWins; + } +#endif